diff options
author | nobody <> | 2004-02-14 00:00:34 +0000 |
---|---|---|
committer | nobody <> | 2004-02-14 00:00:34 +0000 |
commit | 2f344a4dcd2a8c4297702027a943e3587e6b60c8 (patch) | |
tree | 8614f4d9fc669ec37a90e4b4f70b31f00c489661 /gdb/dwarf2-frame.c | |
parent | a5dd37ab655106440e987830db5111b43f271ecc (diff) | |
download | binutils-cagney_bfdfile-20040213-branch.zip binutils-cagney_bfdfile-20040213-branch.tar.gz binutils-cagney_bfdfile-20040213-branch.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.c | 182 |
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, ®); 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, ®); 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, ®); 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) |