aboutsummaryrefslogtreecommitdiff
path: root/gdb/dwarf2-frame.c
diff options
context:
space:
mode:
authornobody <>2004-02-14 00:00:34 +0000
committernobody <>2004-02-14 00:00:34 +0000
commit2f344a4dcd2a8c4297702027a943e3587e6b60c8 (patch)
tree8614f4d9fc669ec37a90e4b4f70b31f00c489661 /gdb/dwarf2-frame.c
parenta5dd37ab655106440e987830db5111b43f271ecc (diff)
downloadgdb-2f344a4dcd2a8c4297702027a943e3587e6b60c8.zip
gdb-2f344a4dcd2a8c4297702027a943e3587e6b60c8.tar.gz
gdb-2f344a4dcd2a8c4297702027a943e3587e6b60c8.tar.bz2
This commit was manufactured by cvs2svn to create branchcagney_bfdfile-20040213-branchpointcagney_bfdfile-20040213-branch
'cagney_bfdfile-20040213-branch'. Sprout from cagney_bigcore-20040122-branch 2004-01-22 00:00:03 UTC nobody 'This commit was manufactured by cvs2svn to create branch' Cherrypick from master 2004-02-14 00:00:33 UTC gdbadmin <gdbadmin@sourceware.org> '*** empty log message ***': COPYING.NEWLIB ChangeLog Makefile.def Makefile.in bfd/ChangeLog bfd/bfd-in.h bfd/bfd-in2.h bfd/bfdio.c bfd/cache.c bfd/coff-h8300.c bfd/config.in bfd/configure bfd/configure.in bfd/elf-bfd.h bfd/elf.c bfd/elf32-arm.h bfd/elf32-frv.c bfd/elf32-h8300.c bfd/elf64-alpha.c bfd/elfxx-ia64.c bfd/elfxx-mips.c bfd/elfxx-mips.h bfd/elfxx-target.h bfd/libbfd-in.h bfd/libbfd.h bfd/version.h binutils/ChangeLog binutils/readelf.c configure configure.in gas/ChangeLog gas/config/tc-arm.c gas/config/tc-ia64.c gas/config/tc-ia64.h gas/config/tc-m68k.c gas/config/tc-m68k.h gas/config/tc-mips.c gas/config/tc-mips.h gas/doc/internals.texi gas/dwarf2dbg.c gas/frags.c gas/frags.h gas/read.c gas/read.h gas/testsuite/ChangeLog gas/testsuite/gas/arm/arm.exp gas/testsuite/gas/arm/undefined.l gas/testsuite/gas/arm/undefined.s gas/testsuite/gas/macros/test2.s gas/testsuite/gas/mips/div.d gas/testsuite/gas/mips/elf-rel-got-n32.d gas/testsuite/gas/mips/elf-rel-got-n64.d gas/testsuite/gas/mips/elf-rel-xgot-n32.d gas/testsuite/gas/mips/elf-rel-xgot-n64.d gas/testsuite/gas/mips/elf-rel19.d gas/testsuite/gas/mips/elf-rel19.s gas/testsuite/gas/mips/la-svr4pic.d gas/testsuite/gas/mips/la-xgot.d gas/testsuite/gas/mips/lca-svr4pic.d gas/testsuite/gas/mips/lca-xgot.d gas/testsuite/gas/mips/macro-warn-1-n32.d gas/testsuite/gas/mips/macro-warn-1-n32.l gas/testsuite/gas/mips/macro-warn-1.d gas/testsuite/gas/mips/macro-warn-1.l gas/testsuite/gas/mips/macro-warn-1.s gas/testsuite/gas/mips/macro-warn-2-n32.d gas/testsuite/gas/mips/macro-warn-2.d gas/testsuite/gas/mips/macro-warn-2.l gas/testsuite/gas/mips/macro-warn-2.s gas/testsuite/gas/mips/macro-warn-3.d gas/testsuite/gas/mips/macro-warn-3.l gas/testsuite/gas/mips/macro-warn-3.s gas/testsuite/gas/mips/macro-warn-4.d gas/testsuite/gas/mips/macro-warn-4.l gas/testsuite/gas/mips/macro-warn-4.s gas/testsuite/gas/mips/mips.exp gas/testsuite/gas/mips/relax-swap1-mips2.d gas/testsuite/gas/mips/relax-swap1.s gas/testsuite/gas/mips/relax-swap2.s gas/testsuite/gas/sh/basic.exp gas/testsuite/gas/sh/err-sh4a-fp.s gas/testsuite/gas/sh/sh4a-fp.d gas/testsuite/gas/sh/sh4a-fp.s gdb/ChangeLog gdb/Makefile.in gdb/NEWS gdb/PROBLEMS gdb/ada-lang.c gdb/alpha-tdep.c gdb/arch-utils.c gdb/arch-utils.h gdb/arm-tdep.c gdb/auxv.c gdb/auxv.h gdb/avr-tdep.c gdb/ax-gdb.c gdb/bcache.c gdb/blockframe.c gdb/breakpoint.c gdb/breakpoint.h gdb/buildsym.c gdb/c-lang.c gdb/cli/cli-cmds.c gdb/cli/cli-decode.c gdb/coffread.c gdb/config/mips/tm-linux.h gdb/config/nm-linux.h gdb/config/sparc/nm-nbsd.h gdb/config/sparc/obsd.mt gdb/config/sparc/obsd64.mt gdb/configure gdb/configure.host gdb/configure.in gdb/configure.tgt gdb/corelow.c gdb/cp-namespace.c gdb/cp-support.c gdb/cp-support.h gdb/cris-tdep.c gdb/d10v-tdep.c gdb/dbxread.c gdb/defs.h gdb/doc/ChangeLog gdb/doc/gdb.texinfo gdb/doc/gdbint.texinfo gdb/doc/stabs.texinfo gdb/dwarf2-frame.c gdb/dwarf2-frame.h gdb/dwarf2loc.c gdb/dwarf2loc.h gdb/dwarf2read.c gdb/dwarfread.c gdb/elfread.c gdb/f-lang.c gdb/findvar.c gdb/frame.c gdb/frame.h gdb/frv-tdep.c gdb/gdb-events.h gdb/gdb-events.sh gdb/gdb_curses.h gdb/gdb_obstack.h gdb/gdbarch.c gdb/gdbarch.h gdb/gdbarch.sh gdb/gdbserver/ChangeLog gdb/gdbserver/linux-low.c gdb/gdbserver/linux-low.h gdb/gdbserver/regcache.c gdb/gdbtypes.c gdb/gdbtypes.h gdb/h8300-tdep.c gdb/hppa-tdep.c gdb/hpread.c gdb/i386-linux-tdep.c gdb/i386-nto-tdep.c gdb/ia64-tdep.c gdb/infcmd.c gdb/infrun.c gdb/inftarg.c gdb/jv-lang.c gdb/language.c gdb/language.h gdb/linespec.c gdb/linux-proc.c gdb/m2-lang.c gdb/m32r-rom.c gdb/m32r-tdep.c gdb/m68hc11-tdep.c gdb/m68k-tdep.c gdb/m68klinux-tdep.c gdb/main.c gdb/mcore-tdep.c gdb/mdebugread.c gdb/mi/mi-cmd-stack.c gdb/mi/mi-cmd-var.c gdb/mi/mi-cmds.h gdb/minsyms.c gdb/mips-linux-nat.c gdb/mips-linux-tdep.c gdb/mips-tdep.c gdb/mn10300-tdep.c gdb/ns32k-tdep.c gdb/objc-lang.c gdb/objfiles.c gdb/objfiles.h gdb/osabi.c gdb/p-lang.c gdb/pa64solib.c gdb/printcmd.c gdb/proc-api.c gdb/procfs.c gdb/regcache.c gdb/remote-fileio.c gdb/remote-rdi.c gdb/remote-sim.c gdb/remote.c gdb/rs6000-tdep.c gdb/s390-tdep.c gdb/scm-lang.c gdb/ser-pipe.c gdb/sh-tdep.c gdb/sh64-tdep.c gdb/sol-thread.c gdb/solib-sunos.c gdb/somread.c gdb/somsolib.c gdb/source.c gdb/sparc-nat.c gdb/sparc-tdep.c gdb/sparc-tdep.h gdb/sparc64-tdep.h gdb/sparc64nbsd-tdep.c gdb/sparc64obsd-tdep.c gdb/sparcnbsd-tdep.c gdb/sparcobsd-tdep.c gdb/stabsread.c gdb/stack.c gdb/symfile.c gdb/symfile.h gdb/symmisc.c gdb/symtab.c gdb/symtab.h gdb/target.h gdb/testsuite/ChangeLog gdb/testsuite/config/sim.exp gdb/testsuite/gdb.arch/gdb1291.c gdb/testsuite/gdb.arch/gdb1431.c gdb/testsuite/gdb.asm/asm-source.exp gdb/testsuite/gdb.asm/ia64.inc gdb/testsuite/gdb.asm/openbsd.inc gdb/testsuite/gdb.base/Makefile.in gdb/testsuite/gdb.base/bang.exp gdb/testsuite/gdb.base/call-ar-st.exp gdb/testsuite/gdb.base/charset.c gdb/testsuite/gdb.base/chng-syms.c gdb/testsuite/gdb.base/chng-syms.exp gdb/testsuite/gdb.base/completion.exp gdb/testsuite/gdb.base/dump.c gdb/testsuite/gdb.base/dump.exp gdb/testsuite/gdb.base/fileio.c gdb/testsuite/gdb.base/finish.exp gdb/testsuite/gdb.base/gcore.exp gdb/testsuite/gdb.base/huge.c gdb/testsuite/gdb.base/huge.exp gdb/testsuite/gdb.base/info-proc.exp gdb/testsuite/gdb.base/langs.exp gdb/testsuite/gdb.base/maint.exp gdb/testsuite/gdb.base/pending.c gdb/testsuite/gdb.base/pending.exp gdb/testsuite/gdb.base/pendshr.c gdb/testsuite/gdb.base/return2.exp gdb/testsuite/gdb.base/shlib-call.exp gdb/testsuite/gdb.cp/ambiguous.exp gdb/testsuite/gdb.cp/annota2.exp gdb/testsuite/gdb.cp/annota3.exp gdb/testsuite/gdb.cp/anon-union.exp gdb/testsuite/gdb.cp/breakpoint.cc gdb/testsuite/gdb.cp/breakpoint.exp gdb/testsuite/gdb.cp/bs15503.cc gdb/testsuite/gdb.cp/casts.exp gdb/testsuite/gdb.cp/class2.cc gdb/testsuite/gdb.cp/classes.exp gdb/testsuite/gdb.cp/cplusfuncs.exp gdb/testsuite/gdb.cp/ctti.exp gdb/testsuite/gdb.cp/cttiadd.cc gdb/testsuite/gdb.cp/cttiadd1.cc gdb/testsuite/gdb.cp/cttiadd2.cc gdb/testsuite/gdb.cp/cttiadd3.cc gdb/testsuite/gdb.cp/demangle.exp gdb/testsuite/gdb.cp/derivation.exp gdb/testsuite/gdb.cp/exception.cc gdb/testsuite/gdb.cp/exception.exp gdb/testsuite/gdb.cp/hang.exp gdb/testsuite/gdb.cp/inherit.exp gdb/testsuite/gdb.cp/local.exp gdb/testsuite/gdb.cp/maint.exp gdb/testsuite/gdb.cp/member-ptr.cc gdb/testsuite/gdb.cp/member-ptr.exp gdb/testsuite/gdb.cp/method.exp gdb/testsuite/gdb.cp/misc.exp gdb/testsuite/gdb.cp/namespace.cc gdb/testsuite/gdb.cp/namespace.exp gdb/testsuite/gdb.cp/namespace1.cc gdb/testsuite/gdb.cp/overload.cc gdb/testsuite/gdb.cp/overload.exp gdb/testsuite/gdb.cp/ovldbreak.exp gdb/testsuite/gdb.cp/psmang.exp gdb/testsuite/gdb.cp/ref-types.exp gdb/testsuite/gdb.cp/rtti.exp gdb/testsuite/gdb.cp/rtti1.cc gdb/testsuite/gdb.cp/templates.exp gdb/testsuite/gdb.cp/userdef.exp gdb/testsuite/gdb.cp/virtfunc.exp gdb/testsuite/gdb.mi/mi-stack.exp gdb/testsuite/gdb.mi/mi-var-child.exp gdb/testsuite/gdb.objc/basicclass.exp gdb/testsuite/gdb.threads/gcore-thread.exp gdb/testsuite/gdb.threads/thread-specific.c gdb/testsuite/gdb.threads/thread-specific.exp gdb/testsuite/lib/compiler.c gdb/testsuite/lib/compiler.cc gdb/testsuite/lib/gdb.exp gdb/tui/tui-command.c gdb/tui/tui-data.c gdb/tui/tui-data.h gdb/tui/tui-disasm.c gdb/tui/tui-file.c gdb/tui/tui-hooks.c gdb/tui/tui-hooks.h gdb/tui/tui-interp.c gdb/tui/tui-io.c gdb/tui/tui-layout.c gdb/tui/tui-layout.h gdb/tui/tui-regs.c gdb/tui/tui-regs.h gdb/tui/tui-source.c gdb/tui/tui-source.h gdb/tui/tui-stack.c gdb/tui/tui-stack.h gdb/tui/tui-win.c gdb/tui/tui-win.h gdb/tui/tui-windata.c gdb/tui/tui-windata.h gdb/tui/tui-wingeneral.c gdb/tui/tui-wingeneral.h gdb/tui/tui-winsource.c gdb/tui/tui-winsource.h gdb/tui/tui.c gdb/tui/tui.h gdb/utils.c gdb/v850-tdep.c gdb/valops.c gdb/values.c gdb/vax-tdep.c gdb/version.in gdb/xcoffread.c gdb/xstormy16-tdep.c include/elf/ChangeLog include/elf/common.h include/opcode/ChangeLog include/opcode/h8300.h ld/ChangeLog ld/emulparams/armelf.sh ld/emulparams/armelf_linux.sh ld/emulparams/elf32bmip.sh ld/emulparams/elf32bmipn32.sh ld/emulparams/elf32btsmipn32.sh ld/emulparams/elf64_ia64.sh ld/emulparams/shlelf_linux.sh ld/emultempl/pe.em ld/genscripts.sh ld/testsuite/ChangeLog ld/testsuite/ld-arm/arm-app-abs32.d ld/testsuite/ld-arm/arm-app-abs32.r ld/testsuite/ld-arm/arm-app-abs32.s ld/testsuite/ld-arm/arm-elf.exp ld/testsuite/ld-h8300/h8300.exp ld/testsuite/ld-h8300/relax-5-coff.d ld/testsuite/ld-h8300/relax-5.d ld/testsuite/ld-h8300/relax-5.s libiberty/ChangeLog libiberty/Makefile.in libiberty/configure libiberty/configure.ac libiberty/getpwd.c libiberty/maint-tool opcodes/ChangeLog opcodes/m32r-dis.c opcodes/sh-opc.h readline/ChangeLog.gdb readline/bind.c readline/mbutil.c readline/readline.c readline/vi_mode.c sim/ChangeLog sim/configure sim/configure.in sim/m32r/ChangeLog sim/m32r/mloop2.in sim/m32r/mloopx.in sim/ppc/ChangeLog sim/ppc/ppc-instructions sim/sh/ChangeLog sim/sh/gencode.c sim/sh/interp.c sim/testsuite/ChangeLog sim/testsuite/lib/sim-defs.exp sim/testsuite/sim/mips/ChangeLog sim/testsuite/sim/mips/basic.exp sim/testsuite/sim/mips/sanity.s sim/testsuite/sim/mips/testutils.inc sim/testsuite/sim/sh/ChangeLog sim/testsuite/sim/sh/allinsn.exp sim/testsuite/sim/sh/and.s sim/testsuite/sim/sh/movi.s sim/testsuite/sim/sh/sett.s sim/testsuite/sim/sh/testutils.inc Delete: gdb/testsuite/gdb.mi/mi1-basics.exp gdb/testsuite/gdb.mi/mi1-break.exp gdb/testsuite/gdb.mi/mi1-console.exp gdb/testsuite/gdb.mi/mi1-disassemble.exp gdb/testsuite/gdb.mi/mi1-eval.exp gdb/testsuite/gdb.mi/mi1-hack-cli.exp gdb/testsuite/gdb.mi/mi1-pthreads.exp gdb/testsuite/gdb.mi/mi1-read-memory.exp gdb/testsuite/gdb.mi/mi1-regs.exp gdb/testsuite/gdb.mi/mi1-return.exp gdb/testsuite/gdb.mi/mi1-simplerun.exp gdb/testsuite/gdb.mi/mi1-stack.exp gdb/testsuite/gdb.mi/mi1-stepi.exp gdb/testsuite/gdb.mi/mi1-symbol.exp gdb/testsuite/gdb.mi/mi1-until.exp gdb/testsuite/gdb.mi/mi1-var-block.exp gdb/testsuite/gdb.mi/mi1-var-child.exp gdb/testsuite/gdb.mi/mi1-var-cmd.exp gdb/testsuite/gdb.mi/mi1-var-display.exp gdb/testsuite/gdb.mi/mi1-watch.exp
Diffstat (limited to 'gdb/dwarf2-frame.c')
-rw-r--r--gdb/dwarf2-frame.c182
1 files changed, 80 insertions, 102 deletions
diff --git a/gdb/dwarf2-frame.c b/gdb/dwarf2-frame.c
index 2c655d9..5a55976 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,24 +624,32 @@ 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)
{
- if (fs->retaddr_column < fs->regs.num_regs)
- cache->reg[regnum] = fs->regs.reg[fs->retaddr_column];
+ 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
+ assumes that the return address can be found in the
+ register corresponding to the return address column.
+ Incidentally, that's how should treat a return address
+ column specifying "same value" too. */
+ if (fs->retaddr_column < fs->regs.num_regs
+ && retaddr_reg->how != DWARF2_FRAME_REG_UNSPECIFIED
+ && retaddr_reg->how != DWARF2_FRAME_REG_SAME_VALUE)
+ cache->reg[regnum] = *retaddr_reg;
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;
+ cache->reg[regnum].how = DWARF2_FRAME_REG_SAVED_REG;
}
}
}
@@ -698,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;
@@ -719,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;
@@ -727,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,
@@ -748,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
@@ -765,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;
@@ -1233,7 +1211,7 @@ decode_frame_entry_1 (struct comp_unit *unit, char *start, int eh_frame_p)
return end;
cie = (struct dwarf2_cie *)
- obstack_alloc (&unit->objfile->psymbol_obstack,
+ obstack_alloc (&unit->objfile->objfile_obstack,
sizeof (struct dwarf2_cie));
cie->initial_instructions = NULL;
cie->cie_pointer = cie_pointer;
@@ -1349,7 +1327,7 @@ decode_frame_entry_1 (struct comp_unit *unit, char *start, int eh_frame_p)
return NULL;
fde = (struct dwarf2_fde *)
- obstack_alloc (&unit->objfile->psymbol_obstack,
+ obstack_alloc (&unit->objfile->objfile_obstack,
sizeof (struct dwarf2_fde));
fde->cie = find_cie (unit, cie_pointer);
if (fde->cie == NULL)