aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom de Vries <tdevries@suse.de>2025-08-12 16:35:05 +0200
committerTom de Vries <tdevries@suse.de>2025-08-12 16:35:05 +0200
commit6f9909c4179983330a29b6fd246b39ab1b003934 (patch)
tree7465418522a76ca9aeaf7b908e6c2eececef358d
parent3769fe5ed37ac05f78b9879a4bcbdf2e77f49d0f (diff)
downloadbinutils-6f9909c4179983330a29b6fd246b39ab1b003934.zip
binutils-6f9909c4179983330a29b6fd246b39ab1b003934.tar.gz
binutils-6f9909c4179983330a29b6fd246b39ab1b003934.tar.bz2
[gdb/tdep] Handle M1 ldp in aarch64_stopped_data_address
In test-case gdb.base/watchpoint-unaligned.exp, in function write_size8twice, two adjacent 8-byte vars are written. For aarch64, we use a single stp instruction for that. If we do the same in function read_size8twice for two adjacent 8-byte var reads using aarch64 insn ldp, on an aarch64-linux M1 system we get a hang: ... (gdb) continue^M Continuing.^M FAIL: $exp: fun=read_size8twice: offset=0: index=1: continue (timeout) FAIL: $exp: fun=read_size8twice: offset=0: index=1: $got_hit ... The same problem was observed for stp in PR tdep/29423, fixed by commit 9a03f218534 ("[gdb/tdep] Fix gdb.base/watchpoint-unaligned.exp on aarch64"). See that commit for an explanation of the hang. That commit introduced max_access_size in aarch64_stopped_data_address: ... The access size also can be larger than that of the watchpoint itself. For instance, the access size of an stp instruction is 16. So, if we use stp to store to address p, and set a watchpoint on address p + 8, the reported ADDR_TRAP can be p + 8 (observed on RK3399 SOC). But it also can be p (observed on M1 SOC). Checking for this situation introduces the possibility of false positives, so we only do this for hw_write watchpoints. */ const CORE_ADDR max_access_size = type == hw_write ? 16 : 8; ... If we say that hangs are worse than false positives, then we should also fix this case. Fix this by setting max_access_size to 16 for all watchpoint types. Tested on aarch64-linux, both on an M1 SOC and an RK3399 SOC. Approved-By: Luis Machado <luis.machado.foss@gmail.com>
-rw-r--r--gdb/nat/aarch64-hw-point.c6
-rw-r--r--gdb/testsuite/gdb.base/watchpoint-unaligned.c8
2 files changed, 10 insertions, 4 deletions
diff --git a/gdb/nat/aarch64-hw-point.c b/gdb/nat/aarch64-hw-point.c
index 6d8dce8..8c0854b 100644
--- a/gdb/nat/aarch64-hw-point.c
+++ b/gdb/nat/aarch64-hw-point.c
@@ -710,10 +710,8 @@ aarch64_stopped_data_address (const struct aarch64_debug_reg_state *state,
itself. For instance, the access size of an stp instruction is 16.
So, if we use stp to store to address p, and set a watchpoint on
address p + 8, the reported ADDR_TRAP can be p + 8 (observed on
- RK3399 SOC). But it also can be p (observed on M1 SOC). Checking
- for this situation introduces the possibility of false positives,
- so we only do this for hw_write watchpoints. */
- const CORE_ADDR max_access_size = type == hw_write ? 16 : 8;
+ RK3399 SOC). But it also can be p (observed on M1 SOC). */
+ const CORE_ADDR max_access_size = 16;
const CORE_ADDR addr_watch_base = addr_watch_aligned -
(max_access_size - AARCH64_HWP_MAX_LEN_PER_REG);
if (!(addr_trap >= addr_watch_base
diff --git a/gdb/testsuite/gdb.base/watchpoint-unaligned.c b/gdb/testsuite/gdb.base/watchpoint-unaligned.c
index baa7ae0..ca2fa45 100644
--- a/gdb/testsuite/gdb.base/watchpoint-unaligned.c
+++ b/gdb/testsuite/gdb.base/watchpoint-unaligned.c
@@ -71,8 +71,16 @@ read_size8twice (void)
static uint64_t volatile first;
static uint64_t volatile second;
+#ifdef __aarch64__
+ volatile void *p = &data.u.size8twice[offset];
+ asm volatile ("ldp %0, %1, [%2]"
+ : "=r" (first), "=r" (second) /* output */
+ : "r" (p) /* input */
+ : /* clobber */);
+#else
first = data.u.size8twice[offset];
second = data.u.size8twice[offset + 1];
+#endif
/* Setting a breakpoint on an instruction after an instruction triggering a
watchpoint makes it ambiguous which one will be reported.