Module Name: src
Committed By: kamil
Date: Tue Dec 24 14:51:00 UTC 2019
Modified Files:
src/external/gpl3/gdb/dist/gdb: nbsd-nat.c
src/sys/arch/alpha/include: ptrace.h
src/sys/arch/hppa/include: ptrace.h
src/sys/arch/powerpc/include: ptrace.h
src/sys/arch/sh3/include: ptrace.h
src/sys/arch/sparc/include: ptrace.h
src/sys/compat/netbsd32: netbsd32.h netbsd32_ptrace.c
src/sys/kern: core_elf32.c sys_ptrace.c sys_ptrace_common.c
src/sys/sys: ptrace.h
src/tests/lib/libc/sys: t_ptrace_wait.c
Log Message:
Introduce PT_LWPSTATUS + PT_LWPNEXT, obsolete PT_LWPINFO
PT_LWPINFO is a legacy ptrace(2) operation that was originally intended
to retrieve the thread (LWP) information inside a traced process.
It has a number of flaws and is confused with PT_LWPINFO from FreeBSD.
PT_LWPSTATUS and PT_LWPNEXT address the problems (shortly by: rename,
removal of pl_event) and introduces new features: signal context
(pl_sigpend, pl_sigmask), LWP name (pl_name), LWP TLS base address
(pl_private). The private pointer was so far missing information for
a debugger.
PT_LWPSTATUS@nnn is now shipped with core(5) files and contain LWP specific
information, so far missed in the core(5) files.
PT_LWPSTATUS retrieves LWP information for the prompted thread.
PT_LWPNEXT retrieves LWP information for the next thread, borrowing the
semantics from NetBSD specific PT_LWPINFO.
PT_LWPINFO is namespaced with __LEGACY_PT_LWPINFO and still available for
the foreseeable future, without plans of removing it.
Add ATF tests for PT_LWPSTATUS + PT_LWPNEXT.
Keep ATF tests for PT_LWPINFO.
Switch GDB to new API.
Proposed on tech-kern@.
To generate a diff of this commit:
cvs rdiff -u -r1.13 -r1.14 src/external/gpl3/gdb/dist/gdb/nbsd-nat.c
cvs rdiff -u -r1.10 -r1.11 src/sys/arch/alpha/include/ptrace.h
cvs rdiff -u -r1.9 -r1.10 src/sys/arch/hppa/include/ptrace.h
cvs rdiff -u -r1.15 -r1.16 src/sys/arch/powerpc/include/ptrace.h
cvs rdiff -u -r1.16 -r1.17 src/sys/arch/sh3/include/ptrace.h
cvs rdiff -u -r1.14 -r1.15 src/sys/arch/sparc/include/ptrace.h
cvs rdiff -u -r1.131 -r1.132 src/sys/compat/netbsd32/netbsd32.h
cvs rdiff -u -r1.7 -r1.8 src/sys/compat/netbsd32/netbsd32_ptrace.c
cvs rdiff -u -r1.60 -r1.61 src/sys/kern/core_elf32.c
cvs rdiff -u -r1.5 -r1.6 src/sys/kern/sys_ptrace.c
cvs rdiff -u -r1.73 -r1.74 src/sys/kern/sys_ptrace_common.c
cvs rdiff -u -r1.67 -r1.68 src/sys/sys/ptrace.h
cvs rdiff -u -r1.142 -r1.143 src/tests/lib/libc/sys/t_ptrace_wait.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/external/gpl3/gdb/dist/gdb/nbsd-nat.c
diff -u src/external/gpl3/gdb/dist/gdb/nbsd-nat.c:1.13 src/external/gpl3/gdb/dist/gdb/nbsd-nat.c:1.14
--- src/external/gpl3/gdb/dist/gdb/nbsd-nat.c:1.13 Sun Jul 14 18:50:58 2019
+++ src/external/gpl3/gdb/dist/gdb/nbsd-nat.c Tue Dec 24 14:51:00 2019
@@ -145,10 +145,10 @@ nbsd_nat_target::thread_alive (ptid_t pt
{
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);
Index: src/sys/arch/alpha/include/ptrace.h
diff -u src/sys/arch/alpha/include/ptrace.h:1.10 src/sys/arch/alpha/include/ptrace.h:1.11
--- src/sys/arch/alpha/include/ptrace.h:1.10 Tue Jun 18 21:18:11 2019
+++ src/sys/arch/alpha/include/ptrace.h Tue Dec 24 14:50:59 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: ptrace.h,v 1.10 2019/06/18 21:18:11 kamil Exp $ */
+/* $NetBSD: ptrace.h,v 1.11 2019/12/24 14:50:59 kamil Exp $ */
/*
* Copyright (c) 1994 Christopher G. Demetriou
@@ -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
Index: src/sys/arch/hppa/include/ptrace.h
diff -u src/sys/arch/hppa/include/ptrace.h:1.9 src/sys/arch/hppa/include/ptrace.h:1.10
--- src/sys/arch/hppa/include/ptrace.h:1.9 Tue Jun 18 21:18:12 2019
+++ src/sys/arch/hppa/include/ptrace.h Tue Dec 24 14:50:59 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: ptrace.h,v 1.9 2019/06/18 21:18:12 kamil Exp $ */
+/* $NetBSD: ptrace.h,v 1.10 2019/12/24 14:50:59 kamil Exp $ */
/* $OpenBSD: ptrace.h,v 1.2 1998/12/01 03:05:44 mickey Exp $ */
@@ -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
Index: src/sys/arch/powerpc/include/ptrace.h
diff -u src/sys/arch/powerpc/include/ptrace.h:1.15 src/sys/arch/powerpc/include/ptrace.h:1.16
--- src/sys/arch/powerpc/include/ptrace.h:1.15 Fri Nov 29 12:04:32 2019
+++ src/sys/arch/powerpc/include/ptrace.h Tue Dec 24 14:50:59 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: ptrace.h,v 1.15 2019/11/29 12:04:32 martin Exp $ */
+/* $NetBSD: ptrace.h,v 1.16 2019/12/24 14:50:59 kamil Exp $ */
#ifndef _POWERPC_PTRACE_H
#define _POWERPC_PTRACE_H
@@ -77,4 +77,8 @@ int procfs_machdep_validvecregs(struct l
#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 */
Index: src/sys/arch/sh3/include/ptrace.h
diff -u src/sys/arch/sh3/include/ptrace.h:1.16 src/sys/arch/sh3/include/ptrace.h:1.17
--- src/sys/arch/sh3/include/ptrace.h:1.16 Fri Oct 4 15:25:30 2019
+++ src/sys/arch/sh3/include/ptrace.h Tue Dec 24 14:50:59 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: ptrace.h,v 1.16 2019/10/04 15:25:30 maya Exp $ */
+/* $NetBSD: ptrace.h,v 1.17 2019/12/24 14:50:59 kamil Exp $ */
/*
* Copyright (c) 1993 Christopher G. Demetriou
@@ -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_ */
Index: src/sys/arch/sparc/include/ptrace.h
diff -u src/sys/arch/sparc/include/ptrace.h:1.14 src/sys/arch/sparc/include/ptrace.h:1.15
--- src/sys/arch/sparc/include/ptrace.h:1.14 Tue Jun 18 21:18:13 2019
+++ src/sys/arch/sparc/include/ptrace.h Tue Dec 24 14:50:59 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: ptrace.h,v 1.14 2019/06/18 21:18:13 kamil Exp $ */
+/* $NetBSD: ptrace.h,v 1.15 2019/12/24 14:50:59 kamil Exp $ */
/*
* Copyright (c) 1992, 1993
@@ -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
Index: src/sys/compat/netbsd32/netbsd32.h
diff -u src/sys/compat/netbsd32/netbsd32.h:1.131 src/sys/compat/netbsd32/netbsd32.h:1.132
--- src/sys/compat/netbsd32/netbsd32.h:1.131 Mon Nov 18 12:06:26 2019
+++ src/sys/compat/netbsd32/netbsd32.h Tue Dec 24 14:50:59 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: netbsd32.h,v 1.131 2019/11/18 12:06:26 rin Exp $ */
+/* $NetBSD: netbsd32.h,v 1.132 2019/12/24 14:50:59 kamil Exp $ */
/*
* Copyright (c) 1998, 2001, 2008, 2015 Matthew R. Green
@@ -39,6 +39,7 @@
#include <sys/param.h> /* precautionary upon removal from ucred.h */
#include <sys/systm.h>
#include <sys/mount.h>
+#include <sys/ptrace.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <sys/syscallargs.h>
@@ -331,6 +332,16 @@ struct netbsd32_ptrace_siginfo {
* (route signal to all LWPs) */
};
+#define PL32_LNAMELEN 20
+
+struct netbsd32_ptrace_lwpstatus {
+ lwpid_t pl_lwpid;
+ sigset_t pl_sigpend;
+ sigset_t pl_sigmask;
+ char pl_name[PL32_LNAMELEN];
+ netbsd32_voidp pl_private;
+};
+
/* from <sys/quotactl.h> */
typedef netbsd32_pointer_t netbsd32_quotactlargsp_t;
struct netbsd32_quotactlargs {
@@ -1213,6 +1224,8 @@ void netbsd32_si32_to_si(siginfo_t *, co
void netbsd32_ksi32_to_ksi(struct _ksiginfo *si, const struct __ksiginfo32 *si32);
+void netbsd32_read_lwpstatus(struct lwp *, struct netbsd32_ptrace_lwpstatus *);
+
#ifdef KTRACE
void netbsd32_ktrpsig(int, sig_t, const sigset_t *, const ksiginfo_t *);
#else
Index: src/sys/compat/netbsd32/netbsd32_ptrace.c
diff -u src/sys/compat/netbsd32/netbsd32_ptrace.c:1.7 src/sys/compat/netbsd32/netbsd32_ptrace.c:1.8
--- src/sys/compat/netbsd32/netbsd32_ptrace.c:1.7 Tue Jun 4 16:29:53 2019
+++ src/sys/compat/netbsd32/netbsd32_ptrace.c Tue Dec 24 14:50:59 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: netbsd32_ptrace.c,v 1.7 2019/06/04 16:29:53 mgorny Exp $ */
+/* $NetBSD: netbsd32_ptrace.c,v 1.8 2019/12/24 14:50:59 kamil Exp $ */
/*
* Copyright (c) 2016 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: netbsd32_ptrace.c,v 1.7 2019/06/04 16:29:53 mgorny Exp $");
+__KERNEL_RCSID(0, "$NetBSD: netbsd32_ptrace.c,v 1.8 2019/12/24 14:50:59 kamil Exp $");
#if defined(_KERNEL_OPT)
#include "opt_ptrace.h"
@@ -51,6 +51,27 @@ __KERNEL_RCSID(0, "$NetBSD: netbsd32_ptr
#define PTRACE_TRANSLATE_REQUEST32(x) x
#endif
+static void
+netbsd32_lwpstatus_to_lwpstatus32(struct netbsd32_ptrace_lwpstatus *pls32,
+ const struct ptrace_lwpstatus *pls)
+{
+ 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);
+}
+
+void
+netbsd32_read_lwpstatus(struct lwp *l, struct netbsd32_ptrace_lwpstatus *pls32)
+{
+ struct ptrace_lwpstatus pls;
+
+ process_read_lwpstatus(l, &pls);
+
+ netbsd32_lwpstatus_to_lwpstatus32(pls32, &pls);
+}
+
/*
* PTRACE methods
*/
@@ -119,6 +140,19 @@ netbsd32_copyout_siginfo(const struct pt
}
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;
+
+ netbsd32_lwpstatus_to_lwpstatus32(&pls32, pls);
+
+ return copyout(&pls32, addr, MIN(len, sizeof(pls32)));
+}
+
+static int
netbsd32_doregs(struct lwp *curl /*tracer*/,
struct lwp *l /*traced*/,
struct uio *uio)
@@ -237,6 +271,7 @@ static struct ptrace_methods netbsd32_pt
.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
Index: src/sys/kern/core_elf32.c
diff -u src/sys/kern/core_elf32.c:1.60 src/sys/kern/core_elf32.c:1.61
--- src/sys/kern/core_elf32.c:1.60 Fri Nov 22 15:57:49 2019
+++ src/sys/kern/core_elf32.c Tue Dec 24 14:50:59 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: core_elf32.c,v 1.60 2019/11/22 15:57:49 pgoyette Exp $ */
+/* $NetBSD: core_elf32.c,v 1.61 2019/12/24 14:50:59 kamil Exp $ */
/*
* Copyright (c) 2001 Wasabi Systems, Inc.
@@ -40,7 +40,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(1, "$NetBSD: core_elf32.c,v 1.60 2019/11/22 15:57:49 pgoyette Exp $");
+__KERNEL_RCSID(1, "$NetBSD: core_elf32.c,v 1.61 2019/12/24 14:50:59 kamil Exp $");
#ifdef _KERNEL_OPT
#include "opt_compat_netbsd32.h"
@@ -96,6 +96,9 @@ static int ELFNAMEEND(coredump_note)(str
/* The 'note' section names and data are always 4-byte aligned. */
#define ELFROUNDSIZE 4 /* XXX Should it be sizeof(Elf_Word)? */
+#define elf_read_lwpstatus CONCAT(process_read_lwpstatus, ELFSIZE)
+#define elf_lwpstatus CONCAT(process_lwpstatus, ELFSIZE)
+
#define elf_process_read_regs CONCAT(process_read_regs, ELFSIZE)
#define elf_process_read_fpregs CONCAT(process_read_fpregs, ELFSIZE)
#define elf_reg CONCAT(process_reg, ELFSIZE)
@@ -369,8 +372,6 @@ coredump_note_procinfo(struct lwp *l, st
{
struct proc *p;
struct netbsd_elfcore_procinfo cpi;
- struct lwp *l0;
- sigset_t ss1, ss2;
p = l->l_proc;
@@ -382,16 +383,16 @@ coredump_note_procinfo(struct lwp *l, st
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,
@@ -482,6 +483,7 @@ ELFNAMEEND(coredump_note)(struct lwp *l,
{
int error;
char name[64];
+ elf_lwpstatus els;
elf_reg intreg;
#ifdef PT_GETFPREGS
elf_fpreg freg;
@@ -491,6 +493,11 @@ ELFNAMEEND(coredump_note)(struct lwp *l,
snprintf(name, sizeof(name), "%s@%d",
ELF_NOTE_NETBSD_CORE_NAME, l->l_lid);
+ elf_read_lwpstatus(l, &els);
+
+ ELFNAMEEND(coredump_savenote)(ns, PT_LWPSTATUS, name, &els,
+ sizeof(els));
+
error = elf_process_read_regs(l, &intreg);
if (error)
return (error);
Index: src/sys/kern/sys_ptrace.c
diff -u src/sys/kern/sys_ptrace.c:1.5 src/sys/kern/sys_ptrace.c:1.6
--- src/sys/kern/sys_ptrace.c:1.5 Sun Dec 17 20:59:27 2017
+++ src/sys/kern/sys_ptrace.c Tue Dec 24 14:50:59 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: sys_ptrace.c,v 1.5 2017/12/17 20:59:27 christos Exp $ */
+/* $NetBSD: sys_ptrace.c,v 1.6 2019/12/24 14:50:59 kamil Exp $ */
/*-
* Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -118,7 +118,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sys_ptrace.c,v 1.5 2017/12/17 20:59:27 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sys_ptrace.c,v 1.6 2019/12/24 14:50:59 kamil Exp $");
#ifdef _KERNEL_OPT
#include "opt_ptrace.h"
@@ -185,11 +185,20 @@ ptrace_copyout_siginfo(const struct ptra
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,
Index: src/sys/kern/sys_ptrace_common.c
diff -u src/sys/kern/sys_ptrace_common.c:1.73 src/sys/kern/sys_ptrace_common.c:1.74
--- src/sys/kern/sys_ptrace_common.c:1.73 Fri Nov 22 05:01:44 2019
+++ src/sys/kern/sys_ptrace_common.c Tue Dec 24 14:50:59 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: sys_ptrace_common.c,v 1.73 2019/11/22 05:01:44 rin Exp $ */
+/* $NetBSD: sys_ptrace_common.c,v 1.74 2019/12/24 14:50:59 kamil Exp $ */
/*-
* Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -118,7 +118,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sys_ptrace_common.c,v 1.73 2019/11/22 05:01:44 rin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sys_ptrace_common.c,v 1.74 2019/12/24 14:50:59 kamil Exp $");
#ifdef _KERNEL_OPT
#include "opt_ptrace.h"
@@ -288,6 +288,8 @@ ptrace_listener_cb(kauth_cred_t cred, ka
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, s
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,104 @@ ptrace_lwpinfo(struct proc *t, struct lw
return copyout(&pl, addr, sizeof(pl));
}
+static void
+ptrace_read_lwpstatus(struct lwp *l, struct ptrace_lwpstatus *pls)
+{
+
+ KASSERT(l->l_lid == pls->pl_lwpid);
+
+ 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
+}
+
+void
+process_read_lwpstatus(struct lwp *l, struct ptrace_lwpstatus *pls)
+{
+
+ pls->pl_lwpid = l->l_lid;
+
+ ptrace_read_lwpstatus(l, pls);
+}
+
+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;
+
+ ptrace_read_lwpstatus(l, &pls);
+
+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, data);
+}
+
static int
ptrace_startstop(struct proc *t, struct lwp **lt, int rq, void *addr,
size_t data)
@@ -1419,6 +1521,14 @@ do_ptrace(struct ptrace_methods *ptm, st
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
Index: src/sys/sys/ptrace.h
diff -u src/sys/sys/ptrace.h:1.67 src/sys/sys/ptrace.h:1.68
--- src/sys/sys/ptrace.h:1.67 Wed Dec 4 13:52:27 2019
+++ src/sys/sys/ptrace.h Tue Dec 24 14:50:59 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: ptrace.h,v 1.67 2019/12/04 13:52:27 kamil Exp $ */
+/* $NetBSD: ptrace.h,v 1.68 2019/12/24 14:50:59 kamil Exp $ */
/*-
* Copyright (c) 1984, 1993
@@ -35,6 +35,7 @@
#define _SYS_PTRACE_H_
#include <sys/siginfo.h>
+#include <sys/signal.h>
#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/ptrace.h> /* 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
@@ -154,6 +179,23 @@ typedef struct ptrace_siginfo {
#ifdef _KERNEL
+#ifdef _KERNEL_OPT
+#include "opt_compat_netbsd32.h"
+#endif
+
+#ifdef COMPAT_NETBSD32
+#include <compat/netbsd32/netbsd32.h>
+#define process_read_lwpstatus32 netbsd32_read_lwpstatus
+#define process_lwpstatus32 struct netbsd32_ptrace_lwpstatus
+#endif
+
+#ifndef process_lwpstatus32
+#define process_lwpstatus32 struct ptrace_lwpstatus
+#endif
+#ifndef process_lwpstatus64
+#define process_lwpstatus64 struct ptrace_lwpstatus
+#endif
+
#if defined(PT_GETREGS) || defined(PT_SETREGS)
struct reg;
#ifndef process_reg32
@@ -189,6 +231,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 *);
@@ -217,11 +260,20 @@ void proc_changeparent(struct proc *, st
int do_ptrace(struct ptrace_methods *, struct lwp *, int, pid_t, void *,
int, register_t *);
+void process_read_lwpstatus(struct lwp *, struct ptrace_lwpstatus *);
+#ifndef process_read_lwpstatus32
+#define process_read_lwpstatus32 process_read_lwpstatus
+#endif
+#ifndef process_read_lwpstatus64
+#define process_read_lwpstatus64 process_read_lwpstatus
+#endif
+
/*
* 64bit architectures that support 32bit emulation (amd64 and sparc64)
* will #define process_read_regs32 to netbsd32_process_read_regs (etc).
* In all other cases these #defines drop the size suffix.
*/
+
#ifdef PT_GETDBREGS
int process_read_dbregs(struct lwp *, struct dbreg *, size_t *);
#ifndef process_read_dbregs32
Index: src/tests/lib/libc/sys/t_ptrace_wait.c
diff -u src/tests/lib/libc/sys/t_ptrace_wait.c:1.142 src/tests/lib/libc/sys/t_ptrace_wait.c:1.143
--- src/tests/lib/libc/sys/t_ptrace_wait.c:1.142 Fri Dec 6 01:09:50 2019
+++ src/tests/lib/libc/sys/t_ptrace_wait.c Tue Dec 24 14:50:59 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: t_ptrace_wait.c,v 1.142 2019/12/06 01:09:50 kamil Exp $ */
+/* $NetBSD: t_ptrace_wait.c,v 1.143 2019/12/24 14:50:59 kamil Exp $ */
/*-
* Copyright (c) 2016, 2017, 2018, 2019 The NetBSD Foundation, Inc.
@@ -27,7 +27,9 @@
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: t_ptrace_wait.c,v 1.142 2019/12/06 01:09:50 kamil Exp $");
+__RCSID("$NetBSD: t_ptrace_wait.c,v 1.143 2019/12/24 14:50:59 kamil Exp $");
+
+#define __LEGACY_PT_LWPINFO
#include <sys/param.h>
#include <sys/types.h>
@@ -4801,8 +4803,52 @@ 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[] = {SIGXCPU, 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)
+{
+ sigset_t s;
+ 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());
+
+ sigemptyset(&s);
+ pthread_mutex_lock(&lwpinfo_thread_mtx);
+ sigaddset(&s, lwpinfo_thread_sigmask[lwpinfo_thread_done]);
+ lwpinfo_thread_done++;
+ pthread_sigmask(SIG_BLOCK, &s, NULL);
+ 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 +4857,26 @@ 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;
+ sigset_t s;
/* 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 +4884,32 @@ 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());
+
+ sigemptyset(&s);
+ sigaddset(&s, lwpinfo_thread_sigmask[lwpinfo_thread_done]);
+ pthread_sigmask(SIG_BLOCK, &s, NULL);
+
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 +4935,47 @@ 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 (strstr(iter, "LWPINFO") != NULL) {
+ 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);
+
+ if (strstr(iter, "LWPSTATUS") != NULL) {
+ DPRINTF("Before calling ptrace(2) with PT_LWPSTATUS "
+ "for child\n");
+ lwpstatus.pl_lwpid = lwp.pl_lwpid;
+ SYSCALL_REQUIRE(ptrace(PT_LWPSTATUS, 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("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);
+ 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("Assert that there exists a single thread only %d\n", lwpstatus.pl_lwpid);
+ ATF_REQUIRE(lwpstatus.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 +4999,131 @@ 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 (strstr(iter, "LWPINFO") != NULL) {
+ 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("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 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 there are no more threads\n");
- ATF_REQUIRE_EQ(lwp.pl_lwpid, 0);
+ if (strstr(iter, "LWPSTATUS") != NULL) {
+ DPRINTF("Before calling ptrace(2) with "
+ "PT_LWPSTATUS for child\n");
+ lwpstatus.pl_lwpid = lwp.pl_lwpid;
+ SYSCALL_REQUIRE(ptrace(PT_LWPSTATUS, child,
+ &lwpstatus, sizeof(lwpstatus)) != -1);
+
+ goto check_lwpstatus;
+ }
+ } 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);
+
+ check_lwpstatus:
+
+ 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);
+ }
+ }
+ }
+
+ if (strstr(iter, "LWPINFO") != NULL) {
+ 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 +5138,77 @@ 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_lwpinfo0_lwpstatus, 0, "LWPINFO+LWPSTATUS")
+TRACEME_LWPINFO(traceme_lwpinfo1_lwpstatus, 1, "LWPINFO+LWPSTATUS")
+TRACEME_LWPINFO(traceme_lwpinfo2_lwpstatus, 2, "LWPINFO+LWPSTATUS")
+TRACEME_LWPINFO(traceme_lwpinfo3_lwpstatus, 3, "LWPINFO+LWPSTATUS")
+
+TRACEME_LWPINFO(traceme_lwpinfo0_lwpstatus_pl_sigmask, 0,
+ "LWPINFO+LWPSTATUS+pl_sigmask")
+TRACEME_LWPINFO(traceme_lwpinfo1_lwpstatus_pl_sigmask, 1,
+ "LWPINFO+LWPSTATUS+pl_sigmask")
+TRACEME_LWPINFO(traceme_lwpinfo2_lwpstatus_pl_sigmask, 2,
+ "LWPINFO+LWPSTATUS+pl_sigmask")
+TRACEME_LWPINFO(traceme_lwpinfo3_lwpstatus_pl_sigmask, 3,
+ "LWPINFO+LWPSTATUS+pl_sigmask")
+
+TRACEME_LWPINFO(traceme_lwpinfo0_lwpstatus_pl_name, 0,
+ "LWPINFO+LWPSTATUS+pl_name")
+TRACEME_LWPINFO(traceme_lwpinfo1_lwpstatus_pl_name, 1,
+ "LWPINFO+LWPSTATUS+pl_name")
+TRACEME_LWPINFO(traceme_lwpinfo2_lwpstatus_pl_name, 2,
+ "LWPINFO+LWPSTATUS+pl_name")
+TRACEME_LWPINFO(traceme_lwpinfo3_lwpstatus_pl_name, 3,
+ "LWPINFO+LWPSTATUS+pl_name")
+
+TRACEME_LWPINFO(traceme_lwpinfo0_lwpstatus_pl_private, 0,
+ "LWPINFO+LWPSTATUS+pl_private")
+TRACEME_LWPINFO(traceme_lwpinfo1_lwpstatus_pl_private, 1,
+ "LWPINFO+LWPSTATUS+pl_private")
+TRACEME_LWPINFO(traceme_lwpinfo2_lwpstatus_pl_private, 2,
+ "LWPINFO+LWPSTATUS+pl_private")
+TRACEME_LWPINFO(traceme_lwpinfo3_lwpstatus_pl_private, 3,
+ "LWPINFO+LWPSTATUS+pl_private")
+
+TRACEME_LWPINFO(traceme_lwpnext0, 0, "LWPNEXT")
+TRACEME_LWPINFO(traceme_lwpnext1, 1, "LWPNEXT")
+TRACEME_LWPINFO(traceme_lwpnext2, 2, "LWPNEXT")
+TRACEME_LWPINFO(traceme_lwpnext3, 3, "LWPNEXT")
+
+TRACEME_LWPINFO(traceme_lwpnext0_pl_sigmask, 0, "LWPNEXT+pl_sigmask")
+TRACEME_LWPINFO(traceme_lwpnext1_pl_sigmask, 1, "LWPNEXT+pl_sigmask")
+TRACEME_LWPINFO(traceme_lwpnext2_pl_sigmask, 2, "LWPNEXT+pl_sigmask")
+TRACEME_LWPINFO(traceme_lwpnext3_pl_sigmask, 3, "LWPNEXT+pl_sigmask")
+
+TRACEME_LWPINFO(traceme_lwpnext0_pl_name, 0, "LWPNEXT+pl_name")
+TRACEME_LWPINFO(traceme_lwpnext1_pl_name, 1, "LWPNEXT+pl_name")
+TRACEME_LWPINFO(traceme_lwpnext2_pl_name, 2, "LWPNEXT+pl_name")
+TRACEME_LWPINFO(traceme_lwpnext3_pl_name, 3, "LWPNEXT+pl_name")
+
+TRACEME_LWPINFO(traceme_lwpnext0_pl_private, 0, "LWPNEXT+pl_private")
+TRACEME_LWPINFO(traceme_lwpnext1_pl_private, 1, "LWPNEXT+pl_private")
+TRACEME_LWPINFO(traceme_lwpnext2_pl_private, 2, "LWPNEXT+pl_private")
+TRACEME_LWPINFO(traceme_lwpnext3_pl_private, 3, "LWPNEXT+pl_private")
/// ----------------------------------------------------------------------------
@@ -8192,6 +8452,46 @@ 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_lwpinfo0_lwpstatus);
+ ATF_TP_ADD_TC(tp, traceme_lwpinfo1_lwpstatus);
+ ATF_TP_ADD_TC(tp, traceme_lwpinfo2_lwpstatus);
+ ATF_TP_ADD_TC(tp, traceme_lwpinfo3_lwpstatus);
+
+ ATF_TP_ADD_TC(tp, traceme_lwpinfo0_lwpstatus_pl_sigmask);
+ ATF_TP_ADD_TC(tp, traceme_lwpinfo1_lwpstatus_pl_sigmask);
+ ATF_TP_ADD_TC(tp, traceme_lwpinfo2_lwpstatus_pl_sigmask);
+ ATF_TP_ADD_TC(tp, traceme_lwpinfo3_lwpstatus_pl_sigmask);
+
+ ATF_TP_ADD_TC(tp, traceme_lwpinfo0_lwpstatus_pl_name);
+ ATF_TP_ADD_TC(tp, traceme_lwpinfo1_lwpstatus_pl_name);
+ ATF_TP_ADD_TC(tp, traceme_lwpinfo2_lwpstatus_pl_name);
+ ATF_TP_ADD_TC(tp, traceme_lwpinfo3_lwpstatus_pl_name);
+
+ ATF_TP_ADD_TC(tp, traceme_lwpinfo0_lwpstatus_pl_private);
+ ATF_TP_ADD_TC(tp, traceme_lwpinfo1_lwpstatus_pl_private);
+ ATF_TP_ADD_TC(tp, traceme_lwpinfo2_lwpstatus_pl_private);
+ ATF_TP_ADD_TC(tp, traceme_lwpinfo3_lwpstatus_pl_private);
+
+ ATF_TP_ADD_TC(tp, traceme_lwpnext0);
+ ATF_TP_ADD_TC(tp, traceme_lwpnext1);
+ ATF_TP_ADD_TC(tp, traceme_lwpnext2);
+ ATF_TP_ADD_TC(tp, traceme_lwpnext3);
+
+ ATF_TP_ADD_TC(tp, traceme_lwpnext0_pl_sigmask);
+ ATF_TP_ADD_TC(tp, traceme_lwpnext1_pl_sigmask);
+ ATF_TP_ADD_TC(tp, traceme_lwpnext2_pl_sigmask);
+ ATF_TP_ADD_TC(tp, traceme_lwpnext3_pl_sigmask);
+
+ ATF_TP_ADD_TC(tp, traceme_lwpnext0_pl_name);
+ ATF_TP_ADD_TC(tp, traceme_lwpnext1_pl_name);
+ ATF_TP_ADD_TC(tp, traceme_lwpnext2_pl_name);
+ ATF_TP_ADD_TC(tp, traceme_lwpnext3_pl_name);
+
+ ATF_TP_ADD_TC(tp, traceme_lwpnext0_pl_private);
+ ATF_TP_ADD_TC(tp, traceme_lwpnext1_pl_private);
+ ATF_TP_ADD_TC(tp, traceme_lwpnext2_pl_private);
+ ATF_TP_ADD_TC(tp, traceme_lwpnext3_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);