diff options
author | Mark Kettenis <kettenis@gnu.org> | 2003-12-27 23:15:00 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@gnu.org> | 2003-12-27 23:15:00 +0000 |
commit | 9b1a720f91d2bbaa9684ca663ec75c380fcde4a9 (patch) | |
tree | 68692ac16ea35060976d76ca967803185d325c60 /gdb/dwarf2-frame.c | |
parent | 42260a8023cfa941407d65eb4cf8001db19c4636 (diff) | |
download | gdb-9b1a720f91d2bbaa9684ca663ec75c380fcde4a9.tar.gz |
* dwarf2-frame.c (dwarf2_reg_rule): Add REG_RA and REG_CFA.
(dwarf2_frame_cache): Initialize PC_REGNUM with REG_RA and
SP_REGNUM with REG_CFA. Don't overwrite the initialized register
rule for registers left unspecified by the CFI. Remove the
special handling of PC_REGNUM. Add code to eleminate any REG_RA
rules.
(dwarf2_frame_prev_register): Remove the special handling of
SP_REGNUM. Add support for the REG_CFA rule.
Diffstat (limited to 'gdb/dwarf2-frame.c')
-rw-r--r-- | gdb/dwarf2-frame.c | 187 |
1 files changed, 79 insertions, 108 deletions
diff --git a/gdb/dwarf2-frame.c b/gdb/dwarf2-frame.c index aed3f3a10d6..84bc1c2d50c 100644 --- a/gdb/dwarf2-frame.c +++ b/gdb/dwarf2-frame.c @@ -105,6 +105,7 @@ enum dwarf2_reg_rule 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 @@ -115,7 +116,12 @@ enum dwarf2_reg_rule REG_SAVED_OFFSET, REG_SAVED_REG, REG_SAVED_EXP, - REG_SAME_VALUE + 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 @@ -547,13 +553,43 @@ dwarf2_frame_cache (struct frame_info *next_frame, void **this_cache) internal_error (__FILE__, __LINE__, "Unknown CFA rule."); } - /* Initialize things so that all registers are marked as - unspecified. */ + /* 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. */ { int regnum; for (regnum = 0; regnum < num_regs; regnum++) - cache->reg[regnum].how = REG_UNSPECIFIED; + { + 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; + } } /* Go through the DWARF2 CFI generated table and save its register @@ -590,35 +626,33 @@ dwarf2_frame_cache (struct frame_info *next_frame, void **this_cache) complaint (&symfile_complaints, "Incomplete CFI data; unspecified registers at 0x%s", paddr (fs->pc)); - - cache->reg[regnum] = fs->regs.reg[column]; + else + cache->reg[regnum] = fs->regs.reg[column]; } } - /* Store the location of the return addess. If the return address - column (adjusted) is not the same as GDB's PC_REGNUM, then this - implies a copy from the return address column register. */ - if (fs->retaddr_column < fs->regs.num_regs - && fs->regs.reg[fs->retaddr_column].how != REG_UNDEFINED) - { - /* See comment above about a possibly negative PC_REGNUM. If - this assertion fails, it's a problem with this code and not - the architecture. */ - gdb_assert (PC_REGNUM >= 0); - cache->reg[PC_REGNUM] = fs->regs.reg[fs->retaddr_column]; - } - else - { - if (DWARF2_REG_TO_REGNUM (fs->retaddr_column) != PC_REGNUM) - { - /* See comment above about PC_REGNUM being negative. If - this assertion fails, it's a problem with this code and - not the architecture. */ - gdb_assert (PC_REGNUM >= 0); - cache->reg[PC_REGNUM].loc.reg = fs->retaddr_column; - cache->reg[PC_REGNUM].how = REG_SAVED_REG; - } - } + /* Eliminate any REG_RA rules. */ + { + int regnum; + + for (regnum = 0; regnum < num_regs; regnum++) + { + if (cache->reg[regnum].how == REG_RA) + { + if (fs->retaddr_column < fs->regs.num_regs) + cache->reg[regnum] = fs->regs.reg[fs->retaddr_column]; + else + { + /* It turns out that GCC assumes that if the return + address column is "empty" the return address can be + found in the register corresponding to the return + address column. */ + cache->reg[regnum].loc.reg = fs->retaddr_column; + cache->reg[regnum].how = REG_SAVED_REG; + } + } + } + } do_cleanups (old_chain); @@ -654,42 +688,7 @@ dwarf2_frame_prev_register (struct frame_info *next_frame, void **this_cache, *lvalp = not_lval; *addrp = 0; *realnump = -1; - if (regnum == SP_REGNUM) - { - /* GCC defines the CFA as the value of the stack pointer - just before the call instruction is executed. Do other - compilers use the same definition? */ - /* DWARF V3 Draft 7 p102: 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). */ - /* DWARF V3 Draft 7 p103: The first column of the rules - defines the rule which computes the CFA value; it may be - either a register and a signed offset that are added - together or a DWARF expression that is evaluated. */ - /* FIXME: cagney/2003-07-07: I don't understand this. The - CFI info should have provided unwind information for the - SP register and then pointed ->cfa_reg at it, not the - reverse. Assuming that SP_REGNUM isn't negative, there - is a very real posibility that CFA is an offset from some - other register, having nothing to do with the unwound SP - value. */ - /* FIXME: cagney/2003-09-05: I think I understand. GDB was - lumping the two states "unspecified" and "undefined" - together. Here SP_REGNUM was "unspecified", GCC assuming - that in such a case CFA would be used. This branch of - the if statement should be deleted - the problem of - SP_REGNUM is now handed by the case REG_UNSPECIFIED - below. */ - *optimizedp = 0; - if (valuep) - { - /* Store the value. */ - store_typed_address (valuep, builtin_type_void_data_ptr, - cache->cfa); - } - } - else if (valuep) + if (valuep) { /* In some cases, for example %eflags on the i386, we have to provide a sane value, even though this register wasn't @@ -740,48 +739,8 @@ dwarf2_frame_prev_register (struct frame_info *next_frame, void **this_cache, "undefined"). Code above issues a complaint about this. Here just fudge the books, assume GCC, and that the value is more inner on the stack. */ - if (SP_REGNUM >= 0 && regnum == SP_REGNUM) - { - /* Can things get worse? Yep! One of the registers GCC - forgot to provide unwind information for was the stack - pointer. Outch! GCC appears to assumes that the CFA - address can be used - after all it points to the inner - most address of the previous frame before the function - call and that's always the same as the stack pointer on - return, right? Wrong. See GCC's i386 STDCALL option for - an ABI that has a different entry and return stack - pointer. */ - /* DWARF V3 Draft 7 p102: 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). */ - /* DWARF V3 Draft 7 p103: The first column of the rules - defines the rule which computes the CFA value; it may be - either a register and a signed offset that are added - together or a DWARF expression that is evaluated. */ - /* NOTE: cagney/2003-09-05: Should issue a complaint. - Unfortunately it turns out that DWARF2 CFI has a problem. - Since CFI specifies the location at which a register was - saved (not its value) it isn't possible to specify - something like "unwound(REG) == REG + constant" using CFI - as will almost always occure with the stack pointer. I - guess CFI should be point SP at CFA. Ref: danielj, - "Describing unsaved stack pointers", posted to dwarf2 - list 2003-08-15. */ - *optimizedp = 0; - *lvalp = not_lval; - *addrp = 0; - *realnump = -1; - if (valuep) - /* Store the value. */ - store_typed_address (valuep, builtin_type_void_data_ptr, - cache->cfa); - } - else - /* Assume that the register can be found in the next inner - most frame. */ - frame_register_unwind (next_frame, regnum, - optimizedp, lvalp, addrp, realnump, valuep); + frame_register_unwind (next_frame, regnum, + optimizedp, lvalp, addrp, realnump, valuep); break; case REG_SAME_VALUE: @@ -789,6 +748,18 @@ dwarf2_frame_prev_register (struct frame_info *next_frame, void **this_cache, optimizedp, lvalp, addrp, realnump, valuep); break; + case REG_CFA: + *optimizedp = 0; + *lvalp = not_lval; + *addrp = 0; + *realnump = -1; + if (valuep) + { + /* Store the value. */ + store_typed_address (valuep, builtin_type_void_data_ptr, cache->cfa); + } + break; + default: internal_error (__FILE__, __LINE__, "Unknown register rule."); } |