diff options
author | John Baldwin <jhb@FreeBSD.org> | 2018-03-03 21:25:33 -0800 |
---|---|---|
committer | John Baldwin <jhb@FreeBSD.org> | 2018-03-03 21:25:33 -0800 |
commit | 12279366d71627bfbdd74d1a6675dca825d8feca (patch) | |
tree | e15692d8fa4694fb384cd0ef3c19d2b1c5a1dcc0 /gdb/nat | |
parent | 72f53f22dfc1bb79ae0141a91b8f9786e1964f41 (diff) | |
download | binutils-12279366d71627bfbdd74d1a6675dca825d8feca.zip binutils-12279366d71627bfbdd74d1a6675dca825d8feca.tar.gz binutils-12279366d71627bfbdd74d1a6675dca825d8feca.tar.bz2 |
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.
Diffstat (limited to 'gdb/nat')
-rw-r--r-- | gdb/nat/x86-dregs.c | 45 | ||||
-rw-r--r-- | gdb/nat/x86-dregs.h | 4 |
2 files changed, 49 insertions, 0 deletions
diff --git a/gdb/nat/x86-dregs.c b/gdb/nat/x86-dregs.c index c816473..f11a708 100644 --- a/gdb/nat/x86-dregs.c +++ b/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 a/gdb/nat/x86-dregs.h b/gdb/nat/x86-dregs.h index dd6242e..e86e83a 100644 --- a/gdb/nat/x86-dregs.h +++ b/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 */ |