diff options
author | Pedro Alves <palves@redhat.com> | 2011-03-18 18:52:32 +0000 |
---|---|---|
committer | Pedro Alves <palves@redhat.com> | 2011-03-18 18:52:32 +0000 |
commit | 8fbca658f0643a6c3d5b61840351ae70e5bf2db6 (patch) | |
tree | 29aac28e10802153b6d0a1575797c7fc1f4a6146 /gdb/i386-tdep.c | |
parent | 8661b11b1820e3cc09a19c9ac0b195d18f2f8638 (diff) | |
download | gdb-8fbca658f0643a6c3d5b61840351ae70e5bf2db6.zip gdb-8fbca658f0643a6c3d5b61840351ae70e5bf2db6.tar.gz gdb-8fbca658f0643a6c3d5b61840351ae70e5bf2db6.tar.bz2 |
gdb/
* frame.c (frame_unwind_register): Throw an error if unwinding the
register failed.
* get_prev_frame_1 (get_prev_frame_1): Ask the unwinder if there's
an unwind stop reason.
(frame_stop_reason_string): Handle UNWIND_UNAVAILABLE.
* frame.h (enum unwind_stop_reason) <UNWIND_OUTERMOST,
UNWIND_UNAVAILABLE>: New.
* inline-frame.c (inline_frame_unwind): Install
default_frame_unwind_stop_reason.
* frame-unwind.c: Include "exceptions.h".
(frame_unwind_find_by_frame): Swallow NOT_AVAILABLE_ERROR errors.
(default_frame_unwind_stop_reason): New.
* frame-unwind.h (frame_unwind_stop_reason_ftype): New typedef.
(default_frame_unwind_stop_reason): Declare.
(struct frame_unwind) <stop_reason>: New function pointer.
* dummy-frame.c: Install default_frame_unwind_stop_reason.
* dwarf2-frame.c: Include exceptions.h.
(struct dwarf2_frame_cache) <unavailable_retaddr>: New field.
(dwarf2_frame_cache): Swallow NOT_AVAILABLE_ERROR errors when
computing the CFA. If such an error was thrown, set
unavailable_retaddr.
(dwarf2_frame_unwind_stop_reason): New.
(dwarf2_frame_this_id): Don't build a frame id if the CFA was
unavailable.
(dwarf2_frame_unwind): Install dwarf2_frame_unwind_stop_reason.
(dwarf2_signal_frame_unwind): Ditto.
* amd64-tdep.c: Include "exceptions.h".
(struct amd64_frame_cache): New field "base_p".
(amd64_init_frame_cache): Clear it.
(amd64_frame_cache_1): New, factored out from amd64_frame_cache.
Avoid reading registers with functions that throw if the register
is not necessary to compute the frame base.
(amd64_frame_cache): Reimplement wrapping amd64_frame_cache_1, and
swallowing NOT_AVAILABLE_ERROR.
(amd64_frame_unwind_stop_reason): New.
(amd64_frame_this_id): Don't build a frame id if the frame base
was unavailable.
(amd64_frame_unwind): Install amd64_frame_unwind_stop_reason.
(amd64_sigtramp_frame_cache): Swallow NOT_AVAILABLE_ERROR, and set
base_p if the frame base was computable.
(amd64_sigtramp_frame_unwind_stop_reason): New.
(amd64_sigtramp_frame_this_id): Don't build a frame id if the
frame base was unavailable.
(amd64_sigtramp_frame_unwind): Install
amd64_sigtramp_frame_unwind_stop_reason.
(amd64_epilogue_frame_cache): Swallow NOT_AVAILABLE_ERROR, and set
base_p if the frame base was computable.
(amd64_epilogue_frame_unwind_stop_reason): New.
(amd64_epilogue_frame_this_id): Don't build a frame id if the
frame base was unavailable.
(amd64_epilogue_frame_unwind): Install
amd64_epilogue_frame_unwind_stop_reason.
* i386-tdep.c: Include "exceptions.h".
(struct i386_frame_cache): New field "base_p".
(i386_init_frame_cache): Clear it.
(i386_frame_cache_1): New, factored out from amd64_frame_cache.
Avoid reading registers with functions that throw if the register
is not necessary to compute the frame base.
(i386_frame_cache): Reimplement wrapping amd64_frame_cache_1, and
swallowing NOT_AVAILABLE_ERROR.
(i386_frame_unwind_stop_reason): New.
(i386_frame_this_id): Don't build a frame id if the frame base was
unavailable.
(i386_frame_prev_register): Handle unavailable SP.
(i386_frame_unwind): Install i386_frame_unwind_stop_reason.
(i386_epilogue_frame_cache): Swallow NOT_AVAILABLE_ERROR, and set
base_p if the frame base was computable.
(i386_epilogue_frame_unwind_stop_reason): New.
(i386_epilogue_frame_this_id): Don't build a frame id if the frame
base was unavailable.
(i386_epilogue_frame_unwind): Install
i386_epilogue_frame_unwind_stop_reason.
(i386_sigtramp_frame_cache): Swallow NOT_AVAILABLE_ERROR, and set
base_p if the frame base was computable.
(i386_sigtramp_frame_unwind_stop_reason): New.
(i386_sigtramp_frame_this_id): Don't build a frame id if the frame
base was unavailable.
(i386_sigtramp_frame_unwind): Install
i386_sigtramp_frame_unwind_stop_reason.
* sentinel-frame.c (sentinel_frame_prev_register): Use the value
type's size, not the register's.
(sentinel_frame_unwind): Install default_frame_unwind_stop_reason.
* alpha-mdebug-tdep.c (alpha_mdebug_frame_unwind): Install
default_frame_unwind_stop_reason.
* alpha-tdep.c (alpha_sigtramp_frame_unwind)
(alpha_heuristic_frame_unwind): Ditto.
* amd64obsd-tdep.c (amd64obsd_trapframe_unwind): Ditto.
* arm-tdep.c (arm_prologue_unwind, arm_stub_unwind): Ditto.
* avr-tdep.c (avr_frame_unwind): Ditto.
* cris-tdep.c (cris_sigtramp_frame_unwind, cris_frame_unwind):
Ditto.
* frv-linux-tdep.c (frv_linux_sigtramp_frame_unwind): Ditto.
* frv-tdep.c (frv_frame_unwind): Ditto.
* h8300-tdep.c (h8300_frame_unwind): Ditto.
* hppa-hpux-tdep.c (hppa_hpux_sigtramp_frame_unwind): Ditto.
* hppa-linux-tdep.c (hppa_linux_sigtramp_frame_unwind): Ditto.
* hppa-tdep.c (hppa_frame_unwind, hppa_fallback_frame_unwind)
(hppa_stub_frame_unwind): Ditto.
* i386obsd-tdep.c (i386obsd_trapframe_unwind): Ditto.
* ia64-tdep.c (ia64_frame_unwind, ia64_sigtramp_frame_unwind)
(ia64_libunwind_frame_unwind)
(ia64_libunwind_sigtramp_frame_unwind): Ditto.
* iq2000-tdep.c (iq2000_frame_unwind): Ditto.
* lm32-tdep.c (lm32_frame_unwind): Ditto.
* m32c-tdep.c (m32c_unwind): Ditto.
* m32r-linux-tdep.c (m32r_linux_sigtramp_frame_unwind): Ditto.
* m32r-tdep.c (m32r_frame_unwind): Ditto.
* m68hc11-tdep.c (m68hc11_frame_unwind): Ditto.
* m68k-tdep.c (m68k_frame_unwind): Ditto.
* m68klinux-tdep.c (m68k_linux_sigtramp_frame_unwind): Ditto.
* m88k-tdep.c (m88k_frame_unwind): Ditto.
* mep-tdep.c (mep_frame_unwind): Ditto.
* microblaze-tdep.c (microblaze_frame_unwind): Ditto.
* mips-tdep.c (mips_insn16_frame_unwind, mips_insn32_frame_unwind)
(mips_stub_frame_unwind): Ditto.
* mn10300-tdep.c (mn10300_frame_unwind): Ditto.
* moxie-tdep.c (moxie_frame_unwind): Ditto.
* mt-tdep.c (mt_frame_unwind): Ditto.
* ppc-linux-tdep.c (ppu2spu_unwind): Ditto.
* ppcobsd-tdep.c (ppcobsd_sigtramp_frame_unwind): Ditto.
* rs6000-tdep.c (rs6000_frame_unwind): Ditto.
* s390-tdep.c (s390_frame_unwind, s390_stub_frame_unwind)
(s390_sigtramp_frame_unwind): Ditto.
* score-tdep.c (score_prologue_unwind): Ditto.
* sh-tdep.c (sh_frame_unwind): Ditto.
* sh64-tdep.c (sh64_frame_unwind): Ditto.
* sparc-sol2-tdep.c (sparc32_sol2_sigtramp_frame_unwind): Ditto.
* sparc-tdep.c (sparc32_frame_unwind): Ditto.
* sparc64-sol2-tdep.c (sparc64_sol2_sigtramp_frame_unwind): Ditto.
* sparc64-tdep.c (sparc64_frame_unwind): Ditto.
* sparc64fbsd-tdep.c (sparc64fbsd_sigtramp_frame_unwind): Ditto.
* sparc64nbsd-tdep.c (sparc64nbsd_sigcontext_frame_unwind): Ditto.
* sparc64obsd-tdep.c (sparc64obsd_frame_unwind)
(sparc64obsd_trapframe_unwind): Ditto.
* sparcnbsd-tdep.c (sparc32nbsd_sigcontext_frame_unwind): Ditto.
* sparcobsd-tdep.c (sparc32obsd_sigtramp_frame_unwind): Ditto.
* spu-tdep.c (spu_frame_unwind, spu2ppu_unwind): Ditto.
* v850-tdep.c (v850_frame_unwind): Ditto.
* vax-tdep.c (vax_frame_unwind): Ditto.
* vaxobsd-tdep.c (vaxobsd_sigtramp_frame_unwind): Ditto.
* xstormy16-tdep.c (frame_unwind xstormy16_frame_unwind): Ditto.
* xtensa-tdep.c (xtensa_unwind): Ditto.
Diffstat (limited to 'gdb/i386-tdep.c')
-rw-r--r-- | gdb/i386-tdep.c | 193 |
1 files changed, 147 insertions, 46 deletions
diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c index 62df614..c7ad3a6 100644 --- a/gdb/i386-tdep.c +++ b/gdb/i386-tdep.c @@ -45,7 +45,7 @@ #include "dis-asm.h" #include "disasm.h" #include "remote.h" - +#include "exceptions.h" #include "gdb_assert.h" #include "gdb_string.h" @@ -804,6 +804,7 @@ struct i386_frame_cache { /* Base address. */ CORE_ADDR base; + int base_p; LONGEST sp_offset; CORE_ADDR pc; @@ -828,6 +829,7 @@ i386_alloc_frame_cache (void) cache = FRAME_OBSTACK_ZALLOC (struct i386_frame_cache); /* Base address. */ + cache->base_p = 0; cache->base = 0; cache->sp_offset = -4; cache->pc = 0; @@ -1608,20 +1610,16 @@ i386_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame) /* Normal frames. */ -static struct i386_frame_cache * -i386_frame_cache (struct frame_info *this_frame, void **this_cache) +static void +i386_frame_cache_1 (struct frame_info *this_frame, + struct i386_frame_cache *cache) { struct gdbarch *gdbarch = get_frame_arch (this_frame); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - struct i386_frame_cache *cache; gdb_byte buf[4]; int i; - if (*this_cache) - return *this_cache; - - cache = i386_alloc_frame_cache (); - *this_cache = cache; + cache->pc = get_frame_func (this_frame); /* In principle, for normal frames, %ebp holds the frame pointer, which holds the base address for the current stack frame. @@ -1635,23 +1633,15 @@ i386_frame_cache (struct frame_info *this_frame, void **this_cache) get_frame_register (this_frame, I386_EBP_REGNUM, buf); cache->base = extract_unsigned_integer (buf, 4, byte_order); if (cache->base == 0) - return cache; + return; /* For normal frames, %eip is stored at 4(%ebp). */ cache->saved_regs[I386_EIP_REGNUM] = 4; - cache->pc = get_frame_func (this_frame); if (cache->pc != 0) i386_analyze_prologue (gdbarch, cache->pc, get_frame_pc (this_frame), cache); - if (cache->saved_sp_reg != -1) - { - /* Saved stack pointer has been saved. */ - get_frame_register (this_frame, cache->saved_sp_reg, buf); - cache->saved_sp = extract_unsigned_integer (buf, 4, byte_order); - } - if (cache->locals < 0) { /* We didn't find a valid frame, which means that CACHE->base @@ -1664,6 +1654,10 @@ i386_frame_cache (struct frame_info *this_frame, void **this_cache) if (cache->saved_sp_reg != -1) { + /* Saved stack pointer has been saved. */ + get_frame_register (this_frame, cache->saved_sp_reg, buf); + cache->saved_sp = extract_unsigned_integer (buf, 4, byte_order); + /* We're halfway aligning the stack. */ cache->base = ((cache->saved_sp - 4) & 0xfffffff0) - 4; cache->saved_regs[I386_EIP_REGNUM] = cache->saved_sp - 4; @@ -1691,9 +1685,17 @@ i386_frame_cache (struct frame_info *this_frame, void **this_cache) cache->saved_regs[I386_EBP_REGNUM] = 0; } + if (cache->saved_sp_reg != -1) + { + /* Saved stack pointer has been saved (but the SAVED_SP_REG + register may be unavailable). */ + if (cache->saved_sp == 0 + && frame_register_read (this_frame, cache->saved_sp_reg, buf)) + cache->saved_sp = extract_unsigned_integer (buf, 4, byte_order); + } /* Now that we have the base address for the stack frame we can calculate the value of %esp in the calling frame. */ - if (cache->saved_sp == 0) + else if (cache->saved_sp == 0) cache->saved_sp = cache->base + 8; /* Adjust all the saved registers such that they contain addresses @@ -1702,6 +1704,28 @@ i386_frame_cache (struct frame_info *this_frame, void **this_cache) if (cache->saved_regs[i] != -1) cache->saved_regs[i] += cache->base; + cache->base_p = 1; +} + +static struct i386_frame_cache * +i386_frame_cache (struct frame_info *this_frame, void **this_cache) +{ + volatile struct gdb_exception ex; + struct i386_frame_cache *cache; + + if (*this_cache) + return *this_cache; + + cache = i386_alloc_frame_cache (); + *this_cache = cache; + + TRY_CATCH (ex, RETURN_MASK_ERROR) + { + i386_frame_cache_1 (this_frame, cache); + } + if (ex.reason < 0 && ex.error != NOT_AVAILABLE_ERROR) + throw_exception (ex); + return cache; } @@ -1719,6 +1743,22 @@ i386_frame_this_id (struct frame_info *this_frame, void **this_cache, (*this_id) = frame_id_build (cache->base + 8, cache->pc); } +static enum unwind_stop_reason +i386_frame_unwind_stop_reason (struct frame_info *this_frame, + void **this_cache) +{ + struct i386_frame_cache *cache = i386_frame_cache (this_frame, this_cache); + + if (!cache->base_p) + return UNWIND_UNAVAILABLE; + + /* This marks the outermost frame. */ + if (cache->base == 0) + return UNWIND_OUTERMOST; + + return UNWIND_NO_REASON; +} + static struct value * i386_frame_prev_register (struct frame_info *this_frame, void **this_cache, int regnum) @@ -1758,8 +1798,18 @@ i386_frame_prev_register (struct frame_info *this_frame, void **this_cache, if (regnum == I386_EIP_REGNUM && cache->pc_in_eax) return frame_unwind_got_register (this_frame, regnum, I386_EAX_REGNUM); - if (regnum == I386_ESP_REGNUM && cache->saved_sp) - return frame_unwind_got_constant (this_frame, regnum, cache->saved_sp); + if (regnum == I386_ESP_REGNUM) + { + /* If the SP has been saved, but we don't know where, then this + means that SAVED_SP_REG register was found unavailable back + when we built the cache. */ + if (cache->saved_sp == 0 && cache->saved_sp_reg != -1) + return frame_unwind_got_register (this_frame, regnum, + cache->saved_sp_reg); + else + return frame_unwind_got_constant (this_frame, regnum, + cache->saved_sp); + } if (regnum < I386_NUM_SAVED_REGS && cache->saved_regs[regnum] != -1) return frame_unwind_got_memory (this_frame, regnum, @@ -1771,6 +1821,7 @@ i386_frame_prev_register (struct frame_info *this_frame, void **this_cache, static const struct frame_unwind i386_frame_unwind = { NORMAL_FRAME, + i386_frame_unwind_stop_reason, i386_frame_this_id, i386_frame_prev_register, NULL, @@ -1814,6 +1865,7 @@ i386_epilogue_frame_cache (struct frame_info *this_frame, void **this_cache) { struct gdbarch *gdbarch = get_frame_arch (this_frame); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + volatile struct gdb_exception ex; struct i386_frame_cache *cache; gdb_byte buf[4]; @@ -1823,23 +1875,43 @@ i386_epilogue_frame_cache (struct frame_info *this_frame, void **this_cache) cache = i386_alloc_frame_cache (); *this_cache = cache; - /* Cache base will be %esp plus cache->sp_offset (-4). */ - get_frame_register (this_frame, I386_ESP_REGNUM, buf); - cache->base = extract_unsigned_integer (buf, 4, - byte_order) + cache->sp_offset; + TRY_CATCH (ex, RETURN_MASK_ERROR) + { + /* Cache base will be %esp plus cache->sp_offset (-4). */ + get_frame_register (this_frame, I386_ESP_REGNUM, buf); + cache->base = extract_unsigned_integer (buf, 4, + byte_order) + cache->sp_offset; - /* Cache pc will be the frame func. */ - cache->pc = get_frame_pc (this_frame); + /* Cache pc will be the frame func. */ + cache->pc = get_frame_pc (this_frame); - /* The saved %esp will be at cache->base plus 8. */ - cache->saved_sp = cache->base + 8; + /* The saved %esp will be at cache->base plus 8. */ + cache->saved_sp = cache->base + 8; - /* The saved %eip will be at cache->base plus 4. */ - cache->saved_regs[I386_EIP_REGNUM] = cache->base + 4; + /* The saved %eip will be at cache->base plus 4. */ + cache->saved_regs[I386_EIP_REGNUM] = cache->base + 4; + + cache->base_p = 1; + } + if (ex.reason < 0 && ex.error != NOT_AVAILABLE_ERROR) + throw_exception (ex); return cache; } +static enum unwind_stop_reason +i386_epilogue_frame_unwind_stop_reason (struct frame_info *this_frame, + void **this_cache) +{ + struct i386_frame_cache *cache + = i386_epilogue_frame_cache (this_frame, this_cache); + + if (!cache->base_p) + return UNWIND_UNAVAILABLE; + + return UNWIND_NO_REASON; +} + static void i386_epilogue_frame_this_id (struct frame_info *this_frame, void **this_cache, @@ -1848,12 +1920,16 @@ i386_epilogue_frame_this_id (struct frame_info *this_frame, struct i386_frame_cache *cache = i386_epilogue_frame_cache (this_frame, this_cache); + if (!cache->base_p) + return; + (*this_id) = frame_id_build (cache->base + 8, cache->pc); } static const struct frame_unwind i386_epilogue_frame_unwind = { NORMAL_FRAME, + i386_epilogue_frame_unwind_stop_reason, i386_epilogue_frame_this_id, i386_frame_prev_register, NULL, @@ -1869,6 +1945,7 @@ i386_sigtramp_frame_cache (struct frame_info *this_frame, void **this_cache) struct gdbarch *gdbarch = get_frame_arch (this_frame); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + volatile struct gdb_exception ex; struct i386_frame_cache *cache; CORE_ADDR addr; gdb_byte buf[4]; @@ -1878,30 +1955,50 @@ i386_sigtramp_frame_cache (struct frame_info *this_frame, void **this_cache) cache = i386_alloc_frame_cache (); - get_frame_register (this_frame, I386_ESP_REGNUM, buf); - cache->base = extract_unsigned_integer (buf, 4, byte_order) - 4; - - addr = tdep->sigcontext_addr (this_frame); - if (tdep->sc_reg_offset) + TRY_CATCH (ex, RETURN_MASK_ERROR) { - int i; + get_frame_register (this_frame, I386_ESP_REGNUM, buf); + cache->base = extract_unsigned_integer (buf, 4, byte_order) - 4; - gdb_assert (tdep->sc_num_regs <= I386_NUM_SAVED_REGS); + addr = tdep->sigcontext_addr (this_frame); + if (tdep->sc_reg_offset) + { + int i; - for (i = 0; i < tdep->sc_num_regs; i++) - if (tdep->sc_reg_offset[i] != -1) - cache->saved_regs[i] = addr + tdep->sc_reg_offset[i]; - } - else - { - cache->saved_regs[I386_EIP_REGNUM] = addr + tdep->sc_pc_offset; - cache->saved_regs[I386_ESP_REGNUM] = addr + tdep->sc_sp_offset; + gdb_assert (tdep->sc_num_regs <= I386_NUM_SAVED_REGS); + + for (i = 0; i < tdep->sc_num_regs; i++) + if (tdep->sc_reg_offset[i] != -1) + cache->saved_regs[i] = addr + tdep->sc_reg_offset[i]; + } + else + { + cache->saved_regs[I386_EIP_REGNUM] = addr + tdep->sc_pc_offset; + cache->saved_regs[I386_ESP_REGNUM] = addr + tdep->sc_sp_offset; + } + + cache->base_p = 1; } + if (ex.reason < 0 && ex.error != NOT_AVAILABLE_ERROR) + throw_exception (ex); *this_cache = cache; return cache; } +static enum unwind_stop_reason +i386_sigtramp_frame_unwind_stop_reason (struct frame_info *this_frame, + void **this_cache) +{ + struct i386_frame_cache *cache = + i386_sigtramp_frame_cache (this_frame, this_cache); + + if (!cache->base_p) + return UNWIND_UNAVAILABLE; + + return UNWIND_NO_REASON; +} + static void i386_sigtramp_frame_this_id (struct frame_info *this_frame, void **this_cache, struct frame_id *this_id) @@ -1909,6 +2006,9 @@ i386_sigtramp_frame_this_id (struct frame_info *this_frame, void **this_cache, struct i386_frame_cache *cache = i386_sigtramp_frame_cache (this_frame, this_cache); + if (!cache->base_p) + return; + /* See the end of i386_push_dummy_call. */ (*this_id) = frame_id_build (cache->base + 8, get_frame_pc (this_frame)); } @@ -1956,6 +2056,7 @@ i386_sigtramp_frame_sniffer (const struct frame_unwind *self, static const struct frame_unwind i386_sigtramp_frame_unwind = { SIGTRAMP_FRAME, + i386_sigtramp_frame_unwind_stop_reason, i386_sigtramp_frame_this_id, i386_sigtramp_frame_prev_register, NULL, |