[PATCH] MIPS: Introduce hardware breakpoint
Heiher
r@hev.cc
Wed Jun 17 15:58:58 GMT 2020
gdb/ChangeLog:
2020-06-17 Heiher <r@hev.cc>
* mips-linux-nat.c (mips_linux_nat_target::can_use_hw_breakpoint):
Handle case.
(mips_linux_nat_target::stopped_by_watchpoint): Update.
(mips_linux_nat_target::insert_hw_breakpoint): New methods.
(mips_linux_nat_target::remove_hw_breakpoint): New methods.
* nat/mips-linux-watch.c (mips_linux_watch_type_to_irw): Handle case.
---
gdb/ChangeLog | 8 +++
gdb/mips-linux-nat.c | 127 ++++++++++++++++++++++++++++++++++++-
gdb/nat/mips-linux-watch.c | 2 +
3 files changed, 136 insertions(+), 1 deletion(-)
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index cb3761c1ba..7e913abcb5 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,11 @@
+2020-06-17 Heiher <r@hev.cc>
+ * mips-linux-nat.c (mips_linux_nat_target::can_use_hw_breakpoint):
+ Handle case.
+ (mips_linux_nat_target::stopped_by_watchpoint): Update.
+ (mips_linux_nat_target::insert_hw_breakpoint): New methods.
+ (mips_linux_nat_target::remove_hw_breakpoint): New methods.
+ * nat/mips-linux-watch.c (mips_linux_watch_type_to_irw): Handle case.
+
2020-06-16 Tom Tromey <tom@tromey.com>
* python/py-tui.c (tui_py_window::~tui_py_window): Handle case
diff --git a/gdb/mips-linux-nat.c b/gdb/mips-linux-nat.c
index 38ff461a35..9b0a910861 100644
--- a/gdb/mips-linux-nat.c
+++ b/gdb/mips-linux-nat.c
@@ -52,6 +52,8 @@ class mips_linux_nat_target final : public linux_nat_trad_target
void close () override;
int can_use_hw_breakpoint (enum bptype, int, int) override;
+ int insert_hw_breakpoint (struct gdbarch *, struct bp_target_info *) override;
+ int remove_hw_breakpoint (struct gdbarch *, struct bp_target_info *) override;
int remove_watchpoint (CORE_ADDR, int, enum target_hw_bp_type,
struct expression *) override;
@@ -546,6 +548,9 @@ mips_linux_nat_target::can_use_hw_breakpoint (enum bptype type,
switch (type)
{
+ case bp_hardware_breakpoint:
+ wanted_mask = I_MASK;
+ break;
case bp_hardware_watchpoint:
wanted_mask = W_MASK;
break;
@@ -588,7 +593,7 @@ mips_linux_nat_target::stopped_by_watchpoint ()
num_valid = mips_linux_watch_get_num_valid (&watch_readback);
for (n = 0; n < MAX_DEBUG_REGISTER && n < num_valid; n++)
- if (mips_linux_watch_get_watchhi (&watch_readback, n) & (R_MASK | W_MASK))
+ if (mips_linux_watch_get_watchhi (&watch_readback, n) & IRW_MASK)
return true;
return false;
@@ -761,6 +766,126 @@ mips_linux_nat_target::remove_watchpoint (CORE_ADDR addr, int len,
return retval;
}
+/* Insert a hardware-assisted breakpoint at BP_TGT->reqstd_address.
+ Return 0 on success, -1 on failure. */
+
+int
+mips_linux_nat_target::insert_hw_breakpoint (struct gdbarch *gdbarch,
+ struct bp_target_info *bp_tgt)
+{
+ struct pt_watch_regs regs;
+ struct mips_watchpoint *new_watch;
+ struct mips_watchpoint **pw;
+
+ const enum target_hw_bp_type type = hw_execute;
+ CORE_ADDR addr = bp_tgt->placed_address = bp_tgt->reqstd_address;
+ int retval;
+ int len;
+
+ gdbarch_breakpoint_from_pc (gdbarch, &addr, &len);
+
+ if (show_debug_regs)
+ fprintf_unfiltered
+ (gdb_stdlog,
+ "insert_hw_breakpoint on entry (addr=0x%08lx, len=%d))\n",
+ (unsigned long) addr, len);
+
+ if (!mips_linux_read_watch_registers (inferior_ptid.lwp (),
+ &watch_readback,
+ &watch_readback_valid, 0))
+ return -1;
+
+ if (len <= 0)
+ return -1;
+
+ regs = watch_readback;
+ /* Add the current watches. */
+ mips_linux_watch_populate_regs (current_watches, ®s);
+
+ /* Now try to add the new watch. */
+ if (!mips_linux_watch_try_one_watch (®s, addr, len,
+ mips_linux_watch_type_to_irw (type)))
+ return -1;
+
+ /* It fit. Stick it on the end of the list. */
+ new_watch = XNEW (struct mips_watchpoint);
+ new_watch->addr = addr;
+ new_watch->len = len;
+ new_watch->type = type;
+ new_watch->next = NULL;
+
+ pw = ¤t_watches;
+ while (*pw != NULL)
+ pw = &(*pw)->next;
+ *pw = new_watch;
+
+ watch_mirror = regs;
+ retval = write_watchpoint_regs ();
+
+ if (show_debug_regs)
+ mips_show_dr ("insert_hw_breakpoint", addr, len, type);
+
+ return retval;
+}
+
+/* Remove a hardware-assisted breakpoint at BP_TGT->placed_address.
+ Return 0 on success, -1 on failure. */
+
+int
+mips_linux_nat_target::remove_hw_breakpoint (struct gdbarch *gdbarch,
+ struct bp_target_info *bp_tgt)
+{
+ int retval;
+ int deleted_one;
+ int len = 4;
+
+ struct mips_watchpoint **pw;
+ struct mips_watchpoint *w;
+
+ const enum target_hw_bp_type type = hw_execute;
+ CORE_ADDR addr = bp_tgt->placed_address;
+
+ gdbarch_breakpoint_from_pc (gdbarch, &addr, &len);
+
+ if (show_debug_regs)
+ fprintf_unfiltered
+ (gdb_stdlog, "remove_hw_breakpoint on entry (addr=0x%08lx, len=%d))\n",
+ (unsigned long) addr, len);
+
+ /* Search for a known watch that matches. Then unlink and free
+ it. */
+ deleted_one = 0;
+ pw = ¤t_watches;
+ while ((w = *pw))
+ {
+ if (w->addr == addr && w->len == len && w->type == type)
+ {
+ *pw = w->next;
+ xfree (w);
+ deleted_one = 1;
+ break;
+ }
+ pw = &(w->next);
+ }
+
+ if (!deleted_one)
+ return -1; /* We don't know about it, fail doing nothing. */
+
+ /* At this point watch_readback is known to be valid because we
+ could not have added the watch without reading it. */
+ gdb_assert (watch_readback_valid == 1);
+
+ watch_mirror = watch_readback;
+ mips_linux_watch_populate_regs (current_watches, &watch_mirror);
+
+ retval = write_watchpoint_regs ();
+
+ if (show_debug_regs)
+ mips_show_dr ("remove_hw_watchpoint", addr, len, type);
+
+ return retval;
+}
+
/* Target to_close implementation. Free any watches and call the
super implementation. */
diff --git a/gdb/nat/mips-linux-watch.c b/gdb/nat/mips-linux-watch.c
index c975e2218a..74b95a9ac7 100644
--- a/gdb/nat/mips-linux-watch.c
+++ b/gdb/nat/mips-linux-watch.c
@@ -202,6 +202,8 @@ mips_linux_watch_type_to_irw (enum target_hw_bp_type type)
{
switch (type)
{
+ case hw_execute:
+ return I_MASK;
case hw_write:
return W_MASK;
case hw_read:
--
2.27.0
More information about the Gdb-patches
mailing list