Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 6 Sep 2018 22:23:39 +0000 (UTC)
From:      John Baldwin <jhb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r338514 - in stable/11: sys/arm/include sys/arm64/include sys/mips/include sys/riscv/include tests/sys/kern
Message-ID:  <201809062223.w86MNdcq067782@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jhb
Date: Thu Sep  6 22:23:39 2018
New Revision: 338514
URL: https://svnweb.freebsd.org/changeset/base/338514

Log:
  MFC 332906,332907,332976,333679,336053: Expand testing of breakpoints.
  
  332906:
  Extend support for ptrace() tests using breakpoints.
  
  - Use a single list of platforms to define HAVE_BREAKPOINT for platforms
    that expose a functional breakpoint() inline to userland.  Replace
    existing lists of platform tests with HAVE_BREAKPOINT instead.
  - Add support for advancing PC past a breakpoint inserted via breakpoint()
    to support the existing ptrace__PT_CONTINUE_different_thread test on
    non-x86 platforms (x86 advances the PC past the breakpoint instruction,
    but other platforms do not).  This is implemented by defining a new
    SKIP_BREAK macro which accepts a pointer to a 'struct reg' as its sole
    argument and modifies the contents to advance the PC.  The intention is
    to use it in between PT_GETREGS and PT_SETREGS.
  
  332907:
  Expose breakpoint() to userland from <machine/cpufunc.h> on MIPS.
  
  Enable ptrace() tests using breakpoint on MIPS as well.
  
  332976:
  Shorten some recently-added lines that are an extra indent over 80 columns.
  
  333679:
  Export a breakpoint() function to userland for riscv.
  
  As a result, enable tests using breakpoint() on riscv.
  
  336053:
  Export a breakpoint() function to userland for arm and arm64.
  
  Enable ptrace() tests using breakpoint() on these architectures.

Modified:
  stable/11/sys/arm/include/cpufunc.h
  stable/11/sys/arm64/include/cpufunc.h
  stable/11/sys/mips/include/cpufunc.h
  stable/11/sys/riscv/include/cpufunc.h
  stable/11/tests/sys/kern/ptrace_test.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/arm/include/cpufunc.h
==============================================================================
--- stable/11/sys/arm/include/cpufunc.h	Thu Sep  6 21:24:14 2018	(r338513)
+++ stable/11/sys/arm/include/cpufunc.h	Thu Sep  6 22:23:39 2018	(r338514)
@@ -52,7 +52,7 @@
 static __inline void
 breakpoint(void)
 {
-	__asm(".word      0xe7ffffff");
+	__asm("udf        0xffff");
 }
 
 struct cpu_functions {
@@ -525,6 +525,19 @@ extern int	arm_dcache_align_mask;
 extern u_int	arm_cache_level;
 extern u_int	arm_cache_loc;
 extern u_int	arm_cache_type[14];
+
+#else	/* !_KERNEL */
+
+static __inline void
+breakpoint(void)
+{
+
+	/*
+	 * This matches the instruction used by GDB for software
+	 * breakpoints.
+	 */
+	__asm("udf        0xfdee");
+}
 
 #endif	/* _KERNEL */
 #endif	/* _MACHINE_CPUFUNC_H_ */

Modified: stable/11/sys/arm64/include/cpufunc.h
==============================================================================
--- stable/11/sys/arm64/include/cpufunc.h	Thu Sep  6 21:24:14 2018	(r338513)
+++ stable/11/sys/arm64/include/cpufunc.h	Thu Sep  6 22:23:39 2018	(r338514)
@@ -29,18 +29,18 @@
 #ifndef _MACHINE_CPUFUNC_H_
 #define	_MACHINE_CPUFUNC_H_
 
-#ifdef _KERNEL
-
-#include <machine/armreg.h>
-
-void pan_enable(void);
-
 static __inline void
 breakpoint(void)
 {
 
 	__asm("brk #0");
 }
+
+#ifdef _KERNEL
+
+#include <machine/armreg.h>
+
+void pan_enable(void);
 
 static __inline register_t
 dbg_disable(void)

Modified: stable/11/sys/mips/include/cpufunc.h
==============================================================================
--- stable/11/sys/mips/include/cpufunc.h	Thu Sep  6 21:24:14 2018	(r338513)
+++ stable/11/sys/mips/include/cpufunc.h	Thu Sep  6 22:23:39 2018	(r338514)
@@ -106,6 +106,12 @@ mips_wbflush(void)
 #endif
 }
 
