xref: /titanic_50/usr/src/lib/libtnfctl/prb_proc.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
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