aboutsummaryrefslogtreecommitdiff
path: root/gdb/aarch64-tdep.c
diff options
context:
space:
mode:
authorLuis Machado <luis.machado@arm.com>2023-03-30 15:16:53 +0100
committerLuis Machado <luis.machado@arm.com>2023-10-04 16:23:39 +0100
commit89c4ee8398e3915c6685bb74057eb5644cf36959 (patch)
tree8715b6a65694a141e735c41d28b73b378f122c00 /gdb/aarch64-tdep.c
parent78d6a7e98ccf5f788f23d49cbd95c45da7ee4660 (diff)
downloadbinutils-89c4ee8398e3915c6685bb74057eb5644cf36959.zip
binutils-89c4ee8398e3915c6685bb74057eb5644cf36959.tar.gz
binutils-89c4ee8398e3915c6685bb74057eb5644cf36959.tar.bz2
sve: Fix return command when using V registers in a SVE-enabled target
In a target without SVE support, the V registers have a size of 16 bytes, otherwise they may have a size bigger than 16 bytes (depending on the current vector length for the Z registers, as they overlap the V registers). In aarch64-tdep.c:aarch64_store_return_value, the code is laid out in a way that allocates the buffer with the size of the register, but only updates the amount of bytes for the particular type we're returning. This may cause a situation where we have a register size of 32 bytes but are returning a floating point value of 8 bytes. The temporary buffer will therefore have 32 bytes, but we'll only update 8 bytes of it. When we write the entire register back, it will have potentially 24 bytes of garbage in it. Fix this by first reading the original contents of the register and then overriding only the bytes that we need for the return value. Tested on aarch64-linux Ubuntu 22.04/20.04. Reviewed-by: Thiago Jung Bauermann <thiago.bauermann@linaro.org>
Diffstat (limited to 'gdb/aarch64-tdep.c')
-rw-r--r--gdb/aarch64-tdep.c5
1 files changed, 5 insertions, 0 deletions
diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
index 21dd6c7..b1d7da9 100644
--- a/gdb/aarch64-tdep.c
+++ b/gdb/aarch64-tdep.c
@@ -2417,6 +2417,11 @@ aarch64_store_return_value (struct type *type, struct regcache *regs,
("write HFA or HVA return value element %d to %s",
i + 1, gdbarch_register_name (gdbarch, regno));
+ /* Depending on whether the target supports SVE or not, the V
+ registers may report a size > 16 bytes. In that case, read the
+ original contents of the register before overriding it with a new
+ value that has a potential size <= 16 bytes. */
+ regs->cooked_read (regno, tmpbuf);
memcpy (tmpbuf, valbuf,
len > V_REGISTER_SIZE ? V_REGISTER_SIZE : len);
regs->cooked_write (regno, tmpbuf);