diff options
author | Simon Marchi <simon.marchi@efficios.com> | 2023-12-01 11:27:18 -0500 |
---|---|---|
committer | Simon Marchi <simon.marchi@efficios.com> | 2023-12-14 16:04:49 +0000 |
commit | 51e6b8cfd649013ae16a3d00f1451b2531ba6bc9 (patch) | |
tree | 7f07b62493f0ffdcfb523d57452812cf491a88f2 /gdb/nat | |
parent | 08d8e7ff9474a88b491d22139ace851daae1a1c6 (diff) | |
download | binutils-51e6b8cfd649013ae16a3d00f1451b2531ba6bc9.zip binutils-51e6b8cfd649013ae16a3d00f1451b2531ba6bc9.tar.gz binutils-51e6b8cfd649013ae16a3d00f1451b2531ba6bc9.tar.bz2 |
gdb: change regcache interface to use array_view
Change most of regcache (and base classes) to use array_view when
possible, instead of raw pointers. By propagating the use of array_view
further, it enables having some runtime checks to make sure the what we
read from or write to regcaches has the expected length (such as the one
in the `copy(array_view, array_view)` function. It also integrates well
when connecting with other APIs already using gdb::array_view.
Add some overloads of the methods using raw pointers to avoid having to
change all call sites at once (which is both a lot of work and risky).
I tried to do this change in small increments, but since many of these
functions use each other, it ended up simpler to do it in one shot than
having a lot of intermediary / transient changes.
This change extends into gdbserver as well, because there is some part
of the regcache interface that is shared.
Changing the reg_buffer_common interface to use array_view caused some
build failures in nat/aarch64-scalable-linux-ptrace.c. That file
currently "takes advantage" of the fact that
reg_buffer_common::{raw_supply,raw_collect} operates on `void *`, which
IMO is dangerous. It uses raw_supply/raw_collect directly on
uint64_t's, which I guess is fine because it is expected that native
code will have the same endianness as the debugged process. To
accomodate that, add some overloads of raw_collect and raw_supply that
work on uint64_t.
This file also uses raw_collect and raw_supply on `char` pointers.
Change it to use `gdb_byte` pointers instead. Add overloads of
raw_collect and raw_supply that work on `gdb_byte *` and make an
array_view on the fly using the register's size. Those call sites could
be converted to use array_view with not much work, in which case these
overloads could be removed, but I didn't want to do it in this patch, to
avoid starting to dig in arch-specific code.
During development, I inadvertently changed reg_buffer::raw_compare's
behavior to not accept an offset equal to the register size. This
behavior (effectively comparing 0 bytes, returning true) change was
caught by the AArch64 SME core tests. Add a selftest to make sure that
this raw_compare behavior is preserved in the future.
Change-Id: I9005f04114543ddff738949e12d85a31855304c2
Reviewed-By: John Baldwin <jhb@FreeBSD.org>
Diffstat (limited to 'gdb/nat')
-rw-r--r-- | gdb/nat/aarch64-scalable-linux-ptrace.c | 20 |
1 files changed, 12 insertions, 8 deletions
diff --git a/gdb/nat/aarch64-scalable-linux-ptrace.c b/gdb/nat/aarch64-scalable-linux-ptrace.c index dc0e45f..b8fb317 100644 --- a/gdb/nat/aarch64-scalable-linux-ptrace.c +++ b/gdb/nat/aarch64-scalable-linux-ptrace.c @@ -613,7 +613,7 @@ aarch64_sve_regs_copy_to_reg_buf (int tid, struct reg_buffer_common *reg_buf) { gdb::byte_vector sve_state = aarch64_fetch_sve_regset (tid); - char *base = (char *) sve_state.data (); + gdb_byte *base = sve_state.data (); struct user_sve_header *header = (struct user_sve_header *) sve_state.data (); @@ -684,8 +684,10 @@ aarch64_sve_regs_copy_to_reg_buf (int tid, struct reg_buffer_common *reg_buf) reg_buf->raw_supply (AARCH64_SVE_Z0_REGNUM + i, reg); } - reg_buf->raw_supply (AARCH64_FPSR_REGNUM, &fpsimd->fpsr); - reg_buf->raw_supply (AARCH64_FPCR_REGNUM, &fpsimd->fpcr); + reg_buf->raw_supply (AARCH64_FPSR_REGNUM, + (const gdb_byte *) &fpsimd->fpsr); + reg_buf->raw_supply (AARCH64_FPCR_REGNUM, + (const gdb_byte *) &fpsimd->fpcr); /* Clear the SVE only registers. */ memset (reg, 0, SVE_PT_SVE_ZREG_SIZE (vq)); @@ -720,7 +722,7 @@ aarch64_sve_regs_copy_from_reg_buf (int tid, gdb::byte_vector new_state (SVE_PT_SIZE (32, SVE_PT_REGS_SVE), 0); memcpy (new_state.data (), sve_state.data (), sve_state.size ()); header = (struct user_sve_header *) new_state.data (); - char *base = (char *) new_state.data (); + gdb_byte *base = new_state.data (); /* Sanity check the data in the header. */ if (!sve_vl_valid (header->vl) @@ -805,9 +807,11 @@ aarch64_sve_regs_copy_from_reg_buf (int tid, } if (REG_VALID == reg_buf->get_register_status (AARCH64_FPSR_REGNUM)) - reg_buf->raw_collect (AARCH64_FPSR_REGNUM, &fpsimd->fpsr); + reg_buf->raw_collect (AARCH64_FPSR_REGNUM, + (gdb_byte *) &fpsimd->fpsr); if (REG_VALID == reg_buf->get_register_status (AARCH64_FPCR_REGNUM)) - reg_buf->raw_collect (AARCH64_FPCR_REGNUM, &fpsimd->fpcr); + reg_buf->raw_collect (AARCH64_FPCR_REGNUM, + (gdb_byte *) &fpsimd->fpcr); /* At this point we have collected all the data from the register cache and we are ready to update the FPSIMD register content @@ -894,7 +898,7 @@ aarch64_za_regs_copy_to_reg_buf (int tid, struct reg_buffer_common *reg_buf, /* Sanity check. */ gdb_assert (!za_state.empty ()); - char *base = (char *) za_state.data (); + gdb_byte *base = za_state.data (); struct user_za_header *header = (struct user_za_header *) base; /* If we have ZA state, read it. Otherwise, make the contents of ZA @@ -1027,7 +1031,7 @@ aarch64_za_regs_copy_from_reg_buf (int tid, /* Fetch the current ZA state from the thread. */ gdb::byte_vector za_state = aarch64_fetch_za_regset (tid); - char *base = (char *) za_state.data (); + gdb_byte *base = za_state.data (); struct user_za_header *za_header = (struct user_za_header *) base; uint64_t svq = sve_vq_from_vl (za_header->vl); |