#include "symfile.h"
#include "disasm.h"
#include "gdb_assert.h"
-
+#include "exceptions.h"
#include "amd64-tdep.h"
#include "i387-tdep.h"
return i386_pseudo_register_name (gdbarch, regnum);
}
-static void
+static enum register_status
amd64_pseudo_register_read (struct gdbarch *gdbarch,
struct regcache *regcache,
int regnum, gdb_byte *buf)
{
gdb_byte raw_buf[MAX_REGISTER_SIZE];
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ enum register_status status;
if (i386_byte_regnum_p (gdbarch, regnum))
{
if (gpnum >= AMD64_NUM_LOWER_BYTE_REGS)
{
/* Special handling for AH, BH, CH, DH. */
- regcache_raw_read (regcache,
- gpnum - AMD64_NUM_LOWER_BYTE_REGS, raw_buf);
- memcpy (buf, raw_buf + 1, 1);
+ status = regcache_raw_read (regcache,
+ gpnum - AMD64_NUM_LOWER_BYTE_REGS,
+ raw_buf);
+ if (status == REG_VALID)
+ memcpy (buf, raw_buf + 1, 1);
}
else
{
- regcache_raw_read (regcache, gpnum, raw_buf);
- memcpy (buf, raw_buf, 1);
+ status = regcache_raw_read (regcache, gpnum, raw_buf);
+ if (status == REG_VALID)
+ memcpy (buf, raw_buf, 1);
}
+
+ return status;
}
else if (i386_dword_regnum_p (gdbarch, regnum))
{
int gpnum = regnum - tdep->eax_regnum;
/* Extract (always little endian). */
- regcache_raw_read (regcache, gpnum, raw_buf);
- memcpy (buf, raw_buf, 4);
+ status = regcache_raw_read (regcache, gpnum, raw_buf);
+ if (status == REG_VALID)
+ memcpy (buf, raw_buf, 4);
+
+ return status;
}
else
- i386_pseudo_register_read (gdbarch, regcache, regnum, buf);
+ return i386_pseudo_register_read (gdbarch, regcache, regnum, buf);
}
static void
{
/* Base address. */
CORE_ADDR base;
+ int base_p;
CORE_ADDR sp_offset;
CORE_ADDR pc;
/* Base address. */
cache->base = 0;
+ cache->base_p = 0;
cache->sp_offset = -8;
cache->pc = 0;
/* Normal frames. */
-static struct amd64_frame_cache *
-amd64_frame_cache (struct frame_info *this_frame, void **this_cache)
+static void
+amd64_frame_cache_1 (struct frame_info *this_frame,
+ struct amd64_frame_cache *cache)
{
struct gdbarch *gdbarch = get_frame_arch (this_frame);
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- struct amd64_frame_cache *cache;
gdb_byte buf[8];
int i;
- if (*this_cache)
- return *this_cache;
-
- cache = amd64_alloc_frame_cache ();
- *this_cache = cache;
-
cache->pc = get_frame_func (this_frame);
if (cache->pc != 0)
amd64_analyze_prologue (gdbarch, cache->pc, get_frame_pc (this_frame),
cache);
- if (cache->saved_sp_reg != -1)
- {
- /* Stack pointer has been saved. */
- get_frame_register (this_frame, cache->saved_sp_reg, buf);
- cache->saved_sp = extract_unsigned_integer(buf, 8, byte_order);
- }
-
if (cache->frameless_p)
{
/* We didn't find a valid frame. If we're at the start of a
if (cache->saved_sp_reg != -1)
{
+ /* Stack pointer has been saved. */
+ get_frame_register (this_frame, cache->saved_sp_reg, buf);
+ cache->saved_sp = extract_unsigned_integer (buf, 8, byte_order);
+
/* We're halfway aligning the stack. */
cache->base = ((cache->saved_sp - 8) & 0xfffffffffffffff0LL) - 8;
cache->saved_regs[AMD64_RIP_REGNUM] = cache->saved_sp - 8;
if (cache->saved_regs[i] != -1)
cache->saved_regs[i] += cache->base;
+ cache->base_p = 1;
+}
+
+static struct amd64_frame_cache *
+amd64_frame_cache (struct frame_info *this_frame, void **this_cache)
+{
+ volatile struct gdb_exception ex;
+ struct amd64_frame_cache *cache;
+
+ if (*this_cache)
+ return *this_cache;
+
+ cache = amd64_alloc_frame_cache ();
+ *this_cache = cache;
+
+ TRY_CATCH (ex, RETURN_MASK_ERROR)
+ {
+ amd64_frame_cache_1 (this_frame, cache);
+ }
+ if (ex.reason < 0 && ex.error != NOT_AVAILABLE_ERROR)
+ throw_exception (ex);
+
return cache;
}
+static enum unwind_stop_reason
+amd64_frame_unwind_stop_reason (struct frame_info *this_frame,
+ void **this_cache)
+{
+ struct amd64_frame_cache *cache =
+ amd64_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 void
amd64_frame_this_id (struct frame_info *this_frame, void **this_cache,
struct frame_id *this_id)
struct amd64_frame_cache *cache =
amd64_frame_cache (this_frame, this_cache);
+ if (!cache->base_p)
+ return;
+
/* This marks the outermost frame. */
if (cache->base == 0)
return;
static const struct frame_unwind amd64_frame_unwind =
{
NORMAL_FRAME,
+ amd64_frame_unwind_stop_reason,
amd64_frame_this_id,
amd64_frame_prev_register,
NULL,
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 amd64_frame_cache *cache;
CORE_ADDR addr;
gdb_byte buf[8];
cache = amd64_alloc_frame_cache ();
- get_frame_register (this_frame, AMD64_RSP_REGNUM, buf);
- cache->base = extract_unsigned_integer (buf, 8, byte_order) - 8;
+ TRY_CATCH (ex, RETURN_MASK_ERROR)
+ {
+ get_frame_register (this_frame, AMD64_RSP_REGNUM, buf);
+ cache->base = extract_unsigned_integer (buf, 8, byte_order) - 8;
- addr = tdep->sigcontext_addr (this_frame);
- gdb_assert (tdep->sc_reg_offset);
- gdb_assert (tdep->sc_num_regs <= AMD64_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];
+ addr = tdep->sigcontext_addr (this_frame);
+ gdb_assert (tdep->sc_reg_offset);
+ gdb_assert (tdep->sc_num_regs <= AMD64_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];
+
+ 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
+amd64_sigtramp_frame_unwind_stop_reason (struct frame_info *this_frame,
+ void **this_cache)
+{
+ struct amd64_frame_cache *cache =
+ amd64_sigtramp_frame_cache (this_frame, this_cache);
+
+ if (!cache->base_p)
+ return UNWIND_UNAVAILABLE;
+
+ return UNWIND_NO_REASON;
+}
+
static void
amd64_sigtramp_frame_this_id (struct frame_info *this_frame,
void **this_cache, struct frame_id *this_id)
struct amd64_frame_cache *cache =
amd64_sigtramp_frame_cache (this_frame, this_cache);
+ if (!cache->base_p)
+ return;
+
(*this_id) = frame_id_build (cache->base + 16, get_frame_pc (this_frame));
}
static const struct frame_unwind amd64_sigtramp_frame_unwind =
{
SIGTRAMP_FRAME,
+ amd64_sigtramp_frame_unwind_stop_reason,
amd64_sigtramp_frame_this_id,
amd64_sigtramp_frame_prev_register,
NULL,
amd64_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
{
gdb_byte insn;
+ struct symtab *symtab;
+
+ symtab = find_pc_symtab (pc);
+ if (symtab && symtab->epilogue_unwind_valid)
+ return 0;
if (target_read_memory (pc, &insn, 1))
return 0; /* Can't read memory at pc. */
{
struct gdbarch *gdbarch = get_frame_arch (this_frame);
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ volatile struct gdb_exception ex;
struct amd64_frame_cache *cache;
gdb_byte buf[8];
cache = amd64_alloc_frame_cache ();
*this_cache = cache;
- /* Cache base will be %esp plus cache->sp_offset (-8). */
- get_frame_register (this_frame, AMD64_RSP_REGNUM, buf);
- cache->base = extract_unsigned_integer (buf, 8,
- byte_order) + cache->sp_offset;
+ TRY_CATCH (ex, RETURN_MASK_ERROR)
+ {
+ /* Cache base will be %esp plus cache->sp_offset (-8). */
+ get_frame_register (this_frame, AMD64_RSP_REGNUM, buf);
+ cache->base = extract_unsigned_integer (buf, 8,
+ 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 16. */
- cache->saved_sp = cache->base + 16;
+ /* The saved %esp will be at cache->base plus 16. */
+ cache->saved_sp = cache->base + 16;
- /* The saved %eip will be at cache->base plus 8. */
- cache->saved_regs[AMD64_RIP_REGNUM] = cache->base + 8;
+ /* The saved %eip will be at cache->base plus 8. */
+ cache->saved_regs[AMD64_RIP_REGNUM] = cache->base + 8;
+
+ cache->base_p = 1;
+ }
+ if (ex.reason < 0 && ex.error != NOT_AVAILABLE_ERROR)
+ throw_exception (ex);
return cache;
}
+static enum unwind_stop_reason
+amd64_epilogue_frame_unwind_stop_reason (struct frame_info *this_frame,
+ void **this_cache)
+{
+ struct amd64_frame_cache *cache
+ = amd64_epilogue_frame_cache (this_frame, this_cache);
+
+ if (!cache->base_p)
+ return UNWIND_UNAVAILABLE;
+
+ return UNWIND_NO_REASON;
+}
+
static void
amd64_epilogue_frame_this_id (struct frame_info *this_frame,
void **this_cache,
struct amd64_frame_cache *cache = amd64_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 amd64_epilogue_frame_unwind =
{
NORMAL_FRAME,
+ amd64_epilogue_frame_unwind_stop_reason,
amd64_epilogue_frame_this_id,
amd64_frame_prev_register,
NULL,
}
}
-/* Similar to amd64_collect_fxsave, but but use XSAVE extended state. */
+/* Similar to amd64_collect_fxsave, but use XSAVE extended state. */
void
amd64_collect_xsave (const struct regcache *regcache, int regnum,