/* Definitions for dealing with stack frames, for GDB, the GNU debugger.
- Copyright (C) 1986-2020 Free Software Foundation, Inc.
+ Copyright (C) 1986-2021 Free Software Foundation, Inc.
This file is part of GDB.
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:
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. */
+ /* Stack address is invalid. */
FID_STACK_INVALID = 0,
/* Stack address is valid, and is found in the stack_addr field. */
/* Sentinel frame. */
FID_STACK_SENTINEL = 2,
+ /* Outer frame. Since a frame's stack address is typically defined as the
+ value the stack pointer had prior to the activation of the frame, an outer
+ frame doesn't have a stack address. The frame ids of frames inlined in the
+ outer frame are also of this type. */
+ FID_STACK_OUTER = 3,
+
/* 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). */
/* 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
+ 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.
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;
+
+ /* Return a string representation of this frame id. */
+ std::string to_string () const;
};
/* Save and restore the currently selected frame. */
private:
- /* The ID of the previously selected frame. */
+ /* The ID and level of the previously selected frame. */
struct frame_id m_fid;
+ int m_level;
+
+ /* 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. */
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);
+/* Returns true when L is a valid frame. */
+extern bool frame_id_p (frame_id l);
-/* Returns non-zero when L is a valid frame representing a frame made up by GDB
+/* 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 int frame_id_artificial_p (struct frame_id l);
-
-/* 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);
-
-/* 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);
+extern bool frame_id_artificial_p (frame_id l);
+/* Returns true when L and R identify the same frame. */
+extern bool frame_id_eq (frame_id l, frame_id r);
/* Frame types. Some are real, some are signal trampolines, and some
are completely artificial (dummy). */
/* 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);
-
-/* If there is a selected frame, return it. Otherwise, return NULL. */
-extern struct frame_info *get_selected_frame_if_set (void);
+extern struct frame_info *get_selected_frame (const char *message = nullptr);
-/* Select a specific frame. NULL, apparently implies re-select the
- inner most frame. */
+/* Select a specific frame. NULL implies re-select the inner most
+ frame. */
extern void select_frame (struct frame_info *);
+/* 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.
+
+ 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;
+
+/* 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;
+
+/* Lookup the frame_info object for the selected frame FRAME_ID /
+ FRAME_LEVEL and cache the result.
+
+ If FRAME_LEVEL > 0 and the originally selected frame isn't found,
+ warn and select the innermost (current) frame. */
+extern void lookup_selected_frame (frame_id frame_id, int frame_level);
+
/* 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 *);
/* 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 (frame_info *frame, CORE_ADDR *pc);
/* An address (not necessarily aligned to an instruction boundary)
that falls within THIS frame's code block.
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 (frame_info *this_frame,
+ CORE_ADDR *pc);
/* The frame's inner-most bound. AKA the stack-pointer. Confusingly
known as top-of-stack. */
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 (frame_info *fi, CORE_ADDR *);
/* Closely related to the resume address, various symbol table
attributes that are determined by the PC. Note that for a normal
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);
+extern bool read_frame_register_unsigned (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
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);
+extern bool get_frame_register_bytes (frame_info *frame, int regnum,
+ CORE_ADDR offset,
+ gdb::array_view<gdb_byte> buffer,
+ int *optimizedp, int *unavailablep);
-/* Write LEN bytes to one or multiple registers starting with REGNUM
- in frame FRAME, starting at OFFSET, into BUF. */
+/* Write bytes from BUFFER to one or multiple registers starting with REGNUM
+ in frame FRAME, starting at OFFSET. */
extern 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);
/* Unwind the PC. Strictly speaking return the resume address of the
calling frame. For GDB, `pc' is the resume address and not a
adaptor frames this should be ok. */
extern void get_frame_memory (struct frame_info *this_frame, CORE_ADDR addr,
- gdb_byte *buf, int len);
+ gdb::array_view<gdb_byte> buffer);
extern LONGEST get_frame_memory_signed (struct frame_info *this_frame,
CORE_ADDR memaddr, int len);
extern ULONGEST get_frame_memory_unsigned (struct frame_info *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 (frame_info *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 struct frame_info *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 (frame_info *frame, int regnum,
+ gdb_byte *buf);
/* From stack.c. */
/* 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 (frame_info *fi, const frame_unwind *unwinder);
/* Return the language of FRAME. */
/* 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 (struct frame_info *frame);