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