X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=gdb%2Fframe.c;h=ae45e22d613d79aaaedc8984d63e622b80a3e13f;hb=8b8da1a9f31941fa167c9f2bd2a80cdd1dccb452;hp=4618da6c81e2d8dd3b08424ec684f86bd211394f;hpb=2b3cb4006a2e80743eb78f263bd4d6c4f67833f9;p=binutils-gdb.git diff --git a/gdb/frame.c b/gdb/frame.c index 4618da6c81e..ae45e22d613 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -1,6 +1,6 @@ /* Cache and manage frames for GDB, the GNU debugger. - Copyright (C) 1986-2020 Free Software Foundation, Inc. + Copyright (C) 1986-2022 Free Software Foundation, Inc. This file is part of GDB. @@ -24,7 +24,7 @@ #include "inferior.h" /* for inferior_ptid */ #include "regcache.h" #include "user-regs.h" -#include "gdb_obstack.h" +#include "gdbsupport/gdb_obstack.h" #include "dummy-frame.h" #include "sentinel-frame.h" #include "gdbcore.h" @@ -111,6 +111,9 @@ enum class frame_id_status struct frame_info { + /* Return a string representation of this frame. */ + std::string to_string () const; + /* Level of this frame. The inner-most (youngest) frame is at level 0. As you move towards the outer-most (oldest) frame, the level increases. This is a cached value. It could just as easily be @@ -330,12 +333,13 @@ scoped_restore_selected_frame::~scoped_restore_selected_frame () /* Flag to control debugging. */ -unsigned int frame_debug; +bool frame_debug; + static void show_frame_debug (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) { - fprintf_filtered (file, _("Frame debugging is %s.\n"), value); + gdb_printf (file, _("Frame debugging is %s.\n"), value); } /* Implementation of "show backtrace past-main". */ @@ -344,10 +348,10 @@ static void show_backtrace_past_main (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) { - fprintf_filtered (file, - _("Whether backtraces should " - "continue past \"main\" is %s.\n"), - value); + gdb_printf (file, + _("Whether backtraces should " + "continue past \"main\" is %s.\n"), + value); } /* Implementation of "show backtrace past-entry". */ @@ -356,9 +360,9 @@ static void show_backtrace_past_entry (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) { - fprintf_filtered (file, _("Whether backtraces should continue past the " - "entry point of a program is %s.\n"), - value); + gdb_printf (file, _("Whether backtraces should continue past the " + "entry point of a program is %s.\n"), + value); } /* Implementation of "show backtrace limit". */ @@ -367,140 +371,131 @@ static void show_backtrace_limit (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) { - fprintf_filtered (file, - _("An upper bound on the number " - "of backtrace levels is %s.\n"), - value); + gdb_printf (file, + _("An upper bound on the number " + "of backtrace levels is %s.\n"), + value); } +/* See frame.h. */ -static void -fprint_field (struct ui_file *file, const char *name, int p, CORE_ADDR addr) +std::string +frame_id::to_string () const { - if (p) - fprintf_unfiltered (file, "%s=%s", name, hex_string (addr)); - else - fprintf_unfiltered (file, "!%s", name); -} + const struct frame_id &id = *this; -void -fprint_frame_id (struct ui_file *file, struct frame_id id) -{ - fprintf_unfiltered (file, "{"); + std::string res = "{"; if (id.stack_status == FID_STACK_INVALID) - fprintf_unfiltered (file, "!stack"); + res += "!stack"; else if (id.stack_status == FID_STACK_UNAVAILABLE) - fprintf_unfiltered (file, "stack="); + res += "stack="; else if (id.stack_status == FID_STACK_SENTINEL) - fprintf_unfiltered (file, "stack="); + res += "stack="; else if (id.stack_status == FID_STACK_OUTER) - fprintf_unfiltered (file, "stack="); + res += "stack="; else - fprintf_unfiltered (file, "stack=%s", hex_string (id.stack_addr)); - - fprintf_unfiltered (file, ","); + res += std::string ("stack=") + hex_string (id.stack_addr); - fprint_field (file, "code", id.code_addr_p, id.code_addr); - fprintf_unfiltered (file, ","); + /* Helper function to format 'N=A' if P is true, otherwise '!N'. */ + auto field_to_string = [] (const char *n, bool p, CORE_ADDR a) -> std::string + { + if (p) + return std::string (n) + "=" + core_addr_to_string (a); + else + return std::string ("!") + std::string (n); + }; - fprint_field (file, "special", id.special_addr_p, id.special_addr); + res += (std::string (",") + + field_to_string ("code", id.code_addr_p, id.code_addr) + + std::string (",") + + field_to_string ("special", id.special_addr_p, id.special_addr)); if (id.artificial_depth) - fprintf_unfiltered (file, ",artificial=%d", id.artificial_depth); - - fprintf_unfiltered (file, "}"); + res += ",artificial=" + std::to_string (id.artificial_depth); + res += "}"; + return res; } -static void -fprint_frame_type (struct ui_file *file, enum frame_type type) +/* Return a string representation of TYPE. */ + +static const char * +frame_type_str (frame_type type) { switch (type) { case NORMAL_FRAME: - fprintf_unfiltered (file, "NORMAL_FRAME"); - return; + return "NORMAL_FRAME"; + case DUMMY_FRAME: - fprintf_unfiltered (file, "DUMMY_FRAME"); - return; + return "DUMMY_FRAME"; + case INLINE_FRAME: - fprintf_unfiltered (file, "INLINE_FRAME"); - return; + return "INLINE_FRAME"; + case TAILCALL_FRAME: - fprintf_unfiltered (file, "TAILCALL_FRAME"); - return; + return "TAILCALL_FRAME"; + case SIGTRAMP_FRAME: - fprintf_unfiltered (file, "SIGTRAMP_FRAME"); - return; + return "SIGTRAMP_FRAME"; + case ARCH_FRAME: - fprintf_unfiltered (file, "ARCH_FRAME"); - return; + return "ARCH_FRAME"; + case SENTINEL_FRAME: - fprintf_unfiltered (file, "SENTINEL_FRAME"); - return; + return "SENTINEL_FRAME"; + default: - fprintf_unfiltered (file, ""); - return; + return ""; }; } -static void -fprint_frame (struct ui_file *file, struct frame_info *fi) + /* See struct frame_info. */ + +std::string +frame_info::to_string () const { - if (fi == NULL) - { - fprintf_unfiltered (file, ""); - return; - } + const frame_info *fi = this; - fprintf_unfiltered (file, "{"); - fprintf_unfiltered (file, "level=%d", fi->level); - fprintf_unfiltered (file, ","); + std::string res; + + res += string_printf ("{level=%d,", fi->level); - fprintf_unfiltered (file, "type="); if (fi->unwind != NULL) - fprint_frame_type (file, fi->unwind->type); + res += string_printf ("type=%s,", frame_type_str (fi->unwind->type)); else - fprintf_unfiltered (file, ""); - fprintf_unfiltered (file, ","); + res += "type=,"; - fprintf_unfiltered (file, "unwind="); if (fi->unwind != NULL) - gdb_print_host_address (fi->unwind, file); + res += string_printf ("unwinder=\"%s\",", fi->unwind->name); else - fprintf_unfiltered (file, ""); - fprintf_unfiltered (file, ","); + res += "unwinder=,"; - fprintf_unfiltered (file, "pc="); if (fi->next == NULL || fi->next->prev_pc.status == CC_UNKNOWN) - fprintf_unfiltered (file, ""); + res += "pc=,"; else if (fi->next->prev_pc.status == CC_VALUE) - { - fprintf_unfiltered (file, "%s", hex_string (fi->next->prev_pc.value)); - if (fi->next->prev_pc.masked) - fprintf_unfiltered (file, "[PAC]"); - } + res += string_printf ("pc=%s%s,", hex_string (fi->next->prev_pc.value), + fi->next->prev_pc.masked ? "[PAC]" : ""); else if (fi->next->prev_pc.status == CC_NOT_SAVED) - val_print_not_saved (file); + res += "pc=,"; else if (fi->next->prev_pc.status == CC_UNAVAILABLE) - val_print_unavailable (file); - fprintf_unfiltered (file, ","); + res += "pc=,"; - fprintf_unfiltered (file, "id="); if (fi->this_id.p == frame_id_status::NOT_COMPUTED) - fprintf_unfiltered (file, ""); + res += "id=,"; else if (fi->this_id.p == frame_id_status::COMPUTING) - fprintf_unfiltered (file, ""); + res += "id=,"; else - fprint_frame_id (file, fi->this_id.value); - fprintf_unfiltered (file, ","); + res += string_printf ("id=%s,", fi->this_id.value.to_string ().c_str ()); - fprintf_unfiltered (file, "func="); if (fi->next != NULL && fi->next->prev_func.status == CC_VALUE) - fprintf_unfiltered (file, "%s", hex_string (fi->next->prev_func.addr)); + res += string_printf ("func=%s", hex_string (fi->next->prev_func.addr)); else - fprintf_unfiltered (file, ""); - fprintf_unfiltered (file, "}"); + res += "func="; + + res += "}"; + + return res; } /* Given FRAME, return the enclosing frame as found in real frames read-in from @@ -565,6 +560,8 @@ skip_tailcall_frames (struct frame_info *frame) static void compute_frame_id (struct frame_info *fi) { + FRAME_SCOPED_DEBUG_ENTER_EXIT; + gdb_assert (fi->this_id.p == frame_id_status::NOT_COMPUTED); unsigned int entry_generation = get_frame_cache_generation (); @@ -574,9 +571,7 @@ compute_frame_id (struct frame_info *fi) /* Mark this frame's id as "being computed. */ fi->this_id.p = frame_id_status::COMPUTING; - if (frame_debug) - fprintf_unfiltered (gdb_stdlog, "{ compute_frame_id (fi=%d) ", - fi->level); + frame_debug_printf ("fi=%d", fi->level); /* Find the unwinder. */ if (fi->unwind == NULL) @@ -591,12 +586,7 @@ compute_frame_id (struct frame_info *fi) /* Mark this frame's id as "computed". */ fi->this_id.p = frame_id_status::COMPUTED; - if (frame_debug) - { - fprintf_unfiltered (gdb_stdlog, "-> "); - fprint_frame_id (gdb_stdlog, fi->this_id.value); - fprintf_unfiltered (gdb_stdlog, " }\n"); - } + frame_debug_printf (" -> %s", fi->this_id.value.to_string ().c_str ()); } catch (const gdb_exception &ex) { @@ -747,12 +737,7 @@ frame_id_p (frame_id l) /* The frame is valid iff it has a valid stack address. */ bool p = l.stack_status != FID_STACK_INVALID; - if (frame_debug) - { - fprintf_unfiltered (gdb_stdlog, "{ frame_id_p (l="); - fprint_frame_id (gdb_stdlog, l); - fprintf_unfiltered (gdb_stdlog, ") -> %d }\n", p); - } + frame_debug_printf ("l=%s -> %d", l.to_string ().c_str (), p); return p; } @@ -795,14 +780,8 @@ frame_id_eq (frame_id l, frame_id r) /* Frames are equal. */ eq = true; - if (frame_debug) - { - fprintf_unfiltered (gdb_stdlog, "{ frame_id_eq (l="); - fprint_frame_id (gdb_stdlog, l); - fprintf_unfiltered (gdb_stdlog, ",r="); - fprint_frame_id (gdb_stdlog, r); - fprintf_unfiltered (gdb_stdlog, ") -> %d }\n", eq); - } + frame_debug_printf ("l=%s, r=%s -> %d", + l.to_string ().c_str (), r.to_string ().c_str (), eq); return eq; } @@ -878,14 +857,9 @@ frame_id_inner (struct gdbarch *gdbarch, struct frame_id l, struct frame_id r) different .code and/or .special address). */ inner = gdbarch_inner_than (gdbarch, l.stack_addr, r.stack_addr); - if (frame_debug) - { - fprintf_unfiltered (gdb_stdlog, "{ frame_id_inner (l="); - fprint_frame_id (gdb_stdlog, l); - fprintf_unfiltered (gdb_stdlog, ",r="); - fprint_frame_id (gdb_stdlog, r); - fprintf_unfiltered (gdb_stdlog, ") -> %d }\n", inner); - } + frame_debug_printf ("is l=%s inner than r=%s? %d", + l.to_string ().c_str (), r.to_string ().c_str (), + inner); return inner; } @@ -980,21 +954,15 @@ frame_unwind_pc (struct frame_info *this_frame) { this_frame->prev_pc.status = CC_UNAVAILABLE; - if (frame_debug) - fprintf_unfiltered (gdb_stdlog, - "{ frame_unwind_pc (this_frame=%d)" - " -> }\n", - this_frame->level); + frame_debug_printf ("this_frame=%d -> ", + 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)" - " -> }\n", - this_frame->level); + frame_debug_printf ("this_frame=%d -> ", + this_frame->level); } else throw; @@ -1004,12 +972,10 @@ frame_unwind_pc (struct frame_info *this_frame) { 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_debug_printf ("this_frame=%d -> %s", + this_frame->level, + hex_string (this_frame->prev_pc.value)); } } @@ -1052,21 +1018,18 @@ get_frame_func_if_available (frame_info *this_frame, CORE_ADDR *pc) if (!get_frame_address_in_block_if_available (this_frame, &addr_in_block)) { next_frame->prev_func.status = CC_UNAVAILABLE; - if (frame_debug) - fprintf_unfiltered (gdb_stdlog, - "{ get_frame_func (this_frame=%d)" - " -> unavailable }\n", - this_frame->level); + + frame_debug_printf ("this_frame=%d -> unavailable", + this_frame->level); } else { next_frame->prev_func.status = CC_VALUE; next_frame->prev_func.addr = get_pc_function_start (addr_in_block); - if (frame_debug) - fprintf_unfiltered (gdb_stdlog, - "{ get_frame_func (this_frame=%d) -> %s }\n", - this_frame->level, - hex_string (next_frame->prev_func.addr)); + + frame_debug_printf ("this_frame=%d -> %s", + this_frame->level, + hex_string (next_frame->prev_func.addr)); } } @@ -1193,7 +1156,7 @@ frame_register_unwind (frame_info *next_frame, int regnum, if (bufferp) { if (!*optimizedp && !*unavailablep) - memcpy (bufferp, value_contents_all (value), + memcpy (bufferp, value_contents_all (value).data (), TYPE_LENGTH (value_type (value))); else memset (bufferp, 0, TYPE_LENGTH (value_type (value))); @@ -1254,66 +1217,61 @@ get_frame_register (struct frame_info *frame, struct value * frame_unwind_register_value (frame_info *next_frame, int regnum) { - struct gdbarch *gdbarch; - struct value *value; + FRAME_SCOPED_DEBUG_ENTER_EXIT; gdb_assert (next_frame != NULL); - gdbarch = frame_unwind_arch (next_frame); - - if (frame_debug) - { - fprintf_unfiltered (gdb_stdlog, - "{ frame_unwind_register_value " - "(frame=%d,regnum=%d(%s),...) ", - next_frame->level, regnum, - user_reg_map_regnum_to_name (gdbarch, regnum)); - } + gdbarch *gdbarch = frame_unwind_arch (next_frame); + frame_debug_printf ("frame=%d, regnum=%d(%s)", + next_frame->level, regnum, + user_reg_map_regnum_to_name (gdbarch, regnum)); /* Find the unwinder. */ if (next_frame->unwind == NULL) frame_unwind_find_by_frame (next_frame, &next_frame->prologue_cache); /* Ask this frame to unwind its register. */ - value = next_frame->unwind->prev_register (next_frame, - &next_frame->prologue_cache, - regnum); + value *value = next_frame->unwind->prev_register (next_frame, + &next_frame->prologue_cache, + regnum); if (frame_debug) { - fprintf_unfiltered (gdb_stdlog, "->"); + string_file debug_file; + + gdb_printf (&debug_file, " ->"); if (value_optimized_out (value)) { - fprintf_unfiltered (gdb_stdlog, " "); - val_print_not_saved (gdb_stdlog); + gdb_printf (&debug_file, " "); + val_print_not_saved (&debug_file); } else { if (VALUE_LVAL (value) == lval_register) - fprintf_unfiltered (gdb_stdlog, " register=%d", - VALUE_REGNUM (value)); + gdb_printf (&debug_file, " register=%d", + VALUE_REGNUM (value)); else if (VALUE_LVAL (value) == lval_memory) - fprintf_unfiltered (gdb_stdlog, " address=%s", - paddress (gdbarch, - value_address (value))); + gdb_printf (&debug_file, " address=%s", + paddress (gdbarch, + value_address (value))); else - fprintf_unfiltered (gdb_stdlog, " computed"); + gdb_printf (&debug_file, " computed"); if (value_lazy (value)) - fprintf_unfiltered (gdb_stdlog, " lazy"); + gdb_printf (&debug_file, " lazy"); else { int i; - const gdb_byte *buf = value_contents (value); + gdb::array_view buf = value_contents (value); - fprintf_unfiltered (gdb_stdlog, " bytes="); - fprintf_unfiltered (gdb_stdlog, "["); + gdb_printf (&debug_file, " bytes="); + gdb_printf (&debug_file, "["); for (i = 0; i < register_size (gdbarch, regnum); i++) - fprintf_unfiltered (gdb_stdlog, "%02x", buf[i]); - fprintf_unfiltered (gdb_stdlog, "]"); + gdb_printf (&debug_file, "%02x", buf[i]); + gdb_printf (&debug_file, "]"); } } - fprintf_unfiltered (gdb_stdlog, " }\n"); + frame_debug_printf ("%s", debug_file.c_str ()); } return value; @@ -1330,7 +1288,6 @@ frame_unwind_register_signed (frame_info *next_frame, int regnum) { struct gdbarch *gdbarch = frame_unwind_arch (next_frame); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - int size = register_size (gdbarch, regnum); struct value *value = frame_unwind_register_value (next_frame, regnum); gdb_assert (value != NULL); @@ -1346,8 +1303,7 @@ frame_unwind_register_signed (frame_info *next_frame, int regnum) _("Register %d is not available"), regnum); } - LONGEST r = extract_signed_integer (value_contents_all (value), size, - byte_order); + LONGEST r = extract_signed_integer (value_contents_all (value), byte_order); release_value (value); return r; @@ -1380,8 +1336,8 @@ frame_unwind_register_unsigned (frame_info *next_frame, int regnum) _("Register %d is not available"), regnum); } - ULONGEST r = extract_unsigned_integer (value_contents_all (value), size, - byte_order); + ULONGEST r = extract_unsigned_integer (value_contents_all (value).data (), + size, byte_order); release_value (value); return r; @@ -1406,7 +1362,8 @@ read_frame_register_unsigned (frame_info *frame, int regnum, enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); int size = register_size (gdbarch, VALUE_REGNUM (regval)); - *val = extract_unsigned_integer (value_contents (regval), size, byte_order); + *val = extract_unsigned_integer (value_contents (regval).data (), size, + byte_order); return true; } @@ -1469,7 +1426,8 @@ deprecated_frame_register_read (frame_info *frame, int regnum, bool get_frame_register_bytes (frame_info *frame, int regnum, - CORE_ADDR offset, int len, gdb_byte *myaddr, + CORE_ADDR offset, + gdb::array_view buffer, int *optimizedp, int *unavailablep) { struct gdbarch *gdbarch = get_frame_arch (frame); @@ -1496,6 +1454,8 @@ get_frame_register_bytes (frame_info *frame, int regnum, break; /* This register is not available on this architecture. */ maxsize += thissize; } + + int len = buffer.size (); if (len > maxsize) error (_("Bad debug information detected: " "Attempt to read %d bytes from registers."), len); @@ -1508,6 +1468,8 @@ get_frame_register_bytes (frame_info *frame, int regnum, if (curr_len > len) curr_len = len; + gdb_byte *myaddr = buffer.data (); + if (curr_len == register_size (gdbarch, regnum)) { enum lval_type lval; @@ -1533,7 +1495,8 @@ get_frame_register_bytes (frame_info *frame, int regnum, return false; } - memcpy (myaddr, value_contents_all (value) + offset, curr_len); + memcpy (myaddr, value_contents_all (value).data () + offset, + curr_len); release_value (value); } @@ -1551,7 +1514,8 @@ get_frame_register_bytes (frame_info *frame, int regnum, void put_frame_register_bytes (struct frame_info *frame, int regnum, - CORE_ADDR offset, int len, const gdb_byte *myaddr) + CORE_ADDR offset, + gdb::array_view buffer) { struct gdbarch *gdbarch = get_frame_arch (frame); @@ -1562,6 +1526,7 @@ put_frame_register_bytes (struct frame_info *frame, int regnum, regnum++; } + int len = buffer.size (); /* Copy the data. */ while (len > 0) { @@ -1570,6 +1535,7 @@ put_frame_register_bytes (struct frame_info *frame, int regnum, if (curr_len > len) curr_len = len; + const gdb_byte *myaddr = buffer.data (); if (curr_len == register_size (gdbarch, regnum)) { put_frame_register (frame, regnum, myaddr); @@ -1580,9 +1546,10 @@ put_frame_register_bytes (struct frame_info *frame, int regnum, regnum); gdb_assert (value != NULL); - memcpy ((char *) value_contents_writeable (value) + offset, myaddr, - curr_len); - put_frame_register (frame, regnum, value_contents_raw (value)); + memcpy ((char *) value_contents_writeable (value).data () + offset, + myaddr, curr_len); + put_frame_register (frame, regnum, + value_contents_raw (value).data ()); release_value (value); } @@ -1615,12 +1582,9 @@ create_sentinel_frame (struct program_space *pspace, struct regcache *regcache) /* The sentinel frame has a special ID. */ frame->this_id.p = frame_id_status::COMPUTED; frame->this_id.value = sentinel_frame_id; - if (frame_debug) - { - fprintf_unfiltered (gdb_stdlog, "{ create_sentinel_frame (...) -> "); - fprint_frame (gdb_stdlog, frame); - fprintf_unfiltered (gdb_stdlog, " }\n"); - } + + frame_debug_printf (" -> %s", frame->to_string ().c_str ()); + return frame; } @@ -1826,7 +1790,7 @@ has_stack_frames () return false; /* ... or from a spinning thread. */ - if (tp->executing) + if (tp->executing ()) return false; } @@ -1944,12 +1908,7 @@ create_new_frame (CORE_ADDR addr, CORE_ADDR pc) { struct frame_info *fi; - if (frame_debug) - { - fprintf_unfiltered (gdb_stdlog, - "{ create_new_frame (addr=%s, pc=%s) ", - hex_string (addr), hex_string (pc)); - } + frame_debug_printf ("addr=%s, pc=%s", hex_string (addr), hex_string (pc)); fi = FRAME_OBSTACK_ZALLOC (struct frame_info); @@ -1974,12 +1933,7 @@ create_new_frame (CORE_ADDR addr, CORE_ADDR pc) fi->this_id.p = frame_id_status::COMPUTED; fi->this_id.value = frame_id_build (addr, pc); - if (frame_debug) - { - fprintf_unfiltered (gdb_stdlog, "-> "); - fprint_frame (gdb_stdlog, fi); - fprintf_unfiltered (gdb_stdlog, " }\n"); - } + frame_debug_printf (" -> %s", fi->to_string ().c_str ()); return fi; } @@ -2052,8 +2006,8 @@ reinit_frame_cache (void) sentinel_frame = NULL; /* Invalidate cache */ select_frame (NULL); frame_stash_invalidate (); - if (frame_debug) - fprintf_unfiltered (gdb_stdlog, "{ reinit_frame_cache () }\n"); + + frame_debug_printf ("generation=%d", frame_cache_generation); } /* Find where a register is saved (in memory or another register). @@ -2091,14 +2045,23 @@ frame_register_unwind_location (struct frame_info *this_frame, int regnum, outermost, with UNWIND_SAME_ID stop reason. Unlike the other validity tests, that compare THIS_FRAME and the next frame, we do this right after creating the previous frame, to avoid ever ending - up with two frames with the same id in the frame chain. */ + up with two frames with the same id in the frame chain. + + There is however, one case where this cycle detection is not desirable, + when asking for the previous frame of an inline frame, in this case, if + the previous frame is a duplicate and we return nullptr then we will be + unable to calculate the frame_id of the inline frame, this in turn + causes inline_frame_this_id() to fail. So for inline frames (and only + for inline frames), the previous frame will always be returned, even when it + has a duplicate frame_id. We're not worried about cycles in the frame + chain as, if the previous frame returned here has a duplicate frame_id, + then the frame_id of the inline frame, calculated based off the frame_id + of the previous frame, should also be a duplicate. */ static struct frame_info * -get_prev_frame_if_no_cycle (struct frame_info *this_frame) +get_prev_frame_maybe_check_cycle (struct frame_info *this_frame) { - struct frame_info *prev_frame; - - prev_frame = get_prev_frame_raw (this_frame); + struct frame_info *prev_frame = get_prev_frame_raw (this_frame); /* Don't compute the frame id of the current frame yet. Unwinding the sentinel frame can fail (e.g., if the thread is gone and we @@ -2117,16 +2080,47 @@ get_prev_frame_if_no_cycle (struct frame_info *this_frame) try { compute_frame_id (prev_frame); - if (!frame_stash_add (prev_frame)) + + bool cycle_detection_p = get_frame_type (this_frame) != INLINE_FRAME; + + /* This assert checks GDB's state with respect to calculating the + frame-id of THIS_FRAME, in the case where THIS_FRAME is an inline + frame. + + If THIS_FRAME is frame #0, and is an inline frame, then we put off + calculating the frame_id until we specifically make a call to + get_frame_id(). As a result we can enter this function in two + possible states. If GDB asked for the previous frame of frame #0 + then THIS_FRAME will be frame #0 (an inline frame), and the + frame_id will be in the NOT_COMPUTED state. However, if GDB asked + for the frame_id of frame #0, then, as getting the frame_id of an + inline frame requires us to get the frame_id of the previous + frame, we will still end up in here, and the frame_id status will + be COMPUTING. + + If, instead, THIS_FRAME is at a level greater than #0 then things + are simpler. For these frames we immediately compute the frame_id + when the frame is initially created, and so, for those frames, we + will always enter this function with the frame_id status of + COMPUTING. */ + gdb_assert (cycle_detection_p + || (this_frame->level > 0 + && (this_frame->this_id.p + == frame_id_status::COMPUTING)) + || (this_frame->level == 0 + && (this_frame->this_id.p + != frame_id_status::COMPUTED))); + + /* We must do the CYCLE_DETECTION_P check after attempting to add + PREV_FRAME into the cache; if PREV_FRAME is unique then we do want + it in the cache, but if it is a duplicate and CYCLE_DETECTION_P is + false, then we don't want to unlink it. */ + if (!frame_stash_add (prev_frame) && cycle_detection_p) { /* Another frame with the same id was already in the stash. We just detected a cycle. */ - if (frame_debug) - { - fprintf_unfiltered (gdb_stdlog, "-> "); - fprint_frame (gdb_stdlog, NULL); - fprintf_unfiltered (gdb_stdlog, " // this frame has same ID }\n"); - } + frame_debug_printf (" -> nullptr // this frame has same ID"); + this_frame->stop_reason = UNWIND_SAME_ID; /* Unlink. */ prev_frame->next = NULL; @@ -2155,30 +2149,30 @@ get_prev_frame_if_no_cycle (struct frame_info *this_frame) static struct frame_info * get_prev_frame_always_1 (struct frame_info *this_frame) { - struct gdbarch *gdbarch; + FRAME_SCOPED_DEBUG_ENTER_EXIT; gdb_assert (this_frame != NULL); - gdbarch = get_frame_arch (this_frame); if (frame_debug) { - fprintf_unfiltered (gdb_stdlog, "{ get_prev_frame_always (this_frame="); if (this_frame != NULL) - fprintf_unfiltered (gdb_stdlog, "%d", this_frame->level); + frame_debug_printf ("this_frame=%d", this_frame->level); else - fprintf_unfiltered (gdb_stdlog, ""); - fprintf_unfiltered (gdb_stdlog, ") "); + frame_debug_printf ("this_frame=nullptr"); } + struct gdbarch *gdbarch = get_frame_arch (this_frame); + /* Only try to do the unwind once. */ if (this_frame->prev_p) { - if (frame_debug) - { - fprintf_unfiltered (gdb_stdlog, "-> "); - fprint_frame (gdb_stdlog, this_frame->prev); - fprintf_unfiltered (gdb_stdlog, " // cached \n"); - } + if (this_frame->prev != nullptr) + frame_debug_printf (" -> %s // cached", + this_frame->prev->to_string ().c_str ()); + else + frame_debug_printf + (" -> nullptr // %s // cached", + frame_stop_reason_symbol_string (this_frame->stop_reason)); return this_frame->prev; } @@ -2198,7 +2192,7 @@ get_prev_frame_always_1 (struct frame_info *this_frame) until we have unwound all the way down to the previous non-inline frame. */ if (get_frame_type (this_frame) == INLINE_FRAME) - return get_prev_frame_if_no_cycle (this_frame); + return get_prev_frame_maybe_check_cycle (this_frame); /* If this_frame is the current frame, then compute and stash its frame id prior to fetching and computing the frame id of the @@ -2225,15 +2219,9 @@ get_prev_frame_always_1 (struct frame_info *this_frame) if (this_frame->stop_reason != UNWIND_NO_REASON) { - if (frame_debug) - { - enum unwind_stop_reason reason = this_frame->stop_reason; - - fprintf_unfiltered (gdb_stdlog, "-> "); - fprint_frame (gdb_stdlog, NULL); - fprintf_unfiltered (gdb_stdlog, " // %s }\n", - frame_stop_reason_symbol_string (reason)); - } + frame_debug_printf + (" -> nullptr // %s", + frame_stop_reason_symbol_string (this_frame->stop_reason)); return NULL; } @@ -2250,7 +2238,7 @@ get_prev_frame_always_1 (struct frame_info *this_frame) CORE_ADDR this_pc_in_block; struct minimal_symbol *morestack_msym; const char *morestack_name = NULL; - + /* gcc -fsplit-stack __morestack can continue the stack anywhere. */ this_pc_in_block = get_frame_address_in_block (this_frame); morestack_msym = lookup_minimal_symbol_by_pc (this_pc_in_block).minsym; @@ -2258,13 +2246,7 @@ get_prev_frame_always_1 (struct frame_info *this_frame) morestack_name = morestack_msym->linkage_name (); if (!morestack_name || strcmp (morestack_name, "__morestack") != 0) { - if (frame_debug) - { - fprintf_unfiltered (gdb_stdlog, "-> "); - fprint_frame (gdb_stdlog, NULL); - fprintf_unfiltered (gdb_stdlog, - " // this frame ID is inner }\n"); - } + frame_debug_printf (" -> nullptr // this frame ID is inner"); this_frame->stop_reason = UNWIND_INNER_ID; return NULL; } @@ -2304,20 +2286,14 @@ get_prev_frame_always_1 (struct frame_info *this_frame) if ((lval == lval_memory && lval == nlval && addr == naddr) || (lval == lval_register && lval == nlval && realnum == nrealnum)) { - if (frame_debug) - { - fprintf_unfiltered (gdb_stdlog, "-> "); - fprint_frame (gdb_stdlog, NULL); - fprintf_unfiltered (gdb_stdlog, " // no saved PC }\n"); - } - + frame_debug_printf (" -> nullptr // no saved PC"); this_frame->stop_reason = UNWIND_NO_SAVED_PC; this_frame->prev = NULL; return NULL; } } - return get_prev_frame_if_no_cycle (this_frame); + return get_prev_frame_maybe_check_cycle (this_frame); } /* Return a "struct frame_info" corresponding to the frame that called @@ -2412,12 +2388,7 @@ get_prev_frame_raw (struct frame_info *this_frame) this_frame->prev = prev_frame; prev_frame->next = this_frame; - if (frame_debug) - { - fprintf_unfiltered (gdb_stdlog, "-> "); - fprint_frame (gdb_stdlog, prev_frame); - fprintf_unfiltered (gdb_stdlog, " }\n"); - } + frame_debug_printf (" -> %s", prev_frame->to_string ().c_str ()); return prev_frame; } @@ -2430,12 +2401,10 @@ frame_debug_got_null_frame (struct frame_info *this_frame, { if (frame_debug) { - fprintf_unfiltered (gdb_stdlog, "{ get_prev_frame (this_frame="); if (this_frame != NULL) - fprintf_unfiltered (gdb_stdlog, "%d", this_frame->level); + frame_debug_printf ("this_frame=%d -> %s", this_frame->level, reason); else - fprintf_unfiltered (gdb_stdlog, ""); - fprintf_unfiltered (gdb_stdlog, ") -> // %s}\n", reason); + frame_debug_printf ("this_frame=nullptr -> %s", reason); } } @@ -2461,18 +2430,17 @@ inside_main_func (frame_info *this_frame) if (bs.symbol == nullptr) return false; - const struct block *block = SYMBOL_BLOCK_VALUE (bs.symbol); + const struct block *block = bs.symbol->value_block (); gdb_assert (block != nullptr); - sym_addr = BLOCK_START (block); + sym_addr = block->start (); } else - sym_addr = BMSYMBOL_VALUE_ADDRESS (msymbol); + sym_addr = msymbol.value_address (); /* Convert any function descriptor addresses into the actual function code address. */ - sym_addr - = gdbarch_convert_from_func_ptr_addr (get_frame_arch (this_frame), - sym_addr, current_top_target ()); + sym_addr = gdbarch_convert_from_func_ptr_addr + (get_frame_arch (this_frame), sym_addr, current_inferior ()->top_target ()); return sym_addr == get_frame_func (this_frame); } @@ -2502,6 +2470,8 @@ inside_entry_func (frame_info *this_frame) struct frame_info * get_prev_frame (struct frame_info *this_frame) { + FRAME_SCOPED_DEBUG_ENTER_EXIT; + CORE_ADDR frame_pc; int frame_pc_p; @@ -2518,9 +2488,9 @@ get_prev_frame (struct frame_info *this_frame) pcsqh register (space register for the instruction at the head of the instruction queue) cannot be written directly; the only way to set it is to branch to code that is in the target space. In order to implement - frame dummies on HPUX, the called function is made to jump back to where - the inferior was when the user function was called. If gdb was inside - the main function when we created the dummy frame, the dummy frame will + frame dummies on HPUX, the called function is made to jump back to where + the inferior was when the user function was called. If gdb was inside + the main function when we created the dummy frame, the dummy frame will point inside the main function. */ if (this_frame->level >= 0 && get_frame_type (this_frame) == NORMAL_FRAME @@ -2565,7 +2535,7 @@ get_prev_frame (struct frame_info *this_frame) That should provide a far better stopper than the current heuristics. */ /* NOTE: tausq/2004-10-09: this is needed if, for example, the compiler - applied tail-call optimizations to main so that a function called + applied tail-call optimizations to main so that a function called from main returns directly to the caller of main. Since we don't stop at main, we should at least stop at the entry point of the application. */ @@ -2595,22 +2565,6 @@ get_prev_frame (struct frame_info *this_frame) return get_prev_frame_always (this_frame); } -struct frame_id -get_prev_frame_id_by_id (struct frame_id id) -{ - struct frame_id prev_id; - struct frame_info *frame; - - frame = frame_find_by_id (id); - - if (frame != NULL) - prev_id = get_frame_id (get_prev_frame (frame)); - else - prev_id = null_frame_id; - - return prev_id; -} - CORE_ADDR get_frame_pc (struct frame_info *frame) { @@ -2745,10 +2699,10 @@ find_frame_sal (frame_info *frame) gdb_assert (sym); symtab_and_line sal; - if (SYMBOL_LINE (sym) != 0) + if (sym->line () != 0) { - sal.symtab = symbol_symtab (sym); - sal.line = SYMBOL_LINE (sym); + sal.symtab = sym->symtab (); + sal.line = sym->line (); } else /* If the symbol does not have a location, we don't know where @@ -2891,9 +2845,9 @@ get_frame_address_space (struct frame_info *frame) void get_frame_memory (struct frame_info *this_frame, CORE_ADDR addr, - gdb_byte *buf, int len) + gdb::array_view buffer) { - read_memory (addr, buf, len); + read_memory (addr, buffer.data (), buffer.size ()); } LONGEST @@ -2918,10 +2872,10 @@ get_frame_memory_unsigned (struct frame_info *this_frame, CORE_ADDR addr, bool safe_frame_unwind_memory (struct frame_info *this_frame, - CORE_ADDR addr, gdb_byte *buf, int len) + CORE_ADDR addr, gdb::array_view buffer) { /* NOTE: target_read_memory returns zero on success! */ - return target_read_memory (addr, buf, len) == 0; + return target_read_memory (addr, buffer.data (), buffer.size ()) == 0; } /* Architecture methods. */ @@ -2950,11 +2904,9 @@ frame_unwind_arch (struct frame_info *next_frame) next_frame->prev_arch.arch = arch; next_frame->prev_arch.p = true; - if (frame_debug) - fprintf_unfiltered (gdb_stdlog, - "{ frame_unwind_arch (next_frame=%d) -> %s }\n", - next_frame->level, - gdbarch_bfd_arch_info (arch)->printable_name); + frame_debug_printf ("next_frame=%d -> %s", + next_frame->level, + gdbarch_bfd_arch_info (arch)->printable_name); } return next_frame->prev_arch.arch; @@ -3172,18 +3124,18 @@ _initialize_frame () frame_stash_create (); - gdb::observers::target_changed.attach (frame_observer_target_changed); + gdb::observers::target_changed.attach (frame_observer_target_changed, + "frame"); - add_basic_prefix_cmd ("backtrace", class_maintenance, _("\ + add_setshow_prefix_cmd ("backtrace", class_maintenance, + _("\ Set backtrace specific variables.\n\ Configure backtrace variables such as the backtrace limit"), - &set_backtrace_cmdlist, "set backtrace ", - 0/*allow-unknown*/, &setlist); - add_show_prefix_cmd ("backtrace", class_maintenance, _("\ + _("\ Show backtrace specific variables.\n\ Show backtrace variables such as the backtrace limit."), - &show_backtrace_cmdlist, "show backtrace ", - 0/*allow-unknown*/, &showlist); + &set_backtrace_cmdlist, &show_backtrace_cmdlist, + &setlist, &showlist); add_setshow_uinteger_cmd ("limit", class_obscure, &user_set_backtrace_options.backtrace_limit, _("\ @@ -3201,11 +3153,11 @@ Literal \"unlimited\" or zero means no limit."), set_backtrace_option_defs, &set_backtrace_cmdlist, &show_backtrace_cmdlist); /* Debug this files internals. */ - add_setshow_zuinteger_cmd ("frame", class_maintenance, &frame_debug, _("\ + add_setshow_boolean_cmd ("frame", class_maintenance, &frame_debug, _("\ Set frame debugging."), _("\ Show frame debugging."), _("\ When non-zero, frame specific internal debugging is enabled."), - NULL, - show_frame_debug, - &setdebuglist, &showdebuglist); + NULL, + show_frame_debug, + &setdebuglist, &showdebuglist); }