+static __inline void
+breakpoint(void)
+{
+	__asm __volatile ("break");
+}
+
 #ifdef _KERNEL
 /*
  * XXX
@@ -339,12 +345,6 @@ get_intr_mask(void)
 {
 
 	return (mips_rd_status() & MIPS_SR_INT_MASK);
-}
-
-static __inline void
-breakpoint(void)
-{
-	__asm __volatile ("break");
 }
 
 #if defined(__GNUC__) && !defined(__mips_o32)

Modified: stable/11/sys/riscv/include/cpufunc.h
==============================================================================
--- stable/11/sys/riscv/include/cpufunc.h	Thu Sep  6 21:24:14 2018	(r338513)
+++ stable/11/sys/riscv/include/cpufunc.h	Thu Sep  6 22:23:39 2018	(r338514)
@@ -37,16 +37,16 @@
 #ifndef _MACHINE_CPUFUNC_H_
 #define	_MACHINE_CPUFUNC_H_
 
-#ifdef _KERNEL
-
-#include <machine/riscvreg.h>
-
 static __inline void
 breakpoint(void)
 {
 
 	__asm("ebreak");
 }
+
+#ifdef _KERNEL
+
+#include <machine/riscvreg.h>
 
 static __inline register_t
 intr_disable(void)

Modified: stable/11/tests/sys/kern/ptrace_test.c
==============================================================================
--- stable/11/tests/sys/kern/ptrace_test.c	Thu Sep  6 21:24:14 2018	(r338513)
+++ stable/11/tests/sys/kern/ptrace_test.c	Thu Sep  6 22:23:39 2018	(r338514)
@@ -52,6 +52,37 @@ __FBSDID("$FreeBSD$");
 #include <atf-c.h>
 
 /*
+ * Architectures with a user-visible breakpoint().
+ */
+#if defined(__aarch64__) || defined(__amd64__) || defined(__arm__) ||	\
+    defined(__i386__) || defined(__mips__) || defined(__riscv) ||	\
+    defined(__sparc64__)
+#define	HAVE_BREAKPOINT
+#endif
+
+/*
+ * Adjust PC to skip over a breakpoint when stopped for a breakpoint trap.
+ */
+#ifdef HAVE_BREAKPOINT
+#if defined(__aarch64__)
+#define	SKIP_BREAK(reg)	((reg)->elr += 4)
+#elif defined(__amd64__) || defined(__i386__)
+#define	SKIP_BREAK(reg)
+#elif defined(__arm__)
+#define	SKIP_BREAK(reg)	((reg)->r_pc += 4)
+#elif defined(__mips__)
+#define	SKIP_BREAK(reg)	((reg)->r_regs[PC] += 4)
+#elif defined(__riscv)
+#define	SKIP_BREAK(reg)	((reg)->sepc += 4)
+#elif defined(__sparc64__)
+#define	SKIP_BREAK(reg)	do {						\
+	(reg)->r_tpc = (reg)->r_tnpc + 4;				\
+	(reg)->r_tnpc += 8;						\
+} while (0)
+#endif
+#endif
+
+/*
  * A variant of ATF_REQUIRE that is suitable for use in child
  * processes.  This only works if the parent process is tripped up by
  * the early exit and fails some requirement itself.
@@ -1688,12 +1719,8 @@ ATF_TC_BODY(ptrace__ptrace_vfork_follow, tc)
 	ATF_REQUIRE(errno == ECHILD);
 }
 
+#ifdef HAVE_BREAKPOINT
 /*
- * XXX: There's nothing inherently platform specific about this test, however a
- * userspace visible breakpoint() is a prerequisite.
- */
- #if defined(__amd64__) || defined(__i386__) || defined(__sparc64__)
-/*
  * Verify that no more events are reported after PT_KILL except for the
  * process exit when stopped due to a breakpoint trap.
  */
