This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH 2/3] [AArch64] Adjust breakpoint on tagged address


Nowadays, GDB can't set breakpoint on a tagged address, because kernel
requires tag bits should be removed, and reject the request,

(gdb) hbreak *func_ptr
gdb.execute_unwinders function is missing:
Hardware assisted breakpoint 2 at 0xf0000000004006f0
(gdb) c
Continuing.
main () at binutils-gdb/gdb/testsuite/gdb.arch/aarch64-tagged-pointer.c:47
47	  sp2->i = 4321; /* breakpoint here.  */
Unexpected error setting hardware debug registers

With this patch, when user sets a breakpoint on tagged address, 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 kernle 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.  I did try the different approach, that is keep the tag in
the address saved in the breakpoint location, but I need to change many
places of "loc->address == pc", so I give up on this way.

gdb:

2017-10-24  Yao Qi  <yao.qi@linaro.org>

	* aarch64-tdep.c (aarch64_adjust_breakpoint_address): New
	function.
	(aarch64_gdbarch_init): Install adjust_breakpoint_address.

gdb/testsuite:

2017-10-24  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/aarch64-tdep.c                                | 10 ++++++++++
 gdb/testsuite/gdb.arch/aarch64-tagged-pointer.c   |  9 +++++++++
 gdb/testsuite/gdb.arch/aarch64-tagged-pointer.exp | 24 +++++++++++++++++++++++
 3 files changed, 43 insertions(+)

diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
index 85cabfd..42c14c2 100644
--- a/gdb/aarch64-tdep.c
+++ b/gdb/aarch64-tdep.c
@@ -2828,6 +2828,14 @@ aarch64_displaced_step_hw_singlestep (struct gdbarch *gdbarch,
   return 1;
 }
 
+/* Implement the "adjust_breakpoint_address" gdbarch method.  */
+
+static CORE_ADDR
+aarch64_adjust_breakpoint_address (struct gdbarch *gdbarch, CORE_ADDR bpaddr)
+{
+  return bpaddr & 0x0fffffffffffffffULL;
+}
+
 /* Initialize the current architecture based on INFO.  If possible,
    re-use an architecture from ARCHES, which is a list of
    architectures already created during this debugging session.
@@ -2945,6 +2953,8 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 				       aarch64_breakpoint::bp_from_kind);
   set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1);
   set_gdbarch_software_single_step (gdbarch, aarch64_software_single_step);
+  set_gdbarch_adjust_breakpoint_address (gdbarch,
+					 aarch64_adjust_breakpoint_address);
 
   /* Information about registers, etc.  */
   set_gdbarch_sp_regnum (gdbarch, AARCH64_SP_REGNUM);
diff --git a/gdb/testsuite/gdb.arch/aarch64-tagged-pointer.c b/gdb/testsuite/gdb.arch/aarch64-tagged-pointer.c
index 7c90132..ec3574d 100644
--- a/gdb/testsuite/gdb.arch/aarch64-tagged-pointer.c
+++ b/gdb/testsuite/gdb.arch/aarch64-tagged-pointer.c
@@ -45,4 +45,13 @@ main (void)
   void (*func_ptr) (void) = foo;
   func_ptr = (void (*) (void)) ((uintptr_t) func_ptr | 0xf000000000000000ULL);
   sp2->i = 4321; /* breakpoint here.  */
+
+  int j;
+  for (j = 0; j < 2; j++)
+    {
+      foo ();
+      (*func_ptr) ();
+    }
+
+  sp1->i = 8765;
 }
diff --git a/gdb/testsuite/gdb.arch/aarch64-tagged-pointer.exp b/gdb/testsuite/gdb.arch/aarch64-tagged-pointer.exp
index 4d36d09..2a5b1eb 100644
--- a/gdb/testsuite/gdb.arch/aarch64-tagged-pointer.exp
+++ b/gdb/testsuite/gdb.arch/aarch64-tagged-pointer.exp
@@ -66,3 +66,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
+}
-- 
1.9.1


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]