From 6314f104748d0e970aa089d2ba544f81a491b565 Mon Sep 17 00:00:00 2001 From: Andrew Cagney Date: Wed, 5 Mar 2003 23:14:18 +0000 Subject: [PATCH] 2003-03-05 Andrew Cagney * 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 * gdbint.texinfo (Target Architecture Definition): Document unwind_dummy_id. Cross reference unwind_dummy_id and SAVE_DUMMY_FRAME_TOS. --- gdb/ChangeLog | 11 ++++- gdb/d10v-tdep.c | 20 ++++++++ gdb/doc/ChangeLog | 6 +++ gdb/doc/gdbint.texinfo | 17 +++++-- gdb/frame.c | 109 +++++++++++++++++++++++++++++------------ gdb/gdbarch.c | 37 ++++++++++++++ gdb/gdbarch.h | 6 +++ gdb/gdbarch.sh | 1 + 8 files changed, 171 insertions(+), 36 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index b369718748..f17fda082b 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,13 @@ +2003-03-05 Andrew Cagney + + * 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. + 2003-03-05 Andrew Cagney * d10v-tdep.c (struct d10v_unwind_cache): Add field "base". @@ -357,7 +367,6 @@ * f-lang.c (build_fortran_types): New function. (_initialize_f_language): Gdbarch-register built-in fortran types. - * doublest.c (extract_floating): Fix warning text. 2003-02-27 Andrew Cagney diff --git a/gdb/d10v-tdep.c b/gdb/d10v-tdep.c index fc05e806ed..5f334e6a7a 100644 --- a/gdb/d10v-tdep.c +++ b/gdb/d10v-tdep.c @@ -1612,6 +1612,22 @@ d10v_frame_p (CORE_ADDR pc) 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 * @@ -1749,6 +1765,10 @@ d10v_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) 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; } diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index dbdd1ba948..00935e2774 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,9 @@ +2003-03-05 Andrew Cagney + + * gdbint.texinfo (Target Architecture Definition): Document + unwind_dummy_id. Cross reference unwind_dummy_id and + SAVE_DUMMY_FRAME_TOS. + 2003-03-05 James Ingham Daniel Jacobowitz diff --git a/gdb/doc/gdbint.texinfo b/gdb/doc/gdbint.texinfo index 9776a3515b..7deabfc6d3 100644 --- a/gdb/doc/gdbint.texinfo +++ b/gdb/doc/gdbint.texinfo @@ -3697,10 +3697,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 @@ -3884,6 +3885,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 5d220c9f2b..bf860fe2cc 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -1330,39 +1330,86 @@ 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? */ - /* 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 diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c index 68247d6892..636349c7be 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", @@ -5031,6 +5042,32 @@ set_gdbarch_save_dummy_frame_tos (struct gdbarch *gdbarch, gdbarch->save_dummy_frame_tos = save_dummy_frame_tos; } +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) { diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h index 59dd3d60a0..b1cb72bd18 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 12953c286d..b367fda7b7 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 -- 2.34.1