* 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_.
This commit is contained in:
Mark Kettenis 2004-02-07 14:44:50 +00:00
parent dd1abb8c9e
commit 05cbe71add
3 changed files with 142 additions and 100 deletions

View file

@ -1,3 +1,26 @@
2004-02-07 Mark Kettenis <kettenis@gnu.org>
* 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 <cagney@redhat.com>
* tui/tui-data.h (struct tui_list): Rename _TuiList.

View file

@ -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, &reg);
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, &reg);
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, &reg);
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;

View file

@ -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. */