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 31*fcf9fc10SMark Johnston #include <sys/cdefs.h> 32*fcf9fc10SMark Johnston __FBSDID("$FreeBSD$"); 33*fcf9fc10SMark Johnston 348eb20f36SRui Paulo #include <sys/types.h> 352c633af4SJohn Birrell #include <sys/ptrace.h> 362c633af4SJohn Birrell #include <sys/wait.h> 37*fcf9fc10SMark Johnston 388eb20f36SRui Paulo #include <err.h> 398eb20f36SRui Paulo #include <errno.h> 408eb20f36SRui Paulo #include <signal.h> 418eb20f36SRui Paulo #include <string.h> 4292f92525SMark Johnston #include <unistd.h> 43*fcf9fc10SMark Johnston 448eb20f36SRui Paulo #include "_libproc.h" 452c633af4SJohn Birrell 462c633af4SJohn Birrell int 472c633af4SJohn Birrell proc_clearflags(struct proc_handle *phdl, int mask) 482c633af4SJohn Birrell { 498eb20f36SRui Paulo 502c633af4SJohn Birrell if (phdl == NULL) 512c633af4SJohn Birrell return (EINVAL); 522c633af4SJohn Birrell 532c633af4SJohn Birrell phdl->flags &= ~mask; 542c633af4SJohn Birrell 552c633af4SJohn Birrell return (0); 562c633af4SJohn Birrell } 572c633af4SJohn Birrell 588eb20f36SRui Paulo /* 598eb20f36SRui Paulo * NB: we return -1 as the Solaris libproc Psetrun() function. 608eb20f36SRui Paulo */ 612c633af4SJohn Birrell int 622c633af4SJohn Birrell proc_continue(struct proc_handle *phdl) 632c633af4SJohn Birrell { 64*fcf9fc10SMark Johnston int pending; 658eb20f36SRui Paulo 662c633af4SJohn Birrell if (phdl == NULL) 678eb20f36SRui Paulo return (-1); 682c633af4SJohn Birrell 6992f92525SMark Johnston if (phdl->status == PS_STOP && WSTOPSIG(phdl->wstat) != SIGTRAP) 7092f92525SMark Johnston pending = WSTOPSIG(phdl->wstat); 71*fcf9fc10SMark Johnston else 72*fcf9fc10SMark Johnston pending = 0; 7392f92525SMark Johnston if (ptrace(PT_CONTINUE, phdl->pid, (caddr_t)(uintptr_t)1, pending) != 0) 748eb20f36SRui Paulo return (-1); 752c633af4SJohn Birrell 762c633af4SJohn Birrell phdl->status = PS_RUN; 772c633af4SJohn Birrell 782c633af4SJohn Birrell return (0); 792c633af4SJohn Birrell } 802c633af4SJohn Birrell 812c633af4SJohn Birrell int 828eb20f36SRui Paulo proc_detach(struct proc_handle *phdl, int reason) 832c633af4SJohn Birrell { 848eb20f36SRui Paulo int status; 858eb20f36SRui Paulo 862c633af4SJohn Birrell if (phdl == NULL) 872c633af4SJohn Birrell return (EINVAL); 888eb20f36SRui Paulo if (reason == PRELEASE_KILL) { 898eb20f36SRui Paulo kill(phdl->pid, SIGKILL); 908eb20f36SRui Paulo return (0); 918eb20f36SRui Paulo } 928eb20f36SRui Paulo if (ptrace(PT_DETACH, phdl->pid, 0, 0) != 0 && errno == ESRCH) 938eb20f36SRui Paulo return (0); 948eb20f36SRui Paulo if (errno == EBUSY) { 958eb20f36SRui Paulo kill(phdl->pid, SIGSTOP); 968eb20f36SRui Paulo waitpid(phdl->pid, &status, WUNTRACED); 978eb20f36SRui Paulo ptrace(PT_DETACH, phdl->pid, 0, 0); 988eb20f36SRui Paulo kill(phdl->pid, SIGCONT); 998eb20f36SRui Paulo return (0); 1008eb20f36SRui Paulo } 1012c633af4SJohn Birrell 1022c633af4SJohn Birrell return (0); 1032c633af4SJohn Birrell } 1042c633af4SJohn Birrell 1052c633af4SJohn Birrell int 1062c633af4SJohn Birrell proc_getflags(struct proc_handle *phdl) 1072c633af4SJohn Birrell { 1088eb20f36SRui Paulo 1092c633af4SJohn Birrell if (phdl == NULL) 1102c633af4SJohn Birrell return (-1); 1112c633af4SJohn Birrell 1122c633af4SJohn Birrell return (phdl->flags); 1132c633af4SJohn Birrell } 1142c633af4SJohn Birrell 1152c633af4SJohn Birrell int 1162c633af4SJohn Birrell proc_setflags(struct proc_handle *phdl, int mask) 1172c633af4SJohn Birrell { 1188eb20f36SRui Paulo 1192c633af4SJohn Birrell if (phdl == NULL) 1202c633af4SJohn Birrell return (EINVAL); 1212c633af4SJohn Birrell 1222c633af4SJohn Birrell phdl->flags |= mask; 1232c633af4SJohn Birrell 1242c633af4SJohn Birrell return (0); 1252c633af4SJohn Birrell } 1262c633af4SJohn Birrell 1272c633af4SJohn Birrell int 1282c633af4SJohn Birrell proc_state(struct proc_handle *phdl) 1292c633af4SJohn Birrell { 1308eb20f36SRui Paulo 1312c633af4SJohn Birrell if (phdl == NULL) 1322c633af4SJohn Birrell return (-1); 1332c633af4SJohn Birrell 1342c633af4SJohn Birrell return (phdl->status); 1352c633af4SJohn Birrell } 1362c633af4SJohn Birrell 1372c633af4SJohn Birrell pid_t 1382c633af4SJohn Birrell proc_getpid(struct proc_handle *phdl) 1392c633af4SJohn Birrell { 1408eb20f36SRui Paulo 1412c633af4SJohn Birrell if (phdl == NULL) 1422c633af4SJohn Birrell return (-1); 1432c633af4SJohn Birrell 1442c633af4SJohn Birrell return (phdl->pid); 1452c633af4SJohn Birrell } 1468eb20f36SRui Paulo 1478eb20f36SRui Paulo int 1484808a678SMark Johnston proc_getmodel(struct proc_handle *phdl) 1494808a678SMark Johnston { 1504808a678SMark Johnston 1514808a678SMark Johnston if (phdl == NULL) 1524808a678SMark Johnston return (-1); 1534808a678SMark Johnston 1544808a678SMark Johnston return (phdl->model); 1554808a678SMark Johnston } 1564808a678SMark Johnston 1574808a678SMark Johnston int 1588eb20f36SRui Paulo proc_wstatus(struct proc_handle *phdl) 1598eb20f36SRui Paulo { 1608eb20f36SRui Paulo int status; 1618eb20f36SRui Paulo 1628eb20f36SRui Paulo if (phdl == NULL) 1638eb20f36SRui Paulo return (-1); 1644c74b245SRui Paulo if (waitpid(phdl->pid, &status, WUNTRACED) < 0) { 165fb15925cSMark Johnston if (errno != EINTR) 16630e81f7eSMark Johnston DPRINTF("waitpid"); 1678eb20f36SRui Paulo return (-1); 1684c74b245SRui Paulo } 1698eb20f36SRui Paulo if (WIFSTOPPED(status)) 1708eb20f36SRui Paulo phdl->status = PS_STOP; 1718eb20f36SRui Paulo if (WIFEXITED(status) || WIFSIGNALED(status)) 1728eb20f36SRui Paulo phdl->status = PS_UNDEAD; 1738eb20f36SRui Paulo phdl->wstat = status; 1748eb20f36SRui Paulo 1754c74b245SRui Paulo return (phdl->status); 1768eb20f36SRui Paulo } 1778eb20f36SRui Paulo 1788eb20f36SRui Paulo int 1798eb20f36SRui Paulo proc_getwstat(struct proc_handle *phdl) 1808eb20f36SRui Paulo { 1818eb20f36SRui Paulo 1828eb20f36SRui Paulo if (phdl == NULL) 1838eb20f36SRui Paulo return (-1); 1848eb20f36SRui Paulo 1858eb20f36SRui Paulo return (phdl->wstat); 1868eb20f36SRui Paulo } 1878eb20f36SRui Paulo 1888eb20f36SRui Paulo char * 1898eb20f36SRui Paulo proc_signame(int sig, char *name, size_t namesz) 1908eb20f36SRui Paulo { 1918eb20f36SRui Paulo 1928eb20f36SRui Paulo strlcpy(name, strsignal(sig), namesz); 1938eb20f36SRui Paulo 1948eb20f36SRui Paulo return (name); 1958eb20f36SRui Paulo } 1968eb20f36SRui Paulo 1978eb20f36SRui Paulo int 1984c74b245SRui Paulo proc_read(struct proc_handle *phdl, void *buf, size_t size, size_t addr) 1998eb20f36SRui Paulo { 2008eb20f36SRui Paulo struct ptrace_io_desc piod; 2018eb20f36SRui Paulo 2028eb20f36SRui Paulo if (phdl == NULL) 2038eb20f36SRui Paulo return (-1); 2048eb20f36SRui Paulo piod.piod_op = PIOD_READ_D; 2058eb20f36SRui Paulo piod.piod_len = size; 2068eb20f36SRui Paulo piod.piod_addr = (void *)buf; 2078eb20f36SRui Paulo piod.piod_offs = (void *)addr; 2088eb20f36SRui Paulo 2098eb20f36SRui Paulo if (ptrace(PT_IO, phdl->pid, (caddr_t)&piod, 0) < 0) 2108eb20f36SRui Paulo return (-1); 2118eb20f36SRui Paulo return (piod.piod_len); 2128eb20f36SRui Paulo } 2138eb20f36SRui Paulo 2148eb20f36SRui Paulo const lwpstatus_t * 2158eb20f36SRui Paulo proc_getlwpstatus(struct proc_handle *phdl) 2168eb20f36SRui Paulo { 2178eb20f36SRui Paulo struct ptrace_lwpinfo lwpinfo; 2188eb20f36SRui Paulo lwpstatus_t *psp = &phdl->lwps; 2198eb20f36SRui Paulo siginfo_t *siginfo; 2208eb20f36SRui Paulo 2218eb20f36SRui Paulo if (phdl == NULL) 2228eb20f36SRui Paulo return (NULL); 2234c74b245SRui Paulo if (ptrace(PT_LWPINFO, phdl->pid, (caddr_t)&lwpinfo, 2244c74b245SRui Paulo sizeof(lwpinfo)) < 0) 2258eb20f36SRui Paulo return (NULL); 2268eb20f36SRui Paulo siginfo = &lwpinfo.pl_siginfo; 2278eb20f36SRui Paulo if (lwpinfo.pl_event == PL_EVENT_SIGNAL && 22892f92525SMark Johnston (lwpinfo.pl_flags & PL_FLAG_SI) != 0) { 22992f92525SMark Johnston if (siginfo->si_signo == SIGTRAP && 2308eb20f36SRui Paulo (siginfo->si_code == TRAP_BRKPT || 2318eb20f36SRui Paulo siginfo->si_code == TRAP_TRACE)) { 2328eb20f36SRui Paulo psp->pr_why = PR_FAULTED; 2338eb20f36SRui Paulo psp->pr_what = FLTBPT; 23492f92525SMark Johnston } else { 23592f92525SMark Johnston psp->pr_why = PR_SIGNALLED; 23692f92525SMark Johnston psp->pr_what = siginfo->si_signo; 23792f92525SMark Johnston } 2388eb20f36SRui Paulo } else if (lwpinfo.pl_flags & PL_FLAG_SCE) { 2398eb20f36SRui Paulo psp->pr_why = PR_SYSENTRY; 2408eb20f36SRui Paulo } else if (lwpinfo.pl_flags & PL_FLAG_SCX) { 2418eb20f36SRui Paulo psp->pr_why = PR_SYSEXIT; 2428eb20f36SRui Paulo } 2438eb20f36SRui Paulo 2448eb20f36SRui Paulo return (psp); 2458eb20f36SRui Paulo } 246