commit 4d1399710ff8af5f342c053185e5a93fb280156f Author: Kamil Rytarowski Date: Sat Dec 7 05:31:01 2019 +0100 fix diff --git a/external/gpl3/gdb/dist/gdb/nbsd-nat.c b/external/gpl3/gdb/dist/gdb/nbsd-nat.c index e7a2da1134b3..775ea0a15d82 100644 --- a/external/gpl3/gdb/dist/gdb/nbsd-nat.c +++ b/external/gpl3/gdb/dist/gdb/nbsd-nat.c @@ -145,10 +145,10 @@ nbsd_nat_target::thread_alive (ptid_t ptid) { if (ptid.lwp_p ()) { - struct ptrace_lwpinfo pl; + struct ptrace_lwpstatus pl; pl.pl_lwpid = ptid.lwp (); - if (ptrace (PT_LWPINFO, ptid.pid (), (caddr_t) &pl, sizeof pl) + if (ptrace (PT_LWPSTATUS, ptid.pid (), (caddr_t) &pl, sizeof pl) == -1) return 0; } @@ -255,10 +255,10 @@ static void nbsd_add_threads (pid_t pid) { int val; - struct ptrace_lwpinfo pl; + struct ptrace_lwpstatus pl; pl.pl_lwpid = 0; - while ((val = ptrace (PT_LWPINFO, pid, (void *)&pl, sizeof(pl))) != -1 + while ((val = ptrace (PT_LWPNEXT, pid, (void *)&pl, sizeof(pl))) != -1 && pl.pl_lwpid != 0) { ptid_t ptid = ptid_t (pid, pl.pl_lwpid, 0); diff --git a/sys/arch/alpha/include/ptrace.h b/sys/arch/alpha/include/ptrace.h index e7a4aee2c239..0f41f57143b9 100644 --- a/sys/arch/alpha/include/ptrace.h +++ b/sys/arch/alpha/include/ptrace.h @@ -56,3 +56,7 @@ #define PTRACE_BREAKPOINT ((const uint8_t[]) { 0x80, 0x00, 0x00, 0x00 }) #define PTRACE_BREAKPOINT_ASM __asm __volatile("bpt" ::: "memory") #define PTRACE_BREAKPOINT_SIZE 4 + +#ifdef _KERNEL +#define PTRACE_LWP_GETPRIVATE(l) ((struct pcb *)lwp_getpcb(l))->pcb_hw.apcb_unique +#endif diff --git a/sys/arch/amd64/conf/GENERIC b/sys/arch/amd64/conf/GENERIC index 48b0d2482597..e314235e4531 100644 --- a/sys/arch/amd64/conf/GENERIC +++ b/sys/arch/amd64/conf/GENERIC @@ -104,7 +104,7 @@ options DIAGNOSTIC # inexpensive kernel consistency checks # Because gcc omits the frame pointer for any -O level, the line below # is needed to make backtraces in DDB work. # -makeoptions COPTS="-O2 -fno-omit-frame-pointer" +makeoptions COPTS="-O0 -fno-inline -fno-omit-frame-pointer" options DDB # in-kernel debugger #options DDB_COMMANDONENTER="bt" # execute command when ddb is entered #options DDB_ONPANIC=1 # see also sysctl(7): `ddb.onpanic' diff --git a/sys/arch/hppa/include/ptrace.h b/sys/arch/hppa/include/ptrace.h index 4b59e76a489b..b9933b31f533 100644 --- a/sys/arch/hppa/include/ptrace.h +++ b/sys/arch/hppa/include/ptrace.h @@ -61,3 +61,7 @@ #define PTRACE_BREAKPOINT ((const uint8_t[]) { 0x00, 0x01, 0x00, 0x04 }) #define PTRACE_BREAKPOINT_ASM __asm __volatile("break %0, %1" :: "i" (HPPA_BREAK_KERNEL), "i" (HPPA_BREAK_SS) : "memory") #define PTRACE_BREAKPOINT_SIZE 4 + +#ifdef _KERNEL +#define PTRACE_LWP_GETPRIVATE(l) (l)->l_md.md_regs->tf_cr27 +#endif diff --git a/sys/arch/powerpc/include/ptrace.h b/sys/arch/powerpc/include/ptrace.h index 5098572f1a20..8711f775563f 100644 --- a/sys/arch/powerpc/include/ptrace.h +++ b/sys/arch/powerpc/include/ptrace.h @@ -77,4 +77,8 @@ int procfs_machdep_validvecregs(struct lwp *, struct mount *); #define PTRACE_BREAKPOINT_ASM __asm __volatile("trap") #define PTRACE_BREAKPOINT_SIZE 4 +#ifdef _KERNEL +#define PTRACE_LWP_GETPRIVATE(l) (l)->l_md.md_utf->tf_fixreg[_REG_R2] +#endif + #endif /* _POWERPC_PTRACE_H */ diff --git a/sys/arch/sh3/include/ptrace.h b/sys/arch/sh3/include/ptrace.h index c3cae6d9f5d4..4f6e0958972a 100644 --- a/sys/arch/sh3/include/ptrace.h +++ b/sys/arch/sh3/include/ptrace.h @@ -98,5 +98,6 @@ int ptrace_machdep_dorequest(struct lwp *, struct lwp *, int, void *, int); #endif +#define PTRACE_LWP_GETPRIVATE(l) (l)->l_md.md_regs->tf_gbr #endif /* _KERNEL */ #endif /* !_SH3_PTRACE_H_ */ diff --git a/sys/arch/sparc/include/ptrace.h b/sys/arch/sparc/include/ptrace.h index 53ece3851760..85ca3084a161 100644 --- a/sys/arch/sparc/include/ptrace.h +++ b/sys/arch/sparc/include/ptrace.h @@ -69,3 +69,7 @@ #define PTRACE_BREAKPOINT ((const uint8_t[]) { 0x91, 0xd0, 0x20, 0x01 }) #define PTRACE_BREAKPOINT_ASM __asm __volatile("ta 1") #define PTRACE_BREAKPOINT_SIZE 4 + +#ifdef _KERNEL +#define PTRACE_LWP_GETPRIVATE(l) (l)->l_md.md_tf->tf_global[7] +#endif diff --git a/sys/compat/netbsd32/netbsd32.h b/sys/compat/netbsd32/netbsd32.h index b78504f63198..260ac999ab54 100644 --- a/sys/compat/netbsd32/netbsd32.h +++ b/sys/compat/netbsd32/netbsd32.h @@ -39,6 +39,7 @@ #include /* precautionary upon removal from ucred.h */ #include #include +#include #include #include #include @@ -331,6 +332,14 @@ struct netbsd32_ptrace_siginfo { * (route signal to all LWPs) */ }; +struct netbsd32_ptrace_lwpstatus { + lwpid_t pl_lwpid; + sigset_t pl_sigpend; + sigset_t pl_sigmask; + char pl_name[PL_LNAMELEN]; + netbsd32_voidp pl_private; +}; + /* from */ typedef netbsd32_pointer_t netbsd32_quotactlargsp_t; struct netbsd32_quotactlargs { diff --git a/sys/compat/netbsd32/netbsd32_ptrace.c b/sys/compat/netbsd32/netbsd32_ptrace.c index 1741b852051c..623bf2cb9498 100644 --- a/sys/compat/netbsd32/netbsd32_ptrace.c +++ b/sys/compat/netbsd32/netbsd32_ptrace.c @@ -118,6 +118,23 @@ netbsd32_copyout_siginfo(const struct ptrace_siginfo *psi, void *addr, size_t le return copyout(&psi32, addr, sizeof(psi32)); } +static int +netbsd32_copyout_lwpstatus(const struct ptrace_lwpstatus *pls, void *addr, size_t len) +{ + struct netbsd32_ptrace_lwpstatus pls32; + + if (len > sizeof(pls32)) + return EINVAL; + + pls32.pl_lwpid = pls->pl_lwpid; + pls32.pl_sigpend = pls->pl_sigpend; + pls32.pl_sigmask = pls->pl_sigmask; + memcpy(&pls32.pl_name, &pls->pl_name, PL_LNAMELEN); + NETBSD32PTR32(pls32.pl_private, pls->pl_private); + + return copyout(&pls32, addr, MIN(len, sizeof(pls32))); +} + static int netbsd32_doregs(struct lwp *curl /*tracer*/, struct lwp *l /*traced*/, @@ -237,6 +254,7 @@ static struct ptrace_methods netbsd32_ptm = { .ptm_copyout_piod = netbsd32_copyout_piod, .ptm_copyin_siginfo = netbsd32_copyin_siginfo, .ptm_copyout_siginfo = netbsd32_copyout_siginfo, + .ptm_copyout_lwpstatus = netbsd32_copyout_lwpstatus, .ptm_doregs = netbsd32_doregs, .ptm_dofpregs = netbsd32_dofpregs, .ptm_dodbregs = netbsd32_dodbregs diff --git a/sys/kern/core_elf32.c b/sys/kern/core_elf32.c index 7db43d0cc10b..62fca12ba458 100644 --- a/sys/kern/core_elf32.c +++ b/sys/kern/core_elf32.c @@ -369,8 +369,6 @@ coredump_note_procinfo(struct lwp *l, struct note_state *ns) { struct proc *p; struct netbsd_elfcore_procinfo cpi; - struct lwp *l0; - sigset_t ss1, ss2; p = l->l_proc; @@ -382,16 +380,16 @@ coredump_note_procinfo(struct lwp *l, struct note_state *ns) cpi.cpi_siglwp = p->p_sigctx.ps_lwp; /* - * XXX This should be per-LWP. + * per-LWP pending signals are stored in PT_LWPSTATUS@nnn. */ - ss1 = p->p_sigpend.sp_set; - sigemptyset(&ss2); - LIST_FOREACH(l0, &p->p_lwps, l_sibling) { - sigplusset(&l0->l_sigpend.sp_set, &ss1); - sigplusset(&l0->l_sigmask, &ss2); - } - memcpy(&cpi.cpi_sigpend, &ss1, sizeof(cpi.cpi_sigpend)); - memcpy(&cpi.cpi_sigmask, &ss2, sizeof(cpi.cpi_sigmask)); + memcpy(&cpi.cpi_sigpend, &p->p_sigpend.sp_set, sizeof(cpi.cpi_sigpend)); + + /* + * Signal mask is stored on a per-LWP basis in PT_LWPSTATUS@nnn. + * For compatibility purposes, cpi_sigmask is present, but zeroed. + */ + memset(&cpi.cpi_sigmask, 0, sizeof(cpi.cpi_sigmask)); + memcpy(&cpi.cpi_sigignore, &p->p_sigctx.ps_sigignore, sizeof(cpi.cpi_sigignore)); memcpy(&cpi.cpi_sigcatch, &p->p_sigctx.ps_sigcatch, diff --git a/sys/kern/sys_ptrace.c b/sys/kern/sys_ptrace.c index 8515b6f4cd14..d3e2fd7015a5 100644 --- a/sys/kern/sys_ptrace.c +++ b/sys/kern/sys_ptrace.c @@ -185,11 +185,20 @@ ptrace_copyout_siginfo(const struct ptrace_siginfo *psi, void *addr, size_t len) return copyout(psi, addr, sizeof(*psi)); } +static int +ptrace_copyout_lwpstatus(const struct ptrace_lwpstatus *pls, void *addr, + size_t len) +{ + + return copyout(pls, addr, len); +} + static struct ptrace_methods native_ptm = { .ptm_copyin_piod = ptrace_copyin_piod, .ptm_copyout_piod = ptrace_copyout_piod, .ptm_copyin_siginfo = ptrace_copyin_siginfo, .ptm_copyout_siginfo = ptrace_copyout_siginfo, + .ptm_copyout_lwpstatus = ptrace_copyout_lwpstatus, .ptm_doregs = process_doregs, .ptm_dofpregs = process_dofpregs, .ptm_dodbregs = process_dodbregs, diff --git a/sys/kern/sys_ptrace_common.c b/sys/kern/sys_ptrace_common.c index d5d83bba51a1..cd388d299bcb 100644 --- a/sys/kern/sys_ptrace_common.c +++ b/sys/kern/sys_ptrace_common.c @@ -288,6 +288,8 @@ ptrace_listener_cb(kauth_cred_t cred, kauth_action_t action, void *cookie, case PT_RESUME: case PT_SUSPEND: case PT_STOP: + case PT_LWPSTATUS: + case PT_LWPNEXT: result = KAUTH_RESULT_ALLOW; break; @@ -496,6 +498,8 @@ ptrace_allowed(struct lwp *l, int req, struct proc *t, struct proc *p, case PT_RESUME: case PT_SUSPEND: case PT_STOP: + case PT_LWPSTATUS: + case PT_LWPNEXT: /* * You can't do what you want to the process if: * (1) It's not being traced at all, @@ -786,6 +790,86 @@ ptrace_lwpinfo(struct proc *t, struct lwp **lt, void *addr, size_t data) return copyout(&pl, addr, sizeof(pl)); } +static int +ptrace_lwpstatus(struct proc *t, struct ptrace_methods *ptm, struct lwp **lt, + void *addr, size_t data, bool next) +{ + struct ptrace_lwpstatus pls; + struct lwp *l; + int error; + + if (data > sizeof(pls) || data < sizeof(lwpid_t)) { + DPRINTF(("%s: invalid data: %zu < %zu < %zu\n", + __func__, sizeof(lwpid_t), data, sizeof(pls))); + return EINVAL; + } + error = copyin(addr, &pls, sizeof(lwpid_t)); + if (error) + return error; + + if (next) { + lwp_delref(*lt); + lwpid_t tmp = pls.pl_lwpid; + mutex_enter(t->p_lock); + if (tmp == 0) + *lt = lwp_find_first(t); + else { + *lt = lwp_find(t, tmp); + if (*lt == NULL) { + mutex_exit(t->p_lock); + return ESRCH; + } + *lt = LIST_NEXT(*lt, l_sibling); + } + + while (*lt != NULL && !lwp_alive(*lt) && + ((*lt)->l_flag & LW_SYSTEM) != 0) + *lt = LIST_NEXT(*lt, l_sibling); + + if (*lt == NULL) { + memset(&pls, 0, sizeof(pls)); + mutex_exit(t->p_lock); + goto out; + } + lwp_addref(*lt); + mutex_exit(t->p_lock); + + pls.pl_lwpid = (*lt)->l_lid; + } else { + if ((error = ptrace_update_lwp(t, lt, pls.pl_lwpid)) != 0) + return error; + } + + l = *lt; + + memcpy(&pls.pl_sigmask, &l->l_sigmask, sizeof(pls.pl_sigmask)); + memcpy(&pls.pl_sigpend, &l->l_sigpend.sp_set, sizeof(pls.pl_sigpend)); + + if (l->l_name == NULL) + memset(&pls.pl_name, 0, PL_LNAMELEN); + else { + KASSERT(strlen(l->l_name) < PL_LNAMELEN); + strncpy(pls.pl_name, l->l_name, PL_LNAMELEN); + } + +#ifdef PTRACE_LWP_GETPRIVATE + pls.pl_private = PTRACE_LWP_GETPRIVATE(l); +#else + pls.pl_private = l->l_private; +#endif + +out: + DPRINTF(("%s: lwp=%d sigpend=%02x%02x%02x%02x sigmask=%02x%02x%02x%02x " + "name='%s' private=%p\n", __func__, pls.pl_lwpid, + pls.pl_sigpend.__bits[0], pls.pl_sigpend.__bits[1], + pls.pl_sigpend.__bits[2], pls.pl_sigpend.__bits[3], + pls.pl_sigmask.__bits[0], pls.pl_sigmask.__bits[1], + pls.pl_sigmask.__bits[2], pls.pl_sigmask.__bits[3], + pls.pl_name, pls.pl_private)); + + return ptm->ptm_copyout_lwpstatus(&pls, addr, sizeof(pls)); +} + static int ptrace_startstop(struct proc *t, struct lwp **lt, int rq, void *addr, size_t data) @@ -1419,6 +1503,14 @@ do_ptrace(struct ptrace_methods *ptm, struct lwp *l, int req, pid_t pid, error = ptrace_startstop(t, <, req, addr, data); break; + case PT_LWPSTATUS: + error = ptrace_lwpstatus(t, ptm, <, addr, data, false); + break; + + case PT_LWPNEXT: + error = ptrace_lwpstatus(t, ptm, <, addr, data, true); + break; + #ifdef PT_REGISTERS case_PT_SETREGS case_PT_GETREGS diff --git a/sys/sys/ptrace.h b/sys/sys/ptrace.h index f569d8b35910..384909430239 100644 --- a/sys/sys/ptrace.h +++ b/sys/sys/ptrace.h @@ -35,6 +35,7 @@ #define _SYS_PTRACE_H_ #include +#include #define PT_TRACE_ME 0 /* child declares it's being traced */ #define PT_READ_I 1 /* read word in child's I space */ @@ -47,7 +48,9 @@ #define PT_DETACH 10 /* detach from running process */ #define PT_IO 11 /* do I/O to/from the stopped process */ #define PT_DUMPCORE 12 /* make child generate a core dump */ -#define PT_LWPINFO 13 /* get info about the LWP */ +#if defined(__LEGACY_PT_LWPINFO) || defined(_KERNEL) +#define PT_LWPINFO 13 /* OBSOLETE: get info about the LWP */ +#endif #define PT_SYSCALL 14 /* stop on syscall entry/exit */ #define PT_SYSCALLEMU 15 /* cancel syscall, tracer emulates it */ #define PT_SET_EVENT_MASK 16 /* set the event mask, defined below */ @@ -58,6 +61,8 @@ #define PT_RESUME 21 /* allow execution of the LWP */ #define PT_SUSPEND 22 /* prevent execution of the LWP */ #define PT_STOP 23 /* stop the child process */ +#define PT_LWPSTATUS 24 /* get info about the LWP */ +#define PT_LWPNEXT 25 /* get info about next LWP */ #define PT_FIRSTMACH 32 /* for machine-specific requests */ #include /* machine-specific requests, if any */ @@ -86,7 +91,9 @@ /* 20 */ "PT_GET_SIGINFO", \ /* 21 */ "PT_RESUME", \ /* 22 */ "PT_SUSPEND", \ -/* 23 */ "PT_STOP", +/* 23 */ "PT_STOP", \ +/* 24 */ "PT_LWPSTATUS", \ +/* 25 */ "PT_LWPNEXT" /* PT_{G,S}EVENT_MASK */ typedef struct ptrace_event { @@ -129,18 +136,36 @@ struct ptrace_io_desc { #define PIOD_WRITE_I 4 /* write to I space */ #define PIOD_READ_AUXV 5 /* Read from aux array */ +#if defined(__LEGACY_PT_LWPINFO) || defined(_KERNEL) /* * Argument structure for PT_LWPINFO. + * + * DEPRECATED: Use ptrace_lwpstatus. */ struct ptrace_lwpinfo { lwpid_t pl_lwpid; /* LWP described */ int pl_event; /* Event that stopped the LWP */ - /* Add fields at the end */ }; #define PL_EVENT_NONE 0 #define PL_EVENT_SIGNAL 1 #define PL_EVENT_SUSPENDED 2 +#endif + +/* + * Argument structure for PT_LWPSTATUS. + */ + +#define PL_LNAMELEN 20 /* extra 4 for alignment */ + +struct ptrace_lwpstatus { + lwpid_t pl_lwpid; /* LWP described */ + sigset_t pl_sigpend; /* LWP signals pending */ + sigset_t pl_sigmask; /* LWP signal mask */ + char pl_name[PL_LNAMELEN]; /* LWP name, may be empty */ + void *pl_private; /* LWP private data */ + /* Add fields at the end */ +}; /* * Signal Information structure @@ -189,6 +214,7 @@ struct ptrace_methods { int (*ptm_copyout_piod)(const struct ptrace_io_desc *, void *, size_t); int (*ptm_copyin_siginfo)(struct ptrace_siginfo *, const void *, size_t); int (*ptm_copyout_siginfo)(const struct ptrace_siginfo *, void *, size_t); + int (*ptm_copyout_lwpstatus)(const struct ptrace_lwpstatus *, void *, size_t); int (*ptm_doregs)(struct lwp *, struct lwp *, struct uio *); int (*ptm_dofpregs)(struct lwp *, struct lwp *, struct uio *); int (*ptm_dodbregs)(struct lwp *, struct lwp *, struct uio *); diff --git a/tests/lib/libc/sys/t_ptrace_wait.c b/tests/lib/libc/sys/t_ptrace_wait.c index 6fc43572e015..2e21d2ea2c8e 100644 --- a/tests/lib/libc/sys/t_ptrace_wait.c +++ b/tests/lib/libc/sys/t_ptrace_wait.c @@ -29,6 +29,8 @@ #include __RCSID("$NetBSD: t_ptrace_wait.c,v 1.142 2019/12/06 01:09:50 kamil Exp $"); +#define __LEGACY_PT_LWPINFO + #include #include #include @@ -114,7 +116,7 @@ static_assert(sizeof(((struct ptrace_state *)0)->pe_other_pid) == #define SYSCALL_REQUIRE_ERRNO(res, exp) ATF_REQUIRE_MSG(res == exp, \ "%d(%s) != %d", res, strerror(res), exp) -static int debug = 0; +static int debug = 1; #define DPRINTF(a, ...) do \ if (debug) \ @@ -4801,8 +4803,49 @@ PTRACE_KILL(kill3, "killpg(SIGKILL)") /// ---------------------------------------------------------------------------- +static void * +get_private(void) +{ + +#ifdef __HAVE___LWP_GETTCB_FAST + return __lwp_gettcb_fast(); +#elif defined(__HAVE___LWP_GETPRIVATE_FAST) + return __lwp_getprivate_fast(); +#else +#error Unknown code path! +#endif +} + +static int lwpinfo_thread_sigmask[] = {SIGINT, SIGPIPE, SIGALRM, SIGURG}; + +static pthread_mutex_t lwpinfo_thread_mtx = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t lwpinfo_thread_cnd = PTHREAD_COND_INITIALIZER; +static volatile size_t lwpinfo_thread_done; + +static void * +lwpinfo_thread(void *arg) +{ + volatile void **tcb; + + tcb = (volatile void **)arg; + + *tcb = get_private(); + DPRINTF("Storing tcb[] = %p from thread %d\n", *tcb, _lwp_self()); + + pthread_setname_np(pthread_self(), "thread %d", + (void *)(intptr_t)_lwp_self()); + + pthread_mutex_lock(&lwpinfo_thread_mtx); + lwpinfo_thread_done++; + signal(lwpinfo_thread_sigmask[lwpinfo_thread_done], SIG_IGN); + pthread_cond_signal(&lwpinfo_thread_cnd); + pthread_mutex_unlock(&lwpinfo_thread_mtx); + + return infinite_thread(NULL); +} + static void -traceme_lwpinfo(const int threads) +traceme_lwpinfo(const size_t threads, const char *iter) { const int sigval = SIGSTOP; const int sigval2 = SIGINT; @@ -4811,13 +4854,25 @@ traceme_lwpinfo(const int threads) int status; #endif struct ptrace_lwpinfo lwp = {0, 0}; + struct ptrace_lwpstatus lwpstatus = {0}; struct ptrace_siginfo info; + void *private; + char *name; + char namebuf[PL_LNAMELEN]; + volatile void *tcb[4]; + bool found; /* Maximum number of supported threads in this test */ - pthread_t t[3]; - int n, rv; + pthread_t t[__arraycount(tcb) - 1]; + size_t n, m; + int rv; + size_t bytes_read; - ATF_REQUIRE((int)__arraycount(t) >= threads); + struct ptrace_io_desc io; + sigset_t sigmask; + + ATF_REQUIRE(__arraycount(t) >= threads); + memset(tcb, 0, sizeof(tcb)); DPRINTF("Before forking process PID=%d\n", getpid()); SYSCALL_REQUIRE((child = fork()) != -1); @@ -4825,14 +4880,30 @@ traceme_lwpinfo(const int threads) DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); + tcb[0] = get_private(); + DPRINTF("Storing tcb[0] = %p\n", tcb[0]); + + pthread_setname_np(pthread_self(), "thread %d", + (void *)(intptr_t)_lwp_self()); + + signal(lwpinfo_thread_sigmask[lwpinfo_thread_done], SIG_IGN); + DPRINTF("Before raising %s from child\n", strsignal(sigval)); FORKEE_ASSERT(raise(sigval) == 0); for (n = 0; n < threads; n++) { - rv = pthread_create(&t[n], NULL, infinite_thread, NULL); + rv = pthread_create(&t[n], NULL, lwpinfo_thread, + &tcb[n + 1]); FORKEE_ASSERT(rv == 0); } + pthread_mutex_lock(&lwpinfo_thread_mtx); + while (lwpinfo_thread_done < threads) { + pthread_cond_wait(&lwpinfo_thread_cnd, + &lwpinfo_thread_mtx); + } + pthread_mutex_unlock(&lwpinfo_thread_mtx); + DPRINTF("Before raising %s from child\n", strsignal(sigval2)); FORKEE_ASSERT(raise(sigval2) == 0); @@ -4858,21 +4929,39 @@ traceme_lwpinfo(const int threads) ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); - DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); - SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); + if (strcmp(iter, "LWPINFO") == 0) { + DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); + SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) + != -1); - DPRINTF("Assert that there exists a single thread only\n"); - ATF_REQUIRE(lwp.pl_lwpid > 0); + DPRINTF("Assert that there exists a single thread only\n"); + ATF_REQUIRE(lwp.pl_lwpid > 0); - DPRINTF("Assert that lwp thread %d received event PL_EVENT_SIGNAL\n", - lwp.pl_lwpid); - FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL); + DPRINTF("Assert that lwp thread %d received event " + "PL_EVENT_SIGNAL\n", lwp.pl_lwpid); + FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL); + + DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); + SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) + != -1); + + DPRINTF("Assert that there exists a single thread only\n"); + ATF_REQUIRE_EQ(lwp.pl_lwpid, 0); + } else { + DPRINTF("Before calling ptrace(2) with PT_LWPNEXT for child\n"); + SYSCALL_REQUIRE(ptrace(PT_LWPNEXT, child, &lwpstatus, + sizeof(lwpstatus)) != -1); - DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); - SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); + DPRINTF("Assert that there exists a single thread only %d\n", lwpstatus.pl_lwpid); + ATF_REQUIRE(lwpstatus.pl_lwpid > 0); - DPRINTF("Assert that there exists a single thread only\n"); - ATF_REQUIRE_EQ(lwp.pl_lwpid, 0); + DPRINTF("Before calling ptrace(2) with PT_LWPNEXT for child\n"); + SYSCALL_REQUIRE(ptrace(PT_LWPNEXT, child, &lwpstatus, + sizeof(lwpstatus)) != -1); + + DPRINTF("Assert that there exists a single thread only\n"); + ATF_REQUIRE_EQ(lwpstatus.pl_lwpid, 0); + } DPRINTF("Before resuming the child process where it left off and " "without signal to be sent\n"); @@ -4896,26 +4985,119 @@ traceme_lwpinfo(const int threads) ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); memset(&lwp, 0, sizeof(lwp)); + memset(&lwpstatus, 0, sizeof(lwpstatus)); + + memset(&io, 0, sizeof(io)); + + bytes_read = 0; + io.piod_op = PIOD_READ_D; + io.piod_len = sizeof(tcb); + + do { + io.piod_addr = (char *)&tcb + bytes_read; + io.piod_offs = io.piod_addr; + + rv = ptrace(PT_IO, child, &io, sizeof(io)); + ATF_REQUIRE(rv != -1 && io.piod_len != 0); + + bytes_read += io.piod_len; + io.piod_len = sizeof(tcb) - bytes_read; + } while (bytes_read < sizeof(tcb)); for (n = 0; n <= threads; n++) { - DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); - SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); - DPRINTF("LWP=%d\n", lwp.pl_lwpid); + if (strcmp(iter, "LWPINFO") == 0) { + DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " + "child\n"); + SYSCALL_REQUIRE( + ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); + DPRINTF("LWP=%d\n", lwp.pl_lwpid); - DPRINTF("Assert that the thread exists\n"); - ATF_REQUIRE(lwp.pl_lwpid > 0); + DPRINTF("Assert that the thread exists\n"); + ATF_REQUIRE(lwp.pl_lwpid > 0); - DPRINTF("Assert that lwp thread %d received expected event\n", - lwp.pl_lwpid); - FORKEE_ASSERT_EQ(lwp.pl_event, info.psi_lwpid == lwp.pl_lwpid ? - PL_EVENT_SIGNAL : PL_EVENT_NONE); + DPRINTF("Assert that lwp thread %d received expected " + "event\n", lwp.pl_lwpid); + FORKEE_ASSERT_EQ(lwp.pl_event, + info.psi_lwpid == lwp.pl_lwpid ? + PL_EVENT_SIGNAL : PL_EVENT_NONE); + } else { + DPRINTF("Before calling ptrace(2) with PT_LWPNEXT for " + "child\n"); + SYSCALL_REQUIRE( + ptrace(PT_LWPNEXT, child, &lwpstatus, + sizeof(lwpstatus)) != -1); + DPRINTF("LWP=%d\n", lwpstatus.pl_lwpid); + + DPRINTF("Assert that the thread exists\n"); + ATF_REQUIRE(lwpstatus.pl_lwpid > 0); + + if (strstr(iter, "pl_sigmask") != NULL) { + sigmask = lwpstatus.pl_sigmask; + + DPRINTF("Retrieved sigmask: " + "%02x%02x%02x%02x\n", + sigmask.__bits[0], sigmask.__bits[1], + sigmask.__bits[2], sigmask.__bits[3]); + + found = false; + for (m = 0; + m < __arraycount(lwpinfo_thread_sigmask); + m++) { + if (sigismember(&sigmask, + lwpinfo_thread_sigmask[m])) { + found = true; + lwpinfo_thread_sigmask[m] = 0; + break; + } + } + ATF_REQUIRE(found == true); + } else if (strstr(iter, "pl_name") != NULL) { + name = lwpstatus.pl_name; + + DPRINTF("Retrieved thread name: " + "%s\n", name); + + snprintf(namebuf, sizeof namebuf, "thread %d", + lwpstatus.pl_lwpid); + + ATF_REQUIRE(strcmp(name, namebuf) == 0); + } else if (strstr(iter, "pl_private") != NULL) { + private = lwpstatus.pl_private; + + DPRINTF("Retrieved thread private pointer: " + "%p\n", private); + + found = false; + for (m = 0; m < __arraycount(tcb); m++) { + DPRINTF("Comparing %p and %p\n", + private, tcb[m]); + if (private == tcb[m]) { + found = true; + break; + } + } + ATF_REQUIRE(found == true); + } + } } - DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); - SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); - DPRINTF("LWP=%d\n", lwp.pl_lwpid); - DPRINTF("Assert that there are no more threads\n"); - ATF_REQUIRE_EQ(lwp.pl_lwpid, 0); + if (strcmp(iter, "LWPINFO") == 0) { + DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " + "child\n"); + SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) + != -1); + DPRINTF("LWP=%d\n", lwp.pl_lwpid); + + DPRINTF("Assert that there are no more threads\n"); + ATF_REQUIRE_EQ(lwp.pl_lwpid, 0); + } else { + DPRINTF("Before calling ptrace(2) with PT_LWPNEXT for child\n"); + SYSCALL_REQUIRE(ptrace(PT_LWPNEXT, child, &lwpstatus, + sizeof(lwpstatus)) != -1); + + DPRINTF("Assert that there exists a single thread only\n"); + ATF_REQUIRE_EQ(lwpstatus.pl_lwpid, 0); + } DPRINTF("Before resuming the child process where it left off and " "without signal to be sent\n"); @@ -4930,25 +5112,45 @@ traceme_lwpinfo(const int threads) TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } -#define TRACEME_LWPINFO(test, threads) \ +#define TRACEME_LWPINFO(test, threads, iter) \ ATF_TC(test); \ ATF_TC_HEAD(test, tc) \ { \ atf_tc_set_md_var(tc, "descr", \ - "Verify LWPINFO with the child with " #threads \ + "Verify " iter " with the child with " #threads \ " spawned extra threads"); \ } \ \ ATF_TC_BODY(test, tc) \ { \ \ - traceme_lwpinfo(threads); \ + traceme_lwpinfo(threads, iter); \ } -TRACEME_LWPINFO(traceme_lwpinfo0, 0) -TRACEME_LWPINFO(traceme_lwpinfo1, 1) -TRACEME_LWPINFO(traceme_lwpinfo2, 2) -TRACEME_LWPINFO(traceme_lwpinfo3, 3) +TRACEME_LWPINFO(traceme_lwpinfo0, 0, "LWPINFO") +TRACEME_LWPINFO(traceme_lwpinfo1, 1, "LWPINFO") +TRACEME_LWPINFO(traceme_lwpinfo2, 2, "LWPINFO") +TRACEME_LWPINFO(traceme_lwpinfo3, 3, "LWPINFO") + +TRACEME_LWPINFO(traceme_lwpstatus0, 0, "LWPSTATUS") +TRACEME_LWPINFO(traceme_lwpstatus1, 1, "LWPSTATUS") +TRACEME_LWPINFO(traceme_lwpstatus2, 2, "LWPSTATUS") +TRACEME_LWPINFO(traceme_lwpstatus3, 3, "LWPSTATUS") + +TRACEME_LWPINFO(traceme_lwpstatus0_pl_sigmask, 0, "LWPSTATUS+pl_sigmask") +TRACEME_LWPINFO(traceme_lwpstatus1_pl_sigmask, 1, "LWPSTATUS+pl_sigmask") +TRACEME_LWPINFO(traceme_lwpstatus2_pl_sigmask, 2, "LWPSTATUS+pl_sigmask") +TRACEME_LWPINFO(traceme_lwpstatus3_pl_sigmask, 3, "LWPSTATUS+pl_sigmask") + +TRACEME_LWPINFO(traceme_lwpstatus0_pl_name, 0, "LWPSTATUS+pl_name") +TRACEME_LWPINFO(traceme_lwpstatus1_pl_name, 1, "LWPSTATUS+pl_name") +TRACEME_LWPINFO(traceme_lwpstatus2_pl_name, 2, "LWPSTATUS+pl_name") +TRACEME_LWPINFO(traceme_lwpstatus3_pl_name, 3, "LWPSTATUS+pl_name") + +TRACEME_LWPINFO(traceme_lwpstatus0_pl_private, 0, "LWPSTATUS+pl_private") +TRACEME_LWPINFO(traceme_lwpstatus1_pl_private, 1, "LWPSTATUS+pl_private") +TRACEME_LWPINFO(traceme_lwpstatus2_pl_private, 2, "LWPSTATUS+pl_private") +TRACEME_LWPINFO(traceme_lwpstatus3_pl_private, 3, "LWPSTATUS+pl_private") /// ---------------------------------------------------------------------------- @@ -8192,6 +8394,26 @@ ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TC(tp, traceme_lwpinfo2); ATF_TP_ADD_TC(tp, traceme_lwpinfo3); + ATF_TP_ADD_TC(tp, traceme_lwpstatus0); + ATF_TP_ADD_TC(tp, traceme_lwpstatus1); + ATF_TP_ADD_TC(tp, traceme_lwpstatus2); + ATF_TP_ADD_TC(tp, traceme_lwpstatus3); + + ATF_TP_ADD_TC(tp, traceme_lwpstatus0_pl_sigmask); + ATF_TP_ADD_TC(tp, traceme_lwpstatus1_pl_sigmask); + ATF_TP_ADD_TC(tp, traceme_lwpstatus2_pl_sigmask); + ATF_TP_ADD_TC(tp, traceme_lwpstatus3_pl_sigmask); + + ATF_TP_ADD_TC(tp, traceme_lwpstatus0_pl_name); + ATF_TP_ADD_TC(tp, traceme_lwpstatus1_pl_name); + ATF_TP_ADD_TC(tp, traceme_lwpstatus2_pl_name); + ATF_TP_ADD_TC(tp, traceme_lwpstatus3_pl_name); + + ATF_TP_ADD_TC(tp, traceme_lwpstatus0_pl_private); + ATF_TP_ADD_TC(tp, traceme_lwpstatus1_pl_private); + ATF_TP_ADD_TC(tp, traceme_lwpstatus2_pl_private); + ATF_TP_ADD_TC(tp, traceme_lwpstatus3_pl_private); + ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo0); ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo1); ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo2);