diff options
-rw-r--r-- | gdb/ChangeLog | 17 | ||||
-rw-r--r-- | gdb/dummy-frame.c | 12 | ||||
-rw-r--r-- | gdb/dummy-frame.h | 6 | ||||
-rw-r--r-- | gdb/frame-unwind.c | 20 | ||||
-rw-r--r-- | gdb/frame-unwind.h | 12 | ||||
-rw-r--r-- | gdb/frame.c | 132 | ||||
-rw-r--r-- | gdb/gdbarch.c | 41 | ||||
-rw-r--r-- | gdb/gdbarch.h | 13 | ||||
-rwxr-xr-x | gdb/gdbarch.sh | 16 |
9 files changed, 155 insertions, 114 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 4283cbb..28ab334 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,20 @@ +2018-12-19 Andrew Burgess <andrew.burgess@embecosm.com> + + * gdb/dummy-frame.c (default_dummy_id): Defined new function. + * gdb/dummy-frame.h (default_dummy_id): Declare new function. + * gdb/frame-unwind.c (default_unwind_pc): Define new function. + (default_unwind_sp): Define new function. + * gdb/frame-unwind.h (default_unwind_pc): Declare new function. + (default_unwind_sp): Declare new function. + * gdb/frame.c (frame_unwind_pc): Assume gdbarch_unwind_pc is + available. + (get_frame_sp): Assume that gdbarch_unwind_sp is available. + * gdb/gdbarch.c: Regenerate. + * gdb/gdbarch.h: Regenerate. + * gdb/gdbarch.sh: Update definition of dummy_id, unwind_pc, and + unwind_sp. Add additional header files to be included in + generated file. + 2018-12-19 Dimitar Dimitrov <dimitar@dinux.eu> * nat/linux-ptrace.c (linux_ptrace_test_ret_to_nx): Remove diff --git a/gdb/dummy-frame.c b/gdb/dummy-frame.c index c6f874a..8e380ae 100644 --- a/gdb/dummy-frame.c +++ b/gdb/dummy-frame.c @@ -385,6 +385,18 @@ const struct frame_unwind dummy_frame_unwind = dummy_frame_sniffer, }; +/* See dummy-frame.h. */ + +struct frame_id +default_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame) +{ + CORE_ADDR sp, pc; + + sp = get_frame_sp (this_frame); + pc = get_frame_pc (this_frame); + return frame_id_build (sp, pc); +} + static void fprint_dummy_frames (struct ui_file *file) { diff --git a/gdb/dummy-frame.h b/gdb/dummy-frame.h index 407f398..9eaec34 100644 --- a/gdb/dummy-frame.h +++ b/gdb/dummy-frame.h @@ -73,4 +73,10 @@ extern void register_dummy_frame_dtor (frame_id dummy_id, extern int find_dummy_frame_dtor (dummy_frame_dtor_ftype *dtor, void *dtor_data); +/* Default implementation of gdbarch_dummy_id. Generate a dummy frame_id + for THIS_FRAME assuming that the frame is a dummy frame. */ + +extern struct frame_id default_dummy_id (struct gdbarch *gdbarch, + struct frame_info *this_frame); + #endif /* !defined (DUMMY_FRAME_H) */ diff --git a/gdb/frame-unwind.c b/gdb/frame-unwind.c index e6e6353..fb0e5e8 100644 --- a/gdb/frame-unwind.c +++ b/gdb/frame-unwind.c @@ -193,6 +193,26 @@ default_frame_unwind_stop_reason (struct frame_info *this_frame, return UNWIND_NO_REASON; } +/* See frame-unwind.h. */ + +CORE_ADDR +default_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame) +{ + int pc_regnum = gdbarch_pc_regnum (gdbarch); + CORE_ADDR pc = frame_unwind_register_unsigned (next_frame, pc_regnum); + pc = gdbarch_addr_bits_remove (gdbarch, pc); + return pc; +} + +/* See frame-unwind.h. */ + +CORE_ADDR +default_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame) +{ + int sp_regnum = gdbarch_sp_regnum (gdbarch); + return frame_unwind_register_unsigned (next_frame, sp_regnum); +} + /* Helper functions for value-based register unwinding. These return a (possibly lazy) value of the appropriate type. */ diff --git a/gdb/frame-unwind.h b/gdb/frame-unwind.h index af220f7..3ca3fdf 100644 --- a/gdb/frame-unwind.h +++ b/gdb/frame-unwind.h @@ -70,6 +70,18 @@ enum unwind_stop_reason default_frame_unwind_stop_reason (struct frame_info *this_frame, void **this_cache); +/* A default unwind_pc callback that simply unwinds the register identified + by GDBARCH_PC_REGNUM. */ + +extern CORE_ADDR default_unwind_pc (struct gdbarch *gdbarch, + struct frame_info *next_frame); + +/* A default unwind_sp callback that simply unwinds the register identified + by GDBARCH_SP_REGNUM. */ + +extern CORE_ADDR default_unwind_sp (struct gdbarch *gdbarch, + struct frame_info *next_frame); + /* Assuming the frame chain: (outer) prev <-> this <-> next (inner); use THIS frame, and through it the NEXT frame's register unwind method, to determine the frame ID of THIS frame. diff --git a/gdb/frame.c b/gdb/frame.c index 4624ead..f98a54a 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -872,76 +872,71 @@ frame_unwind_pc (struct frame_info *this_frame) { if (this_frame->prev_pc.status == CC_UNKNOWN) { - if (gdbarch_unwind_pc_p (frame_unwind_arch (this_frame))) + struct gdbarch *prev_gdbarch; + CORE_ADDR pc = 0; + int pc_p = 0; + + /* 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_unsigned_integer (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. */ + prev_gdbarch = frame_unwind_arch (this_frame); + + TRY { - struct gdbarch *prev_gdbarch; - CORE_ADDR pc = 0; - int pc_p = 0; - - /* 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_unsigned_integer (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. */ - prev_gdbarch = frame_unwind_arch (this_frame); - - TRY + pc = gdbarch_unwind_pc (prev_gdbarch, this_frame); + pc_p = 1; + } + CATCH (ex, RETURN_MASK_ERROR) + { + if (ex.error == NOT_AVAILABLE_ERROR) { - pc = gdbarch_unwind_pc (prev_gdbarch, this_frame); - pc_p = 1; + this_frame->prev_pc.status = CC_UNAVAILABLE; + + if (frame_debug) + fprintf_unfiltered (gdb_stdlog, + "{ frame_unwind_pc (this_frame=%d)" + " -> <unavailable> }\n", + this_frame->level); } - CATCH (ex, RETURN_MASK_ERROR) + else if (ex.error == OPTIMIZED_OUT_ERROR) { - if (ex.error == NOT_AVAILABLE_ERROR) - { - this_frame->prev_pc.status = CC_UNAVAILABLE; - - if (frame_debug) - fprintf_unfiltered (gdb_stdlog, - "{ frame_unwind_pc (this_frame=%d)" - " -> <unavailable> }\n", - this_frame->level); - } - else if (ex.error == OPTIMIZED_OUT_ERROR) - { - this_frame->prev_pc.status = CC_NOT_SAVED; - - if (frame_debug) - fprintf_unfiltered (gdb_stdlog, - "{ frame_unwind_pc (this_frame=%d)" - " -> <not saved> }\n", - this_frame->level); - } - else - throw_exception (ex); - } - END_CATCH + this_frame->prev_pc.status = CC_NOT_SAVED; - if (pc_p) - { - this_frame->prev_pc.value = pc; - this_frame->prev_pc.status = CC_VALUE; if (frame_debug) fprintf_unfiltered (gdb_stdlog, - "{ frame_unwind_pc (this_frame=%d) " - "-> %s }\n", - this_frame->level, - hex_string (this_frame->prev_pc.value)); + "{ frame_unwind_pc (this_frame=%d)" + " -> <not saved> }\n", + this_frame->level); } + else + throw_exception (ex); + } + END_CATCH + + if (pc_p) + { + this_frame->prev_pc.value = pc; + this_frame->prev_pc.status = CC_VALUE; + if (frame_debug) + fprintf_unfiltered (gdb_stdlog, + "{ frame_unwind_pc (this_frame=%d) " + "-> %s }\n", + this_frame->level, + hex_string (this_frame->prev_pc.value)); } - else - internal_error (__FILE__, __LINE__, _("No unwind_pc method")); } if (this_frame->prev_pc.status == CC_VALUE) @@ -2782,18 +2777,9 @@ get_frame_sp (struct frame_info *this_frame) { struct gdbarch *gdbarch = get_frame_arch (this_frame); - /* Normality - an architecture that provides a way of obtaining any - frame inner-most address. */ - if (gdbarch_unwind_sp_p (gdbarch)) - /* NOTE drow/2008-06-28: gdbarch_unwind_sp could be converted to - operate on THIS_FRAME now. */ - return gdbarch_unwind_sp (gdbarch, this_frame->next); - /* Now things are really are grim. Hope that the value returned by - the gdbarch_sp_regnum register is meaningful. */ - if (gdbarch_sp_regnum (gdbarch) >= 0) - return get_frame_register_unsigned (this_frame, - gdbarch_sp_regnum (gdbarch)); - internal_error (__FILE__, __LINE__, _("Missing unwind SP method")); + /* NOTE drow/2008-06-28: gdbarch_unwind_sp could be converted to + operate on THIS_FRAME now. */ + return gdbarch_unwind_sp (gdbarch, this_frame->next); } /* Return the reason why we can't unwind past FRAME. */ diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c index bc4f786..193142c 100644 --- a/gdb/gdbarch.c +++ b/gdb/gdbarch.c @@ -48,6 +48,8 @@ #include "regcache.h" #include "objfiles.h" #include "auxv.h" +#include "frame-unwind.h" +#include "dummy-frame.h" /* Static function declarations */ @@ -408,6 +410,7 @@ gdbarch_alloc (const struct gdbarch_info *info, gdbarch->ecoff_reg_to_regnum = no_op_reg_to_regnum; gdbarch->sdb_reg_to_regnum = no_op_reg_to_regnum; gdbarch->dwarf2_reg_to_regnum = no_op_reg_to_regnum; + gdbarch->dummy_id = default_dummy_id; gdbarch->deprecated_fp_regnum = -1; gdbarch->call_dummy_location = AT_ENTRY_POINT; gdbarch->code_of_frame_writable = default_code_of_frame_writable; @@ -427,6 +430,8 @@ gdbarch_alloc (const struct gdbarch_info *info, gdbarch->memory_insert_breakpoint = default_memory_insert_breakpoint; gdbarch->memory_remove_breakpoint = default_memory_remove_breakpoint; gdbarch->remote_register_number = default_remote_register_number; + gdbarch->unwind_pc = default_unwind_pc; + gdbarch->unwind_sp = default_unwind_sp; gdbarch->stabs_argument_has_addr = default_stabs_argument_has_addr; gdbarch->convert_from_func_ptr_addr = convert_from_func_ptr_addr_identity; gdbarch->addr_bits_remove = core_addr_identity; @@ -570,7 +575,7 @@ verify_gdbarch (struct gdbarch *gdbarch) if (gdbarch->register_name == 0) log.puts ("\n\tregister_name"); /* Skip verify of register_type, has predicate. */ - /* Skip verify of dummy_id, has predicate. */ + /* Skip verify of dummy_id, invalid_p == 0 */ /* Skip verify of deprecated_fp_regnum, invalid_p == 0 */ /* Skip verify of push_dummy_call, has predicate. */ /* Skip verify of call_dummy_location, invalid_p == 0 */ @@ -609,8 +614,8 @@ verify_gdbarch (struct gdbarch *gdbarch) /* Skip verify of remote_register_number, invalid_p == 0 */ /* Skip verify of fetch_tls_load_module_address, has predicate. */ /* Skip verify of frame_args_skip, invalid_p == 0 */ - /* Skip verify of unwind_pc, has predicate. */ - /* Skip verify of unwind_sp, has predicate. */ + /* Skip verify of unwind_pc, invalid_p == 0 */ + /* Skip verify of unwind_sp, invalid_p == 0 */ /* Skip verify of frame_num_args, has predicate. */ /* Skip verify of frame_align, has predicate. */ /* Skip verify of stabs_argument_has_addr, invalid_p == 0 */ @@ -955,9 +960,6 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file) "gdbarch_dump: dtrace_probe_is_enabled = <%s>\n", host_address_to_string (gdbarch->dtrace_probe_is_enabled)); fprintf_unfiltered (file, - "gdbarch_dump: gdbarch_dummy_id_p() = %d\n", - gdbarch_dummy_id_p (gdbarch)); - fprintf_unfiltered (file, "gdbarch_dump: dummy_id = <%s>\n", host_address_to_string (gdbarch->dummy_id)); fprintf_unfiltered (file, @@ -1441,15 +1443,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file) "gdbarch_dump: type_align = <%s>\n", host_address_to_string (gdbarch->type_align)); fprintf_unfiltered (file, - "gdbarch_dump: gdbarch_unwind_pc_p() = %d\n", - gdbarch_unwind_pc_p (gdbarch)); - fprintf_unfiltered (file, "gdbarch_dump: unwind_pc = <%s>\n", host_address_to_string (gdbarch->unwind_pc)); fprintf_unfiltered (file, - "gdbarch_dump: gdbarch_unwind_sp_p() = %d\n", - gdbarch_unwind_sp_p (gdbarch)); - fprintf_unfiltered (file, "gdbarch_dump: unwind_sp = <%s>\n", host_address_to_string (gdbarch->unwind_sp)); fprintf_unfiltered (file, @@ -2307,13 +2303,6 @@ set_gdbarch_register_type (struct gdbarch *gdbarch, gdbarch->register_type = register_type; } -int -gdbarch_dummy_id_p (struct gdbarch *gdbarch) -{ - gdb_assert (gdbarch != NULL); - return gdbarch->dummy_id != NULL; -} - struct frame_id gdbarch_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame) { @@ -3046,13 +3035,6 @@ set_gdbarch_frame_args_skip (struct gdbarch *gdbarch, gdbarch->frame_args_skip = frame_args_skip; } -int -gdbarch_unwind_pc_p (struct gdbarch *gdbarch) -{ - gdb_assert (gdbarch != NULL); - return gdbarch->unwind_pc != NULL; -} - CORE_ADDR gdbarch_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame) { @@ -3070,13 +3052,6 @@ set_gdbarch_unwind_pc (struct gdbarch *gdbarch, gdbarch->unwind_pc = unwind_pc; } -int -gdbarch_unwind_sp_p (struct gdbarch *gdbarch) -{ - gdb_assert (gdbarch != NULL); - return gdbarch->unwind_sp != NULL; -} - CORE_ADDR gdbarch_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame) { diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h index e13c469..e53f4d4 100644 --- a/gdb/gdbarch.h +++ b/gdb/gdbarch.h @@ -403,7 +403,14 @@ typedef struct type * (gdbarch_register_type_ftype) (struct gdbarch *gdbarch, in extern struct type * gdbarch_register_type (struct gdbarch *gdbarch, int reg_nr); extern void set_gdbarch_register_type (struct gdbarch *gdbarch, gdbarch_register_type_ftype *register_type); -extern int gdbarch_dummy_id_p (struct gdbarch *gdbarch); +/* Generate a dummy frame_id for THIS_FRAME assuming that the frame is + a dummy frame. A dummy frame is created before an inferior call, + the frame_id returned here must match the frame_id that was built + for the inferior call. Usually this means the returned frame_id's + stack address should match the address returned by + gdbarch_push_dummy_call, and the returned frame_id's code address + should match the address at which the breakpoint was set in the dummy + frame. */ typedef struct frame_id (gdbarch_dummy_id_ftype) (struct gdbarch *gdbarch, struct frame_info *this_frame); extern struct frame_id gdbarch_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame); @@ -645,14 +652,10 @@ extern void set_gdbarch_fetch_tls_load_module_address (struct gdbarch *gdbarch, extern CORE_ADDR gdbarch_frame_args_skip (struct gdbarch *gdbarch); extern void set_gdbarch_frame_args_skip (struct gdbarch *gdbarch, CORE_ADDR frame_args_skip); -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); -extern int gdbarch_unwind_sp_p (struct gdbarch *gdbarch); - typedef CORE_ADDR (gdbarch_unwind_sp_ftype) (struct gdbarch *gdbarch, struct frame_info *next_frame); extern CORE_ADDR gdbarch_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame); extern void set_gdbarch_unwind_sp (struct gdbarch *gdbarch, gdbarch_unwind_sp_ftype *unwind_sp); diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh index a876a21..1606556 100755 --- a/gdb/gdbarch.sh +++ b/gdb/gdbarch.sh @@ -480,7 +480,15 @@ m;const char *;register_name;int regnr;regnr;;0 # use "register_type". M;struct type *;register_type;int reg_nr;reg_nr -M;struct frame_id;dummy_id;struct frame_info *this_frame;this_frame +# Generate a dummy frame_id for THIS_FRAME assuming that the frame is +# a dummy frame. A dummy frame is created before an inferior call, +# the frame_id returned here must match the frame_id that was built +# for the inferior call. Usually this means the returned frame_id's +# stack address should match the address returned by +# gdbarch_push_dummy_call, and the returned frame_id's code address +# should match the address at which the breakpoint was set in the dummy +# frame. +m;struct frame_id;dummy_id;struct frame_info *this_frame;this_frame;;default_dummy_id;;0 # Implement DUMMY_ID and PUSH_DUMMY_CALL, then delete # deprecated_fp_regnum. v;int;deprecated_fp_regnum;;;-1;-1;;0 @@ -596,8 +604,8 @@ m;int;remote_register_number;int regno;regno;;default_remote_register_number;;0 F;CORE_ADDR;fetch_tls_load_module_address;struct objfile *objfile;objfile # v;CORE_ADDR;frame_args_skip;;;0;;;0 -M;CORE_ADDR;unwind_pc;struct frame_info *next_frame;next_frame -M;CORE_ADDR;unwind_sp;struct frame_info *next_frame;next_frame +m;CORE_ADDR;unwind_pc;struct frame_info *next_frame;next_frame;;default_unwind_pc;;0 +m;CORE_ADDR;unwind_sp;struct frame_info *next_frame;next_frame;;default_unwind_sp;;0 # DEPRECATED_FRAME_LOCALS_ADDRESS as been replaced by the per-frame # frame-base. Enable frame-base before frame-unwind. F;int;frame_num_args;struct frame_info *frame;frame @@ -1690,6 +1698,8 @@ cat <<EOF #include "regcache.h" #include "objfiles.h" #include "auxv.h" +#include "frame-unwind.h" +#include "dummy-frame.h" /* Static function declarations */ |