@@ -1738,7 +1765,7 @@ ATF_TC_BODY(ptrace__PT_KILL_breakpoint, tc)
 	ATF_REQUIRE(wpid == -1);
 	ATF_REQUIRE(errno == ECHILD);
 }
-#endif /* defined(__amd64__) || defined(__i386__) || defined(__sparc64__) */
+#endif /* HAVE_BREAKPOINT */
 
 /*
  * Verify that no more events are reported after PT_KILL except for the
@@ -3468,11 +3495,7 @@ ATF_TC_BODY(ptrace__PT_STEP_with_signal, tc)
 	ATF_REQUIRE(errno == ECHILD);
 }
 
-#if defined(__amd64__) || defined(__i386__)
-/*
- * Only x86 both define breakpoint() and have a PC after breakpoint so
- * that restarting doesn't retrigger the breakpoint.
- */
+#if defined(HAVE_BREAKPOINT) && defined(SKIP_BREAK)
 static void *
 continue_thread(void *arg __unused)
 {
@@ -3506,6 +3529,7 @@ ATF_TC_BODY(ptrace__PT_CONTINUE_different_thread, tc)
 	pid_t fpid, wpid;
 	lwpid_t lwps[2];
 	bool hit_break[2];
+	struct reg reg;
 	int i, j, status;
 
 	ATF_REQUIRE((fpid = fork()) != -1);
@@ -3579,6 +3603,9 @@ ATF_TC_BODY(ptrace__PT_CONTINUE_different_thread, tc)
 	else
 		i = 1;
 	hit_break[i] = true;
+	ATF_REQUIRE(ptrace(PT_GETREGS, pl.pl_lwpid, (caddr_t)&reg, 0) != -1);
+	SKIP_BREAK(&reg);
+	ATF_REQUIRE(ptrace(PT_SETREGS, pl.pl_lwpid, (caddr_t)&reg, 0) != -1);
 
 	/*
 	 * Resume both threads but pass the other thread's LWPID to
@@ -3616,6 +3643,11 @@ ATF_TC_BODY(ptrace__PT_CONTINUE_different_thread, tc)
 			ATF_REQUIRE_MSG(!hit_break[i],
 			    "double breakpoint event");
 			hit_break[i] = true;
+			ATF_REQUIRE(ptrace(PT_GETREGS, pl.pl_lwpid, (caddr_t)&reg,
+			    0) != -1);
+			SKIP_BREAK(&reg);
+			ATF_REQUIRE(ptrace(PT_SETREGS, pl.pl_lwpid, (caddr_t)&reg,
+			    0) != -1);
 		}
 
 		ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
@@ -3663,7 +3695,7 @@ ATF_TP_ADD_TCS(tp)
 	ATF_TP_ADD_TC(tp, ptrace__event_mask);
 	ATF_TP_ADD_TC(tp, ptrace__ptrace_vfork);
 	ATF_TP_ADD_TC(tp, ptrace__ptrace_vfork_follow);
-#if defined(__amd64__) || defined(__i386__) || defined(__sparc64__)
+#ifdef HAVE_BREAKPOINT
 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_breakpoint);
 #endif
 	ATF_TP_ADD_TC(tp, ptrace__PT_KILL_system_call);
@@ -3688,7 +3720,7 @@ ATF_TP_ADD_TCS(tp)
 	ATF_TP_ADD_TC(tp, ptrace__event_mask_sigkill_discard);
 	ATF_TP_ADD_TC(tp, ptrace__PT_ATTACH_with_SBDRY_thread);
 	ATF_TP_ADD_TC(tp, ptrace__PT_STEP_with_signal);
-#if defined(__amd64__) || defined(__i386__)
+#if defined(HAVE_BREAKPOINT) && defined(SKIP_BREAK)
 	ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_different_thread);
 #endif
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201809062223.w86MNdcq067782>