aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Cagney <cagney@redhat.com>2003-03-05 05:00:04 +0000
committerAndrew Cagney <cagney@redhat.com>2003-03-05 05:00:04 +0000
commitfdd93b8b10a297196af99279086ddc214f3d9bb6 (patch)
tree3fc2944b974ec1b30ea675176c158f67b0a8821e
parentfc34faedba1aacec97bca094627e9c322049e68d (diff)
downloadfsf-binutils-gdb-fdd93b8b10a297196af99279086ddc214f3d9bb6.zip
fsf-binutils-gdb-fdd93b8b10a297196af99279086ddc214f3d9bb6.tar.gz
fsf-binutils-gdb-fdd93b8b10a297196af99279086ddc214f3d9bb6.tar.bz2
2003-03-04 Andrew Cagney <cagney@redhat.com>
* d10v-tdep.c (struct d10v_unwind_cache): Add field "r11_addr", change type of "next_addr" to LONGEST. Delete member "frameless". (prologue_find_regs): Parse "st rn, @r11", save r11's offset. (d10v_frame_unwind_cache): Compute both the frame base and the previous stack pointer. Store the previous SP's value in the saved_regs array. (d10v_frame_id_unwind): Remove commented out code. Check for circular stack. (saved_regs_unwinder): When SP_REGNUM, extract the value from the saved_regs array. (d10v_unwind_dummy_id): New function. (d10v_gdbarch_init): Initialize d10v_unwind_dummy_id and save_dummy_frame_tos. (struct frame_extra_info): Delete. (saved_regs_unwind): New function. (d10v_frame_pop): Update to match current code. (d10v_frame_register_unwind): Don't unwind LR_REGNUM. Unwind the PC_REGNUM by returning the saved LR_REGNUM. * frame.c (get_prev_frame): Store this frame's ID in the next frame's unwound ID cache. (deprecated_update_frame_pc_hack): Update the cached value in NEXT as well. 2003-02-27 Andrew Cagney <cagney@redhat.com> * frame.c (get_prev_frame): Rewrite the frame ID unwind code to use unwind_dummy_id when available. * gdbarch.sh (get_dummy_frame_id): New multi-arch method with predicate. * gdbarch.h, gdbarch.c: Regneerate.
-rw-r--r--gdb/ChangeLog32
-rw-r--r--gdb/d10v-tdep.c222
-rw-r--r--gdb/doc/ChangeLog7
-rw-r--r--gdb/doc/gdbint.texinfo17
-rw-r--r--gdb/frame.c109
-rw-r--r--gdb/gdbarch.c37
-rw-r--r--gdb/gdbarch.h6
-rwxr-xr-xgdb/gdbarch.sh1
8 files changed, 314 insertions, 117 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 32b7990..8ac3ae9 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,37 @@
2003-03-04 Andrew Cagney <cagney@redhat.com>
+ * d10v-tdep.c (struct d10v_unwind_cache): Add field "r11_addr",
+ change type of "next_addr" to LONGEST. Delete member "frameless".
+ (prologue_find_regs): Parse "st rn, @r11", save r11's offset.
+ (d10v_frame_unwind_cache): Compute both the frame base and the
+ previous stack pointer. Store the previous SP's value in the
+ saved_regs array.
+ (d10v_frame_id_unwind): Remove commented out code. Check for
+ circular stack.
+ (saved_regs_unwinder): When SP_REGNUM, extract the value from the
+ saved_regs array.
+ (d10v_unwind_dummy_id): New function.
+ (d10v_gdbarch_init): Initialize d10v_unwind_dummy_id and
+ save_dummy_frame_tos.
+ (struct frame_extra_info): Delete.
+ (saved_regs_unwind): New function.
+ (d10v_frame_pop): Update to match current code.
+ (d10v_frame_register_unwind): Don't unwind LR_REGNUM. Unwind the
+ PC_REGNUM by returning the saved LR_REGNUM.
+ * frame.c (get_prev_frame): Store this frame's ID in the next
+ frame's unwound ID cache.
+ (deprecated_update_frame_pc_hack): Update the cached value in NEXT
+ as well.
+
+ 2003-02-27 Andrew Cagney <cagney@redhat.com>
+ * frame.c (get_prev_frame): Rewrite the frame ID unwind code to
+ use unwind_dummy_id when available.
+ * gdbarch.sh (get_dummy_frame_id): New multi-arch method with
+ predicate.
+ * gdbarch.h, gdbarch.c: Regneerate.
+
+2003-03-04 Andrew Cagney <cagney@redhat.com>
+
* d10v-tdep.c (d10v_frame_unwind_cache): Update to work with
NEXT_FRAME and THIS_CACHE.
(d10v_frame_pc_unwind): Ditto.
diff --git a/gdb/d10v-tdep.c b/gdb/d10v-tdep.c
index 9111aa3..5cbdddc 100644
--- a/gdb/d10v-tdep.c
+++ b/gdb/d10v-tdep.c
@@ -45,20 +45,9 @@
#include "gdb_assert.h"
-static void d10v_frame_register_unwind (struct frame_info *next_frame,
- void **this_cache,
- int prev_regnum, int *optimizedp,
- enum lval_type *lvalp,
- CORE_ADDR *addrp,
- int *realnump, void *bufferp);
-
-
-struct frame_extra_info
- {
- CORE_ADDR return_pc;
- int frameless;
- int size;
- };
+static void saved_regs_unwind (struct frame_info *next_frame,
+ CORE_ADDR *saved_regs, int prev_regnum,
+ void *bufferp);
struct gdbarch_tdep
{
@@ -625,10 +614,10 @@ d10v_skip_prologue (CORE_ADDR pc)
struct d10v_unwind_cache
{
CORE_ADDR base;
- int frameless;
int size;
CORE_ADDR *saved_regs;
- CORE_ADDR next_addr;
+ LONGEST next_addr;
+ LONGEST r11_addr;
int uses_frame;
void **regs;
};
@@ -672,6 +661,15 @@ prologue_find_regs (struct d10v_unwind_cache *info, unsigned short op,
if (op == 0x417E)
{
info->uses_frame = 1;
+ info->r11_addr = info->next_addr;
+ return 1;
+ }
+
+ /* st rn, @r11 */
+ if ((op & 0x7E1F) == 0x6816)
+ {
+ n = (op & 0x1E0) >> 5;
+ info->saved_regs[n] = info->r11_addr;
return 1;
}
@@ -724,7 +722,6 @@ d10v_frame_unwind_cache (struct frame_info *next_frame,
(*this_cache) = info;
info->saved_regs = frame_obstack_zalloc (SIZEOF_FRAME_SAVED_REGS);
- info->frameless = 0;
info->size = 0;
info->next_addr = 0;
@@ -784,40 +781,51 @@ d10v_frame_unwind_cache (struct frame_info *next_frame,
info->size = -info->next_addr;
- /* Start out with the frame's stack top. */
- frame_unwind_unsigned_register (next_frame, SP_REGNUM, &sp);
- sp = d10v_make_daddr (sp);
-
- for (i = 0; i < NUM_REGS - 1; i++)
- if (info->saved_regs[i])
- {
- info->saved_regs[i] = sp - (info->next_addr - info->saved_regs[i]);
- }
-
/* Compute the frame's base. */
- if (info->saved_regs[FP_REGNUM])
+ if (info->uses_frame)
{
- /* The FP was saved, which means that the current FP is live.
- Unwind its value from the NEXT frame. */
+ /* The SP was moved into the FP. This indicates that a new
+ frame was created. Get THIS frame's FP value by unwinding it
+ from the next frame. */
frame_unwind_unsigned_register (next_frame, FP_REGNUM, &base);
+ /* The FP points at the last saved register. Adjust the FP back
+ to before the first saved register giving the SP. */
+ sp = base + info->size;
}
else if (info->saved_regs[SP_REGNUM])
{
- /* The SP was saved (this is very unusual), the frame base is
+ /* The SP was saved (which is very unusual), the frame base is
just the PREV's frame's TOP-OF-STACK. */
base = read_memory_unsigned_integer (info->saved_regs[SP_REGNUM],
register_size (current_gdbarch,
SP_REGNUM));
- info->frameless = 1;
+ sp = base;
}
else
{
/* Assume that the FP is this frame's SP but with that pushed
stack space added back. */
frame_unwind_unsigned_register (next_frame, SP_REGNUM, &base);
- base += info->size;
+ sp = base + info->size;
}
+
info->base = d10v_make_daddr (base);
+ sp = d10v_make_daddr (sp);
+
+ /* Adjust all the saved registers so that they contain addresses and
+ not offsets. */
+ for (i = 0; i < NUM_REGS - 1; i++)
+ {
+ if (info->saved_regs[i])
+ {
+ info->saved_regs[i] = (sp + info->saved_regs[i]);
+ }
+ }
+
+ /* The SP_REGNUM is special. Instead of the address of the SP, the
+ previous frame's SP value is saved. */
+ info->saved_regs[SP_REGNUM] = sp;
+
return info;
}
@@ -1429,17 +1437,13 @@ static CORE_ADDR
d10v_frame_pc_unwind (struct frame_info *next_frame,
void **this_cache)
{
- /* FIXME: This shouldn't be needed. Instead a per-architecture
- method should be called. */
- int optimized;
- enum lval_type lval;
- CORE_ADDR addr;
- int realnum;
- ULONGEST lr;
+ /* FIXME: This shouldn't be needed. Instead single per-architecture
+ method should be called for all frames. */
+ CORE_ADDR lr;
+ struct d10v_unwind_cache *info
+ = d10v_frame_unwind_cache (next_frame, this_cache);
void *buffer = alloca (max_register_size (current_gdbarch));
- d10v_frame_register_unwind (next_frame, this_cache, LR_REGNUM,
- &optimized, &lval, &addr, &realnum,
- buffer);
+ saved_regs_unwind (next_frame, info->saved_regs, LR_REGNUM, buffer);
lr = extract_unsigned_integer (buffer, register_size (current_gdbarch,
LR_REGNUM));
return d10v_make_iaddr (lr);
@@ -1472,26 +1476,24 @@ d10v_frame_id_unwind (struct frame_info *next_frame,
return;
}
-#if 0
- if (!info->saved_regs[FP_REGNUM])
- {
- if (!info->saved_regs[SP_REGNUM]
- || info->saved_regs[SP_REGNUM] == STACK_START)
- return;
-
- this_id->base = info->saved_regs[SP_REGNUM];
- this_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 on the same frame ID.
+ Be careful to avoid applying the test to sentinel frames (which
+ do go round in circles). Can't use ID_EQ as that doesn't yet
+ compare PC values. */
+ 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;
-#endif
- /* Hopefully the prolog analysis has correctly determined the
- frame's base. */
- this_id->base = info->base;
+ this_id->base = base;
this_id->pc = pc;
}
@@ -1504,15 +1506,30 @@ saved_regs_unwinder (struct frame_info *next_frame,
{
if (saved_regs[prev_regnum] != 0)
{
- *optimizedp = 0;
- *lvalp = lval_memory;
- *addrp = saved_regs[prev_regnum];
- *realnump = -1;
- if (bufferp != NULL)
+ if (prev_regnum == SP_REGNUM)
+ {
+ /* SP register treated specially. */
+ *optimizedp = 0;
+ *lvalp = not_lval;
+ *addrp = 0;
+ *realnump = -1;
+ if (bufferp != NULL)
+ store_address (bufferp,
+ register_size (current_gdbarch, SP_REGNUM),
+ saved_regs[SP_REGNUM]);
+ }
+ else
{
- /* Read the value in from memory. */
- read_memory (saved_regs[prev_regnum], bufferp,
- register_size (current_gdbarch, prev_regnum));
+ *optimizedp = 0;
+ *lvalp = lval_memory;
+ *addrp = saved_regs[prev_regnum];
+ *realnump = -1;
+ if (bufferp != NULL)
+ {
+ /* Read the value in from memory. */
+ read_memory (saved_regs[prev_regnum], bufferp,
+ register_size (current_gdbarch, prev_regnum));
+ }
}
return;
}
@@ -1525,6 +1542,20 @@ saved_regs_unwinder (struct frame_info *next_frame,
realnump, bufferp);
}
+/* Wrapper so that local code can unwind register values. */
+
+static void
+saved_regs_unwind (struct frame_info *next_frame, CORE_ADDR *saved_regs,
+ int prev_regnum, void *bufferp)
+{
+ int optimized;
+ enum lval_type lval;
+ CORE_ADDR addr;
+ int realnum;
+ saved_regs_unwinder (next_frame, saved_regs, prev_regnum,
+ &optimized, &lval, &addr, &realnum, bufferp);
+}
+
static void
d10v_frame_register_unwind (struct frame_info *next_frame,
@@ -1535,44 +1566,67 @@ d10v_frame_register_unwind (struct frame_info *next_frame,
{
struct d10v_unwind_cache *info
= d10v_frame_unwind_cache (next_frame, this_cache);
- if (prev_regnum == PC_REGNUM)
- prev_regnum = LR_REGNUM;
- saved_regs_unwinder (next_frame, info->saved_regs, prev_regnum, optimizedp,
- lvalp, addrp, realnump, bufferp);
+ if (prev_regnum == LR_REGNUM)
+ /* Unwinding the LR isn't possible. It's value is trashed by the
+ call instruction. Mark the value as optimized away. */
+ {
+ *optimizedp = 1;
+ *lvalp = lval_register;
+ *addrp = 0;
+ *realnump = LR_REGNUM;
+ if (bufferp != NULL)
+ memset (bufferp, 0, register_size (current_gdbarch, LR_REGNUM));
+ }
+ else if (prev_regnum == PC_REGNUM)
+ /* The caller's PC is saved in LR_REGNUM. Find/return the
+ LR_REGNUM. */
+ saved_regs_unwinder (next_frame, info->saved_regs, LR_REGNUM, optimizedp,
+ lvalp, addrp, realnump, bufferp);
+ else
+ saved_regs_unwinder (next_frame, info->saved_regs, prev_regnum, optimizedp,
+ lvalp, addrp, realnump, bufferp);
}
+static struct frame_id
+d10v_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame)
+{
+ ULONGEST base;
+ struct frame_id id;
+ id.pc = frame_pc_unwind (next_frame);
+ frame_unwind_unsigned_register (next_frame, SP_REGNUM, &base);
+ id.base = d10v_make_daddr (base);
+ return id;
+}
+
static void
-d10v_frame_pop (struct frame_info *fi, void **unwind_cache,
+d10v_frame_pop (struct frame_info *next_frame, void **this_cache,
struct regcache *regcache)
{
- struct d10v_unwind_cache *info = d10v_frame_unwind_cache (fi, unwind_cache);
+ struct d10v_unwind_cache *info
+ = d10v_frame_unwind_cache (next_frame, this_cache);
CORE_ADDR fp;
int regnum;
char raw_buffer[8];
- fp = get_frame_base (fi);
-
/* now update the current registers with the old values */
for (regnum = A0_REGNUM; regnum < A0_REGNUM + NR_A_REGS; regnum++)
{
- frame_unwind_register (fi, regnum, raw_buffer);
+ saved_regs_unwind (next_frame, info->saved_regs, regnum, raw_buffer);
regcache_cooked_write (regcache, regnum, raw_buffer);
}
for (regnum = 0; regnum < SP_REGNUM; regnum++)
{
- frame_unwind_register (fi, regnum, raw_buffer);
+ saved_regs_unwind (next_frame, info->saved_regs, regnum, raw_buffer);
regcache_cooked_write (regcache, regnum, raw_buffer);
}
- frame_unwind_register (fi, PSW_REGNUM, raw_buffer);
+ saved_regs_unwind (next_frame, info->saved_regs, PSW_REGNUM, raw_buffer);
regcache_cooked_write (regcache, PSW_REGNUM, raw_buffer);
- frame_unwind_register (fi, LR_REGNUM, raw_buffer);
+ saved_regs_unwind (next_frame, info->saved_regs, LR_REGNUM, raw_buffer);
regcache_cooked_write (regcache, PC_REGNUM, raw_buffer);
- store_unsigned_integer (raw_buffer,
- register_size (current_gdbarch, SP_REGNUM),
- fp + info->size);
+ saved_regs_unwind (next_frame, info->saved_regs, SP_REGNUM, raw_buffer);
regcache_cooked_write (regcache, SP_REGNUM, raw_buffer);
target_store_registers (-1);
@@ -1728,6 +1782,8 @@ d10v_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_print_registers_info (gdbarch, d10v_print_registers_info);
frame_unwind_append_predicate (gdbarch, d10v_frame_p);
+ set_gdbarch_unwind_dummy_id (gdbarch, d10v_unwind_dummy_id);
+ set_gdbarch_save_dummy_frame_tos (gdbarch, generic_save_dummy_frame_tos);
return gdbarch;
}
diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog
index 013e8ca..c1f5206 100644
--- a/gdb/doc/ChangeLog
+++ b/gdb/doc/ChangeLog
@@ -1,3 +1,10 @@
+2003-03-04 Andrew Cagney <cagney@redhat.com>
+
+ 2003-02-27 Andrew Cagney <cagney@redhat.com>
+ * gdbint.texinfo (Target Architecture Definition): Document
+ unwind_dummy_id. Cross reference unwind_dummy_id and
+ SAVE_DUMMY_FRAME_TOS.
+
2003-03-02 Daniel Jacobowitz <drow@mvista.com>
* Makefile.in (distclean): Remove config.log.
diff --git a/gdb/doc/gdbint.texinfo b/gdb/doc/gdbint.texinfo
index 35acd14..eba00ca 100644
--- a/gdb/doc/gdbint.texinfo
+++ b/gdb/doc/gdbint.texinfo
@@ -3691,10 +3691,11 @@ rather than directly.
@item SAVE_DUMMY_FRAME_TOS (@var{sp})
@findex SAVE_DUMMY_FRAME_TOS
-Used in @samp{call_function_by_hand} to notify the target dependent code
-of the top-of-stack value that will be passed to the the inferior code.
-This is the value of the @code{SP} after both the dummy frame and space
-for parameters/results have been allocated on the stack.
+@anchor{SAVE_DUMMY_FRAME_TOS} Used in @samp{call_function_by_hand} to
+notify the target dependent code of the top-of-stack value that will be
+passed to the the inferior code. This is the value of the @code{SP}
+after both the dummy frame and space for parameters/results have been
+allocated on the stack. @xref{unwind_dummy_id}.
@item SDB_REG_TO_REGNUM
@findex SDB_REG_TO_REGNUM
@@ -3878,6 +3879,14 @@ Libraries, ,Opcodes}). @var{info} is a structure (of type
@code{disassemble_info}) defined in @file{include/dis-asm.h} used to
pass information to the instruction decoding routine.
+@item struct frame_id unwind_dummy_id (struct frame_info *@var{frame})
+@findex unwind_dummy_id
+@anchor{unwind_dummy_id} Given @var{frame} return a @code{struct
+frame_id} that uniquely identifies an inferior function call's dummy
+frame. The value returned must match the dummy frame stack value
+previously saved using @code{SAVE_DUMMY_FRAME_TOS}.
+@xref{SAVE_DUMMY_FRAME_TOS}.
+
@item USE_STRUCT_CONVENTION (@var{gcc_p}, @var{type})
@findex USE_STRUCT_CONVENTION
If defined, this must be an expression that is nonzero if a value of the
diff --git a/gdb/frame.c b/gdb/frame.c
index d70ac96..dd3cd68 100644
--- a/gdb/frame.c
+++ b/gdb/frame.c
@@ -1345,39 +1345,83 @@ get_prev_frame (struct frame_info *next_frame)
prev_frame->unwind = frame_unwind_find_by_pc (current_gdbarch,
prev_frame->pc);
- /* FIXME: cagney/2003-01-13: A dummy frame doesn't need to unwind
- the frame ID because the frame ID comes from the previous frame.
- The other frames do though. True? */
+ /* Find the prev's frame's ID. */
{
- /* FIXME: cagney/2002-12-18: Instead of this hack, should just
- save the frame ID directly. */
- struct frame_id id;
- prev_frame->unwind->id (next_frame, &prev_frame->unwind_cache, &id);
- /* Check that the unwound ID is valid. As of 2003-02-24 the
- x86-64 was returning an invalid frame ID when trying to do an
- unwind a sentinel frame that belonged to a frame dummy. */
- if (!frame_id_p (id))
+ switch (prev_frame->type)
{
- if (frame_debug)
- fprintf_unfiltered (gdb_stdlog,
- "Outermost frame - unwound frame ID invalid\n");
- return NULL;
+ case DUMMY_FRAME:
+ /* A dummy doesn't have anything resembling either a sane
+ frame or PC. The PC is sitting in the entry code and the
+ stack, which has nothing to do with that entry address, is
+ a down right mess. Trying to use the standard frame ID
+ unwind code to get the previous frame ID is just asking for
+ trouble. */
+ if (gdbarch_unwind_dummy_id_p (current_gdbarch))
+ {
+ /* Assume hand_function_call(), via SAVE_DUMMY_FRAME_TOS,
+ previously saved the dummy ID that is being obtained
+ here. Things only work if the two match. */
+ gdb_assert (SAVE_DUMMY_FRAME_TOS_P ());
+ /* Use an architecture specific method to extract the
+ prev's dummy ID from the next frame. Note that this
+ method typically uses frame_register_unwind to obtain
+ register values needed to determine the dummy ID. */
+ next_frame->id_unwind_cache =
+ gdbarch_unwind_dummy_id (current_gdbarch, next_frame);
+ }
+ else if (next_frame->level == 0)
+ {
+ /* We're `unwinding' the sentinel frame. Just fake up the
+ ID the same way that the traditional hacks did it. */
+ next_frame->id_unwind_cache.pc = read_pc ();
+ next_frame->id_unwind_cache.pc = read_fp ();
+ }
+ else
+ {
+ /* Outch! We're not on the innermost frame yet we're
+ trying to unwind to a dummy. The architecture must
+ provide the unwind_dummy_id() method. */
+ internal_error (__FILE__, __LINE__,
+ "Missing unwind_dummy_id architecture method");
+ }
+ break;
+ case NORMAL_FRAME:
+ case SIGTRAMP_FRAME:
+ prev_frame->unwind->id (next_frame, &prev_frame->unwind_cache,
+ &next_frame->id_unwind_cache);
+ /* Check that the unwound ID is valid. */
+ if (!frame_id_p (next_frame->id_unwind_cache))
+ {
+ if (frame_debug)
+ fprintf_unfiltered (gdb_stdlog,
+ "Outermost frame - unwound frame ID invalid\n");
+ return NULL;
+ }
+ /* Check that the new frame isn't inner to (younger, below,
+ next) the old frame. If that happens the frame unwind is
+ going backwards. */
+ /* FIXME: cagney/2003-02-25: Ignore the sentinel frame since
+ that doesn't have a valid frame ID. Should instead set the
+ sentinel frame's frame ID to a `sentinel'. Leave it until
+ after the switch to storing the frame ID, instead of the
+ frame base, in the frame object. */
+ if (next_frame->level >= 0
+ && frame_id_inner (next_frame->id_unwind_cache,
+ get_frame_id (next_frame)))
+ error ("Unwound frame inner-to selected frame (corrupt stack?)");
+ /* Note that, due to frameless functions, the stronger test of
+ the new frame being outer to the old frame can't be used -
+ frameless functions differ by only their PC value. */
+ break;
+ default:
+ internal_error (__FILE__, __LINE__, "bad switch");
}
- /* Check that the new frame isn't inner to (younger, below, next)
- the old frame. If that happens the frame unwind is going
- backwards. */
- /* FIXME: cagney/2003-02-25: Ignore the sentinel frame since that
- doesn't have a valid frame ID. Should instead set the sentinel
- frame's frame ID to a `sentinel'. Leave it until after the
- switch to storing the frame ID, instead of the frame base, in
- the frame object. */
- if (next_frame->level >= 0
- && frame_id_inner (id, get_frame_id (next_frame)))
- error ("Unwound frame inner-to selected frame (corrupt stack?)");
- /* Note that, due to frameless functions, the stronger test of the
- new frame being outer to the old frame can't be used -
- frameless functions differ by only their PC value. */
- prev_frame->frame = id.base;
+ /* FIXME: cagney/2002-12-18: Instead of this hack, the frame ID
+ should be directly stored in the `struct frame_info'.
+ Unfortunatly, GDB isn't quite ready for this, need to get HP/UX
+ multi-arch and make 'struct frame_info' opaque. */
+ next_frame->id_unwind_cache_p = 1;
+ prev_frame->frame = next_frame->id_unwind_cache.base;
}
/* Link it in. */
@@ -1514,7 +1558,12 @@ deprecated_update_frame_pc_hack (struct frame_info *frame, CORE_ADDR pc)
{
/* See comment in "frame.h". */
gdb_assert (frame->next != NULL);
+ /* Fix up this PC's value. */
frame->pc = pc;
+ /* While we're at it, also update the cache, in NEXT, that also
+ contains that value. */
+ frame->next->pc_unwind_cache = pc;
+ frame->next->pc_unwind_cache_p = 1;
}
void
diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c
index 68247d6..636349c 100644
--- a/gdb/gdbarch.c
+++ b/gdb/gdbarch.c
@@ -251,6 +251,7 @@ struct gdbarch
int extra_stack_alignment_needed;
gdbarch_reg_struct_has_addr_ftype *reg_struct_has_addr;
gdbarch_save_dummy_frame_tos_ftype *save_dummy_frame_tos;
+ gdbarch_unwind_dummy_id_ftype *unwind_dummy_id;
int parm_boundary;
const struct floatformat * float_format;
const struct floatformat * double_format;
@@ -431,6 +432,7 @@ struct gdbarch startup_gdbarch =
0,
0,
0,
+ 0,
generic_in_function_epilogue_p,
construct_inferior_arguments,
0,
@@ -770,6 +772,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
/* Skip verify of extra_stack_alignment_needed, invalid_p == 0 */
/* Skip verify of reg_struct_has_addr, has predicate */
/* Skip verify of save_dummy_frame_tos, has predicate */
+ /* Skip verify of unwind_dummy_id, has predicate */
if (gdbarch->float_format == 0)
gdbarch->float_format = default_float_format (gdbarch);
if (gdbarch->double_format == 0)
@@ -2567,6 +2570,14 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
(long) current_gdbarch->write_sp
/*TARGET_WRITE_SP ()*/);
#endif
+ if (GDB_MULTI_ARCH)
+ fprintf_unfiltered (file,
+ "gdbarch_dump: gdbarch_unwind_dummy_id_p() = %d\n",
+ gdbarch_unwind_dummy_id_p (current_gdbarch));
+ if (GDB_MULTI_ARCH)
+ fprintf_unfiltered (file,
+ "gdbarch_dump: unwind_dummy_id = 0x%08lx\n",
+ (long) current_gdbarch->unwind_dummy_id);
#ifdef USE_STRUCT_CONVENTION
fprintf_unfiltered (file,
"gdbarch_dump: %s # %s\n",
@@ -5032,6 +5043,32 @@ set_gdbarch_save_dummy_frame_tos (struct gdbarch *gdbarch,
}
int
+gdbarch_unwind_dummy_id_p (struct gdbarch *gdbarch)
+{
+ gdb_assert (gdbarch != NULL);
+ return gdbarch->unwind_dummy_id != 0;
+}
+
+struct frame_id
+gdbarch_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *info)
+{
+ gdb_assert (gdbarch != NULL);
+ if (gdbarch->unwind_dummy_id == 0)
+ internal_error (__FILE__, __LINE__,
+ "gdbarch: gdbarch_unwind_dummy_id invalid");
+ if (gdbarch_debug >= 2)
+ fprintf_unfiltered (gdb_stdlog, "gdbarch_unwind_dummy_id called\n");
+ return gdbarch->unwind_dummy_id (gdbarch, info);
+}
+
+void
+set_gdbarch_unwind_dummy_id (struct gdbarch *gdbarch,
+ gdbarch_unwind_dummy_id_ftype unwind_dummy_id)
+{
+ gdbarch->unwind_dummy_id = unwind_dummy_id;
+}
+
+int
gdbarch_parm_boundary (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
index 59dd3d6..b1cb72b 100644
--- a/gdb/gdbarch.h
+++ b/gdb/gdbarch.h
@@ -2458,6 +2458,12 @@ extern void set_gdbarch_save_dummy_frame_tos (struct gdbarch *gdbarch, gdbarch_s
#endif
#endif
+extern int gdbarch_unwind_dummy_id_p (struct gdbarch *gdbarch);
+
+typedef struct frame_id (gdbarch_unwind_dummy_id_ftype) (struct gdbarch *gdbarch, struct frame_info *info);
+extern struct frame_id gdbarch_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *info);
+extern void set_gdbarch_unwind_dummy_id (struct gdbarch *gdbarch, gdbarch_unwind_dummy_id_ftype *unwind_dummy_id);
+
extern int gdbarch_parm_boundary (struct gdbarch *gdbarch);
extern void set_gdbarch_parm_boundary (struct gdbarch *gdbarch, int parm_boundary);
#if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) && defined (PARM_BOUNDARY)
diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh
index 12953c2..b367fda 100755
--- a/gdb/gdbarch.sh
+++ b/gdb/gdbarch.sh
@@ -602,6 +602,7 @@ M:::CORE_ADDR:frame_align:CORE_ADDR address:address
v:2:EXTRA_STACK_ALIGNMENT_NEEDED:int:extra_stack_alignment_needed::::0:1::0:::
F:2:REG_STRUCT_HAS_ADDR:int:reg_struct_has_addr:int gcc_p, struct type *type:gcc_p, type::0:0
F:2:SAVE_DUMMY_FRAME_TOS:void:save_dummy_frame_tos:CORE_ADDR sp:sp::0:0
+M::UNWIND_DUMMY_ID:struct frame_id:unwind_dummy_id:struct frame_info *info:info::0:0
v:2:PARM_BOUNDARY:int:parm_boundary
#
v:2:TARGET_FLOAT_FORMAT:const struct floatformat *:float_format::::::default_float_format (gdbarch)::%s:(TARGET_FLOAT_FORMAT)->name