t_ptrace_wait.c revision 1.42
11.42Skamil/*	$NetBSD: t_ptrace_wait.c,v 1.42 2018/05/16 01:36:29 kamil Exp $	*/
21.1Skamil
31.1Skamil/*-
41.1Skamil * Copyright (c) 2016 The NetBSD Foundation, Inc.
51.1Skamil * All rights reserved.
61.1Skamil *
71.1Skamil * Redistribution and use in source and binary forms, with or without
81.1Skamil * modification, are permitted provided that the following conditions
91.1Skamil * are met:
101.1Skamil * 1. Redistributions of source code must retain the above copyright
111.1Skamil *    notice, this list of conditions and the following disclaimer.
121.1Skamil * 2. Redistributions in binary form must reproduce the above copyright
131.1Skamil *    notice, this list of conditions and the following disclaimer in the
141.1Skamil *    documentation and/or other materials provided with the distribution.
151.1Skamil *
161.1Skamil * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
171.1Skamil * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
181.1Skamil * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
191.1Skamil * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
201.1Skamil * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
211.1Skamil * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
221.1Skamil * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
231.1Skamil * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
241.1Skamil * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
251.1Skamil * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
261.1Skamil * POSSIBILITY OF SUCH DAMAGE.
271.1Skamil */
281.1Skamil
291.1Skamil#include <sys/cdefs.h>
301.42Skamil__RCSID("$NetBSD: t_ptrace_wait.c,v 1.42 2018/05/16 01:36:29 kamil Exp $");
311.1Skamil
321.1Skamil#include <sys/param.h>
331.1Skamil#include <sys/types.h>
341.39Skamil#include <sys/mman.h>
351.1Skamil#include <sys/ptrace.h>
361.1Skamil#include <sys/resource.h>
371.1Skamil#include <sys/stat.h>
381.1Skamil#include <sys/syscall.h>
391.1Skamil#include <sys/sysctl.h>
401.1Skamil#include <sys/wait.h>
411.1Skamil#include <machine/reg.h>
421.1Skamil#include <elf.h>
431.1Skamil#include <err.h>
441.1Skamil#include <errno.h>
451.1Skamil#include <lwp.h>
461.1Skamil#include <sched.h>
471.1Skamil#include <signal.h>
481.1Skamil#include <stdint.h>
491.1Skamil#include <stdio.h>
501.1Skamil#include <stdlib.h>
511.1Skamil#include <strings.h>
521.26Skamil#include <time.h>
531.1Skamil#include <unistd.h>
541.1Skamil
551.1Skamil#include <atf-c.h>
561.1Skamil
571.1Skamil#include "h_macros.h"
581.1Skamil
591.1Skamil#include "t_ptrace_wait.h"
601.1Skamil#include "msg.h"
611.1Skamil
621.1Skamil#define PARENT_TO_CHILD(info, fds, msg) \
631.13Schristos    SYSCALL_REQUIRE(msg_write_child(info " to child " # fds, &fds, &msg, sizeof(msg)) == 0)
641.1Skamil
651.1Skamil#define CHILD_FROM_PARENT(info, fds, msg) \
661.1Skamil    FORKEE_ASSERT(msg_read_parent(info " from parent " # fds, &fds, &msg, sizeof(msg)) == 0)
671.1Skamil
681.1Skamil#define CHILD_TO_PARENT(info, fds, msg) \
691.1Skamil    FORKEE_ASSERT(msg_write_parent(info " to parent " # fds, &fds, &msg, sizeof(msg)) == 0)
701.1Skamil
711.1Skamil#define PARENT_FROM_CHILD(info, fds, msg) \
721.13Schristos    SYSCALL_REQUIRE(msg_read_child(info " from parent " # fds, &fds, &msg, sizeof(msg)) == 0)
731.13Schristos
741.13Schristos#define SYSCALL_REQUIRE(expr) ATF_REQUIRE_MSG(expr, "%s: %s", # expr, \
751.13Schristos    strerror(errno))
761.18Schristos#define SYSCALL_REQUIRE_ERRNO(res, exp) ATF_REQUIRE_MSG(res == exp, \
771.18Schristos    "%d(%s) != %d", res, strerror(res), exp)
781.13Schristos
791.13Schristosstatic int debug = 0;
801.13Schristos
811.13Schristos#define DPRINTF(a, ...)	do  \
821.13Schristos	if (debug) printf(a,  ##__VA_ARGS__); \
831.13Schristos    while (/*CONSTCOND*/0)
841.1Skamil
851.34Skamil/// ----------------------------------------------------------------------------
861.34Skamil
871.33Skamilstatic void
881.33Skamiltraceme_raise(int sigval)
891.1Skamil{
901.1Skamil	const int exitval = 5;
911.1Skamil	pid_t child, wpid;
921.1Skamil#if defined(TWAIT_HAVE_STATUS)
931.1Skamil	int status;
941.1Skamil#endif
951.1Skamil
961.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
971.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
981.1Skamil	if (child == 0) {
991.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
1001.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
1011.1Skamil
1021.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
1031.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
1041.1Skamil
1051.36Skamil		switch (sigval) {
1061.36Skamil		case SIGKILL:
1071.36Skamil			/* NOTREACHED */
1081.36Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
1091.36Skamil		default:
1101.36Skamil			DPRINTF("Before exiting of the child process\n");
1111.36Skamil			_exit(exitval);
1121.36Skamil		}
1131.1Skamil	}
1141.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
1151.1Skamil
1161.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1171.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1181.1Skamil
1191.36Skamil	switch (sigval) {
1201.36Skamil	case SIGKILL:
1211.36Skamil		validate_status_signaled(status, sigval, 0);
1221.36Skamil		break;
1231.36Skamil	default:
1241.36Skamil		validate_status_stopped(status, sigval);
1251.1Skamil
1261.36Skamil		DPRINTF("Before resuming the child process where it left off "
1271.36Skamil		    "and without signal to be sent\n");
1281.36Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1291.1Skamil
1301.36Skamil		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1311.36Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
1321.36Skamil		                      child);
1331.36Skamil		break;
1341.36Skamil	}
1351.1Skamil
1361.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1371.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
1381.1Skamil}
1391.1Skamil
1401.33Skamil#define TRACEME_RAISE(test, sig)						\
1411.33SkamilATF_TC(test);									\
1421.33SkamilATF_TC_HEAD(test, tc)								\
1431.33Skamil{										\
1441.33Skamil	atf_tc_set_md_var(tc, "descr",						\
1451.33Skamil	    "Verify " #sig " followed by _exit(2) in a child");			\
1461.33Skamil}										\
1471.33Skamil										\
1481.33SkamilATF_TC_BODY(test, tc)								\
1491.33Skamil{										\
1501.33Skamil										\
1511.33Skamil	traceme_raise(sig);							\
1521.33Skamil}
1531.33Skamil
1541.36SkamilTRACEME_RAISE(traceme_raise1, SIGKILL) /* non-maskable */
1551.33SkamilTRACEME_RAISE(traceme_raise2, SIGSTOP) /* non-maskable */
1561.33SkamilTRACEME_RAISE(traceme_raise3, SIGABRT) /* regular abort trap */
1571.33SkamilTRACEME_RAISE(traceme_raise4, SIGHUP)  /* hangup */
1581.33SkamilTRACEME_RAISE(traceme_raise5, SIGCONT) /* continued? */
1591.33Skamil
1601.34Skamil/// ----------------------------------------------------------------------------
1611.1Skamil
1621.1Skamilstatic void
1631.34Skamiltraceme_sighandler_catch(int sigsent, void (*sah)(int arg), int *traceme_caught)
1641.1Skamil{
1651.1Skamil	const int exitval = 5;
1661.34Skamil	const int sigval = SIGSTOP;
1671.1Skamil	pid_t child, wpid;
1681.1Skamil	struct sigaction sa;
1691.1Skamil#if defined(TWAIT_HAVE_STATUS)
1701.1Skamil	int status;
1711.1Skamil#endif
1721.1Skamil
1731.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
1741.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
1751.1Skamil	if (child == 0) {
1761.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
1771.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
1781.1Skamil
1791.34Skamil		sa.sa_handler = sah;
1801.1Skamil		sa.sa_flags = SA_SIGINFO;
1811.1Skamil		sigemptyset(&sa.sa_mask);
1821.1Skamil
1831.1Skamil		FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1);
1841.1Skamil
1851.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
1861.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
1871.1Skamil
1881.34Skamil		FORKEE_ASSERT_EQ(*traceme_caught, 1);
1891.1Skamil
1901.13Schristos		DPRINTF("Before exiting of the child process\n");
1911.1Skamil		_exit(exitval);
1921.1Skamil	}
1931.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
1941.1Skamil
1951.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1961.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1971.1Skamil
1981.1Skamil	validate_status_stopped(status, sigval);
1991.1Skamil
2001.13Schristos	DPRINTF("Before resuming the child process where it left off and with "
2011.1Skamil	    "signal %s to be sent\n", strsignal(sigsent));
2021.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
2031.1Skamil
2041.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2051.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2061.1Skamil
2071.1Skamil	validate_status_exited(status, exitval);
2081.1Skamil
2091.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
2101.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
2111.1Skamil}
2121.1Skamil
2131.34Skamil#define TRACEME_SIGHANDLER_CATCH(test, sig)					\
2141.34SkamilATF_TC(test);									\
2151.34SkamilATF_TC_HEAD(test, tc)								\
2161.34Skamil{										\
2171.34Skamil	atf_tc_set_md_var(tc, "descr",						\
2181.34Skamil	    "Verify that a signal " #sig " emitted by a tracer to a child is "	\
2191.34Skamil	    "handled correctly and caught by a signal handler");		\
2201.34Skamil}										\
2211.34Skamil										\
2221.34Skamilstatic int test##_caught = 0;							\
2231.34Skamil										\
2241.34Skamilstatic void									\
2251.34Skamiltest##_sighandler(int arg)							\
2261.34Skamil{										\
2271.34Skamil	FORKEE_ASSERT_EQ(arg, sig);						\
2281.34Skamil										\
2291.34Skamil	++ test##_caught;							\
2301.34Skamil}										\
2311.34Skamil										\
2321.34SkamilATF_TC_BODY(test, tc)								\
2331.34Skamil{										\
2341.34Skamil										\
2351.34Skamil	traceme_sighandler_catch(sig, test##_sighandler, & test##_caught);	\
2361.34Skamil}
2371.34Skamil
2381.34Skamil// A signal handler for SIGKILL and SIGSTOP cannot be registered.
2391.34SkamilTRACEME_SIGHANDLER_CATCH(traceme_sighandler_catch1, SIGABRT) /* abort trap */
2401.34SkamilTRACEME_SIGHANDLER_CATCH(traceme_sighandler_catch2, SIGHUP)  /* hangup */
2411.34SkamilTRACEME_SIGHANDLER_CATCH(traceme_sighandler_catch3, SIGCONT) /* continued? */
2421.34Skamil
2431.34Skamil/// ----------------------------------------------------------------------------
2441.34Skamil
2451.35Skamilstatic void
2461.35Skamiltraceme_signal_nohandler(int sigsent)
2471.1Skamil{
2481.35Skamil	const int sigval = SIGSTOP;
2491.35Skamil	int exitval = 0;
2501.1Skamil	pid_t child, wpid;
2511.1Skamil#if defined(TWAIT_HAVE_STATUS)
2521.1Skamil	int status;
2531.35Skamil	int expect_core = (sigsent == SIGABRT) ? 1 : 0;
2541.1Skamil#endif
2551.1Skamil
2561.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
2571.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
2581.1Skamil	if (child == 0) {
2591.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
2601.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
2611.1Skamil
2621.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
2631.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
2641.1Skamil
2651.35Skamil		switch (sigsent) {
2661.35Skamil		case SIGCONT:
2671.35Skamil			_exit(exitval);
2681.35Skamil		default:
2691.35Skamil			/* NOTREACHED */
2701.35Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
2711.35Skamil		}
2721.1Skamil	}
2731.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
2741.1Skamil
2751.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2761.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2771.1Skamil
2781.1Skamil	validate_status_stopped(status, sigval);
2791.1Skamil
2801.13Schristos	DPRINTF("Before resuming the child process where it left off and with "
2811.1Skamil	    "signal %s to be sent\n", strsignal(sigsent));
2821.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
2831.1Skamil
2841.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2851.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2861.1Skamil
2871.35Skamil	switch (sigsent) {
2881.35Skamil	case SIGCONT:
2891.35Skamil		validate_status_exited(status, exitval);
2901.35Skamil		break;
2911.35Skamil	default:
2921.35Skamil		validate_status_signaled(status, sigsent, expect_core);
2931.35Skamil		break;
2941.35Skamil	}
2951.1Skamil
2961.13Schristos	DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME);
2971.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
2981.1Skamil}
2991.1Skamil
3001.35Skamil#define TRACEME_SIGNAL_NOHANDLER(test, sig)					\
3011.35SkamilATF_TC(test);									\
3021.35SkamilATF_TC_HEAD(test, tc)								\
3031.35Skamil{										\
3041.35Skamil	atf_tc_set_md_var(tc, "descr",						\
3051.35Skamil	    "Verify that a signal " #sig " emitted by a tracer to a child is "	\
3061.35Skamil	    "handled correctly in a child without a signal handler");		\
3071.35Skamil}										\
3081.35Skamil										\
3091.35SkamilATF_TC_BODY(test, tc)								\
3101.35Skamil{										\
3111.35Skamil										\
3121.35Skamil	traceme_signal_nohandler(sig);						\
3131.35Skamil}
3141.35Skamil
3151.35SkamilTRACEME_SIGNAL_NOHANDLER(traceme_signal_nohandler1, SIGKILL) /* non-maskable */
3161.35Skamil//TRACEME_SIGNAL_NOHANDLER(traceme_signal_nohandler2, SIGSTOP) /* non-maskable */
3171.35SkamilTRACEME_SIGNAL_NOHANDLER(traceme_signal_nohandler3, SIGABRT) /* abort trap */
3181.35SkamilTRACEME_SIGNAL_NOHANDLER(traceme_signal_nohandler4, SIGHUP)  /* hangup */
3191.35SkamilTRACEME_SIGNAL_NOHANDLER(traceme_signal_nohandler5, SIGCONT) /* continued? */
3201.35Skamil
3211.35Skamil/// ----------------------------------------------------------------------------
3221.35Skamil
3231.37SkamilATF_TC(traceme_pid1_parent);
3241.37SkamilATF_TC_HEAD(traceme_pid1_parent, tc)
3251.37Skamil{
3261.37Skamil	atf_tc_set_md_var(tc, "descr",
3271.37Skamil	    "Verify that PT_TRACE_ME is not allowed when our parent is PID1");
3281.37Skamil}
3291.37Skamil
3301.37SkamilATF_TC_BODY(traceme_pid1_parent, tc)
3311.37Skamil{
3321.37Skamil	struct msg_fds parent_child;
3331.37Skamil	int exitval_child1 = 1, exitval_child2 = 2;
3341.37Skamil	pid_t child1, child2, wpid;
3351.37Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
3361.37Skamil#if defined(TWAIT_HAVE_STATUS)
3371.37Skamil	int status;
3381.37Skamil#endif
3391.37Skamil
3401.37Skamil	SYSCALL_REQUIRE(msg_open(&parent_child) == 0);
3411.37Skamil
3421.37Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
3431.37Skamil	SYSCALL_REQUIRE((child1 = fork()) != -1);
3441.37Skamil	if (child1 == 0) {
3451.37Skamil		DPRINTF("Before forking process PID=%d\n", getpid());
3461.37Skamil		SYSCALL_REQUIRE((child2 = fork()) != -1);
3471.37Skamil		if (child2 != 0) {
3481.37Skamil			DPRINTF("Parent process PID=%d, child2's PID=%d\n",
3491.37Skamil			        getpid(), child2);
3501.37Skamil			_exit(exitval_child1);
3511.37Skamil		}
3521.37Skamil		CHILD_FROM_PARENT("exit child1", parent_child, msg);
3531.37Skamil
3541.37Skamil		DPRINTF("Assert that our parent is PID1 (initproc)\n");
3551.37Skamil		FORKEE_ASSERT_EQ(getppid(), 1);
3561.37Skamil
3571.37Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
3581.37Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) == -1);
3591.37Skamil		SYSCALL_REQUIRE_ERRNO(errno, EPERM);
3601.37Skamil
3611.37Skamil		CHILD_TO_PARENT("child2 exiting", parent_child, msg);
3621.37Skamil
3631.37Skamil		_exit(exitval_child2);
3641.37Skamil	}
3651.37Skamil	DPRINTF("Parent process PID=%d, child1's PID=%d\n", getpid(), child1);
3661.37Skamil
3671.37Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3681.37Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child1, &status, WEXITED),
3691.37Skamil	                      child1);
3701.37Skamil
3711.37Skamil	validate_status_exited(status, exitval_child1);
3721.37Skamil
3731.37Skamil	DPRINTF("Notify that child1 is dead\n");
3741.37Skamil	PARENT_TO_CHILD("exit child1", parent_child, msg);
3751.37Skamil
3761.37Skamil	DPRINTF("Wait for exiting of child2\n");
3771.37Skamil	PARENT_FROM_CHILD("child2 exiting", parent_child, msg);
3781.37Skamil}
3791.37Skamil
3801.37Skamil/// ----------------------------------------------------------------------------
3811.37Skamil
3821.40Skamilstatic void
3831.40Skamiltraceme_vfork_raise(int sigval)
3841.40Skamil{
3851.40Skamil	const int exitval = 5;
3861.40Skamil	pid_t child, wpid;
3871.40Skamil#if defined(TWAIT_HAVE_STATUS)
3881.40Skamil	int status;
3891.40Skamil	int expect_core = (sigval == SIGABRT) ? 1 : 0;
3901.40Skamil#endif
3911.40Skamil
3921.40Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
3931.40Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
3941.40Skamil	if (child == 0) {
3951.40Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
3961.40Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
3971.40Skamil
3981.40Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
3991.40Skamil		FORKEE_ASSERT(raise(sigval) == 0);
4001.40Skamil
4011.40Skamil		switch (sigval) {
4021.40Skamil		case SIGKILL:
4031.40Skamil		case SIGABRT:
4041.40Skamil		case SIGHUP:
4051.40Skamil			/* NOTREACHED */
4061.40Skamil			FORKEE_ASSERTX(0 && "This shall not be reached");
4071.40Skamil		default:
4081.40Skamil			DPRINTF("Before exiting of the child process\n");
4091.40Skamil			_exit(exitval);
4101.40Skamil		}
4111.40Skamil	}
4121.40Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
4131.40Skamil
4141.40Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4151.40Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4161.40Skamil
4171.40Skamil	switch (sigval) {
4181.40Skamil	case SIGKILL:
4191.40Skamil	case SIGABRT:
4201.40Skamil	case SIGHUP:
4211.40Skamil		validate_status_signaled(status, sigval, expect_core);
4221.40Skamil		break;
4231.40Skamil	case SIGSTOP:
4241.40Skamil	case SIGCONT:
4251.40Skamil		validate_status_exited(status, exitval);
4261.40Skamil		break;
4271.40Skamil	default:
4281.40Skamil		/* NOTREACHED */
4291.40Skamil		ATF_REQUIRE(0 && "NOT IMPLEMENTED");
4301.40Skamil		break;
4311.40Skamil	}
4321.40Skamil
4331.40Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4341.40Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
4351.40Skamil}
4361.40Skamil
4371.40Skamil#define TRACEME_VFORK_RAISE(test, sig)						\
4381.40SkamilATF_TC(test);									\
4391.40SkamilATF_TC_HEAD(test, tc)								\
4401.40Skamil{										\
4411.40Skamil	atf_tc_set_md_var(tc, "descr",						\
4421.42Skamil	    "Verify PT_TRACE_ME followed by raise of " #sig " in a vfork(2)ed "	\
4431.42Skamil	    "child");								\
4441.40Skamil}										\
4451.40Skamil										\
4461.40SkamilATF_TC_BODY(test, tc)								\
4471.40Skamil{										\
4481.40Skamil										\
4491.40Skamil	traceme_vfork_raise(sig);						\
4501.40Skamil}
4511.40Skamil
4521.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise1, SIGKILL) /* non-maskable */
4531.40Skamil// TRACEME_VFORK_RAISE(traceme_vfork_raise2, SIGSTOP) /* non-maskable */ // TODO
4541.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise3, SIGABRT) /* regular abort trap */
4551.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise4, SIGHUP)  /* hangup */
4561.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise5, SIGCONT) /* continued? */
4571.40Skamil
4581.40Skamil/// ----------------------------------------------------------------------------
4591.40Skamil
4601.41SkamilATF_TC(traceme_vfork_breakpoint);
4611.41SkamilATF_TC_HEAD(traceme_vfork_breakpoint, tc)
4621.41Skamil{
4631.41Skamil	atf_tc_set_md_var(tc, "descr",
4641.41Skamil	    "Verify software breakpoint in a vfork(2)ed child");
4651.41Skamil}
4661.41Skamil
4671.41SkamilATF_TC_BODY(traceme_vfork_breakpoint, tc)
4681.41Skamil{
4691.41Skamil	pid_t child, wpid;
4701.41Skamil#if defined(TWAIT_HAVE_STATUS)
4711.41Skamil	int status;
4721.41Skamil#endif
4731.41Skamil
4741.41Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
4751.41Skamil	SYSCALL_REQUIRE((child = vfork()) != -1);
4761.41Skamil	if (child == 0) {
4771.41Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
4781.41Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
4791.41Skamil
4801.41Skamil		DPRINTF("Before executing a software breakpoint\n");
4811.41Skamil#ifdef PTRACE_BREAKPOINT_ASM
4821.41Skamil		PTRACE_BREAKPOINT_ASM;
4831.41Skamil#else
4841.41Skamil		/* port me */
4851.41Skamil#endif
4861.41Skamil
4871.41Skamil		/* NOTREACHED */
4881.41Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
4891.41Skamil	}
4901.41Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
4911.41Skamil
4921.41Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4931.41Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4941.41Skamil
4951.41Skamil	validate_status_signaled(status, SIGTRAP, 1);
4961.41Skamil
4971.41Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
4981.41Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
4991.41Skamil}
5001.41Skamil
5011.41Skamil/// ----------------------------------------------------------------------------
5021.41Skamil
5031.1Skamil#if defined(TWAIT_HAVE_PID)
5041.1SkamilATF_TC(attach1);
5051.1SkamilATF_TC_HEAD(attach1, tc)
5061.1Skamil{
5071.1Skamil	atf_tc_set_md_var(tc, "descr",
5081.1Skamil	    "Assert that tracer sees process termination before the parent");
5091.1Skamil}
5101.1Skamil
5111.26Skamilstatic void
5121.26Skamilattach1_raw(bool raw)
5131.1Skamil{
5141.1Skamil	struct msg_fds parent_tracee, parent_tracer;
5151.1Skamil	const int exitval_tracee = 5;
5161.1Skamil	const int exitval_tracer = 10;
5171.1Skamil	pid_t tracee, tracer, wpid;
5181.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
5191.1Skamil#if defined(TWAIT_HAVE_STATUS)
5201.1Skamil	int status;
5211.1Skamil#endif
5221.1Skamil
5231.13Schristos	DPRINTF("Spawn tracee\n");
5241.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
5251.1Skamil	tracee = atf_utils_fork();
5261.1Skamil	if (tracee == 0) {
5271.1Skamil		// Wait for parent to let us exit
5281.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
5291.1Skamil		_exit(exitval_tracee);
5301.1Skamil	}
5311.1Skamil
5321.13Schristos	DPRINTF("Spawn debugger\n");
5331.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
5341.1Skamil	tracer = atf_utils_fork();
5351.1Skamil	if (tracer == 0) {
5361.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
5371.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
5381.1Skamil
5391.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
5401.1Skamil		FORKEE_REQUIRE_SUCCESS(
5411.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
5421.1Skamil
5431.1Skamil		forkee_status_stopped(status, SIGSTOP);
5441.1Skamil
5451.1Skamil		/* Resume tracee with PT_CONTINUE */
5461.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
5471.1Skamil
5481.1Skamil		/* Inform parent that tracer has attached to tracee */
5491.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
5501.1Skamil
5511.1Skamil		/* Wait for parent to tell use that tracee should have exited */
5521.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
5531.1Skamil
5541.1Skamil		/* Wait for tracee and assert that it exited */
5551.1Skamil		FORKEE_REQUIRE_SUCCESS(
5561.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
5571.1Skamil
5581.1Skamil		forkee_status_exited(status, exitval_tracee);
5591.13Schristos		DPRINTF("Tracee %d exited with %d\n", tracee, exitval_tracee);
5601.1Skamil
5611.13Schristos		DPRINTF("Before exiting of the tracer process\n");
5621.1Skamil		_exit(exitval_tracer);
5631.1Skamil	}
5641.1Skamil
5651.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
5661.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
5671.1Skamil
5681.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
5691.1Skamil	PARENT_TO_CHILD("exit tracee", parent_tracee,  msg);
5701.1Skamil
5711.13Schristos	DPRINTF("Detect that tracee is zombie\n");
5721.26Skamil	if (raw)
5731.26Skamil		await_zombie_raw(tracee, 0);
5741.26Skamil	else
5751.26Skamil		await_zombie(tracee);
5761.1Skamil
5771.13Schristos	DPRINTF("Assert that there is no status about tracee %d - "
5781.1Skamil	    "Tracer must detect zombie first - calling %s()\n", tracee,
5791.1Skamil	    TWAIT_FNAME);
5801.1Skamil	TWAIT_REQUIRE_SUCCESS(
5811.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
5821.1Skamil
5831.13Schristos	DPRINTF("Tell the tracer child should have exited\n");
5841.1Skamil	PARENT_TO_CHILD("wait for tracee exit", parent_tracer,  msg);
5851.13Schristos	DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n",
5861.1Skamil	    TWAIT_FNAME);
5871.1Skamil
5881.13Schristos	DPRINTF("Wait from tracer child to complete waiting for tracee\n");
5891.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
5901.1Skamil	    tracer);
5911.1Skamil
5921.1Skamil	validate_status_exited(status, exitval_tracer);
5931.1Skamil
5941.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
5951.1Skamil	    TWAIT_FNAME);
5961.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
5971.1Skamil	    tracee);
5981.1Skamil
5991.1Skamil	validate_status_exited(status, exitval_tracee);
6001.1Skamil
6011.1Skamil	msg_close(&parent_tracer);
6021.1Skamil	msg_close(&parent_tracee);
6031.1Skamil}
6041.26Skamil
6051.26SkamilATF_TC_BODY(attach1, tc)
6061.26Skamil{
6071.26Skamil
6081.26Skamil	/* Reuse this test with race1 */
6091.26Skamil	attach1_raw(false);
6101.26Skamil}
6111.26Skamil
6121.1Skamil#endif
6131.1Skamil
6141.1Skamil#if defined(TWAIT_HAVE_PID)
6151.1SkamilATF_TC(attach2);
6161.1SkamilATF_TC_HEAD(attach2, tc)
6171.1Skamil{
6181.1Skamil	atf_tc_set_md_var(tc, "descr",
6191.1Skamil	    "Assert that any tracer sees process termination before its "
6201.1Skamil	    "parent");
6211.1Skamil}
6221.1Skamil
6231.1SkamilATF_TC_BODY(attach2, tc)
6241.1Skamil{
6251.1Skamil	struct msg_fds parent_tracer, parent_tracee;
6261.1Skamil	const int exitval_tracee = 5;
6271.1Skamil	const int exitval_tracer1 = 10, exitval_tracer2 = 20;
6281.1Skamil	pid_t tracee, tracer, wpid;
6291.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
6301.1Skamil#if defined(TWAIT_HAVE_STATUS)
6311.1Skamil	int status;
6321.1Skamil#endif
6331.1Skamil
6341.13Schristos	DPRINTF("Spawn tracee\n");
6351.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
6361.1Skamil	tracee = atf_utils_fork();
6371.1Skamil	if (tracee == 0) {
6381.1Skamil		/* Wait for message from the parent */
6391.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
6401.1Skamil		_exit(exitval_tracee);
6411.1Skamil	}
6421.1Skamil
6431.13Schristos	DPRINTF("Spawn debugger\n");
6441.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
6451.1Skamil	tracer = atf_utils_fork();
6461.1Skamil	if (tracer == 0) {
6471.1Skamil		/* Fork again and drop parent to reattach to PID 1 */
6481.1Skamil		tracer = atf_utils_fork();
6491.1Skamil		if (tracer != 0)
6501.1Skamil			_exit(exitval_tracer1);
6511.1Skamil
6521.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
6531.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
6541.1Skamil
6551.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
6561.1Skamil		FORKEE_REQUIRE_SUCCESS(
6571.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
6581.1Skamil
6591.1Skamil		forkee_status_stopped(status, SIGSTOP);
6601.1Skamil
6611.1Skamil		/* Resume tracee with PT_CONTINUE */
6621.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
6631.1Skamil
6641.1Skamil		/* Inform parent that tracer has attached to tracee */
6651.1Skamil		CHILD_TO_PARENT("Message 1", parent_tracer, msg);
6661.1Skamil		CHILD_FROM_PARENT("Message 2", parent_tracer, msg);
6671.1Skamil
6681.1Skamil		/* Wait for tracee and assert that it exited */
6691.1Skamil		FORKEE_REQUIRE_SUCCESS(
6701.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
6711.1Skamil
6721.1Skamil		forkee_status_exited(status, exitval_tracee);
6731.1Skamil
6741.13Schristos		DPRINTF("Before exiting of the tracer process\n");
6751.1Skamil		_exit(exitval_tracer2);
6761.1Skamil	}
6771.13Schristos	DPRINTF("Wait for the tracer process (direct child) to exit calling "
6781.1Skamil	    "%s()\n", TWAIT_FNAME);
6791.1Skamil	TWAIT_REQUIRE_SUCCESS(
6801.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
6811.1Skamil
6821.1Skamil	validate_status_exited(status, exitval_tracer1);
6831.1Skamil
6841.13Schristos	DPRINTF("Wait for the non-exited tracee process with %s()\n",
6851.1Skamil	    TWAIT_FNAME);
6861.1Skamil	TWAIT_REQUIRE_SUCCESS(
6871.1Skamil	    wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0);
6881.1Skamil
6891.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
6901.1Skamil	PARENT_FROM_CHILD("Message 1", parent_tracer, msg);
6911.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
6921.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
6931.1Skamil
6941.13Schristos	DPRINTF("Detect that tracee is zombie\n");
6951.1Skamil	await_zombie(tracee);
6961.1Skamil
6971.13Schristos	DPRINTF("Assert that there is no status about tracee - "
6981.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
6991.1Skamil	TWAIT_REQUIRE_SUCCESS(
7001.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
7011.1Skamil
7021.13Schristos	DPRINTF("Resume the tracer and let it detect exited tracee\n");
7031.1Skamil	PARENT_TO_CHILD("Message 2", parent_tracer, msg);
7041.1Skamil
7051.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
7061.1Skamil	    TWAIT_FNAME);
7071.24Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0),
7081.1Skamil	    tracee);
7091.1Skamil
7101.1Skamil	validate_status_exited(status, exitval_tracee);
7111.1Skamil
7121.1Skamil	msg_close(&parent_tracer);
7131.1Skamil	msg_close(&parent_tracee);
7141.1Skamil}
7151.1Skamil#endif
7161.1Skamil
7171.1SkamilATF_TC(attach3);
7181.1SkamilATF_TC_HEAD(attach3, tc)
7191.1Skamil{
7201.1Skamil	atf_tc_set_md_var(tc, "descr",
7211.1Skamil	    "Assert that tracer parent can PT_ATTACH to its child");
7221.1Skamil}
7231.1Skamil
7241.1SkamilATF_TC_BODY(attach3, tc)
7251.1Skamil{
7261.1Skamil	struct msg_fds parent_tracee;
7271.1Skamil	const int exitval_tracee = 5;
7281.1Skamil	pid_t tracee, wpid;
7291.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
7301.1Skamil#if defined(TWAIT_HAVE_STATUS)
7311.1Skamil	int status;
7321.1Skamil#endif
7331.1Skamil
7341.13Schristos	DPRINTF("Spawn tracee\n");
7351.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
7361.1Skamil	tracee = atf_utils_fork();
7371.1Skamil	if (tracee == 0) {
7381.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
7391.13Schristos		DPRINTF("Parent should now attach to tracee\n");
7401.1Skamil
7411.1Skamil		CHILD_FROM_PARENT("Message 2", parent_tracee, msg);
7421.1Skamil		/* Wait for message from the parent */
7431.1Skamil		_exit(exitval_tracee);
7441.1Skamil	}
7451.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
7461.1Skamil
7471.13Schristos	DPRINTF("Before calling PT_ATTACH for tracee %d\n", tracee);
7481.13Schristos	SYSCALL_REQUIRE(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
7491.1Skamil
7501.13Schristos	DPRINTF("Wait for the stopped tracee process with %s()\n",
7511.1Skamil	    TWAIT_FNAME);
7521.1Skamil	TWAIT_REQUIRE_SUCCESS(
7531.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
7541.1Skamil
7551.1Skamil	validate_status_stopped(status, SIGSTOP);
7561.1Skamil
7571.13Schristos	DPRINTF("Resume tracee with PT_CONTINUE\n");
7581.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
7591.1Skamil
7601.13Schristos	DPRINTF("Let the tracee exit now\n");
7611.1Skamil	PARENT_TO_CHILD("Message 2", parent_tracee, msg);
7621.1Skamil
7631.13Schristos	DPRINTF("Wait for tracee to exit with %s()\n", TWAIT_FNAME);
7641.1Skamil	TWAIT_REQUIRE_SUCCESS(
7651.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
7661.1Skamil
7671.1Skamil	validate_status_exited(status, exitval_tracee);
7681.1Skamil
7691.13Schristos	DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME);
7701.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
7711.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, 0));
7721.1Skamil
7731.1Skamil	msg_close(&parent_tracee);
7741.1Skamil}
7751.1Skamil
7761.1SkamilATF_TC(attach4);
7771.1SkamilATF_TC_HEAD(attach4, tc)
7781.1Skamil{
7791.1Skamil	atf_tc_set_md_var(tc, "descr",
7801.1Skamil	    "Assert that tracer child can PT_ATTACH to its parent");
7811.1Skamil}
7821.1Skamil
7831.1SkamilATF_TC_BODY(attach4, tc)
7841.1Skamil{
7851.1Skamil	struct msg_fds parent_tracee;
7861.1Skamil	const int exitval_tracer = 5;
7871.1Skamil	pid_t tracer, wpid;
7881.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
7891.1Skamil#if defined(TWAIT_HAVE_STATUS)
7901.1Skamil	int status;
7911.1Skamil#endif
7921.1Skamil
7931.13Schristos	DPRINTF("Spawn tracer\n");
7941.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
7951.1Skamil	tracer = atf_utils_fork();
7961.1Skamil	if (tracer == 0) {
7971.1Skamil
7981.1Skamil		/* Wait for message from the parent */
7991.1Skamil		CHILD_FROM_PARENT("Message 1", parent_tracee, msg);
8001.1Skamil
8011.13Schristos		DPRINTF("Attach to parent PID %d with PT_ATTACH from child\n",
8021.1Skamil		    getppid());
8031.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, getppid(), NULL, 0) != -1);
8041.1Skamil
8051.13Schristos		DPRINTF("Wait for the stopped parent process with %s()\n",
8061.1Skamil		    TWAIT_FNAME);
8071.1Skamil		FORKEE_REQUIRE_SUCCESS(
8081.1Skamil		    wpid = TWAIT_GENERIC(getppid(), &status, 0), getppid());
8091.1Skamil
8101.1Skamil		forkee_status_stopped(status, SIGSTOP);
8111.1Skamil
8121.13Schristos		DPRINTF("Resume parent with PT_DETACH\n");
8131.1Skamil		FORKEE_ASSERT(ptrace(PT_DETACH, getppid(), (void *)1, 0)
8141.1Skamil		    != -1);
8151.1Skamil
8161.1Skamil		/* Tell parent we are ready */
8171.1Skamil		CHILD_TO_PARENT("Message 1", parent_tracee, msg);
8181.1Skamil
8191.1Skamil		_exit(exitval_tracer);
8201.1Skamil	}
8211.1Skamil
8221.13Schristos	DPRINTF("Wait for the tracer to become ready\n");
8231.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
8241.13Schristos	DPRINTF("Allow the tracer to exit now\n");
8251.1Skamil	PARENT_FROM_CHILD("Message 1", parent_tracee, msg);
8261.1Skamil
8271.13Schristos	DPRINTF("Wait for tracer to exit with %s()\n", TWAIT_FNAME);
8281.1Skamil	TWAIT_REQUIRE_SUCCESS(
8291.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0), tracer);
8301.1Skamil
8311.1Skamil	validate_status_exited(status, exitval_tracer);
8321.1Skamil
8331.13Schristos	DPRINTF("Before calling %s() for tracer\n", TWAIT_FNAME);
8341.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
8351.1Skamil	    wpid = TWAIT_GENERIC(tracer, &status, 0));
8361.1Skamil
8371.1Skamil	msg_close(&parent_tracee);
8381.1Skamil}
8391.1Skamil
8401.1Skamil#if defined(TWAIT_HAVE_PID)
8411.1SkamilATF_TC(attach5);
8421.1SkamilATF_TC_HEAD(attach5, tc)
8431.1Skamil{
8441.1Skamil	atf_tc_set_md_var(tc, "descr",
8451.1Skamil	    "Assert that tracer sees its parent when attached to tracer "
8461.1Skamil	    "(check getppid(2))");
8471.1Skamil}
8481.1Skamil
8491.1SkamilATF_TC_BODY(attach5, tc)
8501.1Skamil{
8511.1Skamil	struct msg_fds parent_tracer, parent_tracee;
8521.1Skamil	const int exitval_tracee = 5;
8531.1Skamil	const int exitval_tracer = 10;
8541.1Skamil	pid_t parent, tracee, tracer, wpid;
8551.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
8561.1Skamil#if defined(TWAIT_HAVE_STATUS)
8571.1Skamil	int status;
8581.1Skamil#endif
8591.1Skamil
8601.13Schristos	DPRINTF("Spawn tracee\n");
8611.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
8621.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
8631.1Skamil	tracee = atf_utils_fork();
8641.1Skamil	if (tracee == 0) {
8651.1Skamil		parent = getppid();
8661.1Skamil
8671.1Skamil		/* Emit message to the parent */
8681.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
8691.1Skamil		CHILD_FROM_PARENT("exit tracee", parent_tracee, msg);
8701.1Skamil
8711.1Skamil		FORKEE_ASSERT_EQ(parent, getppid());
8721.1Skamil
8731.1Skamil		_exit(exitval_tracee);
8741.1Skamil	}
8751.13Schristos	DPRINTF("Wait for child to record its parent identifier (pid)\n");
8761.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
8771.1Skamil
8781.13Schristos	DPRINTF("Spawn debugger\n");
8791.1Skamil	tracer = atf_utils_fork();
8801.1Skamil	if (tracer == 0) {
8811.1Skamil		/* No IPC to communicate with the child */
8821.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
8831.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
8841.1Skamil
8851.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
8861.1Skamil		FORKEE_REQUIRE_SUCCESS(
8871.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
8881.1Skamil
8891.1Skamil		forkee_status_stopped(status, SIGSTOP);
8901.1Skamil
8911.1Skamil		/* Resume tracee with PT_CONTINUE */
8921.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
8931.1Skamil
8941.1Skamil		/* Inform parent that tracer has attached to tracee */
8951.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
8961.1Skamil
8971.1Skamil		/* Wait for parent to tell use that tracee should have exited */
8981.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
8991.1Skamil
9001.1Skamil		/* Wait for tracee and assert that it exited */
9011.1Skamil		FORKEE_REQUIRE_SUCCESS(
9021.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
9031.1Skamil
9041.1Skamil		forkee_status_exited(status, exitval_tracee);
9051.1Skamil
9061.13Schristos		DPRINTF("Before exiting of the tracer process\n");
9071.1Skamil		_exit(exitval_tracer);
9081.1Skamil	}
9091.1Skamil
9101.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
9111.1Skamil	PARENT_FROM_CHILD("tracer ready",  parent_tracer, msg);
9121.1Skamil
9131.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
9141.1Skamil	PARENT_TO_CHILD("exit tracee",  parent_tracee, msg);
9151.1Skamil
9161.13Schristos	DPRINTF("Detect that tracee is zombie\n");
9171.1Skamil	await_zombie(tracee);
9181.1Skamil
9191.13Schristos	DPRINTF("Assert that there is no status about tracee - "
9201.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
9211.1Skamil	TWAIT_REQUIRE_SUCCESS(
9221.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
9231.1Skamil
9241.13Schristos	DPRINTF("Tell the tracer child should have exited\n");
9251.1Skamil	PARENT_TO_CHILD("wait for tracee exit",  parent_tracer, msg);
9261.1Skamil
9271.13Schristos	DPRINTF("Wait from tracer child to complete waiting for tracee\n");
9281.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
9291.1Skamil	    tracer);
9301.1Skamil
9311.1Skamil	validate_status_exited(status, exitval_tracer);
9321.1Skamil
9331.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
9341.1Skamil	    TWAIT_FNAME);
9351.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
9361.1Skamil	    tracee);
9371.1Skamil
9381.1Skamil	validate_status_exited(status, exitval_tracee);
9391.1Skamil
9401.1Skamil	msg_close(&parent_tracer);
9411.1Skamil	msg_close(&parent_tracee);
9421.1Skamil}
9431.1Skamil#endif
9441.1Skamil
9451.1Skamil#if defined(TWAIT_HAVE_PID)
9461.1SkamilATF_TC(attach6);
9471.1SkamilATF_TC_HEAD(attach6, tc)
9481.1Skamil{
9491.1Skamil	atf_tc_set_md_var(tc, "descr",
9501.1Skamil	    "Assert that tracer sees its parent when attached to tracer "
9511.1Skamil	    "(check sysctl(7) and struct kinfo_proc2)");
9521.1Skamil}
9531.1Skamil
9541.1SkamilATF_TC_BODY(attach6, tc)
9551.1Skamil{
9561.1Skamil	struct msg_fds parent_tracee, parent_tracer;
9571.1Skamil	const int exitval_tracee = 5;
9581.1Skamil	const int exitval_tracer = 10;
9591.1Skamil	pid_t parent, tracee, tracer, wpid;
9601.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
9611.1Skamil#if defined(TWAIT_HAVE_STATUS)
9621.1Skamil	int status;
9631.1Skamil#endif
9641.1Skamil	int name[CTL_MAXNAME];
9651.1Skamil	struct kinfo_proc2 kp;
9661.1Skamil	size_t len = sizeof(kp);
9671.1Skamil	unsigned int namelen;
9681.1Skamil
9691.13Schristos	DPRINTF("Spawn tracee\n");
9701.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
9711.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
9721.1Skamil	tracee = atf_utils_fork();
9731.1Skamil	if (tracee == 0) {
9741.1Skamil		parent = getppid();
9751.1Skamil
9761.1Skamil		/* Emit message to the parent */
9771.1Skamil		CHILD_TO_PARENT("Message 1", parent_tracee, msg);
9781.1Skamil		CHILD_FROM_PARENT("Message 2", parent_tracee, msg);
9791.1Skamil
9801.1Skamil		namelen = 0;
9811.1Skamil		name[namelen++] = CTL_KERN;
9821.1Skamil		name[namelen++] = KERN_PROC2;
9831.1Skamil		name[namelen++] = KERN_PROC_PID;
9841.1Skamil		name[namelen++] = getpid();
9851.1Skamil		name[namelen++] = len;
9861.1Skamil		name[namelen++] = 1;
9871.1Skamil
9881.1Skamil		FORKEE_ASSERT(sysctl(name, namelen, &kp, &len, NULL, 0) == 0);
9891.1Skamil		FORKEE_ASSERT_EQ(parent, kp.p_ppid);
9901.1Skamil
9911.1Skamil		_exit(exitval_tracee);
9921.1Skamil	}
9931.1Skamil
9941.13Schristos	DPRINTF("Wait for child to record its parent identifier (pid)\n");
9951.1Skamil	PARENT_FROM_CHILD("Message 1", parent_tracee, msg);
9961.1Skamil
9971.13Schristos	DPRINTF("Spawn debugger\n");
9981.1Skamil	tracer = atf_utils_fork();
9991.1Skamil	if (tracer == 0) {
10001.1Skamil		/* No IPC to communicate with the child */
10011.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
10021.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
10031.1Skamil
10041.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
10051.1Skamil		FORKEE_REQUIRE_SUCCESS(
10061.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
10071.1Skamil
10081.1Skamil		forkee_status_stopped(status, SIGSTOP);
10091.1Skamil
10101.1Skamil		/* Resume tracee with PT_CONTINUE */
10111.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
10121.1Skamil
10131.1Skamil		/* Inform parent that tracer has attached to tracee */
10141.1Skamil		CHILD_TO_PARENT("Message 1", parent_tracer, msg);
10151.1Skamil
10161.1Skamil		CHILD_FROM_PARENT("Message 2", parent_tracer, msg);
10171.1Skamil
10181.1Skamil		/* Wait for tracee and assert that it exited */
10191.1Skamil		FORKEE_REQUIRE_SUCCESS(
10201.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
10211.1Skamil
10221.1Skamil		forkee_status_exited(status, exitval_tracee);
10231.1Skamil
10241.13Schristos		DPRINTF("Before exiting of the tracer process\n");
10251.1Skamil		_exit(exitval_tracer);
10261.1Skamil	}
10271.1Skamil
10281.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
10291.1Skamil	PARENT_FROM_CHILD("Message 1", parent_tracer, msg);
10301.1Skamil
10311.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
10321.1Skamil	PARENT_TO_CHILD("Message 1", parent_tracee, msg);
10331.1Skamil
10341.13Schristos	DPRINTF("Detect that tracee is zombie\n");
10351.1Skamil	await_zombie(tracee);
10361.1Skamil
10371.13Schristos	DPRINTF("Assert that there is no status about tracee - "
10381.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
10391.1Skamil	TWAIT_REQUIRE_SUCCESS(
10401.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
10411.1Skamil
10421.13Schristos	DPRINTF("Resume the tracer and let it detect exited tracee\n");
10431.1Skamil	PARENT_TO_CHILD("Message 2", parent_tracer, msg);
10441.1Skamil
10451.13Schristos	DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n",
10461.1Skamil	    TWAIT_FNAME);
10471.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
10481.1Skamil	    tracer);
10491.1Skamil
10501.1Skamil	validate_status_exited(status, exitval_tracer);
10511.1Skamil
10521.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
10531.1Skamil	    TWAIT_FNAME);
10541.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
10551.1Skamil	    tracee);
10561.1Skamil
10571.1Skamil	validate_status_exited(status, exitval_tracee);
10581.1Skamil
10591.1Skamil	msg_close(&parent_tracee);
10601.1Skamil	msg_close(&parent_tracer);
10611.1Skamil}
10621.1Skamil#endif
10631.1Skamil
10641.1Skamil#if defined(TWAIT_HAVE_PID)
10651.1SkamilATF_TC(attach7);
10661.1SkamilATF_TC_HEAD(attach7, tc)
10671.1Skamil{
10681.1Skamil	atf_tc_set_md_var(tc, "descr",
10691.1Skamil	    "Assert that tracer sees its parent when attached to tracer "
10701.1Skamil	    "(check /proc/curproc/status 3rd column)");
10711.1Skamil}
10721.1Skamil
10731.1SkamilATF_TC_BODY(attach7, tc)
10741.1Skamil{
10751.1Skamil	struct msg_fds parent_tracee, parent_tracer;
10761.1Skamil	int rv;
10771.1Skamil	const int exitval_tracee = 5;
10781.1Skamil	const int exitval_tracer = 10;
10791.1Skamil	pid_t parent, tracee, tracer, wpid;
10801.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
10811.1Skamil#if defined(TWAIT_HAVE_STATUS)
10821.1Skamil	int status;
10831.1Skamil#endif
10841.1Skamil	FILE *fp;
10851.1Skamil	struct stat st;
10861.1Skamil	const char *fname = "/proc/curproc/status";
10871.1Skamil	char s_executable[MAXPATHLEN];
10881.1Skamil	int s_pid, s_ppid;
10891.1Skamil	/*
10901.1Skamil	 * Format:
10911.1Skamil	 *  EXECUTABLE PID PPID ...
10921.1Skamil	 */
10931.1Skamil
10941.13Schristos	SYSCALL_REQUIRE((rv = stat(fname, &st)) == 0 || (errno == ENOENT));
10951.1Skamil	if (rv != 0) {
10961.1Skamil		atf_tc_skip("/proc/curproc/status not found");
10971.1Skamil	}
10981.1Skamil
10991.13Schristos	DPRINTF("Spawn tracee\n");
11001.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
11011.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
11021.1Skamil	tracee = atf_utils_fork();
11031.1Skamil	if (tracee == 0) {
11041.1Skamil		parent = getppid();
11051.1Skamil
11061.1Skamil		// Wait for parent to let us exit
11071.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
11081.1Skamil		CHILD_FROM_PARENT("tracee exit", parent_tracee, msg);
11091.1Skamil
11101.1Skamil		FORKEE_ASSERT((fp = fopen(fname, "r")) != NULL);
11111.1Skamil		fscanf(fp, "%s %d %d", s_executable, &s_pid, &s_ppid);
11121.1Skamil		FORKEE_ASSERT(fclose(fp) == 0);
11131.1Skamil		FORKEE_ASSERT_EQ(parent, s_ppid);
11141.1Skamil
11151.1Skamil		_exit(exitval_tracee);
11161.1Skamil	}
11171.1Skamil
11181.13Schristos	DPRINTF("Wait for child to record its parent identifier (pid)\n");
11191.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
11201.1Skamil
11211.13Schristos	DPRINTF("Spawn debugger\n");
11221.1Skamil	tracer = atf_utils_fork();
11231.1Skamil	if (tracer == 0) {
11241.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
11251.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
11261.1Skamil
11271.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
11281.1Skamil		FORKEE_REQUIRE_SUCCESS(
11291.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
11301.1Skamil
11311.1Skamil		forkee_status_stopped(status, SIGSTOP);
11321.1Skamil
11331.1Skamil		/* Resume tracee with PT_CONTINUE */
11341.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
11351.1Skamil
11361.1Skamil		/* Inform parent that tracer has attached to tracee */
11371.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
11381.1Skamil
11391.1Skamil		/* Wait for parent to tell use that tracee should have exited */
11401.1Skamil		CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg);
11411.1Skamil
11421.1Skamil		/* Wait for tracee and assert that it exited */
11431.1Skamil		FORKEE_REQUIRE_SUCCESS(
11441.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
11451.1Skamil
11461.1Skamil		forkee_status_exited(status, exitval_tracee);
11471.1Skamil
11481.13Schristos		DPRINTF("Before exiting of the tracer process\n");
11491.1Skamil		_exit(exitval_tracer);
11501.1Skamil	}
11511.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
11521.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
11531.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
11541.1Skamil	PARENT_TO_CHILD("tracee exit", parent_tracee, msg);
11551.1Skamil
11561.13Schristos	DPRINTF("Detect that tracee is zombie\n");
11571.1Skamil	await_zombie(tracee);
11581.1Skamil
11591.13Schristos	DPRINTF("Assert that there is no status about tracee - "
11601.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
11611.1Skamil	TWAIT_REQUIRE_SUCCESS(
11621.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
11631.1Skamil
11641.13Schristos	DPRINTF("Resume the tracer and let it detect exited tracee\n");
11651.1Skamil	PARENT_TO_CHILD("Message 2", parent_tracer, msg);
11661.1Skamil
11671.13Schristos	DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n",
11681.1Skamil	    TWAIT_FNAME);
11691.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
11701.1Skamil	    tracer);
11711.1Skamil
11721.1Skamil	validate_status_exited(status, exitval_tracer);
11731.1Skamil
11741.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
11751.1Skamil	    TWAIT_FNAME);
11761.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
11771.1Skamil	    tracee);
11781.1Skamil
11791.1Skamil	validate_status_exited(status, exitval_tracee);
11801.1Skamil
11811.1Skamil	msg_close(&parent_tracee);
11821.1Skamil	msg_close(&parent_tracer);
11831.1Skamil}
11841.1Skamil#endif
11851.1Skamil
11861.1SkamilATF_TC(eventmask1);
11871.1SkamilATF_TC_HEAD(eventmask1, tc)
11881.1Skamil{
11891.1Skamil	atf_tc_set_md_var(tc, "descr",
11901.1Skamil	    "Verify that empty EVENT_MASK is preserved");
11911.1Skamil}
11921.1Skamil
11931.1SkamilATF_TC_BODY(eventmask1, tc)
11941.1Skamil{
11951.1Skamil	const int exitval = 5;
11961.1Skamil	const int sigval = SIGSTOP;
11971.1Skamil	pid_t child, wpid;
11981.1Skamil#if defined(TWAIT_HAVE_STATUS)
11991.1Skamil	int status;
12001.1Skamil#endif
12011.1Skamil	ptrace_event_t set_event, get_event;
12021.1Skamil	const int len = sizeof(ptrace_event_t);
12031.1Skamil
12041.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
12051.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
12061.1Skamil	if (child == 0) {
12071.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
12081.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
12091.1Skamil
12101.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
12111.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
12121.1Skamil
12131.13Schristos		DPRINTF("Before exiting of the child process\n");
12141.1Skamil		_exit(exitval);
12151.1Skamil	}
12161.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
12171.1Skamil
12181.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12191.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
12201.1Skamil
12211.1Skamil	validate_status_stopped(status, sigval);
12221.1Skamil
12231.1Skamil	set_event.pe_set_event = 0;
12241.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
12251.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
12261.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
12271.1Skamil
12281.13Schristos	DPRINTF("Before resuming the child process where it left off and "
12291.1Skamil	    "without signal to be sent\n");
12301.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
12311.1Skamil
12321.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12331.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
12341.1Skamil
12351.1Skamil	validate_status_exited(status, exitval);
12361.1Skamil
12371.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12381.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
12391.1Skamil}
12401.1Skamil
12411.1SkamilATF_TC(eventmask2);
12421.1SkamilATF_TC_HEAD(eventmask2, tc)
12431.1Skamil{
12441.1Skamil	atf_tc_set_md_var(tc, "descr",
12451.1Skamil	    "Verify that PTRACE_FORK in EVENT_MASK is preserved");
12461.1Skamil}
12471.1Skamil
12481.1SkamilATF_TC_BODY(eventmask2, tc)
12491.1Skamil{
12501.1Skamil	const int exitval = 5;
12511.1Skamil	const int sigval = SIGSTOP;
12521.1Skamil	pid_t child, wpid;
12531.1Skamil#if defined(TWAIT_HAVE_STATUS)
12541.1Skamil	int status;
12551.1Skamil#endif
12561.1Skamil	ptrace_event_t set_event, get_event;
12571.1Skamil	const int len = sizeof(ptrace_event_t);
12581.1Skamil
12591.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
12601.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
12611.1Skamil	if (child == 0) {
12621.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
12631.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
12641.1Skamil
12651.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
12661.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
12671.1Skamil
12681.13Schristos		DPRINTF("Before exiting of the child process\n");
12691.1Skamil		_exit(exitval);
12701.1Skamil	}
12711.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
12721.1Skamil
12731.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12741.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
12751.1Skamil
12761.1Skamil	validate_status_stopped(status, sigval);
12771.1Skamil
12781.1Skamil	set_event.pe_set_event = PTRACE_FORK;
12791.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
12801.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
12811.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
12821.1Skamil
12831.13Schristos	DPRINTF("Before resuming the child process where it left off and "
12841.1Skamil	    "without signal to be sent\n");
12851.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
12861.1Skamil
12871.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12881.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
12891.1Skamil
12901.1Skamil	validate_status_exited(status, exitval);
12911.1Skamil
12921.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
12931.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
12941.1Skamil}
12951.1Skamil
12961.1SkamilATF_TC(eventmask3);
12971.1SkamilATF_TC_HEAD(eventmask3, tc)
12981.1Skamil{
12991.1Skamil	atf_tc_set_md_var(tc, "descr",
13001.1Skamil	    "Verify that PTRACE_VFORK in EVENT_MASK is preserved");
13011.1Skamil}
13021.1Skamil
13031.1SkamilATF_TC_BODY(eventmask3, tc)
13041.1Skamil{
13051.1Skamil	const int exitval = 5;
13061.1Skamil	const int sigval = SIGSTOP;
13071.1Skamil	pid_t child, wpid;
13081.1Skamil#if defined(TWAIT_HAVE_STATUS)
13091.1Skamil	int status;
13101.1Skamil#endif
13111.1Skamil	ptrace_event_t set_event, get_event;
13121.1Skamil	const int len = sizeof(ptrace_event_t);
13131.1Skamil
13141.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
13151.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
13161.1Skamil	if (child == 0) {
13171.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
13181.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
13191.1Skamil
13201.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
13211.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
13221.1Skamil
13231.13Schristos		DPRINTF("Before exiting of the child process\n");
13241.1Skamil		_exit(exitval);
13251.1Skamil	}
13261.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
13271.1Skamil
13281.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
13291.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
13301.1Skamil
13311.1Skamil	validate_status_stopped(status, sigval);
13321.1Skamil
13331.1Skamil	set_event.pe_set_event = PTRACE_VFORK;
13341.38Skamil	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
13351.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
13361.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
13371.1Skamil
13381.13Schristos	DPRINTF("Before resuming the child process where it left off and "
13391.1Skamil	    "without signal to be sent\n");
13401.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
13411.1Skamil
13421.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
13431.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
13441.1Skamil
13451.1Skamil	validate_status_exited(status, exitval);
13461.1Skamil
13471.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
13481.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
13491.1Skamil}
13501.1Skamil
13511.1SkamilATF_TC(eventmask4);
13521.1SkamilATF_TC_HEAD(eventmask4, tc)
13531.1Skamil{
13541.1Skamil	atf_tc_set_md_var(tc, "descr",
13551.1Skamil	    "Verify that PTRACE_VFORK_DONE in EVENT_MASK is preserved");
13561.1Skamil}
13571.1Skamil
13581.1SkamilATF_TC_BODY(eventmask4, tc)
13591.1Skamil{
13601.1Skamil	const int exitval = 5;
13611.1Skamil	const int sigval = SIGSTOP;
13621.1Skamil	pid_t child, wpid;
13631.1Skamil#if defined(TWAIT_HAVE_STATUS)
13641.1Skamil	int status;
13651.1Skamil#endif
13661.1Skamil	ptrace_event_t set_event, get_event;
13671.1Skamil	const int len = sizeof(ptrace_event_t);
13681.1Skamil
13691.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
13701.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
13711.1Skamil	if (child == 0) {
13721.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
13731.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
13741.1Skamil
13751.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
13761.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
13771.1Skamil
13781.13Schristos		DPRINTF("Before exiting of the child process\n");
13791.1Skamil		_exit(exitval);
13801.1Skamil	}
13811.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
13821.1Skamil
13831.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
13841.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
13851.1Skamil
13861.1Skamil	validate_status_stopped(status, sigval);
13871.1Skamil
13881.1Skamil	set_event.pe_set_event = PTRACE_VFORK_DONE;
13891.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
13901.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
13911.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
13921.1Skamil
13931.13Schristos	DPRINTF("Before resuming the child process where it left off and "
13941.1Skamil	    "without signal to be sent\n");
13951.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
13961.1Skamil
13971.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
13981.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
13991.1Skamil
14001.1Skamil	validate_status_exited(status, exitval);
14011.1Skamil
14021.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14031.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
14041.1Skamil}
14051.1Skamil
14061.1SkamilATF_TC(eventmask5);
14071.1SkamilATF_TC_HEAD(eventmask5, tc)
14081.1Skamil{
14091.1Skamil	atf_tc_set_md_var(tc, "descr",
14101.1Skamil	    "Verify that PTRACE_LWP_CREATE in EVENT_MASK is preserved");
14111.1Skamil}
14121.1Skamil
14131.1SkamilATF_TC_BODY(eventmask5, tc)
14141.1Skamil{
14151.1Skamil	const int exitval = 5;
14161.1Skamil	const int sigval = SIGSTOP;
14171.1Skamil	pid_t child, wpid;
14181.1Skamil#if defined(TWAIT_HAVE_STATUS)
14191.1Skamil	int status;
14201.1Skamil#endif
14211.1Skamil	ptrace_event_t set_event, get_event;
14221.1Skamil	const int len = sizeof(ptrace_event_t);
14231.1Skamil
14241.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
14251.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
14261.1Skamil	if (child == 0) {
14271.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
14281.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
14291.1Skamil
14301.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
14311.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
14321.1Skamil
14331.13Schristos		DPRINTF("Before exiting of the child process\n");
14341.1Skamil		_exit(exitval);
14351.1Skamil	}
14361.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
14371.1Skamil
14381.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14391.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
14401.1Skamil
14411.1Skamil	validate_status_stopped(status, sigval);
14421.1Skamil
14431.1Skamil	set_event.pe_set_event = PTRACE_LWP_CREATE;
14441.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
14451.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
14461.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
14471.1Skamil
14481.13Schristos	DPRINTF("Before resuming the child process where it left off and "
14491.1Skamil	    "without signal to be sent\n");
14501.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
14511.1Skamil
14521.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14531.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
14541.1Skamil
14551.1Skamil	validate_status_exited(status, exitval);
14561.1Skamil
14571.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14581.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
14591.1Skamil}
14601.1Skamil
14611.1SkamilATF_TC(eventmask6);
14621.1SkamilATF_TC_HEAD(eventmask6, tc)
14631.1Skamil{
14641.1Skamil	atf_tc_set_md_var(tc, "descr",
14651.1Skamil	    "Verify that PTRACE_LWP_EXIT in EVENT_MASK is preserved");
14661.1Skamil}
14671.1Skamil
14681.1SkamilATF_TC_BODY(eventmask6, tc)
14691.1Skamil{
14701.1Skamil	const int exitval = 5;
14711.1Skamil	const int sigval = SIGSTOP;
14721.1Skamil	pid_t child, wpid;
14731.1Skamil#if defined(TWAIT_HAVE_STATUS)
14741.1Skamil	int status;
14751.1Skamil#endif
14761.1Skamil	ptrace_event_t set_event, get_event;
14771.1Skamil	const int len = sizeof(ptrace_event_t);
14781.1Skamil
14791.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
14801.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
14811.1Skamil	if (child == 0) {
14821.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
14831.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
14841.1Skamil
14851.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
14861.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
14871.1Skamil
14881.13Schristos		DPRINTF("Before exiting of the child process\n");
14891.1Skamil		_exit(exitval);
14901.1Skamil	}
14911.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
14921.1Skamil
14931.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
14941.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
14951.1Skamil
14961.1Skamil	validate_status_stopped(status, sigval);
14971.1Skamil
14981.1Skamil	set_event.pe_set_event = PTRACE_LWP_EXIT;
14991.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
15001.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
15011.1Skamil	ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
15021.1Skamil
15031.13Schristos	DPRINTF("Before resuming the child process where it left off and "
15041.1Skamil	    "without signal to be sent\n");
15051.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
15061.1Skamil
15071.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
15081.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
15091.1Skamil
15101.1Skamil	validate_status_exited(status, exitval);
15111.1Skamil
15121.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
15131.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
15141.1Skamil}
15151.1Skamil
15161.28Skamilstatic void
15171.32Skamilfork_body(pid_t (*fn)(void), bool trackfork, bool trackvfork,
15181.32Skamil          bool trackvforkdone, bool detachchild, bool detachparent)
15191.1Skamil{
15201.1Skamil	const int exitval = 5;
15211.1Skamil	const int exitval2 = 15;
15221.1Skamil	const int sigval = SIGSTOP;
15231.31Skamil	pid_t child, child2 = 0, wpid;
15241.1Skamil#if defined(TWAIT_HAVE_STATUS)
15251.1Skamil	int status;
15261.1Skamil#endif
15271.1Skamil	ptrace_state_t state;
15281.1Skamil	const int slen = sizeof(state);
15291.1Skamil	ptrace_event_t event;
15301.1Skamil	const int elen = sizeof(event);
15311.1Skamil
15321.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
15331.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
15341.1Skamil	if (child == 0) {
15351.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
15361.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
15371.1Skamil
15381.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
15391.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
15401.1Skamil
15411.30Skamil		FORKEE_ASSERT((child2 = (fn)()) != -1);
15421.1Skamil
15431.1Skamil		if (child2 == 0)
15441.1Skamil			_exit(exitval2);
15451.1Skamil
15461.1Skamil		FORKEE_REQUIRE_SUCCESS
15471.1Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
15481.1Skamil
15491.1Skamil		forkee_status_exited(status, exitval2);
15501.1Skamil
15511.13Schristos		DPRINTF("Before exiting of the child process\n");
15521.1Skamil		_exit(exitval);
15531.1Skamil	}
15541.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
15551.1Skamil
15561.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
15571.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
15581.1Skamil
15591.1Skamil	validate_status_stopped(status, sigval);
15601.1Skamil
15611.30Skamil	DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n",
15621.30Skamil	        trackfork ? "|PTRACE_FORK" : "",
15631.30Skamil	        trackvfork ? "|PTRACE_VFORK" : "",
15641.30Skamil	        trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child);
15651.30Skamil	event.pe_set_event = 0;
15661.30Skamil	if (trackfork)
15671.30Skamil		event.pe_set_event |= PTRACE_FORK;
15681.30Skamil	if (trackvfork)
15691.30Skamil		event.pe_set_event |= PTRACE_VFORK;
15701.30Skamil	if (trackvforkdone)
15711.30Skamil		event.pe_set_event |= PTRACE_VFORK_DONE;
15721.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
15731.1Skamil
15741.13Schristos	DPRINTF("Before resuming the child process where it left off and "
15751.1Skamil	    "without signal to be sent\n");
15761.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
15771.1Skamil
15781.29Skamil#if defined(TWAIT_HAVE_PID)
15791.31Skamil	if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) {
15801.29Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
15811.29Skamil		        child);
15821.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
15831.29Skamil		                      child);
15841.1Skamil
15851.29Skamil		validate_status_stopped(status, SIGTRAP);
15861.1Skamil
15871.29Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state,
15881.29Skamil		                       slen) != -1);
15891.31Skamil		if (trackfork && fn == fork) {
15901.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
15911.30Skamil			       PTRACE_FORK);
15921.30Skamil		}
15931.31Skamil		if (trackvfork && fn == vfork) {
15941.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
15951.30Skamil			       PTRACE_VFORK);
15961.30Skamil		}
15971.29Skamil
15981.29Skamil		child2 = state.pe_other_pid;
15991.30Skamil		DPRINTF("Reported ptrace event with forkee %d\n", child2);
16001.29Skamil
16011.29Skamil		DPRINTF("Before calling %s() for the forkee %d of the child "
16021.29Skamil		        "%d\n", TWAIT_FNAME, child2, child);
16031.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
16041.29Skamil		    child2);
16051.1Skamil
16061.29Skamil		validate_status_stopped(status, SIGTRAP);
16071.1Skamil
16081.29Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child2, &state,
16091.29Skamil		                       slen) != -1);
16101.31Skamil		if (trackfork && fn == fork) {
16111.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
16121.30Skamil			       PTRACE_FORK);
16131.30Skamil		}
16141.31Skamil		if (trackvfork && fn == vfork) {
16151.30Skamil			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
16161.30Skamil			       PTRACE_VFORK);
16171.30Skamil		}
16181.30Skamil
16191.29Skamil		ATF_REQUIRE_EQ(state.pe_other_pid, child);
16201.29Skamil
16211.29Skamil		DPRINTF("Before resuming the forkee process where it left off "
16221.29Skamil		    "and without signal to be sent\n");
16231.29Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0)
16241.29Skamil		                != -1);
16251.29Skamil
16261.29Skamil		DPRINTF("Before resuming the child process where it left off "
16271.29Skamil		        "and without signal to be sent\n");
16281.29Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
16291.30Skamil	}
16301.30Skamil#endif
16311.30Skamil
16321.31Skamil	if (trackvforkdone && fn == vfork) {
16331.30Skamil		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
16341.30Skamil		        child);
16351.30Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
16361.30Skamil		                      child);
16371.30Skamil
16381.30Skamil		validate_status_stopped(status, SIGTRAP);
16391.30Skamil
16401.30Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state,
16411.30Skamil		                       slen) != -1);
16421.30Skamil		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
16431.30Skamil
16441.30Skamil		child2 = state.pe_other_pid;
16451.30Skamil		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
16461.30Skamil		        child2);
16471.30Skamil
16481.30Skamil		DPRINTF("Before resuming the child process where it left off "
16491.30Skamil		        "and without signal to be sent\n");
16501.30Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
16511.30Skamil	}
16521.29Skamil
16531.30Skamil#if defined(TWAIT_HAVE_PID)
16541.31Skamil	if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) {
16551.29Skamil		DPRINTF("Before calling %s() for the forkee - expected exited"
16561.29Skamil		        "\n", TWAIT_FNAME);
16571.29Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
16581.29Skamil		    child2);
16591.29Skamil
16601.29Skamil		validate_status_exited(status, exitval2);
16611.29Skamil
16621.29Skamil		DPRINTF("Before calling %s() for the forkee - expected no "
16631.29Skamil		        "process\n", TWAIT_FNAME);
16641.29Skamil		TWAIT_REQUIRE_FAILURE(ECHILD,
16651.29Skamil		    wpid = TWAIT_GENERIC(child2, &status, 0));
16661.29Skamil	}
16671.29Skamil#endif
16681.1Skamil
16691.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
16701.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
16711.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
16721.1Skamil
16731.1Skamil	validate_status_stopped(status, SIGCHLD);
16741.1Skamil
16751.13Schristos	DPRINTF("Before resuming the child process where it left off and "
16761.1Skamil	    "without signal to be sent\n");
16771.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
16781.1Skamil
16791.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
16801.1Skamil	    TWAIT_FNAME);
16811.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
16821.1Skamil
16831.1Skamil	validate_status_exited(status, exitval);
16841.1Skamil
16851.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
16861.1Skamil	    TWAIT_FNAME);
16871.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
16881.1Skamil}
16891.28Skamil
16901.32Skamil#define FORK_TEST(name,descr,fun,tfork,tvfork,tvforkdone,detchild,detparent)	\
16911.32SkamilATF_TC(name);									\
16921.32SkamilATF_TC_HEAD(name, tc)								\
16931.32Skamil{										\
16941.32Skamil	atf_tc_set_md_var(tc, "descr", descr);					\
16951.32Skamil}										\
16961.32Skamil										\
16971.32SkamilATF_TC_BODY(name, tc)								\
16981.32Skamil{										\
16991.32Skamil										\
17001.32Skamil	fork_body(fun, tfork, tvfork, tvforkdone, detchild, detparent);		\
17011.32Skamil}
17021.32Skamil
17031.32Skamil#define F false
17041.32Skamil#define T true
17051.32Skamil
17061.32Skamil#define F_IF__0(x)
17071.32Skamil#define F_IF__1(x) x
17081.32Skamil#define F_IF__(x,y) F_IF__ ## x (y)
17091.32Skamil#define F_IF_(x,y) F_IF__(x,y)
17101.32Skamil#define F_IF(x,y) F_IF_(x,y)
17111.32Skamil
17121.32Skamil#define DSCR(function,forkbit,vforkbit,vforkdonebit,dchildbit,dparentbit)	\
17131.32Skamil        "Verify " #function "(2) called with 0"					\
17141.32Skamil        F_IF(forkbit,"|PTRACE_FORK")						\
17151.32Skamil        F_IF(vforkbit,"|PTRACE_VFORK")						\
17161.32Skamil        F_IF(vforkdonebit,"|PTRACE_VFORK_DONE")					\
17171.32Skamil        " in EVENT_MASK."							\
17181.32Skamil        F_IF(dchildbit," Detach child in this test.")				\
17191.32Skamil        F_IF(dparentbit," Detach parent in this test.")
17201.1Skamil
17211.32SkamilFORK_TEST(fork1, DSCR(fork,0,0,0,0,0), fork, F, F, F, F, F)
17221.31Skamil#if defined(TWAIT_HAVE_PID)
17231.32SkamilFORK_TEST(fork2, DSCR(fork,1,0,0,0,0), fork, T, F, F, F, F)
17241.32SkamilFORK_TEST(fork3, DSCR(fork,0,1,0,0,0), fork, F, T, F, F, F)
17251.32SkamilFORK_TEST(fork4, DSCR(fork,1,1,0,0,0), fork, T, T, F, F, F)
17261.31Skamil#endif
17271.32SkamilFORK_TEST(fork5, DSCR(fork,0,0,1,0,0), fork, F, F, T, F, F)
17281.31Skamil#if defined(TWAIT_HAVE_PID)
17291.32SkamilFORK_TEST(fork6, DSCR(fork,1,0,1,0,0), fork, T, F, T, F, F)
17301.32SkamilFORK_TEST(fork7, DSCR(fork,0,1,1,0,0), fork, F, T, T, F, F)
17311.32SkamilFORK_TEST(fork8, DSCR(fork,1,1,1,0,0), fork, T, T, T, F, F)
17321.31Skamil#endif
17331.1Skamil
17341.32SkamilFORK_TEST(vfork1, DSCR(vfork,0,0,0,0,0), vfork, F, F, F, F, F)
17351.31Skamil#if defined(TWAIT_HAVE_PID)
17361.32SkamilFORK_TEST(vfork2, DSCR(vfork,1,0,0,0,0), vfork, T, F, F, F, F)
17371.32SkamilFORK_TEST(vfork3, DSCR(vfork,0,1,0,0,0), vfork, F, T, F, F, F)
17381.32SkamilFORK_TEST(vfork4, DSCR(vfork,1,1,0,0,0), vfork, T, T, F, F, F)
17391.31Skamil#endif
17401.32SkamilFORK_TEST(vfork5, DSCR(vfork,0,0,1,0,0), vfork, F, F, T, F, F)
17411.31Skamil#if defined(TWAIT_HAVE_PID)
17421.32SkamilFORK_TEST(vfork6, DSCR(vfork,1,0,1,0,0), vfork, T, F, T, F, F)
17431.32SkamilFORK_TEST(vfork7, DSCR(vfork,0,1,1,0,0), vfork, F, T, T, F, F)
17441.32SkamilFORK_TEST(vfork8, DSCR(vfork,1,1,1,0,0), vfork, T, T, T, F, F)
17451.31Skamil#endif
17461.31Skamil
17471.31Skamil
17481.31Skamil
17491.1Skamil
17501.1SkamilATF_TC(io_read_d1);
17511.1SkamilATF_TC_HEAD(io_read_d1, tc)
17521.1Skamil{
17531.1Skamil	atf_tc_set_md_var(tc, "descr",
17541.1Skamil	    "Verify PT_IO with PIOD_READ_D and len = sizeof(uint8_t)");
17551.1Skamil}
17561.1Skamil
17571.1SkamilATF_TC_BODY(io_read_d1, tc)
17581.1Skamil{
17591.1Skamil	const int exitval = 5;
17601.1Skamil	const int sigval = SIGSTOP;
17611.1Skamil	pid_t child, wpid;
17621.1Skamil	uint8_t lookup_me = 0;
17631.1Skamil	const uint8_t magic = 0xab;
17641.1Skamil	struct ptrace_io_desc io = {
17651.1Skamil		.piod_op = PIOD_READ_D,
17661.1Skamil		.piod_offs = &lookup_me,
17671.1Skamil		.piod_addr = &lookup_me,
17681.1Skamil		.piod_len = sizeof(lookup_me)
17691.1Skamil	};
17701.1Skamil#if defined(TWAIT_HAVE_STATUS)
17711.1Skamil	int status;
17721.1Skamil#endif
17731.1Skamil
17741.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
17751.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
17761.1Skamil	if (child == 0) {
17771.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
17781.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
17791.1Skamil
17801.1Skamil		lookup_me = magic;
17811.1Skamil
17821.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
17831.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
17841.1Skamil
17851.13Schristos		DPRINTF("Before exiting of the child process\n");
17861.1Skamil		_exit(exitval);
17871.1Skamil	}
17881.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
17891.1Skamil
17901.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
17911.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
17921.1Skamil
17931.1Skamil	validate_status_stopped(status, sigval);
17941.1Skamil
17951.13Schristos	DPRINTF("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
17961.1Skamil	    child, getpid());
17971.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
17981.1Skamil
17991.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
18001.1Skamil	    "got value %" PRIx8 " != expected %" PRIx8, lookup_me, magic);
18011.1Skamil
18021.13Schristos	DPRINTF("Before resuming the child process where it left off and "
18031.1Skamil	    "without signal to be sent\n");
18041.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
18051.1Skamil
18061.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18071.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
18081.1Skamil
18091.1Skamil	validate_status_exited(status, exitval);
18101.1Skamil
18111.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18121.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
18131.1Skamil}
18141.1Skamil
18151.1SkamilATF_TC(io_read_d2);
18161.1SkamilATF_TC_HEAD(io_read_d2, tc)
18171.1Skamil{
18181.1Skamil	atf_tc_set_md_var(tc, "descr",
18191.1Skamil	    "Verify PT_IO with PIOD_READ_D and len = sizeof(uint16_t)");
18201.1Skamil}
18211.1Skamil
18221.1SkamilATF_TC_BODY(io_read_d2, tc)
18231.1Skamil{
18241.1Skamil	const int exitval = 5;
18251.1Skamil	const int sigval = SIGSTOP;
18261.1Skamil	pid_t child, wpid;
18271.1Skamil	uint16_t lookup_me = 0;
18281.1Skamil	const uint16_t magic = 0x1234;
18291.1Skamil	struct ptrace_io_desc io = {
18301.1Skamil		.piod_op = PIOD_READ_D,
18311.1Skamil		.piod_offs = &lookup_me,
18321.1Skamil		.piod_addr = &lookup_me,
18331.1Skamil		.piod_len = sizeof(lookup_me)
18341.1Skamil	};
18351.1Skamil#if defined(TWAIT_HAVE_STATUS)
18361.1Skamil	int status;
18371.1Skamil#endif
18381.1Skamil
18391.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
18401.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
18411.1Skamil	if (child == 0) {
18421.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
18431.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
18441.1Skamil
18451.1Skamil		lookup_me = magic;
18461.1Skamil
18471.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
18481.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
18491.1Skamil
18501.13Schristos		DPRINTF("Before exiting of the child process\n");
18511.1Skamil		_exit(exitval);
18521.1Skamil	}
18531.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
18541.1Skamil
18551.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18561.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
18571.1Skamil
18581.1Skamil	validate_status_stopped(status, sigval);
18591.1Skamil
18601.13Schristos	DPRINTF("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
18611.1Skamil	    child, getpid());
18621.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
18631.1Skamil
18641.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
18651.1Skamil	    "got value %" PRIx16 " != expected %" PRIx16, lookup_me, magic);
18661.1Skamil
18671.13Schristos	DPRINTF("Before resuming the child process where it left off and "
18681.1Skamil	    "without signal to be sent\n");
18691.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
18701.1Skamil
18711.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18721.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
18731.1Skamil
18741.1Skamil	validate_status_exited(status, exitval);
18751.1Skamil
18761.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
18771.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
18781.1Skamil}
18791.1Skamil
18801.1SkamilATF_TC(io_read_d3);
18811.1SkamilATF_TC_HEAD(io_read_d3, tc)
18821.1Skamil{
18831.1Skamil	atf_tc_set_md_var(tc, "descr",
18841.1Skamil	    "Verify PT_IO with PIOD_READ_D and len = sizeof(uint32_t)");
18851.1Skamil}
18861.1Skamil
18871.1SkamilATF_TC_BODY(io_read_d3, tc)
18881.1Skamil{
18891.1Skamil	const int exitval = 5;
18901.1Skamil	const int sigval = SIGSTOP;
18911.1Skamil	pid_t child, wpid;
18921.1Skamil	uint32_t lookup_me = 0;
18931.1Skamil	const uint32_t magic = 0x1234abcd;
18941.1Skamil	struct ptrace_io_desc io = {
18951.1Skamil		.piod_op = PIOD_READ_D,
18961.1Skamil		.piod_offs = &lookup_me,
18971.1Skamil		.piod_addr = &lookup_me,
18981.1Skamil		.piod_len = sizeof(lookup_me)
18991.1Skamil	};
19001.1Skamil#if defined(TWAIT_HAVE_STATUS)
19011.1Skamil	int status;
19021.1Skamil#endif
19031.1Skamil
19041.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
19051.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
19061.1Skamil	if (child == 0) {
19071.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
19081.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
19091.1Skamil
19101.1Skamil		lookup_me = magic;
19111.1Skamil
19121.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
19131.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
19141.1Skamil
19151.13Schristos		DPRINTF("Before exiting of the child process\n");
19161.1Skamil		_exit(exitval);
19171.1Skamil	}
19181.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
19191.1Skamil
19201.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
19211.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
19221.1Skamil
19231.1Skamil	validate_status_stopped(status, sigval);
19241.1Skamil
19251.13Schristos	DPRINTF("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
19261.1Skamil	    child, getpid());
19271.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
19281.1Skamil
19291.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
19301.1Skamil	    "got value %" PRIx32 " != expected %" PRIx32, lookup_me, magic);
19311.1Skamil
19321.13Schristos	DPRINTF("Before resuming the child process where it left off and "
19331.1Skamil	    "without signal to be sent\n");
19341.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
19351.1Skamil
19361.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
19371.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
19381.1Skamil
19391.1Skamil	validate_status_exited(status, exitval);
19401.1Skamil
19411.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
19421.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
19431.1Skamil}
19441.1Skamil
19451.1SkamilATF_TC(io_read_d4);
19461.1SkamilATF_TC_HEAD(io_read_d4, tc)
19471.1Skamil{
19481.1Skamil	atf_tc_set_md_var(tc, "descr",
19491.1Skamil	    "Verify PT_IO with PIOD_READ_D and len = sizeof(uint64_t)");
19501.1Skamil}
19511.1Skamil
19521.1SkamilATF_TC_BODY(io_read_d4, tc)
19531.1Skamil{
19541.1Skamil	const int exitval = 5;
19551.1Skamil	const int sigval = SIGSTOP;
19561.1Skamil	pid_t child, wpid;
19571.1Skamil	uint64_t lookup_me = 0;
19581.1Skamil	const uint64_t magic = 0x1234abcd9876dcfa;
19591.1Skamil	struct ptrace_io_desc io = {
19601.1Skamil		.piod_op = PIOD_READ_D,
19611.1Skamil		.piod_offs = &lookup_me,
19621.1Skamil		.piod_addr = &lookup_me,
19631.1Skamil		.piod_len = sizeof(lookup_me)
19641.1Skamil	};
19651.1Skamil#if defined(TWAIT_HAVE_STATUS)
19661.1Skamil	int status;
19671.1Skamil#endif
19681.1Skamil
19691.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
19701.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
19711.1Skamil	if (child == 0) {
19721.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
19731.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
19741.1Skamil
19751.1Skamil		lookup_me = magic;
19761.1Skamil
19771.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
19781.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
19791.1Skamil
19801.13Schristos		DPRINTF("Before exiting of the child process\n");
19811.1Skamil		_exit(exitval);
19821.1Skamil	}
19831.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
19841.1Skamil
19851.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
19861.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
19871.1Skamil
19881.1Skamil	validate_status_stopped(status, sigval);
19891.1Skamil
19901.13Schristos	DPRINTF("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
19911.1Skamil	    child, getpid());
19921.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
19931.1Skamil
19941.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
19951.1Skamil	    "got value %" PRIx64 " != expected %" PRIx64, lookup_me, magic);
19961.1Skamil
19971.13Schristos	DPRINTF("Before resuming the child process where it left off and "
19981.1Skamil	    "without signal to be sent\n");
19991.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
20001.1Skamil
20011.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
20021.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
20031.1Skamil
20041.1Skamil	validate_status_exited(status, exitval);
20051.1Skamil
20061.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
20071.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
20081.1Skamil}
20091.1Skamil
20101.1SkamilATF_TC(io_write_d1);
20111.1SkamilATF_TC_HEAD(io_write_d1, tc)
20121.1Skamil{
20131.1Skamil	atf_tc_set_md_var(tc, "descr",
20141.1Skamil	    "Verify PT_IO with PIOD_WRITE_D and len = sizeof(uint8_t)");
20151.1Skamil}
20161.1Skamil
20171.1SkamilATF_TC_BODY(io_write_d1, tc)
20181.1Skamil{
20191.1Skamil	const int exitval = 5;
20201.1Skamil	const int sigval = SIGSTOP;
20211.1Skamil	pid_t child, wpid;
20221.1Skamil	uint8_t lookup_me = 0;
20231.1Skamil	const uint8_t magic = 0xab;
20241.1Skamil	struct ptrace_io_desc io = {
20251.1Skamil		.piod_op = PIOD_WRITE_D,
20261.1Skamil		.piod_offs = &lookup_me,
20271.1Skamil		.piod_addr = &lookup_me,
20281.1Skamil		.piod_len = sizeof(lookup_me)
20291.1Skamil	};
20301.1Skamil#if defined(TWAIT_HAVE_STATUS)
20311.1Skamil	int status;
20321.1Skamil#endif
20331.1Skamil
20341.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
20351.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
20361.1Skamil	if (child == 0) {
20371.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
20381.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
20391.1Skamil
20401.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
20411.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
20421.1Skamil
20431.1Skamil		FORKEE_ASSERT_EQ(lookup_me, magic);
20441.1Skamil
20451.13Schristos		DPRINTF("Before exiting of the child process\n");
20461.1Skamil		_exit(exitval);
20471.1Skamil	}
20481.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
20491.1Skamil
20501.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
20511.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
20521.1Skamil
20531.1Skamil	validate_status_stopped(status, sigval);
20541.1Skamil
20551.1Skamil	lookup_me = magic;
20561.1Skamil
20571.13Schristos	DPRINTF("Write new lookup_me to tracee (PID=%d) from tracer (PID=%d)\n",
20581.1Skamil	    child, getpid());
20591.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
20601.1Skamil
20611.13Schristos	DPRINTF("Before resuming the child process where it left off and "
20621.1Skamil	    "without signal to be sent\n");
20631.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
20641.1Skamil
20651.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
20661.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
20671.1Skamil
20681.1Skamil	validate_status_exited(status, exitval);
20691.1Skamil
20701.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
20711.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
20721.1Skamil}
20731.1Skamil
20741.1SkamilATF_TC(io_write_d2);
20751.1SkamilATF_TC_HEAD(io_write_d2, tc)
20761.1Skamil{
20771.1Skamil	atf_tc_set_md_var(tc, "descr",
20781.1Skamil	    "Verify PT_IO with PIOD_WRITE_D and len = sizeof(uint16_t)");
20791.1Skamil}
20801.1Skamil
20811.1SkamilATF_TC_BODY(io_write_d2, tc)
20821.1Skamil{
20831.1Skamil	const int exitval = 5;
20841.1Skamil	const int sigval = SIGSTOP;
20851.1Skamil	pid_t child, wpid;
20861.1Skamil	uint16_t lookup_me = 0;
20871.1Skamil	const uint16_t magic = 0xab12;
20881.1Skamil	struct ptrace_io_desc io = {
20891.1Skamil		.piod_op = PIOD_WRITE_D,
20901.1Skamil		.piod_offs = &lookup_me,
20911.1Skamil		.piod_addr = &lookup_me,
20921.1Skamil		.piod_len = sizeof(lookup_me)
20931.1Skamil	};
20941.1Skamil#if defined(TWAIT_HAVE_STATUS)
20951.1Skamil	int status;
20961.1Skamil#endif
20971.1Skamil
20981.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
20991.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
21001.1Skamil	if (child == 0) {
21011.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
21021.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
21031.1Skamil
21041.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
21051.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
21061.1Skamil
21071.1Skamil		FORKEE_ASSERT_EQ(lookup_me, magic);
21081.1Skamil
21091.13Schristos		DPRINTF("Before exiting of the child process\n");
21101.1Skamil		_exit(exitval);
21111.1Skamil	}
21121.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
21131.1Skamil
21141.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
21151.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
21161.1Skamil
21171.1Skamil	validate_status_stopped(status, sigval);
21181.1Skamil
21191.1Skamil	lookup_me = magic;
21201.1Skamil
21211.13Schristos	DPRINTF("Write new lookup_me to tracee (PID=%d) from tracer (PID=%d)\n",
21221.1Skamil	    child, getpid());
21231.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
21241.1Skamil
21251.13Schristos	DPRINTF("Before resuming the child process where it left off and "
21261.1Skamil	    "without signal to be sent\n");
21271.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
21281.1Skamil
21291.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
21301.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
21311.1Skamil
21321.1Skamil	validate_status_exited(status, exitval);
21331.1Skamil
21341.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
21351.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
21361.1Skamil}
21371.1Skamil
21381.1SkamilATF_TC(io_write_d3);
21391.1SkamilATF_TC_HEAD(io_write_d3, tc)
21401.1Skamil{
21411.1Skamil	atf_tc_set_md_var(tc, "descr",
21421.1Skamil	    "Verify PT_IO with PIOD_WRITE_D and len = sizeof(uint32_t)");
21431.1Skamil}
21441.1Skamil
21451.1SkamilATF_TC_BODY(io_write_d3, tc)
21461.1Skamil{
21471.1Skamil	const int exitval = 5;
21481.1Skamil	const int sigval = SIGSTOP;
21491.1Skamil	pid_t child, wpid;
21501.1Skamil	uint32_t lookup_me = 0;
21511.1Skamil	const uint32_t magic = 0xab127643;
21521.1Skamil	struct ptrace_io_desc io = {
21531.1Skamil		.piod_op = PIOD_WRITE_D,
21541.1Skamil		.piod_offs = &lookup_me,
21551.1Skamil		.piod_addr = &lookup_me,
21561.1Skamil		.piod_len = sizeof(lookup_me)
21571.1Skamil	};
21581.1Skamil#if defined(TWAIT_HAVE_STATUS)
21591.1Skamil	int status;
21601.1Skamil#endif
21611.1Skamil
21621.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
21631.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
21641.1Skamil	if (child == 0) {
21651.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
21661.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
21671.1Skamil
21681.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
21691.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
21701.1Skamil
21711.1Skamil		FORKEE_ASSERT_EQ(lookup_me, magic);
21721.1Skamil
21731.13Schristos		DPRINTF("Before exiting of the child process\n");
21741.1Skamil		_exit(exitval);
21751.1Skamil	}
21761.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
21771.1Skamil
21781.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
21791.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
21801.1Skamil
21811.1Skamil	validate_status_stopped(status, sigval);
21821.1Skamil
21831.1Skamil	lookup_me = magic;
21841.1Skamil
21851.13Schristos	DPRINTF("Write new lookup_me to tracee (PID=%d) from tracer (PID=%d)\n",
21861.1Skamil	    child, getpid());
21871.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
21881.1Skamil
21891.13Schristos	DPRINTF("Before resuming the child process where it left off and "
21901.1Skamil	    "without signal to be sent\n");
21911.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
21921.1Skamil
21931.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
21941.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
21951.1Skamil
21961.1Skamil	validate_status_exited(status, exitval);
21971.1Skamil
21981.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
21991.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
22001.1Skamil}
22011.1Skamil
22021.1SkamilATF_TC(io_write_d4);
22031.1SkamilATF_TC_HEAD(io_write_d4, tc)
22041.1Skamil{
22051.1Skamil	atf_tc_set_md_var(tc, "descr",
22061.1Skamil	    "Verify PT_IO with PIOD_WRITE_D and len = sizeof(uint64_t)");
22071.1Skamil}
22081.1Skamil
22091.1SkamilATF_TC_BODY(io_write_d4, tc)
22101.1Skamil{
22111.1Skamil	const int exitval = 5;
22121.1Skamil	const int sigval = SIGSTOP;
22131.1Skamil	pid_t child, wpid;
22141.1Skamil	uint64_t lookup_me = 0;
22151.1Skamil	const uint64_t magic = 0xab12764376490123;
22161.1Skamil	struct ptrace_io_desc io = {
22171.1Skamil		.piod_op = PIOD_WRITE_D,
22181.1Skamil		.piod_offs = &lookup_me,
22191.1Skamil		.piod_addr = &lookup_me,
22201.1Skamil		.piod_len = sizeof(lookup_me)
22211.1Skamil	};
22221.1Skamil#if defined(TWAIT_HAVE_STATUS)
22231.1Skamil	int status;
22241.1Skamil#endif
22251.1Skamil
22261.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
22271.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
22281.1Skamil	if (child == 0) {
22291.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
22301.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
22311.1Skamil
22321.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
22331.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
22341.1Skamil
22351.1Skamil		FORKEE_ASSERT_EQ(lookup_me, magic);
22361.1Skamil
22371.13Schristos		DPRINTF("Before exiting of the child process\n");
22381.1Skamil		_exit(exitval);
22391.1Skamil	}
22401.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
22411.1Skamil
22421.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
22431.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
22441.1Skamil
22451.1Skamil	validate_status_stopped(status, sigval);
22461.1Skamil
22471.1Skamil	lookup_me = magic;
22481.1Skamil
22491.13Schristos	DPRINTF("Write new lookup_me to tracee (PID=%d) from tracer (PID=%d)\n",
22501.1Skamil	    child, getpid());
22511.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
22521.1Skamil
22531.13Schristos	DPRINTF("Before resuming the child process where it left off and "
22541.1Skamil	    "without signal to be sent\n");
22551.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
22561.1Skamil
22571.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
22581.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
22591.1Skamil
22601.1Skamil	validate_status_exited(status, exitval);
22611.1Skamil
22621.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
22631.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
22641.1Skamil}
22651.1Skamil
22661.1SkamilATF_TC(io_read_auxv1);
22671.1SkamilATF_TC_HEAD(io_read_auxv1, tc)
22681.1Skamil{
22691.1Skamil	atf_tc_set_md_var(tc, "descr",
22701.1Skamil	    "Verify PT_READ_AUXV called for tracee");
22711.1Skamil}
22721.1Skamil
22731.1SkamilATF_TC_BODY(io_read_auxv1, tc)
22741.1Skamil{
22751.1Skamil	const int exitval = 5;
22761.1Skamil	const int sigval = SIGSTOP;
22771.1Skamil	pid_t child, wpid;
22781.1Skamil#if defined(TWAIT_HAVE_STATUS)
22791.1Skamil	int status;
22801.1Skamil#endif
22811.1Skamil	AuxInfo ai[100], *aip;
22821.1Skamil	struct ptrace_io_desc io = {
22831.1Skamil		.piod_op = PIOD_READ_AUXV,
22841.1Skamil		.piod_offs = 0,
22851.1Skamil		.piod_addr = ai,
22861.1Skamil		.piod_len = sizeof(ai)
22871.1Skamil	};
22881.1Skamil
22891.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
22901.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
22911.1Skamil	if (child == 0) {
22921.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
22931.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
22941.1Skamil
22951.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
22961.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
22971.1Skamil
22981.13Schristos		DPRINTF("Before exiting of the child process\n");
22991.1Skamil		_exit(exitval);
23001.1Skamil	}
23011.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
23021.1Skamil
23031.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23041.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
23051.1Skamil
23061.1Skamil	validate_status_stopped(status, sigval);
23071.1Skamil
23081.13Schristos	DPRINTF("Read new AUXV from tracee (PID=%d) by tracer (PID=%d)\n",
23091.1Skamil	    child, getpid());
23101.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
23111.1Skamil
23121.13Schristos	DPRINTF("Asserting that AUXV length (%zu) is > 0\n", io.piod_len);
23131.1Skamil	ATF_REQUIRE(io.piod_len > 0);
23141.1Skamil
23151.1Skamil	for (aip = ai; aip->a_type != AT_NULL; aip++)
23161.13Schristos		DPRINTF("a_type=%#llx a_v=%#llx\n",
23171.1Skamil		    (long long int)aip->a_type, (long long int)aip->a_v);
23181.1Skamil
23191.13Schristos	DPRINTF("Before resuming the child process where it left off and "
23201.1Skamil	    "without signal to be sent\n");
23211.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
23221.1Skamil
23231.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23241.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
23251.1Skamil
23261.1Skamil	validate_status_exited(status, exitval);
23271.1Skamil
23281.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23291.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
23301.1Skamil}
23311.1Skamil
23321.1SkamilATF_TC(read_d1);
23331.1SkamilATF_TC_HEAD(read_d1, tc)
23341.1Skamil{
23351.1Skamil	atf_tc_set_md_var(tc, "descr",
23361.1Skamil	    "Verify PT_READ_D called once");
23371.1Skamil}
23381.1Skamil
23391.1SkamilATF_TC_BODY(read_d1, tc)
23401.1Skamil{
23411.1Skamil	const int exitval = 5;
23421.1Skamil	const int sigval = SIGSTOP;
23431.1Skamil	pid_t child, wpid;
23441.1Skamil	int lookup_me = 0;
23451.1Skamil	const int magic = (int)random();
23461.1Skamil#if defined(TWAIT_HAVE_STATUS)
23471.1Skamil	int status;
23481.1Skamil#endif
23491.1Skamil
23501.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
23511.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
23521.1Skamil	if (child == 0) {
23531.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
23541.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
23551.1Skamil
23561.1Skamil		lookup_me = magic;
23571.1Skamil
23581.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
23591.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
23601.1Skamil
23611.13Schristos		DPRINTF("Before exiting of the child process\n");
23621.1Skamil		_exit(exitval);
23631.1Skamil	}
23641.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
23651.1Skamil
23661.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23671.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
23681.1Skamil
23691.1Skamil	validate_status_stopped(status, sigval);
23701.1Skamil
23711.13Schristos	DPRINTF("Read new lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
23721.1Skamil	    child, getpid());
23731.1Skamil	errno = 0;
23741.1Skamil	lookup_me = ptrace(PT_READ_D, child, &lookup_me, 0);
23751.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
23761.1Skamil
23771.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
23781.1Skamil	    "got value %#x != expected %#x", lookup_me, magic);
23791.1Skamil
23801.13Schristos	DPRINTF("Before resuming the child process where it left off and "
23811.1Skamil	    "without signal to be sent\n");
23821.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
23831.1Skamil
23841.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23851.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
23861.1Skamil
23871.1Skamil	validate_status_exited(status, exitval);
23881.1Skamil
23891.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
23901.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
23911.1Skamil}
23921.1Skamil
23931.1SkamilATF_TC(read_d2);
23941.1SkamilATF_TC_HEAD(read_d2, tc)
23951.1Skamil{
23961.1Skamil	atf_tc_set_md_var(tc, "descr",
23971.1Skamil	    "Verify PT_READ_D called twice");
23981.1Skamil}
23991.1Skamil
24001.1SkamilATF_TC_BODY(read_d2, tc)
24011.1Skamil{
24021.1Skamil	const int exitval = 5;
24031.1Skamil	const int sigval = SIGSTOP;
24041.1Skamil	pid_t child, wpid;
24051.1Skamil	int lookup_me1 = 0;
24061.1Skamil	int lookup_me2 = 0;
24071.1Skamil	const int magic1 = (int)random();
24081.1Skamil	const int magic2 = (int)random();
24091.1Skamil#if defined(TWAIT_HAVE_STATUS)
24101.1Skamil	int status;
24111.1Skamil#endif
24121.1Skamil
24131.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
24141.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
24151.1Skamil	if (child == 0) {
24161.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
24171.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
24181.1Skamil
24191.1Skamil		lookup_me1 = magic1;
24201.1Skamil		lookup_me2 = magic2;
24211.1Skamil
24221.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
24231.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
24241.1Skamil
24251.13Schristos		DPRINTF("Before exiting of the child process\n");
24261.1Skamil		_exit(exitval);
24271.1Skamil	}
24281.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
24291.1Skamil
24301.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
24311.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
24321.1Skamil
24331.1Skamil	validate_status_stopped(status, sigval);
24341.1Skamil
24351.13Schristos	DPRINTF("Read new lookup_me1 from tracee (PID=%d) by tracer (PID=%d)\n",
24361.1Skamil	    child, getpid());
24371.1Skamil	errno = 0;
24381.1Skamil	lookup_me1 = ptrace(PT_READ_D, child, &lookup_me1, 0);
24391.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
24401.1Skamil
24411.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me1, magic1,
24421.1Skamil	    "got value %#x != expected %#x", lookup_me1, magic1);
24431.1Skamil
24441.13Schristos	DPRINTF("Read new lookup_me2 from tracee (PID=%d) by tracer (PID=%d)\n",
24451.1Skamil	    child, getpid());
24461.1Skamil	errno = 0;
24471.1Skamil	lookup_me2 = ptrace(PT_READ_D, child, &lookup_me2, 0);
24481.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
24491.1Skamil
24501.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me2, magic2,
24511.1Skamil	    "got value %#x != expected %#x", lookup_me2, magic2);
24521.1Skamil
24531.13Schristos	DPRINTF("Before resuming the child process where it left off and "
24541.1Skamil	    "without signal to be sent\n");
24551.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
24561.1Skamil
24571.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
24581.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
24591.1Skamil
24601.1Skamil	validate_status_exited(status, exitval);
24611.1Skamil
24621.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
24631.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
24641.1Skamil}
24651.1Skamil
24661.1SkamilATF_TC(read_d3);
24671.1SkamilATF_TC_HEAD(read_d3, tc)
24681.1Skamil{
24691.1Skamil	atf_tc_set_md_var(tc, "descr",
24701.1Skamil	    "Verify PT_READ_D called three times");
24711.1Skamil}
24721.1Skamil
24731.1SkamilATF_TC_BODY(read_d3, tc)
24741.1Skamil{
24751.1Skamil	const int exitval = 5;
24761.1Skamil	const int sigval = SIGSTOP;
24771.1Skamil	pid_t child, wpid;
24781.1Skamil	int lookup_me1 = 0;
24791.1Skamil	int lookup_me2 = 0;
24801.1Skamil	int lookup_me3 = 0;
24811.1Skamil	const int magic1 = (int)random();
24821.1Skamil	const int magic2 = (int)random();
24831.1Skamil	const int magic3 = (int)random();
24841.1Skamil#if defined(TWAIT_HAVE_STATUS)
24851.1Skamil	int status;
24861.1Skamil#endif
24871.1Skamil
24881.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
24891.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
24901.1Skamil	if (child == 0) {
24911.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
24921.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
24931.1Skamil
24941.1Skamil		lookup_me1 = magic1;
24951.1Skamil		lookup_me2 = magic2;
24961.1Skamil		lookup_me3 = magic3;
24971.1Skamil
24981.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
24991.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
25001.1Skamil
25011.13Schristos		DPRINTF("Before exiting of the child process\n");
25021.1Skamil		_exit(exitval);
25031.1Skamil	}
25041.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
25051.1Skamil
25061.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
25071.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
25081.1Skamil
25091.1Skamil	validate_status_stopped(status, sigval);
25101.1Skamil
25111.13Schristos	DPRINTF("Read new lookup_me1 from tracee (PID=%d) by tracer (PID=%d)\n",
25121.1Skamil	    child, getpid());
25131.1Skamil	errno = 0;
25141.1Skamil	lookup_me1 = ptrace(PT_READ_D, child, &lookup_me1, 0);
25151.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
25161.1Skamil
25171.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me1, magic1,
25181.1Skamil	    "got value %#x != expected %#x", lookup_me1, magic1);
25191.1Skamil
25201.13Schristos	DPRINTF("Read new lookup_me2 from tracee (PID=%d) by tracer (PID=%d)\n",
25211.1Skamil	    child, getpid());
25221.1Skamil	errno = 0;
25231.1Skamil	lookup_me2 = ptrace(PT_READ_D, child, &lookup_me2, 0);
25241.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
25251.1Skamil
25261.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me2, magic2,
25271.1Skamil	    "got value %#x != expected %#x", lookup_me2, magic2);
25281.1Skamil
25291.13Schristos	DPRINTF("Read new lookup_me3 from tracee (PID=%d) by tracer (PID=%d)\n",
25301.1Skamil	    child, getpid());
25311.1Skamil	errno = 0;
25321.1Skamil	lookup_me3 = ptrace(PT_READ_D, child, &lookup_me3, 0);
25331.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
25341.1Skamil
25351.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me3, magic3,
25361.1Skamil	    "got value %#x != expected %#x", lookup_me3, magic3);
25371.1Skamil
25381.13Schristos	DPRINTF("Before resuming the child process where it left off and "
25391.1Skamil	    "without signal to be sent\n");
25401.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
25411.1Skamil
25421.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
25431.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
25441.1Skamil
25451.1Skamil	validate_status_exited(status, exitval);
25461.1Skamil
25471.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
25481.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
25491.1Skamil}
25501.1Skamil
25511.1SkamilATF_TC(read_d4);
25521.1SkamilATF_TC_HEAD(read_d4, tc)
25531.1Skamil{
25541.1Skamil	atf_tc_set_md_var(tc, "descr",
25551.1Skamil	    "Verify PT_READ_D called four times");
25561.1Skamil}
25571.1Skamil
25581.1SkamilATF_TC_BODY(read_d4, tc)
25591.1Skamil{
25601.1Skamil	const int exitval = 5;
25611.1Skamil	const int sigval = SIGSTOP;
25621.1Skamil	pid_t child, wpid;
25631.1Skamil	int lookup_me1 = 0;
25641.1Skamil	int lookup_me2 = 0;
25651.1Skamil	int lookup_me3 = 0;
25661.1Skamil	int lookup_me4 = 0;
25671.1Skamil	const int magic1 = (int)random();
25681.1Skamil	const int magic2 = (int)random();
25691.1Skamil	const int magic3 = (int)random();
25701.1Skamil	const int magic4 = (int)random();
25711.1Skamil#if defined(TWAIT_HAVE_STATUS)
25721.1Skamil	int status;
25731.1Skamil#endif
25741.1Skamil
25751.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
25761.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
25771.1Skamil	if (child == 0) {
25781.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
25791.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
25801.1Skamil
25811.1Skamil		lookup_me1 = magic1;
25821.1Skamil		lookup_me2 = magic2;
25831.1Skamil		lookup_me3 = magic3;
25841.1Skamil		lookup_me4 = magic4;
25851.1Skamil
25861.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
25871.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
25881.1Skamil
25891.13Schristos		DPRINTF("Before exiting of the child process\n");
25901.1Skamil		_exit(exitval);
25911.1Skamil	}
25921.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
25931.1Skamil
25941.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
25951.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
25961.1Skamil
25971.1Skamil	validate_status_stopped(status, sigval);
25981.1Skamil
25991.13Schristos	DPRINTF("Read new lookup_me1 from tracee (PID=%d) by tracer (PID=%d)\n",
26001.1Skamil	    child, getpid());
26011.1Skamil	errno = 0;
26021.1Skamil	lookup_me1 = ptrace(PT_READ_D, child, &lookup_me1, 0);
26031.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
26041.1Skamil
26051.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me1, magic1,
26061.1Skamil	    "got value %#x != expected %#x", lookup_me1, magic1);
26071.1Skamil
26081.13Schristos	DPRINTF("Read new lookup_me2 from tracee (PID=%d) by tracer (PID=%d)\n",
26091.1Skamil	    child, getpid());
26101.1Skamil	errno = 0;
26111.1Skamil	lookup_me2 = ptrace(PT_READ_D, child, &lookup_me2, 0);
26121.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
26131.1Skamil
26141.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me2, magic2,
26151.1Skamil	    "got value %#x != expected %#x", lookup_me2, magic2);
26161.1Skamil
26171.13Schristos	DPRINTF("Read new lookup_me3 from tracee (PID=%d) by tracer (PID=%d)\n",
26181.1Skamil	    child, getpid());
26191.1Skamil	errno = 0;
26201.1Skamil	lookup_me3 = ptrace(PT_READ_D, child, &lookup_me3, 0);
26211.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
26221.1Skamil
26231.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me3, magic3,
26241.1Skamil	    "got value %#x != expected %#x", lookup_me3, magic3);
26251.1Skamil
26261.13Schristos	DPRINTF("Read new lookup_me4 from tracee (PID=%d) by tracer (PID=%d)\n",
26271.1Skamil	    child, getpid());
26281.1Skamil	errno = 0;
26291.1Skamil	lookup_me4 = ptrace(PT_READ_D, child, &lookup_me4, 0);
26301.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
26311.1Skamil
26321.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me4, magic4,
26331.1Skamil	    "got value %#x != expected %#x", lookup_me4, magic4);
26341.1Skamil
26351.13Schristos	DPRINTF("Before resuming the child process where it left off and "
26361.1Skamil	    "without signal to be sent\n");
26371.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
26381.1Skamil
26391.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26401.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
26411.1Skamil
26421.1Skamil	validate_status_exited(status, exitval);
26431.1Skamil
26441.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26451.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
26461.1Skamil}
26471.1Skamil
26481.1SkamilATF_TC(write_d1);
26491.1SkamilATF_TC_HEAD(write_d1, tc)
26501.1Skamil{
26511.1Skamil	atf_tc_set_md_var(tc, "descr",
26521.1Skamil	    "Verify PT_WRITE_D called once");
26531.1Skamil}
26541.1Skamil
26551.1SkamilATF_TC_BODY(write_d1, tc)
26561.1Skamil{
26571.1Skamil	const int exitval = 5;
26581.1Skamil	const int sigval = SIGSTOP;
26591.1Skamil	pid_t child, wpid;
26601.1Skamil	int lookup_me = 0;
26611.1Skamil	const int magic = (int)random();
26621.1Skamil#if defined(TWAIT_HAVE_STATUS)
26631.1Skamil	int status;
26641.1Skamil#endif
26651.1Skamil
26661.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
26671.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
26681.1Skamil	if (child == 0) {
26691.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
26701.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
26711.1Skamil
26721.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
26731.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
26741.1Skamil
26751.1Skamil		FORKEE_ASSERT_EQ(lookup_me, magic);
26761.1Skamil
26771.13Schristos		DPRINTF("Before exiting of the child process\n");
26781.1Skamil		_exit(exitval);
26791.1Skamil	}
26801.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
26811.1Skamil
26821.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26831.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
26841.1Skamil
26851.1Skamil	validate_status_stopped(status, sigval);
26861.1Skamil
26871.13Schristos	DPRINTF("Write new lookup_me to tracee (PID=%d) from tracer (PID=%d)\n",
26881.1Skamil	    child, getpid());
26891.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me, magic) != -1);
26901.1Skamil
26911.13Schristos	DPRINTF("Before resuming the child process where it left off and "
26921.1Skamil	    "without signal to be sent\n");
26931.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
26941.1Skamil
26951.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
26961.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
26971.1Skamil
26981.1Skamil	validate_status_exited(status, exitval);
26991.1Skamil
27001.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27011.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
27021.1Skamil}
27031.1Skamil
27041.1SkamilATF_TC(write_d2);
27051.1SkamilATF_TC_HEAD(write_d2, tc)
27061.1Skamil{
27071.1Skamil	atf_tc_set_md_var(tc, "descr",
27081.1Skamil	    "Verify PT_WRITE_D called twice");
27091.1Skamil}
27101.1Skamil
27111.1SkamilATF_TC_BODY(write_d2, tc)
27121.1Skamil{
27131.1Skamil	const int exitval = 5;
27141.1Skamil	const int sigval = SIGSTOP;
27151.1Skamil	pid_t child, wpid;
27161.1Skamil	int lookup_me1 = 0;
27171.1Skamil	int lookup_me2 = 0;
27181.1Skamil	const int magic1 = (int)random();
27191.1Skamil	const int magic2 = (int)random();
27201.1Skamil#if defined(TWAIT_HAVE_STATUS)
27211.1Skamil	int status;
27221.1Skamil#endif
27231.1Skamil
27241.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
27251.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
27261.1Skamil	if (child == 0) {
27271.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
27281.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
27291.1Skamil
27301.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
27311.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
27321.1Skamil
27331.1Skamil		FORKEE_ASSERT_EQ(lookup_me1, magic1);
27341.1Skamil		FORKEE_ASSERT_EQ(lookup_me2, magic2);
27351.1Skamil
27361.13Schristos		DPRINTF("Before exiting of the child process\n");
27371.1Skamil		_exit(exitval);
27381.1Skamil	}
27391.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
27401.1Skamil
27411.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27421.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
27431.1Skamil
27441.1Skamil	validate_status_stopped(status, sigval);
27451.1Skamil
27461.13Schristos	DPRINTF("Write new lookup_me1 to tracee (PID=%d) from tracer (PID=%d)\n",
27471.1Skamil	    child, getpid());
27481.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me1, magic1) != -1);
27491.1Skamil
27501.13Schristos	DPRINTF("Write new lookup_me2 to tracee (PID=%d) from tracer (PID=%d)\n",
27511.1Skamil	    child, getpid());
27521.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me2, magic2) != -1);
27531.1Skamil
27541.13Schristos	DPRINTF("Before resuming the child process where it left off and "
27551.1Skamil	    "without signal to be sent\n");
27561.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
27571.1Skamil
27581.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27591.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
27601.1Skamil
27611.1Skamil	validate_status_exited(status, exitval);
27621.1Skamil
27631.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
27641.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
27651.1Skamil}
27661.1Skamil
27671.1SkamilATF_TC(write_d3);
27681.1SkamilATF_TC_HEAD(write_d3, tc)
27691.1Skamil{
27701.1Skamil	atf_tc_set_md_var(tc, "descr",
27711.1Skamil	    "Verify PT_WRITE_D called three times");
27721.1Skamil}
27731.1Skamil
27741.1SkamilATF_TC_BODY(write_d3, tc)
27751.1Skamil{
27761.1Skamil	const int exitval = 5;
27771.1Skamil	const int sigval = SIGSTOP;
27781.1Skamil	pid_t child, wpid;
27791.1Skamil	int lookup_me1 = 0;
27801.1Skamil	int lookup_me2 = 0;
27811.1Skamil	int lookup_me3 = 0;
27821.1Skamil	const int magic1 = (int)random();
27831.1Skamil	const int magic2 = (int)random();
27841.1Skamil	const int magic3 = (int)random();
27851.1Skamil#if defined(TWAIT_HAVE_STATUS)
27861.1Skamil	int status;
27871.1Skamil#endif
27881.1Skamil
27891.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
27901.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
27911.1Skamil	if (child == 0) {
27921.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
27931.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
27941.1Skamil
27951.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
27961.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
27971.1Skamil
27981.1Skamil		FORKEE_ASSERT_EQ(lookup_me1, magic1);
27991.1Skamil		FORKEE_ASSERT_EQ(lookup_me2, magic2);
28001.1Skamil		FORKEE_ASSERT_EQ(lookup_me3, magic3);
28011.1Skamil
28021.13Schristos		DPRINTF("Before exiting of the child process\n");
28031.1Skamil		_exit(exitval);
28041.1Skamil	}
28051.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
28061.1Skamil
28071.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28081.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
28091.1Skamil
28101.1Skamil	validate_status_stopped(status, sigval);
28111.1Skamil
28121.13Schristos	DPRINTF("Write new lookup_me1 to tracee (PID=%d) from tracer (PID=%d)\n",
28131.1Skamil	    child, getpid());
28141.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me1, magic1) != -1);
28151.1Skamil
28161.13Schristos	DPRINTF("Write new lookup_me2 to tracee (PID=%d) from tracer (PID=%d)\n",
28171.1Skamil	    child, getpid());
28181.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me2, magic2) != -1);
28191.1Skamil
28201.13Schristos	DPRINTF("Write new lookup_me3 to tracee (PID=%d) from tracer (PID=%d)\n",
28211.1Skamil	    child, getpid());
28221.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me3, magic3) != -1);
28231.1Skamil
28241.13Schristos	DPRINTF("Before resuming the child process where it left off and "
28251.1Skamil	    "without signal to be sent\n");
28261.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
28271.1Skamil
28281.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28291.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
28301.1Skamil
28311.1Skamil	validate_status_exited(status, exitval);
28321.1Skamil
28331.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28341.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
28351.1Skamil}
28361.1Skamil
28371.1SkamilATF_TC(write_d4);
28381.1SkamilATF_TC_HEAD(write_d4, tc)
28391.1Skamil{
28401.1Skamil	atf_tc_set_md_var(tc, "descr",
28411.1Skamil	    "Verify PT_WRITE_D called four times");
28421.1Skamil}
28431.1Skamil
28441.1SkamilATF_TC_BODY(write_d4, tc)
28451.1Skamil{
28461.1Skamil	const int exitval = 5;
28471.1Skamil	const int sigval = SIGSTOP;
28481.1Skamil	pid_t child, wpid;
28491.1Skamil	int lookup_me1 = 0;
28501.1Skamil	int lookup_me2 = 0;
28511.1Skamil	int lookup_me3 = 0;
28521.1Skamil	int lookup_me4 = 0;
28531.1Skamil	const int magic1 = (int)random();
28541.1Skamil	const int magic2 = (int)random();
28551.1Skamil	const int magic3 = (int)random();
28561.1Skamil	const int magic4 = (int)random();
28571.1Skamil#if defined(TWAIT_HAVE_STATUS)
28581.1Skamil	int status;
28591.1Skamil#endif
28601.1Skamil
28611.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
28621.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
28631.1Skamil	if (child == 0) {
28641.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
28651.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
28661.1Skamil
28671.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
28681.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
28691.1Skamil
28701.1Skamil		FORKEE_ASSERT_EQ(lookup_me1, magic1);
28711.1Skamil		FORKEE_ASSERT_EQ(lookup_me2, magic2);
28721.1Skamil		FORKEE_ASSERT_EQ(lookup_me3, magic3);
28731.1Skamil		FORKEE_ASSERT_EQ(lookup_me4, magic4);
28741.1Skamil
28751.13Schristos		DPRINTF("Before exiting of the child process\n");
28761.1Skamil		_exit(exitval);
28771.1Skamil	}
28781.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
28791.1Skamil
28801.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
28811.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
28821.1Skamil
28831.1Skamil	validate_status_stopped(status, sigval);
28841.1Skamil
28851.13Schristos	DPRINTF("Write new lookup_me1 to tracee (PID=%d) from tracer (PID=%d)\n",
28861.1Skamil	    child, getpid());
28871.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me1, magic1) != -1);
28881.1Skamil
28891.13Schristos	DPRINTF("Write new lookup_me2 to tracee (PID=%d) from tracer (PID=%d)\n",
28901.1Skamil	    child, getpid());
28911.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me2, magic2) != -1);
28921.1Skamil
28931.13Schristos	DPRINTF("Write new lookup_me3 to tracee (PID=%d) from tracer (PID=%d)\n",
28941.1Skamil	    child, getpid());
28951.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me3, magic3) != -1);
28961.1Skamil
28971.13Schristos	DPRINTF("Write new lookup_me4 to tracee (PID=%d) from tracer (PID=%d)\n",
28981.1Skamil	    child, getpid());
28991.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, &lookup_me4, magic4) != -1);
29001.1Skamil
29011.13Schristos	DPRINTF("Before resuming the child process where it left off and "
29021.1Skamil	    "without signal to be sent\n");
29031.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
29041.1Skamil
29051.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29061.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29071.1Skamil
29081.1Skamil	validate_status_exited(status, exitval);
29091.1Skamil
29101.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29111.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
29121.1Skamil}
29131.1Skamil
29141.1SkamilATF_TC(io_read_d_write_d_handshake1);
29151.1SkamilATF_TC_HEAD(io_read_d_write_d_handshake1, tc)
29161.1Skamil{
29171.1Skamil	atf_tc_set_md_var(tc, "descr",
29181.1Skamil	    "Verify PT_IO with PIOD_READ_D and PIOD_WRITE_D handshake");
29191.1Skamil}
29201.1Skamil
29211.1SkamilATF_TC_BODY(io_read_d_write_d_handshake1, tc)
29221.1Skamil{
29231.1Skamil	const int exitval = 5;
29241.1Skamil	const int sigval = SIGSTOP;
29251.1Skamil	pid_t child, wpid;
29261.1Skamil	uint8_t lookup_me_fromtracee = 0;
29271.1Skamil	const uint8_t magic_fromtracee = (uint8_t)random();
29281.1Skamil	uint8_t lookup_me_totracee = 0;
29291.1Skamil	const uint8_t magic_totracee = (uint8_t)random();
29301.1Skamil	struct ptrace_io_desc io_fromtracee = {
29311.1Skamil		.piod_op = PIOD_READ_D,
29321.1Skamil		.piod_offs = &lookup_me_fromtracee,
29331.1Skamil		.piod_addr = &lookup_me_fromtracee,
29341.1Skamil		.piod_len = sizeof(lookup_me_fromtracee)
29351.1Skamil	};
29361.1Skamil	struct ptrace_io_desc io_totracee = {
29371.1Skamil		.piod_op = PIOD_WRITE_D,
29381.1Skamil		.piod_offs = &lookup_me_totracee,
29391.1Skamil		.piod_addr = &lookup_me_totracee,
29401.1Skamil		.piod_len = sizeof(lookup_me_totracee)
29411.1Skamil	};
29421.1Skamil#if defined(TWAIT_HAVE_STATUS)
29431.1Skamil	int status;
29441.1Skamil#endif
29451.1Skamil
29461.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
29471.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
29481.1Skamil	if (child == 0) {
29491.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
29501.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
29511.1Skamil
29521.1Skamil		lookup_me_fromtracee = magic_fromtracee;
29531.1Skamil
29541.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
29551.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
29561.1Skamil
29571.1Skamil		FORKEE_ASSERT_EQ(lookup_me_totracee, magic_totracee);
29581.1Skamil
29591.13Schristos		DPRINTF("Before exiting of the child process\n");
29601.1Skamil		_exit(exitval);
29611.1Skamil	}
29621.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
29631.1Skamil
29641.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29651.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29661.1Skamil
29671.1Skamil	validate_status_stopped(status, sigval);
29681.1Skamil
29691.13Schristos	DPRINTF("Read lookup_me_fromtracee PID=%d by tracer (PID=%d)\n",
29701.1Skamil	    child, getpid());
29711.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io_fromtracee, 0) != -1);
29721.1Skamil
29731.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me_fromtracee, magic_fromtracee,
29741.1Skamil	    "got value %" PRIx8 " != expected %" PRIx8, lookup_me_fromtracee,
29751.1Skamil	    magic_fromtracee);
29761.1Skamil
29771.1Skamil	lookup_me_totracee = magic_totracee;
29781.1Skamil
29791.13Schristos	DPRINTF("Write lookup_me_totracee to PID=%d by tracer (PID=%d)\n",
29801.1Skamil	    child, getpid());
29811.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io_totracee, 0) != -1);
29821.1Skamil
29831.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me_totracee, magic_totracee,
29841.1Skamil	    "got value %" PRIx8 " != expected %" PRIx8, lookup_me_totracee,
29851.1Skamil	    magic_totracee);
29861.1Skamil
29871.13Schristos	DPRINTF("Before resuming the child process where it left off and "
29881.1Skamil	    "without signal to be sent\n");
29891.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
29901.1Skamil
29911.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29921.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
29931.1Skamil
29941.1Skamil	validate_status_exited(status, exitval);
29951.1Skamil
29961.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
29971.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
29981.1Skamil}
29991.1Skamil
30001.1SkamilATF_TC(io_read_d_write_d_handshake2);
30011.1SkamilATF_TC_HEAD(io_read_d_write_d_handshake2, tc)
30021.1Skamil{
30031.1Skamil	atf_tc_set_md_var(tc, "descr",
30041.1Skamil	    "Verify PT_IO with PIOD_WRITE_D and PIOD_READ_D handshake");
30051.1Skamil}
30061.1Skamil
30071.1SkamilATF_TC_BODY(io_read_d_write_d_handshake2, tc)
30081.1Skamil{
30091.1Skamil	const int exitval = 5;
30101.1Skamil	const int sigval = SIGSTOP;
30111.1Skamil	pid_t child, wpid;
30121.1Skamil	uint8_t lookup_me_fromtracee = 0;
30131.1Skamil	const uint8_t magic_fromtracee = (uint8_t)random();
30141.1Skamil	uint8_t lookup_me_totracee = 0;
30151.1Skamil	const uint8_t magic_totracee = (uint8_t)random();
30161.1Skamil	struct ptrace_io_desc io_fromtracee = {
30171.1Skamil		.piod_op = PIOD_READ_D,
30181.1Skamil		.piod_offs = &lookup_me_fromtracee,
30191.1Skamil		.piod_addr = &lookup_me_fromtracee,
30201.1Skamil		.piod_len = sizeof(lookup_me_fromtracee)
30211.1Skamil	};
30221.1Skamil	struct ptrace_io_desc io_totracee = {
30231.1Skamil		.piod_op = PIOD_WRITE_D,
30241.1Skamil		.piod_offs = &lookup_me_totracee,
30251.1Skamil		.piod_addr = &lookup_me_totracee,
30261.1Skamil		.piod_len = sizeof(lookup_me_totracee)
30271.1Skamil	};
30281.1Skamil#if defined(TWAIT_HAVE_STATUS)
30291.1Skamil	int status;
30301.1Skamil#endif
30311.1Skamil
30321.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
30331.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
30341.1Skamil	if (child == 0) {
30351.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
30361.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
30371.1Skamil
30381.1Skamil		lookup_me_fromtracee = magic_fromtracee;
30391.1Skamil
30401.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
30411.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
30421.1Skamil
30431.1Skamil		FORKEE_ASSERT_EQ(lookup_me_totracee, magic_totracee);
30441.1Skamil
30451.13Schristos		DPRINTF("Before exiting of the child process\n");
30461.1Skamil		_exit(exitval);
30471.1Skamil	}
30481.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
30491.1Skamil
30501.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30511.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
30521.1Skamil
30531.1Skamil	validate_status_stopped(status, sigval);
30541.1Skamil
30551.1Skamil	lookup_me_totracee = magic_totracee;
30561.1Skamil
30571.13Schristos	DPRINTF("Write lookup_me_totracee to PID=%d by tracer (PID=%d)\n",
30581.1Skamil	    child, getpid());
30591.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io_totracee, 0) != -1);
30601.1Skamil
30611.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me_totracee, magic_totracee,
30621.1Skamil	    "got value %" PRIx8 " != expected %" PRIx8, lookup_me_totracee,
30631.1Skamil	    magic_totracee);
30641.1Skamil
30651.13Schristos	DPRINTF("Read lookup_me_fromtracee PID=%d by tracer (PID=%d)\n",
30661.1Skamil	    child, getpid());
30671.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io_fromtracee, 0) != -1);
30681.1Skamil
30691.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me_fromtracee, magic_fromtracee,
30701.1Skamil	    "got value %" PRIx8 " != expected %" PRIx8, lookup_me_fromtracee,
30711.1Skamil	    magic_fromtracee);
30721.1Skamil
30731.13Schristos	DPRINTF("Before resuming the child process where it left off and "
30741.1Skamil	    "without signal to be sent\n");
30751.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
30761.1Skamil
30771.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30781.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
30791.1Skamil
30801.1Skamil	validate_status_exited(status, exitval);
30811.1Skamil
30821.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
30831.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
30841.1Skamil}
30851.1Skamil
30861.1SkamilATF_TC(read_d_write_d_handshake1);
30871.1SkamilATF_TC_HEAD(read_d_write_d_handshake1, tc)
30881.1Skamil{
30891.1Skamil	atf_tc_set_md_var(tc, "descr",
30901.1Skamil	    "Verify PT_READ_D with PT_WRITE_D handshake");
30911.1Skamil}
30921.1Skamil
30931.1SkamilATF_TC_BODY(read_d_write_d_handshake1, tc)
30941.1Skamil{
30951.1Skamil	const int exitval = 5;
30961.1Skamil	const int sigval = SIGSTOP;
30971.1Skamil	pid_t child, wpid;
30981.1Skamil	int lookup_me_fromtracee = 0;
30991.1Skamil	const int magic_fromtracee = (int)random();
31001.1Skamil	int lookup_me_totracee = 0;
31011.1Skamil	const int magic_totracee = (int)random();
31021.1Skamil#if defined(TWAIT_HAVE_STATUS)
31031.1Skamil	int status;
31041.1Skamil#endif
31051.1Skamil
31061.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
31071.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
31081.1Skamil	if (child == 0) {
31091.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
31101.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
31111.1Skamil
31121.1Skamil		lookup_me_fromtracee = magic_fromtracee;
31131.1Skamil
31141.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
31151.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
31161.1Skamil
31171.1Skamil		FORKEE_ASSERT_EQ(lookup_me_totracee, magic_totracee);
31181.1Skamil
31191.13Schristos		DPRINTF("Before exiting of the child process\n");
31201.1Skamil		_exit(exitval);
31211.1Skamil	}
31221.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
31231.1Skamil
31241.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
31251.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
31261.1Skamil
31271.1Skamil	validate_status_stopped(status, sigval);
31281.1Skamil
31291.13Schristos	DPRINTF("Read new lookup_me_fromtracee PID=%d by tracer (PID=%d)\n",
31301.1Skamil	    child, getpid());
31311.1Skamil	errno = 0;
31321.1Skamil	lookup_me_fromtracee =
31331.1Skamil	    ptrace(PT_READ_D, child, &lookup_me_fromtracee, 0);
31341.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
31351.1Skamil
31361.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me_fromtracee, magic_fromtracee,
31371.1Skamil	    "got value %#x != expected %#x", lookup_me_fromtracee,
31381.1Skamil	    magic_fromtracee);
31391.1Skamil
31401.13Schristos	DPRINTF("Write new lookup_me_totracee to PID=%d from tracer (PID=%d)\n",
31411.1Skamil	    child, getpid());
31421.1Skamil	ATF_REQUIRE
31431.1Skamil	    (ptrace(PT_WRITE_D, child, &lookup_me_totracee, magic_totracee)
31441.1Skamil	    != -1);
31451.1Skamil
31461.13Schristos	DPRINTF("Before resuming the child process where it left off and "
31471.1Skamil	    "without signal to be sent\n");
31481.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
31491.1Skamil
31501.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
31511.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
31521.1Skamil
31531.1Skamil	validate_status_exited(status, exitval);
31541.1Skamil
31551.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
31561.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
31571.1Skamil}
31581.1Skamil
31591.1SkamilATF_TC(read_d_write_d_handshake2);
31601.1SkamilATF_TC_HEAD(read_d_write_d_handshake2, tc)
31611.1Skamil{
31621.1Skamil	atf_tc_set_md_var(tc, "descr",
31631.1Skamil	    "Verify PT_WRITE_D with PT_READ_D handshake");
31641.1Skamil}
31651.1Skamil
31661.1SkamilATF_TC_BODY(read_d_write_d_handshake2, tc)
31671.1Skamil{
31681.1Skamil	const int exitval = 5;
31691.1Skamil	const int sigval = SIGSTOP;
31701.1Skamil	pid_t child, wpid;
31711.1Skamil	int lookup_me_fromtracee = 0;
31721.1Skamil	const int magic_fromtracee = (int)random();
31731.1Skamil	int lookup_me_totracee = 0;
31741.1Skamil	const int magic_totracee = (int)random();
31751.1Skamil#if defined(TWAIT_HAVE_STATUS)
31761.1Skamil	int status;
31771.1Skamil#endif
31781.1Skamil
31791.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
31801.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
31811.1Skamil	if (child == 0) {
31821.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
31831.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
31841.1Skamil
31851.1Skamil		lookup_me_fromtracee = magic_fromtracee;
31861.1Skamil
31871.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
31881.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
31891.1Skamil
31901.1Skamil		FORKEE_ASSERT_EQ(lookup_me_totracee, magic_totracee);
31911.1Skamil
31921.13Schristos		DPRINTF("Before exiting of the child process\n");
31931.1Skamil		_exit(exitval);
31941.1Skamil	}
31951.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
31961.1Skamil
31971.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
31981.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
31991.1Skamil
32001.1Skamil	validate_status_stopped(status, sigval);
32011.1Skamil
32021.13Schristos	DPRINTF("Write new lookup_me_totracee to PID=%d from tracer (PID=%d)\n",
32031.1Skamil	    child, getpid());
32041.1Skamil	ATF_REQUIRE
32051.1Skamil	    (ptrace(PT_WRITE_D, child, &lookup_me_totracee, magic_totracee)
32061.1Skamil	    != -1);
32071.1Skamil
32081.13Schristos	DPRINTF("Read new lookup_me_fromtracee PID=%d by tracer (PID=%d)\n",
32091.1Skamil	    child, getpid());
32101.1Skamil	errno = 0;
32111.1Skamil	lookup_me_fromtracee =
32121.1Skamil	    ptrace(PT_READ_D, child, &lookup_me_fromtracee, 0);
32131.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
32141.1Skamil
32151.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me_fromtracee, magic_fromtracee,
32161.1Skamil	    "got value %#x != expected %#x", lookup_me_fromtracee,
32171.1Skamil	    magic_fromtracee);
32181.1Skamil
32191.13Schristos	DPRINTF("Before resuming the child process where it left off and "
32201.1Skamil	    "without signal to be sent\n");
32211.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
32221.1Skamil
32231.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32241.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
32251.1Skamil
32261.1Skamil	validate_status_exited(status, exitval);
32271.1Skamil
32281.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
32291.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
32301.1Skamil}
32311.1Skamil
32321.1Skamil/* These dummy functions are used to be copied with ptrace(2) calls */
32331.1Skamilstatic int __used
32341.1Skamildummy_fn1(int a, int b, int c, int d)
32351.1Skamil{
32361.1Skamil
32371.1Skamil	a *= 1;
32381.1Skamil	b += 2;
32391.1Skamil	c -= 3;
32401.1Skamil	d /= 4;
32411.1Skamil
32421.1Skamil	return a + b * c - d;
32431.1Skamil}
32441.1Skamil
32451.1Skamilstatic int __used
32461.1Skamildummy_fn2(int a, int b, int c, int d)
32471.1Skamil{
32481.1Skamil
32491.1Skamil	a *= 4;
32501.1Skamil	b += 3;
32511.1Skamil	c -= 2;
32521.1Skamil	d /= 1;
32531.1Skamil
32541.1Skamil	return a + b * c - d;
32551.1Skamil}
32561.1Skamil
32571.1Skamilstatic int __used
32581.1Skamildummy_fn3(int a, int b, int c, int d)
32591.1Skamil{
32601.1Skamil
32611.1Skamil	a *= 10;
32621.1Skamil	b += 20;
32631.1Skamil	c -= 30;
32641.1Skamil	d /= 40;
32651.1Skamil
32661.1Skamil	return a + b * c - d;
32671.1Skamil}
32681.1Skamil
32691.1Skamilstatic int __used
32701.1Skamildummy_fn4(int a, int b, int c, int d)
32711.1Skamil{
32721.1Skamil
32731.1Skamil	a *= 40;
32741.1Skamil	b += 30;
32751.1Skamil	c -= 20;
32761.1Skamil	d /= 10;
32771.1Skamil
32781.1Skamil	return a + b * c - d;
32791.1Skamil}
32801.1Skamil
32811.1SkamilATF_TC(io_read_i1);
32821.1SkamilATF_TC_HEAD(io_read_i1, tc)
32831.1Skamil{
32841.1Skamil	atf_tc_set_md_var(tc, "descr",
32851.1Skamil	    "Verify PT_IO with PIOD_READ_I and len = sizeof(uint8_t)");
32861.1Skamil}
32871.1Skamil
32881.1SkamilATF_TC_BODY(io_read_i1, tc)
32891.1Skamil{
32901.1Skamil	const int exitval = 5;
32911.1Skamil	const int sigval = SIGSTOP;
32921.1Skamil	pid_t child, wpid;
32931.1Skamil	uint8_t lookup_me = 0;
32941.1Skamil	uint8_t magic;
32951.1Skamil	memcpy(&magic, dummy_fn1, sizeof(magic));
32961.1Skamil	struct ptrace_io_desc io = {
32971.1Skamil		.piod_op = PIOD_READ_I,
32981.1Skamil		.piod_offs = dummy_fn1,
32991.1Skamil		.piod_addr = &lookup_me,
33001.1Skamil		.piod_len = sizeof(lookup_me)
33011.1Skamil	};
33021.1Skamil#if defined(TWAIT_HAVE_STATUS)
33031.1Skamil	int status;
33041.1Skamil#endif
33051.1Skamil
33061.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
33071.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
33081.1Skamil	if (child == 0) {
33091.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
33101.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
33111.1Skamil
33121.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
33131.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
33141.1Skamil
33151.13Schristos		DPRINTF("Before exiting of the child process\n");
33161.1Skamil		_exit(exitval);
33171.1Skamil	}
33181.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
33191.1Skamil
33201.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
33211.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
33221.1Skamil
33231.1Skamil	validate_status_stopped(status, sigval);
33241.1Skamil
33251.13Schristos	DPRINTF("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
33261.1Skamil	    child, getpid());
33271.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
33281.1Skamil
33291.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
33301.1Skamil	    "got value %" PRIx8 " != expected %" PRIx8, lookup_me, magic);
33311.1Skamil
33321.13Schristos	DPRINTF("Before resuming the child process where it left off and "
33331.1Skamil	    "without signal to be sent\n");
33341.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
33351.1Skamil
33361.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
33371.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
33381.1Skamil
33391.1Skamil	validate_status_exited(status, exitval);
33401.1Skamil
33411.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
33421.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
33431.1Skamil}
33441.1Skamil
33451.1SkamilATF_TC(io_read_i2);
33461.1SkamilATF_TC_HEAD(io_read_i2, tc)
33471.1Skamil{
33481.1Skamil	atf_tc_set_md_var(tc, "descr",
33491.1Skamil	    "Verify PT_IO with PIOD_READ_I and len = sizeof(uint16_t)");
33501.1Skamil}
33511.1Skamil
33521.1SkamilATF_TC_BODY(io_read_i2, tc)
33531.1Skamil{
33541.1Skamil	const int exitval = 5;
33551.1Skamil	const int sigval = SIGSTOP;
33561.1Skamil	pid_t child, wpid;
33571.1Skamil	uint16_t lookup_me = 0;
33581.1Skamil	uint16_t magic;
33591.1Skamil	memcpy(&magic, dummy_fn1, sizeof(magic));
33601.1Skamil	struct ptrace_io_desc io = {
33611.1Skamil		.piod_op = PIOD_READ_I,
33621.1Skamil		.piod_offs = dummy_fn1,
33631.1Skamil		.piod_addr = &lookup_me,
33641.1Skamil		.piod_len = sizeof(lookup_me)
33651.1Skamil	};
33661.1Skamil#if defined(TWAIT_HAVE_STATUS)
33671.1Skamil	int status;
33681.1Skamil#endif
33691.1Skamil
33701.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
33711.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
33721.1Skamil	if (child == 0) {
33731.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
33741.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
33751.1Skamil
33761.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
33771.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
33781.1Skamil
33791.13Schristos		DPRINTF("Before exiting of the child process\n");
33801.1Skamil		_exit(exitval);
33811.1Skamil	}
33821.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
33831.1Skamil
33841.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
33851.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
33861.1Skamil
33871.1Skamil	validate_status_stopped(status, sigval);
33881.1Skamil
33891.13Schristos	DPRINTF("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
33901.1Skamil	    child, getpid());
33911.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
33921.1Skamil
33931.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
33941.1Skamil	    "got value %" PRIx16 " != expected %" PRIx16, lookup_me, magic);
33951.1Skamil
33961.13Schristos	DPRINTF("Before resuming the child process where it left off and "
33971.1Skamil	    "without signal to be sent\n");
33981.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
33991.1Skamil
34001.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
34011.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
34021.1Skamil
34031.1Skamil	validate_status_exited(status, exitval);
34041.1Skamil
34051.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
34061.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
34071.1Skamil}
34081.1Skamil
34091.1SkamilATF_TC(io_read_i3);
34101.1SkamilATF_TC_HEAD(io_read_i3, tc)
34111.1Skamil{
34121.1Skamil	atf_tc_set_md_var(tc, "descr",
34131.1Skamil	    "Verify PT_IO with PIOD_READ_I and len = sizeof(uint32_t)");
34141.1Skamil}
34151.1Skamil
34161.1SkamilATF_TC_BODY(io_read_i3, tc)
34171.1Skamil{
34181.1Skamil	const int exitval = 5;
34191.1Skamil	const int sigval = SIGSTOP;
34201.1Skamil	pid_t child, wpid;
34211.1Skamil	uint32_t lookup_me = 0;
34221.1Skamil	uint32_t magic;
34231.1Skamil	memcpy(&magic, dummy_fn1, sizeof(magic));
34241.1Skamil	struct ptrace_io_desc io = {
34251.1Skamil		.piod_op = PIOD_READ_I,
34261.1Skamil		.piod_offs = dummy_fn1,
34271.1Skamil		.piod_addr = &lookup_me,
34281.1Skamil		.piod_len = sizeof(lookup_me)
34291.1Skamil	};
34301.1Skamil#if defined(TWAIT_HAVE_STATUS)
34311.1Skamil	int status;
34321.1Skamil#endif
34331.1Skamil
34341.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
34351.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
34361.1Skamil	if (child == 0) {
34371.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
34381.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
34391.1Skamil
34401.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
34411.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
34421.1Skamil
34431.13Schristos		DPRINTF("Before exiting of the child process\n");
34441.1Skamil		_exit(exitval);
34451.1Skamil	}
34461.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
34471.1Skamil
34481.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
34491.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
34501.1Skamil
34511.1Skamil	validate_status_stopped(status, sigval);
34521.1Skamil
34531.13Schristos	DPRINTF("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
34541.1Skamil	    child, getpid());
34551.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
34561.1Skamil
34571.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
34581.1Skamil	    "got value %" PRIx32 " != expected %" PRIx32, lookup_me, magic);
34591.1Skamil
34601.13Schristos	DPRINTF("Before resuming the child process where it left off and "
34611.1Skamil	    "without signal to be sent\n");
34621.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
34631.1Skamil
34641.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
34651.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
34661.1Skamil
34671.1Skamil	validate_status_exited(status, exitval);
34681.1Skamil
34691.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
34701.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
34711.1Skamil}
34721.1Skamil
34731.1SkamilATF_TC(io_read_i4);
34741.1SkamilATF_TC_HEAD(io_read_i4, tc)
34751.1Skamil{
34761.1Skamil	atf_tc_set_md_var(tc, "descr",
34771.1Skamil	    "Verify PT_IO with PIOD_READ_I and len = sizeof(uint64_t)");
34781.1Skamil}
34791.1Skamil
34801.1SkamilATF_TC_BODY(io_read_i4, tc)
34811.1Skamil{
34821.1Skamil	const int exitval = 5;
34831.1Skamil	const int sigval = SIGSTOP;
34841.1Skamil	pid_t child, wpid;
34851.1Skamil	uint64_t lookup_me = 0;
34861.1Skamil	uint64_t magic;
34871.1Skamil	memcpy(&magic, dummy_fn1, sizeof(magic));
34881.1Skamil	struct ptrace_io_desc io = {
34891.1Skamil		.piod_op = PIOD_READ_I,
34901.1Skamil		.piod_offs = dummy_fn1,
34911.1Skamil		.piod_addr = &lookup_me,
34921.1Skamil		.piod_len = sizeof(lookup_me)
34931.1Skamil	};
34941.1Skamil#if defined(TWAIT_HAVE_STATUS)
34951.1Skamil	int status;
34961.1Skamil#endif
34971.1Skamil
34981.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
34991.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
35001.1Skamil	if (child == 0) {
35011.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
35021.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
35031.1Skamil
35041.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
35051.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
35061.1Skamil
35071.13Schristos		DPRINTF("Before exiting of the child process\n");
35081.1Skamil		_exit(exitval);
35091.1Skamil	}
35101.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
35111.1Skamil
35121.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35131.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
35141.1Skamil
35151.1Skamil	validate_status_stopped(status, sigval);
35161.1Skamil
35171.13Schristos	DPRINTF("Read lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
35181.1Skamil	    child, getpid());
35191.13Schristos	SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
35201.1Skamil
35211.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
35221.1Skamil	    "got value %" PRIx64 " != expected %" PRIx64, lookup_me, magic);
35231.1Skamil
35241.13Schristos	DPRINTF("Before resuming the child process where it left off and "
35251.1Skamil	    "without signal to be sent\n");
35261.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
35271.1Skamil
35281.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35291.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
35301.1Skamil
35311.1Skamil	validate_status_exited(status, exitval);
35321.1Skamil
35331.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35341.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
35351.1Skamil}
35361.1Skamil
35371.1SkamilATF_TC(read_i1);
35381.1SkamilATF_TC_HEAD(read_i1, tc)
35391.1Skamil{
35401.1Skamil	atf_tc_set_md_var(tc, "descr",
35411.1Skamil	    "Verify PT_READ_I called once");
35421.1Skamil}
35431.1Skamil
35441.1SkamilATF_TC_BODY(read_i1, tc)
35451.1Skamil{
35461.1Skamil	const int exitval = 5;
35471.1Skamil	const int sigval = SIGSTOP;
35481.1Skamil	pid_t child, wpid;
35491.1Skamil	int lookup_me = 0;
35501.1Skamil	int magic;
35511.1Skamil	memcpy(&magic, dummy_fn1, sizeof(magic));
35521.1Skamil#if defined(TWAIT_HAVE_STATUS)
35531.1Skamil	int status;
35541.1Skamil#endif
35551.1Skamil
35561.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
35571.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
35581.1Skamil	if (child == 0) {
35591.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
35601.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
35611.1Skamil
35621.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
35631.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
35641.1Skamil
35651.13Schristos		DPRINTF("Before exiting of the child process\n");
35661.1Skamil		_exit(exitval);
35671.1Skamil	}
35681.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
35691.1Skamil
35701.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35711.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
35721.1Skamil
35731.1Skamil	validate_status_stopped(status, sigval);
35741.1Skamil
35751.13Schristos	DPRINTF("Read new lookup_me from tracee (PID=%d) by tracer (PID=%d)\n",
35761.1Skamil	    child, getpid());
35771.1Skamil	errno = 0;
35781.1Skamil	lookup_me = ptrace(PT_READ_I, child, dummy_fn1, 0);
35791.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
35801.1Skamil
35811.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me, magic,
35821.1Skamil	    "got value %#x != expected %#x", lookup_me, magic);
35831.1Skamil
35841.13Schristos	DPRINTF("Before resuming the child process where it left off and "
35851.1Skamil	    "without signal to be sent\n");
35861.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
35871.1Skamil
35881.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35891.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
35901.1Skamil
35911.1Skamil	validate_status_exited(status, exitval);
35921.1Skamil
35931.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
35941.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
35951.1Skamil}
35961.1Skamil
35971.1SkamilATF_TC(read_i2);
35981.1SkamilATF_TC_HEAD(read_i2, tc)
35991.1Skamil{
36001.1Skamil	atf_tc_set_md_var(tc, "descr",
36011.1Skamil	    "Verify PT_READ_I called twice");
36021.1Skamil}
36031.1Skamil
36041.1SkamilATF_TC_BODY(read_i2, tc)
36051.1Skamil{
36061.1Skamil	const int exitval = 5;
36071.1Skamil	const int sigval = SIGSTOP;
36081.1Skamil	pid_t child, wpid;
36091.1Skamil	int lookup_me1 = 0;
36101.1Skamil	int lookup_me2 = 0;
36111.1Skamil	int magic1;
36121.1Skamil	int magic2;
36131.1Skamil	memcpy(&magic1, dummy_fn1, sizeof(magic1));
36141.1Skamil	memcpy(&magic2, dummy_fn2, sizeof(magic2));
36151.1Skamil#if defined(TWAIT_HAVE_STATUS)
36161.1Skamil	int status;
36171.1Skamil#endif
36181.1Skamil
36191.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
36201.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
36211.1Skamil	if (child == 0) {
36221.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
36231.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
36241.1Skamil
36251.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
36261.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
36271.1Skamil
36281.13Schristos		DPRINTF("Before exiting of the child process\n");
36291.1Skamil		_exit(exitval);
36301.1Skamil	}
36311.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
36321.1Skamil
36331.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36341.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
36351.1Skamil
36361.1Skamil	validate_status_stopped(status, sigval);
36371.1Skamil
36381.13Schristos	DPRINTF("Read new lookup_me1 from tracee (PID=%d) by tracer (PID=%d)\n",
36391.1Skamil	    child, getpid());
36401.1Skamil	errno = 0;
36411.1Skamil	lookup_me1 = ptrace(PT_READ_I, child, dummy_fn1, 0);
36421.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
36431.1Skamil
36441.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me1, magic1,
36451.1Skamil	    "got value %#x != expected %#x", lookup_me1, magic1);
36461.1Skamil
36471.13Schristos	DPRINTF("Read new lookup_me2 from tracee (PID=%d) by tracer (PID=%d)\n",
36481.1Skamil	    child, getpid());
36491.1Skamil	errno = 0;
36501.1Skamil	lookup_me2 = ptrace(PT_READ_I, child, dummy_fn2, 0);
36511.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
36521.1Skamil
36531.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me2, magic2,
36541.1Skamil	    "got value %#x != expected %#x", lookup_me2, magic2);
36551.1Skamil
36561.13Schristos	DPRINTF("Before resuming the child process where it left off and "
36571.1Skamil	    "without signal to be sent\n");
36581.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
36591.1Skamil
36601.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36611.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
36621.1Skamil
36631.1Skamil	validate_status_exited(status, exitval);
36641.1Skamil
36651.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
36661.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
36671.1Skamil}
36681.1Skamil
36691.1SkamilATF_TC(read_i3);
36701.1SkamilATF_TC_HEAD(read_i3, tc)
36711.1Skamil{
36721.1Skamil	atf_tc_set_md_var(tc, "descr",
36731.1Skamil	    "Verify PT_READ_I called three times");
36741.1Skamil}
36751.1Skamil
36761.1SkamilATF_TC_BODY(read_i3, tc)
36771.1Skamil{
36781.1Skamil	const int exitval = 5;
36791.1Skamil	const int sigval = SIGSTOP;
36801.1Skamil	pid_t child, wpid;
36811.1Skamil	int lookup_me1 = 0;
36821.1Skamil	int lookup_me2 = 0;
36831.1Skamil	int lookup_me3 = 0;
36841.1Skamil	int magic1;
36851.1Skamil	int magic2;
36861.1Skamil	int magic3;
36871.1Skamil	memcpy(&magic1, dummy_fn1, sizeof(magic1));
36881.1Skamil	memcpy(&magic2, dummy_fn2, sizeof(magic2));
36891.1Skamil	memcpy(&magic3, dummy_fn3, sizeof(magic3));
36901.1Skamil#if defined(TWAIT_HAVE_STATUS)
36911.1Skamil	int status;
36921.1Skamil#endif
36931.1Skamil
36941.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
36951.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
36961.1Skamil	if (child == 0) {
36971.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
36981.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
36991.1Skamil
37001.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
37011.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
37021.1Skamil
37031.13Schristos		DPRINTF("Before exiting of the child process\n");
37041.1Skamil		_exit(exitval);
37051.1Skamil	}
37061.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
37071.1Skamil
37081.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37091.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
37101.1Skamil
37111.1Skamil	validate_status_stopped(status, sigval);
37121.1Skamil
37131.13Schristos	DPRINTF("Read new lookup_me1 from tracee (PID=%d) by tracer (PID=%d)\n",
37141.1Skamil	    child, getpid());
37151.1Skamil	errno = 0;
37161.1Skamil	lookup_me1 = ptrace(PT_READ_I, child, dummy_fn1, 0);
37171.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
37181.1Skamil
37191.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me1, magic1,
37201.1Skamil	    "got value %#x != expected %#x", lookup_me1, magic1);
37211.1Skamil
37221.13Schristos	DPRINTF("Read new lookup_me2 from tracee (PID=%d) by tracer (PID=%d)\n",
37231.1Skamil	    child, getpid());
37241.1Skamil	errno = 0;
37251.1Skamil	lookup_me2 = ptrace(PT_READ_I, child, dummy_fn2, 0);
37261.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
37271.1Skamil
37281.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me2, magic2,
37291.1Skamil	    "got value %#x != expected %#x", lookup_me2, magic2);
37301.1Skamil
37311.13Schristos	DPRINTF("Read new lookup_me3 from tracee (PID=%d) by tracer (PID=%d)\n",
37321.1Skamil	    child, getpid());
37331.1Skamil	errno = 0;
37341.1Skamil	lookup_me3 = ptrace(PT_READ_I, child, dummy_fn3, 0);
37351.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
37361.1Skamil
37371.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me3, magic3,
37381.1Skamil	    "got value %#x != expected %#x", lookup_me3, magic3);
37391.1Skamil
37401.13Schristos	DPRINTF("Before resuming the child process where it left off and "
37411.1Skamil	    "without signal to be sent\n");
37421.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
37431.1Skamil
37441.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37451.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
37461.1Skamil
37471.1Skamil	validate_status_exited(status, exitval);
37481.1Skamil
37491.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37501.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
37511.1Skamil}
37521.1Skamil
37531.1SkamilATF_TC(read_i4);
37541.1SkamilATF_TC_HEAD(read_i4, tc)
37551.1Skamil{
37561.1Skamil	atf_tc_set_md_var(tc, "descr",
37571.1Skamil	    "Verify PT_READ_I called four times");
37581.1Skamil}
37591.1Skamil
37601.1SkamilATF_TC_BODY(read_i4, tc)
37611.1Skamil{
37621.1Skamil	const int exitval = 5;
37631.1Skamil	const int sigval = SIGSTOP;
37641.1Skamil	pid_t child, wpid;
37651.1Skamil	int lookup_me1 = 0;
37661.1Skamil	int lookup_me2 = 0;
37671.1Skamil	int lookup_me3 = 0;
37681.1Skamil	int lookup_me4 = 0;
37691.1Skamil	int magic1;
37701.1Skamil	int magic2;
37711.1Skamil	int magic3;
37721.1Skamil	int magic4;
37731.1Skamil	memcpy(&magic1, dummy_fn1, sizeof(magic1));
37741.1Skamil	memcpy(&magic2, dummy_fn2, sizeof(magic2));
37751.1Skamil	memcpy(&magic3, dummy_fn3, sizeof(magic3));
37761.1Skamil	memcpy(&magic4, dummy_fn4, sizeof(magic4));
37771.1Skamil#if defined(TWAIT_HAVE_STATUS)
37781.1Skamil	int status;
37791.1Skamil#endif
37801.1Skamil
37811.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
37821.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
37831.1Skamil	if (child == 0) {
37841.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
37851.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
37861.1Skamil
37871.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
37881.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
37891.1Skamil
37901.13Schristos		DPRINTF("Before exiting of the child process\n");
37911.1Skamil		_exit(exitval);
37921.1Skamil	}
37931.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
37941.1Skamil
37951.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
37961.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
37971.1Skamil
37981.1Skamil	validate_status_stopped(status, sigval);
37991.1Skamil
38001.13Schristos	DPRINTF("Read new lookup_me1 from tracee (PID=%d) by tracer (PID=%d)\n",
38011.1Skamil	    child, getpid());
38021.1Skamil	errno = 0;
38031.1Skamil	lookup_me1 = ptrace(PT_READ_I, child, dummy_fn1, 0);
38041.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
38051.1Skamil
38061.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me1, magic1,
38071.1Skamil	    "got value %#x != expected %#x", lookup_me1, magic1);
38081.1Skamil
38091.13Schristos	DPRINTF("Read new lookup_me2 from tracee (PID=%d) by tracer (PID=%d)\n",
38101.1Skamil	    child, getpid());
38111.1Skamil	errno = 0;
38121.1Skamil	lookup_me2 = ptrace(PT_READ_I, child, dummy_fn2, 0);
38131.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
38141.1Skamil
38151.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me2, magic2,
38161.1Skamil	    "got value %#x != expected %#x", lookup_me2, magic2);
38171.1Skamil
38181.13Schristos	DPRINTF("Read new lookup_me3 from tracee (PID=%d) by tracer (PID=%d)\n",
38191.1Skamil	    child, getpid());
38201.1Skamil	errno = 0;
38211.1Skamil	lookup_me3 = ptrace(PT_READ_I, child, dummy_fn3, 0);
38221.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
38231.1Skamil
38241.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me3, magic3,
38251.1Skamil	    "got value %#x != expected %#x", lookup_me3, magic3);
38261.1Skamil
38271.13Schristos	DPRINTF("Read new lookup_me4 from tracee (PID=%d) by tracer (PID=%d)\n",
38281.1Skamil	    child, getpid());
38291.1Skamil	errno = 0;
38301.1Skamil	lookup_me4 = ptrace(PT_READ_I, child, dummy_fn4, 0);
38311.18Schristos	SYSCALL_REQUIRE_ERRNO(errno, 0);
38321.1Skamil
38331.1Skamil	ATF_REQUIRE_EQ_MSG(lookup_me4, magic4,
38341.1Skamil	    "got value %#x != expected %#x", lookup_me4, magic4);
38351.1Skamil
38361.13Schristos	DPRINTF("Before resuming the child process where it left off and "
38371.1Skamil	    "without signal to be sent\n");
38381.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
38391.1Skamil
38401.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38411.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
38421.1Skamil
38431.1Skamil	validate_status_exited(status, exitval);
38441.1Skamil
38451.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38461.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
38471.1Skamil}
38481.1Skamil
38491.1Skamil#if defined(HAVE_GPREGS)
38501.1SkamilATF_TC(regs1);
38511.1SkamilATF_TC_HEAD(regs1, tc)
38521.1Skamil{
38531.1Skamil	atf_tc_set_md_var(tc, "descr",
38541.1Skamil	    "Verify plain PT_GETREGS call without further steps");
38551.1Skamil}
38561.1Skamil
38571.1SkamilATF_TC_BODY(regs1, tc)
38581.1Skamil{
38591.1Skamil	const int exitval = 5;
38601.1Skamil	const int sigval = SIGSTOP;
38611.1Skamil	pid_t child, wpid;
38621.1Skamil#if defined(TWAIT_HAVE_STATUS)
38631.1Skamil	int status;
38641.1Skamil#endif
38651.1Skamil	struct reg r;
38661.1Skamil
38671.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
38681.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
38691.1Skamil	if (child == 0) {
38701.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
38711.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
38721.1Skamil
38731.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
38741.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
38751.1Skamil
38761.13Schristos		DPRINTF("Before exiting of the child process\n");
38771.1Skamil		_exit(exitval);
38781.1Skamil	}
38791.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
38801.1Skamil
38811.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38821.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
38831.1Skamil
38841.1Skamil	validate_status_stopped(status, sigval);
38851.1Skamil
38861.13Schristos	DPRINTF("Call GETREGS for the child process\n");
38871.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
38881.1Skamil
38891.13Schristos	DPRINTF("Before resuming the child process where it left off and "
38901.1Skamil	    "without signal to be sent\n");
38911.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
38921.1Skamil
38931.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38941.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
38951.1Skamil
38961.1Skamil	validate_status_exited(status, exitval);
38971.1Skamil
38981.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
38991.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
39001.1Skamil}
39011.1Skamil#endif
39021.1Skamil
39031.1Skamil#if defined(HAVE_GPREGS)
39041.1SkamilATF_TC(regs2);
39051.1SkamilATF_TC_HEAD(regs2, tc)
39061.1Skamil{
39071.1Skamil	atf_tc_set_md_var(tc, "descr",
39081.1Skamil	    "Verify plain PT_GETREGS call and retrieve PC");
39091.1Skamil}
39101.1Skamil
39111.1SkamilATF_TC_BODY(regs2, tc)
39121.1Skamil{
39131.1Skamil	const int exitval = 5;
39141.1Skamil	const int sigval = SIGSTOP;
39151.1Skamil	pid_t child, wpid;
39161.1Skamil#if defined(TWAIT_HAVE_STATUS)
39171.1Skamil	int status;
39181.1Skamil#endif
39191.1Skamil	struct reg r;
39201.1Skamil
39211.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
39221.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
39231.1Skamil	if (child == 0) {
39241.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
39251.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
39261.1Skamil
39271.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
39281.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
39291.1Skamil
39301.13Schristos		DPRINTF("Before exiting of the child process\n");
39311.1Skamil		_exit(exitval);
39321.1Skamil	}
39331.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
39341.1Skamil
39351.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39361.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39371.1Skamil
39381.1Skamil	validate_status_stopped(status, sigval);
39391.1Skamil
39401.13Schristos	DPRINTF("Call GETREGS for the child process\n");
39411.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
39421.1Skamil
39431.13Schristos	DPRINTF("Retrieved PC=%" PRIxREGISTER "\n", PTRACE_REG_PC(&r));
39441.1Skamil
39451.13Schristos	DPRINTF("Before resuming the child process where it left off and "
39461.1Skamil	    "without signal to be sent\n");
39471.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
39481.1Skamil
39491.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39501.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39511.1Skamil
39521.1Skamil	validate_status_exited(status, exitval);
39531.1Skamil
39541.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39551.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
39561.1Skamil}
39571.1Skamil#endif
39581.1Skamil
39591.1Skamil#if defined(HAVE_GPREGS)
39601.1SkamilATF_TC(regs3);
39611.1SkamilATF_TC_HEAD(regs3, tc)
39621.1Skamil{
39631.1Skamil	atf_tc_set_md_var(tc, "descr",
39641.1Skamil	    "Verify plain PT_GETREGS call and retrieve SP");
39651.1Skamil}
39661.1Skamil
39671.1SkamilATF_TC_BODY(regs3, tc)
39681.1Skamil{
39691.1Skamil	const int exitval = 5;
39701.1Skamil	const int sigval = SIGSTOP;
39711.1Skamil	pid_t child, wpid;
39721.1Skamil#if defined(TWAIT_HAVE_STATUS)
39731.1Skamil	int status;
39741.1Skamil#endif
39751.1Skamil	struct reg r;
39761.1Skamil
39771.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
39781.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
39791.1Skamil	if (child == 0) {
39801.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
39811.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
39821.1Skamil
39831.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
39841.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
39851.1Skamil
39861.13Schristos		DPRINTF("Before exiting of the child process\n");
39871.1Skamil		_exit(exitval);
39881.1Skamil	}
39891.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
39901.1Skamil
39911.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
39921.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
39931.1Skamil
39941.1Skamil	validate_status_stopped(status, sigval);
39951.1Skamil
39961.13Schristos	DPRINTF("Call GETREGS for the child process\n");
39971.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
39981.1Skamil
39991.13Schristos	DPRINTF("Retrieved SP=%" PRIxREGISTER "\n", PTRACE_REG_SP(&r));
40001.1Skamil
40011.13Schristos	DPRINTF("Before resuming the child process where it left off and "
40021.1Skamil	    "without signal to be sent\n");
40031.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
40041.1Skamil
40051.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40061.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40071.1Skamil
40081.1Skamil	validate_status_exited(status, exitval);
40091.1Skamil
40101.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40111.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
40121.1Skamil}
40131.1Skamil#endif
40141.1Skamil
40151.1Skamil#if defined(HAVE_GPREGS)
40161.1SkamilATF_TC(regs4);
40171.1SkamilATF_TC_HEAD(regs4, tc)
40181.1Skamil{
40191.1Skamil	atf_tc_set_md_var(tc, "descr",
40201.1Skamil	    "Verify plain PT_GETREGS call and retrieve INTRV");
40211.1Skamil}
40221.1Skamil
40231.1SkamilATF_TC_BODY(regs4, tc)
40241.1Skamil{
40251.1Skamil	const int exitval = 5;
40261.1Skamil	const int sigval = SIGSTOP;
40271.1Skamil	pid_t child, wpid;
40281.1Skamil#if defined(TWAIT_HAVE_STATUS)
40291.1Skamil	int status;
40301.1Skamil#endif
40311.1Skamil	struct reg r;
40321.1Skamil
40331.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
40341.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
40351.1Skamil	if (child == 0) {
40361.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
40371.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
40381.1Skamil
40391.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
40401.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
40411.1Skamil
40421.13Schristos		DPRINTF("Before exiting of the child process\n");
40431.1Skamil		_exit(exitval);
40441.1Skamil	}
40451.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
40461.1Skamil
40471.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40481.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40491.1Skamil
40501.1Skamil	validate_status_stopped(status, sigval);
40511.1Skamil
40521.13Schristos	DPRINTF("Call GETREGS for the child process\n");
40531.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
40541.1Skamil
40551.13Schristos	DPRINTF("Retrieved INTRV=%" PRIxREGISTER "\n", PTRACE_REG_INTRV(&r));
40561.1Skamil
40571.13Schristos	DPRINTF("Before resuming the child process where it left off and "
40581.1Skamil	    "without signal to be sent\n");
40591.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
40601.1Skamil
40611.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40621.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
40631.1Skamil
40641.1Skamil	validate_status_exited(status, exitval);
40651.1Skamil
40661.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
40671.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
40681.1Skamil}
40691.1Skamil#endif
40701.1Skamil
40711.1Skamil#if defined(HAVE_GPREGS)
40721.1SkamilATF_TC(regs5);
40731.1SkamilATF_TC_HEAD(regs5, tc)
40741.1Skamil{
40751.1Skamil	atf_tc_set_md_var(tc, "descr",
40761.1Skamil	    "Verify PT_GETREGS and PT_SETREGS calls without changing regs");
40771.1Skamil}
40781.1Skamil
40791.1SkamilATF_TC_BODY(regs5, tc)
40801.1Skamil{
40811.1Skamil	const int exitval = 5;
40821.1Skamil	const int sigval = SIGSTOP;
40831.1Skamil	pid_t child, wpid;
40841.1Skamil#if defined(TWAIT_HAVE_STATUS)
40851.1Skamil	int status;
40861.1Skamil#endif
40871.1Skamil	struct reg r;
40881.1Skamil
40891.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
40901.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
40911.1Skamil	if (child == 0) {
40921.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
40931.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
40941.1Skamil
40951.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
40961.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
40971.1Skamil
40981.13Schristos		DPRINTF("Before exiting of the child process\n");
40991.1Skamil		_exit(exitval);
41001.1Skamil	}
41011.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
41021.1Skamil
41031.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41041.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41051.1Skamil
41061.1Skamil	validate_status_stopped(status, sigval);
41071.1Skamil
41081.13Schristos	DPRINTF("Call GETREGS for the child process\n");
41091.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
41101.1Skamil
41111.13Schristos	DPRINTF("Call SETREGS for the child process (without changed regs)\n");
41121.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
41131.1Skamil
41141.13Schristos	DPRINTF("Before resuming the child process where it left off and "
41151.1Skamil	    "without signal to be sent\n");
41161.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
41171.1Skamil
41181.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41191.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41201.1Skamil
41211.1Skamil	validate_status_exited(status, exitval);
41221.1Skamil
41231.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41241.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
41251.1Skamil}
41261.1Skamil#endif
41271.1Skamil
41281.1Skamil#if defined(HAVE_FPREGS)
41291.1SkamilATF_TC(fpregs1);
41301.1SkamilATF_TC_HEAD(fpregs1, tc)
41311.1Skamil{
41321.1Skamil	atf_tc_set_md_var(tc, "descr",
41331.1Skamil	    "Verify plain PT_GETFPREGS call without further steps");
41341.1Skamil}
41351.1Skamil
41361.1SkamilATF_TC_BODY(fpregs1, tc)
41371.1Skamil{
41381.1Skamil	const int exitval = 5;
41391.1Skamil	const int sigval = SIGSTOP;
41401.1Skamil	pid_t child, wpid;
41411.1Skamil#if defined(TWAIT_HAVE_STATUS)
41421.1Skamil	int status;
41431.1Skamil#endif
41441.1Skamil	struct fpreg r;
41451.1Skamil
41461.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
41471.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
41481.1Skamil	if (child == 0) {
41491.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
41501.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
41511.1Skamil
41521.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
41531.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
41541.1Skamil
41551.13Schristos		DPRINTF("Before exiting of the child process\n");
41561.1Skamil		_exit(exitval);
41571.1Skamil	}
41581.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
41591.1Skamil
41601.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41611.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41621.1Skamil
41631.1Skamil	validate_status_stopped(status, sigval);
41641.1Skamil
41651.13Schristos	DPRINTF("Call GETFPREGS for the child process\n");
41661.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &r, 0) != -1);
41671.1Skamil
41681.13Schristos	DPRINTF("Before resuming the child process where it left off and "
41691.1Skamil	    "without signal to be sent\n");
41701.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
41711.1Skamil
41721.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41731.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
41741.1Skamil
41751.1Skamil	validate_status_exited(status, exitval);
41761.1Skamil
41771.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
41781.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
41791.1Skamil}
41801.1Skamil#endif
41811.1Skamil
41821.1Skamil#if defined(HAVE_FPREGS)
41831.1SkamilATF_TC(fpregs2);
41841.1SkamilATF_TC_HEAD(fpregs2, tc)
41851.1Skamil{
41861.1Skamil	atf_tc_set_md_var(tc, "descr",
41871.1Skamil	    "Verify PT_GETFPREGS and PT_SETFPREGS calls without changing "
41881.1Skamil	    "regs");
41891.1Skamil}
41901.1Skamil
41911.1SkamilATF_TC_BODY(fpregs2, tc)
41921.1Skamil{
41931.1Skamil	const int exitval = 5;
41941.1Skamil	const int sigval = SIGSTOP;
41951.1Skamil	pid_t child, wpid;
41961.1Skamil#if defined(TWAIT_HAVE_STATUS)
41971.1Skamil	int status;
41981.1Skamil#endif
41991.1Skamil	struct fpreg r;
42001.1Skamil
42011.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
42021.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
42031.1Skamil	if (child == 0) {
42041.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
42051.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
42061.1Skamil
42071.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
42081.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
42091.1Skamil
42101.13Schristos		DPRINTF("Before exiting of the child process\n");
42111.1Skamil		_exit(exitval);
42121.1Skamil	}
42131.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
42141.1Skamil
42151.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42161.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42171.1Skamil
42181.1Skamil	validate_status_stopped(status, sigval);
42191.1Skamil
42201.13Schristos	DPRINTF("Call GETFPREGS for the child process\n");
42211.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &r, 0) != -1);
42221.1Skamil
42231.13Schristos	DPRINTF("Call SETFPREGS for the child (without changed regs)\n");
42241.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SETFPREGS, child, &r, 0) != -1);
42251.1Skamil
42261.13Schristos	DPRINTF("Before resuming the child process where it left off and "
42271.1Skamil	    "without signal to be sent\n");
42281.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
42291.1Skamil
42301.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42311.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42321.1Skamil
42331.1Skamil	validate_status_exited(status, exitval);
42341.1Skamil
42351.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42361.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
42371.1Skamil}
42381.1Skamil#endif
42391.1Skamil
42401.1Skamil#if defined(PT_STEP)
42411.1Skamilstatic void
42421.2Skamilptrace_step(int N, int setstep)
42431.1Skamil{
42441.1Skamil	const int exitval = 5;
42451.1Skamil	const int sigval = SIGSTOP;
42461.1Skamil	pid_t child, wpid;
42471.1Skamil#if defined(TWAIT_HAVE_STATUS)
42481.1Skamil	int status;
42491.1Skamil#endif
42501.1Skamil	int happy;
42511.1Skamil
42521.1Skamil#if defined(__arm__)
42531.1Skamil	/* PT_STEP not supported on arm 32-bit */
42541.1Skamil	atf_tc_expect_fail("PR kern/52119");
42551.1Skamil#endif
42561.1Skamil
42571.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
42581.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
42591.1Skamil	if (child == 0) {
42601.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
42611.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
42621.1Skamil
42631.1Skamil		happy = check_happy(999);
42641.1Skamil
42651.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
42661.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
42671.1Skamil
42681.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(999));
42691.1Skamil
42701.13Schristos		DPRINTF("Before exiting of the child process\n");
42711.1Skamil		_exit(exitval);
42721.1Skamil	}
42731.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
42741.1Skamil
42751.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42761.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
42771.1Skamil
42781.1Skamil	validate_status_stopped(status, sigval);
42791.1Skamil
42801.1Skamil	while (N --> 0) {
42811.2Skamil		if (setstep) {
42821.13Schristos			DPRINTF("Before resuming the child process where it "
42831.2Skamil			    "left off and without signal to be sent (use "
42841.9Skamil			    "PT_SETSTEP and PT_CONTINUE)\n");
42851.13Schristos			SYSCALL_REQUIRE(ptrace(PT_SETSTEP, child, 0, 0) != -1);
42861.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0)
42871.2Skamil			    != -1);
42881.2Skamil		} else {
42891.13Schristos			DPRINTF("Before resuming the child process where it "
42901.2Skamil			    "left off and without signal to be sent (use "
42911.2Skamil			    "PT_STEP)\n");
42921.13Schristos			SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0)
42931.2Skamil			    != -1);
42941.2Skamil		}
42951.1Skamil
42961.13Schristos		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
42971.1Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
42981.1Skamil		    child);
42991.1Skamil
43001.1Skamil		validate_status_stopped(status, SIGTRAP);
43011.2Skamil
43021.2Skamil		if (setstep) {
43031.13Schristos			SYSCALL_REQUIRE(ptrace(PT_CLEARSTEP, child, 0, 0) != -1);
43041.2Skamil		}
43051.1Skamil	}
43061.1Skamil
43071.13Schristos	DPRINTF("Before resuming the child process where it left off and "
43081.1Skamil	    "without signal to be sent\n");
43091.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
43101.1Skamil
43111.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43121.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
43131.1Skamil
43141.1Skamil	validate_status_exited(status, exitval);
43151.1Skamil
43161.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
43171.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
43181.1Skamil}
43191.1Skamil#endif
43201.1Skamil
43211.1Skamil#if defined(PT_STEP)
43221.1SkamilATF_TC(step1);
43231.1SkamilATF_TC_HEAD(step1, tc)
43241.1Skamil{
43251.1Skamil	atf_tc_set_md_var(tc, "descr",
43261.1Skamil	    "Verify single PT_STEP call");
43271.1Skamil}
43281.1Skamil
43291.1SkamilATF_TC_BODY(step1, tc)
43301.1Skamil{
43311.2Skamil	ptrace_step(1, 0);
43321.1Skamil}
43331.1Skamil#endif
43341.1Skamil
43351.1Skamil#if defined(PT_STEP)
43361.1SkamilATF_TC(step2);
43371.1SkamilATF_TC_HEAD(step2, tc)
43381.1Skamil{
43391.1Skamil	atf_tc_set_md_var(tc, "descr",
43401.1Skamil	    "Verify PT_STEP called twice");
43411.1Skamil}
43421.1Skamil
43431.1SkamilATF_TC_BODY(step2, tc)
43441.1Skamil{
43451.2Skamil	ptrace_step(2, 0);
43461.1Skamil}
43471.1Skamil#endif
43481.1Skamil
43491.1Skamil#if defined(PT_STEP)
43501.1SkamilATF_TC(step3);
43511.1SkamilATF_TC_HEAD(step3, tc)
43521.1Skamil{
43531.1Skamil	atf_tc_set_md_var(tc, "descr",
43541.1Skamil	    "Verify PT_STEP called three times");
43551.1Skamil}
43561.1Skamil
43571.1SkamilATF_TC_BODY(step3, tc)
43581.1Skamil{
43591.2Skamil	ptrace_step(3, 0);
43601.1Skamil}
43611.1Skamil#endif
43621.1Skamil
43631.1Skamil#if defined(PT_STEP)
43641.1SkamilATF_TC(step4);
43651.1SkamilATF_TC_HEAD(step4, tc)
43661.1Skamil{
43671.1Skamil	atf_tc_set_md_var(tc, "descr",
43681.1Skamil	    "Verify PT_STEP called four times");
43691.1Skamil}
43701.1Skamil
43711.1SkamilATF_TC_BODY(step4, tc)
43721.1Skamil{
43731.2Skamil	ptrace_step(4, 0);
43741.2Skamil}
43751.2Skamil#endif
43761.2Skamil
43771.2Skamil#if defined(PT_STEP)
43781.2SkamilATF_TC(setstep1);
43791.2SkamilATF_TC_HEAD(setstep1, tc)
43801.2Skamil{
43811.2Skamil	atf_tc_set_md_var(tc, "descr",
43821.2Skamil	    "Verify single PT_SETSTEP call");
43831.2Skamil}
43841.2Skamil
43851.2SkamilATF_TC_BODY(setstep1, tc)
43861.2Skamil{
43871.2Skamil	ptrace_step(1, 1);
43881.2Skamil}
43891.2Skamil#endif
43901.2Skamil
43911.2Skamil#if defined(PT_STEP)
43921.2SkamilATF_TC(setstep2);
43931.2SkamilATF_TC_HEAD(setstep2, tc)
43941.2Skamil{
43951.2Skamil	atf_tc_set_md_var(tc, "descr",
43961.2Skamil	    "Verify PT_SETSTEP called twice");
43971.2Skamil}
43981.2Skamil
43991.2SkamilATF_TC_BODY(setstep2, tc)
44001.2Skamil{
44011.2Skamil	ptrace_step(2, 1);
44021.2Skamil}
44031.2Skamil#endif
44041.2Skamil
44051.2Skamil#if defined(PT_STEP)
44061.2SkamilATF_TC(setstep3);
44071.2SkamilATF_TC_HEAD(setstep3, tc)
44081.2Skamil{
44091.2Skamil	atf_tc_set_md_var(tc, "descr",
44101.2Skamil	    "Verify PT_SETSTEP called three times");
44111.2Skamil}
44121.2Skamil
44131.2SkamilATF_TC_BODY(setstep3, tc)
44141.2Skamil{
44151.2Skamil	ptrace_step(3, 1);
44161.2Skamil}
44171.2Skamil#endif
44181.2Skamil
44191.2Skamil#if defined(PT_STEP)
44201.2SkamilATF_TC(setstep4);
44211.2SkamilATF_TC_HEAD(setstep4, tc)
44221.2Skamil{
44231.2Skamil	atf_tc_set_md_var(tc, "descr",
44241.2Skamil	    "Verify PT_SETSTEP called four times");
44251.2Skamil}
44261.2Skamil
44271.2SkamilATF_TC_BODY(setstep4, tc)
44281.2Skamil{
44291.2Skamil	ptrace_step(4, 1);
44301.1Skamil}
44311.1Skamil#endif
44321.1Skamil
44331.1SkamilATF_TC(kill1);
44341.1SkamilATF_TC_HEAD(kill1, tc)
44351.1Skamil{
44361.1Skamil	atf_tc_set_md_var(tc, "descr",
44371.1Skamil	    "Verify that PT_CONTINUE with SIGKILL terminates child");
44381.1Skamil}
44391.1Skamil
44401.1SkamilATF_TC_BODY(kill1, tc)
44411.1Skamil{
44421.1Skamil	const int sigval = SIGSTOP, sigsent = SIGKILL;
44431.1Skamil	pid_t child, wpid;
44441.1Skamil#if defined(TWAIT_HAVE_STATUS)
44451.1Skamil	int status;
44461.1Skamil#endif
44471.1Skamil
44481.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
44491.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
44501.1Skamil	if (child == 0) {
44511.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
44521.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
44531.1Skamil
44541.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
44551.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
44561.1Skamil
44571.1Skamil		/* NOTREACHED */
44581.1Skamil		FORKEE_ASSERTX(0 &&
44591.1Skamil		    "Child should be terminated by a signal from its parent");
44601.1Skamil	}
44611.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
44621.1Skamil
44631.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44641.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44651.1Skamil
44661.1Skamil	validate_status_stopped(status, sigval);
44671.1Skamil
44681.13Schristos	DPRINTF("Before resuming the child process where it left off and "
44691.1Skamil	    "without signal to be sent\n");
44701.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1);
44711.1Skamil
44721.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44731.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
44741.1Skamil
44751.1Skamil	validate_status_signaled(status, sigsent, 0);
44761.1Skamil
44771.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
44781.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
44791.1Skamil}
44801.1Skamil
44811.1SkamilATF_TC(kill2);
44821.1SkamilATF_TC_HEAD(kill2, tc)
44831.1Skamil{
44841.1Skamil	atf_tc_set_md_var(tc, "descr",
44851.1Skamil	    "Verify that PT_KILL terminates child");
44861.1Skamil}
44871.1Skamil
44881.1SkamilATF_TC_BODY(kill2, tc)
44891.1Skamil{
44901.1Skamil	const int sigval = SIGSTOP;
44911.1Skamil	pid_t child, wpid;
44921.1Skamil#if defined(TWAIT_HAVE_STATUS)
44931.1Skamil	int status;
44941.1Skamil#endif
44951.1Skamil
44961.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
44971.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
44981.1Skamil	if (child == 0) {
44991.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
45001.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
45011.1Skamil
45021.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
45031.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
45041.1Skamil
45051.1Skamil		/* NOTREACHED */
45061.1Skamil		FORKEE_ASSERTX(0 &&
45071.1Skamil		    "Child should be terminated by a signal from its parent");
45081.1Skamil	}
45091.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
45101.1Skamil
45111.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45121.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45131.1Skamil
45141.1Skamil	validate_status_stopped(status, sigval);
45151.1Skamil
45161.13Schristos	DPRINTF("Before resuming the child process where it left off and "
45171.1Skamil	    "without signal to be sent\n");
45181.13Schristos	SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void*)1, 0) != -1);
45191.1Skamil
45201.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45211.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45221.1Skamil
45231.1Skamil	validate_status_signaled(status, SIGKILL, 0);
45241.1Skamil
45251.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45261.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
45271.1Skamil}
45281.1Skamil
45291.1SkamilATF_TC(lwpinfo1);
45301.1SkamilATF_TC_HEAD(lwpinfo1, tc)
45311.1Skamil{
45321.1Skamil	atf_tc_set_md_var(tc, "descr",
45331.1Skamil	    "Verify basic LWPINFO call for single thread (PT_TRACE_ME)");
45341.1Skamil}
45351.1Skamil
45361.1SkamilATF_TC_BODY(lwpinfo1, tc)
45371.1Skamil{
45381.1Skamil	const int exitval = 5;
45391.1Skamil	const int sigval = SIGSTOP;
45401.1Skamil	pid_t child, wpid;
45411.1Skamil#if defined(TWAIT_HAVE_STATUS)
45421.1Skamil	int status;
45431.1Skamil#endif
45441.1Skamil	struct ptrace_lwpinfo info = {0, 0};
45451.1Skamil
45461.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
45471.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
45481.1Skamil	if (child == 0) {
45491.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
45501.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
45511.1Skamil
45521.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
45531.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
45541.1Skamil
45551.13Schristos		DPRINTF("Before exiting of the child process\n");
45561.1Skamil		_exit(exitval);
45571.1Skamil	}
45581.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
45591.1Skamil
45601.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45611.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45621.1Skamil
45631.1Skamil	validate_status_stopped(status, sigval);
45641.1Skamil
45651.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
45661.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &info, sizeof(info)) != -1);
45671.1Skamil
45681.13Schristos	DPRINTF("Assert that there exists a thread\n");
45691.1Skamil	ATF_REQUIRE(info.pl_lwpid > 0);
45701.1Skamil
45711.13Schristos	DPRINTF("Assert that lwp thread %d received event PL_EVENT_SIGNAL\n",
45721.1Skamil	    info.pl_lwpid);
45731.1Skamil	ATF_REQUIRE_EQ_MSG(info.pl_event, PL_EVENT_SIGNAL,
45741.1Skamil	    "Received event %d != expected event %d",
45751.1Skamil	    info.pl_event, PL_EVENT_SIGNAL);
45761.1Skamil
45771.13Schristos	DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
45781.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &info, sizeof(info)) != -1);
45791.1Skamil
45801.13Schristos	DPRINTF("Assert that there are no more lwp threads in child\n");
45811.1Skamil	ATF_REQUIRE_EQ(info.pl_lwpid, 0);
45821.1Skamil
45831.13Schristos	DPRINTF("Before resuming the child process where it left off and "
45841.1Skamil	    "without signal to be sent\n");
45851.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
45861.1Skamil
45871.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45881.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
45891.1Skamil
45901.1Skamil	validate_status_exited(status, exitval);
45911.1Skamil
45921.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
45931.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
45941.1Skamil}
45951.1Skamil
45961.1Skamil#if defined(TWAIT_HAVE_PID)
45971.1SkamilATF_TC(lwpinfo2);
45981.1SkamilATF_TC_HEAD(lwpinfo2, tc)
45991.1Skamil{
46001.1Skamil	atf_tc_set_md_var(tc, "descr",
46011.1Skamil	    "Verify basic LWPINFO call for single thread (PT_ATTACH from "
46021.1Skamil	    "tracer)");
46031.1Skamil}
46041.1Skamil
46051.1SkamilATF_TC_BODY(lwpinfo2, tc)
46061.1Skamil{
46071.1Skamil	struct msg_fds parent_tracee, parent_tracer;
46081.1Skamil	const int exitval_tracee = 5;
46091.1Skamil	const int exitval_tracer = 10;
46101.1Skamil	pid_t tracee, tracer, wpid;
46111.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
46121.1Skamil#if defined(TWAIT_HAVE_STATUS)
46131.1Skamil	int status;
46141.1Skamil#endif
46151.1Skamil	struct ptrace_lwpinfo info = {0, 0};
46161.1Skamil
46171.13Schristos	DPRINTF("Spawn tracee\n");
46181.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0);
46191.13Schristos	SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0);
46201.1Skamil	tracee = atf_utils_fork();
46211.1Skamil	if (tracee == 0) {
46221.1Skamil
46231.1Skamil		/* Wait for message from the parent */
46241.1Skamil		CHILD_TO_PARENT("tracee ready", parent_tracee, msg);
46251.1Skamil		CHILD_FROM_PARENT("tracee exit", parent_tracee, msg);
46261.1Skamil
46271.1Skamil		_exit(exitval_tracee);
46281.1Skamil	}
46291.1Skamil	PARENT_FROM_CHILD("tracee ready", parent_tracee, msg);
46301.1Skamil
46311.13Schristos	DPRINTF("Spawn debugger\n");
46321.1Skamil	tracer = atf_utils_fork();
46331.1Skamil	if (tracer == 0) {
46341.1Skamil		/* No IPC to communicate with the child */
46351.13Schristos		DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid());
46361.1Skamil		FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1);
46371.1Skamil
46381.1Skamil		/* Wait for tracee and assert that it was stopped w/ SIGSTOP */
46391.1Skamil		FORKEE_REQUIRE_SUCCESS(
46401.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
46411.1Skamil
46421.1Skamil		forkee_status_stopped(status, SIGSTOP);
46431.1Skamil
46441.13Schristos		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
46451.1Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &info, sizeof(info))
46461.1Skamil		    != -1);
46471.1Skamil
46481.13Schristos		DPRINTF("Assert that there exists a thread\n");
46491.1Skamil		FORKEE_ASSERTX(info.pl_lwpid > 0);
46501.1Skamil
46511.13Schristos		DPRINTF("Assert that lwp thread %d received event "
46521.1Skamil		    "PL_EVENT_SIGNAL\n", info.pl_lwpid);
46531.1Skamil		FORKEE_ASSERT_EQ(info.pl_event, PL_EVENT_SIGNAL);
46541.1Skamil
46551.13Schristos		DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n");
46561.1Skamil		FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &info, sizeof(info))
46571.1Skamil		    != -1);
46581.1Skamil
46591.13Schristos		DPRINTF("Assert that there are no more lwp threads in child\n");
46601.1Skamil		FORKEE_ASSERTX(info.pl_lwpid == 0);
46611.1Skamil
46621.1Skamil		/* Resume tracee with PT_CONTINUE */
46631.1Skamil		FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1);
46641.1Skamil
46651.1Skamil		/* Inform parent that tracer has attached to tracee */
46661.1Skamil		CHILD_TO_PARENT("tracer ready", parent_tracer, msg);
46671.1Skamil		/* Wait for parent */
46681.1Skamil		CHILD_FROM_PARENT("tracer wait", parent_tracer, msg);
46691.1Skamil
46701.1Skamil		/* Wait for tracee and assert that it exited */
46711.1Skamil		FORKEE_REQUIRE_SUCCESS(
46721.1Skamil		    wpid = TWAIT_GENERIC(tracee, &status, 0), tracee);
46731.1Skamil
46741.1Skamil		forkee_status_exited(status, exitval_tracee);
46751.1Skamil
46761.13Schristos		DPRINTF("Before exiting of the tracer process\n");
46771.1Skamil		_exit(exitval_tracer);
46781.1Skamil	}
46791.1Skamil
46801.13Schristos	DPRINTF("Wait for the tracer to attach to the tracee\n");
46811.1Skamil	PARENT_FROM_CHILD("tracer ready", parent_tracer, msg);
46821.1Skamil
46831.13Schristos	DPRINTF("Resume the tracee and let it exit\n");
46841.1Skamil	PARENT_TO_CHILD("tracee exit", parent_tracee, msg);
46851.1Skamil
46861.13Schristos	DPRINTF("Detect that tracee is zombie\n");
46871.1Skamil	await_zombie(tracee);
46881.1Skamil
46891.13Schristos	DPRINTF("Assert that there is no status about tracee - "
46901.1Skamil	    "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME);
46911.1Skamil	TWAIT_REQUIRE_SUCCESS(
46921.1Skamil	    wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0);
46931.1Skamil
46941.13Schristos	DPRINTF("Resume the tracer and let it detect exited tracee\n");
46951.1Skamil	PARENT_TO_CHILD("tracer wait", parent_tracer, msg);
46961.1Skamil
46971.13Schristos	DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n",
46981.1Skamil	    TWAIT_FNAME);
46991.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0),
47001.1Skamil	    tracer);
47011.1Skamil
47021.1Skamil	validate_status_exited(status, exitval_tracer);
47031.1Skamil
47041.13Schristos	DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n",
47051.1Skamil	    TWAIT_FNAME);
47061.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG),
47071.1Skamil	    tracee);
47081.1Skamil
47091.1Skamil	validate_status_exited(status, exitval_tracee);
47101.1Skamil
47111.1Skamil	msg_close(&parent_tracer);
47121.1Skamil	msg_close(&parent_tracee);
47131.1Skamil}
47141.1Skamil#endif
47151.1Skamil
47161.1SkamilATF_TC(siginfo1);
47171.1SkamilATF_TC_HEAD(siginfo1, tc)
47181.1Skamil{
47191.1Skamil	atf_tc_set_md_var(tc, "descr",
47201.1Skamil	    "Verify basic PT_GET_SIGINFO call for SIGTRAP from tracee");
47211.1Skamil}
47221.1Skamil
47231.1SkamilATF_TC_BODY(siginfo1, tc)
47241.1Skamil{
47251.1Skamil	const int exitval = 5;
47261.1Skamil	const int sigval = SIGTRAP;
47271.1Skamil	pid_t child, wpid;
47281.1Skamil#if defined(TWAIT_HAVE_STATUS)
47291.1Skamil	int status;
47301.1Skamil#endif
47311.1Skamil	struct ptrace_siginfo info;
47321.1Skamil	memset(&info, 0, sizeof(info));
47331.1Skamil
47341.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
47351.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
47361.1Skamil	if (child == 0) {
47371.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
47381.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
47391.1Skamil
47401.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
47411.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
47421.1Skamil
47431.13Schristos		DPRINTF("Before exiting of the child process\n");
47441.1Skamil		_exit(exitval);
47451.1Skamil	}
47461.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
47471.1Skamil
47481.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
47491.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
47501.1Skamil
47511.1Skamil	validate_status_stopped(status, sigval);
47521.1Skamil
47531.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
47541.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
47551.1Skamil
47561.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
47571.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
47581.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
47591.1Skamil	    info.psi_siginfo.si_errno);
47601.1Skamil
47611.13Schristos	DPRINTF("Before resuming the child process where it left off and "
47621.1Skamil	    "without signal to be sent\n");
47631.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
47641.1Skamil
47651.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
47661.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
47671.1Skamil
47681.1Skamil	validate_status_exited(status, exitval);
47691.1Skamil
47701.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
47711.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
47721.1Skamil}
47731.1Skamil
47741.1SkamilATF_TC(siginfo2);
47751.1SkamilATF_TC_HEAD(siginfo2, tc)
47761.1Skamil{
47771.1Skamil	atf_tc_set_md_var(tc, "descr",
47781.1Skamil	    "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls without "
47791.1Skamil	    "modification of SIGINT from tracee");
47801.1Skamil}
47811.1Skamil
47821.1Skamilstatic int siginfo2_caught = 0;
47831.1Skamil
47841.1Skamilstatic void
47851.1Skamilsiginfo2_sighandler(int sig)
47861.1Skamil{
47871.1Skamil	FORKEE_ASSERT_EQ(sig, SIGINT);
47881.1Skamil
47891.1Skamil	++siginfo2_caught;
47901.1Skamil}
47911.1Skamil
47921.1SkamilATF_TC_BODY(siginfo2, tc)
47931.1Skamil{
47941.1Skamil	const int exitval = 5;
47951.1Skamil	const int sigval = SIGINT;
47961.1Skamil	pid_t child, wpid;
47971.1Skamil	struct sigaction sa;
47981.1Skamil#if defined(TWAIT_HAVE_STATUS)
47991.1Skamil	int status;
48001.1Skamil#endif
48011.1Skamil	struct ptrace_siginfo info;
48021.1Skamil	memset(&info, 0, sizeof(info));
48031.1Skamil
48041.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
48051.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
48061.1Skamil	if (child == 0) {
48071.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
48081.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
48091.1Skamil
48101.1Skamil		sa.sa_handler = siginfo2_sighandler;
48111.1Skamil		sa.sa_flags = SA_SIGINFO;
48121.1Skamil		sigemptyset(&sa.sa_mask);
48131.1Skamil
48141.1Skamil		FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1);
48151.1Skamil
48161.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
48171.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
48181.1Skamil
48191.1Skamil		FORKEE_ASSERT_EQ(siginfo2_caught, 1);
48201.1Skamil
48211.13Schristos		DPRINTF("Before exiting of the child process\n");
48221.1Skamil		_exit(exitval);
48231.1Skamil	}
48241.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
48251.1Skamil
48261.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
48271.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48281.1Skamil
48291.1Skamil	validate_status_stopped(status, sigval);
48301.1Skamil
48311.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
48321.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
48331.1Skamil
48341.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
48351.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
48361.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
48371.1Skamil	    info.psi_siginfo.si_errno);
48381.1Skamil
48391.13Schristos	DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n");
48401.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1);
48411.1Skamil
48421.13Schristos	DPRINTF("Before resuming the child process where it left off and "
48431.1Skamil	    "without signal to be sent\n");
48441.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigval) != -1);
48451.1Skamil
48461.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
48471.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
48481.1Skamil
48491.1Skamil	validate_status_exited(status, exitval);
48501.1Skamil
48511.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
48521.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
48531.1Skamil}
48541.1Skamil
48551.1SkamilATF_TC(siginfo3);
48561.1SkamilATF_TC_HEAD(siginfo3, tc)
48571.1Skamil{
48581.1Skamil	atf_tc_set_md_var(tc, "descr",
48591.1Skamil	    "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls with "
48601.1Skamil	    "setting signal to new value");
48611.1Skamil}
48621.1Skamil
48631.1Skamilstatic int siginfo3_caught = 0;
48641.1Skamil
48651.1Skamilstatic void
48661.1Skamilsiginfo3_sigaction(int sig, siginfo_t *info, void *ctx)
48671.1Skamil{
48681.1Skamil	FORKEE_ASSERT_EQ(sig, SIGTRAP);
48691.1Skamil
48701.1Skamil	FORKEE_ASSERT_EQ(info->si_signo, SIGTRAP);
48711.1Skamil	FORKEE_ASSERT_EQ(info->si_code, TRAP_BRKPT);
48721.1Skamil
48731.1Skamil	++siginfo3_caught;
48741.1Skamil}
48751.1Skamil
48761.1SkamilATF_TC_BODY(siginfo3, tc)
48771.1Skamil{
48781.1Skamil	const int exitval = 5;
48791.1Skamil	const int sigval = SIGINT;
48801.1Skamil	const int sigfaked = SIGTRAP;
48811.1Skamil	const int sicodefaked = TRAP_BRKPT;
48821.1Skamil	pid_t child, wpid;
48831.1Skamil	struct sigaction sa;
48841.1Skamil#if defined(TWAIT_HAVE_STATUS)
48851.1Skamil	int status;
48861.1Skamil#endif
48871.1Skamil	struct ptrace_siginfo info;
48881.1Skamil	memset(&info, 0, sizeof(info));
48891.1Skamil
48901.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
48911.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
48921.1Skamil	if (child == 0) {
48931.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
48941.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
48951.1Skamil
48961.1Skamil		sa.sa_sigaction = siginfo3_sigaction;
48971.1Skamil		sa.sa_flags = SA_SIGINFO;
48981.1Skamil		sigemptyset(&sa.sa_mask);
48991.1Skamil
49001.1Skamil		FORKEE_ASSERT(sigaction(sigfaked, &sa, NULL) != -1);
49011.1Skamil
49021.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
49031.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
49041.1Skamil
49051.1Skamil		FORKEE_ASSERT_EQ(siginfo3_caught, 1);
49061.1Skamil
49071.13Schristos		DPRINTF("Before exiting of the child process\n");
49081.1Skamil		_exit(exitval);
49091.1Skamil	}
49101.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
49111.1Skamil
49121.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
49131.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49141.1Skamil
49151.1Skamil	validate_status_stopped(status, sigval);
49161.1Skamil
49171.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
49181.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
49191.1Skamil
49201.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
49211.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
49221.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
49231.1Skamil	    info.psi_siginfo.si_errno);
49241.1Skamil
49251.13Schristos	DPRINTF("Before setting new faked signal to signo=%d si_code=%d\n",
49261.1Skamil	    sigfaked, sicodefaked);
49271.1Skamil	info.psi_siginfo.si_signo = sigfaked;
49281.1Skamil	info.psi_siginfo.si_code = sicodefaked;
49291.1Skamil
49301.13Schristos	DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n");
49311.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1);
49321.1Skamil
49331.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
49341.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
49351.1Skamil
49361.13Schristos	DPRINTF("Before checking siginfo_t\n");
49371.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigfaked);
49381.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, sicodefaked);
49391.1Skamil
49401.13Schristos	DPRINTF("Before resuming the child process where it left off and "
49411.1Skamil	    "without signal to be sent\n");
49421.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigfaked) != -1);
49431.1Skamil
49441.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
49451.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49461.1Skamil
49471.1Skamil	validate_status_exited(status, exitval);
49481.1Skamil
49491.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
49501.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
49511.1Skamil}
49521.1Skamil
49531.1SkamilATF_TC(siginfo4);
49541.1SkamilATF_TC_HEAD(siginfo4, tc)
49551.1Skamil{
49561.1Skamil	atf_tc_set_md_var(tc, "descr",
49571.1Skamil	    "Detect SIGTRAP TRAP_EXEC from tracee");
49581.1Skamil}
49591.1Skamil
49601.1SkamilATF_TC_BODY(siginfo4, tc)
49611.1Skamil{
49621.1Skamil	const int sigval = SIGTRAP;
49631.1Skamil	pid_t child, wpid;
49641.1Skamil#if defined(TWAIT_HAVE_STATUS)
49651.1Skamil	int status;
49661.1Skamil#endif
49671.1Skamil
49681.1Skamil	struct ptrace_siginfo info;
49691.1Skamil	memset(&info, 0, sizeof(info));
49701.1Skamil
49711.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
49721.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
49731.1Skamil	if (child == 0) {
49741.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
49751.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
49761.1Skamil
49771.13Schristos		DPRINTF("Before calling execve(2) from child\n");
49781.1Skamil		execlp("/bin/echo", "/bin/echo", NULL);
49791.1Skamil
49801.1Skamil		FORKEE_ASSERT(0 && "Not reached");
49811.1Skamil	}
49821.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
49831.1Skamil
49841.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
49851.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
49861.1Skamil
49871.1Skamil	validate_status_stopped(status, sigval);
49881.1Skamil
49891.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
49901.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
49911.1Skamil
49921.13Schristos	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
49931.13Schristos	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
49941.1Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
49951.1Skamil	    info.psi_siginfo.si_errno);
49961.1Skamil
49971.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
49981.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
49991.1Skamil
50001.13Schristos	DPRINTF("Before resuming the child process where it left off and "
50011.1Skamil	    "without signal to be sent\n");
50021.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
50031.1Skamil
50041.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
50051.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50061.1Skamil
50071.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
50081.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
50091.1Skamil}
50101.1Skamil
50111.1Skamil#if defined(TWAIT_HAVE_PID)
50121.1SkamilATF_TC(siginfo5);
50131.1SkamilATF_TC_HEAD(siginfo5, tc)
50141.1Skamil{
50151.1Skamil	atf_tc_set_md_var(tc, "descr",
50161.1Skamil	    "Verify that fork(2) is intercepted by ptrace(2) with EVENT_MASK "
50171.1Skamil	    "set to PTRACE_FORK and reports correct signal information");
50181.1Skamil}
50191.1Skamil
50201.1SkamilATF_TC_BODY(siginfo5, tc)
50211.1Skamil{
50221.1Skamil	const int exitval = 5;
50231.1Skamil	const int exitval2 = 15;
50241.1Skamil	const int sigval = SIGSTOP;
50251.1Skamil	pid_t child, child2, wpid;
50261.1Skamil#if defined(TWAIT_HAVE_STATUS)
50271.1Skamil	int status;
50281.1Skamil#endif
50291.1Skamil	ptrace_state_t state;
50301.1Skamil	const int slen = sizeof(state);
50311.1Skamil	ptrace_event_t event;
50321.1Skamil	const int elen = sizeof(event);
50331.1Skamil	struct ptrace_siginfo info;
50341.1Skamil
50351.1Skamil	memset(&info, 0, sizeof(info));
50361.1Skamil
50371.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
50381.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
50391.1Skamil	if (child == 0) {
50401.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
50411.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
50421.1Skamil
50431.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
50441.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
50451.1Skamil
50461.1Skamil		FORKEE_ASSERT((child2 = fork()) != -1);
50471.1Skamil
50481.1Skamil		if (child2 == 0)
50491.1Skamil			_exit(exitval2);
50501.1Skamil
50511.1Skamil		FORKEE_REQUIRE_SUCCESS
50521.1Skamil		    (wpid = TWAIT_GENERIC(child2, &status, 0), child2);
50531.1Skamil
50541.1Skamil		forkee_status_exited(status, exitval2);
50551.1Skamil
50561.13Schristos		DPRINTF("Before exiting of the child process\n");
50571.1Skamil		_exit(exitval);
50581.1Skamil	}
50591.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
50601.1Skamil
50611.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
50621.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50631.1Skamil
50641.1Skamil	validate_status_stopped(status, sigval);
50651.1Skamil
50661.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
50671.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
50681.1Skamil
50691.13Schristos	DPRINTF("Before checking siginfo_t\n");
50701.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
50711.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
50721.1Skamil
50731.13Schristos	DPRINTF("Enable PTRACE_FORK in EVENT_MASK for the child %d\n", child);
50741.1Skamil	event.pe_set_event = PTRACE_FORK;
50751.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
50761.1Skamil
50771.13Schristos	DPRINTF("Before resuming the child process where it left off and "
50781.1Skamil	    "without signal to be sent\n");
50791.13Schristos        DPRINTF("We expect two SIGTRAP events, for child %d (TRAP_CHLD, "
50801.1Skamil               "pe_report_event=PTRACE_FORK, state.pe_other_pid=child2) and "
50811.1Skamil               "for child2 (TRAP_CHLD, pe_report_event=PTRACE_FORK, "
50821.1Skamil                "state.pe_other_pid=child)\n", child);
50831.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
50841.1Skamil
50851.13Schristos	DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, child);
50861.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
50871.1Skamil
50881.1Skamil	validate_status_stopped(status, SIGTRAP);
50891.1Skamil
50901.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
50911.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
50921.1Skamil
50931.13Schristos	DPRINTF("Before checking siginfo_t\n");
50941.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
50951.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_CHLD);
50961.1Skamil
50971.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
50981.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
50991.1Skamil
51001.1Skamil	child2 = state.pe_other_pid;
51011.13Schristos	DPRINTF("Reported PTRACE_FORK event with forkee %d\n", child2);
51021.1Skamil
51031.13Schristos	DPRINTF("Before calling %s() for the forkee %d of the child %d\n",
51041.1Skamil	    TWAIT_FNAME, child2, child);
51051.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
51061.1Skamil	    child2);
51071.1Skamil
51081.1Skamil	validate_status_stopped(status, SIGTRAP);
51091.1Skamil
51101.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
51111.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
51121.1Skamil
51131.13Schristos	DPRINTF("Before checking siginfo_t\n");
51141.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
51151.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_CHLD);
51161.1Skamil
51171.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
51181.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
51191.1Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
51201.1Skamil
51211.13Schristos	DPRINTF("Before resuming the forkee process where it left off and "
51221.1Skamil	    "without signal to be sent\n");
51231.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
51241.1Skamil
51251.13Schristos	DPRINTF("Before resuming the child process where it left off and "
51261.1Skamil	    "without signal to be sent\n");
51271.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
51281.1Skamil
51291.13Schristos	DPRINTF("Before calling %s() for the forkee - expected exited\n",
51301.1Skamil	    TWAIT_FNAME);
51311.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
51321.1Skamil	    child2);
51331.1Skamil
51341.1Skamil	validate_status_exited(status, exitval2);
51351.1Skamil
51361.13Schristos	DPRINTF("Before calling %s() for the forkee - expected no process\n",
51371.1Skamil	    TWAIT_FNAME);
51381.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
51391.1Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
51401.1Skamil
51411.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
51421.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
51431.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51441.1Skamil
51451.1Skamil	validate_status_stopped(status, SIGCHLD);
51461.1Skamil
51471.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
51481.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
51491.1Skamil
51501.13Schristos	DPRINTF("Before checking siginfo_t\n");
51511.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGCHLD);
51521.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, CLD_EXITED);
51531.1Skamil
51541.13Schristos	DPRINTF("Before resuming the child process where it left off and "
51551.1Skamil	    "without signal to be sent\n");
51561.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
51571.1Skamil
51581.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
51591.1Skamil	    TWAIT_FNAME);
51601.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
51611.1Skamil
51621.1Skamil	validate_status_exited(status, exitval);
51631.1Skamil
51641.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
51651.1Skamil	    TWAIT_FNAME);
51661.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
51671.1Skamil}
51681.1Skamil#endif
51691.1Skamil
51701.1Skamil#if defined(PT_STEP)
51711.1SkamilATF_TC(siginfo6);
51721.1SkamilATF_TC_HEAD(siginfo6, tc)
51731.1Skamil{
51741.1Skamil	atf_tc_set_md_var(tc, "descr",
51751.1Skamil	    "Verify single PT_STEP call with signal information check");
51761.1Skamil}
51771.1Skamil
51781.1SkamilATF_TC_BODY(siginfo6, tc)
51791.1Skamil{
51801.1Skamil	const int exitval = 5;
51811.1Skamil	const int sigval = SIGSTOP;
51821.1Skamil	pid_t child, wpid;
51831.1Skamil#if defined(TWAIT_HAVE_STATUS)
51841.1Skamil	int status;
51851.1Skamil#endif
51861.1Skamil	int happy;
51871.1Skamil	struct ptrace_siginfo info;
51881.1Skamil
51891.1Skamil#if defined(__arm__)
51901.1Skamil	/* PT_STEP not supported on arm 32-bit */
51911.1Skamil	atf_tc_expect_fail("PR kern/52119");
51921.1Skamil#endif
51931.1Skamil
51941.1Skamil	memset(&info, 0, sizeof(info));
51951.1Skamil
51961.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
51971.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
51981.1Skamil	if (child == 0) {
51991.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
52001.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
52011.1Skamil
52021.1Skamil		happy = check_happy(100);
52031.1Skamil
52041.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
52051.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
52061.1Skamil
52071.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(100));
52081.1Skamil
52091.13Schristos		DPRINTF("Before exiting of the child process\n");
52101.1Skamil		_exit(exitval);
52111.1Skamil	}
52121.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
52131.1Skamil
52141.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
52151.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52161.1Skamil
52171.1Skamil	validate_status_stopped(status, sigval);
52181.1Skamil
52191.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
52201.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
52211.1Skamil
52221.13Schristos	DPRINTF("Before checking siginfo_t\n");
52231.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
52241.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
52251.1Skamil
52261.13Schristos	DPRINTF("Before resuming the child process where it left off and "
52271.1Skamil	    "without signal to be sent (use PT_STEP)\n");
52281.13Schristos	SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0) != -1);
52291.1Skamil
52301.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
52311.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52321.1Skamil
52331.1Skamil	validate_status_stopped(status, SIGTRAP);
52341.1Skamil
52351.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
52361.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
52371.1Skamil
52381.13Schristos	DPRINTF("Before checking siginfo_t\n");
52391.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
52401.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_TRACE);
52411.1Skamil
52421.13Schristos	DPRINTF("Before resuming the child process where it left off and "
52431.1Skamil	    "without signal to be sent\n");
52441.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
52451.1Skamil
52461.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
52471.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
52481.1Skamil
52491.1Skamil	validate_status_exited(status, exitval);
52501.1Skamil
52511.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
52521.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
52531.1Skamil}
52541.1Skamil#endif
52551.1Skamil
52561.1Skamilvolatile lwpid_t the_lwp_id = 0;
52571.1Skamil
52581.1Skamilstatic void
52591.1Skamillwp_main_func(void *arg)
52601.1Skamil{
52611.1Skamil	the_lwp_id = _lwp_self();
52621.1Skamil	_lwp_exit();
52631.1Skamil}
52641.1Skamil
52651.1SkamilATF_TC(lwp_create1);
52661.1SkamilATF_TC_HEAD(lwp_create1, tc)
52671.1Skamil{
52681.1Skamil	atf_tc_set_md_var(tc, "descr",
52691.1Skamil	    "Verify that 1 LWP creation is intercepted by ptrace(2) with "
52701.1Skamil	    "EVENT_MASK set to PTRACE_LWP_CREATE");
52711.1Skamil}
52721.1Skamil
52731.1SkamilATF_TC_BODY(lwp_create1, tc)
52741.1Skamil{
52751.1Skamil	const int exitval = 5;
52761.1Skamil	const int sigval = SIGSTOP;
52771.1Skamil	pid_t child, wpid;
52781.1Skamil#if defined(TWAIT_HAVE_STATUS)
52791.1Skamil	int status;
52801.1Skamil#endif
52811.1Skamil	ptrace_state_t state;
52821.1Skamil	const int slen = sizeof(state);
52831.1Skamil	ptrace_event_t event;
52841.1Skamil	const int elen = sizeof(event);
52851.1Skamil	ucontext_t uc;
52861.1Skamil	lwpid_t lid;
52871.1Skamil	static const size_t ssize = 16*1024;
52881.1Skamil	void *stack;
52891.1Skamil
52901.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
52911.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
52921.1Skamil	if (child == 0) {
52931.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
52941.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
52951.1Skamil
52961.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
52971.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
52981.1Skamil
52991.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
53001.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
53011.1Skamil
53021.13Schristos		DPRINTF("Before making context for new lwp in child\n");
53031.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
53041.1Skamil
53051.13Schristos		DPRINTF("Before creating new in child\n");
53061.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
53071.1Skamil
53081.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
53091.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
53101.1Skamil
53111.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
53121.1Skamil		    "are the same\n", lid, the_lwp_id);
53131.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
53141.1Skamil
53151.13Schristos		DPRINTF("Before exiting of the child process\n");
53161.1Skamil		_exit(exitval);
53171.1Skamil	}
53181.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
53191.1Skamil
53201.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
53211.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
53221.1Skamil
53231.1Skamil	validate_status_stopped(status, sigval);
53241.1Skamil
53251.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
53261.1Skamil	event.pe_set_event = PTRACE_LWP_CREATE;
53271.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
53281.1Skamil
53291.13Schristos	DPRINTF("Before resuming the child process where it left off and "
53301.1Skamil	    "without signal to be sent\n");
53311.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
53321.1Skamil
53331.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
53341.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
53351.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
53361.1Skamil
53371.1Skamil	validate_status_stopped(status, SIGTRAP);
53381.1Skamil
53391.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
53401.1Skamil
53411.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE);
53421.1Skamil
53431.1Skamil	lid = state.pe_lwp;
53441.13Schristos	DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
53451.1Skamil
53461.13Schristos	DPRINTF("Before resuming the child process where it left off and "
53471.1Skamil	    "without signal to be sent\n");
53481.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
53491.1Skamil
53501.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
53511.1Skamil	    TWAIT_FNAME);
53521.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
53531.1Skamil
53541.1Skamil	validate_status_exited(status, exitval);
53551.1Skamil
53561.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
53571.1Skamil	    TWAIT_FNAME);
53581.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
53591.1Skamil}
53601.1Skamil
53611.1SkamilATF_TC(lwp_exit1);
53621.1SkamilATF_TC_HEAD(lwp_exit1, tc)
53631.1Skamil{
53641.1Skamil	atf_tc_set_md_var(tc, "descr",
53651.1Skamil	    "Verify that 1 LWP creation is intercepted by ptrace(2) with "
53661.1Skamil	    "EVENT_MASK set to PTRACE_LWP_EXIT");
53671.1Skamil}
53681.1Skamil
53691.1SkamilATF_TC_BODY(lwp_exit1, tc)
53701.1Skamil{
53711.1Skamil	const int exitval = 5;
53721.1Skamil	const int sigval = SIGSTOP;
53731.1Skamil	pid_t child, wpid;
53741.1Skamil#if defined(TWAIT_HAVE_STATUS)
53751.1Skamil	int status;
53761.1Skamil#endif
53771.1Skamil	ptrace_state_t state;
53781.1Skamil	const int slen = sizeof(state);
53791.1Skamil	ptrace_event_t event;
53801.1Skamil	const int elen = sizeof(event);
53811.1Skamil	ucontext_t uc;
53821.1Skamil	lwpid_t lid;
53831.1Skamil	static const size_t ssize = 16*1024;
53841.1Skamil	void *stack;
53851.1Skamil
53861.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
53871.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
53881.1Skamil	if (child == 0) {
53891.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
53901.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
53911.1Skamil
53921.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
53931.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
53941.1Skamil
53951.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
53961.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
53971.1Skamil
53981.13Schristos		DPRINTF("Before making context for new lwp in child\n");
53991.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
54001.1Skamil
54011.13Schristos		DPRINTF("Before creating new in child\n");
54021.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
54031.1Skamil
54041.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
54051.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
54061.1Skamil
54071.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
54081.1Skamil		    "are the same\n", lid, the_lwp_id);
54091.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
54101.1Skamil
54111.13Schristos		DPRINTF("Before exiting of the child process\n");
54121.1Skamil		_exit(exitval);
54131.1Skamil	}
54141.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
54151.1Skamil
54161.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
54171.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54181.1Skamil
54191.1Skamil	validate_status_stopped(status, sigval);
54201.1Skamil
54211.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
54221.1Skamil	event.pe_set_event = PTRACE_LWP_EXIT;
54231.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
54241.1Skamil
54251.13Schristos	DPRINTF("Before resuming the child process where it left off and "
54261.1Skamil	    "without signal to be sent\n");
54271.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
54281.1Skamil
54291.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
54301.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
54311.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54321.1Skamil
54331.1Skamil	validate_status_stopped(status, SIGTRAP);
54341.1Skamil
54351.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
54361.1Skamil
54371.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT);
54381.1Skamil
54391.1Skamil	lid = state.pe_lwp;
54401.13Schristos	DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
54411.1Skamil
54421.13Schristos	DPRINTF("Before resuming the child process where it left off and "
54431.1Skamil	    "without signal to be sent\n");
54441.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
54451.1Skamil
54461.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
54471.1Skamil	    TWAIT_FNAME);
54481.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
54491.1Skamil
54501.1Skamil	validate_status_exited(status, exitval);
54511.1Skamil
54521.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
54531.1Skamil	    TWAIT_FNAME);
54541.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
54551.1Skamil}
54561.1Skamil
54571.1SkamilATF_TC(signal1);
54581.1SkamilATF_TC_HEAD(signal1, tc)
54591.1Skamil{
54601.1Skamil	atf_tc_set_md_var(tc, "descr",
54611.1Skamil	    "Verify that masking single unrelated signal does not stop tracer "
54621.1Skamil	    "from catching other signals");
54631.1Skamil}
54641.1Skamil
54651.1SkamilATF_TC_BODY(signal1, tc)
54661.1Skamil{
54671.1Skamil	const int exitval = 5;
54681.1Skamil	const int sigval = SIGSTOP;
54691.1Skamil	const int sigmasked = SIGTRAP;
54701.1Skamil	const int signotmasked = SIGINT;
54711.1Skamil	pid_t child, wpid;
54721.1Skamil#if defined(TWAIT_HAVE_STATUS)
54731.1Skamil	int status;
54741.1Skamil#endif
54751.1Skamil	sigset_t intmask;
54761.1Skamil
54771.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
54781.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
54791.1Skamil	if (child == 0) {
54801.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
54811.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
54821.1Skamil
54831.1Skamil		sigemptyset(&intmask);
54841.1Skamil		sigaddset(&intmask, sigmasked);
54851.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
54861.1Skamil
54871.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
54881.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
54891.1Skamil
54901.13Schristos		DPRINTF("Before raising %s from child\n",
54911.1Skamil		    strsignal(signotmasked));
54921.1Skamil		FORKEE_ASSERT(raise(signotmasked) == 0);
54931.1Skamil
54941.13Schristos		DPRINTF("Before exiting of the child process\n");
54951.1Skamil		_exit(exitval);
54961.1Skamil	}
54971.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
54981.1Skamil
54991.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55001.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55011.1Skamil
55021.1Skamil	validate_status_stopped(status, sigval);
55031.1Skamil
55041.13Schristos	DPRINTF("Before resuming the child process where it left off and "
55051.1Skamil	    "without signal to be sent\n");
55061.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
55071.1Skamil
55081.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55091.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55101.1Skamil
55111.1Skamil	validate_status_stopped(status, signotmasked);
55121.1Skamil
55131.13Schristos	DPRINTF("Before resuming the child process where it left off and "
55141.1Skamil	    "without signal to be sent\n");
55151.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
55161.1Skamil
55171.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55181.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55191.1Skamil
55201.1Skamil	validate_status_exited(status, exitval);
55211.1Skamil
55221.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55231.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
55241.1Skamil}
55251.1Skamil
55261.1SkamilATF_TC(signal2);
55271.1SkamilATF_TC_HEAD(signal2, tc)
55281.1Skamil{
55291.1Skamil	atf_tc_set_md_var(tc, "descr",
55301.1Skamil	    "Verify that masking SIGTRAP in tracee stops tracer from "
55311.1Skamil	    "catching this raised signal");
55321.1Skamil}
55331.1Skamil
55341.1SkamilATF_TC_BODY(signal2, tc)
55351.1Skamil{
55361.1Skamil	const int exitval = 5;
55371.1Skamil	const int sigval = SIGSTOP;
55381.1Skamil	const int sigmasked = SIGTRAP;
55391.1Skamil	pid_t child, wpid;
55401.1Skamil#if defined(TWAIT_HAVE_STATUS)
55411.1Skamil	int status;
55421.1Skamil#endif
55431.1Skamil	sigset_t intmask;
55441.1Skamil
55451.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
55461.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
55471.1Skamil	if (child == 0) {
55481.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
55491.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
55501.1Skamil
55511.1Skamil		sigemptyset(&intmask);
55521.1Skamil		sigaddset(&intmask, sigmasked);
55531.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
55541.1Skamil
55551.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
55561.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
55571.1Skamil
55581.13Schristos		DPRINTF("Before raising %s breakpoint from child\n",
55591.1Skamil		    strsignal(sigmasked));
55601.1Skamil		FORKEE_ASSERT(raise(sigmasked) == 0);
55611.1Skamil
55621.13Schristos		DPRINTF("Before exiting of the child process\n");
55631.1Skamil		_exit(exitval);
55641.1Skamil	}
55651.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
55661.1Skamil
55671.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55681.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55691.1Skamil
55701.1Skamil	validate_status_stopped(status, sigval);
55711.1Skamil
55721.13Schristos	DPRINTF("Before resuming the child process where it left off and "
55731.1Skamil	    "without signal to be sent\n");
55741.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
55751.1Skamil
55761.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55771.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
55781.1Skamil
55791.1Skamil	validate_status_exited(status, exitval);
55801.1Skamil
55811.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
55821.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
55831.1Skamil}
55841.1Skamil
55851.1SkamilATF_TC(signal3);
55861.1SkamilATF_TC_HEAD(signal3, tc)
55871.1Skamil{
55881.7Skamil	atf_tc_set_md_var(tc, "timeout", "5");
55891.1Skamil	atf_tc_set_md_var(tc, "descr",
55901.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
55911.1Skamil	    "catching software breakpoints");
55921.1Skamil}
55931.1Skamil
55941.1SkamilATF_TC_BODY(signal3, tc)
55951.1Skamil{
55961.1Skamil	const int exitval = 5;
55971.1Skamil	const int sigval = SIGSTOP;
55981.1Skamil	const int sigmasked = SIGTRAP;
55991.1Skamil	pid_t child, wpid;
56001.1Skamil#if defined(TWAIT_HAVE_STATUS)
56011.1Skamil	int status;
56021.1Skamil#endif
56031.1Skamil	sigset_t intmask;
56041.1Skamil
56051.20Skamil	atf_tc_expect_fail("PR kern/51918");
56061.20Skamil
56071.20Skamil	// This test breaks now on some ports, temporarily disable it
56081.20Skamil	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
56091.20Skamil
56101.10Smartin#if defined(__sparc__)
56111.7Skamil	atf_tc_expect_timeout("PR kern/52167");
56121.7Skamil
56131.7Skamil	// timeout wins, failure still valid
56141.7Skamil	// atf_tc_expect_fail("PR kern/51918");
56151.7Skamil#endif
56161.1Skamil
56171.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
56181.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
56191.1Skamil	if (child == 0) {
56201.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
56211.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
56221.1Skamil
56231.1Skamil		sigemptyset(&intmask);
56241.1Skamil		sigaddset(&intmask, sigmasked);
56251.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
56261.1Skamil
56271.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
56281.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
56291.1Skamil
56301.13Schristos		DPRINTF("Before raising software breakpoint from child\n");
56311.4Skamil
56321.4Skamil#ifdef PTRACE_BREAKPOINT_ASM
56331.4Skamil		PTRACE_BREAKPOINT_ASM;
56341.1Skamil#else
56351.4Skamil		/* port me */
56361.1Skamil#endif
56371.1Skamil
56381.13Schristos		DPRINTF("Before exiting of the child process\n");
56391.1Skamil		_exit(exitval);
56401.1Skamil	}
56411.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
56421.1Skamil
56431.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56441.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56451.1Skamil
56461.1Skamil	validate_status_stopped(status, sigval);
56471.1Skamil
56481.13Schristos	DPRINTF("Before resuming the child process where it left off and "
56491.1Skamil	    "without signal to be sent\n");
56501.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
56511.1Skamil
56521.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56531.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56541.1Skamil
56551.1Skamil	validate_status_stopped(status, sigmasked);
56561.1Skamil
56571.13Schristos	DPRINTF("Before resuming the child process where it left off and "
56581.1Skamil	    "without signal to be sent\n");
56591.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
56601.1Skamil
56611.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56621.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
56631.1Skamil
56641.1Skamil	validate_status_exited(status, exitval);
56651.1Skamil
56661.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
56671.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
56681.1Skamil}
56691.1Skamil
56701.1Skamil#if defined(PT_STEP)
56711.1SkamilATF_TC(signal4);
56721.1SkamilATF_TC_HEAD(signal4, tc)
56731.1Skamil{
56741.1Skamil	atf_tc_set_md_var(tc, "descr",
56751.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
56761.1Skamil	    "catching single step trap");
56771.1Skamil}
56781.1Skamil
56791.1SkamilATF_TC_BODY(signal4, tc)
56801.1Skamil{
56811.1Skamil	const int exitval = 5;
56821.1Skamil	const int sigval = SIGSTOP;
56831.1Skamil	const int sigmasked = SIGTRAP;
56841.1Skamil	pid_t child, wpid;
56851.1Skamil#if defined(TWAIT_HAVE_STATUS)
56861.1Skamil	int status;
56871.1Skamil#endif
56881.1Skamil	sigset_t intmask;
56891.1Skamil	int happy;
56901.1Skamil
56911.1Skamil#if defined(__arm__)
56921.5Skamil	/* PT_STEP not supported on arm 32-bit */
56931.5Skamil	atf_tc_expect_fail("PR kern/51918 PR kern/52119");
56941.1Skamil#endif
56951.1Skamil
56961.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
56971.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
56981.1Skamil	if (child == 0) {
56991.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
57001.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
57011.1Skamil
57021.1Skamil		happy = check_happy(100);
57031.1Skamil
57041.1Skamil		sigemptyset(&intmask);
57051.1Skamil		sigaddset(&intmask, sigmasked);
57061.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
57071.1Skamil
57081.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
57091.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
57101.1Skamil
57111.1Skamil		FORKEE_ASSERT_EQ(happy, check_happy(100));
57121.1Skamil
57131.13Schristos		DPRINTF("Before exiting of the child process\n");
57141.1Skamil		_exit(exitval);
57151.1Skamil	}
57161.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
57171.1Skamil
57181.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57191.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57201.1Skamil
57211.1Skamil	validate_status_stopped(status, sigval);
57221.1Skamil
57231.13Schristos	DPRINTF("Before resuming the child process where it left off and "
57241.1Skamil	    "without signal to be sent\n");
57251.13Schristos	SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0) != -1);
57261.1Skamil
57271.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57281.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57291.1Skamil
57301.1Skamil	validate_status_stopped(status, sigmasked);
57311.1Skamil
57321.13Schristos	DPRINTF("Before resuming the child process where it left off and "
57331.1Skamil	    "without signal to be sent\n");
57341.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
57351.1Skamil
57361.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57371.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57381.1Skamil
57391.1Skamil	validate_status_exited(status, exitval);
57401.1Skamil
57411.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57421.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
57431.1Skamil}
57441.1Skamil#endif
57451.1Skamil
57461.1SkamilATF_TC(signal5);
57471.1SkamilATF_TC_HEAD(signal5, tc)
57481.1Skamil{
57491.1Skamil	atf_tc_set_md_var(tc, "descr",
57501.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
57511.1Skamil	    "catching exec() breakpoint");
57521.1Skamil}
57531.1Skamil
57541.1SkamilATF_TC_BODY(signal5, tc)
57551.1Skamil{
57561.1Skamil	const int exitval = 5;
57571.1Skamil	const int sigval = SIGSTOP;
57581.1Skamil	const int sigmasked = SIGTRAP;
57591.1Skamil	pid_t child, wpid;
57601.1Skamil#if defined(TWAIT_HAVE_STATUS)
57611.1Skamil	int status;
57621.1Skamil#endif
57631.1Skamil	sigset_t intmask;
57641.1Skamil
57651.14Schristos	atf_tc_expect_fail("wrong signal");
57661.14Schristos
57671.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
57681.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
57691.1Skamil	if (child == 0) {
57701.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
57711.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
57721.1Skamil
57731.1Skamil		sigemptyset(&intmask);
57741.1Skamil		sigaddset(&intmask, sigmasked);
57751.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
57761.1Skamil
57771.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
57781.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
57791.1Skamil
57801.13Schristos		DPRINTF("Before calling execve(2) from child\n");
57811.1Skamil		execlp("/bin/echo", "/bin/echo", NULL);
57821.1Skamil
57831.13Schristos		DPRINTF("Before exiting of the child process\n");
57841.1Skamil		_exit(exitval);
57851.1Skamil	}
57861.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
57871.1Skamil
57881.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57891.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57901.1Skamil
57911.1Skamil	validate_status_stopped(status, sigval);
57921.1Skamil
57931.13Schristos	DPRINTF("Before resuming the child process where it left off and "
57941.1Skamil	    "without signal to be sent\n");
57951.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
57961.1Skamil
57971.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
57981.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
57991.1Skamil
58001.1Skamil	validate_status_stopped(status, sigmasked);
58011.1Skamil
58021.13Schristos	DPRINTF("Before resuming the child process where it left off and "
58031.1Skamil	    "without signal to be sent\n");
58041.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
58051.1Skamil
58061.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
58071.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
58081.1Skamil
58091.1Skamil	validate_status_exited(status, exitval);
58101.1Skamil
58111.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
58121.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
58131.1Skamil}
58141.1Skamil
58151.1Skamil#if defined(TWAIT_HAVE_PID)
58161.1SkamilATF_TC(signal6);
58171.1SkamilATF_TC_HEAD(signal6, tc)
58181.1Skamil{
58191.1Skamil	atf_tc_set_md_var(tc, "timeout", "5");
58201.1Skamil	atf_tc_set_md_var(tc, "descr",
58211.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
58221.1Skamil	    "catching PTRACE_FORK breakpoint");
58231.1Skamil}
58241.1Skamil
58251.1SkamilATF_TC_BODY(signal6, tc)
58261.1Skamil{
58271.1Skamil	const int exitval = 5;
58281.1Skamil	const int exitval2 = 15;
58291.1Skamil	const int sigval = SIGSTOP;
58301.1Skamil	const int sigmasked = SIGTRAP;
58311.1Skamil	pid_t child, child2, wpid;
58321.1Skamil#if defined(TWAIT_HAVE_STATUS)
58331.1Skamil	int status;
58341.1Skamil#endif
58351.1Skamil	sigset_t intmask;
58361.1Skamil	ptrace_state_t state;
58371.1Skamil	const int slen = sizeof(state);
58381.1Skamil	ptrace_event_t event;
58391.1Skamil	const int elen = sizeof(event);
58401.1Skamil
58411.38Skamil	atf_tc_expect_fail("PR kern/51918");
58421.14Schristos
58431.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
58441.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
58451.1Skamil	if (child == 0) {
58461.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
58471.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
58481.1Skamil
58491.1Skamil		sigemptyset(&intmask);
58501.1Skamil		sigaddset(&intmask, sigmasked);
58511.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
58521.1Skamil
58531.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
58541.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
58551.1Skamil
58561.1Skamil		FORKEE_ASSERT((child2 = fork()) != -1);
58571.1Skamil
58581.1Skamil		if (child2 == 0)
58591.1Skamil			_exit(exitval2);
58601.1Skamil
58611.1Skamil		FORKEE_REQUIRE_SUCCESS
58621.1Skamil			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
58631.1Skamil
58641.1Skamil		forkee_status_exited(status, exitval2);
58651.1Skamil
58661.13Schristos		DPRINTF("Before exiting of the child process\n");
58671.1Skamil		_exit(exitval);
58681.1Skamil	}
58691.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
58701.1Skamil
58711.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
58721.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
58731.1Skamil
58741.1Skamil	validate_status_stopped(status, sigval);
58751.1Skamil
58761.13Schristos	DPRINTF("Enable PTRACE_FORK in EVENT_MASK for the child %d\n", child);
58771.1Skamil	event.pe_set_event = PTRACE_FORK;
58781.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
58791.1Skamil
58801.13Schristos	DPRINTF("Before resuming the child process where it left off and "
58811.1Skamil	    "without signal to be sent\n");
58821.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
58831.1Skamil
58841.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
58851.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
58861.1Skamil
58871.1Skamil	validate_status_stopped(status, sigmasked);
58881.1Skamil
58891.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
58901.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
58911.1Skamil
58921.1Skamil	child2 = state.pe_other_pid;
58931.13Schristos	DPRINTF("Reported PTRACE_FORK event with forkee %d\n", child2);
58941.1Skamil
58951.13Schristos	DPRINTF("Before calling %s() for the child2\n", TWAIT_FNAME);
58961.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
58971.1Skamil	    child2);
58981.1Skamil
58991.1Skamil	validate_status_stopped(status, SIGTRAP);
59001.1Skamil
59011.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
59021.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK);
59031.1Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
59041.1Skamil
59051.13Schristos	DPRINTF("Before resuming the forkee process where it left off and "
59061.1Skamil	    "without signal to be sent\n");
59071.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
59081.1Skamil
59091.13Schristos	DPRINTF("Before resuming the child process where it left off and "
59101.1Skamil	    "without signal to be sent\n");
59111.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
59121.1Skamil
59131.13Schristos	DPRINTF("Before calling %s() for the forkee - expected exited\n",
59141.1Skamil	    TWAIT_FNAME);
59151.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
59161.1Skamil	    child2);
59171.1Skamil
59181.1Skamil	validate_status_exited(status, exitval2);
59191.1Skamil
59201.13Schristos	DPRINTF("Before calling %s() for the forkee - expected no process\n",
59211.1Skamil	    TWAIT_FNAME);
59221.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
59231.1Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
59241.1Skamil
59251.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
59261.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
59271.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
59281.1Skamil
59291.1Skamil	validate_status_stopped(status, SIGCHLD);
59301.1Skamil
59311.13Schristos	DPRINTF("Before resuming the child process where it left off and "
59321.1Skamil	    "without signal to be sent\n");
59331.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
59341.1Skamil
59351.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
59361.1Skamil	    TWAIT_FNAME);
59371.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
59381.1Skamil
59391.1Skamil	validate_status_exited(status, exitval);
59401.1Skamil
59411.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
59421.1Skamil	    TWAIT_FNAME);
59431.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
59441.1Skamil}
59451.1Skamil#endif
59461.1Skamil
59471.1Skamil#if defined(TWAIT_HAVE_PID)
59481.1SkamilATF_TC(signal7);
59491.1SkamilATF_TC_HEAD(signal7, tc)
59501.1Skamil{
59511.1Skamil	atf_tc_set_md_var(tc, "descr",
59521.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
59531.1Skamil	    "catching PTRACE_VFORK breakpoint");
59541.1Skamil}
59551.1Skamil
59561.1SkamilATF_TC_BODY(signal7, tc)
59571.1Skamil{
59581.1Skamil	const int exitval = 5;
59591.1Skamil	const int exitval2 = 15;
59601.1Skamil	const int sigval = SIGSTOP;
59611.1Skamil	const int sigmasked = SIGTRAP;
59621.1Skamil	pid_t child, child2, wpid;
59631.1Skamil#if defined(TWAIT_HAVE_STATUS)
59641.1Skamil	int status;
59651.1Skamil#endif
59661.1Skamil	sigset_t intmask;
59671.1Skamil	ptrace_state_t state;
59681.1Skamil	const int slen = sizeof(state);
59691.1Skamil	ptrace_event_t event;
59701.1Skamil	const int elen = sizeof(event);
59711.1Skamil
59721.38Skamil	atf_tc_expect_fail("PR kern/51918");
59731.14Schristos
59741.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
59751.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
59761.1Skamil	if (child == 0) {
59771.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
59781.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
59791.1Skamil
59801.1Skamil		sigemptyset(&intmask);
59811.1Skamil		sigaddset(&intmask, sigmasked);
59821.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
59831.1Skamil
59841.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
59851.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
59861.1Skamil
59871.1Skamil		FORKEE_ASSERT((child2 = fork()) != -1);
59881.1Skamil
59891.1Skamil		if (child2 == 0)
59901.1Skamil			_exit(exitval2);
59911.1Skamil
59921.1Skamil		FORKEE_REQUIRE_SUCCESS
59931.1Skamil			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
59941.1Skamil
59951.1Skamil		forkee_status_exited(status, exitval2);
59961.1Skamil
59971.13Schristos		DPRINTF("Before exiting of the child process\n");
59981.1Skamil		_exit(exitval);
59991.1Skamil	}
60001.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
60011.1Skamil
60021.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
60031.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
60041.1Skamil
60051.1Skamil	validate_status_stopped(status, sigval);
60061.1Skamil
60071.13Schristos	DPRINTF("Enable PTRACE_VFORK in EVENT_MASK for the child %d\n", child);
60081.1Skamil	event.pe_set_event = PTRACE_VFORK;
60091.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1 || errno == ENOTSUP);
60101.1Skamil
60111.13Schristos	DPRINTF("Before resuming the child process where it left off and "
60121.1Skamil	    "without signal to be sent\n");
60131.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
60141.1Skamil
60151.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
60161.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
60171.1Skamil
60181.1Skamil	validate_status_stopped(status, sigmasked);
60191.1Skamil
60201.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
60211.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK);
60221.1Skamil
60231.1Skamil	child2 = state.pe_other_pid;
60241.13Schristos	DPRINTF("Reported PTRACE_VFORK event with forkee %d\n", child2);
60251.1Skamil
60261.13Schristos	DPRINTF("Before calling %s() for the child2\n", TWAIT_FNAME);
60271.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
60281.1Skamil	    child2);
60291.1Skamil
60301.1Skamil	validate_status_stopped(status, SIGTRAP);
60311.1Skamil
60321.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
60331.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK);
60341.1Skamil	ATF_REQUIRE_EQ(state.pe_other_pid, child);
60351.1Skamil
60361.13Schristos	DPRINTF("Before resuming the forkee process where it left off and "
60371.1Skamil	    "without signal to be sent\n");
60381.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
60391.1Skamil
60401.13Schristos	DPRINTF("Before resuming the child process where it left off and "
60411.1Skamil	    "without signal to be sent\n");
60421.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
60431.1Skamil
60441.13Schristos	DPRINTF("Before calling %s() for the forkee - expected exited\n",
60451.1Skamil	    TWAIT_FNAME);
60461.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
60471.1Skamil	    child2);
60481.1Skamil
60491.1Skamil	validate_status_exited(status, exitval2);
60501.1Skamil
60511.13Schristos	DPRINTF("Before calling %s() for the forkee - expected no process\n",
60521.1Skamil	    TWAIT_FNAME);
60531.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD,
60541.1Skamil	    wpid = TWAIT_GENERIC(child2, &status, 0));
60551.1Skamil
60561.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
60571.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
60581.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
60591.1Skamil
60601.1Skamil	validate_status_stopped(status, SIGCHLD);
60611.1Skamil
60621.13Schristos	DPRINTF("Before resuming the child process where it left off and "
60631.1Skamil	    "without signal to be sent\n");
60641.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
60651.1Skamil
60661.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
60671.1Skamil	    TWAIT_FNAME);
60681.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
60691.1Skamil
60701.1Skamil	validate_status_exited(status, exitval);
60711.1Skamil
60721.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
60731.1Skamil	    TWAIT_FNAME);
60741.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
60751.1Skamil}
60761.1Skamil#endif
60771.1Skamil
60781.1SkamilATF_TC(signal8);
60791.1SkamilATF_TC_HEAD(signal8, tc)
60801.1Skamil{
60811.1Skamil	atf_tc_set_md_var(tc, "descr",
60821.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
60831.1Skamil	    "catching PTRACE_VFORK_DONE breakpoint");
60841.1Skamil}
60851.1Skamil
60861.1SkamilATF_TC_BODY(signal8, tc)
60871.1Skamil{
60881.1Skamil	const int exitval = 5;
60891.1Skamil	const int exitval2 = 15;
60901.1Skamil	const int sigval = SIGSTOP;
60911.1Skamil	const int sigmasked = SIGTRAP;
60921.1Skamil	pid_t child, child2, wpid;
60931.1Skamil#if defined(TWAIT_HAVE_STATUS)
60941.1Skamil	int status;
60951.1Skamil#endif
60961.1Skamil	sigset_t intmask;
60971.1Skamil	ptrace_state_t state;
60981.1Skamil	const int slen = sizeof(state);
60991.1Skamil	ptrace_event_t event;
61001.1Skamil	const int elen = sizeof(event);
61011.1Skamil
61021.14Schristos	atf_tc_expect_fail("PR kern/51918");
61031.14Schristos
61041.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
61051.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
61061.1Skamil	if (child == 0) {
61071.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
61081.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
61091.1Skamil
61101.1Skamil		sigemptyset(&intmask);
61111.1Skamil		sigaddset(&intmask, sigmasked);
61121.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
61131.1Skamil
61141.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
61151.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
61161.1Skamil
61171.1Skamil		FORKEE_ASSERT((child2 = vfork()) != -1);
61181.1Skamil
61191.1Skamil		if (child2 == 0)
61201.1Skamil			_exit(exitval2);
61211.1Skamil
61221.1Skamil		FORKEE_REQUIRE_SUCCESS
61231.1Skamil			(wpid = TWAIT_GENERIC(child2, &status, 0), child2);
61241.1Skamil
61251.1Skamil		forkee_status_exited(status, exitval2);
61261.1Skamil
61271.13Schristos		DPRINTF("Before exiting of the child process\n");
61281.1Skamil		_exit(exitval);
61291.1Skamil	}
61301.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
61311.1Skamil
61321.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
61331.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
61341.1Skamil
61351.1Skamil	validate_status_stopped(status, sigval);
61361.1Skamil
61371.13Schristos	DPRINTF("Enable PTRACE_VFORK_DONE in EVENT_MASK for the child %d\n",
61381.1Skamil	    child);
61391.1Skamil	event.pe_set_event = PTRACE_VFORK_DONE;
61401.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
61411.1Skamil
61421.13Schristos	DPRINTF("Before resuming the child process where it left off and "
61431.1Skamil	    "without signal to be sent\n");
61441.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
61451.1Skamil
61461.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
61471.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
61481.1Skamil
61491.1Skamil	validate_status_stopped(status, sigmasked);
61501.1Skamil
61511.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
61521.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
61531.1Skamil
61541.1Skamil	child2 = state.pe_other_pid;
61551.13Schristos	DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", child2);
61561.1Skamil
61571.13Schristos	DPRINTF("Before resuming the child process where it left off and "
61581.1Skamil	    "without signal to be sent\n");
61591.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
61601.1Skamil
61611.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
61621.1Skamil	    "SIGCHLD\n", TWAIT_FNAME);
61631.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
61641.1Skamil
61651.1Skamil	validate_status_stopped(status, SIGCHLD);
61661.1Skamil
61671.13Schristos	DPRINTF("Before resuming the child process where it left off and "
61681.1Skamil	    "without signal to be sent\n");
61691.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
61701.1Skamil
61711.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
61721.1Skamil	    TWAIT_FNAME);
61731.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
61741.1Skamil
61751.1Skamil	validate_status_exited(status, exitval);
61761.1Skamil
61771.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
61781.1Skamil	    TWAIT_FNAME);
61791.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
61801.1Skamil}
61811.1Skamil
61821.1SkamilATF_TC(signal9);
61831.1SkamilATF_TC_HEAD(signal9, tc)
61841.1Skamil{
61851.1Skamil	atf_tc_set_md_var(tc, "descr",
61861.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
61871.1Skamil	    "catching PTRACE_LWP_CREATE breakpoint");
61881.1Skamil}
61891.1Skamil
61901.1SkamilATF_TC_BODY(signal9, tc)
61911.1Skamil{
61921.1Skamil	const int exitval = 5;
61931.1Skamil	const int sigval = SIGSTOP;
61941.1Skamil	const int sigmasked = SIGTRAP;
61951.1Skamil	pid_t child, wpid;
61961.1Skamil#if defined(TWAIT_HAVE_STATUS)
61971.1Skamil	int status;
61981.1Skamil#endif
61991.1Skamil	sigset_t intmask;
62001.1Skamil	ptrace_state_t state;
62011.1Skamil	const int slen = sizeof(state);
62021.1Skamil	ptrace_event_t event;
62031.1Skamil	const int elen = sizeof(event);
62041.1Skamil	ucontext_t uc;
62051.1Skamil	lwpid_t lid;
62061.1Skamil	static const size_t ssize = 16*1024;
62071.1Skamil	void *stack;
62081.1Skamil
62091.14Schristos	atf_tc_expect_fail("PR kern/51918");
62101.14Schristos
62111.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
62121.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
62131.1Skamil	if (child == 0) {
62141.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
62151.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
62161.1Skamil
62171.1Skamil		sigemptyset(&intmask);
62181.1Skamil		sigaddset(&intmask, sigmasked);
62191.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
62201.1Skamil
62211.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
62221.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
62231.1Skamil
62241.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
62251.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
62261.1Skamil
62271.13Schristos		DPRINTF("Before making context for new lwp in child\n");
62281.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
62291.1Skamil
62301.13Schristos		DPRINTF("Before creating new in child\n");
62311.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
62321.1Skamil
62331.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
62341.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
62351.1Skamil
62361.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
62371.1Skamil		    "are the same\n", lid, the_lwp_id);
62381.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
62391.1Skamil
62401.13Schristos		DPRINTF("Before exiting of the child process\n");
62411.1Skamil		_exit(exitval);
62421.1Skamil	}
62431.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
62441.1Skamil
62451.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
62461.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
62471.1Skamil
62481.1Skamil	validate_status_stopped(status, sigval);
62491.1Skamil
62501.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
62511.1Skamil	event.pe_set_event = PTRACE_LWP_CREATE;
62521.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
62531.1Skamil
62541.13Schristos	DPRINTF("Before resuming the child process where it left off and "
62551.1Skamil	    "without signal to be sent\n");
62561.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
62571.1Skamil
62581.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
62591.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
62601.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
62611.1Skamil
62621.1Skamil	validate_status_stopped(status, sigmasked);
62631.1Skamil
62641.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
62651.1Skamil
62661.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE);
62671.1Skamil
62681.1Skamil	lid = state.pe_lwp;
62691.13Schristos	DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
62701.1Skamil
62711.13Schristos	DPRINTF("Before resuming the child process where it left off and "
62721.1Skamil	    "without signal to be sent\n");
62731.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
62741.1Skamil
62751.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
62761.1Skamil	    TWAIT_FNAME);
62771.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
62781.1Skamil
62791.1Skamil	validate_status_exited(status, exitval);
62801.1Skamil
62811.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
62821.1Skamil	    TWAIT_FNAME);
62831.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
62841.1Skamil}
62851.1Skamil
62861.1SkamilATF_TC(signal10);
62871.1SkamilATF_TC_HEAD(signal10, tc)
62881.1Skamil{
62891.1Skamil	atf_tc_set_md_var(tc, "descr",
62901.1Skamil	    "Verify that masking SIGTRAP in tracee does not stop tracer from "
62911.1Skamil	    "catching PTRACE_LWP_EXIT breakpoint");
62921.1Skamil}
62931.1Skamil
62941.1SkamilATF_TC_BODY(signal10, tc)
62951.1Skamil{
62961.1Skamil	const int exitval = 5;
62971.1Skamil	const int sigval = SIGSTOP;
62981.1Skamil	const int sigmasked = SIGTRAP;
62991.1Skamil	pid_t child, wpid;
63001.1Skamil#if defined(TWAIT_HAVE_STATUS)
63011.1Skamil	int status;
63021.1Skamil#endif
63031.1Skamil	sigset_t intmask;
63041.1Skamil	ptrace_state_t state;
63051.1Skamil	const int slen = sizeof(state);
63061.1Skamil	ptrace_event_t event;
63071.1Skamil	const int elen = sizeof(event);
63081.1Skamil	ucontext_t uc;
63091.1Skamil	lwpid_t lid;
63101.1Skamil	static const size_t ssize = 16*1024;
63111.1Skamil	void *stack;
63121.1Skamil
63131.14Schristos	atf_tc_expect_fail("PR kern/51918");
63141.14Schristos
63151.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
63161.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
63171.1Skamil	if (child == 0) {
63181.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
63191.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
63201.1Skamil
63211.1Skamil		sigemptyset(&intmask);
63221.1Skamil		sigaddset(&intmask, sigmasked);
63231.1Skamil		sigprocmask(SIG_BLOCK, &intmask, NULL);
63241.1Skamil
63251.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
63261.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
63271.1Skamil
63281.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
63291.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
63301.1Skamil
63311.13Schristos		DPRINTF("Before making context for new lwp in child\n");
63321.1Skamil		_lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
63331.1Skamil
63341.13Schristos		DPRINTF("Before creating new in child\n");
63351.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
63361.1Skamil
63371.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
63381.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
63391.1Skamil
63401.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
63411.1Skamil		    "are the same\n", lid, the_lwp_id);
63421.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
63431.1Skamil
63441.13Schristos		DPRINTF("Before exiting of the child process\n");
63451.1Skamil		_exit(exitval);
63461.1Skamil	}
63471.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
63481.1Skamil
63491.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
63501.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
63511.1Skamil
63521.1Skamil	validate_status_stopped(status, sigval);
63531.1Skamil
63541.13Schristos	DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
63551.1Skamil	event.pe_set_event = PTRACE_LWP_EXIT;
63561.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
63571.1Skamil
63581.13Schristos	DPRINTF("Before resuming the child process where it left off and "
63591.1Skamil	    "without signal to be sent\n");
63601.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
63611.1Skamil
63621.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
63631.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
63641.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
63651.1Skamil
63661.1Skamil	validate_status_stopped(status, sigmasked);
63671.1Skamil
63681.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
63691.1Skamil
63701.1Skamil	ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT);
63711.1Skamil
63721.1Skamil	lid = state.pe_lwp;
63731.13Schristos	DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
63741.1Skamil
63751.13Schristos	DPRINTF("Before resuming the child process where it left off and "
63761.1Skamil	    "without signal to be sent\n");
63771.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
63781.1Skamil
63791.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
63801.1Skamil	    TWAIT_FNAME);
63811.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
63821.1Skamil
63831.1Skamil	validate_status_exited(status, exitval);
63841.1Skamil
63851.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
63861.1Skamil	    TWAIT_FNAME);
63871.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
63881.1Skamil}
63891.1Skamil
63901.1Skamilstatic void
63911.1Skamillwp_main_stop(void *arg)
63921.1Skamil{
63931.1Skamil	the_lwp_id = _lwp_self();
63941.1Skamil
63951.1Skamil	raise(SIGTRAP);
63961.1Skamil
63971.1Skamil	_lwp_exit();
63981.1Skamil}
63991.1Skamil
64001.1SkamilATF_TC(suspend1);
64011.1SkamilATF_TC_HEAD(suspend1, tc)
64021.1Skamil{
64031.1Skamil	atf_tc_set_md_var(tc, "descr",
64041.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
64051.1Skamil	    "resumed by a tracee");
64061.1Skamil}
64071.1Skamil
64081.1SkamilATF_TC_BODY(suspend1, tc)
64091.1Skamil{
64101.1Skamil	const int exitval = 5;
64111.1Skamil	const int sigval = SIGSTOP;
64121.1Skamil	pid_t child, wpid;
64131.1Skamil#if defined(TWAIT_HAVE_STATUS)
64141.1Skamil	int status;
64151.1Skamil#endif
64161.1Skamil	ucontext_t uc;
64171.1Skamil	lwpid_t lid;
64181.1Skamil	static const size_t ssize = 16*1024;
64191.1Skamil	void *stack;
64201.1Skamil	struct ptrace_lwpinfo pl;
64211.1Skamil	struct ptrace_siginfo psi;
64221.1Skamil	volatile int go = 0;
64231.1Skamil
64241.17Skamil	// Feature pending for refactoring
64251.17Skamil	atf_tc_expect_fail("PR kern/51995");
64261.17Skamil
64271.16Skamil	// Hangs with qemu
64281.16Skamil	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
64291.16Skamil
64301.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
64311.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
64321.1Skamil	if (child == 0) {
64331.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
64341.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
64351.1Skamil
64361.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
64371.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
64381.1Skamil
64391.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
64401.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
64411.1Skamil
64421.13Schristos		DPRINTF("Before making context for new lwp in child\n");
64431.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
64441.1Skamil
64451.13Schristos		DPRINTF("Before creating new in child\n");
64461.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
64471.1Skamil
64481.1Skamil		while (go == 0)
64491.1Skamil			continue;
64501.1Skamil
64511.1Skamil		raise(SIGINT);
64521.1Skamil
64531.1Skamil		FORKEE_ASSERT(_lwp_continue(lid) == 0);
64541.1Skamil
64551.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
64561.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
64571.1Skamil
64581.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
64591.1Skamil		    "are the same\n", lid, the_lwp_id);
64601.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
64611.1Skamil
64621.13Schristos		DPRINTF("Before exiting of the child process\n");
64631.1Skamil		_exit(exitval);
64641.1Skamil	}
64651.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
64661.1Skamil
64671.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
64681.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
64691.1Skamil
64701.1Skamil	validate_status_stopped(status, sigval);
64711.1Skamil
64721.13Schristos	DPRINTF("Before resuming the child process where it left off and "
64731.1Skamil	    "without signal to be sent\n");
64741.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
64751.1Skamil
64761.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
64771.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
64781.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
64791.1Skamil
64801.1Skamil	validate_status_stopped(status, SIGTRAP);
64811.1Skamil
64821.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
64831.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
64841.1Skamil
64851.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
64861.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
64871.1Skamil
64881.13Schristos        DPRINTF("Write new go to tracee (PID=%d) from tracer (PID=%d)\n",
64891.1Skamil	    child, getpid());
64901.13Schristos	SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, __UNVOLATILE(&go), 1) != -1);
64911.1Skamil
64921.13Schristos	DPRINTF("Before resuming the child process where it left off and "
64931.1Skamil	    "without signal to be sent\n");
64941.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
64951.1Skamil
64961.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
64971.1Skamil	    "SIGINT\n", TWAIT_FNAME);
64981.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
64991.1Skamil
65001.1Skamil	validate_status_stopped(status, SIGINT);
65011.1Skamil
65021.1Skamil	pl.pl_lwpid = 0;
65031.1Skamil
65041.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
65051.1Skamil	while (pl.pl_lwpid != 0) {
65061.1Skamil
65071.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
65081.1Skamil		switch (pl.pl_lwpid) {
65091.1Skamil		case 1:
65101.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
65111.1Skamil			break;
65121.1Skamil		case 2:
65131.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
65141.1Skamil			break;
65151.1Skamil		}
65161.1Skamil	}
65171.1Skamil
65181.13Schristos	DPRINTF("Before resuming the child process where it left off and "
65191.1Skamil	    "without signal to be sent\n");
65201.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
65211.1Skamil
65221.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
65231.1Skamil	    TWAIT_FNAME);
65241.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
65251.1Skamil
65261.1Skamil	validate_status_exited(status, exitval);
65271.1Skamil
65281.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
65291.1Skamil	    TWAIT_FNAME);
65301.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
65311.1Skamil}
65321.1Skamil
65331.1SkamilATF_TC(suspend2);
65341.1SkamilATF_TC_HEAD(suspend2, tc)
65351.1Skamil{
65361.1Skamil	atf_tc_set_md_var(tc, "descr",
65371.1Skamil	    "Verify that the while the only thread within a process is "
65381.1Skamil	    "suspended, the whole process cannot be unstopped");
65391.1Skamil}
65401.1Skamil
65411.1SkamilATF_TC_BODY(suspend2, tc)
65421.1Skamil{
65431.1Skamil	const int exitval = 5;
65441.1Skamil	const int sigval = SIGSTOP;
65451.1Skamil	pid_t child, wpid;
65461.1Skamil#if defined(TWAIT_HAVE_STATUS)
65471.1Skamil	int status;
65481.1Skamil#endif
65491.1Skamil	struct ptrace_siginfo psi;
65501.1Skamil
65511.17Skamil	// Feature pending for refactoring
65521.17Skamil	atf_tc_expect_fail("PR kern/51995");
65531.17Skamil
65541.16Skamil	// Hangs with qemu
65551.16Skamil	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
65561.16Skamil
65571.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
65581.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
65591.1Skamil	if (child == 0) {
65601.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
65611.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
65621.1Skamil
65631.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
65641.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
65651.1Skamil
65661.13Schristos		DPRINTF("Before exiting of the child process\n");
65671.1Skamil		_exit(exitval);
65681.1Skamil	}
65691.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
65701.1Skamil
65711.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
65721.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
65731.1Skamil
65741.1Skamil	validate_status_stopped(status, sigval);
65751.1Skamil
65761.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
65771.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
65781.1Skamil
65791.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
65801.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
65811.1Skamil
65821.13Schristos	DPRINTF("Before resuming the child process where it left off and "
65831.1Skamil	    "without signal to be sent\n");
65841.1Skamil	ATF_REQUIRE_ERRNO(EDEADLK,
65851.1Skamil	    ptrace(PT_CONTINUE, child, (void *)1, 0) == -1);
65861.1Skamil
65871.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
65881.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
65891.1Skamil
65901.13Schristos	DPRINTF("Before resuming the child process where it left off and "
65911.1Skamil	    "without signal to be sent\n");
65921.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
65931.1Skamil
65941.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
65951.1Skamil	    TWAIT_FNAME);
65961.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
65971.1Skamil
65981.1Skamil	validate_status_exited(status, exitval);
65991.1Skamil
66001.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
66011.1Skamil	    TWAIT_FNAME);
66021.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
66031.1Skamil}
66041.1Skamil
66051.1SkamilATF_TC(resume1);
66061.1SkamilATF_TC_HEAD(resume1, tc)
66071.1Skamil{
66081.1Skamil	atf_tc_set_md_var(tc, "timeout", "5");
66091.1Skamil	atf_tc_set_md_var(tc, "descr",
66101.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
66111.1Skamil	    "resumed by the debugger");
66121.1Skamil}
66131.1Skamil
66141.1SkamilATF_TC_BODY(resume1, tc)
66151.1Skamil{
66161.1Skamil	struct msg_fds fds;
66171.1Skamil	const int exitval = 5;
66181.1Skamil	const int sigval = SIGSTOP;
66191.1Skamil	pid_t child, wpid;
66201.1Skamil	uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */
66211.1Skamil#if defined(TWAIT_HAVE_STATUS)
66221.1Skamil	int status;
66231.1Skamil#endif
66241.1Skamil	ucontext_t uc;
66251.1Skamil	lwpid_t lid;
66261.1Skamil	static const size_t ssize = 16*1024;
66271.1Skamil	void *stack;
66281.1Skamil	struct ptrace_lwpinfo pl;
66291.1Skamil	struct ptrace_siginfo psi;
66301.1Skamil
66311.17Skamil	// Feature pending for refactoring
66321.17Skamil	atf_tc_expect_fail("PR kern/51995");
66331.17Skamil
66341.15Schristos	// Hangs with qemu
66351.15Schristos	ATF_REQUIRE(0 && "In order to get reliable failure, abort");
66361.1Skamil
66371.13Schristos	SYSCALL_REQUIRE(msg_open(&fds) == 0);
66381.1Skamil
66391.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
66401.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
66411.1Skamil	if (child == 0) {
66421.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
66431.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
66441.1Skamil
66451.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
66461.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
66471.1Skamil
66481.13Schristos		DPRINTF("Before allocating memory for stack in child\n");
66491.1Skamil		FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
66501.1Skamil
66511.13Schristos		DPRINTF("Before making context for new lwp in child\n");
66521.1Skamil		_lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize);
66531.1Skamil
66541.13Schristos		DPRINTF("Before creating new in child\n");
66551.1Skamil		FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
66561.1Skamil
66571.1Skamil		CHILD_TO_PARENT("Message", fds, msg);
66581.1Skamil
66591.1Skamil		raise(SIGINT);
66601.1Skamil
66611.13Schristos		DPRINTF("Before waiting for lwp %d to exit\n", lid);
66621.1Skamil		FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
66631.1Skamil
66641.13Schristos		DPRINTF("Before verifying that reported %d and running lid %d "
66651.1Skamil		    "are the same\n", lid, the_lwp_id);
66661.1Skamil		FORKEE_ASSERT_EQ(lid, the_lwp_id);
66671.1Skamil
66681.13Schristos		DPRINTF("Before exiting of the child process\n");
66691.1Skamil		_exit(exitval);
66701.1Skamil	}
66711.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
66721.1Skamil
66731.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
66741.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
66751.1Skamil
66761.1Skamil	validate_status_stopped(status, sigval);
66771.1Skamil
66781.13Schristos	DPRINTF("Before resuming the child process where it left off and "
66791.1Skamil	    "without signal to be sent\n");
66801.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
66811.1Skamil
66821.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
66831.1Skamil	    "SIGTRAP\n", TWAIT_FNAME);
66841.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
66851.1Skamil
66861.1Skamil	validate_status_stopped(status, SIGTRAP);
66871.1Skamil
66881.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
66891.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
66901.1Skamil
66911.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
66921.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
66931.1Skamil
66941.1Skamil	PARENT_FROM_CHILD("Message", fds, msg);
66951.1Skamil
66961.13Schristos	DPRINTF("Before resuming the child process where it left off and "
66971.1Skamil	    "without signal to be sent\n");
66981.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
66991.1Skamil
67001.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
67011.1Skamil	    "SIGINT\n", TWAIT_FNAME);
67021.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
67031.1Skamil
67041.1Skamil	validate_status_stopped(status, SIGINT);
67051.1Skamil
67061.1Skamil	pl.pl_lwpid = 0;
67071.1Skamil
67081.13Schristos	SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
67091.1Skamil	while (pl.pl_lwpid != 0) {
67101.13Schristos		SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1);
67111.1Skamil		switch (pl.pl_lwpid) {
67121.1Skamil		case 1:
67131.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL);
67141.1Skamil			break;
67151.1Skamil		case 2:
67161.1Skamil			ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED);
67171.1Skamil			break;
67181.1Skamil		}
67191.1Skamil	}
67201.1Skamil
67211.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
67221.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
67231.1Skamil
67241.13Schristos	DPRINTF("Before resuming the child process where it left off and "
67251.1Skamil	    "without signal to be sent\n");
67261.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
67271.1Skamil
67281.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
67291.1Skamil	    TWAIT_FNAME);
67301.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
67311.1Skamil
67321.1Skamil	validate_status_exited(status, exitval);
67331.1Skamil
67341.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
67351.1Skamil	    TWAIT_FNAME);
67361.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
67371.1Skamil
67381.1Skamil	msg_close(&fds);
67391.1Skamil
67401.13Schristos	DPRINTF("XXX: Test worked this time but for consistency timeout it\n");
67411.1Skamil	sleep(10);
67421.1Skamil}
67431.1Skamil
67441.1SkamilATF_TC(syscall1);
67451.1SkamilATF_TC_HEAD(syscall1, tc)
67461.1Skamil{
67471.1Skamil	atf_tc_set_md_var(tc, "descr",
67481.1Skamil	    "Verify that getpid(2) can be traced with PT_SYSCALL");
67491.1Skamil}
67501.1Skamil
67511.1SkamilATF_TC_BODY(syscall1, tc)
67521.1Skamil{
67531.1Skamil	const int exitval = 5;
67541.1Skamil	const int sigval = SIGSTOP;
67551.1Skamil	pid_t child, wpid;
67561.1Skamil#if defined(TWAIT_HAVE_STATUS)
67571.1Skamil	int status;
67581.1Skamil#endif
67591.1Skamil	struct ptrace_siginfo info;
67601.1Skamil	memset(&info, 0, sizeof(info));
67611.1Skamil
67621.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
67631.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
67641.1Skamil	if (child == 0) {
67651.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
67661.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
67671.1Skamil
67681.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
67691.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
67701.1Skamil
67711.1Skamil		syscall(SYS_getpid);
67721.1Skamil
67731.13Schristos		DPRINTF("Before exiting of the child process\n");
67741.1Skamil		_exit(exitval);
67751.1Skamil	}
67761.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
67771.1Skamil
67781.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
67791.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
67801.1Skamil
67811.1Skamil	validate_status_stopped(status, sigval);
67821.1Skamil
67831.13Schristos	DPRINTF("Before resuming the child process where it left off and "
67841.1Skamil	    "without signal to be sent\n");
67851.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
67861.1Skamil
67871.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
67881.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
67891.1Skamil
67901.1Skamil	validate_status_stopped(status, SIGTRAP);
67911.1Skamil
67921.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
67931.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
67941.1Skamil
67951.38Skamil	DPRINTF("Before checking siginfo_t and lwpid\n");
67961.38Skamil	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
67971.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
67981.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCE);
67991.1Skamil
68001.13Schristos	DPRINTF("Before resuming the child process where it left off and "
68011.1Skamil	    "without signal to be sent\n");
68021.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
68031.1Skamil
68041.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
68051.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
68061.1Skamil
68071.1Skamil	validate_status_stopped(status, SIGTRAP);
68081.1Skamil
68091.13Schristos	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
68101.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
68111.1Skamil
68121.38Skamil	DPRINTF("Before checking siginfo_t and lwpid\n");
68131.38Skamil	ATF_REQUIRE_EQ(info.psi_lwpid, 1);
68141.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
68151.1Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCX);
68161.1Skamil
68171.13Schristos	DPRINTF("Before resuming the child process where it left off and "
68181.1Skamil	    "without signal to be sent\n");
68191.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
68201.1Skamil
68211.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
68221.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
68231.1Skamil
68241.1Skamil	validate_status_exited(status, exitval);
68251.1Skamil
68261.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
68271.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
68281.1Skamil}
68291.1Skamil
68301.1SkamilATF_TC(syscallemu1);
68311.1SkamilATF_TC_HEAD(syscallemu1, tc)
68321.1Skamil{
68331.1Skamil	atf_tc_set_md_var(tc, "descr",
68341.1Skamil	    "Verify that exit(2) can be intercepted with PT_SYSCALLEMU");
68351.1Skamil}
68361.1Skamil
68371.1SkamilATF_TC_BODY(syscallemu1, tc)
68381.1Skamil{
68391.1Skamil	const int exitval = 5;
68401.1Skamil	const int sigval = SIGSTOP;
68411.1Skamil	pid_t child, wpid;
68421.1Skamil#if defined(TWAIT_HAVE_STATUS)
68431.1Skamil	int status;
68441.1Skamil#endif
68451.1Skamil
68461.6Skamil#if defined(__sparc__) && !defined(__sparc64__)
68471.6Skamil	/* syscallemu does not work on sparc (32-bit) */
68481.6Skamil	atf_tc_expect_fail("PR kern/52166");
68491.6Skamil#endif
68501.6Skamil
68511.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
68521.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
68531.1Skamil	if (child == 0) {
68541.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
68551.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
68561.1Skamil
68571.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
68581.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
68591.1Skamil
68601.1Skamil		syscall(SYS_exit, 100);
68611.1Skamil
68621.13Schristos		DPRINTF("Before exiting of the child process\n");
68631.1Skamil		_exit(exitval);
68641.1Skamil	}
68651.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
68661.1Skamil
68671.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
68681.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
68691.1Skamil
68701.1Skamil	validate_status_stopped(status, sigval);
68711.1Skamil
68721.13Schristos	DPRINTF("Before resuming the child process where it left off and "
68731.1Skamil	    "without signal to be sent\n");
68741.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
68751.1Skamil
68761.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
68771.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
68781.1Skamil
68791.1Skamil	validate_status_stopped(status, SIGTRAP);
68801.1Skamil
68811.13Schristos	DPRINTF("Set SYSCALLEMU for intercepted syscall\n");
68821.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALLEMU, child, (void *)1, 0) != -1);
68831.1Skamil
68841.13Schristos	DPRINTF("Before resuming the child process where it left off and "
68851.1Skamil	    "without signal to be sent\n");
68861.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1);
68871.1Skamil
68881.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
68891.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
68901.1Skamil
68911.1Skamil	validate_status_stopped(status, SIGTRAP);
68921.1Skamil
68931.13Schristos	DPRINTF("Before resuming the child process where it left off and "
68941.1Skamil	    "without signal to be sent\n");
68951.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
68961.1Skamil
68971.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
68981.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
68991.1Skamil
69001.1Skamil	validate_status_exited(status, exitval);
69011.1Skamil
69021.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
69031.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
69041.1Skamil}
69051.1Skamil
69061.26Skamil#if defined(TWAIT_HAVE_PID)
69071.26SkamilATF_TC(race1);
69081.26SkamilATF_TC_HEAD(race1, tc)
69091.26Skamil{
69101.26Skamil	atf_tc_set_md_var(tc, "descr",
69111.26Skamil	    "Assert that await_zombie() in attach1 always finds a single "
69121.26Skamil	    "process and no other error is reported");
69131.26Skamil}
69141.26Skamil
69151.26SkamilATF_TC_BODY(race1, tc)
69161.26Skamil{
69171.26Skamil	time_t start, end;
69181.26Skamil	double diff;
69191.26Skamil	unsigned long N = 0;
69201.26Skamil
69211.26Skamil	/* Reuse this test with attach1 */
69221.26Skamil
69231.26Skamil	start = time(NULL);
69241.26Skamil	while (true) {
69251.26Skamil		DPRINTF("Step: %lu\n", N);
69261.26Skamil		attach1_raw(true);
69271.26Skamil		end = time(NULL);
69281.26Skamil		diff = difftime(end, start);
69291.26Skamil		if (diff >= 5.0)
69301.26Skamil			break;
69311.26Skamil		++N;
69321.26Skamil	}
69331.26Skamil	DPRINTF("Iterations: %lu\n", N);
69341.26Skamil}
69351.26Skamil#endif
69361.26Skamil
69371.1Skamil#include "t_ptrace_amd64_wait.h"
69381.1Skamil#include "t_ptrace_i386_wait.h"
69391.1Skamil#include "t_ptrace_x86_wait.h"
69401.1Skamil
69411.1SkamilATF_TP_ADD_TCS(tp)
69421.1Skamil{
69431.1Skamil	setvbuf(stdout, NULL, _IONBF, 0);
69441.1Skamil	setvbuf(stderr, NULL, _IONBF, 0);
69451.33Skamil
69461.36Skamil	ATF_TP_ADD_TC(tp, traceme_raise1);
69471.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise2);
69481.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise3);
69491.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise4);
69501.33Skamil	ATF_TP_ADD_TC(tp, traceme_raise5);
69511.33Skamil
69521.34Skamil	ATF_TP_ADD_TC(tp, traceme_sighandler_catch1);
69531.34Skamil	ATF_TP_ADD_TC(tp, traceme_sighandler_catch2);
69541.34Skamil	ATF_TP_ADD_TC(tp, traceme_sighandler_catch3);
69551.34Skamil
69561.35Skamil	ATF_TP_ADD_TC(tp, traceme_signal_nohandler1);
69571.35Skamil//	ATF_TP_ADD_TC(tp, traceme_signal_nohandler2); // not yet
69581.35Skamil	ATF_TP_ADD_TC(tp, traceme_signal_nohandler3);
69591.35Skamil	ATF_TP_ADD_TC(tp, traceme_signal_nohandler4);
69601.35Skamil	ATF_TP_ADD_TC(tp, traceme_signal_nohandler5);
69611.1Skamil
69621.37Skamil	ATF_TP_ADD_TC(tp, traceme_pid1_parent);
69631.37Skamil
69641.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise1);
69651.40Skamil//	ATF_TP_ADD_TC(tp, traceme_vfork_raise2); // not yet
69661.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise3);
69671.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise4);
69681.40Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_raise5);
69691.40Skamil
69701.41Skamil	ATF_TP_ADD_TC(tp, traceme_vfork_breakpoint);
69711.41Skamil
69721.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach1);
69731.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach2);
69741.1Skamil	ATF_TP_ADD_TC(tp, attach3);
69751.1Skamil	ATF_TP_ADD_TC(tp, attach4);
69761.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach5);
69771.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach6);
69781.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, attach7);
69791.1Skamil
69801.1Skamil	ATF_TP_ADD_TC(tp, eventmask1);
69811.1Skamil	ATF_TP_ADD_TC(tp, eventmask2);
69821.1Skamil	ATF_TP_ADD_TC(tp, eventmask3);
69831.1Skamil	ATF_TP_ADD_TC(tp, eventmask4);
69841.1Skamil	ATF_TP_ADD_TC(tp, eventmask5);
69851.1Skamil	ATF_TP_ADD_TC(tp, eventmask6);
69861.1Skamil
69871.31Skamil	ATF_TP_ADD_TC(tp, fork1);
69881.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork2);
69891.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork3);
69901.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork4);
69911.31Skamil	ATF_TP_ADD_TC(tp, fork5);
69921.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork6);
69931.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork7);
69941.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, fork8);
69951.31Skamil
69961.31Skamil	ATF_TP_ADD_TC(tp, vfork1);
69971.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork2);
69981.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork3);
69991.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork4);
70001.31Skamil	ATF_TP_ADD_TC(tp, vfork5);
70011.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork6);
70021.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork7);
70031.31Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, vfork8);
70041.1Skamil
70051.1Skamil	ATF_TP_ADD_TC(tp, io_read_d1);
70061.1Skamil	ATF_TP_ADD_TC(tp, io_read_d2);
70071.1Skamil	ATF_TP_ADD_TC(tp, io_read_d3);
70081.1Skamil	ATF_TP_ADD_TC(tp, io_read_d4);
70091.1Skamil
70101.1Skamil	ATF_TP_ADD_TC(tp, io_write_d1);
70111.1Skamil	ATF_TP_ADD_TC(tp, io_write_d2);
70121.1Skamil	ATF_TP_ADD_TC(tp, io_write_d3);
70131.1Skamil	ATF_TP_ADD_TC(tp, io_write_d4);
70141.1Skamil
70151.1Skamil	ATF_TP_ADD_TC(tp, read_d1);
70161.1Skamil	ATF_TP_ADD_TC(tp, read_d2);
70171.1Skamil	ATF_TP_ADD_TC(tp, read_d3);
70181.1Skamil	ATF_TP_ADD_TC(tp, read_d4);
70191.1Skamil
70201.1Skamil	ATF_TP_ADD_TC(tp, write_d1);
70211.1Skamil	ATF_TP_ADD_TC(tp, write_d2);
70221.1Skamil	ATF_TP_ADD_TC(tp, write_d3);
70231.1Skamil	ATF_TP_ADD_TC(tp, write_d4);
70241.1Skamil
70251.1Skamil	ATF_TP_ADD_TC(tp, io_read_d_write_d_handshake1);
70261.1Skamil	ATF_TP_ADD_TC(tp, io_read_d_write_d_handshake2);
70271.1Skamil
70281.1Skamil	ATF_TP_ADD_TC(tp, read_d_write_d_handshake1);
70291.1Skamil	ATF_TP_ADD_TC(tp, read_d_write_d_handshake2);
70301.1Skamil
70311.1Skamil	ATF_TP_ADD_TC(tp, io_read_i1);
70321.1Skamil	ATF_TP_ADD_TC(tp, io_read_i2);
70331.1Skamil	ATF_TP_ADD_TC(tp, io_read_i3);
70341.1Skamil	ATF_TP_ADD_TC(tp, io_read_i4);
70351.1Skamil
70361.1Skamil	ATF_TP_ADD_TC(tp, read_i1);
70371.1Skamil	ATF_TP_ADD_TC(tp, read_i2);
70381.1Skamil	ATF_TP_ADD_TC(tp, read_i3);
70391.1Skamil	ATF_TP_ADD_TC(tp, read_i4);
70401.1Skamil
70411.1Skamil	ATF_TP_ADD_TC(tp, io_read_auxv1);
70421.1Skamil
70431.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs1);
70441.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs2);
70451.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs3);
70461.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs4);
70471.1Skamil	ATF_TP_ADD_TC_HAVE_GPREGS(tp, regs5);
70481.1Skamil
70491.1Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, fpregs1);
70501.1Skamil	ATF_TP_ADD_TC_HAVE_FPREGS(tp, fpregs2);
70511.1Skamil
70521.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step1);
70531.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step2);
70541.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step3);
70551.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, step4);
70561.1Skamil
70571.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep1);
70581.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep2);
70591.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep3);
70601.2Skamil	ATF_TP_ADD_TC_PT_STEP(tp, setstep4);
70611.2Skamil
70621.1Skamil	ATF_TP_ADD_TC(tp, kill1);
70631.1Skamil	ATF_TP_ADD_TC(tp, kill2);
70641.1Skamil
70651.1Skamil	ATF_TP_ADD_TC(tp, lwpinfo1);
70661.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, lwpinfo2);
70671.1Skamil
70681.1Skamil	ATF_TP_ADD_TC(tp, siginfo1);
70691.1Skamil	ATF_TP_ADD_TC(tp, siginfo2);
70701.1Skamil	ATF_TP_ADD_TC(tp, siginfo3);
70711.1Skamil	ATF_TP_ADD_TC(tp, siginfo4);
70721.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, siginfo5);
70731.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, siginfo6);
70741.1Skamil
70751.1Skamil	ATF_TP_ADD_TC(tp, lwp_create1);
70761.1Skamil
70771.1Skamil	ATF_TP_ADD_TC(tp, lwp_exit1);
70781.1Skamil
70791.1Skamil	ATF_TP_ADD_TC(tp, signal1);
70801.1Skamil	ATF_TP_ADD_TC(tp, signal2);
70811.1Skamil	ATF_TP_ADD_TC(tp, signal3);
70821.1Skamil	ATF_TP_ADD_TC_PT_STEP(tp, signal4);
70831.1Skamil	ATF_TP_ADD_TC(tp, signal5);
70841.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, signal6);
70851.1Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, signal7);
70861.1Skamil	ATF_TP_ADD_TC(tp, signal8);
70871.1Skamil	ATF_TP_ADD_TC(tp, signal9);
70881.1Skamil	ATF_TP_ADD_TC(tp, signal10);
70891.1Skamil
70901.1Skamil	ATF_TP_ADD_TC(tp, suspend1);
70911.1Skamil	ATF_TP_ADD_TC(tp, suspend2);
70921.1Skamil
70931.1Skamil	ATF_TP_ADD_TC(tp, resume1);
70941.1Skamil
70951.1Skamil	ATF_TP_ADD_TC(tp, syscall1);
70961.1Skamil
70971.1Skamil	ATF_TP_ADD_TC(tp, syscallemu1);
70981.1Skamil
70991.26Skamil	ATF_TP_ADD_TC_HAVE_PID(tp, race1);
71001.26Skamil
71011.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64();
71021.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_I386();
71031.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_X86();
71041.1Skamil
71051.1Skamil	return atf_no_error();
71061.1Skamil}
7107