t_ptrace_wait.c revision 1.187
11.187Skamil/*	$NetBSD: t_ptrace_wait.c,v 1.187 2020/05/05 00:33:37 kamil Exp $	*/
21.1Skamil
31.1Skamil/*-
41.181Skamil * Copyright (c) 2016, 2017, 2018, 2019, 2020 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.187Skamil__RCSID("$NetBSD: t_ptrace_wait.c,v 1.187 2020/05/05 00:33:37 kamil Exp $");
311.143Skamil
321.143Skamil#define __LEGACY_PT_LWPINFO
331.1Skamil
341.1Skamil#include <sys/param.h>
351.1Skamil#include <sys/types.h>
361.130Smgorny#include <sys/exec_elf.h>
371.39Skamil#include <sys/mman.h>
381.1Skamil#include <sys/ptrace.h>
391.1Skamil#include <sys/resource.h>
401.1Skamil#include <sys/stat.h>
411.1Skamil#include <sys/syscall.h>
421.1Skamil#include <sys/sysctl.h>
431.129Smgorny#include <sys/uio.h>
441.1Skamil#include <sys/wait.h>
451.1Skamil#include <machine/reg.h>
461.132Skamil#include <assert.h>
471.1Skamil#include <elf.h>
481.1Skamil#include <err.h>
491.1Skamil#include <errno.h>
501.130Smgorny#include <fcntl.h>
511.1Skamil#include <lwp.h>
521.77Skamil#include <pthread.h>
531.1Skamil#include <sched.h>
541.1Skamil#include <signal.h>
551.124Skamil#include <spawn.h>
561.1Skamil#include <stdint.h>
571.1Skamil#include <stdio.h>
581.1Skamil#include <stdlib.h>
591.1Skamil#include <strings.h>
601.26Skamil#include <time.h>
611.1Skamil#include <unistd.h>
621.1Skamil
631.121Smgorny#if defined(__i386__) || defined(__x86_64__)
641.121Smgorny#include <cpuid.h>
651.121Smgorny#include <x86/cpu_extended_state.h>
661.129Smgorny#include <x86/specialreg.h>
671.121Smgorny#endif
681.121Smgorny
691.130Smgorny#include <libelf.h>
701.130Smgorny#include <gelf.h>
711.130Smgorny
721.1Skamil#include <atf-c.h>
731.1Skamil
741.165Skamil#ifdef ENABLE_TESTS
751.165Skamil
761.132Skamil/* Assumptions in the kernel code that must be kept. */
771.171Skamil__CTASSERT(sizeof(((struct ptrace_state *)0)->pe_report_event) ==
781.171Skamil    sizeof(((siginfo_t *)0)->si_pe_report_event));
791.171Skamil__CTASSERT(sizeof(((struct ptrace_state *)0)->pe_other_pid) ==
801.171Skamil    sizeof(((siginfo_t *)0)->si_pe_other_pid));
811.171Skamil__CTASSERT(sizeof(((struct ptrace_state *)0)->pe_lwp) ==
821.171Skamil    sizeof(((siginfo_t *)0)->si_pe_lwp));
831.171Skamil__CTASSERT(sizeof(((struct ptrace_state *)0)->pe_other_pid) ==
841.171Skamil    sizeof(((struct ptrace_state *)0)->pe_lwp));
851.132Skamil
861.1Skamil#include "h_macros.h"
871.1Skamil
881.1Skamil#include "t_ptrace_wait.h"
891.1Skamil#include "msg.h"
901.1Skamil
911.13Schristos#define SYSCALL_REQUIRE(expr) ATF_REQUIRE_MSG(expr, "%s: %s", # expr, \
921.13Schristos    strerror(errno))
931.18Schristos#define SYSCALL_REQUIRE_ERRNO(res, exp) ATF_REQUIRE_MSG(res == exp, \
941.18Schristos    "%d(%s) != %d", res, strerror(res), exp)
951.13Schristos
961.152Skamilstatic int debug = 0;
971.13Schristos
981.13Schristos#define DPRINTF(a, ...)	do  \
991.123Skamil	if (debug) \
1001.142Skamil	printf("%s() %d.%d %s:%d " a, \
1011.142Skamil	__func__, getpid(), _lwp_self(), __FILE__, __LINE__,  ##__VA_ARGS__); \
1021.13Schristos    while (/*CONSTCOND*/0)
1031.1Skamil
1041.34Skamil/// ----------------------------------------------------------------------------
1051.34Skamil
1061.83Skamilstatic void
1071.180Skamilptrace_siginfo(bool faked, void (*sah)(int a, siginfo_t *b, void *c), int *signal_caught)
1081.1Skamil{
1091.180Skamil	const int exitval = 5;
1101.180Skamil	const int sigval = SIGINT;
1111.180Skamil	const int sigfaked = SIGTRAP;
1121.180Skamil	const int sicodefaked = TRAP_BRKPT;
1131.1Skamil	pid_t child, wpid;
1141.180Skamil	struct sigaction sa;
1151.1Skamil#if defined(TWAIT_HAVE_STATUS)
1161.1Skamil	int status;
1171.1Skamil#endif
1181.83Skamil	struct ptrace_siginfo info;
1191.180Skamil	memset(&info, 0, sizeof(info));
1201.83Skamil
1211.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
1221.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
1231.1Skamil	if (child == 0) {
1241.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
1251.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
1261.1Skamil
1271.180Skamil		sa.sa_sigaction = sah;
1281.180Skamil		sa.sa_flags = SA_SIGINFO;
1291.180Skamil		sigemptyset(&sa.sa_mask);
1301.180Skamil
1311.180Skamil		FORKEE_ASSERT(sigaction(faked ? sigfaked : sigval, &sa, NULL)
1321.180Skamil		    != -1);
1331.153Skamil
1341.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
1351.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
1361.1Skamil
1371.180Skamil		FORKEE_ASSERT_EQ(*signal_caught, 1);
1381.1Skamil
1391.180Skamil		DPRINTF("Before exiting of the child process\n");
1401.180Skamil		_exit(exitval);
1411.1Skamil	}
1421.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
1431.1Skamil
1441.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1451.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1461.1Skamil
1471.1Skamil	validate_status_stopped(status, sigval);
1481.1Skamil
1491.83Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
1501.83Skamil	SYSCALL_REQUIRE(
1511.83Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
1521.1Skamil
1531.83Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
1541.83Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
1551.83Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
1561.83Skamil	    info.psi_siginfo.si_errno);
1571.1Skamil
1581.180Skamil	if (faked) {
1591.180Skamil		DPRINTF("Before setting new faked signal to signo=%d "
1601.180Skamil		    "si_code=%d\n", sigfaked, sicodefaked);
1611.180Skamil		info.psi_siginfo.si_signo = sigfaked;
1621.180Skamil		info.psi_siginfo.si_code = sicodefaked;
1631.83Skamil	}
1641.1Skamil
1651.180Skamil	DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n");
1661.180Skamil	SYSCALL_REQUIRE(
1671.180Skamil	    ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1);
1681.1Skamil
1691.180Skamil	if (faked) {
1701.83Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
1711.83Skamil		    "child\n");
1721.180Skamil		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
1731.180Skamil		    sizeof(info)) != -1);
1741.1Skamil
1751.180Skamil		DPRINTF("Before checking siginfo_t\n");
1761.180Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigfaked);
1771.180Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, sicodefaked);
1781.83Skamil	}
1791.1Skamil
1801.180Skamil	DPRINTF("Before resuming the child process where it left off and "
1811.180Skamil	    "without signal to be sent\n");
1821.180Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1,
1831.180Skamil	    faked ? sigfaked : sigval) != -1);
1841.1Skamil
1851.180Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1861.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1871.1Skamil
1881.180Skamil	validate_status_exited(status, exitval);
1891.1Skamil
1901.180Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1911.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
1921.1Skamil}
1931.1Skamil
1941.180Skamil#define PTRACE_SIGINFO(test, faked)					\
1951.83SkamilATF_TC(test);								\
1961.83SkamilATF_TC_HEAD(test, tc)							\
1971.83Skamil{									\
1981.180Skamil	atf_tc_set_md_var(tc, "descr",					\
1991.180Skamil	    "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls"	\
2001.180Skamil	    "with%s setting signal to new value", faked ? "" : "out");	\
2011.180Skamil}									\
2021.180Skamil									\
2031.180Skamilstatic int test##_caught = 0;						\
2041.180Skamil									\
2051.180Skamilstatic void								\
2061.180Skamiltest##_sighandler(int sig, siginfo_t *info, void *ctx)			\
2071.180Skamil{									\
2081.180Skamil	if (faked) {							\
2091.180Skamil		FORKEE_ASSERT_EQ(sig, SIGTRAP);				\
2101.180Skamil		FORKEE_ASSERT_EQ(info->si_signo, SIGTRAP);		\
2111.180Skamil		FORKEE_ASSERT_EQ(info->si_code, TRAP_BRKPT);		\
2121.180Skamil	} else {							\
2131.180Skamil		FORKEE_ASSERT_EQ(sig, SIGINT);				\
2141.180Skamil		FORKEE_ASSERT_EQ(info->si_signo, SIGINT);		\
2151.180Skamil		FORKEE_ASSERT_EQ(info->si_code, SI_LWP);		\
2161.180Skamil	}								\
2171.180Skamil									\
2181.180Skamil	++ test##_caught;						\
2191.83Skamil}									\
2201.83Skamil									\
2211.83SkamilATF_TC_BODY(test, tc)							\
2221.83Skamil{									\
2231.83Skamil									\
2241.180Skamil	ptrace_siginfo(faked, test##_sighandler, & test##_caught); 	\
2251.83Skamil}
2261.83Skamil
2271.180SkamilPTRACE_SIGINFO(siginfo_set_unmodified, false)
2281.180SkamilPTRACE_SIGINFO(siginfo_set_faked, true)
2291.83Skamil
2301.83Skamil/// ----------------------------------------------------------------------------
2311.83Skamil
2321.180Skamil#define TRACE_THREADS_NUM 100
2331.180Skamil
2341.180Skamilstatic volatile int done;
2351.180Skamilpthread_mutex_t trace_threads_mtx = PTHREAD_MUTEX_INITIALIZER;
2361.180Skamil
2371.180Skamilstatic void *
2381.180Skamiltrace_threads_cb(void *arg __unused)
2391.180Skamil{
2401.180Skamil
2411.180Skamil	pthread_mutex_lock(&trace_threads_mtx);
2421.180Skamil	done++;
2431.180Skamil	pthread_mutex_unlock(&trace_threads_mtx);
2441.180Skamil
2451.180Skamil	while (done < TRACE_THREADS_NUM)
2461.180Skamil		sched_yield();
2471.180Skamil
2481.180Skamil	return NULL;
2491.180Skamil}
2501.180Skamil
2511.99Skamilstatic void
2521.180Skamiltrace_threads(bool trace_create, bool trace_exit, bool masked)
2531.1Skamil{
2541.1Skamil	const int sigval = SIGSTOP;
2551.180Skamil	pid_t child, wpid;
2561.1Skamil#if defined(TWAIT_HAVE_STATUS)
2571.1Skamil	int status;
2581.1Skamil#endif
2591.1Skamil	ptrace_state_t state;
2601.1Skamil	const int slen = sizeof(state);
2611.1Skamil	ptrace_event_t event;
2621.1Skamil	const int elen = sizeof(event);
2631.99Skamil	struct ptrace_siginfo info;
2641.180Skamil
2651.99Skamil	sigset_t intmask;
2661.99Skamil
2671.180Skamil	pthread_t t[TRACE_THREADS_NUM];
2681.180Skamil	int rv;
2691.180Skamil	size_t n;
2701.180Skamil	lwpid_t lid;
2711.1Skamil
2721.180Skamil	/* Track created and exited threads */
2731.180Skamil	struct lwp_event_count traced_lwps[__arraycount(t)] = {{0, 0}};
2741.14Schristos
2751.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
2761.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
2771.1Skamil	if (child == 0) {
2781.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
2791.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
2801.1Skamil
2811.99Skamil		if (masked) {
2821.99Skamil			sigemptyset(&intmask);
2831.99Skamil			sigaddset(&intmask, SIGTRAP);
2841.99Skamil			sigprocmask(SIG_BLOCK, &intmask, NULL);
2851.99Skamil		}
2861.99Skamil
2871.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
2881.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
2891.1Skamil
2901.180Skamil		for (n = 0; n < __arraycount(t); n++) {
2911.180Skamil			rv = pthread_create(&t[n], NULL, trace_threads_cb,
2921.180Skamil			    NULL);
2931.180Skamil			FORKEE_ASSERT(rv == 0);
2941.126Skamil		}
2951.1Skamil
2961.180Skamil		for (n = 0; n < __arraycount(t); n++) {
2971.180Skamil			rv = pthread_join(t[n], NULL);
2981.180Skamil			FORKEE_ASSERT(rv == 0);
2991.180Skamil		}
3001.1Skamil
3011.180Skamil		/*
3021.180Skamil		 * There is race between _exit() and pthread_join() detaching
3031.180Skamil		 * a thread. For simplicity kill the process after detecting
3041.180Skamil		 * LWP events.
3051.180Skamil		 */
3061.180Skamil		while (true)
3071.180Skamil			continue;
3081.1Skamil
3091.180Skamil		FORKEE_ASSERT(0 && "Not reached");
3101.1Skamil	}
3111.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
3121.1Skamil
3131.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
3141.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
3151.1Skamil
3161.1Skamil	validate_status_stopped(status, sigval);
3171.1Skamil
3181.99Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
3191.99Skamil	SYSCALL_REQUIRE(
3201.99Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
3211.99Skamil
3221.180Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
3231.180Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
3241.180Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
3251.180Skamil	    info.psi_siginfo.si_errno);
3261.180Skamil
3271.99Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
3281.99Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
3291.1Skamil
3301.180Skamil	DPRINTF("Set LWP event mask for the child %d\n", child);
3311.180Skamil	memset(&event, 0, sizeof(event));
3321.180Skamil	if (trace_create)
3331.180Skamil		event.pe_set_event |= PTRACE_LWP_CREATE;
3341.180Skamil	if (trace_exit)
3351.180Skamil		event.pe_set_event |= PTRACE_LWP_EXIT;
3361.99Skamil	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
3371.1Skamil
3381.99Skamil	DPRINTF("Before resuming the child process where it left off and "
3391.99Skamil	    "without signal to be sent\n");
3401.99Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
3411.1Skamil
3421.180Skamil	for (n = 0; n < (trace_create ? __arraycount(t) : 0); n++) {
3431.180Skamil		DPRINTF("Before calling %s() for the child - expected stopped "
3441.180Skamil		    "SIGTRAP\n", TWAIT_FNAME);
3451.99Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
3461.99Skamil		    child);
3471.1Skamil
3481.99Skamil		validate_status_stopped(status, SIGTRAP);
3491.1Skamil
3501.180Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
3511.180Skamil		    "child\n");
3521.180Skamil		SYSCALL_REQUIRE(
3531.180Skamil		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
3541.180Skamil
3551.180Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
3561.180Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
3571.180Skamil		    "si_errno=%#x\n",
3581.180Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
3591.180Skamil		    info.psi_siginfo.si_errno);
3601.1Skamil
3611.180Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
3621.180Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP);
3631.1Skamil
3641.180Skamil		SYSCALL_REQUIRE(
3651.180Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
3661.1Skamil
3671.180Skamil		ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_CREATE,
3681.180Skamil		    "%d != %d", state.pe_report_event, PTRACE_LWP_CREATE);
3691.1Skamil
3701.180Skamil		lid = state.pe_lwp;
3711.180Skamil		DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
3721.1Skamil
3731.180Skamil		*FIND_EVENT_COUNT(traced_lwps, lid) += 1;
3741.1Skamil
3751.180Skamil		DPRINTF("Before resuming the child process where it left off "
3761.180Skamil		    "and without signal to be sent\n");
3771.180Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
3781.180Skamil	}
3791.1Skamil
3801.180Skamil	for (n = 0; n < (trace_exit ? __arraycount(t) : 0); n++) {
3811.180Skamil		DPRINTF("Before calling %s() for the child - expected stopped "
3821.180Skamil		    "SIGTRAP\n", TWAIT_FNAME);
3831.180Skamil		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
3841.180Skamil		    child);
3851.1Skamil
3861.99Skamil		validate_status_stopped(status, SIGTRAP);
3871.1Skamil
3881.180Skamil		DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
3891.180Skamil		    "child\n");
3901.180Skamil		SYSCALL_REQUIRE(
3911.180Skamil		    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
3921.1Skamil
3931.180Skamil		DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
3941.180Skamil		DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
3951.180Skamil		    "si_errno=%#x\n",
3961.180Skamil		    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
3971.180Skamil		    info.psi_siginfo.si_errno);
3981.1Skamil
3991.180Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
4001.180Skamil		ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP);
4011.14Schristos
4021.180Skamil		SYSCALL_REQUIRE(
4031.180Skamil		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
4041.1Skamil
4051.180Skamil		ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_EXIT,
4061.180Skamil		    "%d != %d", state.pe_report_event, PTRACE_LWP_EXIT);
4071.1Skamil
4081.180Skamil		lid = state.pe_lwp;
4091.180Skamil		DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
4101.1Skamil
4111.180Skamil		if (trace_create) {
4121.180Skamil			int *count = FIND_EVENT_COUNT(traced_lwps, lid);
4131.180Skamil			ATF_REQUIRE_EQ(*count, 1);
4141.180Skamil			*count = 0;
4151.99Skamil		}
4161.1Skamil
4171.99Skamil		DPRINTF("Before resuming the child process where it left off "
4181.99Skamil		    "and without signal to be sent\n");
4191.99Skamil		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
4201.1Skamil	}
4211.1Skamil
4221.180Skamil	kill(child, SIGKILL);
4231.180Skamil
4241.180Skamil	DPRINTF("Before calling %s() for the child - expected exited\n",
4251.180Skamil	    TWAIT_FNAME);
4261.180Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
4271.180Skamil
4281.180Skamil	validate_status_signaled(status, SIGKILL, 0);
4291.1Skamil
4301.180Skamil	DPRINTF("Before calling %s() for the child - expected no process\n",
4311.180Skamil	    TWAIT_FNAME);
4321.180Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
4331.180Skamil}
4341.1Skamil
4351.180Skamil#define TRACE_THREADS(test, trace_create, trace_exit, mask)		\
4361.180SkamilATF_TC(test);								\
4371.180SkamilATF_TC_HEAD(test, tc)							\
4381.180Skamil{									\
4391.180Skamil        atf_tc_set_md_var(tc, "descr",					\
4401.180Skamil            "Verify spawning threads with%s tracing LWP create and"	\
4411.180Skamil	    "with%s tracing LWP exit", trace_create ? "" : "out",	\
4421.180Skamil	    trace_exit ? "" : "out");					\
4431.180Skamil}									\
4441.180Skamil									\
4451.180SkamilATF_TC_BODY(test, tc)							\
4461.180Skamil{									\
4471.180Skamil									\
4481.180Skamil        trace_threads(trace_create, trace_exit, mask);			\
4491.180Skamil}
4501.1Skamil
4511.180SkamilTRACE_THREADS(trace_thread_nolwpevents, false, false, false)
4521.180SkamilTRACE_THREADS(trace_thread_lwpexit, false, true, false)
4531.180SkamilTRACE_THREADS(trace_thread_lwpcreate, true, false, false)
4541.180SkamilTRACE_THREADS(trace_thread_lwpcreate_and_exit, true, true, false)
4551.102Skamil
4561.180SkamilTRACE_THREADS(trace_thread_lwpexit_masked_sigtrap, false, true, true)
4571.180SkamilTRACE_THREADS(trace_thread_lwpcreate_masked_sigtrap, true, false, true)
4581.180SkamilTRACE_THREADS(trace_thread_lwpcreate_and_exit_masked_sigtrap, true, true, true)
4591.1Skamil
4601.180Skamil/// ----------------------------------------------------------------------------
4611.1Skamil
4621.151Skamilstatic void *
4631.151Skamilthread_and_exec_thread_cb(void *arg __unused)
4641.151Skamil{
4651.151Skamil
4661.151Skamil	execlp("/bin/echo", "/bin/echo", NULL);
4671.151Skamil
4681.151Skamil	abort();
4691.151Skamil}
4701.151Skamil
4711.151Skamilstatic void
4721.151Skamilthreads_and_exec(void)
4731.151Skamil{
4741.151Skamil	const int sigval = SIGSTOP;
4751.151Skamil	pid_t child, wpid;
4761.151Skamil#if defined(TWAIT_HAVE_STATUS)
4771.151Skamil	int status;
4781.151Skamil#endif
4791.151Skamil	ptrace_state_t state;
4801.151Skamil	const int slen = sizeof(state);
4811.151Skamil	ptrace_event_t event;
4821.151Skamil	const int elen = sizeof(event);
4831.151Skamil	struct ptrace_siginfo info;
4841.151Skamil
4851.151Skamil	pthread_t t;
4861.151Skamil	lwpid_t lid;
4871.151Skamil
4881.151Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
4891.151Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
4901.151Skamil	if (child == 0) {
4911.151Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
4921.151Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
4931.151Skamil
4941.151Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
4951.151Skamil		FORKEE_ASSERT(raise(sigval) == 0);
4961.151Skamil
4971.151Skamil		FORKEE_ASSERT(pthread_create(&t, NULL,
4981.151Skamil		    thread_and_exec_thread_cb, NULL) == 0);
4991.151Skamil
5001.151Skamil		for (;;)
5011.151Skamil			continue;
5021.151Skamil
5031.151Skamil		FORKEE_ASSERT(0 && "Not reached");
5041.151Skamil	}
5051.151Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
5061.151Skamil
5071.151Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
5081.151Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
5091.151Skamil
5101.151Skamil	validate_status_stopped(status, sigval);
5111.151Skamil
5121.151Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
5131.151Skamil	SYSCALL_REQUIRE(
5141.151Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
5151.151Skamil
5161.151Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
5171.151Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
5181.151Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
5191.151Skamil	    info.psi_siginfo.si_errno);
5201.151Skamil
5211.151Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
5221.151Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
5231.151Skamil
5241.151Skamil	DPRINTF("Set LWP event mask for the child %d\n", child);
5251.151Skamil	memset(&event, 0, sizeof(event));
5261.151Skamil	event.pe_set_event |= PTRACE_LWP_CREATE | PTRACE_LWP_EXIT;
5271.151Skamil	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
5281.151Skamil
5291.151Skamil	DPRINTF("Before resuming the child process where it left off and "
5301.151Skamil	    "without signal to be sent\n");
5311.151Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
5321.151Skamil
5331.151Skamil	DPRINTF("Before calling %s() for the child - expected stopped "
5341.151Skamil	    "SIGTRAP\n", TWAIT_FNAME);
5351.151Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
5361.151Skamil	    child);
5371.151Skamil
5381.151Skamil	validate_status_stopped(status, SIGTRAP);
5391.151Skamil
5401.151Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
5411.151Skamil	    "child\n");
5421.151Skamil	SYSCALL_REQUIRE(
5431.151Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
5441.151Skamil
5451.151Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
5461.151Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
5471.151Skamil	    "si_errno=%#x\n",
5481.151Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
5491.151Skamil	    info.psi_siginfo.si_errno);
5501.151Skamil
5511.151Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
5521.151Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP);
5531.151Skamil
5541.151Skamil	SYSCALL_REQUIRE(
5551.151Skamil	    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
5561.151Skamil
5571.151Skamil	ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_CREATE,
5581.151Skamil	    "%d != %d", state.pe_report_event, PTRACE_LWP_CREATE);
5591.151Skamil
5601.151Skamil	lid = state.pe_lwp;
5611.151Skamil	DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
5621.151Skamil
5631.151Skamil	DPRINTF("Before resuming the child process where it left off "
5641.151Skamil	    "and without signal to be sent\n");
5651.151Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
5661.151Skamil
5671.151Skamil	DPRINTF("Before calling %s() for the child - expected stopped "
5681.151Skamil	    "SIGTRAP\n", TWAIT_FNAME);
5691.151Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
5701.151Skamil	    child);
5711.151Skamil
5721.151Skamil	validate_status_stopped(status, SIGTRAP);
5731.151Skamil
5741.151Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
5751.151Skamil	    "child\n");
5761.151Skamil	SYSCALL_REQUIRE(
5771.151Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
5781.151Skamil
5791.151Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
5801.151Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
5811.151Skamil	    "si_errno=%#x\n",
5821.151Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
5831.151Skamil	    info.psi_siginfo.si_errno);
5841.151Skamil
5851.151Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
5861.151Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP);
5871.151Skamil
5881.151Skamil	SYSCALL_REQUIRE(
5891.151Skamil	    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
5901.151Skamil
5911.151Skamil	ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_EXIT,
5921.151Skamil	    "%d != %d", state.pe_report_event, PTRACE_LWP_EXIT);
5931.151Skamil
5941.151Skamil	lid = state.pe_lwp;
5951.151Skamil	DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid);
5961.151Skamil
5971.151Skamil	DPRINTF("Before resuming the child process where it left off "
5981.151Skamil	    "and without signal to be sent\n");
5991.151Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
6001.151Skamil
6011.151Skamil	DPRINTF("Before calling %s() for the child - expected stopped "
6021.151Skamil	    "SIGTRAP\n", TWAIT_FNAME);
6031.151Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
6041.151Skamil	    child);
6051.151Skamil
6061.151Skamil	validate_status_stopped(status, SIGTRAP);
6071.151Skamil
6081.151Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
6091.151Skamil	    "child\n");
6101.151Skamil	SYSCALL_REQUIRE(
6111.151Skamil	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
6121.151Skamil
6131.151Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
6141.151Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
6151.151Skamil	    "si_errno=%#x\n",
6161.151Skamil	    info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
6171.151Skamil	    info.psi_siginfo.si_errno);
6181.151Skamil
6191.151Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
6201.151Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
6211.151Skamil
6221.151Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
6231.151Skamil
6241.151Skamil	DPRINTF("Before calling %s() for the child - expected exited\n",
6251.151Skamil	    TWAIT_FNAME);
6261.151Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
6271.151Skamil
6281.151Skamil	validate_status_signaled(status, SIGKILL, 0);
6291.151Skamil
6301.151Skamil	DPRINTF("Before calling %s() for the child - expected no process\n",
6311.151Skamil	    TWAIT_FNAME);
6321.151Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
6331.151Skamil}
6341.151Skamil
6351.151SkamilATF_TC(threads_and_exec);
6361.151SkamilATF_TC_HEAD(threads_and_exec, tc)
6371.151Skamil{
6381.151Skamil        atf_tc_set_md_var(tc, "descr",
6391.151Skamil            "Verify that multithreaded application on exec() will report "
6401.151Skamil	    "LWP_EXIT events");
6411.151Skamil}
6421.151Skamil
6431.151SkamilATF_TC_BODY(threads_and_exec, tc)
6441.151Skamil{
6451.151Skamil
6461.151Skamil        threads_and_exec();
6471.151Skamil}
6481.151Skamil
6491.151Skamil/// ----------------------------------------------------------------------------
6501.151Skamil
6511.154SkamilATF_TC(suspend_no_deadlock);
6521.154SkamilATF_TC_HEAD(suspend_no_deadlock, tc)
6531.1Skamil{
6541.1Skamil	atf_tc_set_md_var(tc, "descr",
6551.1Skamil	    "Verify that the while the only thread within a process is "
6561.1Skamil	    "suspended, the whole process cannot be unstopped");
6571.1Skamil}
6581.1Skamil
6591.154SkamilATF_TC_BODY(suspend_no_deadlock, tc)
6601.1Skamil{
6611.1Skamil	const int exitval = 5;
6621.1Skamil	const int sigval = SIGSTOP;
6631.1Skamil	pid_t child, wpid;
6641.1Skamil#if defined(TWAIT_HAVE_STATUS)
6651.1Skamil	int status;
6661.1Skamil#endif
6671.1Skamil	struct ptrace_siginfo psi;
6681.1Skamil
6691.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
6701.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
6711.1Skamil	if (child == 0) {
6721.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
6731.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
6741.1Skamil
6751.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
6761.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
6771.1Skamil
6781.13Schristos		DPRINTF("Before exiting of the child process\n");
6791.1Skamil		_exit(exitval);
6801.1Skamil	}
6811.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
6821.1Skamil
6831.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
6841.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
6851.1Skamil
6861.1Skamil	validate_status_stopped(status, sigval);
6871.1Skamil
6881.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
6891.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
6901.1Skamil
6911.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
6921.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
6931.1Skamil
6941.13Schristos	DPRINTF("Before resuming the child process where it left off and "
6951.1Skamil	    "without signal to be sent\n");
6961.1Skamil	ATF_REQUIRE_ERRNO(EDEADLK,
6971.1Skamil	    ptrace(PT_CONTINUE, child, (void *)1, 0) == -1);
6981.1Skamil
6991.13Schristos	DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid);
7001.13Schristos	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1);
7011.1Skamil
7021.13Schristos	DPRINTF("Before resuming the child process where it left off and "
7031.1Skamil	    "without signal to be sent\n");
7041.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
7051.1Skamil
7061.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
7071.1Skamil	    TWAIT_FNAME);
7081.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
7091.1Skamil
7101.1Skamil	validate_status_exited(status, exitval);
7111.1Skamil
7121.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
7131.1Skamil	    TWAIT_FNAME);
7141.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
7151.1Skamil}
7161.1Skamil
7171.154Skamil/// ----------------------------------------------------------------------------
7181.154Skamil
7191.155Skamilstatic pthread_barrier_t barrier1_resume;
7201.155Skamilstatic pthread_barrier_t barrier2_resume;
7211.154Skamil
7221.155Skamilstatic void *
7231.155Skamilresume_thread(void *arg)
7241.154Skamil{
7251.154Skamil
7261.155Skamil	raise(SIGUSR1);
7271.155Skamil
7281.155Skamil	pthread_barrier_wait(&barrier1_resume);
7291.155Skamil
7301.155Skamil	/* Debugger will suspend the process here */
7311.155Skamil
7321.155Skamil	pthread_barrier_wait(&barrier2_resume);
7331.154Skamil
7341.155Skamil	raise(SIGUSR2);
7351.155Skamil
7361.155Skamil	return infinite_thread(arg);
7371.154Skamil}
7381.154Skamil
7391.155SkamilATF_TC(resume);
7401.155SkamilATF_TC_HEAD(resume, tc)
7411.1Skamil{
7421.1Skamil	atf_tc_set_md_var(tc, "descr",
7431.1Skamil	    "Verify that a thread can be suspended by a debugger and later "
7441.1Skamil	    "resumed by the debugger");
7451.1Skamil}
7461.1Skamil
7471.155SkamilATF_TC_BODY(resume, tc)
7481.1Skamil{
7491.1Skamil	const int sigval = SIGSTOP;
7501.1Skamil	pid_t child, wpid;
7511.1Skamil#if defined(TWAIT_HAVE_STATUS)
7521.1Skamil	int status;
7531.1Skamil#endif
7541.1Skamil	lwpid_t lid;
7551.1Skamil	struct ptrace_siginfo psi;
7561.155Skamil	pthread_t t;
7571.1Skamil
7581.13Schristos	DPRINTF("Before forking process PID=%d\n", getpid());
7591.13Schristos	SYSCALL_REQUIRE((child = fork()) != -1);
7601.1Skamil	if (child == 0) {
7611.13Schristos		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
7621.1Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
7631.1Skamil
7641.155Skamil		pthread_barrier_init(&barrier1_resume, NULL, 2);
7651.155Skamil		pthread_barrier_init(&barrier2_resume, NULL, 2);
7661.155Skamil
7671.13Schristos		DPRINTF("Before raising %s from child\n", strsignal(sigval));
7681.1Skamil		FORKEE_ASSERT(raise(sigval) == 0);
7691.1Skamil
7701.155Skamil		DPRINTF("Before creating new thread in child\n");
7711.155Skamil		FORKEE_ASSERT(pthread_create(&t, NULL, resume_thread, NULL) == 0);
7721.1Skamil
7731.155Skamil		pthread_barrier_wait(&barrier1_resume);
7741.1Skamil
7751.155Skamil		pthread_barrier_wait(&barrier2_resume);
7761.1Skamil
7771.155Skamil		infinite_thread(NULL);
7781.1Skamil	}
7791.13Schristos	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
7801.1Skamil
7811.13Schristos	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
7821.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
7831.1Skamil
7841.1Skamil	validate_status_stopped(status, sigval);
7851.1Skamil
7861.13Schristos	DPRINTF("Before resuming the child process where it left off and "
7871.1Skamil	    "without signal to be sent\n");
7881.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
7891.1Skamil
7901.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
7911.155Skamil	    "SIGUSR1\n", TWAIT_FNAME);
7921.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
7931.1Skamil
7941.155Skamil	validate_status_stopped(status, SIGUSR1);
7951.1Skamil
7961.13Schristos	DPRINTF("Before reading siginfo and lwpid_t\n");
7971.13Schristos	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1);
7981.1Skamil
7991.13Schristos	DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid);
8001.13Schristos	SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1);
8011.1Skamil
8021.155Skamil	lid = psi.psi_lwpid;
8031.1Skamil
8041.13Schristos	DPRINTF("Before resuming the child process where it left off and "
8051.1Skamil	    "without signal to be sent\n");
8061.13Schristos	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
8071.1Skamil
8081.155Skamil	DPRINTF("Before suspending the parent for 1 second, we expect no signals\n");
8091.155Skamil	SYSCALL_REQUIRE(sleep(1) == 0);
8101.155Skamil
8111.155Skamil#if defined(TWAIT_HAVE_OPTIONS)
8121.155Skamil	DPRINTF("Before calling %s() for the child - expected no status\n",
8131.155Skamil	    TWAIT_FNAME);
8141.155Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, WNOHANG), 0);
8151.155Skamil#endif
8161.155Skamil
8171.155Skamil	DPRINTF("Before resuming the child process where it left off and "
8181.155Skamil	    "without signal to be sent\n");
8191.155Skamil	SYSCALL_REQUIRE(ptrace(PT_STOP, child, NULL, 0) != -1);
8201.155Skamil
8211.13Schristos	DPRINTF("Before calling %s() for the child - expected stopped "
8221.155Skamil	    "SIGSTOP\n", TWAIT_FNAME);
8231.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
8241.1Skamil
8251.155Skamil	validate_status_stopped(status, SIGSTOP);
8261.1Skamil
8271.155Skamil	DPRINTF("Before resuming LWP %d\n", lid);
8281.155Skamil	SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, lid) != -1);
8291.155Skamil
8301.155Skamil	DPRINTF("Before resuming the child process where it left off and "
8311.155Skamil	    "without signal to be sent\n");
8321.155Skamil	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
8331.1Skamil
8341.155Skamil	DPRINTF("Before calling %s() for the child - expected stopped "
8351.155Skamil	    "SIGUSR2\n", TWAIT_FNAME);
8361.155Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
8371.1Skamil
8381.155Skamil	validate_status_stopped(status, SIGUSR2);
8391.1Skamil
8401.13Schristos	DPRINTF("Before resuming the child process where it left off and "
8411.1Skamil	    "without signal to be sent\n");
8421.155Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void *)1, 0) != -1);
8431.1Skamil
8441.13Schristos	DPRINTF("Before calling %s() for the child - expected exited\n",
8451.1Skamil	    TWAIT_FNAME);
8461.1Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
8471.1Skamil
8481.155Skamil	validate_status_signaled(status, SIGKILL, 0);
8491.1Skamil
8501.13Schristos	DPRINTF("Before calling %s() for the child - expected no process\n",
8511.1Skamil	    TWAIT_FNAME);
8521.1Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
8531.155Skamil}
8541.1Skamil
8551.155Skamil/// ----------------------------------------------------------------------------
8561.1Skamil
8571.106Skamilstatic void
8581.122Skamiluser_va0_disable(int operation)
8591.122Skamil{
8601.122Skamil	pid_t child, wpid;
8611.122Skamil#if defined(TWAIT_HAVE_STATUS)
8621.122Skamil	int status;
8631.122Skamil#endif
8641.122Skamil	const int sigval = SIGSTOP;
8651.122Skamil	int rv;
8661.122Skamil
8671.122Skamil	struct ptrace_siginfo info;
8681.122Skamil
8691.122Skamil	if (get_user_va0_disable() == 0)
8701.122Skamil		atf_tc_skip("vm.user_va0_disable is set to 0");
8711.122Skamil
8721.122Skamil	memset(&info, 0, sizeof(info));
8731.122Skamil
8741.122Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
8751.122Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
8761.122Skamil	if (child == 0) {
8771.122Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
8781.122Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
8791.122Skamil
8801.122Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
8811.122Skamil		FORKEE_ASSERT(raise(sigval) == 0);
8821.122Skamil
8831.122Skamil		/* NOTREACHED */
8841.122Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
8851.122Skamil		__unreachable();
8861.122Skamil	}
8871.122Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
8881.122Skamil
8891.122Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
8901.122Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
8911.122Skamil
8921.122Skamil	validate_status_stopped(status, sigval);
8931.122Skamil
8941.122Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
8951.122Skamil		"child\n");
8961.122Skamil	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
8971.122Skamil		sizeof(info)) != -1);
8981.122Skamil
8991.122Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
9001.122Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
9011.122Skamil		"si_errno=%#x\n",
9021.122Skamil		info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
9031.122Skamil		info.psi_siginfo.si_errno);
9041.122Skamil
9051.122Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
9061.122Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
9071.122Skamil
9081.122Skamil	DPRINTF("Before resuming the child process in PC=0x0 "
9091.122Skamil	    "and without signal to be sent\n");
9101.122Skamil	errno = 0;
9111.122Skamil	rv = ptrace(operation, child, (void *)0, 0);
9121.122Skamil	ATF_REQUIRE_EQ(errno, EINVAL);
9131.122Skamil	ATF_REQUIRE_EQ(rv, -1);
9141.122Skamil
9151.122Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
9161.122Skamil
9171.122Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9181.122Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
9191.122Skamil	validate_status_signaled(status, SIGKILL, 0);
9201.122Skamil
9211.122Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
9221.122Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
9231.122Skamil}
9241.122Skamil
9251.122Skamil#define USER_VA0_DISABLE(test, operation)				\
9261.122SkamilATF_TC(test);								\
9271.122SkamilATF_TC_HEAD(test, tc)							\
9281.122Skamil{									\
9291.122Skamil	atf_tc_set_md_var(tc, "descr",					\
9301.122Skamil	    "Verify behavior of " #operation " with PC set to 0x0");	\
9311.122Skamil}									\
9321.122Skamil									\
9331.122SkamilATF_TC_BODY(test, tc)							\
9341.122Skamil{									\
9351.122Skamil									\
9361.122Skamil	user_va0_disable(operation);					\
9371.122Skamil}
9381.122Skamil
9391.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_continue, PT_CONTINUE)
9401.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_syscall, PT_SYSCALL)
9411.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_detach, PT_DETACH)
9421.122Skamil
9431.122Skamil/// ----------------------------------------------------------------------------
9441.122Skamil
9451.130Smgorny/*
9461.130Smgorny * Parse the core file and find the requested note.  If the reading or parsing
9471.130Smgorny * fails, the test is failed.  If the note is found, it is read onto buf, up to
9481.130Smgorny * buf_len.  The actual length of the note is returned (which can be greater
9491.130Smgorny * than buf_len, indicating that it has been truncated).  If the note is not
9501.130Smgorny * found, -1 is returned.
9511.172Sthorpej *
9521.172Sthorpej * If the note_name ends in '*', then we find the first note that matches
9531.172Sthorpej * the note_name prefix up to the '*' character, e.g.:
9541.172Sthorpej *
9551.172Sthorpej *	NetBSD-CORE@*
9561.172Sthorpej *
9571.172Sthorpej * finds the first note whose name prefix matches "NetBSD-CORE@".
9581.130Smgorny */
9591.130Smgornystatic ssize_t core_find_note(const char *core_path,
9601.130Smgorny    const char *note_name, uint64_t note_type, void *buf, size_t buf_len)
9611.130Smgorny{
9621.130Smgorny	int core_fd;
9631.130Smgorny	Elf *core_elf;
9641.130Smgorny	size_t core_numhdr, i;
9651.130Smgorny	ssize_t ret = -1;
9661.172Sthorpej	size_t name_len = strlen(note_name);
9671.172Sthorpej	bool prefix_match = false;
9681.172Sthorpej
9691.172Sthorpej	if (note_name[name_len - 1] == '*') {
9701.172Sthorpej		prefix_match = true;
9711.172Sthorpej		name_len--;
9721.172Sthorpej	} else {
9731.172Sthorpej		/* note: we assume note name will be null-terminated */
9741.172Sthorpej		name_len++;
9751.172Sthorpej	}
9761.130Smgorny
9771.130Smgorny	SYSCALL_REQUIRE((core_fd = open(core_path, O_RDONLY)) != -1);
9781.130Smgorny	SYSCALL_REQUIRE(elf_version(EV_CURRENT) != EV_NONE);
9791.130Smgorny	SYSCALL_REQUIRE((core_elf = elf_begin(core_fd, ELF_C_READ, NULL)));
9801.130Smgorny
9811.130Smgorny	SYSCALL_REQUIRE(elf_getphnum(core_elf, &core_numhdr) != 0);
9821.130Smgorny	for (i = 0; i < core_numhdr && ret == -1; i++) {
9831.130Smgorny		GElf_Phdr core_hdr;
9841.130Smgorny		size_t offset;
9851.130Smgorny		SYSCALL_REQUIRE(gelf_getphdr(core_elf, i, &core_hdr));
9861.130Smgorny		if (core_hdr.p_type != PT_NOTE)
9871.130Smgorny		    continue;
9881.130Smgorny
9891.130Smgorny		for (offset = core_hdr.p_offset;
9901.130Smgorny		    offset < core_hdr.p_offset + core_hdr.p_filesz;) {
9911.130Smgorny			Elf64_Nhdr note_hdr;
9921.130Smgorny			char name_buf[64];
9931.130Smgorny
9941.130Smgorny			switch (gelf_getclass(core_elf)) {
9951.130Smgorny			case ELFCLASS64:
9961.130Smgorny				SYSCALL_REQUIRE(pread(core_fd, &note_hdr,
9971.130Smgorny				    sizeof(note_hdr), offset)
9981.130Smgorny				    == sizeof(note_hdr));
9991.130Smgorny				offset += sizeof(note_hdr);
10001.130Smgorny				break;
10011.130Smgorny			case ELFCLASS32:
10021.130Smgorny				{
10031.130Smgorny				Elf32_Nhdr tmp_hdr;
10041.130Smgorny				SYSCALL_REQUIRE(pread(core_fd, &tmp_hdr,
10051.130Smgorny				    sizeof(tmp_hdr), offset)
10061.130Smgorny				    == sizeof(tmp_hdr));
10071.130Smgorny				offset += sizeof(tmp_hdr);
10081.130Smgorny				note_hdr.n_namesz = tmp_hdr.n_namesz;
10091.130Smgorny				note_hdr.n_descsz = tmp_hdr.n_descsz;
10101.130Smgorny				note_hdr.n_type = tmp_hdr.n_type;
10111.130Smgorny				}
10121.130Smgorny				break;
10131.130Smgorny			}
10141.130Smgorny
10151.130Smgorny			/* indicates end of notes */
10161.130Smgorny			if (note_hdr.n_namesz == 0 || note_hdr.n_descsz == 0)
10171.130Smgorny				break;
10181.172Sthorpej			if (((prefix_match &&
10191.172Sthorpej			      note_hdr.n_namesz > name_len) ||
10201.172Sthorpej			     (!prefix_match &&
10211.172Sthorpej			      note_hdr.n_namesz == name_len)) &&
10221.130Smgorny			    note_hdr.n_namesz <= sizeof(name_buf)) {
10231.130Smgorny				SYSCALL_REQUIRE(pread(core_fd, name_buf,
10241.130Smgorny				    note_hdr.n_namesz, offset)
10251.131Skamil				    == (ssize_t)(size_t)note_hdr.n_namesz);
10261.130Smgorny
10271.130Smgorny				if (!strncmp(note_name, name_buf, name_len) &&
10281.130Smgorny				    note_hdr.n_type == note_type)
10291.130Smgorny					ret = note_hdr.n_descsz;
10301.130Smgorny			}
10311.130Smgorny
10321.130Smgorny			offset += note_hdr.n_namesz;
10331.130Smgorny			/* fix to alignment */
10341.146Smgorny			offset = roundup(offset, core_hdr.p_align);
10351.130Smgorny
10361.130Smgorny			/* if name & type matched above */
10371.130Smgorny			if (ret != -1) {
10381.130Smgorny				ssize_t read_len = MIN(buf_len,
10391.130Smgorny				    note_hdr.n_descsz);
10401.130Smgorny				SYSCALL_REQUIRE(pread(core_fd, buf,
10411.130Smgorny				    read_len, offset) == read_len);
10421.130Smgorny				break;
10431.130Smgorny			}
10441.130Smgorny
10451.130Smgorny			offset += note_hdr.n_descsz;
10461.146Smgorny			/* fix to alignment */
10471.146Smgorny			offset = roundup(offset, core_hdr.p_align);
10481.130Smgorny		}
10491.130Smgorny	}
10501.130Smgorny
10511.130Smgorny	elf_end(core_elf);
10521.130Smgorny	close(core_fd);
10531.130Smgorny
10541.130Smgorny	return ret;
10551.130Smgorny}
10561.130Smgorny
10571.130SmgornyATF_TC(core_dump_procinfo);
10581.130SmgornyATF_TC_HEAD(core_dump_procinfo, tc)
10591.130Smgorny{
10601.130Smgorny	atf_tc_set_md_var(tc, "descr",
10611.130Smgorny		"Trigger a core dump and verify its contents.");
10621.130Smgorny}
10631.130Smgorny
10641.130SmgornyATF_TC_BODY(core_dump_procinfo, tc)
10651.130Smgorny{
10661.130Smgorny	const int exitval = 5;
10671.130Smgorny	pid_t child, wpid;
10681.130Smgorny#if defined(TWAIT_HAVE_STATUS)
10691.130Smgorny	const int sigval = SIGTRAP;
10701.130Smgorny	int status;
10711.130Smgorny#endif
10721.130Smgorny	char core_path[] = "/tmp/core.XXXXXX";
10731.130Smgorny	int core_fd;
10741.130Smgorny	struct netbsd_elfcore_procinfo procinfo;
10751.130Smgorny
10761.130Smgorny	DPRINTF("Before forking process PID=%d\n", getpid());
10771.130Smgorny	SYSCALL_REQUIRE((child = fork()) != -1);
10781.130Smgorny	if (child == 0) {
10791.130Smgorny		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
10801.130Smgorny		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
10811.130Smgorny
10821.130Smgorny		DPRINTF("Before triggering SIGTRAP\n");
10831.130Smgorny		trigger_trap();
10841.130Smgorny
10851.130Smgorny		DPRINTF("Before exiting of the child process\n");
10861.130Smgorny		_exit(exitval);
10871.130Smgorny	}
10881.130Smgorny	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
10891.130Smgorny
10901.130Smgorny	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
10911.130Smgorny	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
10921.130Smgorny
10931.130Smgorny	validate_status_stopped(status, sigval);
10941.130Smgorny
10951.130Smgorny	SYSCALL_REQUIRE((core_fd = mkstemp(core_path)) != -1);
10961.130Smgorny	close(core_fd);
10971.130Smgorny
10981.130Smgorny	DPRINTF("Call DUMPCORE for the child process\n");
10991.130Smgorny	SYSCALL_REQUIRE(ptrace(PT_DUMPCORE, child, core_path, strlen(core_path))
11001.130Smgorny	    != -1);
11011.130Smgorny
11021.130Smgorny	DPRINTF("Read core file\n");
11031.130Smgorny	ATF_REQUIRE_EQ(core_find_note(core_path, "NetBSD-CORE",
11041.130Smgorny	    ELF_NOTE_NETBSD_CORE_PROCINFO, &procinfo, sizeof(procinfo)),
11051.130Smgorny	    sizeof(procinfo));
11061.130Smgorny
11071.130Smgorny	ATF_CHECK_EQ(procinfo.cpi_version, 1);
11081.130Smgorny	ATF_CHECK_EQ(procinfo.cpi_cpisize, sizeof(procinfo));
11091.130Smgorny	ATF_CHECK_EQ(procinfo.cpi_signo, SIGTRAP);
11101.130Smgorny	ATF_CHECK_EQ(procinfo.cpi_pid, child);
11111.130Smgorny	ATF_CHECK_EQ(procinfo.cpi_ppid, getpid());
11121.130Smgorny	ATF_CHECK_EQ(procinfo.cpi_pgrp, getpgid(child));
11131.130Smgorny	ATF_CHECK_EQ(procinfo.cpi_sid, getsid(child));
11141.130Smgorny	ATF_CHECK_EQ(procinfo.cpi_ruid, getuid());
11151.130Smgorny	ATF_CHECK_EQ(procinfo.cpi_euid, geteuid());
11161.130Smgorny	ATF_CHECK_EQ(procinfo.cpi_rgid, getgid());
11171.130Smgorny	ATF_CHECK_EQ(procinfo.cpi_egid, getegid());
11181.130Smgorny	ATF_CHECK_EQ(procinfo.cpi_nlwps, 1);
11191.173Skamil	ATF_CHECK(procinfo.cpi_siglwp > 0);
11201.130Smgorny
11211.130Smgorny	unlink(core_path);
11221.130Smgorny
11231.130Smgorny	DPRINTF("Before resuming the child process where it left off and "
11241.130Smgorny	    "without signal to be sent\n");
11251.130Smgorny	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
11261.130Smgorny
11271.130Smgorny	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
11281.130Smgorny	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
11291.130Smgorny
11301.130Smgorny	validate_status_exited(status, exitval);
11311.130Smgorny
11321.130Smgorny	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
11331.130Smgorny	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
11341.130Smgorny}
11351.130Smgorny
11361.130Smgorny/// ----------------------------------------------------------------------------
11371.130Smgorny
11381.138Smgorny#if defined(TWAIT_HAVE_STATUS)
11391.138Smgorny
11401.160Smgorny#define THREAD_CONCURRENT_BREAKPOINT_NUM 50
11411.156Smgorny#define THREAD_CONCURRENT_SIGNALS_NUM 50
11421.161Smgorny#define THREAD_CONCURRENT_WATCHPOINT_NUM 50
11431.138Smgorny
11441.138Smgorny/* List of signals to use for the test */
11451.138Smgornyconst int thread_concurrent_signals_list[] = {
11461.138Smgorny	SIGIO,
11471.138Smgorny	SIGXCPU,
11481.138Smgorny	SIGXFSZ,
11491.138Smgorny	SIGVTALRM,
11501.138Smgorny	SIGPROF,
11511.138Smgorny	SIGWINCH,
11521.138Smgorny	SIGINFO,
11531.138Smgorny	SIGUSR1,
11541.138Smgorny	SIGUSR2
11551.138Smgorny};
11561.138Smgorny
11571.157Smgornyenum thread_concurrent_signal_handling {
11581.157Smgorny	/* the signal is discarded by debugger */
11591.157Smgorny	TCSH_DISCARD,
11601.157Smgorny	/* the handler is set to SIG_IGN */
11611.157Smgorny	TCSH_SIG_IGN,
11621.157Smgorny	/* an actual handler is used */
11631.157Smgorny	TCSH_HANDLER
11641.157Smgorny};
11651.157Smgorny
11661.156Smgornystatic pthread_barrier_t thread_concurrent_barrier;
11671.158Smgornystatic pthread_key_t thread_concurrent_key;
11681.161Smgornystatic uint32_t thread_concurrent_watchpoint_var = 0;
11691.138Smgorny
11701.160Smgornystatic void *
11711.160Smgornythread_concurrent_breakpoint_thread(void *arg)
11721.160Smgorny{
11731.160Smgorny	static volatile int watchme = 1;
11741.160Smgorny	pthread_barrier_wait(&thread_concurrent_barrier);
11751.160Smgorny	DPRINTF("Before entering breakpoint func from LWP %d\n", _lwp_self());
11761.160Smgorny	check_happy(watchme);
11771.160Smgorny	return NULL;
11781.160Smgorny}
11791.160Smgorny
11801.157Smgornystatic void
11811.157Smgornythread_concurrent_sig_handler(int sig)
11821.157Smgorny{
11831.158Smgorny	void *tls_val = pthread_getspecific(thread_concurrent_key);
11841.158Smgorny	DPRINTF("Before increment, LWP %d tls_val=%p\n", _lwp_self(), tls_val);
11851.158Smgorny	FORKEE_ASSERT(pthread_setspecific(thread_concurrent_key,
11861.158Smgorny	    (void*)((uintptr_t)tls_val + 1)) == 0);
11871.157Smgorny}
11881.157Smgorny
11891.138Smgornystatic void *
11901.138Smgornythread_concurrent_signals_thread(void *arg)
11911.138Smgorny{
11921.138Smgorny	int sigval = thread_concurrent_signals_list[
11931.138Smgorny	    _lwp_self() % __arraycount(thread_concurrent_signals_list)];
11941.158Smgorny	enum thread_concurrent_signal_handling *signal_handle = arg;
11951.158Smgorny	void *tls_val;
11961.158Smgorny
11971.156Smgorny	pthread_barrier_wait(&thread_concurrent_barrier);
11981.138Smgorny	DPRINTF("Before raising %s from LWP %d\n", strsignal(sigval),
11991.138Smgorny		_lwp_self());
12001.138Smgorny	pthread_kill(pthread_self(), sigval);
12011.158Smgorny	if (*signal_handle == TCSH_HANDLER) {
12021.158Smgorny	    tls_val = pthread_getspecific(thread_concurrent_key);
12031.158Smgorny	    DPRINTF("After raising, LWP %d tls_val=%p\n", _lwp_self(), tls_val);
12041.158Smgorny	    FORKEE_ASSERT(tls_val == (void*)1);
12051.158Smgorny	}
12061.138Smgorny	return NULL;
12071.138Smgorny}
12081.138Smgorny
12091.161Smgornystatic void *
12101.161Smgornythread_concurrent_watchpoint_thread(void *arg)
12111.161Smgorny{
12121.161Smgorny	pthread_barrier_wait(&thread_concurrent_barrier);
12131.161Smgorny	DPRINTF("Before modifying var from LWP %d\n", _lwp_self());
12141.161Smgorny	thread_concurrent_watchpoint_var = 1;
12151.161Smgorny	return NULL;
12161.161Smgorny}
12171.161Smgorny
12181.160Smgorny#if defined(__i386__) || defined(__x86_64__)
12191.160Smgornyenum thread_concurrent_sigtrap_event {
12201.160Smgorny	TCSE_UNKNOWN,
12211.161Smgorny	TCSE_BREAKPOINT,
12221.161Smgorny	TCSE_WATCHPOINT
12231.160Smgorny};
12241.160Smgorny
12251.160Smgornystatic void
12261.160Smgornythread_concurrent_lwp_setup(pid_t child, lwpid_t lwpid);
12271.160Smgornystatic enum thread_concurrent_sigtrap_event
12281.160Smgornythread_concurrent_handle_sigtrap(pid_t child, ptrace_siginfo_t *info);
12291.160Smgorny#endif
12301.160Smgorny
12311.156Smgornystatic void
12321.157Smgornythread_concurrent_test(enum thread_concurrent_signal_handling signal_handle,
12331.161Smgorny    int breakpoint_threads, int signal_threads, int watchpoint_threads)
12341.138Smgorny{
12351.138Smgorny	const int exitval = 5;
12361.138Smgorny	const int sigval = SIGSTOP;
12371.138Smgorny	pid_t child, wpid;
12381.138Smgorny	int status;
12391.141Skamil	struct lwp_event_count signal_counts[THREAD_CONCURRENT_SIGNALS_NUM]
12401.141Skamil	    = {{0, 0}};
12411.160Smgorny	struct lwp_event_count bp_counts[THREAD_CONCURRENT_BREAKPOINT_NUM]
12421.160Smgorny	    = {{0, 0}};
12431.161Smgorny	struct lwp_event_count wp_counts[THREAD_CONCURRENT_BREAKPOINT_NUM]
12441.161Smgorny	    = {{0, 0}};
12451.159Smgorny	ptrace_event_t event;
12461.156Smgorny	int i;
12471.156Smgorny
12481.164Skamil#if defined(HAVE_DBREGS)
12491.164Skamil	if (!can_we_set_dbregs()) {
12501.164Skamil		atf_tc_skip("Either run this test as root or set sysctl(3) "
12511.164Skamil		            "security.models.extensions.user_set_dbregs to 1");
12521.164Skamil        }
12531.164Skamil#endif
12541.164Skamil
12551.164Skamil	atf_tc_skip("PR kern/54960");
12561.157Smgorny
12571.156Smgorny	/* Protect against out-of-bounds array access. */
12581.160Smgorny	ATF_REQUIRE(breakpoint_threads <= THREAD_CONCURRENT_BREAKPOINT_NUM);
12591.156Smgorny	ATF_REQUIRE(signal_threads <= THREAD_CONCURRENT_SIGNALS_NUM);
12601.161Smgorny	ATF_REQUIRE(watchpoint_threads <= THREAD_CONCURRENT_WATCHPOINT_NUM);
12611.138Smgorny
12621.138Smgorny	DPRINTF("Before forking process PID=%d\n", getpid());
12631.138Smgorny	SYSCALL_REQUIRE((child = fork()) != -1);
12641.138Smgorny	if (child == 0) {
12651.160Smgorny		pthread_t bp_threads[THREAD_CONCURRENT_BREAKPOINT_NUM];
12661.156Smgorny		pthread_t sig_threads[THREAD_CONCURRENT_SIGNALS_NUM];
12671.161Smgorny		pthread_t wp_threads[THREAD_CONCURRENT_WATCHPOINT_NUM];
12681.138Smgorny
12691.138Smgorny		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
12701.138Smgorny		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
12711.138Smgorny
12721.138Smgorny		DPRINTF("Before raising %s from child\n", strsignal(sigval));
12731.138Smgorny		FORKEE_ASSERT(raise(sigval) == 0);
12741.138Smgorny
12751.157Smgorny		if (signal_handle != TCSH_DISCARD) {
12761.157Smgorny			struct sigaction sa;
12771.157Smgorny			unsigned int j;
12781.157Smgorny
12791.157Smgorny			memset(&sa, 0, sizeof(sa));
12801.157Smgorny			if (signal_handle == TCSH_SIG_IGN)
12811.157Smgorny				sa.sa_handler = SIG_IGN;
12821.157Smgorny			else
12831.157Smgorny				sa.sa_handler = thread_concurrent_sig_handler;
12841.157Smgorny			sigemptyset(&sa.sa_mask);
12851.157Smgorny
12861.157Smgorny			for (j = 0;
12871.157Smgorny			    j < __arraycount(thread_concurrent_signals_list);
12881.157Smgorny			    j++)
12891.157Smgorny				FORKEE_ASSERT(sigaction(
12901.157Smgorny				    thread_concurrent_signals_list[j], &sa, NULL)
12911.157Smgorny				    != -1);
12921.157Smgorny		}
12931.157Smgorny
12941.138Smgorny		DPRINTF("Before starting threads from the child\n");
12951.138Smgorny		FORKEE_ASSERT(pthread_barrier_init(
12961.156Smgorny		    &thread_concurrent_barrier, NULL,
12971.161Smgorny		    breakpoint_threads + signal_threads + watchpoint_threads)
12981.161Smgorny		    == 0);
12991.158Smgorny		FORKEE_ASSERT(pthread_key_create(&thread_concurrent_key, NULL)
13001.158Smgorny		    == 0);
13011.138Smgorny
13021.156Smgorny		for (i = 0; i < signal_threads; i++) {
13031.156Smgorny			FORKEE_ASSERT(pthread_create(&sig_threads[i], NULL,
13041.158Smgorny			    thread_concurrent_signals_thread,
13051.158Smgorny			    &signal_handle) == 0);
13061.138Smgorny		}
13071.160Smgorny		for (i = 0; i < breakpoint_threads; i++) {
13081.160Smgorny			FORKEE_ASSERT(pthread_create(&bp_threads[i], NULL,
13091.160Smgorny			    thread_concurrent_breakpoint_thread, NULL) == 0);
13101.160Smgorny		}
13111.161Smgorny		for (i = 0; i < watchpoint_threads; i++) {
13121.161Smgorny			FORKEE_ASSERT(pthread_create(&wp_threads[i], NULL,
13131.161Smgorny			    thread_concurrent_watchpoint_thread, NULL) == 0);
13141.161Smgorny		}
13151.138Smgorny
13161.138Smgorny		DPRINTF("Before joining threads from the child\n");
13171.161Smgorny		for (i = 0; i < watchpoint_threads; i++) {
13181.161Smgorny			FORKEE_ASSERT(pthread_join(wp_threads[i], NULL) == 0);
13191.161Smgorny		}
13201.160Smgorny		for (i = 0; i < breakpoint_threads; i++) {
13211.160Smgorny			FORKEE_ASSERT(pthread_join(bp_threads[i], NULL) == 0);
13221.160Smgorny		}
13231.156Smgorny		for (i = 0; i < signal_threads; i++) {
13241.156Smgorny			FORKEE_ASSERT(pthread_join(sig_threads[i], NULL) == 0);
13251.138Smgorny		}
13261.138Smgorny
13271.158Smgorny		FORKEE_ASSERT(pthread_key_delete(thread_concurrent_key) == 0);
13281.138Smgorny		FORKEE_ASSERT(pthread_barrier_destroy(
13291.156Smgorny		    &thread_concurrent_barrier) == 0);
13301.138Smgorny
13311.138Smgorny		DPRINTF("Before exiting of the child process\n");
13321.138Smgorny		_exit(exitval);
13331.138Smgorny	}
13341.138Smgorny	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
13351.138Smgorny
13361.138Smgorny	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
13371.138Smgorny	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
13381.138Smgorny
13391.138Smgorny	validate_status_stopped(status, sigval);
13401.138Smgorny
13411.159Smgorny	DPRINTF("Set LWP event mask for the child process\n");
13421.159Smgorny	memset(&event, 0, sizeof(event));
13431.159Smgorny	event.pe_set_event |= PTRACE_LWP_CREATE;
13441.159Smgorny	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, sizeof(event))
13451.159Smgorny	    != -1);
13461.159Smgorny
13471.138Smgorny	DPRINTF("Before resuming the child process where it left off\n");
13481.138Smgorny	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
13491.138Smgorny
13501.138Smgorny	DPRINTF("Before entering signal collection loop\n");
13511.138Smgorny	while (1) {
13521.138Smgorny		ptrace_siginfo_t info;
13531.138Smgorny
13541.138Smgorny		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
13551.138Smgorny		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
13561.138Smgorny		    child);
13571.138Smgorny		if (WIFEXITED(status))
13581.138Smgorny			break;
13591.138Smgorny		/* Note: we use validate_status_stopped() to get nice error
13601.138Smgorny		 * message.  Signal is irrelevant since it won't be reached.
13611.138Smgorny		 */
13621.138Smgorny		else if (!WIFSTOPPED(status))
13631.138Smgorny			validate_status_stopped(status, 0);
13641.138Smgorny
13651.138Smgorny		DPRINTF("Before calling PT_GET_SIGINFO\n");
13661.138Smgorny		SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
13671.138Smgorny		    sizeof(info)) != -1);
13681.138Smgorny
13691.138Smgorny		DPRINTF("Received signal %d from LWP %d (wait: %d)\n",
13701.138Smgorny		    info.psi_siginfo.si_signo, info.psi_lwpid,
13711.138Smgorny		    WSTOPSIG(status));
13721.138Smgorny
13731.159Smgorny		ATF_CHECK_EQ_MSG(info.psi_siginfo.si_signo, WSTOPSIG(status),
13741.159Smgorny		    "lwp=%d, WSTOPSIG=%d, psi_siginfo=%d", info.psi_lwpid,
13751.159Smgorny		    WSTOPSIG(status), info.psi_siginfo.si_signo);
13761.159Smgorny
13771.159Smgorny		if (WSTOPSIG(status) != SIGTRAP) {
13781.159Smgorny			int expected_sig =
13791.159Smgorny			    thread_concurrent_signals_list[info.psi_lwpid %
13801.159Smgorny			    __arraycount(thread_concurrent_signals_list)];
13811.159Smgorny			ATF_CHECK_EQ_MSG(WSTOPSIG(status), expected_sig,
13821.159Smgorny				"lwp=%d, expected %d, got %d", info.psi_lwpid,
13831.159Smgorny				expected_sig, WSTOPSIG(status));
13841.138Smgorny
13851.159Smgorny			*FIND_EVENT_COUNT(signal_counts, info.psi_lwpid) += 1;
13861.160Smgorny		} else if (info.psi_siginfo.si_code == TRAP_LWP) {
13871.160Smgorny#if defined(__i386__) || defined(__x86_64__)
13881.160Smgorny			thread_concurrent_lwp_setup(child, info.psi_lwpid);
13891.160Smgorny#endif
13901.159Smgorny		} else {
13911.160Smgorny#if defined(__i386__) || defined(__x86_64__)
13921.160Smgorny			switch (thread_concurrent_handle_sigtrap(child, &info)) {
13931.160Smgorny				case TCSE_UNKNOWN:
13941.160Smgorny					/* already reported inside the function */
13951.160Smgorny					break;
13961.160Smgorny				case TCSE_BREAKPOINT:
13971.160Smgorny					*FIND_EVENT_COUNT(bp_counts,
13981.160Smgorny					    info.psi_lwpid) += 1;
13991.160Smgorny					break;
14001.161Smgorny				case TCSE_WATCHPOINT:
14011.161Smgorny					*FIND_EVENT_COUNT(wp_counts,
14021.161Smgorny					    info.psi_lwpid) += 1;
14031.161Smgorny					break;
14041.160Smgorny			}
14051.160Smgorny#else
14061.160Smgorny			ATF_CHECK_MSG(0, "Unexpected SIGTRAP, si_code=%d\n",
14071.160Smgorny			    info.psi_siginfo.si_code);
14081.160Smgorny#endif
14091.159Smgorny		}
14101.138Smgorny
14111.138Smgorny		DPRINTF("Before resuming the child process\n");
14121.157Smgorny		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1,
14131.159Smgorny		     signal_handle != TCSH_DISCARD && WSTOPSIG(status) != SIGTRAP
14141.159Smgorny		     ? WSTOPSIG(status) : 0) != -1);
14151.138Smgorny	}
14161.138Smgorny
14171.156Smgorny	for (i = 0; i < signal_threads; i++)
14181.141Skamil		ATF_CHECK_EQ_MSG(signal_counts[i].lec_count, 1,
14191.141Skamil		    "signal_counts[%d].lec_count=%d; lec_lwp=%d",
14201.141Skamil		    i, signal_counts[i].lec_count, signal_counts[i].lec_lwp);
14211.156Smgorny	for (i = signal_threads; i < THREAD_CONCURRENT_SIGNALS_NUM; i++)
14221.156Smgorny		ATF_CHECK_EQ_MSG(signal_counts[i].lec_count, 0,
14231.156Smgorny		    "extraneous signal_counts[%d].lec_count=%d; lec_lwp=%d",
14241.156Smgorny		    i, signal_counts[i].lec_count, signal_counts[i].lec_lwp);
14251.138Smgorny
14261.160Smgorny	for (i = 0; i < breakpoint_threads; i++)
14271.160Smgorny		ATF_CHECK_EQ_MSG(bp_counts[i].lec_count, 1,
14281.160Smgorny		    "bp_counts[%d].lec_count=%d; lec_lwp=%d",
14291.160Smgorny		    i, bp_counts[i].lec_count, bp_counts[i].lec_lwp);
14301.160Smgorny	for (i = breakpoint_threads; i < THREAD_CONCURRENT_BREAKPOINT_NUM; i++)
14311.160Smgorny		ATF_CHECK_EQ_MSG(bp_counts[i].lec_count, 0,
14321.160Smgorny		    "extraneous bp_counts[%d].lec_count=%d; lec_lwp=%d",
14331.160Smgorny		    i, bp_counts[i].lec_count, bp_counts[i].lec_lwp);
14341.160Smgorny
14351.161Smgorny	for (i = 0; i < watchpoint_threads; i++)
14361.161Smgorny		ATF_CHECK_EQ_MSG(wp_counts[i].lec_count, 1,
14371.161Smgorny		    "wp_counts[%d].lec_count=%d; lec_lwp=%d",
14381.161Smgorny		    i, wp_counts[i].lec_count, wp_counts[i].lec_lwp);
14391.161Smgorny	for (i = watchpoint_threads; i < THREAD_CONCURRENT_WATCHPOINT_NUM; i++)
14401.161Smgorny		ATF_CHECK_EQ_MSG(wp_counts[i].lec_count, 0,
14411.161Smgorny		    "extraneous wp_counts[%d].lec_count=%d; lec_lwp=%d",
14421.161Smgorny		    i, wp_counts[i].lec_count, wp_counts[i].lec_lwp);
14431.161Smgorny
14441.138Smgorny	validate_status_exited(status, exitval);
14451.138Smgorny}
14461.138Smgorny
14471.161Smgorny#define THREAD_CONCURRENT_TEST(test, sig_hdl, bps, sigs, wps, descr)	\
14481.156SmgornyATF_TC(test);								\
14491.156SmgornyATF_TC_HEAD(test, tc)							\
14501.156Smgorny{									\
14511.156Smgorny	atf_tc_set_md_var(tc, "descr", descr);				\
14521.156Smgorny}									\
14531.156Smgorny									\
14541.156SmgornyATF_TC_BODY(test, tc)							\
14551.156Smgorny{									\
14561.161Smgorny	thread_concurrent_test(sig_hdl, bps, sigs, wps);		\
14571.156Smgorny}
14581.156Smgorny
14591.157SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_signals, TCSH_DISCARD,
14601.161Smgorny    0, THREAD_CONCURRENT_SIGNALS_NUM, 0,
14611.157Smgorny    "Verify that concurrent signals issued to a single thread are reported "
14621.157Smgorny    "correctly");
14631.157SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_signals_sig_ign, TCSH_SIG_IGN,
14641.161Smgorny    0, THREAD_CONCURRENT_SIGNALS_NUM, 0,
14651.157Smgorny    "Verify that concurrent signals issued to a single thread are reported "
14661.157Smgorny    "correctly and passed back to SIG_IGN handler");
14671.157SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_signals_handler, TCSH_HANDLER,
14681.161Smgorny    0, THREAD_CONCURRENT_SIGNALS_NUM, 0,
14691.157Smgorny    "Verify that concurrent signals issued to a single thread are reported "
14701.157Smgorny    "correctly and passed back to a handler function");
14711.156Smgorny
14721.163Skamil#if defined(__i386__) || defined(__x86_64__)
14731.160SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_breakpoints, TCSH_DISCARD,
14741.161Smgorny    THREAD_CONCURRENT_BREAKPOINT_NUM, 0, 0,
14751.161Smgorny    "Verify that concurrent breakpoints are reported correctly");
14761.161SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_watchpoints, TCSH_DISCARD,
14771.161Smgorny    0, 0, THREAD_CONCURRENT_WATCHPOINT_NUM,
14781.160Smgorny    "Verify that concurrent breakpoints are reported correctly");
14791.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_bp_wp, TCSH_DISCARD,
14801.162Smgorny    THREAD_CONCURRENT_BREAKPOINT_NUM, 0, THREAD_CONCURRENT_WATCHPOINT_NUM,
14811.162Smgorny    "Verify that concurrent breakpoints and watchpoints are reported "
14821.162Smgorny    "correctly");
14831.162Smgorny
14841.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_bp_sig, TCSH_DISCARD,
14851.162Smgorny    THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM, 0,
14861.162Smgorny    "Verify that concurrent breakpoints and signals are reported correctly");
14871.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_bp_sig_sig_ign, TCSH_SIG_IGN,
14881.162Smgorny    THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM, 0,
14891.162Smgorny    "Verify that concurrent breakpoints and signals are reported correctly "
14901.162Smgorny    "and passed back to SIG_IGN handler");
14911.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_bp_sig_handler, TCSH_HANDLER,
14921.162Smgorny    THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM, 0,
14931.162Smgorny    "Verify that concurrent breakpoints and signals are reported correctly "
14941.162Smgorny    "and passed back to a handler function");
14951.162Smgorny
14961.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_wp_sig, TCSH_DISCARD,
14971.162Smgorny    0, THREAD_CONCURRENT_SIGNALS_NUM, THREAD_CONCURRENT_WATCHPOINT_NUM,
14981.162Smgorny    "Verify that concurrent watchpoints and signals are reported correctly");
14991.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_wp_sig_sig_ign, TCSH_SIG_IGN,
15001.162Smgorny    0, THREAD_CONCURRENT_SIGNALS_NUM, THREAD_CONCURRENT_WATCHPOINT_NUM,
15011.162Smgorny    "Verify that concurrent watchpoints and signals are reported correctly "
15021.162Smgorny    "and passed back to SIG_IGN handler");
15031.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_wp_sig_handler, TCSH_HANDLER,
15041.162Smgorny    0, THREAD_CONCURRENT_SIGNALS_NUM, THREAD_CONCURRENT_WATCHPOINT_NUM,
15051.162Smgorny    "Verify that concurrent watchpoints and signals are reported correctly "
15061.162Smgorny    "and passed back to a handler function");
15071.162Smgorny
15081.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_bp_wp_sig, TCSH_DISCARD,
15091.162Smgorny    THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM,
15101.162Smgorny    THREAD_CONCURRENT_WATCHPOINT_NUM,
15111.162Smgorny    "Verify that concurrent breakpoints, watchpoints and signals are reported "
15121.162Smgorny    "correctly");
15131.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_bp_wp_sig_sig_ign, TCSH_SIG_IGN,
15141.162Smgorny    THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM,
15151.162Smgorny    THREAD_CONCURRENT_WATCHPOINT_NUM,
15161.162Smgorny    "Verify that concurrent breakpoints, watchpoints and signals are reported "
15171.162Smgorny    "correctly and passed back to SIG_IGN handler");
15181.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_bp_wp_sig_handler, TCSH_HANDLER,
15191.162Smgorny    THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM,
15201.162Smgorny    THREAD_CONCURRENT_WATCHPOINT_NUM,
15211.162Smgorny    "Verify that concurrent breakpoints, watchpoints and signals are reported "
15221.162Smgorny    "correctly and passed back to a handler function");
15231.163Skamil#endif
15241.160Smgorny
15251.138Smgorny#endif /*defined(TWAIT_HAVE_STATUS)*/
15261.138Smgorny
15271.138Smgorny/// ----------------------------------------------------------------------------
15281.138Smgorny
15291.174Skamil#include "t_ptrace_register_wait.h"
15301.175Skamil#include "t_ptrace_syscall_wait.h"
15311.176Skamil#include "t_ptrace_step_wait.h"
15321.177Skamil#include "t_ptrace_kill_wait.h"
15331.178Skamil#include "t_ptrace_bytetransfer_wait.h"
15341.179Skamil#include "t_ptrace_clone_wait.h"
15351.180Skamil#include "t_ptrace_fork_wait.h"
15361.181Skamil#include "t_ptrace_signal_wait.h"
15371.183Skamil#include "t_ptrace_eventmask_wait.h"
15381.185Skamil#include "t_ptrace_lwp_wait.h"
15391.186Skamil#include "t_ptrace_exec_wait.h"
15401.187Skamil#include "t_ptrace_topology_wait.h"
15411.174Skamil
15421.174Skamil/// ----------------------------------------------------------------------------
15431.174Skamil
15441.1Skamil#include "t_ptrace_amd64_wait.h"
15451.1Skamil#include "t_ptrace_i386_wait.h"
15461.1Skamil#include "t_ptrace_x86_wait.h"
15471.1Skamil
15481.165Skamil/// ----------------------------------------------------------------------------
15491.165Skamil
15501.165Skamil#else
15511.165SkamilATF_TC(dummy);
15521.165SkamilATF_TC_HEAD(dummy, tc)
15531.165Skamil{
15541.165Skamil	atf_tc_set_md_var(tc, "descr", "A dummy test");
15551.165Skamil}
15561.165Skamil
15571.165SkamilATF_TC_BODY(dummy, tc)
15581.165Skamil{
15591.165Skamil
15601.165Skamil	// Dummy, skipped
15611.165Skamil	// The ATF framework requires at least a single defined test.
15621.165Skamil}
15631.165Skamil#endif
15641.165Skamil
15651.1SkamilATF_TP_ADD_TCS(tp)
15661.1Skamil{
15671.1Skamil	setvbuf(stdout, NULL, _IONBF, 0);
15681.1Skamil	setvbuf(stderr, NULL, _IONBF, 0);
15691.33Skamil
15701.165Skamil#ifdef ENABLE_TESTS
15711.79Skamil	ATF_TP_ADD_TC(tp, siginfo_set_unmodified);
15721.79Skamil	ATF_TP_ADD_TC(tp, siginfo_set_faked);
15731.79Skamil
15741.119Skamil	ATF_TP_ADD_TC(tp, trace_thread_nolwpevents);
15751.119Skamil	ATF_TP_ADD_TC(tp, trace_thread_lwpexit);
15761.119Skamil	ATF_TP_ADD_TC(tp, trace_thread_lwpcreate);
15771.119Skamil	ATF_TP_ADD_TC(tp, trace_thread_lwpcreate_and_exit);
15781.1Skamil
15791.153Skamil	ATF_TP_ADD_TC(tp, trace_thread_lwpexit_masked_sigtrap);
15801.153Skamil	ATF_TP_ADD_TC(tp, trace_thread_lwpcreate_masked_sigtrap);
15811.153Skamil	ATF_TP_ADD_TC(tp, trace_thread_lwpcreate_and_exit_masked_sigtrap);
15821.153Skamil
15831.151Skamil	ATF_TP_ADD_TC(tp, threads_and_exec);
15841.151Skamil
15851.154Skamil	ATF_TP_ADD_TC(tp, suspend_no_deadlock);
15861.1Skamil
15871.155Skamil	ATF_TP_ADD_TC(tp, resume);
15881.1Skamil
15891.122Skamil	ATF_TP_ADD_TC(tp, user_va0_disable_pt_continue);
15901.122Skamil	ATF_TP_ADD_TC(tp, user_va0_disable_pt_syscall);
15911.122Skamil	ATF_TP_ADD_TC(tp, user_va0_disable_pt_detach);
15921.122Skamil
15931.130Smgorny	ATF_TP_ADD_TC(tp, core_dump_procinfo);
15941.130Smgorny
15951.138Smgorny#if defined(TWAIT_HAVE_STATUS)
15961.138Smgorny	ATF_TP_ADD_TC(tp, thread_concurrent_signals);
15971.157Smgorny	ATF_TP_ADD_TC(tp, thread_concurrent_signals_sig_ign);
15981.157Smgorny	ATF_TP_ADD_TC(tp, thread_concurrent_signals_handler);
15991.160Smgorny#if defined(__i386__) || defined(__x86_64__)
16001.160Smgorny	ATF_TP_ADD_TC(tp, thread_concurrent_breakpoints);
16011.161Smgorny	ATF_TP_ADD_TC(tp, thread_concurrent_watchpoints);
16021.162Smgorny	ATF_TP_ADD_TC(tp, thread_concurrent_bp_wp);
16031.162Smgorny	ATF_TP_ADD_TC(tp, thread_concurrent_bp_sig);
16041.162Smgorny	ATF_TP_ADD_TC(tp, thread_concurrent_bp_sig_sig_ign);
16051.162Smgorny	ATF_TP_ADD_TC(tp, thread_concurrent_bp_sig_handler);
16061.162Smgorny	ATF_TP_ADD_TC(tp, thread_concurrent_wp_sig);
16071.162Smgorny	ATF_TP_ADD_TC(tp, thread_concurrent_wp_sig_sig_ign);
16081.162Smgorny	ATF_TP_ADD_TC(tp, thread_concurrent_wp_sig_handler);
16091.162Smgorny	ATF_TP_ADD_TC(tp, thread_concurrent_bp_wp_sig);
16101.162Smgorny	ATF_TP_ADD_TC(tp, thread_concurrent_bp_wp_sig_sig_ign);
16111.162Smgorny	ATF_TP_ADD_TC(tp, thread_concurrent_bp_wp_sig_handler);
16121.160Smgorny#endif
16131.138Smgorny#endif
16141.138Smgorny
16151.174Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_REGISTER();
16161.175Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_SYSCALL();
16171.176Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_STEP();
16181.177Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_KILL();
16191.178Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_BYTETRANSFER();
16201.179Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_CLONE();
16211.180Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_FORK();
16221.181Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_SIGNAL();
16231.183Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_EVENTMASK();
16241.185Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_LWP();
16251.186Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_EXEC();
16261.187Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_TOPOLOGY();
16271.174Skamil
16281.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64();
16291.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_I386();
16301.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_X86();
16311.1Skamil
16321.165Skamil#else
16331.165Skamil	ATF_TP_ADD_TC(tp, dummy);
16341.165Skamil#endif
16351.165Skamil
16361.1Skamil	return atf_no_error();
16371.1Skamil}
1638