1179185Sjb/*- 2210688Srpaulo * Copyright (c) 2010 The FreeBSD Foundation 3179185Sjb * Copyright (c) 2008 John Birrell (jb@freebsd.org) 4179185Sjb * All rights reserved. 5210688Srpaulo * 6210688Srpaulo * Portions of this software were developed by Rui Paulo under sponsorship 7210688Srpaulo * from the FreeBSD Foundation. 8179185Sjb * 9179185Sjb * Redistribution and use in source and binary forms, with or without 10179185Sjb * modification, are permitted provided that the following conditions 11179185Sjb * are met: 12179185Sjb * 1. Redistributions of source code must retain the above copyright 13179185Sjb * notice, this list of conditions and the following disclaimer. 14179185Sjb * 2. Redistributions in binary form must reproduce the above copyright 15179185Sjb * notice, this list of conditions and the following disclaimer in the 16179185Sjb * documentation and/or other materials provided with the distribution. 17179185Sjb * 18179185Sjb * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19179185Sjb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20179185Sjb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21179185Sjb * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22179185Sjb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23179185Sjb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24179185Sjb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25179185Sjb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26179185Sjb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27179185Sjb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28179185Sjb * SUCH DAMAGE. 29179185Sjb * 30179185Sjb * $FreeBSD$ 31179185Sjb */ 32179185Sjb 33210688Srpaulo#include <sys/types.h> 34210688Srpaulo#include <sys/ptrace.h> 35210688Srpaulo#include <sys/wait.h> 36210688Srpaulo#include <err.h> 37179185Sjb#include <errno.h> 38210688Srpaulo#include <signal.h> 39210688Srpaulo#include <string.h> 40269754Smarkj#include <unistd.h> 41210688Srpaulo#include "_libproc.h" 42179185Sjb 43179185Sjbint 44179185Sjbproc_clearflags(struct proc_handle *phdl, int mask) 45179185Sjb{ 46210688Srpaulo 47179185Sjb if (phdl == NULL) 48179185Sjb return (EINVAL); 49179185Sjb 50179185Sjb phdl->flags &= ~mask; 51179185Sjb 52179185Sjb return (0); 53179185Sjb} 54179185Sjb 55210688Srpaulo/* 56210688Srpaulo * NB: we return -1 as the Solaris libproc Psetrun() function. 57210688Srpaulo */ 58179185Sjbint 59179185Sjbproc_continue(struct proc_handle *phdl) 60179185Sjb{ 61269754Smarkj int pending = 0; 62210688Srpaulo 63179185Sjb if (phdl == NULL) 64210688Srpaulo return (-1); 65179185Sjb 66269754Smarkj if (phdl->status == PS_STOP && WSTOPSIG(phdl->wstat) != SIGTRAP) 67269754Smarkj pending = WSTOPSIG(phdl->wstat); 68269754Smarkj if (ptrace(PT_CONTINUE, phdl->pid, (caddr_t)(uintptr_t)1, pending) != 0) 69210688Srpaulo return (-1); 70179185Sjb 71179185Sjb phdl->status = PS_RUN; 72179185Sjb 73179185Sjb return (0); 74179185Sjb} 75179185Sjb 76179185Sjbint 77210688Srpauloproc_detach(struct proc_handle *phdl, int reason) 78179185Sjb{ 79210688Srpaulo int status; 80210688Srpaulo 81179185Sjb if (phdl == NULL) 82179185Sjb return (EINVAL); 83210688Srpaulo if (reason == PRELEASE_KILL) { 84210688Srpaulo kill(phdl->pid, SIGKILL); 85210688Srpaulo return (0); 86210688Srpaulo } 87210688Srpaulo if (ptrace(PT_DETACH, phdl->pid, 0, 0) != 0 && errno == ESRCH) 88210688Srpaulo return (0); 89210688Srpaulo if (errno == EBUSY) { 90210688Srpaulo kill(phdl->pid, SIGSTOP); 91210688Srpaulo waitpid(phdl->pid, &status, WUNTRACED); 92210688Srpaulo ptrace(PT_DETACH, phdl->pid, 0, 0); 93210688Srpaulo kill(phdl->pid, SIGCONT); 94210688Srpaulo return (0); 95210688Srpaulo } 96179185Sjb 97179185Sjb return (0); 98179185Sjb} 99179185Sjb 100179185Sjbint 101179185Sjbproc_getflags(struct proc_handle *phdl) 102179185Sjb{ 103210688Srpaulo 104179185Sjb if (phdl == NULL) 105179185Sjb return (-1); 106179185Sjb 107179185Sjb return(phdl->flags); 108179185Sjb} 109179185Sjb 110179185Sjbint 111179185Sjbproc_setflags(struct proc_handle *phdl, int mask) 112179185Sjb{ 113210688Srpaulo 114179185Sjb if (phdl == NULL) 115179185Sjb return (EINVAL); 116179185Sjb 117179185Sjb phdl->flags |= mask; 118179185Sjb 119179185Sjb return (0); 120179185Sjb} 121179185Sjb 122179185Sjbint 123179185Sjbproc_state(struct proc_handle *phdl) 124179185Sjb{ 125210688Srpaulo 126179185Sjb if (phdl == NULL) 127179185Sjb return (-1); 128179185Sjb 129179185Sjb return (phdl->status); 130179185Sjb} 131179185Sjb 132210688Srpaulopid_t 133210688Srpauloproc_getpid(struct proc_handle *phdl) 134179185Sjb{ 135179185Sjb 136179185Sjb if (phdl == NULL) 137210688Srpaulo return (-1); 138179185Sjb 139210688Srpaulo return (phdl->pid); 140210688Srpaulo} 141179185Sjb 142210688Srpauloint 143210688Srpauloproc_wstatus(struct proc_handle *phdl) 144210688Srpaulo{ 145210688Srpaulo int status; 146210688Srpaulo 147210688Srpaulo if (phdl == NULL) 148210688Srpaulo return (-1); 149211184Srpaulo if (waitpid(phdl->pid, &status, WUNTRACED) < 0) { 150212831Srpaulo if (errno != EINTR) 151259895Smarkj DPRINTF("waitpid"); 152210688Srpaulo return (-1); 153211184Srpaulo } 154210688Srpaulo if (WIFSTOPPED(status)) 155210688Srpaulo phdl->status = PS_STOP; 156210688Srpaulo if (WIFEXITED(status) || WIFSIGNALED(status)) 157179185Sjb phdl->status = PS_UNDEAD; 158210688Srpaulo phdl->wstat = status; 159179185Sjb 160211184Srpaulo return (phdl->status); 161179185Sjb} 162179185Sjb 163210688Srpauloint 164210688Srpauloproc_getwstat(struct proc_handle *phdl) 165179185Sjb{ 166210688Srpaulo 167179185Sjb if (phdl == NULL) 168179185Sjb return (-1); 169179185Sjb 170210688Srpaulo return (phdl->wstat); 171179185Sjb} 172210688Srpaulo 173210688Srpaulochar * 174210688Srpauloproc_signame(int sig, char *name, size_t namesz) 175210688Srpaulo{ 176210688Srpaulo 177210688Srpaulo strlcpy(name, strsignal(sig), namesz); 178210688Srpaulo 179210688Srpaulo return (name); 180210688Srpaulo} 181210688Srpaulo 182210688Srpauloint 183211184Srpauloproc_read(struct proc_handle *phdl, void *buf, size_t size, size_t addr) 184210688Srpaulo{ 185210688Srpaulo struct ptrace_io_desc piod; 186210688Srpaulo 187210688Srpaulo if (phdl == NULL) 188210688Srpaulo return (-1); 189210688Srpaulo piod.piod_op = PIOD_READ_D; 190210688Srpaulo piod.piod_len = size; 191210688Srpaulo piod.piod_addr = (void *)buf; 192210688Srpaulo piod.piod_offs = (void *)addr; 193210688Srpaulo 194210688Srpaulo if (ptrace(PT_IO, phdl->pid, (caddr_t)&piod, 0) < 0) 195210688Srpaulo return (-1); 196210688Srpaulo return (piod.piod_len); 197210688Srpaulo} 198210688Srpaulo 199210688Srpauloconst lwpstatus_t * 200210688Srpauloproc_getlwpstatus(struct proc_handle *phdl) 201210688Srpaulo{ 202210688Srpaulo struct ptrace_lwpinfo lwpinfo; 203210688Srpaulo lwpstatus_t *psp = &phdl->lwps; 204210688Srpaulo siginfo_t *siginfo; 205210688Srpaulo 206210688Srpaulo if (phdl == NULL) 207210688Srpaulo return (NULL); 208211184Srpaulo if (ptrace(PT_LWPINFO, phdl->pid, (caddr_t)&lwpinfo, 209211184Srpaulo sizeof(lwpinfo)) < 0) 210210688Srpaulo return (NULL); 211210688Srpaulo siginfo = &lwpinfo.pl_siginfo; 212210688Srpaulo if (lwpinfo.pl_event == PL_EVENT_SIGNAL && 213269754Smarkj (lwpinfo.pl_flags & PL_FLAG_SI) != 0) { 214269754Smarkj if (siginfo->si_signo == SIGTRAP && 215269754Smarkj (siginfo->si_code == TRAP_BRKPT || 216269754Smarkj siginfo->si_code == TRAP_TRACE)) { 217269754Smarkj psp->pr_why = PR_FAULTED; 218269754Smarkj psp->pr_what = FLTBPT; 219269754Smarkj } else { 220269754Smarkj psp->pr_why = PR_SIGNALLED; 221269754Smarkj psp->pr_what = siginfo->si_signo; 222269754Smarkj } 223210688Srpaulo } else if (lwpinfo.pl_flags & PL_FLAG_SCE) { 224210688Srpaulo psp->pr_why = PR_SYSENTRY; 225210688Srpaulo } else if (lwpinfo.pl_flags & PL_FLAG_SCX) { 226210688Srpaulo psp->pr_why = PR_SYSEXIT; 227210688Srpaulo } 228210688Srpaulo 229210688Srpaulo return (psp); 230210688Srpaulo} 231