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
prb_proc_open_general(pid_t pid,prb_proc_ctl_t ** proc_pp,int oflg)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
prb_proc_open(pid_t pid,prb_proc_ctl_t ** proc_pp)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
prb_proc_reopen(pid_t pid,prb_proc_ctl_t ** proc_pp)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
prb_proc_close(prb_proc_ctl_t * proc_p)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
prb_proc_pid_get(prb_proc_ctl_t * proc_p)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
prb_proc_stop(prb_proc_ctl_t * proc_p)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
prb_proc_prstop(prb_proc_ctl_t * proc_p)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
prb_proc_state(prb_proc_ctl_t * proc_p,prb_proc_state_t * state_p)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
prb_proc_wait(prb_proc_ctl_t * proc_p,boolean_t use_sigmask,sigset_t * oldmask)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
prb_proc_cont(prb_proc_ctl_t * proc_p)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
prb_proc_istepbpt(prb_proc_ctl_t * proc_p)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
prb_proc_clrbptflt(prb_proc_ctl_t * proc_p)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
prb_proc_tracebpt(prb_proc_ctl_t * proc_p,boolean_t bpt)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
prb_proc_setrlc(prb_proc_ctl_t * proc_p,boolean_t rlc)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
prb_proc_setklc(prb_proc_ctl_t * proc_p,boolean_t klc)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
prb_proc_setfork(prb_proc_ctl_t * proc_p,boolean_t inhfork)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
prb_proc_exit(prb_proc_ctl_t * proc_p,uint_t syscall,prb_syscall_op_t op)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
prb_proc_entry(prb_proc_ctl_t * proc_p,uint_t syscall,prb_syscall_op_t op)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
prb_proc_read(prb_proc_ctl_t * proc_p,uintptr_t addr,void * buf,size_t size)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
prb_proc_write(prb_proc_ctl_t * proc_p,uintptr_t addr,void * buf,size_t size)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
prb_proc_readstr(prb_proc_ctl_t * proc_p,uintptr_t addr,const char ** outstr_pp)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
prb_proc_get_r0_r1(prb_proc_ctl_t * proc_p,prgreg_t * r0,prgreg_t * r1)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