|
|
2c2fa1 |
http://sourceware.org/ml/gdb-patches/2015-02/msg00734.html
|
|
|
2c2fa1 |
Subject: [PATCH 7/8] gdbserver/Linux: Use TRAP_BRKPT/TRAP_HWBPT
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
This patch adjusts gdbserver's Linux backend to tell gdbserver core
|
|
|
2c2fa1 |
(and ultimately GDB) whether a trap was caused by a breakpoint.
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
It teaches the backend to get that information out of the si_code of
|
|
|
2c2fa1 |
the SIGTRAP siginfo.
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
gdb/gdbserver/ChangeLog:
|
|
|
2c2fa1 |
2015-02-25 Pedro Alves <palves@redhat.com>
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
* linux-low.c (check_stopped_by_breakpoint) [USE_SIGTRAP_SIGINFO]:
|
|
|
2c2fa1 |
Decide whether a breakpoint triggered based on the SIGTRAP's
|
|
|
2c2fa1 |
siginfo.si_code.
|
|
|
2c2fa1 |
(thread_still_has_status_pending_p) [USE_SIGTRAP_SIGINFO]: Don't check whether a
|
|
|
2c2fa1 |
breakpoint is inserted if relying on SIGTRAP's siginfo.si_code.
|
|
|
2c2fa1 |
(linux_low_filter_event): Check for breakpoints before checking
|
|
|
2c2fa1 |
watchpoints.
|
|
|
2c2fa1 |
(linux_wait_1): Don't re-increment the PC if relying on SIGTRAP's
|
|
|
2c2fa1 |
siginfo.si_code.
|
|
|
2c2fa1 |
(linux_stopped_by_sw_breakpoint)
|
|
|
2c2fa1 |
(linux_supports_stopped_by_sw_breakpoint)
|
|
|
2c2fa1 |
(linux_stopped_by_hw_breakpoint)
|
|
|
2c2fa1 |
(linux_supports_stopped_by_hw_breakpoint): New functions.
|
|
|
2c2fa1 |
(linux_target_ops): Install new target methods.
|
|
|
2c2fa1 |
---
|
|
|
2c2fa1 |
gdb/gdbserver/linux-low.c | 122 +++++++++++++++++++++++++++++++++++++++++++---
|
|
|
2c2fa1 |
1 file changed, 116 insertions(+), 6 deletions(-)
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
Index: gdb-7.6.1/gdb/gdbserver/linux-low.c
|
|
|
2c2fa1 |
===================================================================
|
|
|
2c2fa1 |
--- gdb-7.6.1.orig/gdb/gdbserver/linux-low.c 2016-03-13 21:42:34.115589901 +0100
|
|
|
2c2fa1 |
+++ gdb-7.6.1/gdb/gdbserver/linux-low.c 2016-03-13 21:45:00.625644976 +0100
|
|
|
2c2fa1 |
@@ -1360,6 +1360,8 @@
|
|
|
2c2fa1 |
return (struct lwp_info*) find_inferior (&all_lwps, same_lwp, &ptid);
|
|
|
2c2fa1 |
}
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
+static void save_stop_reason (struct lwp_info *lwp);
|
|
|
2c2fa1 |
+
|
|
|
2c2fa1 |
static struct lwp_info *
|
|
|
2c2fa1 |
linux_wait_for_lwp (ptid_t ptid, int *wstatp, int options)
|
|
|
2c2fa1 |
{
|
|
|
2c2fa1 |
@@ -1465,6 +1467,10 @@
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
current_inferior = saved_inferior;
|
|
|
2c2fa1 |
}
|
|
|
2c2fa1 |
+
|
|
|
2c2fa1 |
+ /* RHEL */
|
|
|
2c2fa1 |
+ if (!child->stopped_by_watchpoint)
|
|
|
2c2fa1 |
+ save_stop_reason (child);
|
|
|
2c2fa1 |
}
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
/* Store the STOP_PC, with adjustment applied. This depends on the
|
|
|
2c2fa1 |
@@ -1847,6 +1853,47 @@
|
|
|
2c2fa1 |
being stepped. */
|
|
|
2c2fa1 |
ptid_t step_over_bkpt;
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
+// gdb/nat/linux-ptrace.h
|
|
|
2c2fa1 |
+#if defined __i386__ || defined __x86_64__
|
|
|
2c2fa1 |
+# define GDB_ARCH_IS_TRAP_BRKPT(X) ((X) == SI_KERNEL)
|
|
|
2c2fa1 |
+# define GDB_ARCH_IS_TRAP_HWBKPT(X) ((X) == TRAP_HWBKPT)
|
|
|
2c2fa1 |
+#elif defined __powerpc__
|
|
|
2c2fa1 |
+# define GDB_ARCH_IS_TRAP_BRKPT(X) ((X) == SI_KERNEL || (X) == TRAP_BRKPT)
|
|
|
2c2fa1 |
+# define GDB_ARCH_IS_TRAP_HWBKPT(X) ((X) == TRAP_HWBKPT)
|
|
|
2c2fa1 |
+#elif defined __mips__
|
|
|
2c2fa1 |
+# define GDB_ARCH_IS_TRAP_BRKPT(X) ((X) == SI_KERNEL)
|
|
|
2c2fa1 |
+# define GDB_ARCH_IS_TRAP_HWBKPT(X) ((X) == SI_KERNEL)
|
|
|
2c2fa1 |
+#else
|
|
|
2c2fa1 |
+# define GDB_ARCH_IS_TRAP_BRKPT(X) ((X) == TRAP_BRKPT)
|
|
|
2c2fa1 |
+# define GDB_ARCH_IS_TRAP_HWBKPT(X) ((X) == TRAP_HWBKPT)
|
|
|
2c2fa1 |
+#endif
|
|
|
2c2fa1 |
+
|
|
|
2c2fa1 |
+// gdb/nat/linux-ptrace.h
|
|
|
2c2fa1 |
+#ifndef TRAP_HWBKPT
|
|
|
2c2fa1 |
+# define TRAP_HWBKPT 4
|
|
|
2c2fa1 |
+#endif
|
|
|
2c2fa1 |
+
|
|
|
2c2fa1 |
+static void
|
|
|
2c2fa1 |
+save_stop_reason (struct lwp_info *lwp)
|
|
|
2c2fa1 |
+{
|
|
|
2c2fa1 |
+ siginfo_t siginfo;
|
|
|
2c2fa1 |
+
|
|
|
2c2fa1 |
+ if (ptrace (PTRACE_GETSIGINFO, lwpid_of (lwp),
|
|
|
2c2fa1 |
+ (PTRACE_ARG3_TYPE) 0, &siginfo) == 0)
|
|
|
2c2fa1 |
+ {
|
|
|
2c2fa1 |
+ if (siginfo.si_signo == SIGTRAP)
|
|
|
2c2fa1 |
+ {
|
|
|
2c2fa1 |
+ if (GDB_ARCH_IS_TRAP_HWBKPT (siginfo.si_code))
|
|
|
2c2fa1 |
+ {
|
|
|
2c2fa1 |
+ /* This can indicate either a hardware breakpoint or
|
|
|
2c2fa1 |
+ hardware watchpoint. Check debug registers. */
|
|
|
2c2fa1 |
+// if (!check_stopped_by_watchpoint (lwp))
|
|
|
2c2fa1 |
+ lwp->stopped_by_hw_breakpoint = 1;
|
|
|
2c2fa1 |
+ }
|
|
|
2c2fa1 |
+ }
|
|
|
2c2fa1 |
+ }
|
|
|
2c2fa1 |
+}
|
|
|
2c2fa1 |
+
|
|
|
2c2fa1 |
/* Wait for an event from child PID. If PID is -1, wait for any
|
|
|
2c2fa1 |
child. Store the stop status through the status pointer WSTAT.
|
|
|
2c2fa1 |
OPTIONS is passed to the waitpid call. Return 0 if no child stop
|
|
|
2c2fa1 |
@@ -3332,6 +3396,7 @@
|
|
|
2c2fa1 |
errno = 0;
|
|
|
2c2fa1 |
lwp->stopped = 0;
|
|
|
2c2fa1 |
lwp->stopped_by_watchpoint = 0;
|
|
|
2c2fa1 |
+ lwp->stopped_by_hw_breakpoint = 0;
|
|
|
2c2fa1 |
lwp->stepping = step;
|
|
|
2c2fa1 |
ptrace (step ? PTRACE_SINGLESTEP : PTRACE_CONT, lwpid_of (lwp),
|
|
|
2c2fa1 |
(PTRACE_ARG3_TYPE) 0,
|
|
|
2c2fa1 |
@@ -4856,6 +4921,26 @@
|
|
|
2c2fa1 |
return 1;
|
|
|
2c2fa1 |
}
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
+/* Implement the to_stopped_by_hw_breakpoint target_ops
|
|
|
2c2fa1 |
+ method. */
|
|
|
2c2fa1 |
+
|
|
|
2c2fa1 |
+static int
|
|
|
2c2fa1 |
+linux_stopped_by_hw_breakpoint (void)
|
|
|
2c2fa1 |
+{
|
|
|
2c2fa1 |
+ struct lwp_info *lwp = get_thread_lwp (current_inferior);
|
|
|
2c2fa1 |
+
|
|
|
2c2fa1 |
+ return lwp->stopped_by_hw_breakpoint;
|
|
|
2c2fa1 |
+}
|
|
|
2c2fa1 |
+
|
|
|
2c2fa1 |
+/* Implement the to_supports_stopped_by_hw_breakpoint target_ops
|
|
|
2c2fa1 |
+ method. */
|
|
|
2c2fa1 |
+
|
|
|
2c2fa1 |
+static int
|
|
|
2c2fa1 |
+linux_supports_stopped_by_hw_breakpoint (void)
|
|
|
2c2fa1 |
+{
|
|
|
2c2fa1 |
+ return 1; // RHEL
|
|
|
2c2fa1 |
+}
|
|
|
2c2fa1 |
+
|
|
|
2c2fa1 |
static int
|
|
|
2c2fa1 |
linux_stopped_by_watchpoint (void)
|
|
|
2c2fa1 |
{
|
|
|
2c2fa1 |
@@ -5946,6 +6031,8 @@
|
|
|
2c2fa1 |
linux_read_auxv,
|
|
|
2c2fa1 |
linux_insert_point,
|
|
|
2c2fa1 |
linux_remove_point,
|
|
|
2c2fa1 |
+ linux_stopped_by_hw_breakpoint,
|
|
|
2c2fa1 |
+ linux_supports_stopped_by_hw_breakpoint,
|
|
|
2c2fa1 |
linux_stopped_by_watchpoint,
|
|
|
2c2fa1 |
linux_stopped_data_address,
|
|
|
2c2fa1 |
#if defined(__UCLIBC__) && defined(HAS_NOMMU)
|
|
|
2c2fa1 |
Index: gdb-7.6.1/gdb/gdbserver/linux-low.h
|
|
|
2c2fa1 |
===================================================================
|
|
|
2c2fa1 |
--- gdb-7.6.1.orig/gdb/gdbserver/linux-low.h 2016-03-13 21:45:52.861021138 +0100
|
|
|
2c2fa1 |
+++ gdb-7.6.1/gdb/gdbserver/linux-low.h 2016-03-13 21:46:00.668077363 +0100
|
|
|
2c2fa1 |
@@ -223,6 +223,9 @@
|
|
|
2c2fa1 |
watchpoint trap. */
|
|
|
2c2fa1 |
int stopped_by_watchpoint;
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
+ /* RHEL: TARGET_STOPPED_BY_HW_BREAKPOINT */
|
|
|
2c2fa1 |
+ int stopped_by_hw_breakpoint;
|
|
|
2c2fa1 |
+
|
|
|
2c2fa1 |
/* On architectures where it is possible to know the data address of
|
|
|
2c2fa1 |
a triggered watchpoint, STOPPED_DATA_ADDRESS is non-zero, and
|
|
|
2c2fa1 |
contains such data address. Only valid if STOPPED_BY_WATCHPOINT
|