proc_util.c revision 211184
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: head/lib/libproc/proc_util.c 211184 2010-08-11 17:33:26Z rpaulo $ 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> 38179185Sjb#include <unistd.h> 39179185Sjb#include <stdio.h> 40210688Srpaulo#include <signal.h> 41210688Srpaulo#include <string.h> 42210688Srpaulo#include "_libproc.h" 43179185Sjb 44179185Sjbint 45179185Sjbproc_clearflags(struct proc_handle *phdl, int mask) 46179185Sjb{ 47210688Srpaulo 48179185Sjb if (phdl == NULL) 49179185Sjb return (EINVAL); 50179185Sjb 51179185Sjb phdl->flags &= ~mask; 52179185Sjb 53179185Sjb return (0); 54179185Sjb} 55179185Sjb 56210688Srpaulo/* 57210688Srpaulo * NB: we return -1 as the Solaris libproc Psetrun() function. 58210688Srpaulo */ 59179185Sjbint 60179185Sjbproc_continue(struct proc_handle *phdl) 61179185Sjb{ 62210688Srpaulo 63179185Sjb if (phdl == NULL) 64210688Srpaulo return (-1); 65179185Sjb 66179185Sjb if (ptrace(PT_CONTINUE, phdl->pid, (caddr_t)(uintptr_t) 1, 0) != 0) 67210688Srpaulo return (-1); 68179185Sjb 69179185Sjb phdl->status = PS_RUN; 70179185Sjb 71179185Sjb return (0); 72179185Sjb} 73179185Sjb 74179185Sjbint 75210688Srpauloproc_detach(struct proc_handle *phdl, int reason) 76179185Sjb{ 77210688Srpaulo int status; 78210688Srpaulo 79179185Sjb if (phdl == NULL) 80179185Sjb return (EINVAL); 81210688Srpaulo if (reason == PRELEASE_KILL) { 82210688Srpaulo kill(phdl->pid, SIGKILL); 83210688Srpaulo return (0); 84210688Srpaulo } 85210688Srpaulo if (ptrace(PT_DETACH, phdl->pid, 0, 0) != 0 && errno == ESRCH) 86210688Srpaulo return (0); 87210688Srpaulo if (errno == EBUSY) { 88210688Srpaulo kill(phdl->pid, SIGSTOP); 89210688Srpaulo waitpid(phdl->pid, &status, WUNTRACED); 90210688Srpaulo ptrace(PT_DETACH, phdl->pid, 0, 0); 91210688Srpaulo kill(phdl->pid, SIGCONT); 92210688Srpaulo return (0); 93210688Srpaulo } 94179185Sjb 95179185Sjb return (0); 96179185Sjb} 97179185Sjb 98179185Sjbint 99179185Sjbproc_getflags(struct proc_handle *phdl) 100179185Sjb{ 101210688Srpaulo 102179185Sjb if (phdl == NULL) 103179185Sjb return (-1); 104179185Sjb 105179185Sjb return(phdl->flags); 106179185Sjb} 107179185Sjb 108179185Sjbint 109179185Sjbproc_setflags(struct proc_handle *phdl, int mask) 110179185Sjb{ 111210688Srpaulo 112179185Sjb if (phdl == NULL) 113179185Sjb return (EINVAL); 114179185Sjb 115179185Sjb phdl->flags |= mask; 116179185Sjb 117179185Sjb return (0); 118179185Sjb} 119179185Sjb 120179185Sjbint 121179185Sjbproc_state(struct proc_handle *phdl) 122179185Sjb{ 123210688Srpaulo 124179185Sjb if (phdl == NULL) 125179185Sjb return (-1); 126179185Sjb 127179185Sjb return (phdl->status); 128179185Sjb} 129179185Sjb 130210688Srpaulopid_t 131210688Srpauloproc_getpid(struct proc_handle *phdl) 132179185Sjb{ 133179185Sjb 134179185Sjb if (phdl == NULL) 135210688Srpaulo return (-1); 136179185Sjb 137210688Srpaulo return (phdl->pid); 138210688Srpaulo} 139179185Sjb 140210688Srpauloint 141210688Srpauloproc_wstatus(struct proc_handle *phdl) 142210688Srpaulo{ 143210688Srpaulo int status; 144210688Srpaulo 145210688Srpaulo if (phdl == NULL) 146210688Srpaulo return (-1); 147211184Srpaulo if (waitpid(phdl->pid, &status, WUNTRACED) < 0) { 148211184Srpaulo warn("waitpid"); 149210688Srpaulo return (-1); 150211184Srpaulo } 151210688Srpaulo if (WIFSTOPPED(status)) 152210688Srpaulo phdl->status = PS_STOP; 153210688Srpaulo if (WIFEXITED(status) || WIFSIGNALED(status)) 154179185Sjb phdl->status = PS_UNDEAD; 155210688Srpaulo phdl->wstat = status; 156179185Sjb 157211184Srpaulo return (phdl->status); 158179185Sjb} 159179185Sjb 160210688Srpauloint 161210688Srpauloproc_getwstat(struct proc_handle *phdl) 162179185Sjb{ 163210688Srpaulo 164179185Sjb if (phdl == NULL) 165179185Sjb return (-1); 166179185Sjb 167210688Srpaulo return (phdl->wstat); 168179185Sjb} 169210688Srpaulo 170210688Srpaulochar * 171210688Srpauloproc_signame(int sig, char *name, size_t namesz) 172210688Srpaulo{ 173210688Srpaulo 174210688Srpaulo strlcpy(name, strsignal(sig), namesz); 175210688Srpaulo 176210688Srpaulo return (name); 177210688Srpaulo} 178210688Srpaulo 179210688Srpauloint 180211184Srpauloproc_read(struct proc_handle *phdl, void *buf, size_t size, size_t addr) 181210688Srpaulo{ 182210688Srpaulo struct ptrace_io_desc piod; 183210688Srpaulo 184210688Srpaulo if (phdl == NULL) 185210688Srpaulo return (-1); 186210688Srpaulo piod.piod_op = PIOD_READ_D; 187210688Srpaulo piod.piod_len = size; 188210688Srpaulo piod.piod_addr = (void *)buf; 189210688Srpaulo piod.piod_offs = (void *)addr; 190210688Srpaulo 191210688Srpaulo if (ptrace(PT_IO, phdl->pid, (caddr_t)&piod, 0) < 0) 192210688Srpaulo return (-1); 193210688Srpaulo return (piod.piod_len); 194210688Srpaulo} 195210688Srpaulo 196210688Srpauloconst lwpstatus_t * 197210688Srpauloproc_getlwpstatus(struct proc_handle *phdl) 198210688Srpaulo{ 199210688Srpaulo struct ptrace_lwpinfo lwpinfo; 200210688Srpaulo lwpstatus_t *psp = &phdl->lwps; 201210688Srpaulo siginfo_t *siginfo; 202210688Srpaulo 203210688Srpaulo if (phdl == NULL) 204210688Srpaulo return (NULL); 205211184Srpaulo if (ptrace(PT_LWPINFO, phdl->pid, (caddr_t)&lwpinfo, 206211184Srpaulo sizeof(lwpinfo)) < 0) 207210688Srpaulo return (NULL); 208210688Srpaulo siginfo = &lwpinfo.pl_siginfo; 209210688Srpaulo if (lwpinfo.pl_event == PL_EVENT_SIGNAL && 210210688Srpaulo (lwpinfo.pl_flags & PL_FLAG_SI) && 211210688Srpaulo siginfo->si_signo == SIGTRAP && 212210688Srpaulo (siginfo->si_code == TRAP_BRKPT || 213210688Srpaulo siginfo->si_code == TRAP_TRACE)) { 214210688Srpaulo psp->pr_why = PR_FAULTED; 215210688Srpaulo psp->pr_what = FLTBPT; 216210688Srpaulo } else if (lwpinfo.pl_flags & PL_FLAG_SCE) { 217210688Srpaulo psp->pr_why = PR_SYSENTRY; 218210688Srpaulo } else if (lwpinfo.pl_flags & PL_FLAG_SCX) { 219210688Srpaulo psp->pr_why = PR_SYSEXIT; 220210688Srpaulo } 221210688Srpaulo 222210688Srpaulo return (psp); 223210688Srpaulo} 224