summaryrefslogtreecommitdiff
path: root/gdb/dwarf2-frame.c
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@gnu.org>2004-02-07 14:44:50 +0000
committerMark Kettenis <kettenis@gnu.org>2004-02-07 14:44:50 +0000
commitbec313f7f988e337bd982d9f335827ad4e19e50d (patch)
tree7fab95e5a5ca9ae7c47d4be96380c4608f933547 /gdb/dwarf2-frame.c
parentbcc11eaa183a9cd7ea7b79ed8130bbfae303efdf (diff)
downloadgdb-bec313f7f988e337bd982d9f335827ad4e19e50d.tar.gz
* 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_.
Diffstat (limited to 'gdb/dwarf2-frame.c')
-rw-r--r--gdb/dwarf2-frame.c167
1 files changed, 70 insertions, 97 deletions
diff --git a/gdb/dwarf2-frame.c b/gdb/dwarf2-frame.c
index 22e41071f86..ed7f4ab95fa 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, &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;