This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
[commit] Was: [rfc] unwind_dummy_id
- From: Andrew Cagney <ac131313 at redhat dot com>
- To: Andrew Cagney <ac131313 at redhat dot com>
- Cc: gdb-patches at sources dot redhat dot com
- Date: Wed, 05 Mar 2003 18:30:22 -0500
- Subject: [commit] Was: [rfc] unwind_dummy_id
- References: <3E5E7D36.9020106@redhat.com>
http://sources.redhat.com/ml/gdb/2003-02/msg00549.html
This patch adds such a mechanism. I'm going to table this until someone comes up with evidence that it actually fixes a bug :-)
I've found my evidence. The d10v's stack pointer and frame base sit at
oposite ends of a d10v frame. Consequently, when unwinding interleaved
frameless functions and dummy frames, the dummy-frame code can
mis-locate a dummy frame (one dummy's sp matches the other dummy's fp).
Using save_dummy_frame_tos() and unwind_dummy_id() ensures that each
dummy frame is identified by a single unique value.
> Anyway. Eli, does the doco look ok?
Yes, thanks.
I've commited the attached. It's been updated to work with current
sources. It also gained a few more comments and, when the new code, an
extra sanity check.
Andrew
2003-03-05 Andrew Cagney <cagney at redhat dot com>
* d10v-tdep.c (d10v_unwind_dummy_id): New function.
(d10v_gdbarch_init): Set unwind_dummy_id and save_dummy_frame_tos.
* frame.c (get_prev_frame): Restructure the frame ID unwind code
to use unwind_dummy_id when a dummy frame.
* gdbarch.sh (unwind_dummy_id): New multi-arch method with
predicate.
* gdbarch.h, gdbarch.c: Regneerate.
Index: doc/ChangeLog
2003-03-05 Andrew Cagney <cagney at redhat dot com>
* gdbint.texinfo (Target Architecture Definition): Document
unwind_dummy_id. Cross reference unwind_dummy_id and
SAVE_DUMMY_FRAME_TOS.
Index: d10v-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/d10v-tdep.c,v
retrieving revision 1.82
diff -u -r1.82 d10v-tdep.c
--- d10v-tdep.c 5 Mar 2003 22:54:22 -0000 1.82
+++ d10v-tdep.c 5 Mar 2003 23:12:22 -0000
@@ -1612,6 +1612,22 @@
return &d10v_frame_unwind;
}
+/* Assuming NEXT_FRAME->prev is a dummy, return the frame ID of that
+ dummy frame. The frame ID's base needs to match the TOS value
+ saved by save_dummy_frame_tos(), and the PC match the dummy frame's
+ breakpoint. */
+
+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 gdbarch_init_ftype d10v_gdbarch_init;
static struct gdbarch *
@@ -1748,6 +1764,10 @@
set_gdbarch_print_registers_info (gdbarch, d10v_print_registers_info);
frame_unwind_append_predicate (gdbarch, d10v_frame_p);
+
+ /* Methods for saving / extracting a dummy frame's ID. */
+ set_gdbarch_unwind_dummy_id (gdbarch, d10v_unwind_dummy_id);
+ set_gdbarch_save_dummy_frame_tos (gdbarch, generic_save_dummy_frame_tos);
return gdbarch;
}
Index: frame.c
===================================================================
RCS file: /cvs/src/src/gdb/frame.c,v
retrieving revision 1.73
diff -u -r1.73 frame.c
--- frame.c 5 Mar 2003 20:26:46 -0000 1.73
+++ frame.c 5 Mar 2003 23:12:22 -0000
@@ -1330,39 +1330,86 @@
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? */
- /* FIXME: cagney/2003-03-04: The below call isn't right. It should
- instead be doing something like "prev_frame -> unwind -> id
- (next_frame, & prev_frame -> unwind_cache, & prev_frame -> id)"
- but that requires more extensive (pending) changes. */
- next_frame->unwind->id (next_frame, &next_frame->unwind_cache,
- &prev_frame->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 (prev_frame->id))
+ /* Find the prev's frame's ID. */
+ switch (prev_frame->type)
{
- if (frame_debug)
- fprintf_unfiltered (gdb_stdlog,
- "Outermost frame - unwound frame ID invalid\n");
- return NULL;
+ case DUMMY_FRAME:
+ /* When unwinding a normal frame, the stack structure is
+ determined by analyzing the frame's function's code (be it
+ using brute force prologue analysis, or the dwarf2 CFI). In
+ the case of a dummy frame, that simply isn't possible. The
+ The PC is either the program entry point, or some random
+ address on the stack. Trying to use that PC to apply
+ standard frame ID unwind techniques 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 frame's ID. Things only work
+ if the two return the same value. */
+ 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 uses
+ frame_register_unwind to obtain the register values
+ needed to determine the dummy frame's ID. */
+ prev_frame->id = gdbarch_unwind_dummy_id (current_gdbarch,
+ next_frame);
+ }
+ else if (next_frame->level < 0)
+ {
+ /* We're unwinding a sentinel frame, the PC of which is
+ pointing at a stack dummy. Fake up the dummy frame's ID
+ using the same sequence as is found a traditional
+ unwinder. Once all architectures supply the
+ unwind_dummy_id method, this code can go away. */
+ prev_frame->id.base = read_fp ();
+ prev_frame->id.pc = read_pc ();
+ }
+ 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. Abandon the unwind process but
+ only after first warning the user. */
+ internal_warning (__FILE__, __LINE__,
+ "Missing unwind_dummy_id architecture method");
+ return NULL;
+ }
+ break;
+ case NORMAL_FRAME:
+ case SIGTRAMP_FRAME:
+ /* FIXME: cagney/2003-03-04: The below call isn't right. It
+ should instead be doing something like "prev_frame -> unwind
+ -> id (next_frame, & prev_frame -> unwind_cache, & prev_frame
+ -> id)" but that requires more extensive (pending) changes. */
+ next_frame->unwind->id (next_frame, &next_frame->unwind_cache,
+ &prev_frame->id);
+ /* Check that the unwound ID is valid. */
+ if (!frame_id_p (prev_frame->id))
+ {
+ 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 (prev_frame->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. */
+ 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 (prev_frame->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. */
/* FIXME: cagney/2002-12-18: Instead of this hack, should only store
the frame ID in PREV_FRAME. Unfortunatly, some architectures
Index: gdbarch.sh
===================================================================
RCS file: /cvs/src/src/gdb/gdbarch.sh,v
retrieving revision 1.199
diff -u -r1.199 gdbarch.sh
--- gdbarch.sh 3 Mar 2003 20:50:18 -0000 1.199
+++ gdbarch.sh 5 Mar 2003 23:12:23 -0000
@@ -602,6 +602,7 @@
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
Index: doc/gdbint.texinfo
===================================================================
RCS file: /cvs/src/src/gdb/doc/gdbint.texinfo,v
retrieving revision 1.126
diff -u -r1.126 gdbint.texinfo
--- doc/gdbint.texinfo 3 Mar 2003 23:28:55 -0000 1.126
+++ doc/gdbint.texinfo 5 Mar 2003 23:12:23 -0000
@@ -3697,10 +3697,11 @@
@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.
+ at 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
@@ -3883,6 +3884,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.
+
+ at item struct frame_id unwind_dummy_id (struct frame_info * at var{frame})
+ at findex unwind_dummy_id
+ at 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}.
+ at xref{SAVE_DUMMY_FRAME_TOS} dot
@item USE_STRUCT_CONVENTION (@var{gcc_p}, @var{type})
@findex USE_STRUCT_CONVENTION