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