xref: /freebsd/lib/libproc/proc_util.c (revision 4c74b2455d9de9e7d7abf91d9d4304e53e50a987)
12c633af4SJohn Birrell /*-
28eb20f36SRui Paulo  * Copyright (c) 2010 The FreeBSD Foundation
32c633af4SJohn Birrell  * Copyright (c) 2008 John Birrell (jb@freebsd.org)
42c633af4SJohn Birrell  * All rights reserved.
52c633af4SJohn Birrell  *
68eb20f36SRui Paulo  * Portions of this software were developed by Rui Paulo under sponsorship
78eb20f36SRui Paulo  * from the FreeBSD Foundation.
88eb20f36SRui Paulo  *
92c633af4SJohn Birrell  * Redistribution and use in source and binary forms, with or without
102c633af4SJohn Birrell  * modification, are permitted provided that the following conditions
112c633af4SJohn Birrell  * are met:
122c633af4SJohn Birrell  * 1. Redistributions of source code must retain the above copyright
132c633af4SJohn Birrell  *    notice, this list of conditions and the following disclaimer.
142c633af4SJohn Birrell  * 2. Redistributions in binary form must reproduce the above copyright
152c633af4SJohn Birrell  *    notice, this list of conditions and the following disclaimer in the
162c633af4SJohn Birrell  *    documentation and/or other materials provided with the distribution.
172c633af4SJohn Birrell  *
182c633af4SJohn Birrell  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
192c633af4SJohn Birrell  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
202c633af4SJohn Birrell  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
212c633af4SJohn Birrell  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
222c633af4SJohn Birrell  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
232c633af4SJohn Birrell  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
242c633af4SJohn Birrell  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
252c633af4SJohn Birrell  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
262c633af4SJohn Birrell  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
272c633af4SJohn Birrell  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
282c633af4SJohn Birrell  * SUCH DAMAGE.
292c633af4SJohn Birrell  *
302c633af4SJohn Birrell  * $FreeBSD$
312c633af4SJohn Birrell  */
322c633af4SJohn Birrell 
338eb20f36SRui Paulo #include <sys/types.h>
342c633af4SJohn Birrell #include <sys/ptrace.h>
352c633af4SJohn Birrell #include <sys/wait.h>
368eb20f36SRui Paulo #include <err.h>
378eb20f36SRui Paulo #include <errno.h>
388eb20f36SRui Paulo #include <unistd.h>
392c633af4SJohn Birrell #include <stdio.h>
408eb20f36SRui Paulo #include <signal.h>
418eb20f36SRui Paulo #include <string.h>
428eb20f36SRui Paulo #include "_libproc.h"
432c633af4SJohn Birrell 
442c633af4SJohn Birrell int
452c633af4SJohn Birrell proc_clearflags(struct proc_handle *phdl, int mask)
462c633af4SJohn Birrell {
478eb20f36SRui Paulo 
482c633af4SJohn Birrell 	if (phdl == NULL)
492c633af4SJohn Birrell 		return (EINVAL);
502c633af4SJohn Birrell 
512c633af4SJohn Birrell 	phdl->flags &= ~mask;
522c633af4SJohn Birrell 
532c633af4SJohn Birrell 	return (0);
542c633af4SJohn Birrell }
552c633af4SJohn Birrell 
568eb20f36SRui Paulo /*
578eb20f36SRui Paulo  * NB: we return -1 as the Solaris libproc Psetrun() function.
588eb20f36SRui Paulo  */
592c633af4SJohn Birrell int
602c633af4SJohn Birrell proc_continue(struct proc_handle *phdl)
612c633af4SJohn Birrell {
628eb20f36SRui Paulo 
632c633af4SJohn Birrell 	if (phdl == NULL)
648eb20f36SRui Paulo 		return (-1);
652c633af4SJohn Birrell 
662c633af4SJohn Birrell 	if (ptrace(PT_CONTINUE, phdl->pid, (caddr_t)(uintptr_t) 1, 0) != 0)
678eb20f36SRui Paulo 		return (-1);
682c633af4SJohn Birrell 
692c633af4SJohn Birrell 	phdl->status = PS_RUN;
702c633af4SJohn Birrell 
712c633af4SJohn Birrell 	return (0);
722c633af4SJohn Birrell }
732c633af4SJohn Birrell 
742c633af4SJohn Birrell int
758eb20f36SRui Paulo proc_detach(struct proc_handle *phdl, int reason)
762c633af4SJohn Birrell {
778eb20f36SRui Paulo 	int status;
788eb20f36SRui Paulo 
792c633af4SJohn Birrell 	if (phdl == NULL)
802c633af4SJohn Birrell 		return (EINVAL);
818eb20f36SRui Paulo 	if (reason == PRELEASE_KILL) {
828eb20f36SRui Paulo 		kill(phdl->pid, SIGKILL);
838eb20f36SRui Paulo 		return (0);
848eb20f36SRui Paulo 	}
858eb20f36SRui Paulo 	if (ptrace(PT_DETACH, phdl->pid, 0, 0) != 0 && errno == ESRCH)
868eb20f36SRui Paulo 		return (0);
878eb20f36SRui Paulo 	if (errno == EBUSY) {
888eb20f36SRui Paulo 		kill(phdl->pid, SIGSTOP);
898eb20f36SRui Paulo 		waitpid(phdl->pid, &status, WUNTRACED);
908eb20f36SRui Paulo 		ptrace(PT_DETACH, phdl->pid, 0, 0);
918eb20f36SRui Paulo 		kill(phdl->pid, SIGCONT);
928eb20f36SRui Paulo 		return (0);
938eb20f36SRui Paulo 	}
942c633af4SJohn Birrell 
952c633af4SJohn Birrell 	return (0);
962c633af4SJohn Birrell }
972c633af4SJohn Birrell 
982c633af4SJohn Birrell int
992c633af4SJohn Birrell proc_getflags(struct proc_handle *phdl)
1002c633af4SJohn Birrell {
1018eb20f36SRui Paulo 
1022c633af4SJohn Birrell 	if (phdl == NULL)
1032c633af4SJohn Birrell 		return (-1);
1042c633af4SJohn Birrell 
1052c633af4SJohn Birrell 	return(phdl->flags);
1062c633af4SJohn Birrell }
1072c633af4SJohn Birrell 
1082c633af4SJohn Birrell int
1092c633af4SJohn Birrell proc_setflags(struct proc_handle *phdl, int mask)
1102c633af4SJohn Birrell {
1118eb20f36SRui Paulo 
1122c633af4SJohn Birrell 	if (phdl == NULL)
1132c633af4SJohn Birrell 		return (EINVAL);
1142c633af4SJohn Birrell 
1152c633af4SJohn Birrell 	phdl->flags |= mask;
1162c633af4SJohn Birrell 
1172c633af4SJohn Birrell 	return (0);
1182c633af4SJohn Birrell }
1192c633af4SJohn Birrell 
1202c633af4SJohn Birrell int
1212c633af4SJohn Birrell proc_state(struct proc_handle *phdl)
1222c633af4SJohn Birrell {
1238eb20f36SRui Paulo 
1242c633af4SJohn Birrell 	if (phdl == NULL)
1252c633af4SJohn Birrell 		return (-1);
1262c633af4SJohn Birrell 
1272c633af4SJohn Birrell 	return (phdl->status);
1282c633af4SJohn Birrell }
1292c633af4SJohn Birrell 
1302c633af4SJohn Birrell pid_t
1312c633af4SJohn Birrell proc_getpid(struct proc_handle *phdl)
1322c633af4SJohn Birrell {
1338eb20f36SRui Paulo 
1342c633af4SJohn Birrell 	if (phdl == NULL)
1352c633af4SJohn Birrell 		return (-1);
1362c633af4SJohn Birrell 
1372c633af4SJohn Birrell 	return (phdl->pid);
1382c633af4SJohn Birrell }
1398eb20f36SRui Paulo 
1408eb20f36SRui Paulo int
1418eb20f36SRui Paulo proc_wstatus(struct proc_handle *phdl)
1428eb20f36SRui Paulo {
1438eb20f36SRui Paulo 	int status;
1448eb20f36SRui Paulo 
1458eb20f36SRui Paulo 	if (phdl == NULL)
1468eb20f36SRui Paulo 		return (-1);
147*4c74b245SRui Paulo 	if (waitpid(phdl->pid, &status, WUNTRACED) < 0) {
148*4c74b245SRui Paulo 		warn("waitpid");
1498eb20f36SRui Paulo 		return (-1);
150*4c74b245SRui Paulo 	}
1518eb20f36SRui Paulo 	if (WIFSTOPPED(status))
1528eb20f36SRui Paulo 		phdl->status = PS_STOP;
1538eb20f36SRui Paulo 	if (WIFEXITED(status) || WIFSIGNALED(status))
1548eb20f36SRui Paulo 		phdl->status = PS_UNDEAD;
1558eb20f36SRui Paulo 	phdl->wstat = status;
1568eb20f36SRui Paulo 
157*4c74b245SRui Paulo 	return (phdl->status);
1588eb20f36SRui Paulo }
1598eb20f36SRui Paulo 
1608eb20f36SRui Paulo int
1618eb20f36SRui Paulo proc_getwstat(struct proc_handle *phdl)
1628eb20f36SRui Paulo {
1638eb20f36SRui Paulo 
1648eb20f36SRui Paulo 	if (phdl == NULL)
1658eb20f36SRui Paulo 		return (-1);
1668eb20f36SRui Paulo 
1678eb20f36SRui Paulo 	return (phdl->wstat);
1688eb20f36SRui Paulo }
1698eb20f36SRui Paulo 
1708eb20f36SRui Paulo char *
1718eb20f36SRui Paulo proc_signame(int sig, char *name, size_t namesz)
1728eb20f36SRui Paulo {
1738eb20f36SRui Paulo 
1748eb20f36SRui Paulo 	strlcpy(name, strsignal(sig), namesz);
1758eb20f36SRui Paulo 
1768eb20f36SRui Paulo 	return (name);
1778eb20f36SRui Paulo }
1788eb20f36SRui Paulo 
1798eb20f36SRui Paulo int
180*4c74b245SRui Paulo proc_read(struct proc_handle *phdl, void *buf, size_t size, size_t addr)
1818eb20f36SRui Paulo {
1828eb20f36SRui Paulo 	struct ptrace_io_desc piod;
1838eb20f36SRui Paulo 
1848eb20f36SRui Paulo 	if (phdl == NULL)
1858eb20f36SRui Paulo 		return (-1);
1868eb20f36SRui Paulo 	piod.piod_op = PIOD_READ_D;
1878eb20f36SRui Paulo 	piod.piod_len = size;
1888eb20f36SRui Paulo 	piod.piod_addr = (void *)buf;
1898eb20f36SRui Paulo 	piod.piod_offs = (void *)addr;
1908eb20f36SRui Paulo 
1918eb20f36SRui Paulo 	if (ptrace(PT_IO, phdl->pid, (caddr_t)&piod, 0) < 0)
1928eb20f36SRui Paulo 		return (-1);
1938eb20f36SRui Paulo 	return (piod.piod_len);
1948eb20f36SRui Paulo }
1958eb20f36SRui Paulo 
1968eb20f36SRui Paulo const lwpstatus_t *
1978eb20f36SRui Paulo proc_getlwpstatus(struct proc_handle *phdl)
1988eb20f36SRui Paulo {
1998eb20f36SRui Paulo 	struct ptrace_lwpinfo lwpinfo;
2008eb20f36SRui Paulo 	lwpstatus_t *psp = &phdl->lwps;
2018eb20f36SRui Paulo 	siginfo_t *siginfo;
2028eb20f36SRui Paulo 
2038eb20f36SRui Paulo 	if (phdl == NULL)
2048eb20f36SRui Paulo 		return (NULL);
205*4c74b245SRui Paulo 	if (ptrace(PT_LWPINFO, phdl->pid, (caddr_t)&lwpinfo,
206*4c74b245SRui Paulo 	    sizeof(lwpinfo)) < 0)
2078eb20f36SRui Paulo 		return (NULL);
2088eb20f36SRui Paulo 	siginfo = &lwpinfo.pl_siginfo;
2098eb20f36SRui Paulo 	if (lwpinfo.pl_event == PL_EVENT_SIGNAL &&
2108eb20f36SRui Paulo 	    (lwpinfo.pl_flags & PL_FLAG_SI) &&
2118eb20f36SRui Paulo 	    siginfo->si_signo == SIGTRAP &&
2128eb20f36SRui Paulo 	    (siginfo->si_code == TRAP_BRKPT ||
2138eb20f36SRui Paulo 	    siginfo->si_code == TRAP_TRACE)) {
2148eb20f36SRui Paulo 		psp->pr_why = PR_FAULTED;
2158eb20f36SRui Paulo 		psp->pr_what = FLTBPT;
2168eb20f36SRui Paulo 	} else if (lwpinfo.pl_flags & PL_FLAG_SCE) {
2178eb20f36SRui Paulo 		psp->pr_why = PR_SYSENTRY;
2188eb20f36SRui Paulo 	} else if (lwpinfo.pl_flags & PL_FLAG_SCX) {
2198eb20f36SRui Paulo 		psp->pr_why = PR_SYSEXIT;
2208eb20f36SRui Paulo 	}
2218eb20f36SRui Paulo 
2228eb20f36SRui Paulo 	return (psp);
2238eb20f36SRui Paulo }
224