aarch64: PR 19806: watchpoints: false negatives + PR 20207 contiguous ones

Message ID 20180501230339.GA3136080@host1.jankratochvil.net
State New, archived
Headers

Commit Message

Jan Kratochvil May 1, 2018, 11:03 p.m. UTC
  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
  

Patch

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"