Re: [patch] aarch64: PR 19806: watchpoints: false negatives + PR 20207 contiguous ones

Jan Kratochvil
2018-05-01T23:03:46Z

[-- Attachment #1: Type: text/plain, Size: 1181 bytes --]

On Thu, 26 Apr 2018 22:12:16 +0200, Jan Kratochvil wrote:
> On Fri, 20 Apr 2018 16:49:39 +0200, Pedro Alves wrote:
> > ~~~~~~~~~~~~
> > Previously, when the hardware reported a watchpoint hit on an address
> > that did not match our watchpoint (this happens in case of instructions
> > which access large chunks of memory such as "stp") the process would
> > enter a loop where we would be continually resuming it (because we did
> > not recognise that watchpoint hit) and it would keep hitting the
> > watchpoint again and again. The tracing process would never get
> > notified of the watchpoint hit.
> > ~~~~~~~~~~~~
> >
> > ... I'm left with the impression that ADDR_TRAP could be even
> > lower than addr_watch_aligned, in which case we'll still miss
> > watchpoints. I wondering whether GDB should be using a similar
> > trick as that kernel patch does.
>
> This is new for me what you found. I just did not expect the changed region
> region could be larger than aligned 8 bytes.
>
> Unfortunately I cannot reproduce that so I cannot do much with that.
> Does anyone know how to reproduce it?

Attaching the change I made, I will repost the patch in a next mail.

Jan

[-- Attachment #2: 1 --]
[-- Type: text/plain, Size: 2264 bytes --]

diff --git a/gdb/testsuite/gdb.base/watchpoint-unaligned.c b/gdb/testsuite/gdb.base/watchpoint-unaligned.c
index ea844e9..97832a0 100644
--- a/gdb/testsuite/gdb.base/watchpoint-unaligned.c
+++ b/gdb/testsuite/gdb.base/watchpoint-unaligned.c
@@ -29,6 +29,7 @@ static volatile struct
uint32_t size4[2];
uint16_t size2[4];
uint8_t size1[8];
+ uint64_t size8twice[2];
}
u;
} data;
@@ -36,12 +37,32 @@ static volatile struct
static int size = 0;
static int offset;

+static void
+write_size8twice (void)
+{
+ static const uint64_t first = 1;
+ static const uint64_t second = 2;
+
+#ifdef __aarch64__
+ asm volatile ("stp %1, %2, [%0]"
+ : /* output */
+ : "r" (data.u.size8twice), "r" (first), "r" (second) /* input */
+ : "memory" /* clobber */);
+#else
+ data.u.size8twice[0] = first;
+ data.u.size8twice[1] = second;
+#endif
+}
+
int
main (void)
{
volatile uint64_t local;

- assert (sizeof (data) == 8 + 8);
+ assert (sizeof (data) == 8 + 2 * 8);
+
+ write_size8twice ();
+
while (size)
{
switch (size)
@@ -64,5 +85,5 @@ main (void)
size = 0;
size = size; /* start_again */
}
- return 0;
+ return 0; /* final_return */
}
diff --git a/gdb/testsuite/gdb.base/watchpoint-unaligned.exp b/gdb/testsuite/gdb.base/watchpoint-unaligned.exp
index 833997b..25a15a8 100644
--- a/gdb/testsuite/gdb.base/watchpoint-unaligned.exp
+++ b/gdb/testsuite/gdb.base/watchpoint-unaligned.exp
@@ -114,3 +114,29 @@ foreach wpcount {4 7} {
}
gdb_assert $got_hit $test
}
+
+if ![runto_main] {
+ return -1
+}
+gdb_breakpoint [gdb_get_line_number "final_return"] "Breakpoint $decimal at $hex" "final_return"
+set test {watch data.u.size8twice[1]}
+set wpnum ""
+gdb_test_multiple $test $test {
+ -re "Hardware watchpoint (\[0-9\]+): .*\r\n$gdb_prompt $" {
+ set wpnum $expect_out(1,string)
+ }
+}
+set test "continue"
+set got_hit 0
+gdb_test_multiple $test $test {
+ -re "\r\nCould not insert hardware watchpoint .*\r\n$gdb_prompt $" {
+ }
+ -re "Hardware watchpoint $wpnum:.*New value = .*\r\n$gdb_prompt $" {
+ set got_hit 1
+ send_gdb "continue\n"
+ exp_continue
+ }
+ -re " final_return .*\r\n$gdb_prompt $" {
+ }
+}
+gdb_assert $got_hit "size8twice write"