Changeset View
Changeset View
Standalone View
Standalone View
devel/gdb/files/commit-12279366d7
- This file was added.
Property | Old Value | New Value |
---|---|---|
fbsd:nokeywords | null | yes \ No newline at end of property |
svn:eol-style | null | native \ No newline at end of property |
svn:mime-type | null | text/plain \ No newline at end of property |
commit 12279366d71627bfbdd74d1a6675dca825d8feca | |||||
Author: John Baldwin <jhb@FreeBSD.org> | |||||
Date: Sat Mar 3 21:25:33 2018 -0800 | |||||
Implement "to_stopped_by_hw_breakpoint" for x86 debug registers. | |||||
Report that a thread is stopped by a hardware breakpoint if a non-data | |||||
watchpoint is set in DR6. This change should be a no-op since a target | |||||
still needs to implement the "to_supports_stopped_by_hw_breakpoint" | |||||
method before this function is used. | |||||
gdb/ChangeLog: | |||||
* nat/x86-dregs.c (x86_dr_stopped_by_hw_breakpoint): New function. | |||||
* nat/x86-dregs.h (x86_dr_stopped_by_hw_breakpoint): New | |||||
prototype. | |||||
* x86-nat.c (x86_stopped_by_hw_breakpoint): New function. | |||||
(x86_use_watchpoints): Set "stopped_by_hw_breakpoint" target | |||||
method. | |||||
diff --git gdb/nat/x86-dregs.c gdb/nat/x86-dregs.c | |||||
index c816473628..f11a708e27 100644 | |||||
--- gdb/nat/x86-dregs.c | |||||
+++ gdb/nat/x86-dregs.c | |||||
@@ -649,3 +649,48 @@ x86_dr_stopped_by_watchpoint (struct x86_debug_reg_state *state) | |||||
CORE_ADDR addr = 0; | |||||
return x86_dr_stopped_data_address (state, &addr); | |||||
} | |||||
+ | |||||
+/* Return non-zero if the inferior has some hardware breakpoint that | |||||
+ triggered. Otherwise return zero. */ | |||||
+ | |||||
+int | |||||
+x86_dr_stopped_by_hw_breakpoint (struct x86_debug_reg_state *state) | |||||
+{ | |||||
+ CORE_ADDR addr = 0; | |||||
+ int i; | |||||
+ int rc = 0; | |||||
+ /* The current thread's DR_STATUS. We always need to read this to | |||||
+ check whether some watchpoint caused the trap. */ | |||||
+ unsigned status; | |||||
+ /* We need DR_CONTROL as well, but only iff DR_STATUS indicates a | |||||
+ breakpoint trap. Only fetch it when necessary, to avoid an | |||||
+ unnecessary extra syscall when no watchpoint triggered. */ | |||||
+ int control_p = 0; | |||||
+ unsigned control = 0; | |||||
+ | |||||
+ /* As above, always read the current thread's debug registers rather | |||||
+ than trusting dr_mirror. */ | |||||
+ status = x86_dr_low_get_status (); | |||||
+ | |||||
+ ALL_DEBUG_ADDRESS_REGISTERS (i) | |||||
+ { | |||||
+ if (!X86_DR_WATCH_HIT (status, i)) | |||||
+ continue; | |||||
+ | |||||
+ if (!control_p) | |||||
+ { | |||||
+ control = x86_dr_low_get_control (); | |||||
+ control_p = 1; | |||||
+ } | |||||
+ | |||||
+ if (X86_DR_GET_RW_LEN (control, i) == 0) | |||||
+ { | |||||
+ addr = x86_dr_low_get_addr (i); | |||||
+ rc = 1; | |||||
+ if (show_debug_regs) | |||||
+ x86_show_dr (state, "watchpoint_hit", addr, -1, hw_execute); | |||||
+ } | |||||
+ } | |||||
+ | |||||
+ return rc; | |||||
+} | |||||
diff --git gdb/nat/x86-dregs.h gdb/nat/x86-dregs.h | |||||
index dd6242eda9..e86e83aea0 100644 | |||||
--- gdb/nat/x86-dregs.h | |||||
+++ gdb/nat/x86-dregs.h | |||||
@@ -128,4 +128,8 @@ extern int x86_dr_stopped_data_address (struct x86_debug_reg_state *state, | |||||
Otherwise return false. */ | |||||
extern int x86_dr_stopped_by_watchpoint (struct x86_debug_reg_state *state); | |||||
+/* Return true if the inferior has some hardware breakpoint that | |||||
+ triggered. Otherwise return false. */ | |||||
+extern int x86_dr_stopped_by_hw_breakpoint (struct x86_debug_reg_state *state); | |||||
+ | |||||
#endif /* X86_DREGS_H */ | |||||
diff --git gdb/x86-nat.c gdb/x86-nat.c | |||||
index b126c47c94..bec51373a6 100644 | |||||
--- gdb/x86-nat.c | |||||
+++ gdb/x86-nat.c | |||||
@@ -260,6 +260,18 @@ x86_can_use_hw_breakpoint (struct target_ops *self, | |||||
return 1; | |||||
} | |||||
+/* Return non-zero if the inferior has some breakpoint that triggered. | |||||
+ Otherwise return zero. */ | |||||
+ | |||||
+static int | |||||
+x86_stopped_by_hw_breakpoint (struct target_ops *ops) | |||||
+{ | |||||
+ struct x86_debug_reg_state *state | |||||
+ = x86_debug_reg_state (ptid_get_pid (inferior_ptid)); | |||||
+ | |||||
+ return x86_dr_stopped_by_hw_breakpoint (state); | |||||
+} | |||||
+ | |||||
static void | |||||
add_show_debug_regs_command (void) | |||||
{ | |||||
@@ -297,6 +309,11 @@ x86_use_watchpoints (struct target_ops *t) | |||||
t->to_remove_watchpoint = x86_remove_watchpoint; | |||||
t->to_insert_hw_breakpoint = x86_insert_hw_breakpoint; | |||||
t->to_remove_hw_breakpoint = x86_remove_hw_breakpoint; | |||||
+ | |||||
+ /* A target must provide an implementation of the | |||||
+ "to_supports_stopped_by_hw_breakpoint" target method before this | |||||
+ callback will be used. */ | |||||
+ t->to_stopped_by_hw_breakpoint = x86_stopped_by_hw_breakpoint; | |||||
} | |||||
void |