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
This commit is contained in:
John Baldwin 2018-04-24 05:20:16 +00:00
parent 703a6a3b14
commit 403e331d54
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=332906

View File

@ -51,6 +51,27 @@ __FBSDID("$FreeBSD$");
#include <unistd.h>
#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
@ -1688,11 +1709,7 @@ ATF_TC_BODY(ptrace__ptrace_vfork_follow, tc)
ATF_REQUIRE(errno == ECHILD);
}
/*
* 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__)
#ifdef HAVE_BREAKPOINT
/*
* 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