From 05cbe71add4ea89679340baff1a51f3680492c1c Mon Sep 17 00:00:00 2001 From: Mark Kettenis Date: Sat, 7 Feb 2004 14:44:50 +0000 Subject: [PATCH] * dwarf2-frame.h: Update copyright. (enum dwarf2_frame_reg_rule): New. (struct dwarf2_frame_state_reg): New. (dwarf2_frame_sniffer, dwarf2_frame_base_sniffer): Make extern. * dwarf2-frame.c: Update copyright. (enum dwarf2_reg_rule): Remove. (struct dwarf2_frame_state): Remove defenition of `struct dwarf2_frame_state_reg'. (read_reg): Call get_frame_arch to get the architecture instead of using CURRENT_GDBARCH. (execute_cfa_program): Prefix old `enum dwarf2_reg_rule' tags with DWARF2_FRAME_. (dwarf2_frame_init_reg): New function. (dwarf2_frame_cache): Call get_frame_arch to get the architecture instead of using CURRENT_GDBARCH. Call dwarf2_frame_init_reg to initialize the register state. Prefix old `enum dwarf2_reg_rule' tags with DWARF2_FRAME_. (dwarf2_frame_prev_register): Call get_frame_arch to get the architecture instead of using CURRENT_GDBARCH. Prefix old `enum dwarf2_reg_rule' tags with DWARF2_FRAME_. --- gdb/ChangeLog | 23 ++++++++ gdb/dwarf2-frame.c | 167 ++++++++++++++++++++++------------------------------- gdb/dwarf2-frame.h | 52 ++++++++++++++++- 3 files changed, 142 insertions(+), 100 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 11f2ff6..74c0b82 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,26 @@ +2004-02-07 Mark Kettenis + + * dwarf2-frame.h: Update copyright. + (enum dwarf2_frame_reg_rule): New. + (struct dwarf2_frame_state_reg): New. + (dwarf2_frame_sniffer, dwarf2_frame_base_sniffer): Make extern. + * dwarf2-frame.c: Update copyright. + (enum dwarf2_reg_rule): Remove. + (struct dwarf2_frame_state): Remove defenition of `struct + dwarf2_frame_state_reg'. + (read_reg): Call get_frame_arch to get the architecture instead of + using CURRENT_GDBARCH. + (execute_cfa_program): Prefix old `enum dwarf2_reg_rule' tags with + DWARF2_FRAME_. + (dwarf2_frame_init_reg): New function. + (dwarf2_frame_cache): Call get_frame_arch to get the architecture + instead of using CURRENT_GDBARCH. Call dwarf2_frame_init_reg to + initialize the register state. Prefix old `enum dwarf2_reg_rule' + tags with DWARF2_FRAME_. + (dwarf2_frame_prev_register): Call get_frame_arch to get the + architecture instead of using CURRENT_GDBARCH. Prefix old `enum + dwarf2_reg_rule' tags with DWARF2_FRAME_. + 2004-02-06 Andrew Cagney * tui/tui-data.h (struct tui_list): Rename _TuiList. diff --git a/gdb/dwarf2-frame.c b/gdb/dwarf2-frame.c index 22e4107..ed7f4ab 100644 --- a/gdb/dwarf2-frame.c +++ b/gdb/dwarf2-frame.c @@ -1,6 +1,6 @@ /* Frame unwinder for frames with DWARF Call Frame Information. - Copyright 2003 Free Software Foundation, Inc. + Copyright 2003, 2004 Free Software Foundation, Inc. Contributed by Mark Kettenis. @@ -97,49 +97,13 @@ static struct dwarf2_fde *dwarf2_frame_find_fde (CORE_ADDR *pc); /* Structure describing a frame state. */ -enum dwarf2_reg_rule -{ - /* Make certain that 0 maps onto the correct enum value; the - corresponding structure is being initialized using memset zero. - This indicates that CFI didn't provide any information at all - about a register, leaving how to obtain its value totally - unspecified. */ - REG_UNSPECIFIED = 0, - - /* The term "undefined" comes from the DWARF2 CFI spec which this - code is moddeling; it indicates that the register's value is - "undefined". GCC uses the less formal term "unsaved". Its - definition is a combination of REG_UNDEFINED and REG_UNSPECIFIED. - The failure to differentiate the two helps explain a few problems - with the CFI generated by GCC. */ - REG_UNDEFINED, - REG_SAVED_OFFSET, - REG_SAVED_REG, - REG_SAVED_EXP, - REG_SAME_VALUE, - - /* These aren't defined by the DWARF2 CFI specification, but are - used internally by GDB. */ - REG_RA, /* Return Address. */ - REG_CFA /* Call Frame Address. */ -}; - struct dwarf2_frame_state { /* Each register save state can be described in terms of a CFA slot, another register, or a location expression. */ struct dwarf2_frame_state_reg_info { - struct dwarf2_frame_state_reg - { - union { - LONGEST offset; - ULONGEST reg; - unsigned char *exp; - } loc; - ULONGEST exp_len; - enum dwarf2_reg_rule how; - } *reg; + struct dwarf2_frame_state_reg *reg; int num_regs; /* Used to implement DW_CFA_remember_state. */ @@ -242,12 +206,13 @@ static CORE_ADDR read_reg (void *baton, int reg) { struct frame_info *next_frame = (struct frame_info *) baton; + struct gdbarch *gdbarch = get_frame_arch (next_frame); int regnum; char *buf; regnum = DWARF2_REG_TO_REGNUM (reg); - buf = (char *) alloca (register_size (current_gdbarch, regnum)); + buf = (char *) alloca (register_size (gdbarch, regnum)); frame_unwind_register (next_frame, regnum, buf); return extract_typed_address (buf, builtin_type_void_data_ptr); } @@ -321,7 +286,7 @@ execute_cfa_program (unsigned char *insn_ptr, unsigned char *insn_end, insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp); offset = utmp * fs->data_align; dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1); - fs->regs.reg[reg].how = REG_SAVED_OFFSET; + fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAVED_OFFSET; fs->regs.reg[reg].loc.offset = offset; } else if ((insn & 0xc0) == DW_CFA_restore) @@ -361,7 +326,7 @@ execute_cfa_program (unsigned char *insn_ptr, unsigned char *insn_end, insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp); offset = utmp * fs->data_align; dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1); - fs->regs.reg[reg].how = REG_SAVED_OFFSET; + fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAVED_OFFSET; fs->regs.reg[reg].loc.offset = offset; break; @@ -375,20 +340,20 @@ execute_cfa_program (unsigned char *insn_ptr, unsigned char *insn_end, case DW_CFA_undefined: insn_ptr = read_uleb128 (insn_ptr, insn_end, ®); dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1); - fs->regs.reg[reg].how = REG_UNDEFINED; + fs->regs.reg[reg].how = DWARF2_FRAME_REG_UNDEFINED; break; case DW_CFA_same_value: insn_ptr = read_uleb128 (insn_ptr, insn_end, ®); dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1); - fs->regs.reg[reg].how = REG_SAME_VALUE; + fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAME_VALUE; break; case DW_CFA_register: insn_ptr = read_uleb128 (insn_ptr, insn_end, ®); insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp); dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1); - fs->regs.reg[reg].how = REG_SAVED_REG; + fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAVED_REG; fs->regs.reg[reg].loc.reg = utmp; break; @@ -448,7 +413,7 @@ execute_cfa_program (unsigned char *insn_ptr, unsigned char *insn_end, insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp); fs->regs.reg[reg].loc.exp = insn_ptr; fs->regs.reg[reg].exp_len = utmp; - fs->regs.reg[reg].how = REG_SAVED_EXP; + fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAVED_EXP; insn_ptr += utmp; break; @@ -457,7 +422,7 @@ execute_cfa_program (unsigned char *insn_ptr, unsigned char *insn_end, insn_ptr = read_sleb128 (insn_ptr, insn_end, &offset); offset += fs->data_align; dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1); - fs->regs.reg[reg].how = REG_SAVED_OFFSET; + fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAVED_OFFSET; fs->regs.reg[reg].loc.offset = offset; break; @@ -500,10 +465,47 @@ struct dwarf2_frame_cache struct dwarf2_frame_state_reg *reg; }; +/* Initialize the register state REG. If we have a register that acts + as a program counter, mark it as a destination for the return + address. If we have a register that serves as the stack pointer, + arrange for it to be filled with the call frame address (CFA). The + other registers are marked as unspecified. + + We copy the return address to the program counter, since many parts + in GDB assume that it is possible to get the return address by + unwind the program counter register. However, on ISA's with a + dedicated return address register, the CFI usually only contains + information to unwind that return address register. + + The reason we're treating the stack pointer special here is because + in many cases GCC doesn't emit CFI for the stack pointer and + implicitly assumes that it is equal to the CFA. This makes some + sense since the DWARF specification (version 3, draft 8, p. 102) + says that: + + "Typically, the CFA is defined to be the value of the stack pointer + at the call site in the previous frame (which may be different from + its value on entry to the current frame)." + + However, this isn't true for all platforms supported by GCC + (e.g. IBM S/390 and zSeries). For those targets we should override + the defaults given here. */ + +static void +dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum, + struct dwarf2_frame_state_reg *reg) +{ + if (regnum == PC_REGNUM) + reg->how = DWARF2_FRAME_REG_RA; + else if (regnum == SP_REGNUM) + reg->how = DWARF2_FRAME_REG_CFA; +} + static struct dwarf2_frame_cache * dwarf2_frame_cache (struct frame_info *next_frame, void **this_cache) { struct cleanup *old_chain; + struct gdbarch *gdbarch = get_frame_arch (next_frame); const int num_regs = NUM_REGS + NUM_PSEUDO_REGS; struct dwarf2_frame_cache *cache; struct dwarf2_frame_state *fs; @@ -575,43 +577,12 @@ dwarf2_frame_cache (struct frame_info *next_frame, void **this_cache) internal_error (__FILE__, __LINE__, "Unknown CFA rule."); } - /* Initialize the register rules. If we have a register that acts - as a program counter, mark it as a destination for the return - address. If we have a register that serves as the stack pointer, - arrange for it to be filled with the call frame address (CFA). - The other registers are marked as unspecified. - - We copy the return address to the program counter, since many - parts in GDB assume that it is possible to get the return address - by unwind the program counter register. However, on ISA's with a - dedicated return address register, the CFI usually only contains - information to unwind that return address register. - - The reason we're treating the stack pointer special here is - because in many cases GCC doesn't emit CFI for the stack pointer - and implicitly assumes that it is equal to the CFA. This makes - some sense since the DWARF specification (version 3, draft 8, - p. 102) says that: - - "Typically, the CFA is defined to be the value of the stack - pointer at the call site in the previous frame (which may be - different from its value on entry to the current frame)." - - However, this isn't true for all platforms supported by GCC - (e.g. IBM S/390 and zSeries). For those targets we should - override the defaults given here. */ + /* Initialize the register state. */ { int regnum; for (regnum = 0; regnum < num_regs; regnum++) - { - if (regnum == PC_REGNUM) - cache->reg[regnum].how = REG_RA; - else if (regnum == SP_REGNUM) - cache->reg[regnum].how = REG_CFA; - else - cache->reg[regnum].how = REG_UNSPECIFIED; - } + dwarf2_frame_init_reg (gdbarch, regnum, &cache->reg[regnum]); } /* Go through the DWARF2 CFI generated table and save its register @@ -644,7 +615,7 @@ dwarf2_frame_cache (struct frame_info *next_frame, void **this_cache) problems when a debug info register falls outside of the table. We need a way of iterating through all the valid DWARF2 register numbers. */ - if (fs->regs.reg[column].how == REG_UNSPECIFIED) + if (fs->regs.reg[column].how == DWARF2_FRAME_REG_UNSPECIFIED) complaint (&symfile_complaints, "Incomplete CFI data; unspecified registers at 0x%s", paddr (fs->pc)); @@ -653,14 +624,17 @@ dwarf2_frame_cache (struct frame_info *next_frame, void **this_cache) } } - /* Eliminate any REG_RA rules. */ + /* Eliminate any DWARF2_FRAME_REG_RA rules. */ { int regnum; for (regnum = 0; regnum < num_regs; regnum++) { - if (cache->reg[regnum].how == REG_RA) + if (cache->reg[regnum].how == DWARF2_FRAME_REG_RA) { + struct dwarf2_frame_state_reg *retaddr_reg = + &fs->regs.reg[fs->retaddr_column]; + /* It seems rather bizarre to specify an "empty" column as the return adress column. However, this is exactly what GCC does on some targets. It turns out that GCC @@ -669,13 +643,13 @@ dwarf2_frame_cache (struct frame_info *next_frame, void **this_cache) Incidentally, that's how should treat a return address column specifying "same value" too. */ if (fs->retaddr_column < fs->regs.num_regs - && fs->regs.reg[fs->retaddr_column].how != REG_UNSPECIFIED - && fs->regs.reg[fs->retaddr_column].how != REG_SAME_VALUE) - cache->reg[regnum] = fs->regs.reg[fs->retaddr_column]; + && retaddr_reg->how != DWARF2_FRAME_REG_UNSPECIFIED + && retaddr_reg->how != DWARF2_FRAME_REG_SAME_VALUE) + cache->reg[regnum] = *retaddr_reg; else { cache->reg[regnum].loc.reg = fs->retaddr_column; - cache->reg[regnum].how = REG_SAVED_REG; + cache->reg[regnum].how = DWARF2_FRAME_REG_SAVED_REG; } } } @@ -703,12 +677,13 @@ dwarf2_frame_prev_register (struct frame_info *next_frame, void **this_cache, enum lval_type *lvalp, CORE_ADDR *addrp, int *realnump, void *valuep) { + struct gdbarch *gdbarch = get_frame_arch (next_frame); struct dwarf2_frame_cache *cache = dwarf2_frame_cache (next_frame, this_cache); switch (cache->reg[regnum].how) { - case REG_UNDEFINED: + case DWARF2_FRAME_REG_UNDEFINED: /* If CFI explicitly specified that the value isn't defined, mark it as optimized away; the value isn't available. */ *optimizedp = 1; @@ -724,7 +699,7 @@ dwarf2_frame_prev_register (struct frame_info *next_frame, void **this_cache, } break; - case REG_SAVED_OFFSET: + case DWARF2_FRAME_REG_SAVED_OFFSET: *optimizedp = 0; *lvalp = lval_memory; *addrp = cache->cfa + cache->reg[regnum].loc.offset; @@ -732,18 +707,17 @@ dwarf2_frame_prev_register (struct frame_info *next_frame, void **this_cache, if (valuep) { /* Read the value in from memory. */ - read_memory (*addrp, valuep, - register_size (current_gdbarch, regnum)); + read_memory (*addrp, valuep, register_size (gdbarch, regnum)); } break; - case REG_SAVED_REG: + case DWARF2_FRAME_REG_SAVED_REG: regnum = DWARF2_REG_TO_REGNUM (cache->reg[regnum].loc.reg); frame_register_unwind (next_frame, regnum, optimizedp, lvalp, addrp, realnump, valuep); break; - case REG_SAVED_EXP: + case DWARF2_FRAME_REG_SAVED_EXP: *optimizedp = 0; *lvalp = lval_memory; *addrp = execute_stack_op (cache->reg[regnum].loc.exp, @@ -753,12 +727,11 @@ dwarf2_frame_prev_register (struct frame_info *next_frame, void **this_cache, if (valuep) { /* Read the value in from memory. */ - read_memory (*addrp, valuep, - register_size (current_gdbarch, regnum)); + read_memory (*addrp, valuep, register_size (gdbarch, regnum)); } break; - case REG_UNSPECIFIED: + case DWARF2_FRAME_REG_UNSPECIFIED: /* GCC, in its infinite wisdom decided to not provide unwind information for registers that are "same value". Since DWARF2 (3 draft 7) doesn't define such behavior, said @@ -770,12 +743,12 @@ dwarf2_frame_prev_register (struct frame_info *next_frame, void **this_cache, optimizedp, lvalp, addrp, realnump, valuep); break; - case REG_SAME_VALUE: + case DWARF2_FRAME_REG_SAME_VALUE: frame_register_unwind (next_frame, regnum, optimizedp, lvalp, addrp, realnump, valuep); break; - case REG_CFA: + case DWARF2_FRAME_REG_CFA: *optimizedp = 0; *lvalp = not_lval; *addrp = 0; diff --git a/gdb/dwarf2-frame.h b/gdb/dwarf2-frame.h index c9c106f..b650a84 100644 --- a/gdb/dwarf2-frame.h +++ b/gdb/dwarf2-frame.h @@ -1,6 +1,6 @@ /* Frame unwinder for frames with DWARF Call Frame Information. - Copyright 2003 Free Software Foundation, Inc. + Copyright 2003, 2004 Free Software Foundation, Inc. Contributed by Mark Kettenis. @@ -27,15 +27,61 @@ struct objfile; struct frame_info; +/* Register rule. */ + +enum dwarf2_frame_reg_rule +{ + /* Make certain that 0 maps onto the correct enum value; the + corresponding structure is being initialized using memset zero. + This indicates that CFI didn't provide any information at all + about a register, leaving how to obtain its value totally + unspecified. */ + DWARF2_FRAME_REG_UNSPECIFIED = 0, + + /* The term "undefined" comes from the DWARF2 CFI spec which this + code is moddeling; it indicates that the register's value is + "undefined". GCC uses the less formal term "unsaved". Its + definition is a combination of REG_UNDEFINED and REG_UNSPECIFIED. + The failure to differentiate the two helps explain a few problems + with the CFI generated by GCC. */ + DWARF2_FRAME_REG_UNDEFINED, + DWARF2_FRAME_REG_SAVED_OFFSET, + DWARF2_FRAME_REG_SAVED_REG, + DWARF2_FRAME_REG_SAVED_EXP, + DWARF2_FRAME_REG_SAME_VALUE, + + /* These aren't defined by the DWARF2 CFI specification, but are + used internally by GDB. */ + DWARF2_FRAME_REG_RA, /* Return Address. */ + DWARF2_FRAME_REG_CFA /* Call Frame Address. */ +}; + +/* Register state. */ + +struct dwarf2_frame_state_reg +{ + /* Each register save state can be described in terms of a CFA slot, + another register, or a location expression. */ + union { + LONGEST offset; + ULONGEST reg; + unsigned char *exp; + } loc; + ULONGEST exp_len; + enum dwarf2_frame_reg_rule how; +}; + /* Return the frame unwind methods for the function that contains PC, or NULL if it can't be handled by DWARF CFI frame unwinder. */ -const struct frame_unwind *dwarf2_frame_sniffer (struct frame_info *next_frame); +extern const struct frame_unwind * + dwarf2_frame_sniffer (struct frame_info *next_frame); /* Return the frame base methods for the function that contains PC, or NULL if it can't be handled by the DWARF CFI frame unwinder. */ -const struct frame_base *dwarf2_frame_base_sniffer (struct frame_info *next_frame); +extern const struct frame_base * + dwarf2_frame_base_sniffer (struct frame_info *next_frame); /* Register the DWARF CFI for OBJFILE. */ -- 2.7.4