| /* 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 |