Adjust breakpoint address by clearing non-significant bits
authorYao Qi <yao.qi@linaro.org>
Fri, 8 Dec 2017 17:27:03 +0000 (17:27 +0000)
committerYao Qi <yao.qi@linaro.org>
Fri, 8 Dec 2017 17:27:03 +0000 (17:27 +0000)
Tag in tagged address on AArch64 is treated as a non-significant bits of
address, which can be got by gdbarch method significant_addr_bit, and gdb
can clear these bits.

With this patch, when user sets a breakpoint on tagged address on AArch64,
GDB will drop the top byte of address, and put breakpoint at the new place,
as shown below,

(gdb) hbreak *func_ptr
warning: Breakpoint address adjusted from 0xf000000000400690 to 0x00400690.
Hardware assisted breakpoint 2 at 0x400690

(gdb) break *func_ptr
warning: Breakpoint address adjusted from 0xf000000000400690 to 0x00400690.
Breakpoint 3 at 0x400690

When program hits a breakpoint, the stopped pc reported by Linux kernel is
the address *without* tag, so it is better the address recorded in
breakpoint location is the one without tag too, so we can still match
breakpoint location address and stopped pc reported by Linux kernel, by
simple compare.

gdb:

2017-12-08  Yao Qi  <yao.qi@linaro.org>

* breakpoint.c (adjust_breakpoint_address): Call
address_significant.

gdb/testsuite:

2017-12-08  Yao Qi  <yao.qi@linaro.org>

* gdb.arch/aarch64-tagged-pointer.c (main): Update.
* gdb.arch/aarch64-tagged-pointer.exp: Add test for breakpoint.

gdb/ChangeLog
gdb/breakpoint.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.arch/aarch64-tagged-pointer.c
gdb/testsuite/gdb.arch/aarch64-tagged-pointer.exp

index 952a2fffbfe5ff5ba31e9062dbb84636620f7a2f..134f7b4c6de290fabf58966f46210638d5be48a8 100644 (file)
@@ -1,3 +1,8 @@
+2017-12-08  Yao Qi  <yao.qi@linaro.org>
+
+       * breakpoint.c (adjust_breakpoint_address): Call
+       address_significant.
+
 2017-12-08  Yao Qi  <yao.qi@linaro.org>
 
        * aarch64-tdep.c (aarch64_gdbarch_init): Install gdbarch
index b4353d26e8a127642e83256abd1ea300ccdc3d5f..1cee730cc6f3b2f648375676475b45d08bd6360b 100644 (file)
@@ -6973,16 +6973,11 @@ static CORE_ADDR
 adjust_breakpoint_address (struct gdbarch *gdbarch,
                           CORE_ADDR bpaddr, enum bptype bptype)
 {
-  if (!gdbarch_adjust_breakpoint_address_p (gdbarch))
-    {
-      /* Very few targets need any kind of breakpoint adjustment.  */
-      return bpaddr;
-    }
-  else if (bptype == bp_watchpoint
-           || bptype == bp_hardware_watchpoint
-           || bptype == bp_read_watchpoint
-           || bptype == bp_access_watchpoint
-           || bptype == bp_catchpoint)
+  if (bptype == bp_watchpoint
+      || bptype == bp_hardware_watchpoint
+      || bptype == bp_read_watchpoint
+      || bptype == bp_access_watchpoint
+      || bptype == bp_catchpoint)
     {
       /* Watchpoints and the various bp_catch_* eventpoints should not
          have their addresses modified.  */
@@ -7000,11 +6995,16 @@ adjust_breakpoint_address (struct gdbarch *gdbarch,
     }
   else
     {
-      CORE_ADDR adjusted_bpaddr;
+      CORE_ADDR adjusted_bpaddr = bpaddr;
+
+      if (gdbarch_adjust_breakpoint_address_p (gdbarch))
+       {
+         /* Some targets have architectural constraints on the placement
+            of breakpoint instructions.  Obtain the adjusted address.  */
+         adjusted_bpaddr = gdbarch_adjust_breakpoint_address (gdbarch, bpaddr);
+       }
 
-      /* Some targets have architectural constraints on the placement
-         of breakpoint instructions.  Obtain the adjusted address.  */
-      adjusted_bpaddr = gdbarch_adjust_breakpoint_address (gdbarch, bpaddr);
+      adjusted_bpaddr = address_significant (gdbarch, adjusted_bpaddr);
 
       /* An adjusted breakpoint address can significantly alter
          a user's expectations.  Print a warning if an adjustment
index cc834de616a4e7ee2bf537883110e6f49fc456be..17fbe4f939fbe14bd29d41f6d8346d5cafebc5cd 100644 (file)
@@ -1,3 +1,8 @@
+2017-12-08  Yao Qi  <yao.qi@linaro.org>
+
+       * gdb.arch/aarch64-tagged-pointer.c (main): Update.
+       * gdb.arch/aarch64-tagged-pointer.exp: Add test for breakpoint.
+
 2017-12-08  Yao Qi  <yao.qi@linaro.org>
 
        * gdb.arch/aarch64-tagged-pointer.c: New file.
index 7c901325fb218ad5db2f876577a4bf5cc8deec60..9bfe41e12985e566ece27dd26ac00e4567a09b5a 100644 (file)
@@ -45,4 +45,12 @@ main (void)
   void (*func_ptr) (void) = foo;
   func_ptr = (void (*) (void)) ((uintptr_t) func_ptr | 0xf000000000000000ULL);
   sp2->i = 4321; /* breakpoint here.  */
+
+  for (int i = 0; i < 2; i++)
+    {
+      foo ();
+      (*func_ptr) ();
+    }
+
+  sp1->i = 8765;
 }
index 4f2b44c2c4cf8e91d5df68d58897f8952e9e1486..fcab1b76d94b5270f258a5952d4767b264ab5aec 100644 (file)
@@ -65,3 +65,27 @@ gdb_test_multiple $test $test {
 
 gdb_test "disassemble func_ptr,+8" \
     ":\[\t \]+$insn1\[ \r\n\]+.*:\[\t \]+$insn2.*"
+
+foreach_with_prefix bptype {"hbreak" "break"} {
+
+    # Set a breakpoint on a tagged address, func_ptr,
+    gdb_test "$bptype *func_ptr" \
+       "warning: Breakpoint address adjusted from .*reakpoint $decimal at .*" \
+       "breakpoint at *func_ptr"
+    # Resume the program and expect it hits foo,
+    gdb_test "continue" \
+       "Continuing\\..*Breakpoint \[0-9\]+, foo \\(\\) at .*" \
+       "run until breakpoint set *func_ptr"
+    gdb_test "up" "foo \\(\\).*" "caller is foo"
+    delete_breakpoints
+
+    # Set a breakpoint on normal function, call it through tagged
+    # function pointer.
+    gdb_test "$bptype foo" "reakpoint $decimal at .*" \
+       "hardware breakpoint at foo"
+    gdb_test "continue" \
+       "Continuing\\..*Breakpoint \[0-9\]+, foo \\(\\) at .*" \
+       "run until breakpoint set foo"
+    gdb_test "up" "\\(\*func_ptr\\) \\(\\).*" "caller is *func_ptr"
+    delete_breakpoints
+}