/* Cache and manage frames for GDB, the GNU debugger.
- Copyright (C) 1986-2021 Free Software Foundation, Inc.
+ Copyright (C) 1986-2022 Free Software Foundation, Inc.
This file is part of GDB.
#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"
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
/* 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". */
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". */
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". */
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=<unavailable>");
+ res += "stack=<unavailable>";
else if (id.stack_status == FID_STACK_SENTINEL)
- fprintf_unfiltered (file, "stack=<sentinel>");
+ res += "stack=<sentinel>";
else if (id.stack_status == FID_STACK_OUTER)
- fprintf_unfiltered (file, "stack=<outer>");
+ res += "stack=<outer>";
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, "<unknown type>");
- return;
+ return "<unknown type>";
};
}
-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, "<NULL frame>");
- 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, "<unknown>");
- fprintf_unfiltered (file, ",");
+ res += "type=<unknown>,";
- 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, "<unknown>");
- fprintf_unfiltered (file, ",");
+ res += "unwinder=<unknown>,";
- fprintf_unfiltered (file, "pc=");
if (fi->next == NULL || fi->next->prev_pc.status == CC_UNKNOWN)
- fprintf_unfiltered (file, "<unknown>");
+ res += "pc=<unknown>,";
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=<not saved>,";
else if (fi->next->prev_pc.status == CC_UNAVAILABLE)
- val_print_unavailable (file);
- fprintf_unfiltered (file, ",");
+ res += "pc=<unavailable>,";
- fprintf_unfiltered (file, "id=");
if (fi->this_id.p == frame_id_status::NOT_COMPUTED)
- fprintf_unfiltered (file, "<not computed>");
+ res += "id=<not computed>,";
else if (fi->this_id.p == frame_id_status::COMPUTING)
- fprintf_unfiltered (file, "<computing>");
+ res += "id=<computing>,";
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, "<unknown>");
- fprintf_unfiltered (file, "}");
+ res += "func=<unknown>";
+
+ res += "}";
+
+ return res;
}
/* Given FRAME, return the enclosing frame as found in real frames read-in from
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 ();
/* 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)
/* 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)
{
/* 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;
}
/* 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;
}
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;
}
{
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);
+ frame_debug_printf ("this_frame=%d -> <unavailable>",
+ 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);
+ frame_debug_printf ("this_frame=%d -> <not saved>",
+ this_frame->level);
}
else
throw;
{
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));
}
}
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));
}
}
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)));
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<const gdb_byte> 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;
{
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);
_("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;
_("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;
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;
}
bool
get_frame_register_bytes (frame_info *frame, int regnum,
- CORE_ADDR offset, int len, gdb_byte *myaddr,
+ CORE_ADDR offset,
+ gdb::array_view<gdb_byte> buffer,
int *optimizedp, int *unavailablep)
{
struct gdbarch *gdbarch = get_frame_arch (frame);
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);
if (curr_len > len)
curr_len = len;
+ gdb_byte *myaddr = buffer.data ();
+
if (curr_len == register_size (gdbarch, regnum))
{
enum lval_type lval;
return false;
}
- memcpy (myaddr, value_contents_all (value) + offset, curr_len);
+ memcpy (myaddr, value_contents_all (value).data () + offset,
+ curr_len);
release_value (value);
}
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<const gdb_byte> buffer)
{
struct gdbarch *gdbarch = get_frame_arch (frame);
regnum++;
}
+ int len = buffer.size ();
/* Copy the data. */
while (len > 0)
{
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);
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);
}
/* 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;
}
return false;
/* ... or from a spinning thread. */
- if (tp->executing)
+ if (tp->executing ())
return false;
}
{
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);
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;
}
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).
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
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;
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, "<NULL>");
- 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;
}
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
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;
}
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;
}
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
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;
}
{
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, "<NULL>");
- fprintf_unfiltered (gdb_stdlog, ") -> // %s}\n", reason);
+ frame_debug_printf ("this_frame=nullptr -> %s", reason);
}
}
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);
}
struct frame_info *
get_prev_frame (struct frame_info *this_frame)
{
+ FRAME_SCOPED_DEBUG_ENTER_EXIT;
+
CORE_ADDR frame_pc;
int frame_pc_p;
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)
{
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
void
get_frame_memory (struct frame_info *this_frame, CORE_ADDR addr,
- gdb_byte *buf, int len)
+ gdb::array_view<gdb_byte> buffer)
{
- read_memory (addr, buf, len);
+ read_memory (addr, buffer.data (), buffer.size ());
}
LONGEST
bool
safe_frame_unwind_memory (struct frame_info *this_frame,
- CORE_ADDR addr, gdb_byte *buf, int len)
+ CORE_ADDR addr, gdb::array_view<gdb_byte> 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. */
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;
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, _("\
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);
}