2003-09-08 Andrew Cagney <cagney@redhat.com>

* dwarf2-frame.c (enum dwarf2_reg_rule): New, replace anonymous
	enum.  Add REG_UNSPECIFIED, rename REG_UNSAVED to REG_UNDEFINED
	and REG_UNMODIFIED to REG_SAME_VALUE.
	(execute_cfa_program): Update.
	(dwarf2_frame_cache): Update.  Initialize table to
	REG_UNSPECIFIED, complain if CFI fails to specify a register's
	location.
	(dwarf2_frame_prev_register): Update.  Handle REG_UNSPECIFIED.
This commit is contained in:
Andrew Cagney 2003-09-09 03:31:07 +00:00
parent 39efb398a9
commit 3e2c403395
2 changed files with 152 additions and 34 deletions

View File

@ -1,3 +1,14 @@
2003-09-08 Andrew Cagney <cagney@redhat.com>
* dwarf2-frame.c (enum dwarf2_reg_rule): New, replace anonymous
enum. Add REG_UNSPECIFIED, rename REG_UNSAVED to REG_UNDEFINED
and REG_UNMODIFIED to REG_SAME_VALUE.
(execute_cfa_program): Update.
(dwarf2_frame_cache): Update. Initialize table to
REG_UNSPECIFIED, complain if CFI fails to specify a register's
location.
(dwarf2_frame_prev_register): Update. Handle REG_UNSPECIFIED.
2003-09-08 Andrew Cagney <cagney@redhat.com>
* gnu-nat.c: Remove "inline" function attribute.

View File

