* 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:
parent
dd1abb8c9e
commit
05cbe71add
3 changed files with 142 additions and 100 deletions
|
@ -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>
|
2004-02-06 Andrew Cagney <cagney@redhat.com>
|
||||||
|
|
||||||
* tui/tui-data.h (struct tui_list): Rename _TuiList.
|
* tui/tui-data.h (struct tui_list): Rename _TuiList.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* Frame unwinder for frames with DWARF Call Frame Information.
|
/* 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.
|
Contributed by Mark Kettenis.
|
||||||
|
|
||||||
|
@ -97,49 +97,13 @@ static struct dwarf2_fde *dwarf2_frame_find_fde (CORE_ADDR *pc);
|
||||||
|
|
||||||
/* Structure describing a frame state. */
|
/* 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
|
struct dwarf2_frame_state
|
||||||
{
|
{
|
||||||
/* Each register save state can be described in terms of a CFA slot,
|
/* Each register save state can be described in terms of a CFA slot,
|
||||||
another register, or a location expression. */
|
another register, or a location expression. */
|
||||||
struct dwarf2_frame_state_reg_info
|
struct dwarf2_frame_state_reg_info
|
||||||
{
|
{
|
||||||
struct dwarf2_frame_state_reg
|
struct dwarf2_frame_state_reg *reg;
|
||||||
{
|
|
||||||
union {
|
|
||||||
LONGEST offset;
|
|
||||||
ULONGEST reg;
|
|
||||||
unsigned char *exp;
|
|
||||||
} loc;
|
|
||||||
ULONGEST exp_len;
|
|
||||||
enum dwarf2_reg_rule how;
|
|
||||||
} *reg;
|
|
||||||
int num_regs;
|
int num_regs;
|
||||||
|
|
||||||
/* Used to implement DW_CFA_remember_state. */
|
/* Used to implement DW_CFA_remember_state. */
|
||||||
|
@ -242,12 +206,13 @@ static CORE_ADDR
|
||||||
read_reg (void *baton, int reg)
|
read_reg (void *baton, int reg)
|
||||||
{
|
{
|
||||||
struct frame_info *next_frame = (struct frame_info *) baton;
|
struct frame_info *next_frame = (struct frame_info *) baton;
|
||||||
|
struct gdbarch *gdbarch = get_frame_arch (next_frame);
|
||||||
int regnum;
|
int regnum;
|
||||||
char *buf;
|
char *buf;
|
||||||
|
|
||||||
regnum = DWARF2_REG_TO_REGNUM (reg);
|
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);
|
frame_unwind_register (next_frame, regnum, buf);
|
||||||
return extract_typed_address (buf, builtin_type_void_data_ptr);
|
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);
|
insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp);
|
||||||
offset = utmp * fs->data_align;
|
offset = utmp * fs->data_align;
|
||||||
dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
|
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;
|
fs->regs.reg[reg].loc.offset = offset;
|
||||||
}
|
}
|
||||||
else if ((insn & 0xc0) == DW_CFA_restore)
|
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);
|
insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp);
|
||||||
offset = utmp * fs->data_align;
|
offset = utmp * fs->data_align;
|
||||||
dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
|
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;
|
fs->regs.reg[reg].loc.offset = offset;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -375,20 +340,20 @@ execute_cfa_program (unsigned char *insn_ptr, unsigned char *insn_end,
|
||||||
case DW_CFA_undefined:
|
case DW_CFA_undefined:
|
||||||
insn_ptr = read_uleb128 (insn_ptr, insn_end, ®);
|
insn_ptr = read_uleb128 (insn_ptr, insn_end, ®);
|
||||||
dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
|
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;
|
break;
|
||||||
|
|
||||||
case DW_CFA_same_value:
|
case DW_CFA_same_value:
|
||||||
insn_ptr = read_uleb128 (insn_ptr, insn_end, ®);
|
insn_ptr = read_uleb128 (insn_ptr, insn_end, ®);
|
||||||
dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
|
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;
|
break;
|
||||||
|
|
||||||
case DW_CFA_register:
|
case DW_CFA_register:
|
||||||
insn_ptr = read_uleb128 (insn_ptr, insn_end, ®);
|
insn_ptr = read_uleb128 (insn_ptr, insn_end, ®);
|
||||||
insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp);
|
insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp);
|
||||||
dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
|
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;
|
fs->regs.reg[reg].loc.reg = utmp;
|
||||||
break;
|
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);
|
insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp);
|
||||||
fs->regs.reg[reg].loc.exp = insn_ptr;
|
fs->regs.reg[reg].loc.exp = insn_ptr;
|
||||||
fs->regs.reg[reg].exp_len = utmp;
|
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;
|
insn_ptr += utmp;
|
||||||
break;
|
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);
|
insn_ptr = read_sleb128 (insn_ptr, insn_end, &offset);
|
||||||
offset += fs->data_align;
|
offset += fs->data_align;
|
||||||
dwarf2_frame_state_alloc_regs (&fs->regs, reg + 1);
|
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;
|
fs->regs.reg[reg].loc.offset = offset;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -500,10 +465,47 @@ struct dwarf2_frame_cache
|
||||||
struct dwarf2_frame_state_reg *reg;
|
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 *
|
static struct dwarf2_frame_cache *
|
||||||
dwarf2_frame_cache (struct frame_info *next_frame, void **this_cache)
|
dwarf2_frame_cache (struct frame_info *next_frame, void **this_cache)
|
||||||
{
|
{
|
||||||
struct cleanup *old_chain;
|
struct cleanup *old_chain;
|
||||||
|
struct gdbarch *gdbarch = get_frame_arch (next_frame);
|
||||||
const 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_cache *cache;
|
||||||
struct dwarf2_frame_state *fs;
|
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.");
|
internal_error (__FILE__, __LINE__, "Unknown CFA rule.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize the register rules. If we have a register that acts
|
/* Initialize the register state. */
|
||||||
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;
|
int regnum;
|
||||||
|
|
||||||
for (regnum = 0; regnum < num_regs; regnum++)
|
for (regnum = 0; regnum < num_regs; regnum++)
|
||||||
{
|
dwarf2_frame_init_reg (gdbarch, regnum, &cache->reg[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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Go through the DWARF2 CFI generated table and save its register
|
/* 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
|
problems when a debug info register falls outside of the
|
||||||
table. We need a way of iterating through all the valid
|
table. We need a way of iterating through all the valid
|
||||||
DWARF2 register numbers. */
|
DWARF2 register numbers. */
|
||||||
if (fs->regs.reg[column].how == REG_UNSPECIFIED)
|
if (fs->regs.reg[column].how == DWARF2_FRAME_REG_UNSPECIFIED)
|
||||||
complaint (&symfile_complaints,
|
complaint (&symfile_complaints,
|
||||||
"Incomplete CFI data; unspecified registers at 0x%s",
|
"Incomplete CFI data; unspecified registers at 0x%s",
|
||||||
paddr (fs->pc));
|
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;
|
int regnum;
|
||||||
|
|
||||||
for (regnum = 0; regnum < num_regs; 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
|
/* It seems rather bizarre to specify an "empty" column as
|
||||||
the return adress column. However, this is exactly
|
the return adress column. However, this is exactly
|
||||||
what GCC does on some targets. It turns out that GCC
|
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
|
Incidentally, that's how should treat a return address
|
||||||
column specifying "same value" too. */
|
column specifying "same value" too. */
|
||||||
if (fs->retaddr_column < fs->regs.num_regs
|
if (fs->retaddr_column < fs->regs.num_regs
|
||||||
&& fs->regs.reg[fs->retaddr_column].how != REG_UNSPECIFIED
|
&& retaddr_reg->how != DWARF2_FRAME_REG_UNSPECIFIED
|
||||||
&& fs->regs.reg[fs->retaddr_column].how != REG_SAME_VALUE)
|
&& retaddr_reg->how != DWARF2_FRAME_REG_SAME_VALUE)
|
||||||
cache->reg[regnum] = fs->regs.reg[fs->retaddr_column];
|
cache->reg[regnum] = *retaddr_reg;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cache->reg[regnum].loc.reg = fs->retaddr_column;
|
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,
|
enum lval_type *lvalp, CORE_ADDR *addrp,
|
||||||
int *realnump, void *valuep)
|
int *realnump, void *valuep)
|
||||||
{
|
{
|
||||||
|
struct gdbarch *gdbarch = get_frame_arch (next_frame);
|
||||||
struct dwarf2_frame_cache *cache =
|
struct dwarf2_frame_cache *cache =
|
||||||
dwarf2_frame_cache (next_frame, this_cache);
|
dwarf2_frame_cache (next_frame, this_cache);
|
||||||
|
|
||||||
switch (cache->reg[regnum].how)
|
switch (cache->reg[regnum].how)
|
||||||
{
|
{
|
||||||
case REG_UNDEFINED:
|
case DWARF2_FRAME_REG_UNDEFINED:
|
||||||
/* If CFI explicitly specified that the value isn't defined,
|
/* If CFI explicitly specified that the value isn't defined,
|
||||||
mark it as optimized away; the value isn't available. */
|
mark it as optimized away; the value isn't available. */
|
||||||
*optimizedp = 1;
|
*optimizedp = 1;
|
||||||
|
@ -724,7 +699,7 @@ dwarf2_frame_prev_register (struct frame_info *next_frame, void **this_cache,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case REG_SAVED_OFFSET:
|
case DWARF2_FRAME_REG_SAVED_OFFSET:
|
||||||
*optimizedp = 0;
|
*optimizedp = 0;
|
||||||
*lvalp = lval_memory;
|
*lvalp = lval_memory;
|
||||||
*addrp = cache->cfa + cache->reg[regnum].loc.offset;
|
*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)
|
if (valuep)
|
||||||
{
|
{
|
||||||
/* Read the value in from memory. */
|
/* Read the value in from memory. */
|
||||||
read_memory (*addrp, valuep,
|
read_memory (*addrp, valuep, register_size (gdbarch, regnum));
|
||||||
register_size (current_gdbarch, regnum));
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case REG_SAVED_REG:
|
case DWARF2_FRAME_REG_SAVED_REG:
|
||||||
regnum = DWARF2_REG_TO_REGNUM (cache->reg[regnum].loc.reg);
|
regnum = DWARF2_REG_TO_REGNUM (cache->reg[regnum].loc.reg);
|
||||||
frame_register_unwind (next_frame, regnum,
|
frame_register_unwind (next_frame, regnum,
|
||||||
optimizedp, lvalp, addrp, realnump, valuep);
|
optimizedp, lvalp, addrp, realnump, valuep);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case REG_SAVED_EXP:
|
case DWARF2_FRAME_REG_SAVED_EXP:
|
||||||
*optimizedp = 0;
|
*optimizedp = 0;
|
||||||
*lvalp = lval_memory;
|
*lvalp = lval_memory;
|
||||||
*addrp = execute_stack_op (cache->reg[regnum].loc.exp,
|
*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)
|
if (valuep)
|
||||||
{
|
{
|
||||||
/* Read the value in from memory. */
|
/* Read the value in from memory. */
|
||||||
read_memory (*addrp, valuep,
|
read_memory (*addrp, valuep, register_size (gdbarch, regnum));
|
||||||
register_size (current_gdbarch, regnum));
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case REG_UNSPECIFIED:
|
case DWARF2_FRAME_REG_UNSPECIFIED:
|
||||||
/* GCC, in its infinite wisdom decided to not provide unwind
|
/* GCC, in its infinite wisdom decided to not provide unwind
|
||||||
information for registers that are "same value". Since
|
information for registers that are "same value". Since
|
||||||
DWARF2 (3 draft 7) doesn't define such behavior, said
|
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);
|
optimizedp, lvalp, addrp, realnump, valuep);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case REG_SAME_VALUE:
|
case DWARF2_FRAME_REG_SAME_VALUE:
|
||||||
frame_register_unwind (next_frame, regnum,
|
frame_register_unwind (next_frame, regnum,
|
||||||
optimizedp, lvalp, addrp, realnump, valuep);
|
optimizedp, lvalp, addrp, realnump, valuep);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case REG_CFA:
|
case DWARF2_FRAME_REG_CFA:
|
||||||
*optimizedp = 0;
|
*optimizedp = 0;
|
||||||
*lvalp = not_lval;
|
*lvalp = not_lval;
|
||||||
*addrp = 0;
|
*addrp = 0;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* Frame unwinder for frames with DWARF Call Frame Information.
|
/* 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.
|
Contributed by Mark Kettenis.
|
||||||
|
|
||||||
|
@ -27,15 +27,61 @@
|
||||||
struct objfile;
|
struct objfile;
|
||||||
struct frame_info;
|
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,
|
/* Return the frame unwind methods for the function that contains PC,
|
||||||
or NULL if it can't be handled by DWARF CFI frame unwinder. */
|
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
|
/* 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. */
|
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. */
|
/* Register the DWARF CFI for OBJFILE. */
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue