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, ¬e_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