@ -97,6 +97,28 @@ 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 it's 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". */
/* NOTE: cagney/2003-09-08: GCC uses the less formal term "unsaved"
- it's definition is a combination of REG_UNDEFINED and
REG_UNSPECIFIED - the failure to differentiate the two helps
explain a few problems with the CFI GCC outputs. */
REG_UNDEFINED,
REG_SAVED_OFFSET,
REG_SAVED_REG,
REG_SAVED_EXP,
REG_SAME_VALUE
};
struct dwarf2_frame_state
{
/* Each register save state can be described in terms of a CFA slot,
@ -111,13 +133,7 @@ struct dwarf2_frame_state
unsigned char *exp;
} loc;
ULONGEST exp_len;
enum {
REG_UNSAVED,
REG_SAVED_OFFSET,
REG_SAVED_REG,
REG_SAVED_EXP,
REG_UNMODIFIED
} how;
enum dwarf2_reg_rule how;
} *reg;
int num_regs;
@ -354,13 +370,13 @@ execute_cfa_program (unsigned char *insn_ptr, unsigned char *insn_end,
case DW_CFA_undefined:
insn_ptr = read_uleb128 (insn_ptr, insn_end, &reg);
dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
fs->regs.reg[reg].how = REG_UNSAVED;
fs->regs.reg[reg].how = REG_UNDEFINED;
break;
case DW_CFA_same_value:
insn_ptr = read_uleb128 (insn_ptr, insn_end, &reg);
dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
fs->regs.reg[reg].how = REG_UNMODIFIED;
fs->regs.reg[reg].how = REG_SAME_VALUE;
break;
case DW_CFA_register:
@ -460,11 +476,10 @@ static struct dwarf2_frame_cache *
dwarf2_frame_cache (struct frame_info *next_frame, void **this_cache)
{
struct cleanup *old_chain;
int num_regs = NUM_REGS + NUM_PSEUDO_REGS;
const int num_regs = NUM_REGS + NUM_PSEUDO_REGS;
struct dwarf2_frame_cache *cache;
struct dwarf2_frame_state *fs;
struct dwarf2_fde *fde;
int reg;
if (*this_cache)
return *this_cache;
@ -535,34 +550,65 @@ dwarf2_frame_cache (struct frame_info *next_frame, void **this_cache)
internal_error (__FILE__, __LINE__, "Unknown CFA rule.");
}
/* Save the register info in the cache. */
for (reg = 0; reg < fs->regs.num_regs; reg++)
{
int regnum;
/* Initialize things so that all registers are marked as
unspecified. */
{
int regnum;
for (regnum = 0; regnum < num_regs; regnum++)
cache->reg[regnum].how = REG_UNSPECIFIED;
}
/* Skip the return address column. */
if (reg == fs->retaddr_column)
/* NOTE: cagney/2003-06-07: Is this right? What if the
RETADDR_COLUM corresponds to a real register (and, worse,
that isn't the PC_REGNUM)? I'm guessing that the PC_REGNUM
further down is trying to handle this. That can't be right
though - PC_REGNUM may not be valid (it can be -ve). I
think, instead when RETADDR_COLUM isn't a real register, it
should map itself onto frame_pc_unwind. */
continue;
/* Go through the DWARF2 CFI generated table and save its register
location information in the cache. */
{
int column; /* CFI speak for "register number". */
for (column = 0; column < fs->regs.num_regs; column++)
{
int regnum;
/* Skip the return address column. */
if (column == fs->retaddr_column)
/* NOTE: cagney/2003-06-07: Is this right? What if
RETADDR_COLUMN corresponds to a real register (and,
worse, that isn't the PC_REGNUM)? I'm guessing that the
PC_REGNUM further down is trying to handle this. That
can't be right though - PC_REGNUM may not be valid (it
can be -ve). I think, instead when RETADDR_COLUM isn't a
real register, it should map itself onto frame_pc_unwind. */
continue;
/* Use the GDB register number as index. */
regnum = DWARF2_REG_TO_REGNUM (reg);
/* Use the GDB register number as the destination index. */
regnum = DWARF2_REG_TO_REGNUM (column);
if (regnum >= 0 && regnum < num_regs)
cache->reg[regnum] = fs->regs.reg[reg];
}
/* If there's no corresponding GDB register, ignore it. */
if (regnum < 0 || regnum >= num_regs)
continue;
/* NOTE: cagney/2003-09-05: CFI should specify the disposition
of all debug info registers. If it doesn't complain (but
not too loudly). It turns out that GCC, assumes that an
unspecified register implies "same value" when CFI (draft
7) specifies nothing at all. Such a register could equally
be interpreted as "undefined". Also note that this check
isn't sufficient - it only checks that all registers in the
range [0 .. max column] are specified - and won't detect
problems when a debug info register falls outside of the
table. Need a way of iterating through all the valid
DWARF2 register numbers. */
if (fs->regs.reg[column].how == REG_UNSPECIFIED)
complaint (&symfile_complaints,
"Incomplete CFI data; unspecified registers at 0x%s",
paddr (fs->pc));
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 ra column register. */
if (fs->retaddr_column < fs->regs.num_regs
&& fs->regs.reg[fs->retaddr_column].how != REG_UNSAVED)
&& fs->regs.reg[fs->retaddr_column].how != REG_UNDEFINED)
{
/* See comment above about a possibly -ve PC_REGNUM. If this
assertion fails, it's a problem with this code and not the
@ -572,7 +618,7 @@ dwarf2_frame_cache (struct frame_info *next_frame, void **this_cache)
}
else
{
reg = DWARF2_REG_TO_REGNUM (fs->retaddr_column);
int reg = DWARF2_REG_TO_REGNUM (fs->retaddr_column);
if (reg != PC_REGNUM)
{
/* See comment above about PC_REGNUM being -ve. If this
@ -611,7 +657,9 @@ dwarf2_frame_prev_register (struct frame_info *next_frame, void **this_cache,
switch (cache->reg[regnum].how)
{
case REG_UNSAVED:
case REG_UNDEFINED:
/* If CFI explicitly specified that the value isn't defined,
mark it as optimized away - the value isn't available. */
*optimizedp = 1;
*lvalp = not_lval;
*addrp = 0;
@ -636,6 +684,13 @@ dwarf2_frame_prev_register (struct frame_info *next_frame, void **this_cache,
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)
{
@ -687,7 +742,59 @@ dwarf2_frame_prev_register (struct frame_info *next_frame, void **this_cache,
}
break;
case REG_UNMODIFIED:
case 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
registers are actually undefined (which is different to CFI
"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 complain.
Unfortunatly 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);
break;
case REG_SAME_VALUE:
frame_register_unwind (next_frame, regnum,
optimizedp, lvalp, addrp, realnump, valuep);
break;