1139804Simp/*-
21945Sdg * Copyright (c) 1994, Sean Eric Fagan
31945Sdg * All rights reserved.
41541Srgrimes *
51541Srgrimes * Redistribution and use in source and binary forms, with or without
61541Srgrimes * modification, are permitted provided that the following conditions
71541Srgrimes * are met:
81541Srgrimes * 1. Redistributions of source code must retain the above copyright
91541Srgrimes *    notice, this list of conditions and the following disclaimer.
101541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111541Srgrimes *    notice, this list of conditions and the following disclaimer in the
121541Srgrimes *    documentation and/or other materials provided with the distribution.
131541Srgrimes * 3. All advertising materials mentioning features or use of this software
141541Srgrimes *    must display the following acknowledgement:
151945Sdg *	This product includes software developed by Sean Eric Fagan.
161945Sdg * 4. The name of the author may not be used to endorse or promote products
171945Sdg *    derived from this software without specific prior written permission.
181541Srgrimes *
191945Sdg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
201541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
211541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
221945Sdg * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
231541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
241541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
251541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
261541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
271541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
281541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
291541Srgrimes * SUCH DAMAGE.
301541Srgrimes */
311541Srgrimes
32116182Sobrien#include <sys/cdefs.h>
33116182Sobrien__FBSDID("$FreeBSD: stable/10/sys/kern/sys_process.c 328379 2018-01-24 21:48:39Z jhb $");
34116182Sobrien
35147692Speter#include "opt_compat.h"
36147692Speter
371541Srgrimes#include <sys/param.h>
382112Swollman#include <sys/systm.h>
3976166Smarkm#include <sys/lock.h>
4076166Smarkm#include <sys/mutex.h>
41102946Siedowse#include <sys/syscallsubr.h>
42189282Skib#include <sys/sysent.h>
4312221Sbde#include <sys/sysproto.h>
44255708Sjhb#include <sys/priv.h>
451541Srgrimes#include <sys/proc.h>
461945Sdg#include <sys/vnode.h>
471945Sdg#include <sys/ptrace.h>
48248084Sattilio#include <sys/rwlock.h>
4974927Sjhb#include <sys/sx.h>
50132089Sdavidxu#include <sys/malloc.h>
51138129Sdas#include <sys/signalvar.h>
521541Srgrimes
531945Sdg#include <machine/reg.h>
5476166Smarkm
55155634Swsalamon#include <security/audit/audit.h>
56155634Swsalamon
571945Sdg#include <vm/vm.h>
5812662Sdg#include <vm/pmap.h>
5984637Sdes#include <vm/vm_extern.h>
6012662Sdg#include <vm/vm_map.h>
6184637Sdes#include <vm/vm_kern.h>
6284637Sdes#include <vm/vm_object.h>
631945Sdg#include <vm/vm_page.h>
64194766Skib#include <vm/vm_param.h>
651945Sdg
66205014Snwhitehorn#ifdef COMPAT_FREEBSD32
67147692Speter#include <sys/procfs.h>
68209688Skib#include <compat/freebsd32/freebsd32_signal.h>
69147692Speter
70147692Speterstruct ptrace_io_desc32 {
71147692Speter	int		piod_op;
72209390Sed	uint32_t	piod_offs;
73209390Sed	uint32_t	piod_addr;
74209390Sed	uint32_t	piod_len;
75147692Speter};
76203708Smarcel
77203708Smarcelstruct ptrace_vm_entry32 {
78203783Smarcel	int		pve_entry;
79203783Smarcel	int		pve_timestamp;
80203708Smarcel	uint32_t	pve_start;
81203708Smarcel	uint32_t	pve_end;
82203708Smarcel	uint32_t	pve_offset;
83203708Smarcel	u_int		pve_prot;
84203708Smarcel	u_int		pve_pathlen;
85203783Smarcel	int32_t		pve_fileid;
86203783Smarcel	u_int		pve_fsid;
87203708Smarcel	uint32_t	pve_path;
88203708Smarcel};
89203708Smarcel
90209688Skibstruct ptrace_lwpinfo32 {
91209688Skib	lwpid_t	pl_lwpid;	/* LWP described. */
92209688Skib	int	pl_event;	/* Event that stopped the LWP. */
93209688Skib	int	pl_flags;	/* LWP flags. */
94209688Skib	sigset_t	pl_sigmask;	/* LWP signal mask */
95209688Skib	sigset_t	pl_siglist;	/* LWP pending signal */
96209688Skib	struct siginfo32 pl_siginfo;	/* siginfo for signal */
97215679Sattilio	char	pl_tdname[MAXCOMLEN + 1];	/* LWP name. */
98290464Sjhb	pid_t	pl_child_pid;		/* New child pid */
99289780Sjhb	u_int		pl_syscall_code;
100289780Sjhb	u_int		pl_syscall_narg;
101209688Skib};
102209688Skib
103147692Speter#endif
104147692Speter
10591006Sbde/*
10691006Sbde * Functions implemented using PROC_ACTION():
10791006Sbde *
10891006Sbde * proc_read_regs(proc, regs)
10991006Sbde *	Get the current user-visible register set from the process
11091006Sbde *	and copy it into the regs structure (<machine/reg.h>).
11191006Sbde *	The process is stopped at the time read_regs is called.
11291006Sbde *
11391006Sbde * proc_write_regs(proc, regs)
11491006Sbde *	Update the current register set from the passed in regs
11591006Sbde *	structure.  Take care to avoid clobbering special CPU
11691006Sbde *	registers or privileged bits in the PSL.
11791006Sbde *	Depending on the architecture this may have fix-up work to do,
11891006Sbde *	especially if the IAR or PCW are modified.
11991006Sbde *	The process is stopped at the time write_regs is called.
12091006Sbde *
12191006Sbde * proc_read_fpregs, proc_write_fpregs
12291006Sbde *	deal with the floating point register set, otherwise as above.
12391006Sbde *
12491006Sbde * proc_read_dbregs, proc_write_dbregs
12591006Sbde *	deal with the processor debug register set, otherwise as above.
12691006Sbde *
12791006Sbde * proc_sstep(proc)
12891006Sbde *	Arrange for the process to trap after executing a single instruction.
12991006Sbde */
13091006Sbde
13191006Sbde#define	PROC_ACTION(action) do {					\
13285297Sdes	int error;							\
13385297Sdes									\
134113868Sjhb	PROC_LOCK_ASSERT(td->td_proc, MA_OWNED);			\
135172207Sjeff	if ((td->td_proc->p_flag & P_INMEM) == 0)			\
13691006Sbde		error = EIO;						\
13791006Sbde	else								\
13891006Sbde		error = (action);					\
13985297Sdes	return (error);							\
14091006Sbde} while(0)
141112389Sdes
14291006Sbdeint
14391006Sbdeproc_read_regs(struct thread *td, struct reg *regs)
14491006Sbde{
14591006Sbde
14691006Sbde	PROC_ACTION(fill_regs(td, regs));
14785297Sdes}
14885297Sdes
14991006Sbdeint
15091006Sbdeproc_write_regs(struct thread *td, struct reg *regs)
15191006Sbde{
15285297Sdes
15391006Sbde	PROC_ACTION(set_regs(td, regs));
15491006Sbde}
15591006Sbde
15684637Sdesint
15791006Sbdeproc_read_dbregs(struct thread *td, struct dbreg *dbregs)
15891006Sbde{
15991006Sbde
16091006Sbde	PROC_ACTION(fill_dbregs(td, dbregs));
16191006Sbde}
16291006Sbde
16391006Sbdeint
16491006Sbdeproc_write_dbregs(struct thread *td, struct dbreg *dbregs)
16591006Sbde{
16691006Sbde
16791006Sbde	PROC_ACTION(set_dbregs(td, dbregs));
16891006Sbde}
16991006Sbde
17091006Sbde/*
17191006Sbde * Ptrace doesn't support fpregs at all, and there are no security holes
17291006Sbde * or translations for fpregs, so we can just copy them.
17391006Sbde */
17491006Sbdeint
17591006Sbdeproc_read_fpregs(struct thread *td, struct fpreg *fpregs)
17691006Sbde{
17791006Sbde
17891006Sbde	PROC_ACTION(fill_fpregs(td, fpregs));
17991006Sbde}
18091006Sbde
18191006Sbdeint
18291006Sbdeproc_write_fpregs(struct thread *td, struct fpreg *fpregs)
18391006Sbde{
18491006Sbde
18591006Sbde	PROC_ACTION(set_fpregs(td, fpregs));
18691006Sbde}
18791006Sbde
188205014Snwhitehorn#ifdef COMPAT_FREEBSD32
189147692Speter/* For 32 bit binaries, we need to expose the 32 bit regs layouts. */
19091006Sbdeint
191147692Speterproc_read_regs32(struct thread *td, struct reg32 *regs32)
192147692Speter{
193147692Speter
194147692Speter	PROC_ACTION(fill_regs32(td, regs32));
195147692Speter}
196147692Speter
197147692Speterint
198147692Speterproc_write_regs32(struct thread *td, struct reg32 *regs32)
199147692Speter{
200147692Speter
201147692Speter	PROC_ACTION(set_regs32(td, regs32));
202147692Speter}
203147692Speter
204147692Speterint
205147692Speterproc_read_dbregs32(struct thread *td, struct dbreg32 *dbregs32)
206147692Speter{
207147692Speter
208147692Speter	PROC_ACTION(fill_dbregs32(td, dbregs32));
209147692Speter}
210147692Speter
211147692Speterint
212147692Speterproc_write_dbregs32(struct thread *td, struct dbreg32 *dbregs32)
213147692Speter{
214147692Speter
215147692Speter	PROC_ACTION(set_dbregs32(td, dbregs32));
216147692Speter}
217147692Speter
218147692Speterint
219147692Speterproc_read_fpregs32(struct thread *td, struct fpreg32 *fpregs32)
220147692Speter{
221147692Speter
222147692Speter	PROC_ACTION(fill_fpregs32(td, fpregs32));
223147692Speter}
224147692Speter
225147692Speterint
226147692Speterproc_write_fpregs32(struct thread *td, struct fpreg32 *fpregs32)
227147692Speter{
228147692Speter
229147692Speter	PROC_ACTION(set_fpregs32(td, fpregs32));
230147692Speter}
231147692Speter#endif
232147692Speter
233147692Speterint
23485297Sdesproc_sstep(struct thread *td)
23585297Sdes{
23685297Sdes
23791006Sbde	PROC_ACTION(ptrace_single_step(td));
23885297Sdes}
23985297Sdes
24085297Sdesint
24184637Sdesproc_rwmem(struct proc *p, struct uio *uio)
24284483Sdes{
24384637Sdes	vm_map_t map;
244199819Salc	vm_offset_t pageno;		/* page number */
24584637Sdes	vm_prot_t reqprot;
246216604Salc	int error, fault_flags, page_offset, writing;
2471945Sdg
24884637Sdes	/*
249155922Sjhb	 * Assert that someone has locked this vmspace.  (Should be
250155922Sjhb	 * curthread but we can't assert that.)  This keeps the process
251155922Sjhb	 * from exiting out from under us until this operation completes.
25284637Sdes	 */
253155922Sjhb	KASSERT(p->p_lock >= 1, ("%s: process %p (pid %d) not held", __func__,
254155922Sjhb	    p, p->p_pid));
255132684Salc
25684637Sdes	/*
25784637Sdes	 * The map we want...
25884637Sdes	 */
259155922Sjhb	map = &p->p_vmspace->vm_map;
2601945Sdg
261216604Salc	/*
262216604Salc	 * If we are writing, then we request vm_fault() to create a private
263216604Salc	 * copy of each page.  Since these copies will not be writeable by the
264216604Salc	 * process, we must explicity request that they be dirtied.
265216604Salc	 */
26684637Sdes	writing = uio->uio_rw == UIO_WRITE;
267199819Salc	reqprot = writing ? VM_PROT_COPY | VM_PROT_READ : VM_PROT_READ;
268216604Salc	fault_flags = writing ? VM_FAULT_DIRTY : VM_FAULT_NORMAL;
2698876Srgrimes
27084637Sdes	/*
27184637Sdes	 * Only map in one page at a time.  We don't have to, but it
27284637Sdes	 * makes things easier.  This way is trivial - right?
27384637Sdes	 */
27484637Sdes	do {
27584637Sdes		vm_offset_t uva;
27684637Sdes		u_int len;
27784637Sdes		vm_page_t m;
2788876Srgrimes
27984637Sdes		uva = (vm_offset_t)uio->uio_offset;
2801945Sdg
28184637Sdes		/*
28284637Sdes		 * Get the page number of this segment.
28384637Sdes		 */
28484637Sdes		pageno = trunc_page(uva);
28584637Sdes		page_offset = uva - pageno;
2861945Sdg
28784637Sdes		/*
28884637Sdes		 * How many bytes to copy
28984637Sdes		 */
29084637Sdes		len = min(PAGE_SIZE - page_offset, uio->uio_resid);
29184637Sdes
29284637Sdes		/*
293253953Sattilio		 * Fault and hold the page on behalf of the process.
29484637Sdes		 */
295253953Sattilio		error = vm_fault_hold(map, pageno, reqprot, fault_flags, &m);
296216604Salc		if (error != KERN_SUCCESS) {
297194766Skib			if (error == KERN_RESOURCE_SHORTAGE)
298194766Skib				error = ENOMEM;
299194766Skib			else
300194766Skib				error = EFAULT;
30184637Sdes			break;
3021945Sdg		}
3031945Sdg
30484637Sdes		/*
30584637Sdes		 * Now do the i/o move.
30684637Sdes		 */
307127386Salc		error = uiomove_fromphys(&m, page_offset, len, uio);
3081945Sdg
309198341Smarcel		/* Make the I-cache coherent for breakpoints. */
310216604Salc		if (writing && error == 0) {
311216604Salc			vm_map_lock_read(map);
312216604Salc			if (vm_map_check_protection(map, pageno, pageno +
313216604Salc			    PAGE_SIZE, VM_PROT_EXECUTE))
314216604Salc				vm_sync_icache(map, uva, len);
315216604Salc			vm_map_unlock_read(map);
316216604Salc		}
317198341Smarcel
31884637Sdes		/*
319118697Salc		 * Release the page.
32084637Sdes		 */
321253953Sattilio		vm_page_lock(m);
322253953Sattilio		vm_page_unhold(m);
323253953Sattilio		vm_page_unlock(m);
3241945Sdg
32584637Sdes	} while (error == 0 && uio->uio_resid > 0);
3261945Sdg
32784637Sdes	return (error);
3281945Sdg}
3291945Sdg
330203696Smarcelstatic int
331203696Smarcelptrace_vm_entry(struct thread *td, struct proc *p, struct ptrace_vm_entry *pve)
332203696Smarcel{
333203783Smarcel	struct vattr vattr;
334203696Smarcel	vm_map_t map;
335203696Smarcel	vm_map_entry_t entry;
336203696Smarcel	vm_object_t obj, tobj, lobj;
337203783Smarcel	struct vmspace *vm;
338203696Smarcel	struct vnode *vp;
339203696Smarcel	char *freepath, *fullpath;
340203696Smarcel	u_int pathlen;
341241896Skib	int error, index;
342203696Smarcel
343203783Smarcel	error = 0;
344203783Smarcel	obj = NULL;
345203783Smarcel
346203783Smarcel	vm = vmspace_acquire_ref(p);
347203783Smarcel	map = &vm->vm_map;
348203783Smarcel	vm_map_lock_read(map);
349203783Smarcel
350203783Smarcel	do {
351203783Smarcel		entry = map->header.next;
352203783Smarcel		index = 0;
353203783Smarcel		while (index < pve->pve_entry && entry != &map->header) {
354203696Smarcel			entry = entry->next;
355203783Smarcel			index++;
356203783Smarcel		}
357203783Smarcel		if (index != pve->pve_entry) {
358203783Smarcel			error = EINVAL;
359203783Smarcel			break;
360203783Smarcel		}
361203783Smarcel		while (entry != &map->header &&
362203783Smarcel		    (entry->eflags & MAP_ENTRY_IS_SUB_MAP) != 0) {
363203783Smarcel			entry = entry->next;
364203783Smarcel			index++;
365203783Smarcel		}
366203783Smarcel		if (entry == &map->header) {
367203783Smarcel			error = ENOENT;
368203783Smarcel			break;
369203783Smarcel		}
370203696Smarcel
371203783Smarcel		/* We got an entry. */
372203783Smarcel		pve->pve_entry = index + 1;
373203783Smarcel		pve->pve_timestamp = map->timestamp;
374203783Smarcel		pve->pve_start = entry->start;
375203783Smarcel		pve->pve_end = entry->end - 1;
376203783Smarcel		pve->pve_offset = entry->offset;
377203783Smarcel		pve->pve_prot = entry->protection;
378203696Smarcel
379203783Smarcel		/* Backing object's path needed? */
380203783Smarcel		if (pve->pve_pathlen == 0)
381203783Smarcel			break;
382203696Smarcel
383203783Smarcel		pathlen = pve->pve_pathlen;
384203783Smarcel		pve->pve_pathlen = 0;
385203696Smarcel
386203783Smarcel		obj = entry->object.vm_object;
387203783Smarcel		if (obj != NULL)
388249277Sattilio			VM_OBJECT_RLOCK(obj);
389203783Smarcel	} while (0);
390203696Smarcel
391203783Smarcel	vm_map_unlock_read(map);
392203783Smarcel
393203788Smarcel	pve->pve_fsid = VNOVAL;
394203788Smarcel	pve->pve_fileid = VNOVAL;
395203788Smarcel
396203783Smarcel	if (error == 0 && obj != NULL) {
397203783Smarcel		lobj = obj;
398203783Smarcel		for (tobj = obj; tobj != NULL; tobj = tobj->backing_object) {
399203783Smarcel			if (tobj != obj)
400249277Sattilio				VM_OBJECT_RLOCK(tobj);
401203783Smarcel			if (lobj != obj)
402249277Sattilio				VM_OBJECT_RUNLOCK(lobj);
403203783Smarcel			lobj = tobj;
404203783Smarcel			pve->pve_offset += tobj->backing_object_offset;
405203783Smarcel		}
406288499Svangyzen		vp = vm_object_vnode(lobj);
407203696Smarcel		if (vp != NULL)
408203696Smarcel			vref(vp);
409203696Smarcel		if (lobj != obj)
410249277Sattilio			VM_OBJECT_RUNLOCK(lobj);
411249277Sattilio		VM_OBJECT_RUNLOCK(obj);
412203696Smarcel
413203783Smarcel		if (vp != NULL) {
414203783Smarcel			freepath = NULL;
415203783Smarcel			fullpath = NULL;
416203783Smarcel			vn_fullpath(td, vp, &fullpath, &freepath);
417203783Smarcel			vn_lock(vp, LK_SHARED | LK_RETRY);
418203783Smarcel			if (VOP_GETATTR(vp, &vattr, td->td_ucred) == 0) {
419203783Smarcel				pve->pve_fileid = vattr.va_fileid;
420203783Smarcel				pve->pve_fsid = vattr.va_fsid;
421203783Smarcel			}
422203783Smarcel			vput(vp);
423203696Smarcel
424203783Smarcel			if (fullpath != NULL) {
425203783Smarcel				pve->pve_pathlen = strlen(fullpath) + 1;
426203783Smarcel				if (pve->pve_pathlen <= pathlen) {
427203783Smarcel					error = copyout(fullpath, pve->pve_path,
428203783Smarcel					    pve->pve_pathlen);
429203783Smarcel				} else
430203783Smarcel					error = ENAMETOOLONG;
431203783Smarcel			}
432203783Smarcel			if (freepath != NULL)
433203783Smarcel				free(freepath, M_TEMP);
434203783Smarcel		}
435203783Smarcel	}
436303198Skib	vmspace_free(vm);
437284343Sjhb	if (error == 0)
438284343Sjhb		CTR3(KTR_PTRACE, "PT_VM_ENTRY: pid %d, entry %d, start %p",
439284343Sjhb		    p->p_pid, pve->pve_entry, pve->pve_start);
440203696Smarcel
441203783Smarcel	return (error);
442203783Smarcel}
443203783Smarcel
444205014Snwhitehorn#ifdef COMPAT_FREEBSD32
445290324Skibstatic int
446203783Smarcelptrace_vm_entry32(struct thread *td, struct proc *p,
447203783Smarcel    struct ptrace_vm_entry32 *pve32)
448203783Smarcel{
449203783Smarcel	struct ptrace_vm_entry pve;
450203783Smarcel	int error;
451203783Smarcel
452203783Smarcel	pve.pve_entry = pve32->pve_entry;
453203783Smarcel	pve.pve_pathlen = pve32->pve_pathlen;
454203783Smarcel	pve.pve_path = (void *)(uintptr_t)pve32->pve_path;
455203783Smarcel
456203783Smarcel	error = ptrace_vm_entry(td, p, &pve);
457203783Smarcel	if (error == 0) {
458203783Smarcel		pve32->pve_entry = pve.pve_entry;
459203783Smarcel		pve32->pve_timestamp = pve.pve_timestamp;
460203783Smarcel		pve32->pve_start = pve.pve_start;
461203783Smarcel		pve32->pve_end = pve.pve_end;
462203783Smarcel		pve32->pve_offset = pve.pve_offset;
463203783Smarcel		pve32->pve_prot = pve.pve_prot;
464203783Smarcel		pve32->pve_fileid = pve.pve_fileid;
465203783Smarcel		pve32->pve_fsid = pve.pve_fsid;
466203696Smarcel	}
467203783Smarcel
468203783Smarcel	pve32->pve_pathlen = pve.pve_pathlen;
469203696Smarcel	return (error);
470203696Smarcel}
471209688Skib
472209688Skibstatic void
473209688Skibptrace_lwpinfo_to32(const struct ptrace_lwpinfo *pl,
474209688Skib    struct ptrace_lwpinfo32 *pl32)
475209688Skib{
476209688Skib
477325643Skib	bzero(pl32, sizeof(*pl32));
478209688Skib	pl32->pl_lwpid = pl->pl_lwpid;
479209688Skib	pl32->pl_event = pl->pl_event;
480209688Skib	pl32->pl_flags = pl->pl_flags;
481209688Skib	pl32->pl_sigmask = pl->pl_sigmask;
482209688Skib	pl32->pl_siglist = pl->pl_siglist;
483209688Skib	siginfo_to_siginfo32(&pl->pl_siginfo, &pl32->pl_siginfo);
484215679Sattilio	strcpy(pl32->pl_tdname, pl->pl_tdname);
485217819Skib	pl32->pl_child_pid = pl->pl_child_pid;
486289780Sjhb	pl32->pl_syscall_code = pl->pl_syscall_code;
487289780Sjhb	pl32->pl_syscall_narg = pl->pl_syscall_narg;
488209688Skib}
489205014Snwhitehorn#endif /* COMPAT_FREEBSD32 */
490203696Smarcel
4911541Srgrimes/*
4921541Srgrimes * Process debugging system call.
4931541Srgrimes */
49412221Sbde#ifndef _SYS_SYSPROTO_H_
4951541Srgrimesstruct ptrace_args {
4961541Srgrimes	int	req;
4971541Srgrimes	pid_t	pid;
4981541Srgrimes	caddr_t	addr;
4991541Srgrimes	int	data;
5001541Srgrimes};
50112221Sbde#endif
5021945Sdg
503205014Snwhitehorn#ifdef COMPAT_FREEBSD32
504114028Sjhb/*
505147692Speter * This CPP subterfuge is to try and reduce the number of ifdefs in
506147692Speter * the body of the code.
507147692Speter *   COPYIN(uap->addr, &r.reg, sizeof r.reg);
508147692Speter * becomes either:
509147692Speter *   copyin(uap->addr, &r.reg, sizeof r.reg);
510147692Speter * or
511147692Speter *   copyin(uap->addr, &r.reg32, sizeof r.reg32);
512147692Speter * .. except this is done at runtime.
513147692Speter */
514147692Speter#define	COPYIN(u, k, s)		wrap32 ? \
515147692Speter	copyin(u, k ## 32, s ## 32) : \
516147692Speter	copyin(u, k, s)
517147692Speter#define	COPYOUT(k, u, s)	wrap32 ? \
518147692Speter	copyout(k ## 32, u, s ## 32) : \
519147692Speter	copyout(k, u, s)
520147692Speter#else
521147692Speter#define	COPYIN(u, k, s)		copyin(u, k, s)
522147692Speter#define	COPYOUT(k, u, s)	copyout(k, u, s)
523147692Speter#endif
5241549Srgrimesint
525225617Skmacysys_ptrace(struct thread *td, struct ptrace_args *uap)
5261541Srgrimes{
52791007Sbde	/*
52891007Sbde	 * XXX this obfuscation is to reduce stack usage, but the register
52991007Sbde	 * structs may be too large to put on the stack anyway.
53091007Sbde	 */
53184637Sdes	union {
53292395Sdes		struct ptrace_io_desc piod;
533132016Smarcel		struct ptrace_lwpinfo pl;
534203696Smarcel		struct ptrace_vm_entry pve;
53591007Sbde		struct dbreg dbreg;
53691007Sbde		struct fpreg fpreg;
53791007Sbde		struct reg reg;
538205014Snwhitehorn#ifdef COMPAT_FREEBSD32
539147692Speter		struct dbreg32 dbreg32;
540147692Speter		struct fpreg32 fpreg32;
541147692Speter		struct reg32 reg32;
542147692Speter		struct ptrace_io_desc32 piod32;
543209688Skib		struct ptrace_lwpinfo32 pl32;
544203708Smarcel		struct ptrace_vm_entry32 pve32;
545147692Speter#endif
546304188Sjhb		int ptevents;
54784637Sdes	} r;
548102946Siedowse	void *addr;
549102946Siedowse	int error = 0;
550205014Snwhitehorn#ifdef COMPAT_FREEBSD32
551147692Speter	int wrap32 = 0;
552102946Siedowse
553189282Skib	if (SV_CURPROC_FLAG(SV_ILP32))
554147692Speter		wrap32 = 1;
555147692Speter#endif
556195104Srwatson	AUDIT_ARG_PID(uap->pid);
557195104Srwatson	AUDIT_ARG_CMD(uap->req);
558195104Srwatson	AUDIT_ARG_VALUE(uap->data);
559102946Siedowse	addr = &r;
560102946Siedowse	switch (uap->req) {
561304188Sjhb	case PT_GET_EVENT_MASK:
562102946Siedowse	case PT_GETREGS:
563102946Siedowse	case PT_GETFPREGS:
564102946Siedowse	case PT_GETDBREGS:
565132016Smarcel	case PT_LWPINFO:
566102946Siedowse		break;
567102946Siedowse	case PT_SETREGS:
568147692Speter		error = COPYIN(uap->addr, &r.reg, sizeof r.reg);
569102946Siedowse		break;
570102946Siedowse	case PT_SETFPREGS:
571147692Speter		error = COPYIN(uap->addr, &r.fpreg, sizeof r.fpreg);
572102946Siedowse		break;
573102946Siedowse	case PT_SETDBREGS:
574147692Speter		error = COPYIN(uap->addr, &r.dbreg, sizeof r.dbreg);
575102946Siedowse		break;
576304188Sjhb	case PT_SET_EVENT_MASK:
577304188Sjhb		if (uap->data != sizeof(r.ptevents))
578304188Sjhb			error = EINVAL;
579304188Sjhb		else
580304188Sjhb			error = copyin(uap->addr, &r.ptevents, uap->data);
581304188Sjhb		break;
582102946Siedowse	case PT_IO:
583147692Speter		error = COPYIN(uap->addr, &r.piod, sizeof r.piod);
584102946Siedowse		break;
585203696Smarcel	case PT_VM_ENTRY:
586203696Smarcel		error = COPYIN(uap->addr, &r.pve, sizeof r.pve);
587203696Smarcel		break;
588102946Siedowse	default:
589102946Siedowse		addr = uap->addr;
590118932Smarcel		break;
591102946Siedowse	}
592102946Siedowse	if (error)
593102946Siedowse		return (error);
594102946Siedowse
595102946Siedowse	error = kern_ptrace(td, uap->req, uap->pid, addr, uap->data);
596102946Siedowse	if (error)
597102946Siedowse		return (error);
598102946Siedowse
599102946Siedowse	switch (uap->req) {
600203696Smarcel	case PT_VM_ENTRY:
601203696Smarcel		error = COPYOUT(&r.pve, uap->addr, sizeof r.pve);
602203696Smarcel		break;
603102946Siedowse	case PT_IO:
604147692Speter		error = COPYOUT(&r.piod, uap->addr, sizeof r.piod);
605102946Siedowse		break;
606102946Siedowse	case PT_GETREGS:
607147692Speter		error = COPYOUT(&r.reg, uap->addr, sizeof r.reg);
608102946Siedowse		break;
609102946Siedowse	case PT_GETFPREGS:
610147692Speter		error = COPYOUT(&r.fpreg, uap->addr, sizeof r.fpreg);
611102946Siedowse		break;
612102946Siedowse	case PT_GETDBREGS:
613147692Speter		error = COPYOUT(&r.dbreg, uap->addr, sizeof r.dbreg);
614102946Siedowse		break;
615304188Sjhb	case PT_GET_EVENT_MASK:
616304188Sjhb		/* NB: The size in uap->data is validated in kern_ptrace(). */
617304188Sjhb		error = copyout(&r.ptevents, uap->addr, uap->data);
618304188Sjhb		break;
619132016Smarcel	case PT_LWPINFO:
620304188Sjhb		/* NB: The size in uap->data is validated in kern_ptrace(). */
621132016Smarcel		error = copyout(&r.pl, uap->addr, uap->data);
622132016Smarcel		break;
623102946Siedowse	}
624102946Siedowse
625102946Siedowse	return (error);
626102946Siedowse}
627147692Speter#undef COPYIN
628147692Speter#undef COPYOUT
629102946Siedowse
630205014Snwhitehorn#ifdef COMPAT_FREEBSD32
631147692Speter/*
632147692Speter *   PROC_READ(regs, td2, addr);
633147692Speter * becomes either:
634147692Speter *   proc_read_regs(td2, addr);
635147692Speter * or
636147692Speter *   proc_read_regs32(td2, addr);
637147692Speter * .. except this is done at runtime.  There is an additional
638147692Speter * complication in that PROC_WRITE disallows 32 bit consumers
639147692Speter * from writing to 64 bit address space targets.
640147692Speter */
641147692Speter#define	PROC_READ(w, t, a)	wrap32 ? \
642147692Speter	proc_read_ ## w ## 32(t, a) : \
643147692Speter	proc_read_ ## w (t, a)
644147692Speter#define	PROC_WRITE(w, t, a)	wrap32 ? \
645147692Speter	(safe ? proc_write_ ## w ## 32(t, a) : EINVAL ) : \
646147692Speter	proc_write_ ## w (t, a)
647147692Speter#else
648147692Speter#define	PROC_READ(w, t, a)	proc_read_ ## w (t, a)
649147692Speter#define	PROC_WRITE(w, t, a)	proc_write_ ## w (t, a)
650147692Speter#endif
651147692Speter
652304190Skibvoid
653304613Smarkjproc_set_traced(struct proc *p, bool stop)
654304190Skib{
655304190Skib
656304190Skib	PROC_LOCK_ASSERT(p, MA_OWNED);
657304190Skib	p->p_flag |= P_TRACED;
658304613Smarkj	if (stop)
659304613Smarkj		p->p_flag2 |= P2_PTRACE_FSTP;
660304190Skib	p->p_ptevents = PTRACE_DEFAULT;
661304190Skib	p->p_oppid = p->p_pptr->p_pid;
662304190Skib}
663304190Skib
664102946Siedowseint
665102946Siedowsekern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
666102946Siedowse{
667102946Siedowse	struct iovec iov;
668102946Siedowse	struct uio uio;
66994665Salfred	struct proc *curp, *p, *pp;
670238287Sdavidxu	struct thread *td2 = NULL, *td3;
671147692Speter	struct ptrace_io_desc *piod = NULL;
672132016Smarcel	struct ptrace_lwpinfo *pl;
673132089Sdavidxu	int error, write, tmp, num;
67494556Sjhb	int proctree_locked = 0;
675132089Sdavidxu	lwpid_t tid = 0, *buf;
676205014Snwhitehorn#ifdef COMPAT_FREEBSD32
677147692Speter	int wrap32 = 0, safe = 0;
678147692Speter	struct ptrace_io_desc32 *piod32 = NULL;
679209688Skib	struct ptrace_lwpinfo32 *pl32 = NULL;
680209688Skib	struct ptrace_lwpinfo plr;
681147692Speter#endif
6821541Srgrimes
68394665Salfred	curp = td->td_proc;
68494665Salfred
685102946Siedowse	/* Lock proctree before locking the process. */
686102946Siedowse	switch (req) {
68794556Sjhb	case PT_TRACE_ME:
68894556Sjhb	case PT_ATTACH:
68994556Sjhb	case PT_STEP:
69094556Sjhb	case PT_CONTINUE:
691120937Srobert	case PT_TO_SCE:
692120937Srobert	case PT_TO_SCX:
693143820Sdas	case PT_SYSCALL:
694217819Skib	case PT_FOLLOW_FORK:
695304017Sjhb	case PT_LWP_EVENTS:
696304188Sjhb	case PT_GET_EVENT_MASK:
697304188Sjhb	case PT_SET_EVENT_MASK:
69894556Sjhb	case PT_DETACH:
69994556Sjhb		sx_xlock(&proctree_lock);
70094556Sjhb		proctree_locked = 1;
70194556Sjhb		break;
70294556Sjhb	default:
70395165Smarcel		break;
70494556Sjhb	}
705112389Sdes
70648430Speter	write = 0;
707102946Siedowse	if (req == PT_TRACE_ME) {
70894556Sjhb		p = td->td_proc;
70975893Sjhb		PROC_LOCK(p);
71075893Sjhb	} else {
711131450Sdavidxu		if (pid <= PID_MAX) {
712131450Sdavidxu			if ((p = pfind(pid)) == NULL) {
713131450Sdavidxu				if (proctree_locked)
714131450Sdavidxu					sx_xunlock(&proctree_lock);
715131450Sdavidxu				return (ESRCH);
716131450Sdavidxu			}
717131450Sdavidxu		} else {
718213642Sdavidxu			td2 = tdfind(pid, -1);
719213642Sdavidxu			if (td2 == NULL) {
720131450Sdavidxu				if (proctree_locked)
721131450Sdavidxu					sx_xunlock(&proctree_lock);
722131450Sdavidxu				return (ESRCH);
723131450Sdavidxu			}
724213642Sdavidxu			p = td2->td_proc;
725131450Sdavidxu			tid = pid;
726131450Sdavidxu			pid = p->p_pid;
72794556Sjhb		}
7281945Sdg	}
729195104Srwatson	AUDIT_ARG_PROCESS(p);
730155922Sjhb
731155922Sjhb	if ((p->p_flag & P_WEXIT) != 0) {
732155922Sjhb		error = ESRCH;
733155922Sjhb		goto fail;
734155922Sjhb	}
735100418Srwatson	if ((error = p_cansee(td, p)) != 0)
73694556Sjhb		goto fail;
73784637Sdes
73896886Sjhb	if ((error = p_candebug(td, p)) != 0)
73994556Sjhb		goto fail;
74094556Sjhb
74113607Speter	/*
74291007Sbde	 * System processes can't be debugged.
74384637Sdes	 */
74484637Sdes	if ((p->p_flag & P_SYSTEM) != 0) {
74594556Sjhb		error = EINVAL;
74694556Sjhb		goto fail;
74784637Sdes	}
748112389Sdes
749131450Sdavidxu	if (tid == 0) {
750153697Sdavidxu		if ((p->p_flag & P_STOPPED_TRACE) != 0) {
751153697Sdavidxu			KASSERT(p->p_xthread != NULL, ("NULL p_xthread"));
752153697Sdavidxu			td2 = p->p_xthread;
753153697Sdavidxu		} else {
754153697Sdavidxu			td2 = FIRST_THREAD_IN_PROC(p);
755153697Sdavidxu		}
756131450Sdavidxu		tid = td2->td_tid;
757131450Sdavidxu	}
758131450Sdavidxu
759205014Snwhitehorn#ifdef COMPAT_FREEBSD32
76084637Sdes	/*
761147692Speter	 * Test if we're a 32 bit client and what the target is.
762147692Speter	 * Set the wrap controls accordingly.
763147692Speter	 */
764189282Skib	if (SV_CURPROC_FLAG(SV_ILP32)) {
765217896Sdchagin		if (SV_PROC_FLAG(td2->td_proc, SV_ILP32))
766147692Speter			safe = 1;
767147692Speter		wrap32 = 1;
768147692Speter	}
769147692Speter#endif
770147692Speter	/*
77113607Speter	 * Permissions check
77213607Speter	 */
773102946Siedowse	switch (req) {
77413607Speter	case PT_TRACE_ME:
775290324Skib		/*
776290324Skib		 * Always legal, when there is a parent process which
777290324Skib		 * could trace us.  Otherwise, reject.
778290324Skib		 */
779290324Skib		if ((p->p_flag & P_TRACED) != 0) {
780290324Skib			error = EBUSY;
781290324Skib			goto fail;
782290324Skib		}
783290324Skib		if (p->p_pptr == initproc) {
784290324Skib			error = EPERM;
785290324Skib			goto fail;
786290324Skib		}
78713607Speter		break;
7881945Sdg
78913607Speter	case PT_ATTACH:
79013607Speter		/* Self */
791290323Skib		if (p == td->td_proc) {
79294556Sjhb			error = EINVAL;
79394556Sjhb			goto fail;
79475893Sjhb		}
79513607Speter
79613607Speter		/* Already traced */
79773917Sjhb		if (p->p_flag & P_TRACED) {
79894556Sjhb			error = EBUSY;
79994556Sjhb			goto fail;
80073917Sjhb		}
80113607Speter
80294665Salfred		/* Can't trace an ancestor if you're being traced. */
80394665Salfred		if (curp->p_flag & P_TRACED) {
80494665Salfred			for (pp = curp->p_pptr; pp != NULL; pp = pp->p_pptr) {
80594665Salfred				if (pp == p) {
80694665Salfred					error = EINVAL;
80794665Salfred					goto fail;
80894665Salfred				}
80994665Salfred			}
81094665Salfred		}
81194665Salfred
81294665Salfred
81313607Speter		/* OK */
81413607Speter		break;
81513607Speter
816132089Sdavidxu	case PT_CLEARSTEP:
817132089Sdavidxu		/* Allow thread to clear single step for itself */
818132089Sdavidxu		if (td->td_tid == tid)
819132089Sdavidxu			break;
820132089Sdavidxu
821132089Sdavidxu		/* FALLTHROUGH */
822118932Smarcel	default:
82313607Speter		/* not being traced... */
82473917Sjhb		if ((p->p_flag & P_TRACED) == 0) {
82594556Sjhb			error = EPERM;
82694556Sjhb			goto fail;
82773917Sjhb		}
82813607Speter
82913607Speter		/* not being traced by YOU */
83094556Sjhb		if (p->p_pptr != td->td_proc) {
83194556Sjhb			error = EBUSY;
83294556Sjhb			goto fail;
83370317Sjake		}
83413607Speter
83513607Speter		/* not currently stopped */
836153697Sdavidxu		if ((p->p_flag & (P_STOPPED_SIG | P_STOPPED_TRACE)) == 0 ||
837153697Sdavidxu		    p->p_suspcount != p->p_numthreads  ||
838132089Sdavidxu		    (p->p_flag & P_WAITED) == 0) {
83994556Sjhb			error = EBUSY;
84094556Sjhb			goto fail;
84169506Sjhb		}
84213607Speter
843153697Sdavidxu		if ((p->p_flag & P_STOPPED_TRACE) == 0) {
844153697Sdavidxu			static int count = 0;
845153697Sdavidxu			if (count++ == 0)
846153697Sdavidxu				printf("P_STOPPED_TRACE not set.\n");
847153697Sdavidxu		}
848153697Sdavidxu
84913607Speter		/* OK */
85013607Speter		break;
8511945Sdg	}
85213607Speter
853155922Sjhb	/* Keep this process around until we finish this request. */
854155922Sjhb	_PHOLD(p);
855155922Sjhb
85613607Speter#ifdef FIX_SSTEP
85713607Speter	/*
85813607Speter	 * Single step fixup ala procfs
85913607Speter	 */
860155922Sjhb	FIX_SSTEP(td2);
8611945Sdg#endif
86213607Speter
8631541Srgrimes	/*
86413607Speter	 * Actually do the requests
8651541Srgrimes	 */
8661945Sdg
86783366Sjulian	td->td_retval[0] = 0;
86813607Speter
869102946Siedowse	switch (req) {
87013607Speter	case PT_TRACE_ME:
87113607Speter		/* set my trace flag and "owner" so it can read/write me */
872304613Smarkj		proc_set_traced(p, false);
873246484Skib		if (p->p_flag & P_PPWAIT)
874246484Skib			p->p_flag |= P_PPTRACE;
875284343Sjhb		CTR1(KTR_PTRACE, "PT_TRACE_ME: pid %d", p->p_pid);
876155922Sjhb		break;
8771945Sdg
87813607Speter	case PT_ATTACH:
87913607Speter		/* security check done above */
880223212Sobrien		/*
881223212Sobrien		 * It would be nice if the tracing relationship was separate
882223212Sobrien		 * from the parent relationship but that would require
883223212Sobrien		 * another set of links in the proc struct or for "wait"
884223212Sobrien		 * to scan the entire proc table.  To make life easier,
885223212Sobrien		 * we just re-parent the process we're trying to trace.
886223212Sobrien		 * The old parent is remembered so we can put things back
887223212Sobrien		 * on a "detach".
888223212Sobrien		 */
889304613Smarkj		proc_set_traced(p, true);
890223088Sobrien		if (p->p_pptr != td->td_proc) {
89194556Sjhb			proc_reparent(p, td->td_proc);
892223088Sobrien		}
893102946Siedowse		data = SIGSTOP;
894284343Sjhb		CTR2(KTR_PTRACE, "PT_ATTACH: pid %d, oppid %d", p->p_pid,
895284343Sjhb		    p->p_oppid);
89613607Speter		goto sendsig;	/* in PT_CONTINUE below */
89713607Speter
898132089Sdavidxu	case PT_CLEARSTEP:
899284343Sjhb		CTR2(KTR_PTRACE, "PT_CLEARSTEP: tid %d (pid %d)", td2->td_tid,
900284343Sjhb		    p->p_pid);
901132089Sdavidxu		error = ptrace_clear_single_step(td2);
902155922Sjhb		break;
903132089Sdavidxu
904132089Sdavidxu	case PT_SETSTEP:
905284343Sjhb		CTR2(KTR_PTRACE, "PT_SETSTEP: tid %d (pid %d)", td2->td_tid,
906284343Sjhb		    p->p_pid);
907132089Sdavidxu		error = ptrace_single_step(td2);
908155922Sjhb		break;
909132089Sdavidxu
910132089Sdavidxu	case PT_SUSPEND:
911284343Sjhb		CTR2(KTR_PTRACE, "PT_SUSPEND: tid %d (pid %d)", td2->td_tid,
912284343Sjhb		    p->p_pid);
913183911Sdavidxu		td2->td_dbgflags |= TDB_SUSPEND;
914170307Sjeff		thread_lock(td2);
915183911Sdavidxu		td2->td_flags |= TDF_NEEDSUSPCHK;
916170307Sjeff		thread_unlock(td2);
917155922Sjhb		break;
918132089Sdavidxu
919132089Sdavidxu	case PT_RESUME:
920284343Sjhb		CTR2(KTR_PTRACE, "PT_RESUME: tid %d (pid %d)", td2->td_tid,
921284343Sjhb		    p->p_pid);
922183911Sdavidxu		td2->td_dbgflags &= ~TDB_SUSPEND;
923155922Sjhb		break;
924132089Sdavidxu
925217819Skib	case PT_FOLLOW_FORK:
926284343Sjhb		CTR3(KTR_PTRACE, "PT_FOLLOW_FORK: pid %d %s -> %s", p->p_pid,
927304188Sjhb		    p->p_ptevents & PTRACE_FORK ? "enabled" : "disabled",
928284343Sjhb		    data ? "enabled" : "disabled");
929217819Skib		if (data)
930304188Sjhb			p->p_ptevents |= PTRACE_FORK;
931217819Skib		else
932304188Sjhb			p->p_ptevents &= ~PTRACE_FORK;
933217819Skib		break;
934217819Skib
935304017Sjhb	case PT_LWP_EVENTS:
936304017Sjhb		CTR3(KTR_PTRACE, "PT_LWP_EVENTS: pid %d %s -> %s", p->p_pid,
937304188Sjhb		    p->p_ptevents & PTRACE_LWP ? "enabled" : "disabled",
938304017Sjhb		    data ? "enabled" : "disabled");
939304017Sjhb		if (data)
940304188Sjhb			p->p_ptevents |= PTRACE_LWP;
941304017Sjhb		else
942304188Sjhb			p->p_ptevents &= ~PTRACE_LWP;
943304017Sjhb		break;
944304017Sjhb
945304188Sjhb	case PT_GET_EVENT_MASK:
946304188Sjhb		if (data != sizeof(p->p_ptevents)) {
947304188Sjhb			error = EINVAL;
948304188Sjhb			break;
949304188Sjhb		}
950304188Sjhb		CTR2(KTR_PTRACE, "PT_GET_EVENT_MASK: pid %d mask %#x", p->p_pid,
951304188Sjhb		    p->p_ptevents);
952304188Sjhb		*(int *)addr = p->p_ptevents;
953304188Sjhb		break;
954304188Sjhb
955304188Sjhb	case PT_SET_EVENT_MASK:
956304188Sjhb		if (data != sizeof(p->p_ptevents)) {
957304188Sjhb			error = EINVAL;
958304188Sjhb			break;
959304188Sjhb		}
960304188Sjhb		tmp = *(int *)addr;
961304188Sjhb		if ((tmp & ~(PTRACE_EXEC | PTRACE_SCE | PTRACE_SCX |
962304499Sjhb		    PTRACE_FORK | PTRACE_LWP | PTRACE_VFORK)) != 0) {
963304188Sjhb			error = EINVAL;
964304188Sjhb			break;
965304188Sjhb		}
966304188Sjhb		CTR3(KTR_PTRACE, "PT_SET_EVENT_MASK: pid %d mask %#x -> %#x",
967304188Sjhb		    p->p_pid, p->p_ptevents, tmp);
968304188Sjhb		p->p_ptevents = tmp;
969304188Sjhb		break;
970304188Sjhb
97113607Speter	case PT_STEP:
97213607Speter	case PT_CONTINUE:
973120937Srobert	case PT_TO_SCE:
974120937Srobert	case PT_TO_SCX:
975143820Sdas	case PT_SYSCALL:
9761945Sdg	case PT_DETACH:
977118749Snectar		/* Zero means do not send any signal */
978118749Snectar		if (data < 0 || data > _SIG_MAXSIG) {
97994556Sjhb			error = EINVAL;
980155922Sjhb			break;
98194556Sjhb		}
98213607Speter
983120937Srobert		switch (req) {
984120937Srobert		case PT_STEP:
985324215Sjhb			CTR3(KTR_PTRACE, "PT_STEP: tid %d (pid %d), sig = %d",
986324215Sjhb			    td2->td_tid, p->p_pid, data);
98790391Speter			error = ptrace_single_step(td2);
988155922Sjhb			if (error)
989155922Sjhb				goto out;
990120937Srobert			break;
991208555Sjhb		case PT_CONTINUE:
992120937Srobert		case PT_TO_SCE:
993120937Srobert		case PT_TO_SCX:
994120937Srobert		case PT_SYSCALL:
995208555Sjhb			if (addr != (void *)1) {
996208555Sjhb				error = ptrace_set_pc(td2,
997208555Sjhb				    (u_long)(uintfptr_t)addr);
998208555Sjhb				if (error)
999208555Sjhb					goto out;
1000208555Sjhb			}
1001208555Sjhb			switch (req) {
1002208555Sjhb			case PT_TO_SCE:
1003304188Sjhb				p->p_ptevents |= PTRACE_SCE;
1004290456Sjhb				CTR4(KTR_PTRACE,
1005304188Sjhb		    "PT_TO_SCE: pid %d, events = %#x, PC = %#lx, sig = %d",
1006304188Sjhb				    p->p_pid, p->p_ptevents,
1007290456Sjhb				    (u_long)(uintfptr_t)addr, data);
1008208555Sjhb				break;
1009208555Sjhb			case PT_TO_SCX:
1010304188Sjhb				p->p_ptevents |= PTRACE_SCX;
1011290456Sjhb				CTR4(KTR_PTRACE,
1012304188Sjhb		    "PT_TO_SCX: pid %d, events = %#x, PC = %#lx, sig = %d",
1013304188Sjhb				    p->p_pid, p->p_ptevents,
1014290456Sjhb				    (u_long)(uintfptr_t)addr, data);
1015208555Sjhb				break;
1016208555Sjhb			case PT_SYSCALL:
1017304188Sjhb				p->p_ptevents |= PTRACE_SYSCALL;
1018290456Sjhb				CTR4(KTR_PTRACE,
1019304188Sjhb		    "PT_SYSCALL: pid %d, events = %#x, PC = %#lx, sig = %d",
1020304188Sjhb				    p->p_pid, p->p_ptevents,
1021290456Sjhb				    (u_long)(uintfptr_t)addr, data);
1022208555Sjhb				break;
1023284343Sjhb			case PT_CONTINUE:
1024290456Sjhb				CTR3(KTR_PTRACE,
1025290456Sjhb				    "PT_CONTINUE: pid %d, PC = %#lx, sig = %d",
1026290456Sjhb				    p->p_pid, (u_long)(uintfptr_t)addr, data);
1027284343Sjhb				break;
1028208555Sjhb			}
1029120937Srobert			break;
1030208555Sjhb		case PT_DETACH:
1031287604Sjhb			/*
1032287604Sjhb			 * Reset the process parent.
1033287604Sjhb			 *
1034287604Sjhb			 * NB: This clears P_TRACED before reparenting
1035287604Sjhb			 * a detached process back to its original
1036287604Sjhb			 * parent.  Otherwise the debugee will be set
1037287604Sjhb			 * as an orphan of the debugger.
1038287604Sjhb			 */
1039304188Sjhb			p->p_flag &= ~(P_TRACED | P_WAITED);
104013607Speter			if (p->p_oppid != p->p_pptr->p_pid) {
1041152214Sdavidxu				PROC_LOCK(p->p_pptr);
1042152214Sdavidxu				sigqueue_take(p->p_ksi);
1043152214Sdavidxu				PROC_UNLOCK(p->p_pptr);
1044152214Sdavidxu
1045270264Skib				pp = proc_realparent(p);
104676274Sjhb				proc_reparent(p, pp);
1047125993Struckman				if (pp == initproc)
1048125993Struckman					p->p_sigparent = SIGCHLD;
1049290456Sjhb				CTR3(KTR_PTRACE,
1050290456Sjhb			    "PT_DETACH: pid %d reparented to pid %d, sig %d",
1051290456Sjhb				    p->p_pid, pp->p_pid, data);
1052284343Sjhb			} else
1053290456Sjhb				CTR2(KTR_PTRACE, "PT_DETACH: pid %d, sig %d",
1054290456Sjhb				    p->p_pid, data);
1055223088Sobrien			p->p_oppid = 0;
1056304188Sjhb			p->p_ptevents = 0;
1057304190Skib			FOREACH_THREAD_IN_PROC(p, td3) {
1058304190Skib				if ((td3->td_dbgflags & TDB_FSTP) != 0) {
1059304190Skib					sigqueue_delete(&td3->td_sigqueue,
1060304190Skib					    SIGSTOP);
1061304190Skib				}
1062304190Skib				td3->td_dbgflags &= ~(TDB_XSIG | TDB_FSTP);
1063304190Skib			}
1064304190Skib			if ((p->p_flag2 & P2_PTRACE_FSTP) != 0) {
1065304190Skib				sigqueue_delete(&p->p_sigqueue, SIGSTOP);
1066304190Skib				p->p_flag2 &= ~P2_PTRACE_FSTP;
1067304190Skib			}
106873917Sjhb
106913607Speter			/* should we send SIGCHLD? */
1070152214Sdavidxu			/* childproc_continued(p); */
1071208555Sjhb			break;
107213607Speter		}
107313607Speter
107413607Speter	sendsig:
1075328379Sjhb		/*
1076328379Sjhb		 * Clear the pending event for the thread that just
1077328379Sjhb		 * reported its event (p_xthread).  This may not be
1078328379Sjhb		 * the thread passed to PT_CONTINUE, PT_STEP, etc. if
1079328379Sjhb		 * the debugger is resuming a different thread.
1080328379Sjhb		 */
1081328379Sjhb		td2 = p->p_xthread;
1082155922Sjhb		if (proctree_locked) {
108394556Sjhb			sx_xunlock(&proctree_lock);
1084155922Sjhb			proctree_locked = 0;
1085155922Sjhb		}
1086153697Sdavidxu		p->p_xstat = data;
1087153697Sdavidxu		p->p_xthread = NULL;
1088153697Sdavidxu		if ((p->p_flag & (P_STOPPED_SIG | P_STOPPED_TRACE)) != 0) {
1089172485Sjeff			/* deliver or queue signal */
1090183911Sdavidxu			td2->td_dbgflags &= ~TDB_XSIG;
1091172485Sjeff			td2->td_xsig = data;
1092172485Sjeff
1093315949Sbadger			/*
1094315949Sbadger			 * P_WKILLED is insurance that a PT_KILL/SIGKILL always
1095315949Sbadger			 * works immediately, even if another thread is
1096315949Sbadger			 * unsuspended first and attempts to handle a different
1097315949Sbadger			 * signal or if the POSIX.1b style signal queue cannot
1098315949Sbadger			 * accommodate any new signals.
1099315949Sbadger			 */
1100315949Sbadger			if (data == SIGKILL)
1101315949Sbadger				p->p_flag |= P_WKILLED;
1102315949Sbadger
1103132089Sdavidxu			if (req == PT_DETACH) {
1104238287Sdavidxu				FOREACH_THREAD_IN_PROC(p, td3)
1105304190Skib					td3->td_dbgflags &= ~TDB_SUSPEND;
1106132089Sdavidxu			}
1107132089Sdavidxu			/*
1108132089Sdavidxu			 * unsuspend all threads, to not let a thread run,
1109132089Sdavidxu			 * you should use PT_SUSPEND to suspend it before
1110132089Sdavidxu			 * continuing process.
1111132089Sdavidxu			 */
1112184667Sdavidxu			PROC_SLOCK(p);
1113153697Sdavidxu			p->p_flag &= ~(P_STOPPED_TRACE|P_STOPPED_SIG|P_WAITED);
1114103216Sjulian			thread_unsuspend(p);
1115184667Sdavidxu			PROC_SUNLOCK(p);
1116238287Sdavidxu			if (req == PT_ATTACH)
1117238287Sdavidxu				kern_psignal(p, data);
1118172485Sjeff		} else {
1119172485Sjeff			if (data)
1120225617Skmacy				kern_psignal(p, data);
1121153697Sdavidxu		}
1122155922Sjhb		break;
11231945Sdg
11241945Sdg	case PT_WRITE_I:
11251945Sdg	case PT_WRITE_D:
1126202882Skib		td2->td_dbgflags |= TDB_USERWR;
112713607Speter		write = 1;
1128102412Scharnier		/* FALLTHROUGH */
112913607Speter	case PT_READ_I:
113013607Speter	case PT_READ_D:
113194556Sjhb		PROC_UNLOCK(p);
113299880Stmm		tmp = 0;
113313607Speter		/* write = 0 set above */
1134102946Siedowse		iov.iov_base = write ? (caddr_t)&data : (caddr_t)&tmp;
113513607Speter		iov.iov_len = sizeof(int);
113613607Speter		uio.uio_iov = &iov;
113713607Speter		uio.uio_iovcnt = 1;
1138102946Siedowse		uio.uio_offset = (off_t)(uintptr_t)addr;
113913607Speter		uio.uio_resid = sizeof(int);
114091007Sbde		uio.uio_segflg = UIO_SYSSPACE;	/* i.e.: the uap */
114113607Speter		uio.uio_rw = write ? UIO_WRITE : UIO_READ;
114283366Sjulian		uio.uio_td = td;
114384637Sdes		error = proc_rwmem(p, &uio);
114414925Speter		if (uio.uio_resid != 0) {
114514925Speter			/*
114684637Sdes			 * XXX proc_rwmem() doesn't currently return ENOSPC,
114714925Speter			 * so I think write() can bogusly return 0.
114814925Speter			 * XXX what happens for short writes?  We don't want
114914925Speter			 * to write partial data.
115084637Sdes			 * XXX proc_rwmem() returns EPERM for other invalid
115114925Speter			 * addresses.  Convert this to EINVAL.  Does this
115214925Speter			 * clobber returns of EPERM for other reasons?
115314925Speter			 */
115414925Speter			if (error == 0 || error == ENOSPC || error == EPERM)
115514925Speter				error = EINVAL;	/* EOF */
115614925Speter		}
115799880Stmm		if (!write)
115899880Stmm			td->td_retval[0] = tmp;
1159284343Sjhb		if (error == 0) {
1160284343Sjhb			if (write)
1161284343Sjhb				CTR3(KTR_PTRACE, "PT_WRITE: pid %d: %p <= %#x",
1162284343Sjhb				    p->p_pid, addr, data);
1163284343Sjhb			else
1164284343Sjhb				CTR3(KTR_PTRACE, "PT_READ: pid %d: %p >= %#x",
1165284343Sjhb				    p->p_pid, addr, tmp);
1166284343Sjhb		}
1167155922Sjhb		PROC_LOCK(p);
1168155922Sjhb		break;
11691945Sdg
117092395Sdes	case PT_IO:
1171205014Snwhitehorn#ifdef COMPAT_FREEBSD32
1172147692Speter		if (wrap32) {
1173147692Speter			piod32 = addr;
1174147692Speter			iov.iov_base = (void *)(uintptr_t)piod32->piod_addr;
1175147692Speter			iov.iov_len = piod32->piod_len;
1176147692Speter			uio.uio_offset = (off_t)(uintptr_t)piod32->piod_offs;
1177147692Speter			uio.uio_resid = piod32->piod_len;
1178147692Speter		} else
1179147692Speter#endif
1180147692Speter		{
1181147692Speter			piod = addr;
1182147692Speter			iov.iov_base = piod->piod_addr;
1183147692Speter			iov.iov_len = piod->piod_len;
1184147692Speter			uio.uio_offset = (off_t)(uintptr_t)piod->piod_offs;
1185147692Speter			uio.uio_resid = piod->piod_len;
1186147692Speter		}
118792395Sdes		uio.uio_iov = &iov;
118892395Sdes		uio.uio_iovcnt = 1;
118992395Sdes		uio.uio_segflg = UIO_USERSPACE;
119092395Sdes		uio.uio_td = td;
1191205014Snwhitehorn#ifdef COMPAT_FREEBSD32
1192147692Speter		tmp = wrap32 ? piod32->piod_op : piod->piod_op;
1193147692Speter#else
1194147692Speter		tmp = piod->piod_op;
1195147692Speter#endif
1196147692Speter		switch (tmp) {
119792395Sdes		case PIOD_READ_D:
119892395Sdes		case PIOD_READ_I:
1199284343Sjhb			CTR3(KTR_PTRACE, "PT_IO: pid %d: READ (%p, %#x)",
1200284343Sjhb			    p->p_pid, (uintptr_t)uio.uio_offset, uio.uio_resid);
120192395Sdes			uio.uio_rw = UIO_READ;
120292395Sdes			break;
120392395Sdes		case PIOD_WRITE_D:
120492395Sdes		case PIOD_WRITE_I:
1205284343Sjhb			CTR3(KTR_PTRACE, "PT_IO: pid %d: WRITE (%p, %#x)",
1206284343Sjhb			    p->p_pid, (uintptr_t)uio.uio_offset, uio.uio_resid);
1207202882Skib			td2->td_dbgflags |= TDB_USERWR;
120892395Sdes			uio.uio_rw = UIO_WRITE;
120992395Sdes			break;
121092395Sdes		default:
1211155922Sjhb			error = EINVAL;
1212155922Sjhb			goto out;
121392395Sdes		}
1214155922Sjhb		PROC_UNLOCK(p);
121592395Sdes		error = proc_rwmem(p, &uio);
1216205014Snwhitehorn#ifdef COMPAT_FREEBSD32
1217147692Speter		if (wrap32)
1218147692Speter			piod32->piod_len -= uio.uio_resid;
1219147692Speter		else
1220147692Speter#endif
1221147692Speter			piod->piod_len -= uio.uio_resid;
1222155922Sjhb		PROC_LOCK(p);
1223155922Sjhb		break;
122492395Sdes
12251945Sdg	case PT_KILL:
1226284343Sjhb		CTR1(KTR_PTRACE, "PT_KILL: pid %d", p->p_pid);
1227102946Siedowse		data = SIGKILL;
122813607Speter		goto sendsig;	/* in PT_CONTINUE above */
122913607Speter
123013607Speter	case PT_SETREGS:
1231284343Sjhb		CTR2(KTR_PTRACE, "PT_SETREGS: tid %d (pid %d)", td2->td_tid,
1232284343Sjhb		    p->p_pid);
1233202882Skib		td2->td_dbgflags |= TDB_USERWR;
1234147692Speter		error = PROC_WRITE(regs, td2, addr);
1235155922Sjhb		break;
123684637Sdes
12371945Sdg	case PT_GETREGS:
1238284343Sjhb		CTR2(KTR_PTRACE, "PT_GETREGS: tid %d (pid %d)", td2->td_tid,
1239284343Sjhb		    p->p_pid);
1240147692Speter		error = PROC_READ(regs, td2, addr);
1241155922Sjhb		break;
124213607Speter
124313607Speter	case PT_SETFPREGS:
1244284343Sjhb		CTR2(KTR_PTRACE, "PT_SETFPREGS: tid %d (pid %d)", td2->td_tid,
1245284343Sjhb		    p->p_pid);
1246202882Skib		td2->td_dbgflags |= TDB_USERWR;
1247147692Speter		error = PROC_WRITE(fpregs, td2, addr);
1248155922Sjhb		break;
124984637Sdes
125013607Speter	case PT_GETFPREGS:
1251284343Sjhb		CTR2(KTR_PTRACE, "PT_GETFPREGS: tid %d (pid %d)", td2->td_tid,
1252284343Sjhb		    p->p_pid);
1253147692Speter		error = PROC_READ(fpregs, td2, addr);
1254155922Sjhb		break;
125513607Speter
125648691Sjlemon	case PT_SETDBREGS:
1257284343Sjhb		CTR2(KTR_PTRACE, "PT_SETDBREGS: tid %d (pid %d)", td2->td_tid,
1258284343Sjhb		    p->p_pid);
1259202882Skib		td2->td_dbgflags |= TDB_USERWR;
1260147692Speter		error = PROC_WRITE(dbregs, td2, addr);
1261155922Sjhb		break;
126292369Sdes
126348691Sjlemon	case PT_GETDBREGS:
1264284343Sjhb		CTR2(KTR_PTRACE, "PT_GETDBREGS: tid %d (pid %d)", td2->td_tid,
1265284343Sjhb		    p->p_pid);
1266147692Speter		error = PROC_READ(dbregs, td2, addr);
1267155922Sjhb		break;
126848691Sjlemon
1269132016Smarcel	case PT_LWPINFO:
1270209688Skib		if (data <= 0 ||
1271209688Skib#ifdef COMPAT_FREEBSD32
1272209688Skib		    (!wrap32 && data > sizeof(*pl)) ||
1273209688Skib		    (wrap32 && data > sizeof(*pl32))) {
1274209688Skib#else
1275209688Skib		    data > sizeof(*pl)) {
1276209688Skib#endif
1277155922Sjhb			error = EINVAL;
1278155922Sjhb			break;
1279155922Sjhb		}
1280209688Skib#ifdef COMPAT_FREEBSD32
1281209688Skib		if (wrap32) {
1282209688Skib			pl = &plr;
1283209688Skib			pl32 = addr;
1284209688Skib		} else
1285209688Skib#endif
1286132016Smarcel		pl = addr;
1287325643Skib		bzero(pl, sizeof(*pl));
1288153697Sdavidxu		pl->pl_lwpid = td2->td_tid;
1289239135Skib		pl->pl_event = PL_EVENT_NONE;
1290209688Skib		pl->pl_flags = 0;
1291209688Skib		if (td2->td_dbgflags & TDB_XSIG) {
1292132089Sdavidxu			pl->pl_event = PL_EVENT_SIGNAL;
1293209688Skib			if (td2->td_dbgksi.ksi_signo != 0 &&
1294209688Skib#ifdef COMPAT_FREEBSD32
1295209688Skib			    ((!wrap32 && data >= offsetof(struct ptrace_lwpinfo,
1296209688Skib			    pl_siginfo) + sizeof(pl->pl_siginfo)) ||
1297209688Skib			    (wrap32 && data >= offsetof(struct ptrace_lwpinfo32,
1298209688Skib			    pl_siginfo) + sizeof(struct siginfo32)))
1299209688Skib#else
1300209688Skib			    data >= offsetof(struct ptrace_lwpinfo, pl_siginfo)
1301209688Skib			    + sizeof(pl->pl_siginfo)
1302209688Skib#endif
1303209688Skib			){
1304209688Skib				pl->pl_flags |= PL_FLAG_SI;
1305209688Skib				pl->pl_siginfo = td2->td_dbgksi.ksi_info;
1306209688Skib			}
1307209688Skib		}
1308208453Skib		if (td2->td_dbgflags & TDB_SCE)
1309208453Skib			pl->pl_flags |= PL_FLAG_SCE;
1310208453Skib		else if (td2->td_dbgflags & TDB_SCX)
1311208453Skib			pl->pl_flags |= PL_FLAG_SCX;
1312208453Skib		if (td2->td_dbgflags & TDB_EXEC)
1313208453Skib			pl->pl_flags |= PL_FLAG_EXEC;
1314217819Skib		if (td2->td_dbgflags & TDB_FORK) {
1315217819Skib			pl->pl_flags |= PL_FLAG_FORKED;
1316217819Skib			pl->pl_child_pid = td2->td_dbg_forked;
1317304499Sjhb			if (td2->td_dbgflags & TDB_VFORK)
1318304499Sjhb				pl->pl_flags |= PL_FLAG_VFORKED;
1319304499Sjhb		} else if ((td2->td_dbgflags & (TDB_SCX | TDB_VFORK)) ==
1320304499Sjhb		    TDB_VFORK)
1321304499Sjhb			pl->pl_flags |= PL_FLAG_VFORK_DONE;
1322231320Skib		if (td2->td_dbgflags & TDB_CHILD)
1323231320Skib			pl->pl_flags |= PL_FLAG_CHILD;
1324304017Sjhb		if (td2->td_dbgflags & TDB_BORN)
1325304017Sjhb			pl->pl_flags |= PL_FLAG_BORN;
1326304017Sjhb		if (td2->td_dbgflags & TDB_EXIT)
1327304017Sjhb			pl->pl_flags |= PL_FLAG_EXITED;
1328155381Sdavidxu		pl->pl_sigmask = td2->td_sigmask;
1329155381Sdavidxu		pl->pl_siglist = td2->td_siglist;
1330215679Sattilio		strcpy(pl->pl_tdname, td2->td_name);
1331289780Sjhb		if ((td2->td_dbgflags & (TDB_SCE | TDB_SCX)) != 0) {
1332289780Sjhb			pl->pl_syscall_code = td2->td_dbg_sc_code;
1333289780Sjhb			pl->pl_syscall_narg = td2->td_dbg_sc_narg;
1334289780Sjhb		} else {
1335289780Sjhb			pl->pl_syscall_code = 0;
1336289780Sjhb			pl->pl_syscall_narg = 0;
1337289780Sjhb		}
1338209688Skib#ifdef COMPAT_FREEBSD32
1339209688Skib		if (wrap32)
1340209688Skib			ptrace_lwpinfo_to32(pl, pl32);
1341209688Skib#endif
1342290456Sjhb		CTR6(KTR_PTRACE,
1343290456Sjhb    "PT_LWPINFO: tid %d (pid %d) event %d flags %#x child pid %d syscall %d",
1344284343Sjhb		    td2->td_tid, p->p_pid, pl->pl_event, pl->pl_flags,
1345290456Sjhb		    pl->pl_child_pid, pl->pl_syscall_code);
1346155922Sjhb		break;
1347132016Smarcel
1348132089Sdavidxu	case PT_GETNUMLWPS:
1349284343Sjhb		CTR2(KTR_PTRACE, "PT_GETNUMLWPS: pid %d: %d threads", p->p_pid,
1350284343Sjhb		    p->p_numthreads);
1351132089Sdavidxu		td->td_retval[0] = p->p_numthreads;
1352155922Sjhb		break;
1353132089Sdavidxu
1354132089Sdavidxu	case PT_GETLWPLIST:
1355284343Sjhb		CTR3(KTR_PTRACE, "PT_GETLWPLIST: pid %d: data %d, actual %d",
1356284343Sjhb		    p->p_pid, data, p->p_numthreads);
1357132089Sdavidxu		if (data <= 0) {
1358155922Sjhb			error = EINVAL;
1359155922Sjhb			break;
1360132089Sdavidxu		}
1361132089Sdavidxu		num = imin(p->p_numthreads, data);
1362132089Sdavidxu		PROC_UNLOCK(p);
1363132089Sdavidxu		buf = malloc(num * sizeof(lwpid_t), M_TEMP, M_WAITOK);
1364132089Sdavidxu		tmp = 0;
1365132089Sdavidxu		PROC_LOCK(p);
1366132089Sdavidxu		FOREACH_THREAD_IN_PROC(p, td2) {
1367132089Sdavidxu			if (tmp >= num)
1368132089Sdavidxu				break;
1369132089Sdavidxu			buf[tmp++] = td2->td_tid;
1370132089Sdavidxu		}
1371132089Sdavidxu		PROC_UNLOCK(p);
1372132089Sdavidxu		error = copyout(buf, addr, tmp * sizeof(lwpid_t));
1373132089Sdavidxu		free(buf, M_TEMP);
1374132089Sdavidxu		if (!error)
1375163345Strhodes			td->td_retval[0] = tmp;
1376155922Sjhb		PROC_LOCK(p);
1377155922Sjhb		break;
1378132089Sdavidxu
1379203696Smarcel	case PT_VM_TIMESTAMP:
1380284343Sjhb		CTR2(KTR_PTRACE, "PT_VM_TIMESTAMP: pid %d: timestamp %d",
1381284343Sjhb		    p->p_pid, p->p_vmspace->vm_map.timestamp);
1382203696Smarcel		td->td_retval[0] = p->p_vmspace->vm_map.timestamp;
1383203696Smarcel		break;
1384203696Smarcel
1385203696Smarcel	case PT_VM_ENTRY:
1386203783Smarcel		PROC_UNLOCK(p);
1387205014Snwhitehorn#ifdef COMPAT_FREEBSD32
1388203783Smarcel		if (wrap32)
1389203783Smarcel			error = ptrace_vm_entry32(td, p, addr);
1390203783Smarcel		else
1391203708Smarcel#endif
1392203696Smarcel		error = ptrace_vm_entry(td, p, addr);
1393203696Smarcel		PROC_LOCK(p);
1394203696Smarcel		break;
1395203696Smarcel
13961945Sdg	default:
1397118932Smarcel#ifdef __HAVE_PTRACE_MACHDEP
1398118932Smarcel		if (req >= PT_FIRSTMACH) {
1399127034Sjhb			PROC_UNLOCK(p);
1400118932Smarcel			error = cpu_ptrace(td2, req, addr, data);
1401155922Sjhb			PROC_LOCK(p);
1402155922Sjhb		} else
1403118932Smarcel#endif
1404155922Sjhb			/* Unknown request. */
1405155922Sjhb			error = EINVAL;
14061945Sdg		break;
14071945Sdg	}
14081945Sdg
1409155922Sjhbout:
1410155922Sjhb	/* Drop our hold on this process now that the request has completed. */
1411155922Sjhb	_PRELE(p);
141294556Sjhbfail:
141394556Sjhb	PROC_UNLOCK(p);
141494556Sjhb	if (proctree_locked)
141594556Sjhb		sx_xunlock(&proctree_lock);
141694556Sjhb	return (error);
14171541Srgrimes}
1418147692Speter#undef PROC_READ
1419147692Speter#undef PROC_WRITE
14201541Srgrimes
142131564Ssef/*
142284637Sdes * Stop a process because of a debugging event;
142331564Ssef * stay stopped until p->p_step is cleared
142431564Ssef * (cleared by PIOCCONT in procfs).
142531564Ssef */
142631564Ssefvoid
142784637Sdesstopevent(struct proc *p, unsigned int event, unsigned int val)
142871567Sjhb{
142971567Sjhb
1430113635Sjhb	PROC_LOCK_ASSERT(p, MA_OWNED);
143131564Ssef	p->p_step = 1;
1432284343Sjhb	CTR3(KTR_PTRACE, "stopevent: pid %d event %u val %u", p->p_pid, event,
1433284343Sjhb	    val);
143431564Ssef	do {
143531564Ssef		p->p_xstat = val;
1436132089Sdavidxu		p->p_xthread = NULL;
143731564Ssef		p->p_stype = event;	/* Which event caused the stop? */
143831564Ssef		wakeup(&p->p_stype);	/* Wake up any PIOCWAIT'ing procs */
143971567Sjhb		msleep(&p->p_step, &p->p_mtx, PWAIT, "stopevent", 0);
144031564Ssef	} while (p->p_step);
144131564Ssef}
1442