Author: jhb
Date: Tue Apr 24 05:20:16 2018
New Revision: 332906
URL: https://svnweb.freebsd.org/changeset/base/332906

Log:
  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.
  
  Tested on:    amd64, i386, mips (after adding a breakpoint() to mips)
  MFC after:    1 month

Modified:
  head/tests/sys/kern/ptrace_test.c

Modified: head/tests/sys/kern/ptrace_test.c
==============================================================================
--- head/tests/sys/kern/ptrace_test.c   Tue Apr 24 04:07:51 2018        
(r332905)
+++ head/tests/sys/kern/ptrace_test.c   Tue Apr 24 05:20:16 2018        
(r332906)
@@ -52,6 +52,27 @@ __FBSDID("$FreeBSD$");
 #include <atf-c.h>
 
 /*
+ * Architectures with a user-visible breakpoint().
+ */
+#if defined(__amd64__) || defined(__i386__) || defined(__sparc64__)
+#define        HAVE_BREAKPOINT
+#endif
+
+/*
+ * Adjust PC to skip over a breakpoint when stopped for a breakpoint trap.
+ */
+#ifdef HAVE_BREAKPOINT
+#if defined(__amd64__) || defined(__i386__)
+#define        SKIP_BREAK(reg)
+#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 +1709,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 +1755,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 +3485,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 +3519,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 +3593,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 +3633,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 +3685,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 +3710,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
 
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to