X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fframe-unwind.c;h=3334c472d0202b546f5eea17e27ec6cbbabc7476;hb=refs%2Fheads%2Fconcurrent-displaced-stepping-2020-04-01;hp=98d6b436bbee56128a3d96e5cc84cc8328dd4537;hpb=0fb0cc7590113e9b459dfcc48dc71c9d419d9580;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/frame-unwind.c b/gdb/frame-unwind.c index 98d6b436bb..3334c472d0 100644 --- a/gdb/frame-unwind.c +++ b/gdb/frame-unwind.c @@ -1,6 +1,6 @@ /* Definitions for frame unwinder, for GDB, the GNU debugger. - Copyright (C) 2003, 2004, 2007, 2008, 2009 Free Software Foundation, Inc. + Copyright (C) 2003-2020 Free Software Foundation, Inc. This file is part of GDB. @@ -21,11 +21,13 @@ #include "frame.h" #include "frame-unwind.h" #include "dummy-frame.h" +#include "inline-frame.h" #include "value.h" #include "regcache.h" - -#include "gdb_assert.h" #include "gdb_obstack.h" +#include "target.h" +#include "gdbarch.h" +#include "dwarf2/frame-tailcall.h" static struct gdbarch_data *frame_unwind_data; @@ -42,17 +44,41 @@ struct frame_unwind_table struct frame_unwind_table_entry **osabi_head; }; +/* A helper function to add an unwinder to a list. LINK says where to + install the new unwinder. The new link is returned. */ + +static struct frame_unwind_table_entry ** +add_unwinder (struct obstack *obstack, const struct frame_unwind *unwinder, + struct frame_unwind_table_entry **link) +{ + *link = OBSTACK_ZALLOC (obstack, struct frame_unwind_table_entry); + (*link)->unwinder = unwinder; + return &(*link)->next; +} + static void * frame_unwind_init (struct obstack *obstack) { struct frame_unwind_table *table = OBSTACK_ZALLOC (obstack, struct frame_unwind_table); + /* Start the table out with a few default sniffers. OSABI code can't override this. */ - table->list = OBSTACK_ZALLOC (obstack, struct frame_unwind_table_entry); - table->list->unwinder = dummy_frame_unwind; + struct frame_unwind_table_entry **link = &table->list; + + link = add_unwinder (obstack, &dummy_frame_unwind, link); + /* The DWARF tailcall sniffer must come before the inline sniffer. + Otherwise, we can end up in a situation where a DWARF frame finds + tailcall information, but then the inline sniffer claims a frame + before the tailcall sniffer, resulting in confusion. This is + safe to do always because the tailcall sniffer can only ever be + activated if the newer frame was created using the DWARF + unwinder, and it also found tailcall information. */ + link = add_unwinder (obstack, &dwarf2_tailcall_frame_unwind, link); + link = add_unwinder (obstack, &inline_frame_unwind, link); + /* The insertion point for OSABI sniffers. */ - table->osabi_head = &table->list->next; + table->osabi_head = link; return table; } @@ -60,7 +86,8 @@ void frame_unwind_prepend_unwinder (struct gdbarch *gdbarch, const struct frame_unwind *unwinder) { - struct frame_unwind_table *table = gdbarch_data (gdbarch, frame_unwind_data); + struct frame_unwind_table *table + = (struct frame_unwind_table *) gdbarch_data (gdbarch, frame_unwind_data); struct frame_unwind_table_entry *entry; /* Insert the new entry at the start of the list. */ @@ -74,7 +101,8 @@ void frame_unwind_append_unwinder (struct gdbarch *gdbarch, const struct frame_unwind *unwinder) { - struct frame_unwind_table *table = gdbarch_data (gdbarch, frame_unwind_data); + struct frame_unwind_table *table + = (struct frame_unwind_table *) gdbarch_data (gdbarch, frame_unwind_data); struct frame_unwind_table_entry **ip; /* Find the end of the list and insert the new entry there. */ @@ -83,27 +111,81 @@ frame_unwind_append_unwinder (struct gdbarch *gdbarch, (*ip)->unwinder = unwinder; } -const struct frame_unwind * -frame_unwind_find_by_frame (struct frame_info *this_frame, void **this_cache) +/* Call SNIFFER from UNWINDER. If it succeeded set UNWINDER for + THIS_FRAME and return 1. Otherwise the function keeps THIS_FRAME + unchanged and returns 0. */ + +static int +frame_unwind_try_unwinder (struct frame_info *this_frame, void **this_cache, + const struct frame_unwind *unwinder) { - int i; - struct gdbarch *gdbarch = get_frame_arch (this_frame); - struct frame_unwind_table *table = gdbarch_data (gdbarch, frame_unwind_data); - struct frame_unwind_table_entry *entry; - struct cleanup *old_cleanup; - for (entry = table->list; entry != NULL; entry = entry->next) + int res = 0; + + frame_prepare_for_sniffer (this_frame, unwinder); + + try + { + res = unwinder->sniffer (unwinder, this_frame, this_cache); + } + catch (const gdb_exception &ex) { - struct cleanup *old_cleanup; + /* Catch all exceptions, caused by either interrupt or error. + Reset *THIS_CACHE. */ + *this_cache = NULL; + frame_cleanup_after_sniffer (this_frame); - old_cleanup = frame_prepare_for_sniffer (this_frame, entry->unwinder); - if (entry->unwinder->sniffer (entry->unwinder, this_frame, - this_cache)) + if (ex.error == NOT_AVAILABLE_ERROR) { - discard_cleanups (old_cleanup); - return entry->unwinder; + /* This usually means that not even the PC is available, + thus most unwinders aren't able to determine if they're + the best fit. Keep trying. Fallback prologue unwinders + should always accept the frame. */ + return 0; } - do_cleanups (old_cleanup); + throw; + } + + if (res) + return 1; + else + { + /* Don't set *THIS_CACHE to NULL here, because sniffer has to do + so. */ + frame_cleanup_after_sniffer (this_frame); + return 0; } + gdb_assert_not_reached ("frame_unwind_try_unwinder"); +} + +/* Iterate through sniffers for THIS_FRAME frame until one returns with an + unwinder implementation. THIS_FRAME->UNWIND must be NULL, it will get set + by this function. Possibly initialize THIS_CACHE. */ + +void +frame_unwind_find_by_frame (struct frame_info *this_frame, void **this_cache) +{ + struct gdbarch *gdbarch = get_frame_arch (this_frame); + struct frame_unwind_table *table + = (struct frame_unwind_table *) gdbarch_data (gdbarch, frame_unwind_data); + struct frame_unwind_table_entry *entry; + const struct frame_unwind *unwinder_from_target; + + unwinder_from_target = target_get_unwinder (); + if (unwinder_from_target != NULL + && frame_unwind_try_unwinder (this_frame, this_cache, + unwinder_from_target)) + return; + + unwinder_from_target = target_get_tailcall_unwinder (); + if (unwinder_from_target != NULL + && frame_unwind_try_unwinder (this_frame, this_cache, + unwinder_from_target)) + return; + + for (entry = table->list; entry != NULL; entry = entry->next) + if (frame_unwind_try_unwinder (this_frame, this_cache, entry->unwinder)) + return; + internal_error (__FILE__, __LINE__, _("frame_unwind_find_by_frame failed")); } @@ -118,6 +200,40 @@ default_frame_sniffer (const struct frame_unwind *self, return 1; } +/* The default frame unwinder stop_reason callback. */ + +enum unwind_stop_reason +default_frame_unwind_stop_reason (struct frame_info *this_frame, + void **this_cache) +{ + struct frame_id this_id = get_frame_id (this_frame); + + if (frame_id_eq (this_id, outer_frame_id)) + return UNWIND_OUTERMOST; + else + 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. */ @@ -126,19 +242,28 @@ default_frame_sniffer (const struct frame_unwind *self, struct value * frame_unwind_got_optimized (struct frame_info *frame, int regnum) { - struct gdbarch *gdbarch = get_frame_arch (frame); - struct value *reg_val; - - reg_val = value_zero (register_type (gdbarch, regnum), not_lval); - set_value_optimized_out (reg_val, 1); - return reg_val; + struct gdbarch *gdbarch = frame_unwind_arch (frame); + struct type *type = register_type (gdbarch, regnum); + struct value *val; + + /* Return an lval_register value, so that we print it as + "". */ + val = allocate_value_lazy (type); + set_value_lazy (val, 0); + mark_value_bytes_optimized_out (val, 0, TYPE_LENGTH (type)); + VALUE_LVAL (val) = lval_register; + VALUE_REGNUM (val) = regnum; + VALUE_NEXT_FRAME_ID (val) + = get_frame_id (get_next_frame_sentinel_okay (frame)); + return val; } /* Return a value which indicates that FRAME copied REGNUM into register NEW_REGNUM. */ struct value * -frame_unwind_got_register (struct frame_info *frame, int regnum, int new_regnum) +frame_unwind_got_register (struct frame_info *frame, + int regnum, int new_regnum) { return value_of_register_lazy (frame, new_regnum); } @@ -149,9 +274,11 @@ frame_unwind_got_register (struct frame_info *frame, int regnum, int new_regnum) struct value * frame_unwind_got_memory (struct frame_info *frame, int regnum, CORE_ADDR addr) { - struct gdbarch *gdbarch = get_frame_arch (frame); + struct gdbarch *gdbarch = frame_unwind_arch (frame); + struct value *v = value_at_lazy (register_type (gdbarch, regnum), addr); - return value_at_lazy (register_type (gdbarch, regnum), addr); + set_value_stack (v, 1); + return v; } /* Return a value which indicates that FRAME's saved version of @@ -161,19 +288,20 @@ struct value * frame_unwind_got_constant (struct frame_info *frame, int regnum, ULONGEST val) { - struct gdbarch *gdbarch = get_frame_arch (frame); + struct gdbarch *gdbarch = frame_unwind_arch (frame); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); struct value *reg_val; reg_val = value_zero (register_type (gdbarch, regnum), not_lval); store_unsigned_integer (value_contents_writeable (reg_val), - register_size (gdbarch, regnum), val); + register_size (gdbarch, regnum), byte_order, val); return reg_val; } struct value * frame_unwind_got_bytes (struct frame_info *frame, int regnum, gdb_byte *buf) { - struct gdbarch *gdbarch = get_frame_arch (frame); + struct gdbarch *gdbarch = frame_unwind_arch (frame); struct value *reg_val; reg_val = value_zero (register_type (gdbarch, regnum), not_lval); @@ -189,7 +317,7 @@ struct value * frame_unwind_got_address (struct frame_info *frame, int regnum, CORE_ADDR addr) { - struct gdbarch *gdbarch = get_frame_arch (frame); + struct gdbarch *gdbarch = frame_unwind_arch (frame); struct value *reg_val; reg_val = value_zero (register_type (gdbarch, regnum), not_lval); @@ -198,10 +326,9 @@ frame_unwind_got_address (struct frame_info *frame, int regnum, return reg_val; } -extern initialize_file_ftype _initialize_frame_unwind; /* -Wmissing-prototypes */ - +void _initialize_frame_unwind (); void -_initialize_frame_unwind (void) +_initialize_frame_unwind () { frame_unwind_data = gdbarch_data_register_pre_init (frame_unwind_init); }