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:
parent
703a6a3b14
commit
403e331d54
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=332906
@ -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)®, 0) != -1);
|
||||
SKIP_BREAK(®);
|
||||
ATF_REQUIRE(ptrace(PT_SETREGS, pl.pl_lwpid, (caddr_t)®, 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)®,
|
||||
0) != -1);
|
||||
SKIP_BREAK(®);
|
||||
ATF_REQUIRE(ptrace(PT_SETREGS, pl.pl_lwpid, (caddr_t)®,
|
||||
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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user