|  | /* Traditional frame unwind support, for GDB the GNU Debugger. | 
|  |  | 
|  | Copyright (C) 2003-2023 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"		/* For "struct frame_id".  */ | 
|  |  | 
|  | 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 (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, | 
|  | 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 (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 (frame_info_ptr this_frame, | 
|  | trad_frame_saved_reg this_saved_regs[], | 
|  | int regnum); | 
|  |  | 
|  | #endif |