aboutsummaryrefslogtreecommitdiff
path: root/gdb/trad-frame.h
diff options
context:
space:
mode:
authorLuis Machado <luis.machado@linaro.org>2020-12-22 17:45:21 -0300
committerLuis Machado <luis.machado@linaro.org>2021-01-04 12:18:31 -0300
commit098caef485a4ece6096e6cdbb4cd9726e4a13386 (patch)
treebc5808e3f19fbcdf402c9c5e11a52dacff679412 /gdb/trad-frame.h
parentdbb078f66ecfe2d50fd3e03463b5b206a8eed243 (diff)
downloadgdb-098caef485a4ece6096e6cdbb4cd9726e4a13386.zip
gdb-098caef485a4ece6096e6cdbb4cd9726e4a13386.tar.gz
gdb-098caef485a4ece6096e6cdbb4cd9726e4a13386.tar.bz2
Refactor struct trad_frame_saved_regs
The following patch drops the overloading going on with the trad_frame_saved_reg struct and defines a new struct with a KIND enum and a union of different fields. The new struct looks like this: struct trad_frame_saved_reg { setters/getters ... private: trad_frame_saved_reg_kind m_kind; union { LONGEST value; int realreg; LONGEST addr; const gdb_byte *value_bytes; } m_reg; }; And the enums look like this: /* 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 }; The patch also adds setters/getters and updates all the users of the old struct. It is worth mentioning that due to the previous overloaded nature of the fields, some tdep files like to store negative offsets and indexes in the ADDR field, so I kept the ADDR as LONGEST instead of CORE_ADDR. Those cases may be better supported by a new enum entry. I have not addressed those cases in this patch to prevent unwanted breakage, given I have no way to test some of the targets. But it would be nice to clean those up eventually. The change to frame-unwind.* is to constify the parameter being passed to the unwinding functions, given we now accept a "const gdb_byte *" for value bytes. Tested on aarch64-linux/Ubuntu 20.04/18.04 and by building GDB with --enable-targets=all. gdb/ChangeLog: 2021-01-04 Luis Machado <luis.machado@linaro.org> Update all users of trad_frame_saved_reg to use the new member functions. Remote all struct keywords from declarations of trad_frame_saved_reg types, except on forward declarations. * aarch64-tdep.c: Update. * alpha-mdebug-tdep.c: Update. * alpha-tdep.c: Update. * arc-tdep.c: Update. * arm-tdep.c: Update. * avr-tdep.c: Update. * cris-tdep.c: Update. * csky-tdep.c: Update. * frv-tdep.c: Update. * hppa-linux-tdep.c: Update. * hppa-tdep.c: Update. * hppa-tdep.h: Update. * lm32-tdep.c: Update. * m32r-linux-tdep.c: Update. * m32r-tdep.c: Update. * m68hc11-tdep.c: Update. * mips-tdep.c: Update. * moxie-tdep.c: Update. * riscv-tdep.c: Update. * rs6000-tdep.c: Update. * s390-linux-tdep.c: Update. * s390-tdep.c: Update. * score-tdep.c: Update. * sparc-netbsd-tdep.c: Update. * sparc-sol2-tdep.c: Update. * sparc64-fbsd-tdep.c: Update. * sparc64-netbsd-tdep.c: Update. * sparc64-obsd-tdep.c: Update. * sparc64-sol2-tdep.c: Update. * tilegx-tdep.c: Update. * v850-tdep.c: Update. * vax-tdep.c: Update. * frame-unwind.c (frame_unwind_got_bytes): Make parameter const. * frame-unwind.h (frame_unwind_got_bytes): Likewise. * trad-frame.c: Update. Remove TF_REG_* enum. (trad_frame_alloc_saved_regs): Add a static assertion to check for a trivially-constructible struct. (trad_frame_reset_saved_regs): Adjust to use member function. (trad_frame_value_p): Likewise. (trad_frame_addr_p): Likewise. (trad_frame_realreg_p): Likewise. (trad_frame_value_bytes_p): Likewise. (trad_frame_set_value): Likewise. (trad_frame_set_realreg): Likewise. (trad_frame_set_addr): Likewise. (trad_frame_set_unknown): Likewise. (trad_frame_set_value_bytes): Likewise. (trad_frame_get_prev_register): Likewise. * trad-frame.h: Update. (trad_frame_saved_reg_kind): New enum. (struct trad_frame_saved_reg) <addr, realreg, data>: Remove. <m_kind, m_reg>: New member fields. <set_value, set_realreg, set_addr, set_unknown, set_value_bytes> <kind, value, realreg, addr, value_bytes, is_value, is_realreg> <is_addr, is_unknown, is_value_bytes>: New member functions.
Diffstat (limited to 'gdb/trad-frame.h')
-rw-r--r--gdb/trad-frame.h173
1 files changed, 131 insertions, 42 deletions
diff --git a/gdb/trad-frame.h b/gdb/trad-frame.h
index 2df10dc..cdc937c 100644
--- a/gdb/trad-frame.h
+++ b/gdb/trad-frame.h
@@ -62,88 +62,177 @@ struct value *trad_frame_get_register (struct trad_frame_cache *this_trad_cache,
struct frame_info *this_frame,
int regnum);
-/* A traditional saved regs table, indexed by REGNUM, encoding where
- the value of REGNUM for the previous frame can be found in this
- frame.
-
- The table is initialized with an identity encoding (ADDR == -1,
- REALREG == REGNUM) indicating that the value of REGNUM in the
- previous frame can be found in register REGNUM (== REALREG) in this
- frame.
-
- The initial encoding can then be changed:
-
- Modify ADDR (REALREG >= 0, ADDR != -1) to indicate that the value
- of register REGNUM in the previous frame can be found in memory at
- ADDR in this frame (addr_p, !realreg_p, !value_p).
-
- Modify REALREG (REALREG >= 0, ADDR == -1) to indicate that the
- value of register REGNUM in the previous frame is found in register
- REALREG in this frame (!addr_p, realreg_p, !value_p).
-
- Call trad_frame_set_value (REALREG == -1) to indicate that the
- value of register REGNUM in the previous frame is found in ADDR
- (!addr_p, !realreg_p, value_p).
+/* 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
+};
- Call trad_frame_set_unknown (REALREG == -2) to indicate that the
- register's value is not known. */
+/* A struct that describes a saved register in a frame. */
struct trad_frame_saved_reg
{
- LONGEST addr; /* A CORE_ADDR fits in a longest. */
- int realreg;
- /* Register data (for values that don't fit in ADDR). */
- gdb_byte *data;
+ /* 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 (const gdb_byte *value_bytes)
+ {
+ m_kind = trad_frame_saved_reg_kind::VALUE_BYTES;
+ m_reg.value_bytes = value_bytes;
+ }
+
+ /* 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;
};
/* Encode REGNUM value in the trad-frame. */
-void trad_frame_set_value (struct trad_frame_saved_reg this_saved_regs[],
+void trad_frame_set_value (trad_frame_saved_reg this_saved_regs[],
int regnum, LONGEST val);
/* Encode REGNUM is in REALREG in the trad-frame. */
-void trad_frame_set_realreg (struct trad_frame_saved_reg this_saved_regs[],
+void trad_frame_set_realreg (trad_frame_saved_reg this_saved_regs[],
int regnum, int realreg);
/* Encode REGNUM is at address ADDR in the trad-frame. */
-void trad_frame_set_addr (struct trad_frame_saved_reg this_trad_cache[],
+void trad_frame_set_addr (trad_frame_saved_reg this_trad_cache[],
int regnum, CORE_ADDR addr);
/* Mark REGNUM as unknown. */
-void trad_frame_set_unknown (struct trad_frame_saved_reg this_saved_regs[],
+void trad_frame_set_unknown (trad_frame_saved_reg this_saved_regs[],
int regnum);
/* Encode REGNUM value in the trad-frame as a sequence of bytes. This is
useful when the value is larger than what primitive types can hold. */
-void trad_frame_set_value_bytes (struct trad_frame_saved_reg this_saved_regs[],
+void trad_frame_set_value_bytes (trad_frame_saved_reg this_saved_regs[],
int regnum, const gdb_byte *bytes,
size_t size);
/* Convenience functions, return non-zero if the register has been
encoded as specified. */
-int trad_frame_value_p (struct trad_frame_saved_reg this_saved_regs[],
+int trad_frame_value_p (trad_frame_saved_reg this_saved_regs[],
int regnum);
-int trad_frame_addr_p (struct trad_frame_saved_reg this_saved_regs[],
+int trad_frame_addr_p (trad_frame_saved_reg this_saved_regs[],
int regnum);
-int trad_frame_realreg_p (struct trad_frame_saved_reg this_saved_regs[],
+int trad_frame_realreg_p (trad_frame_saved_reg this_saved_regs[],
int regnum);
/* Return TRUE if REGNUM is stored as a sequence of bytes, and FALSE
otherwise. */
-bool trad_frame_value_bytes_p (struct trad_frame_saved_reg this_saved_regs[],
+bool trad_frame_value_bytes_p (trad_frame_saved_reg this_saved_regs[],
int regnum);
-/* Reset the save regs cache, setting register values to -1. */
+/* Reset the saved regs cache, setting register values to -1. */
void trad_frame_reset_saved_regs (struct gdbarch *gdbarch,
- struct trad_frame_saved_reg *regs);
+ trad_frame_saved_reg *regs);
/* Return a freshly allocated (and initialized) trad_frame array. */
-struct trad_frame_saved_reg *trad_frame_alloc_saved_regs (struct frame_info *);
-struct trad_frame_saved_reg *trad_frame_alloc_saved_regs (struct gdbarch *);
+trad_frame_saved_reg *trad_frame_alloc_saved_regs (struct frame_info *);
+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 (struct frame_info *this_frame,
- struct trad_frame_saved_reg this_saved_regs[],
+ trad_frame_saved_reg this_saved_regs[],
int regnum);
#endif