1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright (c) 1994-1999 by Sun Microsystems, Inc. 24*7c478bd9Sstevel@tonic-gate * All rights reserved. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* 30*7c478bd9Sstevel@tonic-gate * This file contains interfaces that are wrappers over the basic 31*7c478bd9Sstevel@tonic-gate * /proc ioctls 32*7c478bd9Sstevel@tonic-gate */ 33*7c478bd9Sstevel@tonic-gate 34*7c478bd9Sstevel@tonic-gate #include <unistd.h> 35*7c478bd9Sstevel@tonic-gate #include <string.h> 36*7c478bd9Sstevel@tonic-gate #include <errno.h> 37*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 38*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 39*7c478bd9Sstevel@tonic-gate #include <stdio.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/uio.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/fault.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/procfs.h> 45*7c478bd9Sstevel@tonic-gate 46*7c478bd9Sstevel@tonic-gate #include "prb_proc_int.h" 47*7c478bd9Sstevel@tonic-gate #include "dbg.h" 48*7c478bd9Sstevel@tonic-gate 49*7c478bd9Sstevel@tonic-gate /* 50*7c478bd9Sstevel@tonic-gate * Declarations 51*7c478bd9Sstevel@tonic-gate */ 52*7c478bd9Sstevel@tonic-gate 53*7c478bd9Sstevel@tonic-gate #define PROCFORMAT "/proc/%d" 54*7c478bd9Sstevel@tonic-gate 55*7c478bd9Sstevel@tonic-gate static prb_status_t 56*7c478bd9Sstevel@tonic-gate prb_proc_open_general(pid_t pid, prb_proc_ctl_t **proc_pp, int oflg); 57*7c478bd9Sstevel@tonic-gate 58*7c478bd9Sstevel@tonic-gate /* 59*7c478bd9Sstevel@tonic-gate * prb_proc_open_general() - function to open the process file 60*7c478bd9Sstevel@tonic-gate * system entry for the supplied process. Opens with different 61*7c478bd9Sstevel@tonic-gate * options based on the 'oflg'. 62*7c478bd9Sstevel@tonic-gate * Returns a pointer to an opaque structure that contains the fd 63*7c478bd9Sstevel@tonic-gate * needed for /proc control. 64*7c478bd9Sstevel@tonic-gate */ 65*7c478bd9Sstevel@tonic-gate 66*7c478bd9Sstevel@tonic-gate prb_status_t 67*7c478bd9Sstevel@tonic-gate prb_proc_open_general(pid_t pid, prb_proc_ctl_t **proc_pp, int oflg) 68*7c478bd9Sstevel@tonic-gate { 69*7c478bd9Sstevel@tonic-gate prb_proc_ctl_t *proc_p; 70*7c478bd9Sstevel@tonic-gate char path[MAXPATHLEN]; 71*7c478bd9Sstevel@tonic-gate int retval; 72*7c478bd9Sstevel@tonic-gate 73*7c478bd9Sstevel@tonic-gate (void) sprintf(path, PROCFORMAT, (int)pid); 74*7c478bd9Sstevel@tonic-gate 75*7c478bd9Sstevel@tonic-gate DBG_TNF_PROBE_1(prb_proc_open_1, "libtnfctl", "sunw%verbosity 2", 76*7c478bd9Sstevel@tonic-gate tnf_string, opening_proc_on, path); 77*7c478bd9Sstevel@tonic-gate 78*7c478bd9Sstevel@tonic-gate retval = open(path, oflg); 79*7c478bd9Sstevel@tonic-gate if (retval == -1) { 80*7c478bd9Sstevel@tonic-gate DBG((void) fprintf(stderr, 81*7c478bd9Sstevel@tonic-gate "proc_open: open of \"%s\" failed: %s\n", 82*7c478bd9Sstevel@tonic-gate path, strerror(errno))); 83*7c478bd9Sstevel@tonic-gate return (prb_status_map(errno)); 84*7c478bd9Sstevel@tonic-gate } 85*7c478bd9Sstevel@tonic-gate /* allocate proc_p and zero fill */ 86*7c478bd9Sstevel@tonic-gate proc_p = calloc(1, sizeof (*proc_p)); 87*7c478bd9Sstevel@tonic-gate if (proc_p == NULL) 88*7c478bd9Sstevel@tonic-gate return (PRB_STATUS_ALLOCFAIL); 89*7c478bd9Sstevel@tonic-gate proc_p->procfd = retval; 90*7c478bd9Sstevel@tonic-gate proc_p->pid = pid; 91*7c478bd9Sstevel@tonic-gate *proc_pp = proc_p; 92*7c478bd9Sstevel@tonic-gate return (PRB_STATUS_OK); 93*7c478bd9Sstevel@tonic-gate } 94*7c478bd9Sstevel@tonic-gate 95*7c478bd9Sstevel@tonic-gate 96*7c478bd9Sstevel@tonic-gate /* 97*7c478bd9Sstevel@tonic-gate * prb_proc_open() - a wrapper which opens the process file system 98*7c478bd9Sstevel@tonic-gate * entry for the supplied process. Returns a pointer to an opaque 99*7c478bd9Sstevel@tonic-gate * structure that contains the fd needed for /proc control. 100*7c478bd9Sstevel@tonic-gate */ 101*7c478bd9Sstevel@tonic-gate 102*7c478bd9Sstevel@tonic-gate prb_status_t 103*7c478bd9Sstevel@tonic-gate prb_proc_open(pid_t pid, prb_proc_ctl_t **proc_pp) 104*7c478bd9Sstevel@tonic-gate { 105*7c478bd9Sstevel@tonic-gate 106*7c478bd9Sstevel@tonic-gate return (prb_proc_open_general(pid, 107*7c478bd9Sstevel@tonic-gate proc_pp, O_RDWR | O_EXCL)); 108*7c478bd9Sstevel@tonic-gate 109*7c478bd9Sstevel@tonic-gate } 110*7c478bd9Sstevel@tonic-gate 111*7c478bd9Sstevel@tonic-gate /* 112*7c478bd9Sstevel@tonic-gate * prb_proc_reopen() - re-opens the process, mainly for setuid/setgid files. 113*7c478bd9Sstevel@tonic-gate * Read the last section of /proc man page for details. 114*7c478bd9Sstevel@tonic-gate * re-open should not use O_EXCL flag. 115*7c478bd9Sstevel@tonic-gate */ 116*7c478bd9Sstevel@tonic-gate 117*7c478bd9Sstevel@tonic-gate prb_status_t 118*7c478bd9Sstevel@tonic-gate prb_proc_reopen(pid_t pid, prb_proc_ctl_t **proc_pp) 119*7c478bd9Sstevel@tonic-gate { 120*7c478bd9Sstevel@tonic-gate 121*7c478bd9Sstevel@tonic-gate return (prb_proc_open_general(pid, 122*7c478bd9Sstevel@tonic-gate proc_pp, O_RDWR)); 123*7c478bd9Sstevel@tonic-gate 124*7c478bd9Sstevel@tonic-gate } 125*7c478bd9Sstevel@tonic-gate 126*7c478bd9Sstevel@tonic-gate /* 127*7c478bd9Sstevel@tonic-gate * prob_proc_close() - close the proc fd and free the memory taken up 128*7c478bd9Sstevel@tonic-gate * by proc_p 129*7c478bd9Sstevel@tonic-gate */ 130*7c478bd9Sstevel@tonic-gate prb_status_t 131*7c478bd9Sstevel@tonic-gate prb_proc_close(prb_proc_ctl_t *proc_p) 132*7c478bd9Sstevel@tonic-gate { 133*7c478bd9Sstevel@tonic-gate DBG_TNF_PROBE_0(prb_proc_close_1, "libtnfctl", "sunw%verbosity 2"); 134*7c478bd9Sstevel@tonic-gate 135*7c478bd9Sstevel@tonic-gate if (proc_p == NULL) 136*7c478bd9Sstevel@tonic-gate return (PRB_STATUS_OK); 137*7c478bd9Sstevel@tonic-gate 138*7c478bd9Sstevel@tonic-gate if (close(proc_p->procfd) == -1) { 139*7c478bd9Sstevel@tonic-gate DBG((void) fprintf(stderr, 140*7c478bd9Sstevel@tonic-gate "proc_close: close failed: %s\n", strerror(errno))); 141*7c478bd9Sstevel@tonic-gate return (prb_status_map(errno)); 142*7c478bd9Sstevel@tonic-gate } 143*7c478bd9Sstevel@tonic-gate free(proc_p); 144*7c478bd9Sstevel@tonic-gate return (PRB_STATUS_OK); 145*7c478bd9Sstevel@tonic-gate } 146*7c478bd9Sstevel@tonic-gate 147*7c478bd9Sstevel@tonic-gate /* 148*7c478bd9Sstevel@tonic-gate * prb_proc_pid_get() - gets the pid of the proc 149*7c478bd9Sstevel@tonic-gate */ 150*7c478bd9Sstevel@tonic-gate pid_t 151*7c478bd9Sstevel@tonic-gate prb_proc_pid_get(prb_proc_ctl_t *proc_p) 152*7c478bd9Sstevel@tonic-gate { 153*7c478bd9Sstevel@tonic-gate return (proc_p->pid); 154*7c478bd9Sstevel@tonic-gate } 155*7c478bd9Sstevel@tonic-gate 156*7c478bd9Sstevel@tonic-gate /* 157*7c478bd9Sstevel@tonic-gate * prb_proc_stop() - stops the target process 158*7c478bd9Sstevel@tonic-gate */ 159*7c478bd9Sstevel@tonic-gate prb_status_t 160*7c478bd9Sstevel@tonic-gate prb_proc_stop(prb_proc_ctl_t *proc_p) 161*7c478bd9Sstevel@tonic-gate { 162*7c478bd9Sstevel@tonic-gate int retval; 163*7c478bd9Sstevel@tonic-gate 164*7c478bd9Sstevel@tonic-gate DBG_TNF_PROBE_0(prb_proc_stop_1, "libtnfctl", 165*7c478bd9Sstevel@tonic-gate "sunw%verbosity 2; sunw%debug 'stopping the target process'"); 166*7c478bd9Sstevel@tonic-gate 167*7c478bd9Sstevel@tonic-gate again: 168*7c478bd9Sstevel@tonic-gate retval = ioctl(proc_p->procfd, PIOCSTOP, NULL); 169*7c478bd9Sstevel@tonic-gate if (retval == -1) { 170*7c478bd9Sstevel@tonic-gate if (errno == EINTR) 171*7c478bd9Sstevel@tonic-gate goto again; 172*7c478bd9Sstevel@tonic-gate DBG((void) fprintf(stderr, 173*7c478bd9Sstevel@tonic-gate "prb_proc_stop: PIOCSTOP failed: %s\n", 174*7c478bd9Sstevel@tonic-gate strerror(errno))); 175*7c478bd9Sstevel@tonic-gate return (prb_status_map(errno)); 176*7c478bd9Sstevel@tonic-gate } 177*7c478bd9Sstevel@tonic-gate return (PRB_STATUS_OK); 178*7c478bd9Sstevel@tonic-gate } 179*7c478bd9Sstevel@tonic-gate 180*7c478bd9Sstevel@tonic-gate 181*7c478bd9Sstevel@tonic-gate /* 182*7c478bd9Sstevel@tonic-gate * prb_proc_prstop() - runs and stops the process, used to clear a target 183*7c478bd9Sstevel@tonic-gate * process out of a system call state. 184*7c478bd9Sstevel@tonic-gate */ 185*7c478bd9Sstevel@tonic-gate prb_status_t 186*7c478bd9Sstevel@tonic-gate prb_proc_prstop(prb_proc_ctl_t *proc_p) 187*7c478bd9Sstevel@tonic-gate { 188*7c478bd9Sstevel@tonic-gate int procfd; 189*7c478bd9Sstevel@tonic-gate int retval; 190*7c478bd9Sstevel@tonic-gate prrun_t prrun; 191*7c478bd9Sstevel@tonic-gate prstatus_t prstat; 192*7c478bd9Sstevel@tonic-gate 193*7c478bd9Sstevel@tonic-gate DBG_TNF_PROBE_0(prb_proc_prstop_1, "libtnfctl", 194*7c478bd9Sstevel@tonic-gate "sunw%verbosity 2; sunw%debug 'stepping the target process'"); 195*7c478bd9Sstevel@tonic-gate 196*7c478bd9Sstevel@tonic-gate procfd = proc_p->procfd; 197*7c478bd9Sstevel@tonic-gate (void) memset((char *)&prrun, 0, sizeof (prrun)); 198*7c478bd9Sstevel@tonic-gate (void) memset((char *)&prstat, 0, sizeof (prstat)); 199*7c478bd9Sstevel@tonic-gate 200*7c478bd9Sstevel@tonic-gate again1: 201*7c478bd9Sstevel@tonic-gate prrun.pr_flags = PRSTOP; 202*7c478bd9Sstevel@tonic-gate retval = ioctl(procfd, PIOCRUN, &prrun); 203*7c478bd9Sstevel@tonic-gate if (retval == -1) { 204*7c478bd9Sstevel@tonic-gate if (errno == EINTR) 205*7c478bd9Sstevel@tonic-gate goto again1; 206*7c478bd9Sstevel@tonic-gate DBG((void) fprintf(stderr, 207*7c478bd9Sstevel@tonic-gate "prb_proc_prstop: PIOCRUN failed: %s\n", 208*7c478bd9Sstevel@tonic-gate strerror(errno))); 209*7c478bd9Sstevel@tonic-gate return (prb_status_map(errno)); 210*7c478bd9Sstevel@tonic-gate } 211*7c478bd9Sstevel@tonic-gate again2: 212*7c478bd9Sstevel@tonic-gate retval = ioctl(procfd, PIOCWSTOP, &prstat); 213*7c478bd9Sstevel@tonic-gate if (retval == -1) { 214*7c478bd9Sstevel@tonic-gate if (errno == EINTR) 215*7c478bd9Sstevel@tonic-gate goto again2; 216*7c478bd9Sstevel@tonic-gate DBG((void) fprintf(stderr, 217*7c478bd9Sstevel@tonic-gate "prb_proc_prstop: PIOCWSTOP failed: %s\n", 218*7c478bd9Sstevel@tonic-gate strerror(errno))); 219*7c478bd9Sstevel@tonic-gate return (prb_status_map(errno)); 220*7c478bd9Sstevel@tonic-gate } 221*7c478bd9Sstevel@tonic-gate /* 222*7c478bd9Sstevel@tonic-gate * if we didn't stop because we requested it (eg. if there was a 223*7c478bd9Sstevel@tonic-gate * signal in the target ?), we might need to try again 224*7c478bd9Sstevel@tonic-gate */ 225*7c478bd9Sstevel@tonic-gate if (prstat.pr_why != PR_REQUESTED) 226*7c478bd9Sstevel@tonic-gate goto again1; 227*7c478bd9Sstevel@tonic-gate 228*7c478bd9Sstevel@tonic-gate return (PRB_STATUS_OK); 229*7c478bd9Sstevel@tonic-gate } 230*7c478bd9Sstevel@tonic-gate 231*7c478bd9Sstevel@tonic-gate 232*7c478bd9Sstevel@tonic-gate /* 233*7c478bd9Sstevel@tonic-gate * prb_proc_state() - returns the status pf the process 234*7c478bd9Sstevel@tonic-gate */ 235*7c478bd9Sstevel@tonic-gate prb_status_t 236*7c478bd9Sstevel@tonic-gate prb_proc_state(prb_proc_ctl_t *proc_p, prb_proc_state_t *state_p) 237*7c478bd9Sstevel@tonic-gate { 238*7c478bd9Sstevel@tonic-gate int procfd; 239*7c478bd9Sstevel@tonic-gate int retval; 240*7c478bd9Sstevel@tonic-gate prstatus_t prstatus; 241*7c478bd9Sstevel@tonic-gate 242*7c478bd9Sstevel@tonic-gate DBG_TNF_PROBE_0(prb_proc_state_1, "libtnfctl", 243*7c478bd9Sstevel@tonic-gate "sunw%verbosity 2; sunw%debug 'getting the status'"); 244*7c478bd9Sstevel@tonic-gate 245*7c478bd9Sstevel@tonic-gate procfd = proc_p->procfd; 246*7c478bd9Sstevel@tonic-gate 247*7c478bd9Sstevel@tonic-gate (void) memset(&prstatus, 0, sizeof (prstatus)); 248*7c478bd9Sstevel@tonic-gate 249*7c478bd9Sstevel@tonic-gate again: 250*7c478bd9Sstevel@tonic-gate retval = ioctl(procfd, PIOCSTATUS, &prstatus); 251*7c478bd9Sstevel@tonic-gate if (retval == -1) { 252*7c478bd9Sstevel@tonic-gate if (errno == EINTR) 253*7c478bd9Sstevel@tonic-gate goto again; 254*7c478bd9Sstevel@tonic-gate DBG((void) fprintf(stderr, 255*7c478bd9Sstevel@tonic-gate "prb_proc_status: PIOCSTATUS failed: %s\n", 256*7c478bd9Sstevel@tonic-gate strerror(errno))); 257*7c478bd9Sstevel@tonic-gate return (prb_status_map(errno)); 258*7c478bd9Sstevel@tonic-gate } 259*7c478bd9Sstevel@tonic-gate state_p->ps_isbptfault = (prstatus.pr_flags & PR_FAULTED && 260*7c478bd9Sstevel@tonic-gate prstatus.pr_what == FLTBPT); 261*7c478bd9Sstevel@tonic-gate state_p->ps_isstopped = ((prstatus.pr_flags & PR_STOPPED) != 0); 262*7c478bd9Sstevel@tonic-gate state_p->ps_isinsys = ((prstatus.pr_flags & PR_ASLEEP) != 0); 263*7c478bd9Sstevel@tonic-gate state_p->ps_isrequested = ((prstatus.pr_why & PR_REQUESTED) != 0); 264*7c478bd9Sstevel@tonic-gate state_p->ps_issysexit = ((prstatus.pr_why & PR_SYSEXIT) != 0); 265*7c478bd9Sstevel@tonic-gate state_p->ps_issysentry = ((prstatus.pr_why & PR_SYSENTRY) != 0); 266*7c478bd9Sstevel@tonic-gate state_p->ps_syscallnum = prstatus.pr_what; 267*7c478bd9Sstevel@tonic-gate return (PRB_STATUS_OK); 268*7c478bd9Sstevel@tonic-gate } 269*7c478bd9Sstevel@tonic-gate 270*7c478bd9Sstevel@tonic-gate 271*7c478bd9Sstevel@tonic-gate /* 272*7c478bd9Sstevel@tonic-gate * prb_proc_wait() - waits for the target process to stop 273*7c478bd9Sstevel@tonic-gate */ 274*7c478bd9Sstevel@tonic-gate prb_status_t 275*7c478bd9Sstevel@tonic-gate prb_proc_wait(prb_proc_ctl_t *proc_p, boolean_t use_sigmask, sigset_t *oldmask) 276*7c478bd9Sstevel@tonic-gate { 277*7c478bd9Sstevel@tonic-gate int procfd; 278*7c478bd9Sstevel@tonic-gate int retval; 279*7c478bd9Sstevel@tonic-gate prstatus_t prstat; 280*7c478bd9Sstevel@tonic-gate sigset_t pendmask; 281*7c478bd9Sstevel@tonic-gate int i, mask_size; 282*7c478bd9Sstevel@tonic-gate boolean_t pending_signal = B_FALSE; 283*7c478bd9Sstevel@tonic-gate 284*7c478bd9Sstevel@tonic-gate DBG_TNF_PROBE_0(prb_proc_wait_1, "libtnfctl", 285*7c478bd9Sstevel@tonic-gate "sunw%verbosity 2;" 286*7c478bd9Sstevel@tonic-gate "sunw%debug 'waiting for the target process to stop'"); 287*7c478bd9Sstevel@tonic-gate 288*7c478bd9Sstevel@tonic-gate procfd = proc_p->procfd; 289*7c478bd9Sstevel@tonic-gate 290*7c478bd9Sstevel@tonic-gate /* 291*7c478bd9Sstevel@tonic-gate * This one of the places where we do not resubmit the ioctl if 292*7c478bd9Sstevel@tonic-gate * if it is terminated by an EINTR (interrupted system call). In 293*7c478bd9Sstevel@tonic-gate * this case, the caller knows best ... 294*7c478bd9Sstevel@tonic-gate */ 295*7c478bd9Sstevel@tonic-gate (void) memset(&prstat, 0, sizeof (prstat)); 296*7c478bd9Sstevel@tonic-gate 297*7c478bd9Sstevel@tonic-gate /* if we blocked signals... */ 298*7c478bd9Sstevel@tonic-gate if (use_sigmask) { 299*7c478bd9Sstevel@tonic-gate if (sigemptyset(&pendmask) == -1) 300*7c478bd9Sstevel@tonic-gate return (prb_status_map(errno)); 301*7c478bd9Sstevel@tonic-gate if (sigpending(&pendmask) == -1) 302*7c478bd9Sstevel@tonic-gate return (prb_status_map(errno)); 303*7c478bd9Sstevel@tonic-gate /* 304*7c478bd9Sstevel@tonic-gate * check if there were any signals pending - 305*7c478bd9Sstevel@tonic-gate * XXXX libc should provide this interface 306*7c478bd9Sstevel@tonic-gate */ 307*7c478bd9Sstevel@tonic-gate mask_size = sizeof (pendmask) / sizeof (pendmask.__sigbits[0]); 308*7c478bd9Sstevel@tonic-gate for (i = 0; i < mask_size; i++) { 309*7c478bd9Sstevel@tonic-gate if (pendmask.__sigbits[i] != 0) 310*7c478bd9Sstevel@tonic-gate pending_signal = B_TRUE; 311*7c478bd9Sstevel@tonic-gate } 312*7c478bd9Sstevel@tonic-gate 313*7c478bd9Sstevel@tonic-gate /* return to original signal mask */ 314*7c478bd9Sstevel@tonic-gate if (sigprocmask(SIG_SETMASK, oldmask, NULL) == -1) 315*7c478bd9Sstevel@tonic-gate return (prb_status_map(errno)); 316*7c478bd9Sstevel@tonic-gate 317*7c478bd9Sstevel@tonic-gate /* if there was a pending signal, don't call PIOCWSTOP ioctl */ 318*7c478bd9Sstevel@tonic-gate if (pending_signal) 319*7c478bd9Sstevel@tonic-gate return (prb_status_map(EINTR)); 320*7c478bd9Sstevel@tonic-gate 321*7c478bd9Sstevel@tonic-gate /* 322*7c478bd9Sstevel@tonic-gate * XXXX - there is a a race between now and when we call 323*7c478bd9Sstevel@tonic-gate * the PIOCWSTOP ioctl. One solution, is for the user to 324*7c478bd9Sstevel@tonic-gate * call an interface in libtnfctl from their signal handler. 325*7c478bd9Sstevel@tonic-gate * This interface will do a longjmp such that it never 326*7c478bd9Sstevel@tonic-gate * calls the ioctl (the setjmp would be before we restore 327*7c478bd9Sstevel@tonic-gate * the signal mask above) 328*7c478bd9Sstevel@tonic-gate */ 329*7c478bd9Sstevel@tonic-gate } 330*7c478bd9Sstevel@tonic-gate 331*7c478bd9Sstevel@tonic-gate retval = ioctl(procfd, PIOCWSTOP, &prstat); 332*7c478bd9Sstevel@tonic-gate 333*7c478bd9Sstevel@tonic-gate DBG_TNF_PROBE_2(prb_proc_wait_2, "libtnfctl", "sunw%verbosity 2;", 334*7c478bd9Sstevel@tonic-gate tnf_opaque, pc, prstat.pr_reg[R_PC], 335*7c478bd9Sstevel@tonic-gate tnf_opaque, instr, prstat.pr_instr); 336*7c478bd9Sstevel@tonic-gate 337*7c478bd9Sstevel@tonic-gate if (retval == -1) { 338*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 339*7c478bd9Sstevel@tonic-gate if (errno != EINTR && errno != ENOENT) 340*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 341*7c478bd9Sstevel@tonic-gate "prb_proc_wait: PIOCWSTOP failed: %s\n", 342*7c478bd9Sstevel@tonic-gate strerror(errno)); 343*7c478bd9Sstevel@tonic-gate 344*7c478bd9Sstevel@tonic-gate #endif 345*7c478bd9Sstevel@tonic-gate return (prb_status_map(errno)); 346*7c478bd9Sstevel@tonic-gate } 347*7c478bd9Sstevel@tonic-gate 348*7c478bd9Sstevel@tonic-gate return (PRB_STATUS_OK); 349*7c478bd9Sstevel@tonic-gate } 350*7c478bd9Sstevel@tonic-gate 351*7c478bd9Sstevel@tonic-gate 352*7c478bd9Sstevel@tonic-gate /* 353*7c478bd9Sstevel@tonic-gate * prb_proc_cont() - continues the target process 354*7c478bd9Sstevel@tonic-gate */ 355*7c478bd9Sstevel@tonic-gate prb_status_t 356*7c478bd9Sstevel@tonic-gate prb_proc_cont(prb_proc_ctl_t *proc_p) 357*7c478bd9Sstevel@tonic-gate { 358*7c478bd9Sstevel@tonic-gate int procfd; 359*7c478bd9Sstevel@tonic-gate int retval; 360*7c478bd9Sstevel@tonic-gate prrun_t prrun; 361*7c478bd9Sstevel@tonic-gate 362*7c478bd9Sstevel@tonic-gate DBG_TNF_PROBE_0(prb_proc_cont_1, "libtnfctl", 363*7c478bd9Sstevel@tonic-gate "sunw%verbosity 2; sunw%debug 'starting the target process'"); 364*7c478bd9Sstevel@tonic-gate procfd = proc_p->procfd; 365*7c478bd9Sstevel@tonic-gate 366*7c478bd9Sstevel@tonic-gate (void) memset((char *)&prrun, 0, sizeof (prrun)); 367*7c478bd9Sstevel@tonic-gate 368*7c478bd9Sstevel@tonic-gate again: 369*7c478bd9Sstevel@tonic-gate prrun.pr_flags = PRCFAULT; 370*7c478bd9Sstevel@tonic-gate retval = ioctl(procfd, PIOCRUN, &prrun); 371*7c478bd9Sstevel@tonic-gate if (retval == -1) { 372*7c478bd9Sstevel@tonic-gate if (errno == EINTR) 373*7c478bd9Sstevel@tonic-gate goto again; 374*7c478bd9Sstevel@tonic-gate DBG((void) fprintf(stderr, 375*7c478bd9Sstevel@tonic-gate "prb_proc_cont: PIOCRUN failed: %s\n", 376*7c478bd9Sstevel@tonic-gate strerror(errno))); 377*7c478bd9Sstevel@tonic-gate return (prb_status_map(errno)); 378*7c478bd9Sstevel@tonic-gate } 379*7c478bd9Sstevel@tonic-gate return (PRB_STATUS_OK); 380*7c478bd9Sstevel@tonic-gate } 381*7c478bd9Sstevel@tonic-gate 382*7c478bd9Sstevel@tonic-gate 383*7c478bd9Sstevel@tonic-gate /* 384*7c478bd9Sstevel@tonic-gate * prb_proc_istepbpt() - step the target process one instruction 385*7c478bd9Sstevel@tonic-gate * 386*7c478bd9Sstevel@tonic-gate * CAUTION!!!! - this routine is specialized to only be able to single 387*7c478bd9Sstevel@tonic-gate * step over the breakpoint location. 388*7c478bd9Sstevel@tonic-gate */ 389*7c478bd9Sstevel@tonic-gate prb_status_t 390*7c478bd9Sstevel@tonic-gate prb_proc_istepbpt(prb_proc_ctl_t *proc_p) 391*7c478bd9Sstevel@tonic-gate { 392*7c478bd9Sstevel@tonic-gate int procfd; 393*7c478bd9Sstevel@tonic-gate int retval; 394*7c478bd9Sstevel@tonic-gate prrun_t run; 395*7c478bd9Sstevel@tonic-gate fltset_t faults; 396*7c478bd9Sstevel@tonic-gate prstatus_t prstat; 397*7c478bd9Sstevel@tonic-gate 398*7c478bd9Sstevel@tonic-gate DBG_TNF_PROBE_0(prb_proc_istepbpt_1, "libtnfctl", 399*7c478bd9Sstevel@tonic-gate "sunw%verbosity 2; " 400*7c478bd9Sstevel@tonic-gate "sunw%debug 'single stepping over breakpoint'"); 401*7c478bd9Sstevel@tonic-gate 402*7c478bd9Sstevel@tonic-gate procfd = proc_p->procfd; 403*7c478bd9Sstevel@tonic-gate 404*7c478bd9Sstevel@tonic-gate (void) memset((char *)&run, 0, sizeof (run)); 405*7c478bd9Sstevel@tonic-gate 406*7c478bd9Sstevel@tonic-gate /* add trace fault to the list of current traced faults */ 407*7c478bd9Sstevel@tonic-gate again1: 408*7c478bd9Sstevel@tonic-gate retval = ioctl(procfd, PIOCGFAULT, &faults); 409*7c478bd9Sstevel@tonic-gate if (retval == -1) { 410*7c478bd9Sstevel@tonic-gate if (errno == EINTR) 411*7c478bd9Sstevel@tonic-gate goto again1; 412*7c478bd9Sstevel@tonic-gate DBG((void) fprintf(stderr, 413*7c478bd9Sstevel@tonic-gate "prb_proc_istepbpt: PIOCGFAULT failed: %s\n", 414*7c478bd9Sstevel@tonic-gate strerror(errno))); 415*7c478bd9Sstevel@tonic-gate return (prb_status_map(errno)); 416*7c478bd9Sstevel@tonic-gate } 417*7c478bd9Sstevel@tonic-gate praddset(&faults, FLTTRACE); 418*7c478bd9Sstevel@tonic-gate 419*7c478bd9Sstevel@tonic-gate /* issue the run command with the single-step option */ 420*7c478bd9Sstevel@tonic-gate run.pr_flags = PRCFAULT | PRSFAULT | PRSTEP; 421*7c478bd9Sstevel@tonic-gate run.pr_fault = faults; 422*7c478bd9Sstevel@tonic-gate 423*7c478bd9Sstevel@tonic-gate /* load the location of the breakpoint */ 424*7c478bd9Sstevel@tonic-gate run.pr_vaddr = (caddr_t)proc_p->bptaddr; 425*7c478bd9Sstevel@tonic-gate run.pr_flags |= PRSVADDR; 426*7c478bd9Sstevel@tonic-gate 427*7c478bd9Sstevel@tonic-gate again2: 428*7c478bd9Sstevel@tonic-gate retval = ioctl(procfd, PIOCRUN, &run); 429*7c478bd9Sstevel@tonic-gate if (retval == -1) { 430*7c478bd9Sstevel@tonic-gate if (errno == EINTR) 431*7c478bd9Sstevel@tonic-gate goto again2; 432*7c478bd9Sstevel@tonic-gate DBG((void) fprintf(stderr, 433*7c478bd9Sstevel@tonic-gate "prb_proc_istepbpt: PIOCRUN failed: %s\n", 434*7c478bd9Sstevel@tonic-gate strerror(errno))); 435*7c478bd9Sstevel@tonic-gate return (prb_status_map(errno)); 436*7c478bd9Sstevel@tonic-gate } 437*7c478bd9Sstevel@tonic-gate again3: 438*7c478bd9Sstevel@tonic-gate retval = ioctl(procfd, PIOCWSTOP, &prstat); 439*7c478bd9Sstevel@tonic-gate if (retval == -1) { 440*7c478bd9Sstevel@tonic-gate if (errno == EINTR) 441*7c478bd9Sstevel@tonic-gate goto again3; 442*7c478bd9Sstevel@tonic-gate DBG((void) fprintf(stderr, 443*7c478bd9Sstevel@tonic-gate "prb_proc_istepbpt: PIOCWSTOP failed: %s\n", 444*7c478bd9Sstevel@tonic-gate strerror(errno))); 445*7c478bd9Sstevel@tonic-gate return (prb_status_map(errno)); 446*7c478bd9Sstevel@tonic-gate } 447*7c478bd9Sstevel@tonic-gate 448*7c478bd9Sstevel@tonic-gate DBG_TNF_PROBE_2(prb_proc_istepbpt_2, "libtnfctl", "sunw%verbosity 2;", 449*7c478bd9Sstevel@tonic-gate tnf_opaque, pc, prstat.pr_reg[R_PC], 450*7c478bd9Sstevel@tonic-gate tnf_opaque, instr, prstat.pr_instr); 451*7c478bd9Sstevel@tonic-gate 452*7c478bd9Sstevel@tonic-gate 453*7c478bd9Sstevel@tonic-gate /* clear any current faults */ 454*7c478bd9Sstevel@tonic-gate again4: 455*7c478bd9Sstevel@tonic-gate retval = ioctl(procfd, PIOCCFAULT, NULL); 456*7c478bd9Sstevel@tonic-gate if (retval == -1) { 457*7c478bd9Sstevel@tonic-gate if (errno == EINTR) 458*7c478bd9Sstevel@tonic-gate goto again4; 459*7c478bd9Sstevel@tonic-gate DBG((void) fprintf(stderr, 460*7c478bd9Sstevel@tonic-gate "prb_proc_clrbptflt: PIOCCFAULT failed: %s\n", 461*7c478bd9Sstevel@tonic-gate strerror(errno))); 462*7c478bd9Sstevel@tonic-gate return (prb_status_map(errno)); 463*7c478bd9Sstevel@tonic-gate } 464*7c478bd9Sstevel@tonic-gate /* remove the trace fault from the current traced faults */ 465*7c478bd9Sstevel@tonic-gate prdelset(&faults, FLTTRACE); 466*7c478bd9Sstevel@tonic-gate again5: 467*7c478bd9Sstevel@tonic-gate retval = ioctl(procfd, PIOCSFAULT, &faults); 468*7c478bd9Sstevel@tonic-gate if (retval == -1) { 469*7c478bd9Sstevel@tonic-gate if (errno == EINTR) 470*7c478bd9Sstevel@tonic-gate goto again5; 471*7c478bd9Sstevel@tonic-gate DBG((void) fprintf(stderr, 472*7c478bd9Sstevel@tonic-gate "prb_proc_istepbpt: PIOCSFAULT failed: %s\n", 473*7c478bd9Sstevel@tonic-gate strerror(errno))); 474*7c478bd9Sstevel@tonic-gate return (prb_status_map(errno)); 475*7c478bd9Sstevel@tonic-gate } 476*7c478bd9Sstevel@tonic-gate return (PRB_STATUS_OK); 477*7c478bd9Sstevel@tonic-gate } 478*7c478bd9Sstevel@tonic-gate 479*7c478bd9Sstevel@tonic-gate 480*7c478bd9Sstevel@tonic-gate /* 481*7c478bd9Sstevel@tonic-gate * prb_proc_clrbptflt() - clear an encountered breakpoint fault 482*7c478bd9Sstevel@tonic-gate */ 483*7c478bd9Sstevel@tonic-gate prb_status_t 484*7c478bd9Sstevel@tonic-gate prb_proc_clrbptflt(prb_proc_ctl_t *proc_p) 485*7c478bd9Sstevel@tonic-gate { 486*7c478bd9Sstevel@tonic-gate int retval; 487*7c478bd9Sstevel@tonic-gate int procfd; 488*7c478bd9Sstevel@tonic-gate 489*7c478bd9Sstevel@tonic-gate DBG_TNF_PROBE_0(prb_proc_clrbptflt_1, "libtnfctl", "sunw%verbosity 2"); 490*7c478bd9Sstevel@tonic-gate 491*7c478bd9Sstevel@tonic-gate procfd = proc_p->procfd; 492*7c478bd9Sstevel@tonic-gate 493*7c478bd9Sstevel@tonic-gate /* clear any current faults */ 494*7c478bd9Sstevel@tonic-gate again: 495*7c478bd9Sstevel@tonic-gate retval = ioctl(procfd, PIOCCFAULT, NULL); 496*7c478bd9Sstevel@tonic-gate if (retval == -1) { 497*7c478bd9Sstevel@tonic-gate if (errno == EINTR) 498*7c478bd9Sstevel@tonic-gate goto again; 499*7c478bd9Sstevel@tonic-gate DBG((void) fprintf(stderr, 500*7c478bd9Sstevel@tonic-gate "prb_proc_clrbptflt: PIOCCFAULT failed: %s\n", 501*7c478bd9Sstevel@tonic-gate strerror(errno))); 502*7c478bd9Sstevel@tonic-gate return (prb_status_map(errno)); 503*7c478bd9Sstevel@tonic-gate } 504*7c478bd9Sstevel@tonic-gate return (PRB_STATUS_OK); 505*7c478bd9Sstevel@tonic-gate } 506*7c478bd9Sstevel@tonic-gate 507*7c478bd9Sstevel@tonic-gate 508*7c478bd9Sstevel@tonic-gate /* 509*7c478bd9Sstevel@tonic-gate * prb_proc_tracebpt() - sets the bpt tracing state. 510*7c478bd9Sstevel@tonic-gate */ 511*7c478bd9Sstevel@tonic-gate prb_status_t 512*7c478bd9Sstevel@tonic-gate prb_proc_tracebpt(prb_proc_ctl_t *proc_p, boolean_t bpt) 513*7c478bd9Sstevel@tonic-gate { 514*7c478bd9Sstevel@tonic-gate int procfd; 515*7c478bd9Sstevel@tonic-gate int retval; 516*7c478bd9Sstevel@tonic-gate fltset_t faults; 517*7c478bd9Sstevel@tonic-gate 518*7c478bd9Sstevel@tonic-gate DBG_TNF_PROBE_1(prb_proc_tracebpt_1, "libtnfctl", "sunw%verbosity 2;", 519*7c478bd9Sstevel@tonic-gate tnf_string, bpt_state, (bpt) ? "enabled" : "disabled"); 520*7c478bd9Sstevel@tonic-gate 521*7c478bd9Sstevel@tonic-gate procfd = proc_p->procfd; 522*7c478bd9Sstevel@tonic-gate /* get the current set of traced faults */ 523*7c478bd9Sstevel@tonic-gate again1: 524*7c478bd9Sstevel@tonic-gate retval = ioctl(procfd, PIOCGFAULT, &faults); 525*7c478bd9Sstevel@tonic-gate if (retval == -1) { 526*7c478bd9Sstevel@tonic-gate if (errno == EINTR) 527*7c478bd9Sstevel@tonic-gate goto again1; 528*7c478bd9Sstevel@tonic-gate DBG((void) fprintf(stderr, 529*7c478bd9Sstevel@tonic-gate "prb_proc_tracebpt: PIOCGFAULT failed: %s\n", 530*7c478bd9Sstevel@tonic-gate strerror(errno))); 531*7c478bd9Sstevel@tonic-gate return (prb_status_map(errno)); 532*7c478bd9Sstevel@tonic-gate } 533*7c478bd9Sstevel@tonic-gate /* set or clear the breakpoint flag */ 534*7c478bd9Sstevel@tonic-gate if (bpt) 535*7c478bd9Sstevel@tonic-gate praddset(&faults, FLTBPT); 536*7c478bd9Sstevel@tonic-gate else 537*7c478bd9Sstevel@tonic-gate prdelset(&faults, FLTBPT); 538*7c478bd9Sstevel@tonic-gate 539*7c478bd9Sstevel@tonic-gate /* write the fault set back */ 540*7c478bd9Sstevel@tonic-gate again2: 541*7c478bd9Sstevel@tonic-gate retval = ioctl(procfd, PIOCSFAULT, &faults); 542*7c478bd9Sstevel@tonic-gate if (retval == -1) { 543*7c478bd9Sstevel@tonic-gate if (errno == EINTR) 544*7c478bd9Sstevel@tonic-gate goto again2; 545*7c478bd9Sstevel@tonic-gate DBG((void) fprintf(stderr, 546*7c478bd9Sstevel@tonic-gate "prb_proc_tracebpt: PIOCSFAULT failed: %s\n", 547*7c478bd9Sstevel@tonic-gate strerror(errno))); 548*7c478bd9Sstevel@tonic-gate return (prb_status_map(errno)); 549*7c478bd9Sstevel@tonic-gate } 550*7c478bd9Sstevel@tonic-gate return (PRB_STATUS_OK); 551*7c478bd9Sstevel@tonic-gate } 552*7c478bd9Sstevel@tonic-gate 553*7c478bd9Sstevel@tonic-gate /* Note - the following 3 functions should be combined */ 554*7c478bd9Sstevel@tonic-gate 555*7c478bd9Sstevel@tonic-gate /* 556*7c478bd9Sstevel@tonic-gate * prb_proc_setrlc() - sets or clears the run-on-last-close flag. 557*7c478bd9Sstevel@tonic-gate */ 558*7c478bd9Sstevel@tonic-gate prb_status_t 559*7c478bd9Sstevel@tonic-gate prb_proc_setrlc(prb_proc_ctl_t *proc_p, boolean_t rlc) 560*7c478bd9Sstevel@tonic-gate { 561*7c478bd9Sstevel@tonic-gate int procfd; 562*7c478bd9Sstevel@tonic-gate long mode; 563*7c478bd9Sstevel@tonic-gate int retval; 564*7c478bd9Sstevel@tonic-gate 565*7c478bd9Sstevel@tonic-gate DBG_TNF_PROBE_1(prb_proc_setrlc_1, "libtnfctl", "sunw%verbosity 2;", 566*7c478bd9Sstevel@tonic-gate tnf_string, run_on_last_close, (rlc) ? "setting" : "clearing"); 567*7c478bd9Sstevel@tonic-gate 568*7c478bd9Sstevel@tonic-gate procfd = proc_p->procfd; 569*7c478bd9Sstevel@tonic-gate mode = PR_RLC; 570*7c478bd9Sstevel@tonic-gate 571*7c478bd9Sstevel@tonic-gate if (rlc) { 572*7c478bd9Sstevel@tonic-gate again1: 573*7c478bd9Sstevel@tonic-gate retval = ioctl(procfd, PIOCSET, &mode); 574*7c478bd9Sstevel@tonic-gate if (retval == -1) { 575*7c478bd9Sstevel@tonic-gate if (errno == EINTR) 576*7c478bd9Sstevel@tonic-gate goto again1; 577*7c478bd9Sstevel@tonic-gate DBG((void) fprintf(stderr, 578*7c478bd9Sstevel@tonic-gate "prb_proc_setrlc: PIOCSET failed: %s\n", 579*7c478bd9Sstevel@tonic-gate strerror(errno))); 580*7c478bd9Sstevel@tonic-gate return (prb_status_map(errno)); 581*7c478bd9Sstevel@tonic-gate } 582*7c478bd9Sstevel@tonic-gate } else { 583*7c478bd9Sstevel@tonic-gate again2: 584*7c478bd9Sstevel@tonic-gate retval = ioctl(procfd, PIOCRESET, &mode); 585*7c478bd9Sstevel@tonic-gate if (retval == -1) { 586*7c478bd9Sstevel@tonic-gate if (errno == EINTR) 587*7c478bd9Sstevel@tonic-gate goto again2; 588*7c478bd9Sstevel@tonic-gate DBG((void) fprintf(stderr, 589*7c478bd9Sstevel@tonic-gate "prb_proc_setrlc: PIOCRESET failed: %s\n", 590*7c478bd9Sstevel@tonic-gate strerror(errno))); 591*7c478bd9Sstevel@tonic-gate return (prb_status_map(errno)); 592*7c478bd9Sstevel@tonic-gate } 593*7c478bd9Sstevel@tonic-gate } 594*7c478bd9Sstevel@tonic-gate 595*7c478bd9Sstevel@tonic-gate return (PRB_STATUS_OK); 596*7c478bd9Sstevel@tonic-gate 597*7c478bd9Sstevel@tonic-gate 598*7c478bd9Sstevel@tonic-gate } /* end prb_proc_setrlc */ 599*7c478bd9Sstevel@tonic-gate 600*7c478bd9Sstevel@tonic-gate 601*7c478bd9Sstevel@tonic-gate /* 602*7c478bd9Sstevel@tonic-gate * prb_proc_setklc() - sets or clears the kill-on-last-close flag. 603*7c478bd9Sstevel@tonic-gate */ 604*7c478bd9Sstevel@tonic-gate prb_status_t 605*7c478bd9Sstevel@tonic-gate prb_proc_setklc(prb_proc_ctl_t *proc_p, boolean_t klc) 606*7c478bd9Sstevel@tonic-gate { 607*7c478bd9Sstevel@tonic-gate int procfd; 608*7c478bd9Sstevel@tonic-gate long mode; 609*7c478bd9Sstevel@tonic-gate int retval; 610*7c478bd9Sstevel@tonic-gate 611*7c478bd9Sstevel@tonic-gate DBG_TNF_PROBE_1(prb_proc_setklc_1, "libtnfctl", "sunw%verbosity 2;", 612*7c478bd9Sstevel@tonic-gate tnf_string, kill_on_last_close, (klc) ? "setting" : "clearing"); 613*7c478bd9Sstevel@tonic-gate 614*7c478bd9Sstevel@tonic-gate procfd = proc_p->procfd; 615*7c478bd9Sstevel@tonic-gate mode = PR_KLC; 616*7c478bd9Sstevel@tonic-gate 617*7c478bd9Sstevel@tonic-gate if (klc) { 618*7c478bd9Sstevel@tonic-gate again1: 619*7c478bd9Sstevel@tonic-gate retval = ioctl(procfd, PIOCSET, &mode); 620*7c478bd9Sstevel@tonic-gate if (retval == -1) { 621*7c478bd9Sstevel@tonic-gate if (errno == EINTR) 622*7c478bd9Sstevel@tonic-gate goto again1; 623*7c478bd9Sstevel@tonic-gate DBG((void) fprintf(stderr, 624*7c478bd9Sstevel@tonic-gate "prb_proc_setklc: PIOCSET failed: %s\n", 625*7c478bd9Sstevel@tonic-gate strerror(errno))); 626*7c478bd9Sstevel@tonic-gate return (prb_status_map(errno)); 627*7c478bd9Sstevel@tonic-gate } 628*7c478bd9Sstevel@tonic-gate } else { 629*7c478bd9Sstevel@tonic-gate again2: 630*7c478bd9Sstevel@tonic-gate retval = ioctl(procfd, PIOCRESET, &mode); 631*7c478bd9Sstevel@tonic-gate if (retval == -1) { 632*7c478bd9Sstevel@tonic-gate if (errno == EINTR) 633*7c478bd9Sstevel@tonic-gate goto again2; 634*7c478bd9Sstevel@tonic-gate DBG((void) fprintf(stderr, 635*7c478bd9Sstevel@tonic-gate "prb_proc_setklc: PIOCRESET failed: %s\n", 636*7c478bd9Sstevel@tonic-gate strerror(errno))); 637*7c478bd9Sstevel@tonic-gate return (prb_status_map(errno)); 638*7c478bd9Sstevel@tonic-gate } 639*7c478bd9Sstevel@tonic-gate } 640*7c478bd9Sstevel@tonic-gate 641*7c478bd9Sstevel@tonic-gate return (PRB_STATUS_OK); 642*7c478bd9Sstevel@tonic-gate 643*7c478bd9Sstevel@tonic-gate } /* end prb_proc_setklc */ 644*7c478bd9Sstevel@tonic-gate 645*7c478bd9Sstevel@tonic-gate /* 646*7c478bd9Sstevel@tonic-gate * prb_proc_setfork() - sets or clears the inherit-on-fork flag 647*7c478bd9Sstevel@tonic-gate */ 648*7c478bd9Sstevel@tonic-gate prb_status_t 649*7c478bd9Sstevel@tonic-gate prb_proc_setfork(prb_proc_ctl_t *proc_p, boolean_t inhfork) 650*7c478bd9Sstevel@tonic-gate { 651*7c478bd9Sstevel@tonic-gate int procfd; 652*7c478bd9Sstevel@tonic-gate long mode; 653*7c478bd9Sstevel@tonic-gate int retval; 654*7c478bd9Sstevel@tonic-gate 655*7c478bd9Sstevel@tonic-gate DBG_TNF_PROBE_1(prb_proc_setfork_1, "libtnfctl", "sunw%verbosity 2;", 656*7c478bd9Sstevel@tonic-gate tnf_string, kill_on_last_close, 657*7c478bd9Sstevel@tonic-gate (inhfork) ? "setting" : "clearing"); 658*7c478bd9Sstevel@tonic-gate 659*7c478bd9Sstevel@tonic-gate procfd = proc_p->procfd; 660*7c478bd9Sstevel@tonic-gate mode = PR_FORK; 661*7c478bd9Sstevel@tonic-gate 662*7c478bd9Sstevel@tonic-gate if (inhfork) { 663*7c478bd9Sstevel@tonic-gate again1: 664*7c478bd9Sstevel@tonic-gate retval = ioctl(procfd, PIOCSET, &mode); 665*7c478bd9Sstevel@tonic-gate if (retval == -1) { 666*7c478bd9Sstevel@tonic-gate if (errno == EINTR) 667*7c478bd9Sstevel@tonic-gate goto again1; 668*7c478bd9Sstevel@tonic-gate DBG((void) fprintf(stderr, 669*7c478bd9Sstevel@tonic-gate "prb_proc_setfork: PIOCSET failed: %s\n", 670*7c478bd9Sstevel@tonic-gate strerror(errno))); 671*7c478bd9Sstevel@tonic-gate return (prb_status_map(errno)); 672*7c478bd9Sstevel@tonic-gate } 673*7c478bd9Sstevel@tonic-gate } else { 674*7c478bd9Sstevel@tonic-gate again2: 675*7c478bd9Sstevel@tonic-gate retval = ioctl(procfd, PIOCRESET, &mode); 676*7c478bd9Sstevel@tonic-gate if (retval == -1) { 677*7c478bd9Sstevel@tonic-gate if (errno == EINTR) 678*7c478bd9Sstevel@tonic-gate goto again2; 679*7c478bd9Sstevel@tonic-gate DBG((void) fprintf(stderr, 680*7c478bd9Sstevel@tonic-gate "prb_proc_setfork: PIOCRESET failed: %s\n", 681*7c478bd9Sstevel@tonic-gate strerror(errno))); 682*7c478bd9Sstevel@tonic-gate return (prb_status_map(errno)); 683*7c478bd9Sstevel@tonic-gate } 684*7c478bd9Sstevel@tonic-gate } 685*7c478bd9Sstevel@tonic-gate 686*7c478bd9Sstevel@tonic-gate return (PRB_STATUS_OK); 687*7c478bd9Sstevel@tonic-gate 688*7c478bd9Sstevel@tonic-gate } /* end prb_proc_setfork */ 689*7c478bd9Sstevel@tonic-gate 690*7c478bd9Sstevel@tonic-gate /* 691*7c478bd9Sstevel@tonic-gate * prb_proc_exit() - if op is PRB_SYS_ALL, sets up the target process to stop 692*7c478bd9Sstevel@tonic-gate * on exit from all system calls. If op is PRB_SYS_NONE, sets up the target 693*7c478bd9Sstevel@tonic-gate * process so that it will not stop on exit from any system call. 694*7c478bd9Sstevel@tonic-gate * PRB_SYS_ADD and PRB_SYS_DEL adds or deletes a particular system call from 695*7c478bd9Sstevel@tonic-gate * the mask of "interested" system calls respectively. This function can be 696*7c478bd9Sstevel@tonic-gate * called multiple times to build up the mask. 697*7c478bd9Sstevel@tonic-gate */ 698*7c478bd9Sstevel@tonic-gate prb_status_t 699*7c478bd9Sstevel@tonic-gate prb_proc_exit(prb_proc_ctl_t *proc_p, 700*7c478bd9Sstevel@tonic-gate uint_t syscall, 701*7c478bd9Sstevel@tonic-gate prb_syscall_op_t op) 702*7c478bd9Sstevel@tonic-gate { 703*7c478bd9Sstevel@tonic-gate int procfd; 704*7c478bd9Sstevel@tonic-gate int retval; 705*7c478bd9Sstevel@tonic-gate sysset_t sysmask; 706*7c478bd9Sstevel@tonic-gate 707*7c478bd9Sstevel@tonic-gate DBG_TNF_PROBE_0(prb_proc_exit_1, "libtnfctl", 708*7c478bd9Sstevel@tonic-gate "sunw%verbosity 2; " 709*7c478bd9Sstevel@tonic-gate "sunw%debug 'setting up target to stop on exit of syscall'"); 710*7c478bd9Sstevel@tonic-gate 711*7c478bd9Sstevel@tonic-gate procfd = proc_p->procfd; 712*7c478bd9Sstevel@tonic-gate 713*7c478bd9Sstevel@tonic-gate switch (op) { 714*7c478bd9Sstevel@tonic-gate case PRB_SYS_ALL: 715*7c478bd9Sstevel@tonic-gate prfillset(&sysmask); 716*7c478bd9Sstevel@tonic-gate break; 717*7c478bd9Sstevel@tonic-gate case PRB_SYS_NONE: 718*7c478bd9Sstevel@tonic-gate premptyset(&sysmask); 719*7c478bd9Sstevel@tonic-gate break; 720*7c478bd9Sstevel@tonic-gate case PRB_SYS_ADD: 721*7c478bd9Sstevel@tonic-gate again1: 722*7c478bd9Sstevel@tonic-gate retval = ioctl(procfd, PIOCGEXIT, &sysmask); 723*7c478bd9Sstevel@tonic-gate if (retval == -1) { 724*7c478bd9Sstevel@tonic-gate if (errno == EINTR) 725*7c478bd9Sstevel@tonic-gate goto again1; 726*7c478bd9Sstevel@tonic-gate DBG((void) fprintf(stderr, 727*7c478bd9Sstevel@tonic-gate "prb_proc_exit: PIOCGEXIT failed: %s\n", 728*7c478bd9Sstevel@tonic-gate strerror(errno))); 729*7c478bd9Sstevel@tonic-gate return (prb_status_map(errno)); 730*7c478bd9Sstevel@tonic-gate } 731*7c478bd9Sstevel@tonic-gate praddset(&sysmask, syscall); 732*7c478bd9Sstevel@tonic-gate break; 733*7c478bd9Sstevel@tonic-gate case PRB_SYS_DEL: 734*7c478bd9Sstevel@tonic-gate again2: 735*7c478bd9Sstevel@tonic-gate retval = ioctl(procfd, PIOCGEXIT, &sysmask); 736*7c478bd9Sstevel@tonic-gate if (retval == -1) { 737*7c478bd9Sstevel@tonic-gate if (errno == EINTR) 738*7c478bd9Sstevel@tonic-gate goto again2; 739*7c478bd9Sstevel@tonic-gate DBG((void) fprintf(stderr, 740*7c478bd9Sstevel@tonic-gate "prb_proc_exit: PIOCGEXIT failed: %s\n", 741*7c478bd9Sstevel@tonic-gate strerror(errno))); 742*7c478bd9Sstevel@tonic-gate return (prb_status_map(errno)); 743*7c478bd9Sstevel@tonic-gate } 744*7c478bd9Sstevel@tonic-gate prdelset(&sysmask, syscall); 745*7c478bd9Sstevel@tonic-gate break; 746*7c478bd9Sstevel@tonic-gate default: 747*7c478bd9Sstevel@tonic-gate DBG((void) fprintf(stderr, "prb_proc_exit: bad input arg\n")); 748*7c478bd9Sstevel@tonic-gate return (PRB_STATUS_BADARG); 749*7c478bd9Sstevel@tonic-gate } 750*7c478bd9Sstevel@tonic-gate again3: 751*7c478bd9Sstevel@tonic-gate retval = ioctl(procfd, PIOCSEXIT, &sysmask); 752*7c478bd9Sstevel@tonic-gate if (retval == -1) { 753*7c478bd9Sstevel@tonic-gate if (errno == EINTR) 754*7c478bd9Sstevel@tonic-gate goto again3; 755*7c478bd9Sstevel@tonic-gate DBG((void) fprintf(stderr, 756*7c478bd9Sstevel@tonic-gate "prb_proc_exit: PIOCSEXIT failed: %s\n", 757*7c478bd9Sstevel@tonic-gate strerror(errno))); 758*7c478bd9Sstevel@tonic-gate return (prb_status_map(errno)); 759*7c478bd9Sstevel@tonic-gate } 760*7c478bd9Sstevel@tonic-gate return (PRB_STATUS_OK); 761*7c478bd9Sstevel@tonic-gate 762*7c478bd9Sstevel@tonic-gate } /* end prb_proc_exit */ 763*7c478bd9Sstevel@tonic-gate 764*7c478bd9Sstevel@tonic-gate /* 765*7c478bd9Sstevel@tonic-gate * prb_proc_entry() - if op is PRB_SYS_ALL, sets up the target process to 766*7c478bd9Sstevel@tonic-gate * stop on entry from all system calls. If op is PRB_SYS_NONE, sets up the 767*7c478bd9Sstevel@tonic-gate * target process so that it will not stop on entry from any system call. 768*7c478bd9Sstevel@tonic-gate * PRB_SYS_ADD and PRB_SYS_DEL adds or deletes a particular system call from 769*7c478bd9Sstevel@tonic-gate * the mask of "interested" system calls respectively. This function can be 770*7c478bd9Sstevel@tonic-gate * called multiple times to build up the mask. 771*7c478bd9Sstevel@tonic-gate */ 772*7c478bd9Sstevel@tonic-gate prb_status_t 773*7c478bd9Sstevel@tonic-gate prb_proc_entry(prb_proc_ctl_t *proc_p, 774*7c478bd9Sstevel@tonic-gate uint_t syscall, 775*7c478bd9Sstevel@tonic-gate prb_syscall_op_t op) 776*7c478bd9Sstevel@tonic-gate { 777*7c478bd9Sstevel@tonic-gate int procfd; 778*7c478bd9Sstevel@tonic-gate int retval; 779*7c478bd9Sstevel@tonic-gate sysset_t sysmask; 780*7c478bd9Sstevel@tonic-gate 781*7c478bd9Sstevel@tonic-gate DBG_TNF_PROBE_0(prb_proc_entry_1, "libtnfctl", 782*7c478bd9Sstevel@tonic-gate "sunw%verbosity 2; " 783*7c478bd9Sstevel@tonic-gate "sunw%debug 'setting up target to stop on entry of syscall'"); 784*7c478bd9Sstevel@tonic-gate 785*7c478bd9Sstevel@tonic-gate procfd = proc_p->procfd; 786*7c478bd9Sstevel@tonic-gate 787*7c478bd9Sstevel@tonic-gate switch (op) { 788*7c478bd9Sstevel@tonic-gate case PRB_SYS_ALL: 789*7c478bd9Sstevel@tonic-gate prfillset(&sysmask); 790*7c478bd9Sstevel@tonic-gate break; 791*7c478bd9Sstevel@tonic-gate case PRB_SYS_NONE: 792*7c478bd9Sstevel@tonic-gate premptyset(&sysmask); 793*7c478bd9Sstevel@tonic-gate break; 794*7c478bd9Sstevel@tonic-gate case PRB_SYS_ADD: 795*7c478bd9Sstevel@tonic-gate again1: 796*7c478bd9Sstevel@tonic-gate retval = ioctl(procfd, PIOCGENTRY, &sysmask); 797*7c478bd9Sstevel@tonic-gate if (retval == -1) { 798*7c478bd9Sstevel@tonic-gate if (errno == EINTR) 799*7c478bd9Sstevel@tonic-gate goto again1; 800*7c478bd9Sstevel@tonic-gate DBG((void) fprintf(stderr, 801*7c478bd9Sstevel@tonic-gate "prb_proc_entry: PIOCGENTRY failed: %s\n", 802*7c478bd9Sstevel@tonic-gate strerror(errno))); 803*7c478bd9Sstevel@tonic-gate return (prb_status_map(errno)); 804*7c478bd9Sstevel@tonic-gate } 805*7c478bd9Sstevel@tonic-gate praddset(&sysmask, syscall); 806*7c478bd9Sstevel@tonic-gate break; 807*7c478bd9Sstevel@tonic-gate case PRB_SYS_DEL: 808*7c478bd9Sstevel@tonic-gate again2: 809*7c478bd9Sstevel@tonic-gate retval = ioctl(procfd, PIOCGENTRY, &sysmask); 810*7c478bd9Sstevel@tonic-gate if (retval == -1) { 811*7c478bd9Sstevel@tonic-gate if (errno == EINTR) 812*7c478bd9Sstevel@tonic-gate goto again2; 813*7c478bd9Sstevel@tonic-gate DBG((void) fprintf(stderr, 814*7c478bd9Sstevel@tonic-gate "prb_proc_entry: PIOCGENTRY failed: %s\n", 815*7c478bd9Sstevel@tonic-gate strerror(errno))); 816*7c478bd9Sstevel@tonic-gate return (prb_status_map(errno)); 817*7c478bd9Sstevel@tonic-gate } 818*7c478bd9Sstevel@tonic-gate prdelset(&sysmask, syscall); 819*7c478bd9Sstevel@tonic-gate break; 820*7c478bd9Sstevel@tonic-gate default: 821*7c478bd9Sstevel@tonic-gate DBG((void) fprintf(stderr, "prb_proc_entry: bad input arg\n")); 822*7c478bd9Sstevel@tonic-gate return (PRB_STATUS_BADARG); 823*7c478bd9Sstevel@tonic-gate } 824*7c478bd9Sstevel@tonic-gate again3: 825*7c478bd9Sstevel@tonic-gate retval = ioctl(procfd, PIOCSENTRY, &sysmask); 826*7c478bd9Sstevel@tonic-gate if (retval == -1) { 827*7c478bd9Sstevel@tonic-gate if (errno == EINTR) 828*7c478bd9Sstevel@tonic-gate goto again3; 829*7c478bd9Sstevel@tonic-gate DBG((void) fprintf(stderr, 830*7c478bd9Sstevel@tonic-gate "prb_proc_entry: PIOCSENTRY failed: %s\n", 831*7c478bd9Sstevel@tonic-gate strerror(errno))); 832*7c478bd9Sstevel@tonic-gate return (prb_status_map(errno)); 833*7c478bd9Sstevel@tonic-gate } 834*7c478bd9Sstevel@tonic-gate return (PRB_STATUS_OK); 835*7c478bd9Sstevel@tonic-gate } 836*7c478bd9Sstevel@tonic-gate 837*7c478bd9Sstevel@tonic-gate /* 838*7c478bd9Sstevel@tonic-gate * prb_proc_read() - reads a block of memory from a processes address space. 839*7c478bd9Sstevel@tonic-gate */ 840*7c478bd9Sstevel@tonic-gate prb_status_t 841*7c478bd9Sstevel@tonic-gate prb_proc_read(prb_proc_ctl_t *proc_p, uintptr_t addr, void *buf, size_t size) 842*7c478bd9Sstevel@tonic-gate { 843*7c478bd9Sstevel@tonic-gate int procfd; 844*7c478bd9Sstevel@tonic-gate ssize_t sz; 845*7c478bd9Sstevel@tonic-gate off_t offset; 846*7c478bd9Sstevel@tonic-gate 847*7c478bd9Sstevel@tonic-gate DBG_TNF_PROBE_2(prb_proc_read_1, "libtnfctl", "sunw%verbosity 3;", 848*7c478bd9Sstevel@tonic-gate tnf_long, num_bytes, size, 849*7c478bd9Sstevel@tonic-gate tnf_opaque, from_address, addr); 850*7c478bd9Sstevel@tonic-gate 851*7c478bd9Sstevel@tonic-gate procfd = proc_p->procfd; 852*7c478bd9Sstevel@tonic-gate offset = lseek(procfd, (off_t)addr, SEEK_SET); 853*7c478bd9Sstevel@tonic-gate if (offset != (off_t)addr) { 854*7c478bd9Sstevel@tonic-gate DBG(perror("prb_proc_read: lseek failed")); 855*7c478bd9Sstevel@tonic-gate return (prb_status_map(errno)); 856*7c478bd9Sstevel@tonic-gate } 857*7c478bd9Sstevel@tonic-gate sz = read(procfd, buf, size); 858*7c478bd9Sstevel@tonic-gate if (sz != size) { 859*7c478bd9Sstevel@tonic-gate DBG(perror("prb_proc_read: read failed")); 860*7c478bd9Sstevel@tonic-gate return (prb_status_map(errno)); 861*7c478bd9Sstevel@tonic-gate } 862*7c478bd9Sstevel@tonic-gate return (PRB_STATUS_OK); 863*7c478bd9Sstevel@tonic-gate } 864*7c478bd9Sstevel@tonic-gate 865*7c478bd9Sstevel@tonic-gate 866*7c478bd9Sstevel@tonic-gate /* 867*7c478bd9Sstevel@tonic-gate * prb_proc_write() - writes a block of memory from a processes address 868*7c478bd9Sstevel@tonic-gate * space. 869*7c478bd9Sstevel@tonic-gate */ 870*7c478bd9Sstevel@tonic-gate prb_status_t 871*7c478bd9Sstevel@tonic-gate prb_proc_write(prb_proc_ctl_t *proc_p, uintptr_t addr, void *buf, size_t size) 872*7c478bd9Sstevel@tonic-gate { 873*7c478bd9Sstevel@tonic-gate int procfd; 874*7c478bd9Sstevel@tonic-gate ssize_t sz; 875*7c478bd9Sstevel@tonic-gate off_t offset; 876*7c478bd9Sstevel@tonic-gate 877*7c478bd9Sstevel@tonic-gate DBG_TNF_PROBE_2(prb_proc_write_1, "libtnfctl", "sunw%verbosity 3;", 878*7c478bd9Sstevel@tonic-gate tnf_long, num_bytes, size, 879*7c478bd9Sstevel@tonic-gate tnf_opaque, to_address, addr); 880*7c478bd9Sstevel@tonic-gate 881*7c478bd9Sstevel@tonic-gate procfd = proc_p->procfd; 882*7c478bd9Sstevel@tonic-gate offset = lseek(procfd, (off_t)addr, SEEK_SET); 883*7c478bd9Sstevel@tonic-gate if (offset != (off_t)addr) { 884*7c478bd9Sstevel@tonic-gate DBG(perror("prb_proc_write: lseek failed")); 885*7c478bd9Sstevel@tonic-gate return (prb_status_map(errno)); 886*7c478bd9Sstevel@tonic-gate } 887*7c478bd9Sstevel@tonic-gate sz = write(procfd, buf, size); 888*7c478bd9Sstevel@tonic-gate if (sz != size) { 889*7c478bd9Sstevel@tonic-gate DBG(perror("prb_proc_write: write failed")); 890*7c478bd9Sstevel@tonic-gate return (prb_status_map(errno)); 891*7c478bd9Sstevel@tonic-gate } 892*7c478bd9Sstevel@tonic-gate return (PRB_STATUS_OK); 893*7c478bd9Sstevel@tonic-gate } 894*7c478bd9Sstevel@tonic-gate 895*7c478bd9Sstevel@tonic-gate 896*7c478bd9Sstevel@tonic-gate /* 897*7c478bd9Sstevel@tonic-gate * prb_proc_readstr() - dereferences a string in the target 898*7c478bd9Sstevel@tonic-gate * NOTE: There is a similar routine called _tnfctl_readstr_targ() 899*7c478bd9Sstevel@tonic-gate * used by tnfctl layer. It would be better if there was only 900*7c478bd9Sstevel@tonic-gate * one of these functions defined. 901*7c478bd9Sstevel@tonic-gate */ 902*7c478bd9Sstevel@tonic-gate 903*7c478bd9Sstevel@tonic-gate #define BUFSZ 256 904*7c478bd9Sstevel@tonic-gate 905*7c478bd9Sstevel@tonic-gate prb_status_t 906*7c478bd9Sstevel@tonic-gate prb_proc_readstr(prb_proc_ctl_t *proc_p, uintptr_t addr, const char **outstr_pp) 907*7c478bd9Sstevel@tonic-gate { 908*7c478bd9Sstevel@tonic-gate prb_status_t prbstat; 909*7c478bd9Sstevel@tonic-gate int bufsz = BUFSZ; 910*7c478bd9Sstevel@tonic-gate char buffer[BUFSZ + 1]; 911*7c478bd9Sstevel@tonic-gate offset_t offset; 912*7c478bd9Sstevel@tonic-gate char *ptr, *orig_ptr; 913*7c478bd9Sstevel@tonic-gate 914*7c478bd9Sstevel@tonic-gate *outstr_pp = NULL; 915*7c478bd9Sstevel@tonic-gate offset = 0; 916*7c478bd9Sstevel@tonic-gate 917*7c478bd9Sstevel@tonic-gate /* allocate an inital return buffer */ 918*7c478bd9Sstevel@tonic-gate ptr = (char *)malloc(BUFSZ); 919*7c478bd9Sstevel@tonic-gate if (!ptr) { 920*7c478bd9Sstevel@tonic-gate DBG((void) fprintf(stderr, 921*7c478bd9Sstevel@tonic-gate "prb_proc_readstr: malloc failed\n")); 922*7c478bd9Sstevel@tonic-gate return (PRB_STATUS_ALLOCFAIL); 923*7c478bd9Sstevel@tonic-gate } 924*7c478bd9Sstevel@tonic-gate /*LINTED constant in conditional context*/ 925*7c478bd9Sstevel@tonic-gate while (1) { 926*7c478bd9Sstevel@tonic-gate int i; 927*7c478bd9Sstevel@tonic-gate 928*7c478bd9Sstevel@tonic-gate /* read a chunk into our buffer */ 929*7c478bd9Sstevel@tonic-gate prbstat = prb_proc_read(proc_p, addr + offset, buffer, bufsz); 930*7c478bd9Sstevel@tonic-gate if (prbstat) { 931*7c478bd9Sstevel@tonic-gate 932*7c478bd9Sstevel@tonic-gate /* 933*7c478bd9Sstevel@tonic-gate * if we get into trouble with a large read, try again 934*7c478bd9Sstevel@tonic-gate * with a single byte. Subsequent failure is real ... 935*7c478bd9Sstevel@tonic-gate */ 936*7c478bd9Sstevel@tonic-gate if (bufsz > 1) { 937*7c478bd9Sstevel@tonic-gate bufsz = 1; 938*7c478bd9Sstevel@tonic-gate continue; 939*7c478bd9Sstevel@tonic-gate } 940*7c478bd9Sstevel@tonic-gate 941*7c478bd9Sstevel@tonic-gate DBG((void) fprintf(stderr, 942*7c478bd9Sstevel@tonic-gate "prb_proc_readstr: prb_proc_read failed: %s\n", 943*7c478bd9Sstevel@tonic-gate prb_status_str(prbstat))); 944*7c478bd9Sstevel@tonic-gate free(ptr); 945*7c478bd9Sstevel@tonic-gate return (prbstat); 946*7c478bd9Sstevel@tonic-gate } 947*7c478bd9Sstevel@tonic-gate /* copy the chracters into the return buffer */ 948*7c478bd9Sstevel@tonic-gate for (i = 0; i < bufsz; i++) { 949*7c478bd9Sstevel@tonic-gate char c = buffer[i]; 950*7c478bd9Sstevel@tonic-gate 951*7c478bd9Sstevel@tonic-gate ptr[offset + i] = c; 952*7c478bd9Sstevel@tonic-gate if (c == '\0') { 953*7c478bd9Sstevel@tonic-gate /* hooray! we saw the end of the string */ 954*7c478bd9Sstevel@tonic-gate *outstr_pp = ptr; 955*7c478bd9Sstevel@tonic-gate return (PRB_STATUS_OK); 956*7c478bd9Sstevel@tonic-gate } 957*7c478bd9Sstevel@tonic-gate } 958*7c478bd9Sstevel@tonic-gate 959*7c478bd9Sstevel@tonic-gate /* bummer, need to grab another bufsz characters */ 960*7c478bd9Sstevel@tonic-gate offset += bufsz; 961*7c478bd9Sstevel@tonic-gate orig_ptr = ptr; 962*7c478bd9Sstevel@tonic-gate ptr = (char *)realloc(ptr, offset + bufsz); 963*7c478bd9Sstevel@tonic-gate if (!ptr) { 964*7c478bd9Sstevel@tonic-gate free(orig_ptr); 965*7c478bd9Sstevel@tonic-gate DBG((void) fprintf(stderr, 966*7c478bd9Sstevel@tonic-gate "prb_proc_readstr: realloc failed\n")); 967*7c478bd9Sstevel@tonic-gate return (PRB_STATUS_ALLOCFAIL); 968*7c478bd9Sstevel@tonic-gate } 969*7c478bd9Sstevel@tonic-gate } 970*7c478bd9Sstevel@tonic-gate 971*7c478bd9Sstevel@tonic-gate #if defined(lint) 972*7c478bd9Sstevel@tonic-gate return (PRB_STATUS_OK); 973*7c478bd9Sstevel@tonic-gate #endif 974*7c478bd9Sstevel@tonic-gate } 975*7c478bd9Sstevel@tonic-gate 976*7c478bd9Sstevel@tonic-gate prb_status_t 977*7c478bd9Sstevel@tonic-gate prb_proc_get_r0_r1(prb_proc_ctl_t *proc_p, prgreg_t *r0, prgreg_t *r1) 978*7c478bd9Sstevel@tonic-gate { 979*7c478bd9Sstevel@tonic-gate int retval; 980*7c478bd9Sstevel@tonic-gate int procfd; 981*7c478bd9Sstevel@tonic-gate prstatus_t prstatus; 982*7c478bd9Sstevel@tonic-gate 983*7c478bd9Sstevel@tonic-gate procfd = proc_p->procfd; 984*7c478bd9Sstevel@tonic-gate again: 985*7c478bd9Sstevel@tonic-gate retval = ioctl(procfd, PIOCSTATUS, &prstatus); 986*7c478bd9Sstevel@tonic-gate if (retval == -1) { 987*7c478bd9Sstevel@tonic-gate if (errno == EINTR) 988*7c478bd9Sstevel@tonic-gate goto again; 989*7c478bd9Sstevel@tonic-gate return (prb_status_map(errno)); 990*7c478bd9Sstevel@tonic-gate } 991*7c478bd9Sstevel@tonic-gate 992*7c478bd9Sstevel@tonic-gate /* 993*7c478bd9Sstevel@tonic-gate * Use R_Rn register definitions for some uniformity 994*7c478bd9Sstevel@tonic-gate * sparc: define R_R0 R_O0 995*7c478bd9Sstevel@tonic-gate * define R_R1 R_O1 996*7c478bd9Sstevel@tonic-gate * x86: define R_R0 EAX 997*7c478bd9Sstevel@tonic-gate * define R_R1 EDX 998*7c478bd9Sstevel@tonic-gate */ 999*7c478bd9Sstevel@tonic-gate *r0 = prstatus.pr_reg[R_R0]; 1000*7c478bd9Sstevel@tonic-gate *r1 = prstatus.pr_reg[R_R1]; 1001*7c478bd9Sstevel@tonic-gate DBG((void) fprintf 1002*7c478bd9Sstevel@tonic-gate (stderr, "prb_proc_get_r0_r1: R_R0 = %d, R_R1 = %d\n", *r0, *r1)); 1003*7c478bd9Sstevel@tonic-gate return (PRB_STATUS_OK); 1004*7c478bd9Sstevel@tonic-gate } 1005