| /* Definitions for a frame unwinder, for GDB, the GNU debugger. |
| |
| Copyright (C) 2003-2025 Free Software Foundation, Inc. |
| |
| This file is part of GDB. |
| |
| This program is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 3 of the License, or |
| (at your option) any later version. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
| |
| #ifndef GDB_FRAME_UNWIND_H |
| #define GDB_FRAME_UNWIND_H |
| |
| struct frame_data; |
| class frame_info_ptr; |
| struct frame_id; |
| struct frame_unwind; |
| struct gdbarch; |
| struct regcache; |
| struct value; |
| |
| #include "frame.h" |
| |
| /* The following unwind functions assume a chain of frames forming the |
| sequence: (outer) prev <-> this <-> next (inner). All the |
| functions are called with this frame's `struct frame_info' and |
| prologue cache. |
| |
| THIS frame's register values can be obtained by unwinding NEXT |
| frame's registers (a recursive operation). |
| |
| THIS frame's prologue cache can be used to cache information such |
| as where this frame's prologue stores the previous frame's |
| registers. */ |
| |
| /* Given THIS frame, take a whiff of its registers (namely |
| the PC and attributes) and if SELF is the applicable unwinder, |
| return non-zero. Possibly also initialize THIS_PROLOGUE_CACHE; but |
| only if returning 1. Initializing THIS_PROLOGUE_CACHE in other |
| cases (0 return) is invalid. In case of exception, the caller has |
| to set *THIS_PROLOGUE_CACHE to NULL. */ |
| |
| typedef int (frame_sniffer_ftype) (const struct frame_unwind *self, |
| const frame_info_ptr &this_frame, |
| void **this_prologue_cache); |
| |
| typedef unwind_stop_reason (frame_unwind_stop_reason_ftype) |
| (const frame_info_ptr &this_frame, void **this_prologue_cache); |
| |
| /* A default frame sniffer which always accepts the frame. Used by |
| fallback prologue unwinders. */ |
| |
| int default_frame_sniffer (const struct frame_unwind *self, |
| const frame_info_ptr &this_frame, |
| void **this_prologue_cache); |
| |
| /* A default stop_reason callback which always claims the frame is |
| unwindable. */ |
| |
| enum unwind_stop_reason |
| default_frame_unwind_stop_reason (const frame_info_ptr &this_frame, |
| void **this_cache); |
| |
| /* A default unwind_pc callback that simply unwinds the register identified |
| by GDBARCH_PC_REGNUM. */ |
| |
| extern CORE_ADDR default_unwind_pc (struct gdbarch *gdbarch, |
| const frame_info_ptr &next_frame); |
| |
| /* A default unwind_sp callback that simply unwinds the register identified |
| by GDBARCH_SP_REGNUM. */ |
| |
| extern CORE_ADDR default_unwind_sp (struct gdbarch *gdbarch, |
| const frame_info_ptr &next_frame); |
| |
| /* Assuming the frame chain: (outer) prev <-> this <-> next (inner); |
| use THIS frame, and through it the NEXT frame's register unwind |
| method, to determine the frame ID of THIS frame. |
| |
| A frame ID provides an invariant that can be used to re-identify an |
| instance of a frame. It is a combination of the frame's `base' and |
| the frame's function's code address. |
| |
| Traditionally, THIS frame's ID was determined by examining THIS |
| frame's function's prologue, and identifying the register/offset |
| used as THIS frame's base. |
| |
| Example: An examination of THIS frame's prologue reveals that, on |
| entry, it saves the PC(+12), SP(+8), and R1(+4) registers |
| (decrementing the SP by 12). Consequently, the frame ID's base can |
| be determined by adding 12 to the THIS frame's stack-pointer, and |
| the value of THIS frame's SP can be obtained by unwinding the NEXT |
| frame's SP. |
| |
| THIS_PROLOGUE_CACHE can be used to share any prolog analysis data |
| with the other unwind methods. Memory for that cache should be |
| allocated using FRAME_OBSTACK_ZALLOC(). */ |
| |
| typedef void (frame_this_id_ftype) (const frame_info_ptr &this_frame, |
| void **this_prologue_cache, |
| struct frame_id *this_id); |
| |
| /* Assuming the frame chain: (outer) prev <-> this <-> next (inner); |
| use THIS frame, and implicitly the NEXT frame's register unwind |
| method, to unwind THIS frame's registers (returning the value of |
| the specified register REGNUM in the previous frame). |
| |
| Traditionally, THIS frame's registers were unwound by examining |
| THIS frame's function's prologue and identifying which registers |
| that prolog code saved on the stack. |
| |
| Example: An examination of THIS frame's prologue reveals that, on |
| entry, it saves the PC(+12), SP(+8), and R1(+4) registers |
| (decrementing the SP by 12). Consequently, the value of the PC |
| register in the previous frame is found in memory at SP+12, and |
| THIS frame's SP can be obtained by unwinding the NEXT frame's SP. |
| |
| This function takes THIS_FRAME as an argument. It can find the |
| values of registers in THIS frame by calling get_frame_register |
| (THIS_FRAME), and reinvoke itself to find other registers in the |
| PREVIOUS frame by calling frame_unwind_register (THIS_FRAME). |
| |
| The result is a GDB value object describing the register value. It |
| may be a lazy reference to memory, a lazy reference to the value of |
| a register in THIS frame, or a non-lvalue. |
| |
| If the previous frame's register was not saved by THIS_FRAME and is |
| therefore undefined, return a wholly optimized-out not_lval value. |
| |
| THIS_PROLOGUE_CACHE can be used to share any prolog analysis data |
| with the other unwind methods. Memory for that cache should be |
| allocated using FRAME_OBSTACK_ZALLOC(). */ |
| |
| typedef value *(frame_prev_register_ftype) (const frame_info_ptr &this_frame, |
| void **this_prologue_cache, |
| int regnum); |
| |
| /* Deallocate extra memory associated with the frame cache if any. */ |
| |
| typedef void (frame_dealloc_cache_ftype) (frame_info *self, |
| void *this_cache); |
| |
| /* Assuming the frame chain: (outer) prev <-> this <-> next (inner); |
| use THIS frame, and implicitly the NEXT frame's register unwind |
| method, return PREV frame's architecture. */ |
| |
| typedef gdbarch *(frame_prev_arch_ftype) (const frame_info_ptr &this_frame, |
| void **this_prologue_cache); |
| |
| /* Unwinders are classified by what part of GDB code created it. */ |
| enum frame_unwind_class |
| { |
| /* This is mostly handled by core GDB code. */ |
| FRAME_UNWIND_GDB, |
| /* This unwinder was added by one of GDB's extension languages. */ |
| FRAME_UNWIND_EXTENSION, |
| /* The unwinder was created and mostly handles debug information. */ |
| FRAME_UNWIND_DEBUGINFO, |
| /* The unwinder was created and handles target dependent things. */ |
| FRAME_UNWIND_ARCH, |
| /* Meta enum value, to ensure we're always sent a valid unwinder class. */ |
| UNWIND_CLASS_NUMBER, |
| }; |
| |
| class frame_unwind |
| { |
| public: |
| frame_unwind (const char *name, frame_type type, frame_unwind_class uclass, |
| const frame_data *data) |
| : m_name (name), m_type (type), m_unwinder_class (uclass), |
| m_unwind_data (data) |
| { } |
| |
| const char *name () const |
| { return m_name; } |
| |
| frame_type type () const |
| { return m_type; } |
| |
| frame_unwind_class unwinder_class () const |
| { return m_unwinder_class; } |
| |
| const frame_data *unwind_data () const |
| { return m_unwind_data; } |
| |
| bool enabled () const |
| { return m_enabled; } |
| |
| void set_enabled (bool state) const |
| { m_enabled = state; } |
| |
| /* Default stop_reason implementation. It reports NO_REASON, unless the |
| frame is the outermost. */ |
| |
| virtual unwind_stop_reason stop_reason (const frame_info_ptr &this_frame, |
| void **this_prologue_cache) const |
| { |
| return default_frame_unwind_stop_reason (this_frame, this_prologue_cache); |
| } |
| |
| /* Default frame sniffer. Will always return that the unwinder |
| is able to unwind the frame. */ |
| |
| virtual int sniff (const frame_info_ptr &this_frame, |
| void **this_prologue_cache) const |
| { return 1; } |
| |
| /* Calculate the ID of the given frame using this unwinder. */ |
| |
| virtual void this_id (const frame_info_ptr &this_frame, |
| void **this_prologue_cache, |
| struct frame_id *id) const = 0; |
| |
| /* Get the value of a register in a previous frame. */ |
| |
| virtual struct value *prev_register (const frame_info_ptr &this_frame, |
| void **this_prologue_cache, |
| int regnum) const = 0; |
| |
| /* Properly deallocate the cache. */ |
| |
| virtual void dealloc_cache (frame_info *self, void *this_cache) const |
| { } |
| |
| /* Get the previous architecture. */ |
| |
| virtual gdbarch *prev_arch (const frame_info_ptr &this_frame, |
| void **this_prologue_cache) const |
| { return get_frame_arch (this_frame); } |
| |
| private: |
| |
| /* Name of the unwinder. Used to uniquely identify unwinders. */ |
| const char *m_name; |
| |
| /* The frame's type. Should this instead be a collection of |
| predicates that test the frame for various attributes? */ |
| frame_type m_type; |
| |
| /* What kind of unwinder is this. It generally follows from where |
| the unwinder was added or where it looks for information to do the |
| unwinding. */ |
| frame_unwind_class m_unwinder_class; |
| |
| /* Additional data used by the trampoline and python frame unwinders. */ |
| const frame_data *m_unwind_data; |
| |
| /* Whether this unwinder can be used when sniffing. */ |
| mutable bool m_enabled = true; |
| }; |
| |
| /* This is a legacy version of the frame unwinder. The original struct |
| used function pointers for callbacks, this updated version has a |
| method that just passes the parameters along to the callback |
| pointer. |
| Do not use this class for new unwinders. Instead, see other classes |
| that inherit from frame_unwind, such as the python unwinder. */ |
| struct frame_unwind_legacy : public frame_unwind |
| { |
| frame_unwind_legacy (const char *name, frame_type type, |
| frame_unwind_class uclass, |
| frame_unwind_stop_reason_ftype *stop_reason_func, |
| frame_this_id_ftype *this_id_func, |
| frame_prev_register_ftype *prev_register_func, |
| const struct frame_data *data, |
| frame_sniffer_ftype *sniffer_func, |
| frame_dealloc_cache_ftype *dealloc_cache_func = nullptr, |
| frame_prev_arch_ftype *prev_arch_func = nullptr) |
| : frame_unwind (name, type, uclass, data), m_stop_reason (stop_reason_func), |
| m_this_id (this_id_func), m_prev_register (prev_register_func), |
| m_sniffer (sniffer_func), m_dealloc_cache (dealloc_cache_func), |
| m_prev_arch (prev_arch_func) |
| { } |
| |
| /* This method just passes the parameters to the callback pointer. */ |
| |
| enum unwind_stop_reason stop_reason (const frame_info_ptr &this_frame, |
| void **this_prologue_cache) const override; |
| |
| /* This method just passes the parameters to the callback pointer. */ |
| |
| void this_id (const frame_info_ptr &this_frame, void **this_prologue_cache, |
| struct frame_id *id) const override; |
| |
| /* This method just passes the parameters to the callback pointer. */ |
| |
| struct value *prev_register (const frame_info_ptr &this_frame, |
| void **this_prologue_cache, |
| int regnum) const override; |
| |
| /* This method just passes the parameters to the callback pointer. */ |
| |
| int sniff (const frame_info_ptr &this_frame, |
| void **this_prologue_cache) const override; |
| |
| /* This method just passes the parameters to the callback pointer. |
| It is safe to call this method if no callback is installed, it |
| just turns into a noop. */ |
| |
| void dealloc_cache (frame_info *self, void *this_cache) const override; |
| |
| /* This method just passes the parameters to the callback pointer. */ |
| |
| struct gdbarch *prev_arch (const frame_info_ptr &this_frame, |
| void **this_prologue_cache) const override; |
| |
| private: |
| |
| frame_unwind_stop_reason_ftype *m_stop_reason; |
| frame_this_id_ftype *m_this_id; |
| frame_prev_register_ftype *m_prev_register; |
| frame_sniffer_ftype *m_sniffer; |
| frame_dealloc_cache_ftype *m_dealloc_cache; |
| frame_prev_arch_ftype *m_prev_arch; |
| }; |
| |
| /* Register a frame unwinder, _prepending_ it to the front of the |
| search list (so it is sniffed before previously registered |
| unwinders). By using a prepend, later calls can install unwinders |
| that override earlier calls. This allows, for instance, an OSABI |
| to install a more specific sigtramp unwinder that overrides the |
| traditional brute-force unwinder. */ |
| extern void frame_unwind_prepend_unwinder (struct gdbarch *, |
| const struct frame_unwind *); |
| |
| /* Add a frame sniffer to the list. The predicates are polled in the |
| order that they are appended. The initial list contains the dummy |
| frame sniffer. */ |
| |
| extern void frame_unwind_append_unwinder (struct gdbarch *gdbarch, |
| const struct frame_unwind *unwinder); |
| |
| /* Iterate through sniffers for THIS_FRAME frame until one returns with an |
| unwinder implementation. THIS_FRAME->UNWIND must be NULL, it will get set |
| by this function. Possibly initialize THIS_CACHE. */ |
| |
| extern void frame_unwind_find_by_frame (const frame_info_ptr &this_frame, |
| void **this_cache); |
| |
| /* Helper functions for value-based register unwinding. These return |
| a (possibly lazy) value of the appropriate type. */ |
| |
| /* Return a value which indicates that FRAME did not save REGNUM. */ |
| |
| value *frame_unwind_got_optimized (const frame_info_ptr &frame, int regnum); |
| |
| /* Return a value which indicates that FRAME copied REGNUM into |
| register NEW_REGNUM. */ |
| |
| value *frame_unwind_got_register (const frame_info_ptr &frame, int regnum, |
| int new_regnum); |
| |
| /* Return a value which indicates that FRAME saved REGNUM in memory at |
| ADDR. */ |
| |
| value *frame_unwind_got_memory (const frame_info_ptr &frame, int regnum, |
| CORE_ADDR addr); |
| |
| /* Return a value which indicates that FRAME's saved version of |
| REGNUM has a known constant (computed) value of VAL. */ |
| |
| value *frame_unwind_got_constant (const frame_info_ptr &frame, int regnum, |
| ULONGEST val); |
| |
| /* Return a value which indicates that FRAME's saved version of |
| REGNUM has a known constant (computed) value which is stored |
| inside BUF. */ |
| |
| value *frame_unwind_got_bytes (const frame_info_ptr &frame, int regnum, |
| gdb::array_view<const gdb_byte> buf); |
| |
| /* Return a value which indicates that FRAME's saved version of REGNUM |
| has a known constant (computed) value of ADDR. Convert the |
| CORE_ADDR to a target address if necessary. */ |
| |
| value *frame_unwind_got_address (const frame_info_ptr &frame, int regnum, |
| CORE_ADDR addr); |
| |
| #endif /* GDB_FRAME_UNWIND_H */ |