Blame SOURCES/gdb-rhbz1854784-powerpc-remove-region-limit-dawr-6of7.patch

4f0e34
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
4f0e34
From: Pedro Franco de Carvalho <pedromfc@linux.ibm.com>
4f0e34
Date: Wed, 7 Jul 2021 19:05:04 -0400
4f0e34
Subject: gdb-rhbz1854784-powerpc-remove-region-limit-dawr-6of7.patch
4f0e34
4f0e34
;; Backport "[PowerPC] Always clear watchpoint with PTRACE_SET_DEBUGREG"
4f0e34
;; (Pedro Franco de Carvalho, RH BZ 1854784)
4f0e34
4f0e34
This patches changes low_prepare_to_resume in the ppc linux native target
4f0e34
to always clear the watchpoint when the old PTRACE_SET_DEBUGREG interface
4f0e34
is used, even if another watchpoint GDB requested to the target is
4f0e34
written right after using the same call.
4f0e34
4f0e34
The reason for this is that there were some older kernel versions for
4f0e34
which overwriting a watchpoint with PTRACE_SET_DEBUGREG would not
4f0e34
re-activate the watchpoint if it was previouly disabled following a hit.
4f0e34
This happened when the kernel was configured with CONFIG_HW_BREAKPOINT on
4f0e34
and uses perf events to install watchpoints.
4f0e34
4f0e34
Previously, the ppc linux native target would immediately remove or
4f0e34
insert watchpoints following a request from the upper layers.  This was
4f0e34
changed in commit 227c0bf4b3dd0cf65dceb58e729e9da81b38b5a7 to fix other
4f0e34
issues, which caused watchpoint requests to be applied to the inferior
4f0e34
only in low_prepare_to_resume, right before the inferior is resumed.
4f0e34
4f0e34
Usually, but maybe not always, after a hit, GDB will remove the
4f0e34
watchpoint, resume the inferior for a single-step, possibly report the
4f0e34
watchpoint hit to the user, and then re-insert the watchpoint before the
4f0e34
inferior is next resumed.  In this case there would be no problems, but
4f0e34
since I can't guarantee that there aren't other paths in GDB that allow
4f0e34
the user to set a new watchpoint after the first one hit, and after its
4f0e34
deletion by GDB, but before the inferior is resumed, there is a chance
4f0e34
that PTRACE_SET_DEBUGREG could be called directly without the watchpoint
4f0e34
first having been cleared, which could cause a false negative with the
4f0e34
older kernel versions.
4f0e34
4f0e34
This issue would affect kernel versions starting from this commit:
4f0e34
4f0e34
5aae8a53708025d4e718f0d2e7c2f766779ddc71
4f0e34
4f0e34
Up to the fix in this commit:
4f0e34
4f0e34
a53fd61ac2f411745471c1c877d5e072fbbf0e5c
4f0e34
4f0e34
gdb/ChangeLog:
4f0e34
4f0e34
	PR breakpoints/26385
4f0e34
	* ppc-linux-nat.c (ppc_linux_nat_target::low_prepare_to_resume):
4f0e34
	Always clear watchpoint with PTRACE_SET_DEBUGREG.
4f0e34
4f0e34
diff --git a/gdb/ppc-linux-nat.c b/gdb/ppc-linux-nat.c
4f0e34
--- a/gdb/ppc-linux-nat.c
4f0e34
+++ b/gdb/ppc-linux-nat.c
4f0e34
@@ -2922,20 +2922,23 @@ ppc_linux_nat_target::low_prepare_to_resume (struct lwp_info *lp)
4f0e34
     {
4f0e34
       gdb_assert (m_dreg_interface.debugreg_p ());
4f0e34
 
4f0e34
-      /* Passing 0 to PTRACE_SET_DEBUGREG will clear the
4f0e34
-	 watchpoint.  */
4f0e34
-      long wp = 0;
4f0e34
+      /* Passing 0 to PTRACE_SET_DEBUGREG will clear the watchpoint.  We
4f0e34
+	 always clear the watchpoint instead of just overwriting it, in
4f0e34
+	 case there is a request for a new watchpoint, because on some
4f0e34
+	 older kernel versions and configurations simply overwriting the
4f0e34
+	 watchpoint after it was hit would not re-enable it.  */
4f0e34
+      if (ptrace (PTRACE_SET_DEBUGREG, lp->ptid.lwp (), 0, 0) < 0)
4f0e34
+	perror_with_name (_("Error clearing hardware watchpoint"));
4f0e34
 
4f0e34
       /* GDB requested a watchpoint to be installed.  */
4f0e34
       if (process_it != m_process_info.end ()
4f0e34
 	  && process_it->second.requested_wp_val.has_value ())
4f0e34
-	wp = *(process_it->second.requested_wp_val);
4f0e34
-
4f0e34
-      long ret = ptrace (PTRACE_SET_DEBUGREG, lp->ptid.lwp (),
4f0e34
-			 0, wp);
4f0e34
+	{
4f0e34
+	  long wp = *(process_it->second.requested_wp_val);
4f0e34
 
4f0e34
-      if (ret < 0)
4f0e34
-	perror_with_name (_("Error setting hardware watchpoint"));
4f0e34
+	  if (ptrace (PTRACE_SET_DEBUGREG, lp->ptid.lwp (), 0, wp) < 0)
4f0e34
+	    perror_with_name (_("Error setting hardware watchpoint"));
4f0e34
+	}
4f0e34
     }
4f0e34
 
4f0e34
   lp_arch_info->debug_regs_stale = false;