aboutsummaryrefslogtreecommitdiff
path: root/gdb/i386-tdep.c
diff options
context:
space:
mode:
authorPedro Alves <palves@redhat.com>2011-03-18 18:52:32 +0000
committerPedro Alves <palves@redhat.com>2011-03-18 18:52:32 +0000
commit8fbca658f0643a6c3d5b61840351ae70e5bf2db6 (patch)
tree29aac28e10802153b6d0a1575797c7fc1f4a6146 /gdb/i386-tdep.c
parent8661b11b1820e3cc09a19c9ac0b195d18f2f8638 (diff)
downloadgdb-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.c193
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,