/* Definitions for dealing with stack frames, for GDB, the GNU debugger.
- Copyright (C) 1986-2017 Free Software Foundation, Inc.
+ Copyright (C) 1986-2024 Free Software Foundation, Inc.
This file is part of GDB.
#define FRAME_H 1
/* The following is the intended naming schema for frame functions.
- It isn't 100% consistent, but it is aproaching that. Frame naming
+ It isn't 100% consistent, but it is approaching that. Frame naming
schema:
Prefixes:
- get_frame_WHAT...(): Get WHAT from the THIS frame (functionaly
+ get_frame_WHAT...(): Get WHAT from the THIS frame (functionally
equivalent to THIS->next->unwind->what)
frame_unwind_WHAT...(): Unwind THIS frame's WHAT from the NEXT
strongly hinting at its unsafeness)
safe_....(): Safer version of various functions, doesn't throw an
- error (leave this for later?). Returns non-zero / non-NULL if the
- request succeeds, zero / NULL otherwize.
+ error (leave this for later?). Returns true / non-NULL if the request
+ succeeds, false / NULL otherwise.
Suffixes:
*/
-#include "language.h"
+#include "cli/cli-option.h"
+#include "frame-id.h"
+#include "gdbsupport/common-debug.h"
+#include "gdbsupport/intrusive_list.h"
struct symtab_and_line;
struct frame_unwind;
struct gdbarch;
struct ui_file;
struct ui_out;
+struct frame_print_options;
-/* Status of a given frame's stack. */
+/* The frame object. */
-enum frame_id_stack_status
-{
- /* Stack address is invalid. E.g., this frame is the outermost
- (i.e., _start), and the stack hasn't been setup yet. */
- FID_STACK_INVALID = 0,
- /* Stack address is valid, and is found in the stack_addr field. */
- FID_STACK_VALID = 1,
+/* Save and restore the currently selected frame. */
- /* Sentinel frame. */
- FID_STACK_SENTINEL = 2,
+class scoped_restore_selected_frame
+{
+public:
+ /* Save the currently selected frame. */
+ scoped_restore_selected_frame ();
- /* Stack address is unavailable. I.e., there's a valid stack, but
- we don't know where it is (because memory or registers we'd
- compute it from were not collected). */
- FID_STACK_UNAVAILABLE = -1
-};
+ /* Restore the currently selected frame. */
+ ~scoped_restore_selected_frame ();
-/* The frame object. */
+ DISABLE_COPY_AND_ASSIGN (scoped_restore_selected_frame);
-struct frame_info;
+private:
-/* The frame object's ID. This provides a per-frame unique identifier
- that can be used to relocate a `struct frame_info' after a target
- resume or a frame cache destruct. It of course assumes that the
- inferior hasn't unwound the stack past that frame. */
+ /* The ID and level of the previously selected frame. */
+ struct frame_id m_fid;
+ int m_level;
-struct frame_id
-{
- /* The frame's stack address. This shall be constant through out
- the lifetime of a frame. Note that this requirement applies to
- not just the function body, but also the prologue and (in theory
- at least) the epilogue. Since that value needs to fall either on
- the boundary, or within the frame's address range, the frame's
- outer-most address (the inner-most address of the previous frame)
- is used. Watch out for all the legacy targets that still use the
- function pointer register or stack pointer register. They are
- wrong.
-
- This field is valid only if frame_id.stack_status is
- FID_STACK_VALID. It will be 0 for other
- FID_STACK_... statuses. */
- CORE_ADDR stack_addr;
-
- /* The frame's code address. This shall be constant through out the
- lifetime of the frame. While the PC (a.k.a. resume address)
- changes as the function is executed, this code address cannot.
- Typically, it is set to the address of the entry point of the
- frame's function (as returned by get_frame_func).
-
- For inlined functions (INLINE_DEPTH != 0), this is the address of
- the first executed instruction in the block corresponding to the
- inlined function.
-
- This field is valid only if code_addr_p is true. Otherwise, this
- frame is considered to have a wildcard code address, i.e. one that
- matches every address value in frame comparisons. */
- CORE_ADDR code_addr;
-
- /* The frame's special address. This shall be constant through out the
- lifetime of the frame. This is used for architectures that may have
- frames that do not change the stack but are still distinct and have
- some form of distinct identifier (e.g. the ia64 which uses a 2nd
- stack for registers). This field is treated as unordered - i.e. will
- not be used in frame ordering comparisons.
-
- This field is valid only if special_addr_p is true. Otherwise, this
- frame is considered to have a wildcard special address, i.e. one that
- matches every address value in frame comparisons. */
- CORE_ADDR special_addr;
-
- /* Flags to indicate the above fields have valid contents. */
- ENUM_BITFIELD(frame_id_stack_status) stack_status : 3;
- unsigned int code_addr_p : 1;
- unsigned int special_addr_p : 1;
-
- /* It is non-zero for a frame made up by GDB without stack data
- representation in inferior, such as INLINE_FRAME or TAILCALL_FRAME.
- Caller of inlined function will have it zero, each more inner called frame
- will have it increasingly one, two etc. Similarly for TAILCALL_FRAME. */
- int artificial_depth;
+ /* Save/restore the language as well, because selecting a frame
+ changes the current language to the frame's language if "set
+ language auto". */
+ enum language m_lang;
};
-/* Methods for constructing and comparing Frame IDs. */
+/* Flag to control debugging. */
-/* For convenience. All fields are zero. This means "there is no frame". */
-extern const struct frame_id null_frame_id;
+extern bool frame_debug;
-/* Sentinel frame. */
-extern const struct frame_id sentinel_frame_id;
+/* Print a "frame" debug statement. */
-/* This means "there is no frame ID, but there is a frame". It should be
- replaced by best-effort frame IDs for the outermost frame, somehow.
- The implementation is only special_addr_p set. */
-extern const struct frame_id outer_frame_id;
+#define frame_debug_printf(fmt, ...) \
+ debug_prefixed_printf_cond (frame_debug, "frame", fmt, ##__VA_ARGS__)
-/* Flag to control debugging. */
+/* Print "frame" enter/exit debug statements. */
-extern unsigned int frame_debug;
+#define FRAME_SCOPED_DEBUG_ENTER_EXIT \
+ scoped_debug_enter_exit (frame_debug, "frame")
/* Construct a frame ID. The first parameter is the frame's constant
stack address (typically the outer-bound), and the second the
as the special identifier address are set to indicate wild cards. */
extern struct frame_id frame_id_build_wild (CORE_ADDR stack_addr);
-/* Returns non-zero when L is a valid frame (a valid frame has a
- non-zero .base). The outermost frame is valid even without an
- ID. */
-extern int frame_id_p (struct frame_id l);
+/* Construct a frame ID for a sentinel frame.
-/* Returns non-zero when L is a valid frame representing a frame made up by GDB
- without stack data representation in inferior, such as INLINE_FRAME or
- TAILCALL_FRAME. */
-extern int frame_id_artificial_p (struct frame_id l);
+ If either STACK_ADDR or CODE_ADDR is not 0, the ID represents a sentinel
+ frame for a user-created frame. STACK_ADDR and CODE_ADDR are the addresses
+ used to create the frame.
-/* Returns non-zero when L and R identify the same frame, or, if
- either L or R have a zero .func, then the same frame base. */
-extern int frame_id_eq (struct frame_id l, struct frame_id r);
+ If STACK_ADDR and CODE_ADDR are both 0, the ID represents a regular sentinel
+ frame (i.e. the "next" frame of the target's current frame). */
+extern frame_id frame_id_build_sentinel (CORE_ADDR stack_addr, CORE_ADDR code_addr);
-/* Write the internal representation of a frame ID on the specified
- stream. */
-extern void fprint_frame_id (struct ui_file *file, struct frame_id id);
+/* Returns true when L is a valid frame. */
+extern bool frame_id_p (frame_id l);
+/* Returns true when L is a valid frame representing a frame made up by GDB
+ without stack data representation in inferior, such as INLINE_FRAME or
+ TAILCALL_FRAME. */
+extern bool frame_id_artificial_p (frame_id l);
/* Frame types. Some are real, some are signal trampolines, and some
are completely artificial (dummy). */
SENTINEL_FRAME
};
+/* Return a string representation of TYPE. */
+
+extern const char *frame_type_str (frame_type type);
+
+/* A wrapper for "frame_info *". frame_info objects are invalidated
+ whenever reinit_frame_cache is called. This class arranges to
+ invalidate the pointer when appropriate. This is done to help
+ detect a GDB bug that was relatively common.
+
+ A small amount of code must still operate on raw pointers, so a
+ "get" method is provided. However, you should normally not use
+ this in new code. */
+
+class frame_info_ptr : public intrusive_list_node<frame_info_ptr>
+{
+public:
+ /* Create a frame_info_ptr from a raw pointer. */
+ explicit frame_info_ptr (struct frame_info *ptr);
+
+ /* Create a null frame_info_ptr. */
+ frame_info_ptr ()
+ {
+ frame_list.push_back (*this);
+ }
+
+ frame_info_ptr (std::nullptr_t)
+ {
+ frame_list.push_back (*this);
+ }
+
+ frame_info_ptr (const frame_info_ptr &other)
+ : m_ptr (other.m_ptr),
+ m_cached_id (other.m_cached_id),
+ m_cached_level (other.m_cached_level)
+ {
+ frame_list.push_back (*this);
+ }
+
+ frame_info_ptr (frame_info_ptr &&other)
+ : m_ptr (other.m_ptr),
+ m_cached_id (other.m_cached_id),
+ m_cached_level (other.m_cached_level)
+ {
+ other.m_ptr = nullptr;
+ other.m_cached_id = null_frame_id;
+ other.m_cached_level = invalid_level;
+ frame_list.push_back (*this);
+ }
+
+ ~frame_info_ptr ()
+ {
+ /* If this node has static storage, it should be be deleted before
+ frame_list. */
+ frame_list.erase (frame_list.iterator_to (*this));
+ }
+
+ frame_info_ptr &operator= (const frame_info_ptr &other)
+ {
+ m_ptr = other.m_ptr;
+ m_cached_id = other.m_cached_id;
+ m_cached_level = other.m_cached_level;
+ return *this;
+ }
+
+ frame_info_ptr &operator= (std::nullptr_t)
+ {
+ m_ptr = nullptr;
+ m_cached_id = null_frame_id;
+ m_cached_level = invalid_level;
+ return *this;
+ }
+
+ frame_info_ptr &operator= (frame_info_ptr &&other)
+ {
+ m_ptr = other.m_ptr;
+ m_cached_id = other.m_cached_id;
+ m_cached_level = other.m_cached_level;
+ other.m_ptr = nullptr;
+ other.m_cached_id = null_frame_id;
+ other.m_cached_level = invalid_level;
+ return *this;
+ }
+
+ frame_info *operator-> () const
+ { return this->reinflate (); }
+
+ /* Fetch the underlying pointer. Note that new code should
+ generally not use this -- avoid it if at all possible. */
+ frame_info *get () const
+ {
+ if (this->is_null ())
+ return nullptr;
+
+ return this->reinflate ();
+ }
+
+ /* Return true if this object is empty (does not wrap a frame_info
+ object). */
+
+ bool is_null () const
+ {
+ return m_cached_level == this->invalid_level;
+ };
+
+ /* This exists for compatibility with pre-existing code that checked
+ a "frame_info *" using "!". */
+ bool operator! () const
+ {
+ return this->is_null ();
+ }
+
+ /* This exists for compatibility with pre-existing code that checked
+ a "frame_info *" like "if (ptr)". */
+ explicit operator bool () const
+ {
+ return !this->is_null ();
+ }
+
+ /* Invalidate this pointer. */
+ void invalidate ()
+ {
+ m_ptr = nullptr;
+ }
+
+private:
+ /* We sometimes need to construct frame_info_ptr objects around the
+ sentinel_frame, which has level -1. Therefore, make the invalid frame
+ level value -2. */
+ static constexpr int invalid_level = -2;
+
+ /* Use the cached frame level and id to reinflate the pointer, and return
+ it. */
+ frame_info *reinflate () const;
+
+ /* The underlying pointer. */
+ mutable frame_info *m_ptr = nullptr;
+
+ /* The frame_id of the underlying pointer.
+
+ For the current target frames (frames with level 0, obtained through
+ get_current_frame), we don't save the frame id, we leave it at
+ null_frame_id. For user-created frames (also with level 0, but created
+ with create_new_frame), we do save the id. */
+ frame_id m_cached_id = null_frame_id;
+
+ /* The frame level of the underlying pointer. */
+ int m_cached_level = invalid_level;
+
+ /* All frame_info_ptr objects are kept on an intrusive list.
+ This keeps their construction and destruction costs
+ reasonably small. */
+ static intrusive_list<frame_info_ptr> frame_list;
+
+ /* A friend so it can invalidate the pointers. */
+ friend void reinit_frame_cache ();
+};
+
+static inline bool
+operator== (const frame_info *self, const frame_info_ptr &other)
+{
+ if (self == nullptr || other.is_null ())
+ return self == nullptr && other.is_null ();
+
+ return self == other.get ();
+}
+
+static inline bool
+operator== (const frame_info_ptr &self, const frame_info_ptr &other)
+{
+ if (self.is_null () || other.is_null ())
+ return self.is_null () && other.is_null ();
+
+ return self.get () == other.get ();
+}
+
+static inline bool
+operator== (const frame_info_ptr &self, const frame_info *other)
+{
+ if (self.is_null () || other == nullptr)
+ return self.is_null () && other == nullptr;
+
+ return self.get () == other;
+}
+
+static inline bool
+operator!= (const frame_info *self, const frame_info_ptr &other)
+{
+ return !(self == other);
+}
+
+static inline bool
+operator!= (const frame_info_ptr &self, const frame_info_ptr &other)
+{
+ return !(self == other);
+}
+
+static inline bool
+operator!= (const frame_info_ptr &self, const frame_info *other)
+{
+ return !(self == other);
+}
+
/* For every stopped thread, GDB tracks two frames: current and
selected. Current frame is the inner most frame of the selected
thread. Selected frame is the one being examined by the GDB
/* On demand, create the inner most frame using information found in
the inferior. If the inner most frame can't be created, throw an
error. */
-extern struct frame_info *get_current_frame (void);
+extern frame_info_ptr get_current_frame (void);
/* Does the current target interface have enough state to be able to
query the current inferior for frame info, and is the inferior in a
state where that is possible? */
-extern int has_stack_frames (void);
+extern bool has_stack_frames ();
/* Invalidates the frame cache (this function should have been called
invalidate_cached_frames).
modifies the target invalidating the frame cache). */
extern void reinit_frame_cache (void);
-/* On demand, create the selected frame and then return it. If the
- selected frame can not be created, this function prints then throws
- an error. When MESSAGE is non-NULL, use it for the error message,
- otherwize use a generic error message. */
+/* Return the selected frame. Always returns non-NULL. If there
+ isn't an inferior sufficient for creating a frame, an error is
+ thrown. When MESSAGE is non-NULL, use it for the error message,
+ otherwise use a generic error message. */
/* FIXME: cagney/2002-11-28: At present, when there is no selected
frame, this function always returns the current (inner most) frame.
It should instead, when a thread has previously had its frame
selected (but not resumed) and the frame cache invalidated, find
and then return that thread's previously selected frame. */
-extern struct frame_info *get_selected_frame (const char *message);
+extern frame_info_ptr get_selected_frame (const char *message = nullptr);
+
+/* Select a specific frame. */
+extern void select_frame (const frame_info_ptr &);
+
+/* Save the frame ID and frame level of the selected frame in FRAME_ID
+ and FRAME_LEVEL, to be restored later with restore_selected_frame.
-/* If there is a selected frame, return it. Otherwise, return NULL. */
-extern struct frame_info *get_selected_frame_if_set (void);
+ This is preferred over getting the same info out of
+ get_selected_frame directly because this function does not create
+ the selected-frame's frame_info object if it hasn't been created
+ yet, and thus is more efficient and doesn't throw. */
+extern void save_selected_frame (frame_id *frame_id, int *frame_level)
+ noexcept;
-/* Select a specific frame. NULL, apparently implies re-select the
- inner most frame. */
-extern void select_frame (struct frame_info *);
+/* Restore selected frame as saved with save_selected_frame.
+
+ Does not try to find the corresponding frame_info object. Instead
+ the next call to get_selected_frame will look it up and cache the
+ result.
+
+ This function does not throw. It is designed to be safe to called
+ from the destructors of RAII types. */
+extern void restore_selected_frame (frame_id frame_id, int frame_level)
+ noexcept;
/* Given a FRAME, return the next (more inner, younger) or previous
(more outer, older) frame. */
-extern struct frame_info *get_prev_frame (struct frame_info *);
-extern struct frame_info *get_next_frame (struct frame_info *);
+extern frame_info_ptr get_prev_frame (const frame_info_ptr &);
+extern frame_info_ptr get_next_frame (const frame_info_ptr &);
/* Like get_next_frame(), but allows return of the sentinel frame. NULL
is never returned. */
-extern struct frame_info *get_next_frame_sentinel_okay (struct frame_info *);
+extern frame_info_ptr get_next_frame_sentinel_okay (const frame_info_ptr &);
/* Return a "struct frame_info" corresponding to the frame that called
THIS_FRAME. Returns NULL if there is no such frame.
Unlike get_prev_frame, this function always tries to unwind the
frame. */
-extern struct frame_info *get_prev_frame_always (struct frame_info *);
+extern frame_info_ptr get_prev_frame_always (const frame_info_ptr &);
/* Given a frame's ID, relocate the frame. Returns NULL if the frame
is not found. */
-extern struct frame_info *frame_find_by_id (struct frame_id id);
-
-/* Given a frame's ID, find the previous frame's ID. Returns null_frame_id
- if the frame is not found. */
-extern struct frame_id get_prev_frame_id_by_id (struct frame_id id);
+extern frame_info_ptr frame_find_by_id (frame_id id);
/* Base attributes of a frame: */
this frame.
This replaced: frame->pc; */
-extern CORE_ADDR get_frame_pc (struct frame_info *);
+extern CORE_ADDR get_frame_pc (const frame_info_ptr &);
/* Same as get_frame_pc, but return a boolean indication of whether
the PC is actually available, instead of throwing an error. */
-extern int get_frame_pc_if_available (struct frame_info *frame,
- CORE_ADDR *pc);
+extern bool get_frame_pc_if_available (const frame_info_ptr &frame, CORE_ADDR *pc);
/* An address (not necessarily aligned to an instruction boundary)
that falls within THIS frame's code block.
function returns the frame's PC-1 which "should" be an address in
the frame's block. */
-extern CORE_ADDR get_frame_address_in_block (struct frame_info *this_frame);
+extern CORE_ADDR get_frame_address_in_block (const frame_info_ptr &this_frame);
/* Same as get_frame_address_in_block, but returns a boolean
indication of whether the frame address is determinable (when the
PC is unavailable, it will not be), instead of possibly throwing an
error trying to read an unavailable PC. */
-extern int
- get_frame_address_in_block_if_available (struct frame_info *this_frame,
- CORE_ADDR *pc);
+extern bool get_frame_address_in_block_if_available (const frame_info_ptr &this_frame,
+ CORE_ADDR *pc);
/* The frame's inner-most bound. AKA the stack-pointer. Confusingly
known as top-of-stack. */
-extern CORE_ADDR get_frame_sp (struct frame_info *);
+extern CORE_ADDR get_frame_sp (const frame_info_ptr &);
/* Following on from the `resume' address. Return the entry point
address of the function containing that resume address, or zero if
that function isn't known. */
-extern CORE_ADDR get_frame_func (struct frame_info *fi);
+extern CORE_ADDR get_frame_func (const frame_info_ptr &fi);
/* Same as get_frame_func, but returns a boolean indication of whether
the frame function is determinable (when the PC is unavailable, it
will not be), instead of possibly throwing an error trying to read
an unavailable PC. */
-extern int get_frame_func_if_available (struct frame_info *fi, CORE_ADDR *);
+extern bool get_frame_func_if_available (const frame_info_ptr &fi, CORE_ADDR *);
/* Closely related to the resume address, various symbol table
attributes that are determined by the PC. Note that for a normal
find_frame_symtab(), find_frame_function(). Each will need to be
carefully considered to determine if the real intent was for it to
apply to the PC or the adjusted PC. */
-extern symtab_and_line find_frame_sal (frame_info *frame);
+extern symtab_and_line find_frame_sal (const frame_info_ptr &frame);
/* Set the current source and line to the location given by frame
FRAME, if possible. */
-void set_current_sal_from_frame (struct frame_info *);
+void set_current_sal_from_frame (const frame_info_ptr &);
/* Return the frame base (what ever that is) (DEPRECATED).
This replaced: frame->frame; */
-extern CORE_ADDR get_frame_base (struct frame_info *);
+extern CORE_ADDR get_frame_base (const frame_info_ptr &);
-/* Return the per-frame unique identifer. Can be used to relocate a
+/* Return the per-frame unique identifier. Can be used to relocate a
frame after a frame cache flush (and other similar operations). If
- FI is NULL, return the null_frame_id.
-
- NOTE: kettenis/20040508: These functions return a structure. On
- platforms where structures are returned in static storage (vax,
- m68k), this may trigger compiler bugs in code like:
-
- if (frame_id_eq (get_frame_id (l), get_frame_id (r)))
-
- where the return value from the first get_frame_id (l) gets
- overwritten by the second get_frame_id (r). Please avoid writing
- code like this. Use code like:
-
- struct frame_id id = get_frame_id (l);
- if (frame_id_eq (id, get_frame_id (r)))
-
- instead, since that avoids the bug. */
-extern struct frame_id get_frame_id (struct frame_info *fi);
-extern struct frame_id get_stack_frame_id (struct frame_info *fi);
-extern struct frame_id frame_unwind_caller_id (struct frame_info *next_frame);
+ FI is NULL, return the null_frame_id. */
+extern frame_id get_frame_id (const frame_info_ptr &fi);
+extern frame_id get_stack_frame_id (const frame_info_ptr &fi);
+extern frame_id frame_unwind_caller_id (const frame_info_ptr &next_frame);
/* Assuming that a frame is `normal', return its base-address, or 0 if
the information isn't available. NOTE: This address is really only
meaningful to the frame's high-level debug info. */
-extern CORE_ADDR get_frame_base_address (struct frame_info *);
+extern CORE_ADDR get_frame_base_address (const frame_info_ptr &);
/* Assuming that a frame is `normal', return the base-address of the
local variables, or 0 if the information isn't available. NOTE:
This address is really only meaningful to the frame's high-level
debug info. Typically, the argument and locals share a single
base-address. */
-extern CORE_ADDR get_frame_locals_address (struct frame_info *);
+extern CORE_ADDR get_frame_locals_address (const frame_info_ptr &);
/* Assuming that a frame is `normal', return the base-address of the
parameter list, or 0 if that information isn't available. NOTE:
This address is really only meaningful to the frame's high-level
debug info. Typically, the argument and locals share a single
base-address. */
-extern CORE_ADDR get_frame_args_address (struct frame_info *);
+extern CORE_ADDR get_frame_args_address (const frame_info_ptr &);
/* The frame's level: 0 for innermost, 1 for its caller, ...; or -1
for an invalid frame). */
-extern int frame_relative_level (struct frame_info *fi);
+extern int frame_relative_level (const frame_info_ptr &fi);
/* Return the frame's type. */
-extern enum frame_type get_frame_type (struct frame_info *);
+extern enum frame_type get_frame_type (const frame_info_ptr &);
/* Return the frame's program space. */
-extern struct program_space *get_frame_program_space (struct frame_info *);
+extern struct program_space *get_frame_program_space (const frame_info_ptr &);
/* Unwind THIS frame's program space from the NEXT frame. */
-extern struct program_space *frame_unwind_program_space (struct frame_info *);
+extern struct program_space *frame_unwind_program_space (const frame_info_ptr &);
+
+class address_space;
/* Return the frame's address space. */
-extern struct address_space *get_frame_address_space (struct frame_info *);
+extern const address_space *get_frame_address_space (const frame_info_ptr &);
+
+/* A frame may have a "static link". That is, in some languages, a
+ nested function may have access to variables from the enclosing
+ block and frame. This function looks for a frame's static link.
+ If found, returns the corresponding frame; otherwise, returns a
+ null frame_info_ptr. */
+extern frame_info_ptr frame_follow_static_link (const frame_info_ptr &frame);
/* For frames where we can not unwind further, describe why. */
/* Return the reason why we can't unwind past this frame. */
-enum unwind_stop_reason get_frame_unwind_stop_reason (struct frame_info *);
+enum unwind_stop_reason get_frame_unwind_stop_reason (const frame_info_ptr &);
/* Translate a reason code to an informative string. This converts the
generic stop reason codes into a generic string describing the code.
Should only be called for frames that don't have a previous frame. */
-const char *frame_stop_reason_string (struct frame_info *);
+const char *frame_stop_reason_string (const frame_info_ptr &);
/* Unwind the stack frame so that the value of REGNUM, in the previous
(up, older) frame is returned. If VALUEP is NULL, don't
fetch/compute the value. Instead just return the location of the
value. */
-extern void frame_register_unwind (struct frame_info *frame, int regnum,
+extern void frame_register_unwind (const frame_info_ptr &frame, int regnum,
int *optimizedp, int *unavailablep,
enum lval_type *lvalp,
CORE_ADDR *addrp, int *realnump,
fetch fails. The value methods never return NULL, but usually
do return a lazy value. */
-extern void frame_unwind_register (struct frame_info *frame,
+extern void frame_unwind_register (const frame_info_ptr &next_frame,
int regnum, gdb_byte *buf);
-extern void get_frame_register (struct frame_info *frame,
+extern void get_frame_register (const frame_info_ptr &frame,
int regnum, gdb_byte *buf);
-struct value *frame_unwind_register_value (struct frame_info *frame,
+struct value *frame_unwind_register_value (const frame_info_ptr &next_frame,
int regnum);
-struct value *get_frame_register_value (struct frame_info *frame,
+struct value *get_frame_register_value (const frame_info_ptr &frame,
int regnum);
-extern LONGEST frame_unwind_register_signed (struct frame_info *frame,
+extern LONGEST frame_unwind_register_signed (const frame_info_ptr &next_frame,
int regnum);
-extern LONGEST get_frame_register_signed (struct frame_info *frame,
+extern LONGEST get_frame_register_signed (const frame_info_ptr &frame,
int regnum);
-extern ULONGEST frame_unwind_register_unsigned (struct frame_info *frame,
- int regnum);
-extern ULONGEST get_frame_register_unsigned (struct frame_info *frame,
+extern ULONGEST frame_unwind_register_unsigned
+ (const frame_info_ptr &next_frame, int regnum);
+extern ULONGEST get_frame_register_unsigned (const frame_info_ptr &frame,
int regnum);
/* Read a register from this, or unwind a register from the next
get_frame_register_value, that do not throw if the result is
optimized out or unavailable. */
-extern int read_frame_register_unsigned (struct frame_info *frame,
- int regnum, ULONGEST *val);
-
-/* Get the value of the register that belongs to this FRAME. This
- function is a wrapper to the call sequence ``frame_register_unwind
- (get_next_frame (FRAME))''. As per frame_register_unwind(), if
- VALUEP is NULL, the registers value is not fetched/computed. */
-
-extern void frame_register (struct frame_info *frame, int regnum,
- int *optimizedp, int *unavailablep,
- enum lval_type *lvalp,
- CORE_ADDR *addrp, int *realnump,
- gdb_byte *valuep);
-
-/* The reverse. Store a register value relative to the specified
- frame. Note: this call makes the frame's state undefined. The
- register and frame caches must be flushed. */
-extern void put_frame_register (struct frame_info *frame, int regnum,
- const gdb_byte *buf);
-
-/* Read LEN bytes from one or multiple registers starting with REGNUM
- in frame FRAME, starting at OFFSET, into BUF. If the register
- contents are optimized out or unavailable, set *OPTIMIZEDP,
- *UNAVAILABLEP accordingly. */
-extern int get_frame_register_bytes (struct frame_info *frame, int regnum,
- CORE_ADDR offset, int len,
- gdb_byte *myaddr,
- int *optimizedp, int *unavailablep);
-
-/* Write LEN bytes to one or multiple registers starting with REGNUM
- in frame FRAME, starting at OFFSET, into BUF. */
-extern void put_frame_register_bytes (struct frame_info *frame, int regnum,
- CORE_ADDR offset, int len,
- const gdb_byte *myaddr);
+extern bool read_frame_register_unsigned (const frame_info_ptr &frame,
+ int regnum, ULONGEST *val);
+
+/* The reverse. Store a register value relative to NEXT_FRAME's previous frame.
+ Note: this call makes the frame's state undefined. The register and frame
+ caches must be flushed. */
+extern void put_frame_register (const frame_info_ptr &next_frame, int regnum,
+ gdb::array_view<const gdb_byte> buf);
+
+/* Read LEN bytes from one or multiple registers starting with REGNUM in
+ NEXT_FRAME's previous frame, starting at OFFSET, into BUF. If the register
+ contents are optimized out or unavailable, set *OPTIMIZEDP, *UNAVAILABLEP
+ accordingly. */
+extern bool get_frame_register_bytes (const frame_info_ptr &next_frame,
+ int regnum, CORE_ADDR offset,
+ gdb::array_view<gdb_byte> buffer,
+ int *optimizedp, int *unavailablep);
+
+/* Write bytes from BUFFER to one or multiple registers starting with REGNUM
+ in NEXT_FRAME's previous frame, starting at OFFSET. */
+extern void put_frame_register_bytes (const frame_info_ptr &next_frame,
+ int regnum, CORE_ADDR offset,
+ gdb::array_view<const gdb_byte> buffer);
/* Unwind the PC. Strictly speaking return the resume address of the
calling frame. For GDB, `pc' is the resume address and not a
specific register. */
-extern CORE_ADDR frame_unwind_caller_pc (struct frame_info *frame);
+extern CORE_ADDR frame_unwind_caller_pc (const frame_info_ptr &next_frame);
/* Discard the specified frame. Restoring the registers to the state
of the caller. */
-extern void frame_pop (struct frame_info *frame);
+extern void frame_pop (const frame_info_ptr &frame);
/* Return memory from the specified frame. A frame knows its thread /
LWP and hence can find its way down to a target. The assumption
If architecture / memory changes are always separated by special
adaptor frames this should be ok. */
-extern void get_frame_memory (struct frame_info *this_frame, CORE_ADDR addr,
- gdb_byte *buf, int len);
-extern LONGEST get_frame_memory_signed (struct frame_info *this_frame,
+extern void get_frame_memory (const frame_info_ptr &this_frame, CORE_ADDR addr,
+ gdb::array_view<gdb_byte> buffer);
+extern LONGEST get_frame_memory_signed (const frame_info_ptr &this_frame,
CORE_ADDR memaddr, int len);
-extern ULONGEST get_frame_memory_unsigned (struct frame_info *this_frame,
+extern ULONGEST get_frame_memory_unsigned (const frame_info_ptr &this_frame,
CORE_ADDR memaddr, int len);
-/* Same as above, but return non-zero when the entire memory read
- succeeds, zero otherwize. */
-extern int safe_frame_unwind_memory (struct frame_info *this_frame,
- CORE_ADDR addr, gdb_byte *buf, int len);
+/* Same as above, but return true zero when the entire memory read
+ succeeds, false otherwise. */
+extern bool safe_frame_unwind_memory (const frame_info_ptr &this_frame, CORE_ADDR addr,
+ gdb::array_view<gdb_byte> buffer);
/* Return this frame's architecture. */
-extern struct gdbarch *get_frame_arch (struct frame_info *this_frame);
+extern gdbarch *get_frame_arch (const frame_info_ptr &this_frame);
/* Return the previous frame's architecture. */
-extern struct gdbarch *frame_unwind_arch (struct frame_info *frame);
+extern gdbarch *frame_unwind_arch (const frame_info_ptr &next_frame);
/* Return the previous frame's architecture, skipping inline functions. */
-extern struct gdbarch *frame_unwind_caller_arch (struct frame_info *frame);
+extern gdbarch *frame_unwind_caller_arch (const frame_info_ptr &next_frame);
-/* Values for the source flag to be used in print_frame_info_base(). */
+/* Values for the source flag to be used in print_frame_info ().
+ For all the cases below, the address is never printed if
+ 'set print address' is off. When 'set print address' is on,
+ the address is printed if the program counter is not at the
+ beginning of the source line of the frame
+ and PRINT_WHAT is != LOC_AND_ADDRESS. */
enum print_what
- {
- /* Print only the source line, like in stepi. */
- SRC_LINE = -1,
- /* Print only the location, i.e. level, address (sometimes)
- function, args, file, line, line num. */
+ {
+ /* Print only the address, source line, like in stepi. */
+ SRC_LINE = -1,
+ /* Print only the location, i.e. level, address,
+ function, args (as controlled by 'set print frame-arguments'),
+ file, line, line num. */
LOCATION,
/* Print both of the above. */
- SRC_AND_LOC,
- /* Print location only, but always include the address. */
- LOC_AND_ADDRESS
+ SRC_AND_LOC,
+ /* Print location only, print the address even if the program counter
+ is at the beginning of the source line. */
+ LOC_AND_ADDRESS,
+ /* Print only level and function,
+ i.e. location only, without address, file, line, line num. */
+ SHORT_LOCATION
};
/* Allocate zero initialized memory from the frame cache obstack.
#define FRAME_OBSTACK_CALLOC(NUMBER,TYPE) \
((TYPE *) frame_obstack_zalloc ((NUMBER) * sizeof (TYPE)))
+class readonly_detached_regcache;
/* Create a regcache, and copy the frame's registers into it. */
-std::unique_ptr<struct regcache> frame_save_as_regcache
- (struct frame_info *this_frame);
+std::unique_ptr<readonly_detached_regcache> frame_save_as_regcache
+ (const frame_info_ptr &this_frame);
-extern const struct block *get_frame_block (struct frame_info *,
+extern const struct block *get_frame_block (const frame_info_ptr &,
CORE_ADDR *addr_in_block);
/* Return the `struct block' that belongs to the selected thread's
extern const struct block *get_selected_block (CORE_ADDR *addr_in_block);
-extern struct symbol *get_frame_function (struct frame_info *);
+extern struct symbol *get_frame_function (const frame_info_ptr &);
extern CORE_ADDR get_pc_function_start (CORE_ADDR);
-extern struct frame_info *find_relative_frame (struct frame_info *, int *);
+extern frame_info_ptr find_relative_frame (frame_info_ptr, int *);
/* Wrapper over print_stack_frame modifying current_uiout with UIOUT for
the function call. */
extern void print_stack_frame_to_uiout (struct ui_out *uiout,
- struct frame_info *, int print_level,
+ const frame_info_ptr &, int print_level,
enum print_what print_what,
int set_current_sal);
-extern void print_stack_frame (struct frame_info *, int print_level,
+extern void print_stack_frame (const frame_info_ptr &, int print_level,
enum print_what print_what,
int set_current_sal);
-extern void print_frame_info (struct frame_info *, int print_level,
+extern void print_frame_info (const frame_print_options &fp_opts,
+ const frame_info_ptr &, int print_level,
enum print_what print_what, int args,
int set_current_sal);
-extern struct frame_info *block_innermost_frame (const struct block *);
+extern frame_info_ptr block_innermost_frame (const struct block *);
-extern int deprecated_frame_register_read (struct frame_info *frame, int regnum,
- gdb_byte *buf);
+extern bool deprecated_frame_register_read (const frame_info_ptr &frame, int regnum,
+ gdb_byte *buf);
/* From stack.c. */
+/* The possible choices of "set print frame-arguments". */
+extern const char print_frame_arguments_all[];
+extern const char print_frame_arguments_scalars[];
+extern const char print_frame_arguments_none[];
+
+/* The possible choices of "set print frame-info". */
+extern const char print_frame_info_auto[];
+extern const char print_frame_info_source_line[];
+extern const char print_frame_info_location[];
+extern const char print_frame_info_source_and_location[];
+extern const char print_frame_info_location_and_address[];
+extern const char print_frame_info_short_location[];
+
+/* The possible choices of "set print entry-values". */
extern const char print_entry_values_no[];
extern const char print_entry_values_only[];
extern const char print_entry_values_preferred[];
extern const char print_entry_values_both[];
extern const char print_entry_values_compact[];
extern const char print_entry_values_default[];
-extern const char *print_entry_values;
+
+/* Data for the frame-printing "set print" settings exposed as command
+ options. */
+
+struct frame_print_options
+{
+ const char *print_frame_arguments = print_frame_arguments_scalars;
+ const char *print_frame_info = print_frame_info_auto;
+ const char *print_entry_values = print_entry_values_default;
+
+ /* If true, don't invoke pretty-printers for frame
+ arguments. */
+ bool print_raw_frame_arguments;
+};
+
+/* The values behind the global "set print ..." settings. */
+extern frame_print_options user_frame_print_options;
/* Inferior function parameter value read in from a frame. */
struct frame_arg
{
/* Symbol for this parameter used for example for its name. */
- struct symbol *sym;
+ struct symbol *sym = nullptr;
/* Value of the parameter. It is NULL if ERROR is not NULL; if both VAL and
ERROR are NULL this parameter's value should not be printed. */
- struct value *val;
+ struct value *val = nullptr;
/* String containing the error message, it is more usually NULL indicating no
- error occured reading this parameter. */
- char *error;
+ error occurred reading this parameter. */
+ gdb::unique_xmalloc_ptr<char> error;
/* One of the print_entry_values_* entries as appropriate specifically for
this frame_arg. It will be different from print_entry_values. With
value - print_entry_values_compact is not permitted fi ui_out_is_mi_like_p
(in such case print_entry_values_no and print_entry_values_only is used
for each parameter kind specifically. */
- const char *entry_kind;
+ const char *entry_kind = nullptr;
};
-extern void read_frame_arg (struct symbol *sym, struct frame_info *frame,
+extern void read_frame_arg (const frame_print_options &fp_opts,
+ symbol *sym, const frame_info_ptr &frame,
struct frame_arg *argp,
struct frame_arg *entryargp);
-extern void read_frame_local (struct symbol *sym, struct frame_info *frame,
+extern void read_frame_local (struct symbol *sym, const frame_info_ptr &frame,
struct frame_arg *argp);
-extern void info_args_command (char *, int);
+extern void info_args_command (const char *, int);
-extern void info_locals_command (char *, int);
+extern void info_locals_command (const char *, int);
-extern void return_command (char *, int);
+extern void return_command (const char *, int);
/* Set FRAME's unwinder temporarily, so that we can call a sniffer.
If sniffing fails, the caller should be sure to call
frame_cleanup_after_sniffer. */
-extern void frame_prepare_for_sniffer (struct frame_info *frame,
+extern void frame_prepare_for_sniffer (const frame_info_ptr &frame,
const struct frame_unwind *unwind);
/* Clean up after a failed (wrong unwinder) attempt to unwind past
FRAME. */
-extern void frame_cleanup_after_sniffer (struct frame_info *frame);
+extern void frame_cleanup_after_sniffer (const frame_info_ptr &frame);
/* Notes (cagney/2002-11-27, drow/2003-09-06):
This function calls get_selected_frame if the inferior should have a
frame, or returns NULL otherwise. */
-extern struct frame_info *deprecated_safe_get_selected_frame (void);
+extern frame_info_ptr deprecated_safe_get_selected_frame (void);
/* Create a frame using the specified BASE and PC. */
-extern struct frame_info *create_new_frame (CORE_ADDR base, CORE_ADDR pc);
+extern frame_info_ptr create_new_frame (CORE_ADDR base, CORE_ADDR pc);
/* Return true if the frame unwinder for frame FI is UNWINDER; false
otherwise. */
-extern int frame_unwinder_is (struct frame_info *fi,
- const struct frame_unwind *unwinder);
+extern bool frame_unwinder_is (const frame_info_ptr &fi, const frame_unwind *unwinder);
/* Return the language of FRAME. */
-extern enum language get_frame_language (struct frame_info *frame);
+extern enum language get_frame_language (const frame_info_ptr &frame);
/* Return the first non-tailcall frame above FRAME or FRAME if it is not a
tailcall frame. Return NULL if FRAME is the start of a tailcall-only
chain. */
-extern struct frame_info *skip_tailcall_frames (struct frame_info *frame);
+extern frame_info_ptr skip_tailcall_frames (const frame_info_ptr &frame);
/* Return the first frame above FRAME or FRAME of which the code is
writable. */
-extern struct frame_info *skip_unwritable_frames (struct frame_info *frame);
+extern frame_info_ptr skip_unwritable_frames (const frame_info_ptr &frame);
+
+/* Data for the "set backtrace" settings. */
+
+struct set_backtrace_options
+{
+ /* Flag to indicate whether backtraces should continue past
+ main. */
+ bool backtrace_past_main = false;
+
+ /* Flag to indicate whether backtraces should continue past
+ entry. */
+ bool backtrace_past_entry = false;
+
+ /* Upper bound on the number of backtrace levels. Note this is not
+ exposed as a command option, because "backtrace" and "frame
+ apply" already have other means to set a frame count limit. */
+ unsigned int backtrace_limit = UINT_MAX;
+};
+
+/* The corresponding option definitions. */
+extern const gdb::option::option_def set_backtrace_option_defs[2];
+
+/* The values behind the global "set backtrace ..." settings. */
+extern set_backtrace_options user_set_backtrace_options;
+
+/* Get the number of calls to reinit_frame_cache. */
+
+unsigned int get_frame_cache_generation ();
+
+/* Mark that the PC value is masked for the previous frame. */
+
+extern void set_frame_previous_pc_masked (const frame_info_ptr &frame);
+
+/* Get whether the PC value is masked for the given frame. */
+
+extern bool get_frame_pc_masked (const frame_info_ptr &frame);
+
#endif /* !defined (FRAME_H) */