This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[PATCH 3/3] [AArch64] Remove tag from address for watchpoint
- From: Yao Qi <qiyaoltc at gmail dot com>
- To: gdb-patches at sourceware dot org
- Date: Thu, 26 Oct 2017 09:29:50 +0100
- Subject: [PATCH 3/3] [AArch64] Remove tag from address for watchpoint
- Authentication-results: sourceware.org; auth=none
- References: <1509006590-9401-1-git-send-email-yao.qi@linaro.org>
Nowadays, GDB can't set watchpoint on tagged address,
(gdb) p p2
$1 = (int *) 0xf000fffffffff474
(gdb) watch *((int *) 0xf000fffffffff474)
Hardware watchpoint 2: *((int *) 0xf000fffffffff474)
(gdb) c
Continuing.
main () at
binutils-gdb/gdb/testsuite/gdb.arch/aarch64-tagged-pointer.c:45
45 void (*func_ptr) (void) = foo;
Unexpected error setting hardware debug registers
This patch is about setting watchpoint on a tagged address. Unlike
breakpoint, watchpoint record the expression rather than the address, and
when a watchpoint is fired, GDB checks the expression value changed
instead of matching address, so we can mask the watchpoint address for
aarch64, by adding a gdbarch method addr_tag_remove.
gdb:
2017-10-25 Yao Qi <yao.qi@linaro.org>
* aarch64-linux-tdep.c (aarch64_linux_addr_tag_remove): New method.
(aarch64_linux_init_abi): Install gdbarch method.
* gdbarch.sh (addr_tag_remove): New gdbarch method.
* gdbarch.c: Re-generated.
* gdbarch.h: Re-generated.
* breakpoint.c (update_watchpoint):
gdb/testsuite:
2017-10-25 Yao Qi <yao.qi@linaro.org>
* gdb.arch/aarch64-tagged-pointer.exp: Add tests for watchpoint.
---
gdb/aarch64-linux-tdep.c | 11 +++++++++++
gdb/breakpoint.c | 3 +--
gdb/gdbarch.c | 23 +++++++++++++++++++++++
gdb/gdbarch.h | 8 ++++++++
gdb/gdbarch.sh | 5 +++++
gdb/testsuite/gdb.arch/aarch64-tagged-pointer.c | 1 +
gdb/testsuite/gdb.arch/aarch64-tagged-pointer.exp | 14 ++++++++++++++
7 files changed, 63 insertions(+), 2 deletions(-)
diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c
index b6052ba..139f336 100644
--- a/gdb/aarch64-linux-tdep.c
+++ b/gdb/aarch64-linux-tdep.c
@@ -1001,6 +1001,15 @@ aarch64_linux_syscall_record (struct regcache *regcache,
return 0;
}
+/* Implement the "addr_tag_remove" gdbarch method. */
+
+static CORE_ADDR
+aarch64_linux_addr_tag_remove (struct gdbarch *gdbarch, CORE_ADDR val)
+{
+ /* Ignore the top byte of virtual address. */
+ return val & 0x0fffffffffffffffULL;
+}
+
static void
aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
@@ -1217,6 +1226,8 @@ aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
set_xml_syscall_file_name (gdbarch, "syscalls/aarch64-linux.xml");
set_gdbarch_get_syscall_number (gdbarch, aarch64_linux_get_syscall_number);
+ set_gdbarch_addr_tag_remove (gdbarch, aarch64_linux_addr_tag_remove);
+
/* Displaced stepping. */
set_gdbarch_max_insn_length (gdbarch, 4 * DISPLACED_MODIFIED_INSNS);
set_gdbarch_displaced_step_copy_insn (gdbarch,
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index e16cfb6..16f03ff 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -1894,8 +1894,7 @@ update_watchpoint (struct watchpoint *b, int reparse)
loc->gdbarch = get_type_arch (value_type (v));
loc->pspace = frame_pspace;
- loc->address = addr;
-
+ loc->address = gdbarch_addr_tag_remove (loc->gdbarch, addr);
if (bitsize != 0)
{
/* Just cover the bytes that make up the bitfield. */
diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c
index 007392c..76574d4 100644
--- a/gdb/gdbarch.c
+++ b/gdb/gdbarch.c
@@ -259,6 +259,7 @@ struct gdbarch
int frame_red_zone_size;
gdbarch_convert_from_func_ptr_addr_ftype *convert_from_func_ptr_addr;
gdbarch_addr_bits_remove_ftype *addr_bits_remove;
+ gdbarch_addr_tag_remove_ftype *addr_tag_remove;
gdbarch_software_single_step_ftype *software_single_step;
gdbarch_single_step_through_delay_ftype *single_step_through_delay;
gdbarch_print_insn_ftype *print_insn;
@@ -428,6 +429,7 @@ gdbarch_alloc (const struct gdbarch_info *info,
gdbarch->stabs_argument_has_addr = default_stabs_argument_has_addr;
gdbarch->convert_from_func_ptr_addr = convert_from_func_ptr_addr_identity;
gdbarch->addr_bits_remove = core_addr_identity;
+ gdbarch->addr_tag_remove = core_addr_identity;
gdbarch->print_insn = default_print_insn;
gdbarch->skip_trampoline_code = generic_skip_trampoline_code;
gdbarch->skip_solib_resolver = generic_skip_solib_resolver;
@@ -618,6 +620,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
/* Skip verify of stabs_argument_has_addr, invalid_p == 0 */
/* Skip verify of convert_from_func_ptr_addr, invalid_p == 0 */
/* Skip verify of addr_bits_remove, invalid_p == 0 */
+ /* Skip verify of addr_tag_remove, invalid_p == 0 */
/* Skip verify of software_single_step, has predicate. */
/* Skip verify of single_step_through_delay, has predicate. */
/* Skip verify of print_insn, invalid_p == 0 */
@@ -737,6 +740,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
"gdbarch_dump: addr_bits_remove = <%s>\n",
host_address_to_string (gdbarch->addr_bits_remove));
fprintf_unfiltered (file,
+ "gdbarch_dump: addr_tag_remove = <%s>\n",
+ host_address_to_string (gdbarch->addr_tag_remove));
+ fprintf_unfiltered (file,
"gdbarch_dump: gdbarch_address_class_name_to_type_flags_p() = %d\n",
gdbarch_address_class_name_to_type_flags_p (gdbarch));
fprintf_unfiltered (file,
@@ -3215,6 +3221,23 @@ set_gdbarch_addr_bits_remove (struct gdbarch *gdbarch,
gdbarch->addr_bits_remove = addr_bits_remove;
}
+CORE_ADDR
+gdbarch_addr_tag_remove (struct gdbarch *gdbarch, CORE_ADDR addr)
+{
+ gdb_assert (gdbarch != NULL);
+ gdb_assert (gdbarch->addr_tag_remove != NULL);
+ if (gdbarch_debug >= 2)
+ fprintf_unfiltered (gdb_stdlog, "gdbarch_addr_tag_remove called\n");
+ return gdbarch->addr_tag_remove (gdbarch, addr);
+}
+
+void
+set_gdbarch_addr_tag_remove (struct gdbarch *gdbarch,
+ gdbarch_addr_tag_remove_ftype addr_tag_remove)
+{
+ gdbarch->addr_tag_remove = addr_tag_remove;
+}
+
int
gdbarch_software_single_step_p (struct gdbarch *gdbarch)
{
diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
index d2e6b6f..769c8fb 100644
--- a/gdb/gdbarch.h
+++ b/gdb/gdbarch.h
@@ -677,6 +677,14 @@ typedef CORE_ADDR (gdbarch_addr_bits_remove_ftype) (struct gdbarch *gdbarch, COR
extern CORE_ADDR gdbarch_addr_bits_remove (struct gdbarch *gdbarch, CORE_ADDR addr);
extern void set_gdbarch_addr_bits_remove (struct gdbarch *gdbarch, gdbarch_addr_bits_remove_ftype *addr_bits_remove);
+/* On some machines, there are bits in address which are ignored by the
+ kernel, the hardeware, etc. They are called "tag", which can be
+ regarded as additional data associated with the address. */
+
+typedef CORE_ADDR (gdbarch_addr_tag_remove_ftype) (struct gdbarch *gdbarch, CORE_ADDR addr);
+extern CORE_ADDR gdbarch_addr_tag_remove (struct gdbarch *gdbarch, CORE_ADDR addr);
+extern void set_gdbarch_addr_tag_remove (struct gdbarch *gdbarch, gdbarch_addr_tag_remove_ftype *addr_tag_remove);
+
/* FIXME/cagney/2001-01-18: This should be split in two. A target method that
indicates if the target needs software single step. An ISA method to
implement it.
diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh
index 6459b12..1f673e7 100755
--- a/gdb/gdbarch.sh
+++ b/gdb/gdbarch.sh
@@ -621,6 +621,11 @@ m;CORE_ADDR;convert_from_func_ptr_addr;CORE_ADDR addr, struct target_ops *targ;a
# possible it should be in TARGET_READ_PC instead).
m;CORE_ADDR;addr_bits_remove;CORE_ADDR addr;addr;;core_addr_identity;;0
+# On some machines, there are bits in address which are ignored by the
+# kernel, the hardeware, etc. They are called "tag", which can be
+# regarded as additional data associated with the address.
+m;CORE_ADDR;addr_tag_remove;CORE_ADDR addr;addr;;core_addr_identity;;0
+
# FIXME/cagney/2001-01-18: This should be split in two. A target method that
# indicates if the target needs software single step. An ISA method to
# implement it.
diff --git a/gdb/testsuite/gdb.arch/aarch64-tagged-pointer.c b/gdb/testsuite/gdb.arch/aarch64-tagged-pointer.c
index ec3574d..19395f5 100644
--- a/gdb/testsuite/gdb.arch/aarch64-tagged-pointer.c
+++ b/gdb/testsuite/gdb.arch/aarch64-tagged-pointer.c
@@ -54,4 +54,5 @@ main (void)
}
sp1->i = 8765;
+ i = 1;
}
diff --git a/gdb/testsuite/gdb.arch/aarch64-tagged-pointer.exp b/gdb/testsuite/gdb.arch/aarch64-tagged-pointer.exp
index 2a5b1eb..f38b876 100644
--- a/gdb/testsuite/gdb.arch/aarch64-tagged-pointer.exp
+++ b/gdb/testsuite/gdb.arch/aarch64-tagged-pointer.exp
@@ -90,3 +90,17 @@ foreach_with_prefix bptype {"hbreak" "break"} {
gdb_test "up" "\\(\*func_ptr\\) \\(\\).*" "caller is *func_ptr"
delete_breakpoints
}
+
+gdb_test "down"
+gdb_test "finish"
+# Watch on tagged pointer.
+gdb_test "watch *sp2"
+gdb_test "continue" \
+ "Continuing\\..*Hardware watchpoint \[0-9\]+.*" \
+ "run until watchpoint on s1"
+delete_breakpoints
+
+gdb_test "watch *p2"
+gdb_test "continue" \
+ "Continuing\\..*Hardware watchpoint \[0-9\]+.*" \
+ "run until watchpoint on i"
--
1.9.1