Blame SOURCES/gdb-rhbz1261564-aarch64-hw-watchpoint-5of5.patch

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