From 12cc2063bed3b79f2a3e92342e92dc6211a3bf12 Mon Sep 17 00:00:00 2001 From: Andrew Cagney Date: Mon, 10 Mar 2003 15:28:41 +0000 Subject: [PATCH] 2003-03-10 Andrew Cagney * gdbarch.sh (gdbarch_unwind_pc): New method. * gdbarch.h, gdbarch.c: Regenerate. * frame.c (frame_pc_unwind): Rewrite. Prefer gdbarch_unwind_pc, but use read_pc and FRAME_SAVED_PC as fall backs. (frame_saved_regs_pc_unwind): Delete function. (trad_frame_unwinder): Update. * frame-unwind.h (frame_unwind_pc_ftype): Delete declaration. (struct frame_unwind): Update. * dummy-frame.c (dummy_frame_pc_unwind): Delete function. (dummy_frame_unwind): Update. * sentinel-frame.c (sentinel_frame_pc_unwind): Delete function. (sentinel_frame_unwinder): Update. * d10v-tdep.c (d10v_frame_pc_unwind): Delete function. (d10v_frame_unwind): Update. (d10v_unwind_pc): New function. (d10v_gdbarch_init): Set unwind_pc. Index: doc/ChangeLog 2003-03-10 Andrew Cagney * gdbint.texinfo (Target Architecture Definition): Cross reference FRAME_SAVED_PC to unwind_pc. Document unwind_pc. --- gdb/ChangeLog | 19 ++++++++++++++ gdb/d10v-tdep.c | 13 +++++----- gdb/doc/ChangeLog | 5 ++++ gdb/doc/gdbint.texinfo | 24 +++++++++++++++-- gdb/dummy-frame.c | 18 ------------- gdb/frame-unwind.h | 7 ----- gdb/frame.c | 58 ++++++++++++++++++++++++++++++++---------- gdb/gdbarch.c | 37 +++++++++++++++++++++++++++ gdb/gdbarch.h | 8 ++++++ gdb/gdbarch.sh | 2 ++ gdb/sentinel-frame.c | 12 --------- 11 files changed, 145 insertions(+), 58 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index a50510366b..4a4a5f43e5 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,22 @@ +2003-03-10 Andrew Cagney + + * gdbarch.sh (gdbarch_unwind_pc): New method. + * gdbarch.h, gdbarch.c: Regenerate. + * frame.c (frame_pc_unwind): Rewrite. Prefer gdbarch_unwind_pc, + but use read_pc and FRAME_SAVED_PC as fall backs. + (frame_saved_regs_pc_unwind): Delete function. + (trad_frame_unwinder): Update. + * frame-unwind.h (frame_unwind_pc_ftype): Delete declaration. + (struct frame_unwind): Update. + * dummy-frame.c (dummy_frame_pc_unwind): Delete function. + (dummy_frame_unwind): Update. + * sentinel-frame.c (sentinel_frame_pc_unwind): Delete function. + (sentinel_frame_unwinder): Update. + * d10v-tdep.c (d10v_frame_pc_unwind): Delete function. + (d10v_frame_unwind): Update. + (d10v_unwind_pc): New function. + (d10v_gdbarch_init): Set unwind_pc. + 2003-03-10 Andrew Cagney * gdbarch.h: Re-generate. diff --git a/gdb/d10v-tdep.c b/gdb/d10v-tdep.c index b50cfa75a8..516cde468a 100644 --- a/gdb/d10v-tdep.c +++ b/gdb/d10v-tdep.c @@ -1445,13 +1445,12 @@ display_trace (int low, int high) } } - static CORE_ADDR -d10v_frame_pc_unwind (struct frame_info *frame, - void **cache) +d10v_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame) { - struct d10v_unwind_cache *info = d10v_frame_unwind_cache (frame, cache); - return info->return_pc; + ULONGEST pc; + frame_unwind_unsigned_register (next_frame, PC_REGNUM, &pc); + return d10v_make_iaddr (pc); } /* Given a GDB frame, determine the address of the calling function's @@ -1612,7 +1611,6 @@ d10v_frame_pop (struct frame_info *fi, void **unwind_cache, static struct frame_unwind d10v_frame_unwind = { d10v_frame_pop, - d10v_frame_pc_unwind, d10v_frame_id_unwind, d10v_frame_register_unwind }; @@ -1780,6 +1778,9 @@ d10v_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_unwind_dummy_id (gdbarch, d10v_unwind_dummy_id); set_gdbarch_save_dummy_frame_tos (gdbarch, generic_save_dummy_frame_tos); + /* Return the unwound PC value. */ + set_gdbarch_unwind_pc (gdbarch, d10v_unwind_pc); + return gdbarch; } diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 4971d3268f..603675878e 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,8 @@ +2003-03-10 Andrew Cagney + + * gdbint.texinfo (Target Architecture Definition): Cross reference + FRAME_SAVED_PC to unwind_pc. Document unwind_pc. + 2003-03-07 Andrew Cagney * gdb.texinfo (Debugging Output): Mention the "set/show debug diff --git a/gdb/doc/gdbint.texinfo b/gdb/doc/gdbint.texinfo index 7deabfc6d3..625f6213e1 100644 --- a/gdb/doc/gdbint.texinfo +++ b/gdb/doc/gdbint.texinfo @@ -3270,8 +3270,28 @@ are being passed. If the number of arguments is not known, return @item FRAME_SAVED_PC(@var{frame}) @findex FRAME_SAVED_PC -Given @var{frame}, return the pc saved there. This is the return -address. +@anchor{FRAME_SAVED_PC} Given @var{frame}, return the pc saved there. +This is the return address. + +This method is deprecated. @xref{unwind_pc}. + +@item CORE_ADDR unwind_pc (struct frame_info *@var{this_frame}) +@findex unwind_pc +@anchor{unwind_pc} Return the instruction address, in @var{this_frame}'s +caller, at which execution will resume after @var{this_frame} returns. +This is commonly refered to as the return address. + +The implementation, which must be frame agnostic (work with any frame), +is typically no more than: + +@smallexample +ULONGEST pc; +frame_unwind_unsigned_register (this_frame, D10V_PC_REGNUM, &pc); +return d10v_make_iaddr (pc); +@end smallexample + +@noindent +@xref{FRAME_SAVED_PC}, which this method replaces. @item FUNCTION_EPILOGUE_SIZE @findex FUNCTION_EPILOGUE_SIZE diff --git a/gdb/dummy-frame.c b/gdb/dummy-frame.c index 5b638306fd..95c859889a 100644 --- a/gdb/dummy-frame.c +++ b/gdb/dummy-frame.c @@ -370,23 +370,6 @@ dummy_frame_register_unwind (struct frame_info *frame, void **cache, } } -/* Assuming that FRAME is a dummy, return the resume address for the - previous frame. */ - -static CORE_ADDR -dummy_frame_pc_unwind (struct frame_info *frame, - void **cache) -{ - struct dummy_frame *dummy = cached_find_dummy_frame (frame, cache); - /* Oops! In a dummy-frame but can't find the stack dummy. Pretend - that the frame doesn't unwind. Should this function instead - return a has-no-caller indication? */ - if (dummy == NULL) - return 0; - return dummy->pc; -} - - /* Assuming that FRAME is a dummy, return the ID of the calling frame (the frame that the dummy has the saved state of). */ @@ -408,7 +391,6 @@ dummy_frame_id_unwind (struct frame_info *frame, static struct frame_unwind dummy_frame_unwind = { dummy_frame_pop, - dummy_frame_pc_unwind, dummy_frame_id_unwind, dummy_frame_register_unwind }; diff --git a/gdb/frame-unwind.h b/gdb/frame-unwind.h index 2c67c969fb..7f4a866b1e 100644 --- a/gdb/frame-unwind.h +++ b/gdb/frame-unwind.h @@ -69,12 +69,6 @@ typedef void (frame_unwind_reg_ftype) (struct frame_info * frame, CORE_ADDR *addrp, int *realnump, void *valuep); -/* Same as for registers above, but return the address at which the - calling frame would resume. */ - -typedef CORE_ADDR (frame_unwind_pc_ftype) (struct frame_info * frame, - void **unwind_cache); - /* Same as for registers above, but return the ID of the frame that called this one. */ @@ -103,7 +97,6 @@ struct frame_unwind /* Should an attribute indicating the frame's address-in-block go here? */ frame_unwind_pop_ftype *pop; - frame_unwind_pc_ftype *pc; frame_unwind_id_ftype *id; frame_unwind_reg_ftype *reg; }; diff --git a/gdb/frame.c b/gdb/frame.c index bf860fe2cc..bbe870af0f 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -135,14 +135,54 @@ frame_find_by_id (struct frame_id id) } CORE_ADDR -frame_pc_unwind (struct frame_info *frame) +frame_pc_unwind (struct frame_info *this_frame) { - if (!frame->pc_unwind_cache_p) + if (!this_frame->pc_unwind_cache_p) { - frame->pc_unwind_cache = frame->unwind->pc (frame, &frame->unwind_cache); - frame->pc_unwind_cache_p = 1; + CORE_ADDR pc; + if (gdbarch_unwind_pc_p (current_gdbarch)) + { + /* The right way. The `pure' way. The one true way. This + method depends solely on the register-unwind code to + determine the value of registers in THIS frame, and hence + the value of this frame's PC (resume address). A typical + implementation is no more than: + + frame_unwind_register (this_frame, ISA_PC_REGNUM, buf); + return extract_address (buf, size of ISA_PC_REGNUM); + + Note: this method is very heavily dependent on a correct + register-unwind implementation, it pays to fix that + method first; this method is frame type agnostic, since + it only deals with register values, it works with any + frame. This is all in stark contrast to the old + FRAME_SAVED_PC which would try to directly handle all the + different ways that a PC could be unwound. */ + pc = gdbarch_unwind_pc (current_gdbarch, this_frame); + } + else if (this_frame->level < 0) + { + /* FIXME: cagney/2003-03-06: Old code and and a sentinel + frame. Do like was always done. Fetch the PC's value + direct from the global registers array (via read_pc). + This assumes that this frame belongs to the current + global register cache. The assumption is dangerous. */ + pc = read_pc (); + } + else if (FRAME_SAVED_PC_P ()) + { + /* FIXME: cagney/2003-03-06: Old code, but not a sentinel + frame. Do like was always done. Note that this method, + unlike unwind_pc(), tries to handle all the different + frame cases directly. It fails. */ + pc = FRAME_SAVED_PC (this_frame); + } + else + internal_error (__FILE__, __LINE__, "No gdbarch_unwind_pc method"); + this_frame->pc_unwind_cache = pc; + this_frame->pc_unwind_cache_p = 1; } - return frame->pc_unwind_cache; + return this_frame->pc_unwind_cache; } void @@ -667,13 +707,6 @@ frame_saved_regs_register_unwind (struct frame_info *frame, void **cache, bufferp); } -static CORE_ADDR -frame_saved_regs_pc_unwind (struct frame_info *frame, void **cache) -{ - gdb_assert (FRAME_SAVED_PC_P ()); - return FRAME_SAVED_PC (frame); -} - static void frame_saved_regs_id_unwind (struct frame_info *next_frame, void **cache, struct frame_id *id) @@ -745,7 +778,6 @@ frame_saved_regs_pop (struct frame_info *fi, void **cache, const struct frame_unwind trad_frame_unwinder = { frame_saved_regs_pop, - frame_saved_regs_pc_unwind, frame_saved_regs_id_unwind, frame_saved_regs_register_unwind }; diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c index 636349c7be..8b5a475375 100644 --- a/gdb/gdbarch.c +++ b/gdb/gdbarch.c @@ -242,6 +242,7 @@ struct gdbarch gdbarch_frame_chain_ftype *frame_chain; gdbarch_frame_chain_valid_ftype *frame_chain_valid; gdbarch_frame_saved_pc_ftype *frame_saved_pc; + gdbarch_unwind_pc_ftype *unwind_pc; gdbarch_frame_args_address_ftype *frame_args_address; gdbarch_frame_locals_address_ftype *frame_locals_address; gdbarch_saved_pc_after_call_ftype *saved_pc_after_call; @@ -433,6 +434,7 @@ struct gdbarch startup_gdbarch = 0, 0, 0, + 0, generic_in_function_epilogue_p, construct_inferior_arguments, 0, @@ -759,6 +761,7 @@ verify_gdbarch (struct gdbarch *gdbarch) /* Skip verify of frame_chain, has predicate */ /* Skip verify of frame_chain_valid, has predicate */ /* Skip verify of frame_saved_pc, has predicate */ + /* Skip verify of unwind_pc, has predicate */ /* Skip verify of frame_args_address, invalid_p == 0 */ /* Skip verify of frame_locals_address, invalid_p == 0 */ if ((GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) @@ -2578,6 +2581,14 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file) fprintf_unfiltered (file, "gdbarch_dump: unwind_dummy_id = 0x%08lx\n", (long) current_gdbarch->unwind_dummy_id); + if (GDB_MULTI_ARCH) + fprintf_unfiltered (file, + "gdbarch_dump: gdbarch_unwind_pc_p() = %d\n", + gdbarch_unwind_pc_p (current_gdbarch)); + if (GDB_MULTI_ARCH) + fprintf_unfiltered (file, + "gdbarch_dump: unwind_pc = 0x%08lx\n", + (long) current_gdbarch->unwind_pc); #ifdef USE_STRUCT_CONVENTION fprintf_unfiltered (file, "gdbarch_dump: %s # %s\n", @@ -4845,6 +4856,32 @@ set_gdbarch_frame_saved_pc (struct gdbarch *gdbarch, gdbarch->frame_saved_pc = frame_saved_pc; } +int +gdbarch_unwind_pc_p (struct gdbarch *gdbarch) +{ + gdb_assert (gdbarch != NULL); + return gdbarch->unwind_pc != 0; +} + +CORE_ADDR +gdbarch_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame) +{ + gdb_assert (gdbarch != NULL); + if (gdbarch->unwind_pc == 0) + internal_error (__FILE__, __LINE__, + "gdbarch: gdbarch_unwind_pc invalid"); + if (gdbarch_debug >= 2) + fprintf_unfiltered (gdb_stdlog, "gdbarch_unwind_pc called\n"); + return gdbarch->unwind_pc (gdbarch, next_frame); +} + +void +set_gdbarch_unwind_pc (struct gdbarch *gdbarch, + gdbarch_unwind_pc_ftype unwind_pc) +{ + gdbarch->unwind_pc = unwind_pc; +} + CORE_ADDR gdbarch_frame_args_address (struct gdbarch *gdbarch, struct frame_info *fi) { diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h index 75d96edd13..abb454a3a0 100644 --- a/gdb/gdbarch.h +++ b/gdb/gdbarch.h @@ -2228,6 +2228,8 @@ extern void set_gdbarch_frame_chain_valid (struct gdbarch *gdbarch, gdbarch_fram #endif #endif +/* NOTE: FRAME_SAVED_PC is replaced by UNWIND_PC */ + #if defined (FRAME_SAVED_PC) /* Legacy for systems yet to multi-arch FRAME_SAVED_PC */ #if !defined (FRAME_SAVED_PC_P) @@ -2265,6 +2267,12 @@ extern void set_gdbarch_frame_saved_pc (struct gdbarch *gdbarch, gdbarch_frame_s #endif #endif +extern int gdbarch_unwind_pc_p (struct gdbarch *gdbarch); + +typedef CORE_ADDR (gdbarch_unwind_pc_ftype) (struct gdbarch *gdbarch, struct frame_info *next_frame); +extern CORE_ADDR gdbarch_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame); +extern void set_gdbarch_unwind_pc (struct gdbarch *gdbarch, gdbarch_unwind_pc_ftype *unwind_pc); + /* Default (function) for non- multi-arch platforms. */ #if (!GDB_MULTI_ARCH) && !defined (FRAME_ARGS_ADDRESS) #define FRAME_ARGS_ADDRESS(fi) (get_frame_base (fi)) diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh index 5d41b5c691..77d2a69569 100755 --- a/gdb/gdbarch.sh +++ b/gdb/gdbarch.sh @@ -591,7 +591,9 @@ v:2:FRAME_ARGS_SKIP:CORE_ADDR:frame_args_skip::::0:-1 f:2:FRAMELESS_FUNCTION_INVOCATION:int:frameless_function_invocation:struct frame_info *fi:fi:::generic_frameless_function_invocation_not::0 F:2:FRAME_CHAIN:CORE_ADDR:frame_chain:struct frame_info *frame:frame::0:0 F:2:FRAME_CHAIN_VALID:int:frame_chain_valid:CORE_ADDR chain, struct frame_info *thisframe:chain, thisframe::0:0 +# NOTE: FRAME_SAVED_PC is replaced by UNWIND_PC F:2:FRAME_SAVED_PC:CORE_ADDR:frame_saved_pc:struct frame_info *fi:fi::0:0 +M::UNWIND_PC:CORE_ADDR:unwind_pc:struct frame_info *next_frame:next_frame: f:2:FRAME_ARGS_ADDRESS:CORE_ADDR:frame_args_address:struct frame_info *fi:fi::0:get_frame_base::0 f:2:FRAME_LOCALS_ADDRESS:CORE_ADDR:frame_locals_address:struct frame_info *fi:fi::0:get_frame_base::0 f:2:SAVED_PC_AFTER_CALL:CORE_ADDR:saved_pc_after_call:struct frame_info *frame:frame::0:0 diff --git a/gdb/sentinel-frame.c b/gdb/sentinel-frame.c index fe11d8a6f4..2b1616a1f8 100644 --- a/gdb/sentinel-frame.c +++ b/gdb/sentinel-frame.c @@ -70,17 +70,6 @@ sentinel_frame_register_unwind (struct frame_info *frame, } } -CORE_ADDR -sentinel_frame_pc_unwind (struct frame_info *frame, - void **cache) -{ - /* FIXME: cagney/2003-01-08: This should be using a per-architecture - method that doesn't suffer from DECR_PC_AFTER_BREAK problems. - Such a method would take unwind_cache, regcache and stop reason - parameters. */ - return read_pc (); -} - void sentinel_frame_id_unwind (struct frame_info *frame, void **cache, @@ -105,7 +94,6 @@ sentinel_frame_pop (struct frame_info *frame, const struct frame_unwind sentinel_frame_unwinder = { sentinel_frame_pop, - sentinel_frame_pc_unwind, sentinel_frame_id_unwind, sentinel_frame_register_unwind };