| /* Traditional frame unwind support, for GDB the GNU Debugger. |
| |
| Copyright (C) 2003-2024 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 TRAD_FRAME_H |
| #define TRAD_FRAME_H |
| |
| #include "frame.h" |
| |
| class frame_info_ptr; |
| struct regcache_map_entry; |
| struct trad_frame_cache; |
| |
| /* A simple, or traditional frame cache. |
| |
| The entire cache is populated in a single pass and then generic |
| routines are used to extract the various cache values. */ |
| |
| struct trad_frame_cache *trad_frame_cache_zalloc (const frame_info_ptr &); |
| |
| /* This frame's ID. */ |
| void trad_frame_set_id (struct trad_frame_cache *this_trad_cache, |
| struct frame_id this_id); |
| void trad_frame_get_id (struct trad_frame_cache *this_trad_cache, |
| struct frame_id *this_id); |
| void trad_frame_set_this_base (struct trad_frame_cache *this_trad_cache, |
| CORE_ADDR this_base); |
| CORE_ADDR trad_frame_get_this_base (struct trad_frame_cache *this_trad_cache); |
| |
| void trad_frame_set_reg_realreg (struct trad_frame_cache *this_trad_cache, |
| int regnum, int realreg); |
| void trad_frame_set_reg_addr (struct trad_frame_cache *this_trad_cache, |
| int regnum, CORE_ADDR addr); |
| void trad_frame_set_reg_regmap (struct trad_frame_cache *this_trad_cache, |
| const struct regcache_map_entry *regmap, |
| CORE_ADDR addr, size_t size); |
| void trad_frame_set_reg_value (struct trad_frame_cache *this_cache, |
| int regnum, LONGEST val); |
| |
| /* Given the cache in THIS_TRAD_CACHE, set the value of REGNUM to the bytes |
| contained in BYTES with size SIZE. */ |
| void trad_frame_set_reg_value_bytes (struct trad_frame_cache *this_trad_cache, |
| int regnum, |
| gdb::array_view<const gdb_byte> bytes); |
| |
| struct value *trad_frame_get_register (struct trad_frame_cache *this_trad_cache, |
| const frame_info_ptr &this_frame, |
| int regnum); |
| |
| /* Describes the kind of encoding a stored register has. */ |
| enum class trad_frame_saved_reg_kind |
| { |
| /* Register value is unknown. */ |
| UNKNOWN = 0, |
| /* Register value is a constant. */ |
| VALUE, |
| /* Register value is in another register. */ |
| REALREG, |
| /* Register value is at an address. */ |
| ADDR, |
| /* Register value is a sequence of bytes. */ |
| VALUE_BYTES |
| }; |
| |
| /* A struct that describes a saved register in a frame. */ |
| |
| struct trad_frame_saved_reg |
| { |
| /* Setters */ |
| |
| /* Encode that the saved register's value is constant VAL in the |
| trad-frame. */ |
| void set_value (LONGEST val) |
| { |
| m_kind = trad_frame_saved_reg_kind::VALUE; |
| m_reg.value = val; |
| } |
| |
| /* Encode that the saved register's value is stored in register REALREG. */ |
| void set_realreg (int realreg) |
| { |
| m_kind = trad_frame_saved_reg_kind::REALREG; |
| m_reg.realreg = realreg; |
| } |
| |
| /* Encode that the saved register's value is stored in memory at ADDR. */ |
| void set_addr (LONGEST addr) |
| { |
| m_kind = trad_frame_saved_reg_kind::ADDR; |
| m_reg.addr = addr; |
| } |
| |
| /* Encode that the saved register's value is unknown. */ |
| void set_unknown () |
| { |
| m_kind = trad_frame_saved_reg_kind::UNKNOWN; |
| } |
| |
| /* Encode that the saved register's value is stored as a sequence of bytes. |
| This is useful when the value is larger than what primitive types |
| can hold. */ |
| void set_value_bytes (gdb::array_view<const gdb_byte> bytes) |
| { |
| /* Allocate the space and copy the data bytes. */ |
| gdb_byte *data = FRAME_OBSTACK_CALLOC (bytes.size (), gdb_byte); |
| memcpy (data, bytes.data (), bytes.size ()); |
| |
| m_kind = trad_frame_saved_reg_kind::VALUE_BYTES; |
| m_reg.value_bytes = data; |
| } |
| |
| /* Getters */ |
| |
| LONGEST value () const |
| { |
| gdb_assert (m_kind == trad_frame_saved_reg_kind::VALUE); |
| return m_reg.value; |
| } |
| |
| int realreg () const |
| { |
| gdb_assert (m_kind == trad_frame_saved_reg_kind::REALREG); |
| return m_reg.realreg; |
| } |
| |
| LONGEST addr () const |
| { |
| gdb_assert (m_kind == trad_frame_saved_reg_kind::ADDR); |
| return m_reg.addr; |
| } |
| |
| const gdb_byte *value_bytes () const |
| { |
| gdb_assert (m_kind == trad_frame_saved_reg_kind::VALUE_BYTES); |
| return m_reg.value_bytes; |
| } |
| |
| /* Convenience functions, return true if the register has been |
| encoded as specified. Return false otherwise. */ |
| bool is_value () const |
| { |
| return m_kind == trad_frame_saved_reg_kind::VALUE; |
| } |
| |
| bool is_realreg () const |
| { |
| return m_kind == trad_frame_saved_reg_kind::REALREG; |
| } |
| |
| bool is_addr () const |
| { |
| return m_kind == trad_frame_saved_reg_kind::ADDR; |
| } |
| |
| bool is_unknown () const |
| { |
| return m_kind == trad_frame_saved_reg_kind::UNKNOWN; |
| } |
| |
| bool is_value_bytes () const |
| { |
| return m_kind == trad_frame_saved_reg_kind::VALUE_BYTES; |
| } |
| |
| private: |
| |
| trad_frame_saved_reg_kind m_kind; |
| |
| union { |
| LONGEST value; |
| int realreg; |
| LONGEST addr; |
| const gdb_byte *value_bytes; |
| } m_reg; |
| }; |
| |
| /* Reset the saved regs cache, setting register values to REALREG. */ |
| void trad_frame_reset_saved_regs (struct gdbarch *gdbarch, |
| trad_frame_saved_reg *regs); |
| |
| /* Return a freshly allocated (and initialized) trad_frame array. */ |
| trad_frame_saved_reg *trad_frame_alloc_saved_regs (const frame_info_ptr &); |
| trad_frame_saved_reg *trad_frame_alloc_saved_regs (struct gdbarch *); |
| |
| /* Given the trad_frame info, return the location of the specified |
| register. */ |
| struct value *trad_frame_get_prev_register (const frame_info_ptr &this_frame, |
| trad_frame_saved_reg this_saved_regs[], |
| int regnum); |
| |
| #endif |