summaryrefslogtreecommitdiff
path: root/gdb/d10v-tdep.c
diff options
context:
space:
mode:
authorAndrew Cagney <cagney@redhat.com>2003-03-17 14:23:50 +0000
committerAndrew Cagney <cagney@redhat.com>2003-03-17 14:23:50 +0000
commit1557b85d755f3373e232f6c3acb643b1e2992eec (patch)
tree8d9eed64edb31e13673dcd85f70217211d83aa49 /gdb/d10v-tdep.c
parent6edb7b34e7416add0d4142498db767ddc9ea19c7 (diff)
downloadgdb-1557b85d755f3373e232f6c3acb643b1e2992eec.tar.gz
2003-03-17 Andrew Cagney <cagney@redhat.com>cagney_lazyid-20030317-branchpoint
Fix frame off-by-one bug. * frame-unwind.h (frame_this_id_ftype): Replace frame_unwind_id_ftype. (frame_prev_register_ftype): Replace frame_unwind_reg_ftype. (struct frame_unwind): Replace "id" with "this_id". Replace "reg" with "prev_register". * frame-unwind.c (frame_unwind_find_by_pc): Return legacy_saved_regs_unwind instead of trad_frame_unwind. Update comment. * dummy-frame.c (cached_find_dummy_frame): Delete function. (dummy_frame_this_id): Replace dummy_frame_id_unwind. (dummy_frame_prev_register): Replace dummy_frame_register_unwind. (dummy_frame_unwind): Update. * sentinel-frame.c (sentinel_frame_prev_register): Replace sentinel_frame_register_unwind. (sentinel_frame_this_id): Replace sentinel_frame_id_unwind. (sentinel_frame_unwinder): Update. * frame.h (legacy_saved_regs_unwind): Replace trad_frame_unwind. (struct frame_info): Rename "unwind_cache" to "prologue_cache". * frame.c (create_sentinel_frame): Update. Initialize "prologue_cache" instead of "unwind_cache". (frame_register_unwind): Call this frame's prev_register with the next frame and this frame's prologue cache. (get_prev_frame): Simplify. Always call prev frame's this_id with this frame and prev frame's prologue cache. Document that this call is shifted one to the left when compared to the frame_register_unwind call. (legacy_saved_regs_prev_register): Replace frame_saved_regs_register_unwind. (legacy_saved_regs_this_id): Replace frame_saved_regs_id_unwind. (legacy_saved_regs_unwinder): Replace trad_frame_unwinder. (legacy_saved_regs_unwind): Replace trad_frame_unwind. * d10v-tdep.c (d10v_frame_this_id): Replace d10v_frame_id_unwind. (d10v_frame_unwind): Update. (d10v_frame_prev_register): Replace d10v_frame_register_unwind. (d10v_frame_unwind_cache): Replace this "fi" with "next_frame". (saved_regs_unwinder): Replace this "frame" with "next_frame", and "saved_regs" with "this_saved_regs".
Diffstat (limited to 'gdb/d10v-tdep.c')
-rw-r--r--gdb/d10v-tdep.c120
1 files changed, 59 insertions, 61 deletions
diff --git a/gdb/d10v-tdep.c b/gdb/d10v-tdep.c
index b60ce7fad3a..f443ceff8dd 100644
--- a/gdb/d10v-tdep.c
+++ b/gdb/d10v-tdep.c
@@ -705,8 +705,8 @@ prologue_find_regs (struct d10v_unwind_cache *info, unsigned short op,
for it IS the sp for the next frame. */
struct d10v_unwind_cache *
-d10v_frame_unwind_cache (struct frame_info *fi,
- void **cache)
+d10v_frame_unwind_cache (struct frame_info *next_frame,
+ void **this_prologue_cache)
{
CORE_ADDR pc;
ULONGEST prev_sp;
@@ -716,18 +716,18 @@ d10v_frame_unwind_cache (struct frame_info *fi,
int i;
struct d10v_unwind_cache *info;
- if ((*cache))
- return (*cache);
+ if ((*this_prologue_cache))
+ return (*this_prologue_cache);
info = FRAME_OBSTACK_ZALLOC (struct d10v_unwind_cache);
- (*cache) = info;
+ (*this_prologue_cache) = info;
info->saved_regs = frame_obstack_zalloc (SIZEOF_FRAME_SAVED_REGS);
info->size = 0;
info->return_pc = 0;
info->sp_offset = 0;
- pc = get_pc_function_start (get_frame_pc (fi));
+ pc = get_pc_function_start (frame_pc_unwind (next_frame));
info->uses_frame = 0;
while (1)
@@ -788,7 +788,7 @@ d10v_frame_unwind_cache (struct frame_info *fi,
/* The SP was moved to the FP. This indicates that a new frame
was created. Get THIS frame's FP value by unwinding it from
the next frame. */
- frame_read_unsigned_register (fi, FP_REGNUM, &this_base);
+ frame_unwind_unsigned_register (next_frame, FP_REGNUM, &this_base);
/* The FP points at the last saved register. Adjust the FP back
to before the first saved register giving the SP. */
prev_sp = this_base + info->size;
@@ -806,7 +806,7 @@ d10v_frame_unwind_cache (struct frame_info *fi,
{
/* Assume that the FP is this frame's SP but with that pushed
stack space added back. */
- frame_read_unsigned_register (fi, SP_REGNUM, &this_base);
+ frame_unwind_unsigned_register (next_frame, SP_REGNUM, &this_base);
prev_sp = this_base + info->size;
}
@@ -831,7 +831,7 @@ d10v_frame_unwind_cache (struct frame_info *fi,
else
{
ULONGEST return_pc;
- frame_read_unsigned_register (fi, LR_REGNUM, &return_pc);
+ frame_unwind_unsigned_register (next_frame, LR_REGNUM, &return_pc);
info->return_pc = d10v_make_iaddr (return_pc);
}
@@ -1457,58 +1457,55 @@ d10v_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
frame. This will be used to create a new GDB frame struct. */
static void
-d10v_frame_id_unwind (struct frame_info *frame,
- void **cache,
- struct frame_id *id)
+d10v_frame_this_id (struct frame_info *next_frame,
+ void **this_prologue_cache,
+ struct frame_id *this_id)
{
- struct d10v_unwind_cache *info = d10v_frame_unwind_cache (frame, cache);
- CORE_ADDR addr;
+ struct d10v_unwind_cache *info
+ = d10v_frame_unwind_cache (next_frame, this_prologue_cache);
+ CORE_ADDR base;
+ CORE_ADDR pc;
/* Start with a NULL frame ID. */
- (*id) = null_frame_id;
+ (*this_id) = null_frame_id;
- if (info->return_pc == IMEM_START
- || info->return_pc <= IMEM_START
- || inside_entry_file (info->return_pc))
- {
- /* This is meant to halt the backtrace at "_start".
- Make sure we don't halt it at a generic dummy frame. */
- return;
- }
+ /* The PC is easy. */
+ pc = frame_pc_unwind (next_frame);
- if (!info->saved_regs[FP_REGNUM])
- {
- if (!info->saved_regs[SP_REGNUM]
- || info->saved_regs[SP_REGNUM] == STACK_START)
- return;
+ /* This is meant to halt the backtrace at "_start". Make sure we
+ don't halt it at a generic dummy frame. */
+ if (pc == IMEM_START || pc <= IMEM_START || inside_entry_file (pc))
+ return;
- id->base = info->saved_regs[SP_REGNUM];
- id->pc = info->return_pc;
- }
+ /* Hopefully the prologue analysis either correctly determined the
+ frame's base (which is the SP from the previous frame), or set
+ that base to "NULL". */
+ base = info->base;
+ if (base == STACK_START || base == 0)
+ return;
- addr = read_memory_unsigned_integer (info->saved_regs[FP_REGNUM],
- register_size (current_gdbarch, FP_REGNUM));
- if (addr == 0)
+ /* Check that we're not going round in circles with the same frame
+ ID (but avoid applying the test to sentinel frames which do go
+ round in circles). Can't use frame_id_eq() as that doesn't yet
+ compare the frame's PC value. */
+ if (frame_relative_level (next_frame) >= 0
+ && get_frame_type (next_frame) != DUMMY_FRAME
+ && get_frame_id (next_frame).pc == pc
+ && get_frame_id (next_frame).base == base)
return;
- id->base = d10v_make_daddr (addr);
- id->pc = info->return_pc;
+ this_id->base = base;
+ this_id->pc = pc;
}
static void
-saved_regs_unwinder (struct frame_info *frame,
- CORE_ADDR *saved_regs,
+saved_regs_unwinder (struct frame_info *next_frame,
+ CORE_ADDR *this_saved_regs,
int regnum, int *optimizedp,
enum lval_type *lvalp, CORE_ADDR *addrp,
int *realnump, void *bufferp)
{
- /* If we're using generic dummy frames, we'd better not be in a call
- dummy. (generic_call_dummy_register_unwind ought to have been called
- instead.) */
- gdb_assert (!(DEPRECATED_USE_GENERIC_DUMMY_FRAMES
- && (get_frame_type (frame) == DUMMY_FRAME)));
-
- if (saved_regs[regnum] != 0)
+ if (this_saved_regs[regnum] != 0)
{
if (regnum == SP_REGNUM)
{
@@ -1519,7 +1516,7 @@ saved_regs_unwinder (struct frame_info *frame,
*realnump = -1;
if (bufferp != NULL)
store_address (bufferp, register_size (current_gdbarch, regnum),
- saved_regs[regnum]);
+ this_saved_regs[regnum]);
}
else
{
@@ -1527,12 +1524,12 @@ saved_regs_unwinder (struct frame_info *frame,
a local copy of its value. */
*optimizedp = 0;
*lvalp = lval_memory;
- *addrp = saved_regs[regnum];
+ *addrp = this_saved_regs[regnum];
*realnump = -1;
if (bufferp != NULL)
{
/* Read the value in from memory. */
- read_memory (saved_regs[regnum], bufferp,
+ read_memory (this_saved_regs[regnum], bufferp,
register_size (current_gdbarch, regnum));
}
}
@@ -1543,38 +1540,39 @@ saved_regs_unwinder (struct frame_info *frame,
value. If a value is needed, pass the request on down the chain;
otherwise just return an indication that the value is in the same
register as the next frame. */
- frame_register (frame, regnum, optimizedp, lvalp, addrp,
- realnump, bufferp);
+ frame_register_unwind (next_frame, regnum, optimizedp, lvalp, addrp,
+ realnump, bufferp);
}
static void
-d10v_frame_register_unwind (struct frame_info *frame,
- void **cache,
- int regnum, int *optimizedp,
- enum lval_type *lvalp, CORE_ADDR *addrp,
- int *realnump, void *bufferp)
-{
- struct d10v_unwind_cache *info = d10v_frame_unwind_cache (frame, cache);
+d10v_frame_prev_register (struct frame_info *next_frame,
+ void **this_prologue_cache,
+ int regnum, int *optimizedp,
+ enum lval_type *lvalp, CORE_ADDR *addrp,
+ int *realnump, void *bufferp)
+{
+ struct d10v_unwind_cache *info
+ = d10v_frame_unwind_cache (next_frame, this_prologue_cache);
if (regnum == PC_REGNUM)
{
/* The call instruction saves the caller's PC in LR. The
function prologue of the callee may then save the LR on the
stack. Find that possibly saved LR value and return it. */
- saved_regs_unwinder (frame, info->saved_regs, LR_REGNUM, optimizedp,
+ saved_regs_unwinder (next_frame, info->saved_regs, LR_REGNUM, optimizedp,
lvalp, addrp, realnump, bufferp);
}
else
{
- saved_regs_unwinder (frame, info->saved_regs, regnum, optimizedp,
+ saved_regs_unwinder (next_frame, info->saved_regs, regnum, optimizedp,
lvalp, addrp, realnump, bufferp);
}
}
static struct frame_unwind d10v_frame_unwind = {
- d10v_frame_id_unwind,
- d10v_frame_register_unwind
+ d10v_frame_this_id,
+ d10v_frame_prev_register
};
const struct frame_unwind *