xref: /illumos-gate/usr/src/cmd/truss/actions.c (revision 7c478bd9)
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 2005 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1988 AT&T	*/
28*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
29*7c478bd9Sstevel@tonic-gate 
30*7c478bd9Sstevel@tonic-gate 
31*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
32*7c478bd9Sstevel@tonic-gate 
33*7c478bd9Sstevel@tonic-gate #include <stdio.h>
34*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
35*7c478bd9Sstevel@tonic-gate #include <unistd.h>
36*7c478bd9Sstevel@tonic-gate #include <ctype.h>
37*7c478bd9Sstevel@tonic-gate #include <string.h>
38*7c478bd9Sstevel@tonic-gate #include <memory.h>
39*7c478bd9Sstevel@tonic-gate #include <errno.h>
40*7c478bd9Sstevel@tonic-gate #include <limits.h>
41*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
42*7c478bd9Sstevel@tonic-gate #include <sys/stack.h>
43*7c478bd9Sstevel@tonic-gate #include <signal.h>
44*7c478bd9Sstevel@tonic-gate #include <sys/isa_defs.h>
45*7c478bd9Sstevel@tonic-gate #include <libproc.h>
46*7c478bd9Sstevel@tonic-gate #include <priv.h>
47*7c478bd9Sstevel@tonic-gate #include "ramdata.h"
48*7c478bd9Sstevel@tonic-gate #include "systable.h"
49*7c478bd9Sstevel@tonic-gate #include "print.h"
50*7c478bd9Sstevel@tonic-gate #include "proto.h"
51*7c478bd9Sstevel@tonic-gate 
52*7c478bd9Sstevel@tonic-gate /*
53*7c478bd9Sstevel@tonic-gate  * Actions to take when process stops.
54*7c478bd9Sstevel@tonic-gate  */
55*7c478bd9Sstevel@tonic-gate 
56*7c478bd9Sstevel@tonic-gate /*
57*7c478bd9Sstevel@tonic-gate  * Function prototypes for static routines in this module.
58*7c478bd9Sstevel@tonic-gate  */
59*7c478bd9Sstevel@tonic-gate int	stopsig(private_t *);
60*7c478bd9Sstevel@tonic-gate void	showpaths(private_t *, const struct systable *);
61*7c478bd9Sstevel@tonic-gate void	showargs(private_t *, int);
62*7c478bd9Sstevel@tonic-gate void	dumpargs(private_t *, long, const char *);
63*7c478bd9Sstevel@tonic-gate 
64*7c478bd9Sstevel@tonic-gate /*
65*7c478bd9Sstevel@tonic-gate  * Report an lwp to be sleeping (if true).
66*7c478bd9Sstevel@tonic-gate  */
67*7c478bd9Sstevel@tonic-gate void
68*7c478bd9Sstevel@tonic-gate report_sleeping(private_t *pri, int dotrace)
69*7c478bd9Sstevel@tonic-gate {
70*7c478bd9Sstevel@tonic-gate 	const lwpstatus_t *Lsp = pri->lwpstat;
71*7c478bd9Sstevel@tonic-gate 	int sys = Lsp->pr_syscall;
72*7c478bd9Sstevel@tonic-gate 
73*7c478bd9Sstevel@tonic-gate 	if (!prismember(&trace, sys) || !dotrace ||
74*7c478bd9Sstevel@tonic-gate 	    !(Lsp->pr_flags & (PR_ASLEEP|PR_VFORKP))) {
75*7c478bd9Sstevel@tonic-gate 		/* Make sure we catch sysexit even if we're not tracing it. */
76*7c478bd9Sstevel@tonic-gate 		(void) Psysexit(Proc, sys, TRUE);
77*7c478bd9Sstevel@tonic-gate 		return;
78*7c478bd9Sstevel@tonic-gate 	}
79*7c478bd9Sstevel@tonic-gate 
80*7c478bd9Sstevel@tonic-gate 	pri->length = 0;
81*7c478bd9Sstevel@tonic-gate 	pri->Errno = 0;
82*7c478bd9Sstevel@tonic-gate 	pri->ErrPriv = PRIV_NONE;
83*7c478bd9Sstevel@tonic-gate 	pri->Rval1 = pri->Rval2 = 0;
84*7c478bd9Sstevel@tonic-gate 	(void) sysentry(pri, dotrace);
85*7c478bd9Sstevel@tonic-gate 	make_pname(pri, 0);
86*7c478bd9Sstevel@tonic-gate 	putpname(pri);
87*7c478bd9Sstevel@tonic-gate 	timestamp(pri);
88*7c478bd9Sstevel@tonic-gate 	pri->length += printf("%s", pri->sys_string);
89*7c478bd9Sstevel@tonic-gate 	pri->sys_leng = 0;
90*7c478bd9Sstevel@tonic-gate 	*pri->sys_string = '\0';
91*7c478bd9Sstevel@tonic-gate 	pri->length >>= 3;
92*7c478bd9Sstevel@tonic-gate 	if (Lsp->pr_flags & PR_VFORKP)
93*7c478bd9Sstevel@tonic-gate 		pri->length += 2;
94*7c478bd9Sstevel@tonic-gate 	if (pri->length >= 4)
95*7c478bd9Sstevel@tonic-gate 		(void) fputc(' ', stdout);
96*7c478bd9Sstevel@tonic-gate 	for (; pri->length < 4; pri->length++)
97*7c478bd9Sstevel@tonic-gate 		(void) fputc('\t', stdout);
98*7c478bd9Sstevel@tonic-gate 	if (Lsp->pr_flags & PR_VFORKP)
99*7c478bd9Sstevel@tonic-gate 		(void) fputs("(waiting for child to exit()/exec()...)\n",
100*7c478bd9Sstevel@tonic-gate 			stdout);
101*7c478bd9Sstevel@tonic-gate 	else
102*7c478bd9Sstevel@tonic-gate 		(void) fputs("(sleeping...)\n", stdout);
103*7c478bd9Sstevel@tonic-gate 	pri->length = 0;
104*7c478bd9Sstevel@tonic-gate 	if (prismember(&verbose, sys)) {
105*7c478bd9Sstevel@tonic-gate 		int raw = prismember(&rawout, sys);
106*7c478bd9Sstevel@tonic-gate 		pri->Errno = 1;
107*7c478bd9Sstevel@tonic-gate 		expound(pri, 0, raw);
108*7c478bd9Sstevel@tonic-gate 		pri->Errno = 0;
109*7c478bd9Sstevel@tonic-gate 	}
110*7c478bd9Sstevel@tonic-gate 	Flush();
111*7c478bd9Sstevel@tonic-gate }
112*7c478bd9Sstevel@tonic-gate 
113*7c478bd9Sstevel@tonic-gate /*
114*7c478bd9Sstevel@tonic-gate  * requested() gets called for these reasons:
115*7c478bd9Sstevel@tonic-gate  *	flag == JOBSIG:		report nothing; change state to JOBSTOP
116*7c478bd9Sstevel@tonic-gate  *	flag == JOBSTOP:	report "Continued ..."
117*7c478bd9Sstevel@tonic-gate  *	default:		report sleeping system call
118*7c478bd9Sstevel@tonic-gate  *
119*7c478bd9Sstevel@tonic-gate  * It returns a new flag:  JOBSTOP or SLEEPING or 0.
120*7c478bd9Sstevel@tonic-gate  */
121*7c478bd9Sstevel@tonic-gate int
122*7c478bd9Sstevel@tonic-gate requested(private_t *pri, int flag, int dotrace)
123*7c478bd9Sstevel@tonic-gate {
124*7c478bd9Sstevel@tonic-gate 	const lwpstatus_t *Lsp = pri->lwpstat;
125*7c478bd9Sstevel@tonic-gate 	int sig = Lsp->pr_cursig;
126*7c478bd9Sstevel@tonic-gate 	int newflag = 0;
127*7c478bd9Sstevel@tonic-gate 
128*7c478bd9Sstevel@tonic-gate 	switch (flag) {
129*7c478bd9Sstevel@tonic-gate 	case JOBSIG:
130*7c478bd9Sstevel@tonic-gate 		return (JOBSTOP);
131*7c478bd9Sstevel@tonic-gate 
132*7c478bd9Sstevel@tonic-gate 	case JOBSTOP:
133*7c478bd9Sstevel@tonic-gate 		if (dotrace && !cflag && prismember(&signals, sig)) {
134*7c478bd9Sstevel@tonic-gate 			pri->length = 0;
135*7c478bd9Sstevel@tonic-gate 			putpname(pri);
136*7c478bd9Sstevel@tonic-gate 			timestamp(pri);
137*7c478bd9Sstevel@tonic-gate 			(void) printf("    Continued with signal #%d, %s",
138*7c478bd9Sstevel@tonic-gate 				sig, signame(pri, sig));
139*7c478bd9Sstevel@tonic-gate 			if (Lsp->pr_action.sa_handler == SIG_DFL)
140*7c478bd9Sstevel@tonic-gate 				(void) printf(" [default]");
141*7c478bd9Sstevel@tonic-gate 			else if (Lsp->pr_action.sa_handler == SIG_IGN)
142*7c478bd9Sstevel@tonic-gate 				(void) printf(" [ignored]");
143*7c478bd9Sstevel@tonic-gate 			else
144*7c478bd9Sstevel@tonic-gate 				(void) printf(" [caught]");
145*7c478bd9Sstevel@tonic-gate 			(void) fputc('\n', stdout);
146*7c478bd9Sstevel@tonic-gate 			Flush();
147*7c478bd9Sstevel@tonic-gate 		}
148*7c478bd9Sstevel@tonic-gate 		newflag = 0;
149*7c478bd9Sstevel@tonic-gate 		break;
150*7c478bd9Sstevel@tonic-gate 
151*7c478bd9Sstevel@tonic-gate 	default:
152*7c478bd9Sstevel@tonic-gate 		newflag = SLEEPING;
153*7c478bd9Sstevel@tonic-gate 		if (!cflag)
154*7c478bd9Sstevel@tonic-gate 			report_sleeping(pri, dotrace);
155*7c478bd9Sstevel@tonic-gate 		break;
156*7c478bd9Sstevel@tonic-gate 	}
157*7c478bd9Sstevel@tonic-gate 
158*7c478bd9Sstevel@tonic-gate 	return (newflag);
159*7c478bd9Sstevel@tonic-gate }
160*7c478bd9Sstevel@tonic-gate 
161*7c478bd9Sstevel@tonic-gate int
162*7c478bd9Sstevel@tonic-gate jobcontrol(private_t *pri, int dotrace)
163*7c478bd9Sstevel@tonic-gate {
164*7c478bd9Sstevel@tonic-gate 	const lwpstatus_t *Lsp = pri->lwpstat;
165*7c478bd9Sstevel@tonic-gate 	int sig = stopsig(pri);
166*7c478bd9Sstevel@tonic-gate 
167*7c478bd9Sstevel@tonic-gate 	if (sig == 0)
168*7c478bd9Sstevel@tonic-gate 		return (0);
169*7c478bd9Sstevel@tonic-gate 
170*7c478bd9Sstevel@tonic-gate 	if (dotrace && !cflag &&		/* not just counting */
171*7c478bd9Sstevel@tonic-gate 	    prismember(&signals, sig)) {	/* tracing this signal */
172*7c478bd9Sstevel@tonic-gate 		int sys;
173*7c478bd9Sstevel@tonic-gate 
174*7c478bd9Sstevel@tonic-gate 		pri->length = 0;
175*7c478bd9Sstevel@tonic-gate 		putpname(pri);
176*7c478bd9Sstevel@tonic-gate 		timestamp(pri);
177*7c478bd9Sstevel@tonic-gate 		(void) printf("    Stopped by signal #%d, %s",
178*7c478bd9Sstevel@tonic-gate 			sig, signame(pri, sig));
179*7c478bd9Sstevel@tonic-gate 		if ((Lsp->pr_flags & PR_ASLEEP) &&
180*7c478bd9Sstevel@tonic-gate 		    (sys = Lsp->pr_syscall) > 0 && sys <= PRMAXSYS)
181*7c478bd9Sstevel@tonic-gate 			(void) printf(", in %s()",
182*7c478bd9Sstevel@tonic-gate 				sysname(pri, sys, getsubcode(pri)));
183*7c478bd9Sstevel@tonic-gate 		(void) fputc('\n', stdout);
184*7c478bd9Sstevel@tonic-gate 		Flush();
185*7c478bd9Sstevel@tonic-gate 	}
186*7c478bd9Sstevel@tonic-gate 
187*7c478bd9Sstevel@tonic-gate 	return (JOBSTOP);
188*7c478bd9Sstevel@tonic-gate }
189*7c478bd9Sstevel@tonic-gate 
190*7c478bd9Sstevel@tonic-gate /*
191*7c478bd9Sstevel@tonic-gate  * Return the signal the process stopped on iff process is already stopped on
192*7c478bd9Sstevel@tonic-gate  * PR_JOBCONTROL or is stopped on PR_SIGNALLED or PR_REQUESTED with a current
193*7c478bd9Sstevel@tonic-gate  * signal that will cause a JOBCONTROL stop when the process is set running.
194*7c478bd9Sstevel@tonic-gate  */
195*7c478bd9Sstevel@tonic-gate int
196*7c478bd9Sstevel@tonic-gate stopsig(private_t *pri)
197*7c478bd9Sstevel@tonic-gate {
198*7c478bd9Sstevel@tonic-gate 	const lwpstatus_t *Lsp = pri->lwpstat;
199*7c478bd9Sstevel@tonic-gate 	int sig = 0;
200*7c478bd9Sstevel@tonic-gate 
201*7c478bd9Sstevel@tonic-gate 	if (Lsp->pr_flags & PR_STOPPED) {
202*7c478bd9Sstevel@tonic-gate 		switch (Lsp->pr_why) {
203*7c478bd9Sstevel@tonic-gate 		case PR_JOBCONTROL:
204*7c478bd9Sstevel@tonic-gate 			sig = Lsp->pr_what;
205*7c478bd9Sstevel@tonic-gate 			if (sig < 0 || sig > PRMAXSIG)
206*7c478bd9Sstevel@tonic-gate 				sig = 0;
207*7c478bd9Sstevel@tonic-gate 			break;
208*7c478bd9Sstevel@tonic-gate 		case PR_SIGNALLED:
209*7c478bd9Sstevel@tonic-gate 		case PR_REQUESTED:
210*7c478bd9Sstevel@tonic-gate 			if (Lsp->pr_action.sa_handler == SIG_DFL) {
211*7c478bd9Sstevel@tonic-gate 				switch (Lsp->pr_cursig) {
212*7c478bd9Sstevel@tonic-gate 				case SIGSTOP:
213*7c478bd9Sstevel@tonic-gate 					sig = SIGSTOP;
214*7c478bd9Sstevel@tonic-gate 					break;
215*7c478bd9Sstevel@tonic-gate 				case SIGTSTP:
216*7c478bd9Sstevel@tonic-gate 				case SIGTTIN:
217*7c478bd9Sstevel@tonic-gate 				case SIGTTOU:
218*7c478bd9Sstevel@tonic-gate 					if (!(Lsp->pr_flags & PR_ORPHAN))
219*7c478bd9Sstevel@tonic-gate 						sig = Lsp->pr_cursig;
220*7c478bd9Sstevel@tonic-gate 					break;
221*7c478bd9Sstevel@tonic-gate 				}
222*7c478bd9Sstevel@tonic-gate 			}
223*7c478bd9Sstevel@tonic-gate 			break;
224*7c478bd9Sstevel@tonic-gate 		}
225*7c478bd9Sstevel@tonic-gate 	}
226*7c478bd9Sstevel@tonic-gate 
227*7c478bd9Sstevel@tonic-gate 	return (sig);
228*7c478bd9Sstevel@tonic-gate }
229*7c478bd9Sstevel@tonic-gate 
230*7c478bd9Sstevel@tonic-gate int
231*7c478bd9Sstevel@tonic-gate signalled(private_t *pri, int flag, int dotrace)
232*7c478bd9Sstevel@tonic-gate {
233*7c478bd9Sstevel@tonic-gate 	const lwpstatus_t *Lsp = pri->lwpstat;
234*7c478bd9Sstevel@tonic-gate 	int sig = Lsp->pr_what;
235*7c478bd9Sstevel@tonic-gate 
236*7c478bd9Sstevel@tonic-gate 	if (sig <= 0 || sig > PRMAXSIG)	/* check bounds */
237*7c478bd9Sstevel@tonic-gate 		return (0);
238*7c478bd9Sstevel@tonic-gate 
239*7c478bd9Sstevel@tonic-gate 	if (dotrace && cflag) {			/* just counting */
240*7c478bd9Sstevel@tonic-gate 		(void) mutex_lock(&count_lock);
241*7c478bd9Sstevel@tonic-gate 		Cp->sigcount[sig]++;
242*7c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&count_lock);
243*7c478bd9Sstevel@tonic-gate 	}
244*7c478bd9Sstevel@tonic-gate 
245*7c478bd9Sstevel@tonic-gate 	if (sig == SIGCONT && (flag == JOBSIG || flag == JOBSTOP))
246*7c478bd9Sstevel@tonic-gate 		flag = requested(pri, JOBSTOP, dotrace);
247*7c478bd9Sstevel@tonic-gate 	else if ((flag = jobcontrol(pri, dotrace)) == 0 &&
248*7c478bd9Sstevel@tonic-gate 	    !cflag && dotrace &&
249*7c478bd9Sstevel@tonic-gate 	    prismember(&signals, sig)) {
250*7c478bd9Sstevel@tonic-gate 		int sys;
251*7c478bd9Sstevel@tonic-gate 
252*7c478bd9Sstevel@tonic-gate 		pri->length = 0;
253*7c478bd9Sstevel@tonic-gate 		putpname(pri);
254*7c478bd9Sstevel@tonic-gate 		timestamp(pri);
255*7c478bd9Sstevel@tonic-gate 		(void) printf("    Received signal #%d, %s",
256*7c478bd9Sstevel@tonic-gate 			sig, signame(pri, sig));
257*7c478bd9Sstevel@tonic-gate 		if ((Lsp->pr_flags & PR_ASLEEP) &&
258*7c478bd9Sstevel@tonic-gate 		    (sys = Lsp->pr_syscall) > 0 && sys <= PRMAXSYS)
259*7c478bd9Sstevel@tonic-gate 			(void) printf(", in %s()",
260*7c478bd9Sstevel@tonic-gate 				sysname(pri, sys, getsubcode(pri)));
261*7c478bd9Sstevel@tonic-gate 		if (Lsp->pr_action.sa_handler == SIG_DFL)
262*7c478bd9Sstevel@tonic-gate 			(void) printf(" [default]");
263*7c478bd9Sstevel@tonic-gate 		else if (Lsp->pr_action.sa_handler == SIG_IGN)
264*7c478bd9Sstevel@tonic-gate 			(void) printf(" [ignored]");
265*7c478bd9Sstevel@tonic-gate 		else
266*7c478bd9Sstevel@tonic-gate 			(void) printf(" [caught]");
267*7c478bd9Sstevel@tonic-gate 		(void) fputc('\n', stdout);
268*7c478bd9Sstevel@tonic-gate 		if (Lsp->pr_info.si_code != 0 ||
269*7c478bd9Sstevel@tonic-gate 		    Lsp->pr_info.si_pid != 0)
270*7c478bd9Sstevel@tonic-gate 			print_siginfo(pri, &Lsp->pr_info);
271*7c478bd9Sstevel@tonic-gate 		Flush();
272*7c478bd9Sstevel@tonic-gate 	}
273*7c478bd9Sstevel@tonic-gate 
274*7c478bd9Sstevel@tonic-gate 	if (flag == JOBSTOP)
275*7c478bd9Sstevel@tonic-gate 		flag = JOBSIG;
276*7c478bd9Sstevel@tonic-gate 	return (flag);
277*7c478bd9Sstevel@tonic-gate }
278*7c478bd9Sstevel@tonic-gate 
279*7c478bd9Sstevel@tonic-gate int
280*7c478bd9Sstevel@tonic-gate faulted(private_t *pri, int dotrace)
281*7c478bd9Sstevel@tonic-gate {
282*7c478bd9Sstevel@tonic-gate 	const lwpstatus_t *Lsp = pri->lwpstat;
283*7c478bd9Sstevel@tonic-gate 	int flt = Lsp->pr_what;
284*7c478bd9Sstevel@tonic-gate 
285*7c478bd9Sstevel@tonic-gate 	if ((uint_t)flt > PRMAXFAULT || !prismember(&faults, flt) || !dotrace)
286*7c478bd9Sstevel@tonic-gate 		return (0);
287*7c478bd9Sstevel@tonic-gate 
288*7c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&count_lock);
289*7c478bd9Sstevel@tonic-gate 	Cp->fltcount[flt]++;
290*7c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&count_lock);
291*7c478bd9Sstevel@tonic-gate 
292*7c478bd9Sstevel@tonic-gate 	if (cflag)		/* just counting */
293*7c478bd9Sstevel@tonic-gate 		return (1);
294*7c478bd9Sstevel@tonic-gate 
295*7c478bd9Sstevel@tonic-gate 	pri->length = 0;
296*7c478bd9Sstevel@tonic-gate 	putpname(pri);
297*7c478bd9Sstevel@tonic-gate 	timestamp(pri);
298*7c478bd9Sstevel@tonic-gate 
299*7c478bd9Sstevel@tonic-gate 	(void) printf("    Incurred fault #%d, %s  %%pc = 0x%.8lX",
300*7c478bd9Sstevel@tonic-gate 		flt, proc_fltname(flt, pri->flt_name, sizeof (pri->flt_name)),
301*7c478bd9Sstevel@tonic-gate 		(long)Lsp->pr_reg[R_PC]);
302*7c478bd9Sstevel@tonic-gate 
303*7c478bd9Sstevel@tonic-gate 	if (flt == FLTPAGE)
304*7c478bd9Sstevel@tonic-gate 		(void) printf("  addr = 0x%.8lX",
305*7c478bd9Sstevel@tonic-gate 			(long)Lsp->pr_info.si_addr);
306*7c478bd9Sstevel@tonic-gate 	(void) fputc('\n', stdout);
307*7c478bd9Sstevel@tonic-gate 	if (Lsp->pr_info.si_signo != 0)
308*7c478bd9Sstevel@tonic-gate 		print_siginfo(pri, &Lsp->pr_info);
309*7c478bd9Sstevel@tonic-gate 	Flush();
310*7c478bd9Sstevel@tonic-gate 	return (1);
311*7c478bd9Sstevel@tonic-gate }
312*7c478bd9Sstevel@tonic-gate 
313*7c478bd9Sstevel@tonic-gate /*
314*7c478bd9Sstevel@tonic-gate  * Set up pri->sys_nargs and pri->sys_args[] (syscall args).
315*7c478bd9Sstevel@tonic-gate  */
316*7c478bd9Sstevel@tonic-gate void
317*7c478bd9Sstevel@tonic-gate setupsysargs(private_t *pri, int what)
318*7c478bd9Sstevel@tonic-gate {
319*7c478bd9Sstevel@tonic-gate 	const lwpstatus_t *Lsp = pri->lwpstat;
320*7c478bd9Sstevel@tonic-gate 	int nargs;
321*7c478bd9Sstevel@tonic-gate 	int i;
322*7c478bd9Sstevel@tonic-gate 
323*7c478bd9Sstevel@tonic-gate #if sparc
324*7c478bd9Sstevel@tonic-gate 	/* determine whether syscall is indirect */
325*7c478bd9Sstevel@tonic-gate 	pri->sys_indirect = (Lsp->pr_reg[R_G1] == SYS_syscall)? 1 : 0;
326*7c478bd9Sstevel@tonic-gate #else
327*7c478bd9Sstevel@tonic-gate 	pri->sys_indirect = 0;
328*7c478bd9Sstevel@tonic-gate #endif
329*7c478bd9Sstevel@tonic-gate 
330*7c478bd9Sstevel@tonic-gate 	(void) memset(pri->sys_args, 0, sizeof (pri->sys_args));
331*7c478bd9Sstevel@tonic-gate 	if (what != Lsp->pr_syscall) {	/* assertion */
332*7c478bd9Sstevel@tonic-gate 		(void) printf("%s\t*** Inconsistent syscall: %d vs %d ***\n",
333*7c478bd9Sstevel@tonic-gate 			pri->pname, what, Lsp->pr_syscall);
334*7c478bd9Sstevel@tonic-gate 	}
335*7c478bd9Sstevel@tonic-gate 	nargs = Lsp->pr_nsysarg;
336*7c478bd9Sstevel@tonic-gate 	for (i = 0;
337*7c478bd9Sstevel@tonic-gate 	    i < nargs && i < sizeof (pri->sys_args) / sizeof (pri->sys_args[0]);
338*7c478bd9Sstevel@tonic-gate 	    i++)
339*7c478bd9Sstevel@tonic-gate 		pri->sys_args[i] = Lsp->pr_sysarg[i];
340*7c478bd9Sstevel@tonic-gate 	pri->sys_nargs = nargs;
341*7c478bd9Sstevel@tonic-gate }
342*7c478bd9Sstevel@tonic-gate 
343*7c478bd9Sstevel@tonic-gate #define	ISREAD(code) \
344*7c478bd9Sstevel@tonic-gate 	((code) == SYS_read || (code) == SYS_pread || \
345*7c478bd9Sstevel@tonic-gate 	(code) == SYS_pread64 || (code) == SYS_readv || \
346*7c478bd9Sstevel@tonic-gate 	(code) == SYS_recv || (code) == SYS_recvfrom)
347*7c478bd9Sstevel@tonic-gate #define	ISWRITE(code) \
348*7c478bd9Sstevel@tonic-gate 	((code) == SYS_write || (code) == SYS_pwrite || \
349*7c478bd9Sstevel@tonic-gate 	(code) == SYS_pwrite64 || (code) == SYS_writev || \
350*7c478bd9Sstevel@tonic-gate 	(code) == SYS_send || (code) == SYS_sendto)
351*7c478bd9Sstevel@tonic-gate 
352*7c478bd9Sstevel@tonic-gate /*
353*7c478bd9Sstevel@tonic-gate  * Return TRUE iff syscall is being traced.
354*7c478bd9Sstevel@tonic-gate  */
355*7c478bd9Sstevel@tonic-gate int
356*7c478bd9Sstevel@tonic-gate sysentry(private_t *pri, int dotrace)
357*7c478bd9Sstevel@tonic-gate {
358*7c478bd9Sstevel@tonic-gate 	pid_t pid = Pstatus(Proc)->pr_pid;
359*7c478bd9Sstevel@tonic-gate 	const lwpstatus_t *Lsp = pri->lwpstat;
360*7c478bd9Sstevel@tonic-gate 	long arg;
361*7c478bd9Sstevel@tonic-gate 	int nargs;
362*7c478bd9Sstevel@tonic-gate 	int i;
363*7c478bd9Sstevel@tonic-gate 	int x;
364*7c478bd9Sstevel@tonic-gate 	int len;
365*7c478bd9Sstevel@tonic-gate 	char *s;
366*7c478bd9Sstevel@tonic-gate 	const struct systable *stp;
367*7c478bd9Sstevel@tonic-gate 	int what = Lsp->pr_what;
368*7c478bd9Sstevel@tonic-gate 	int subcode;
369*7c478bd9Sstevel@tonic-gate 	int istraced;
370*7c478bd9Sstevel@tonic-gate 	int raw;
371*7c478bd9Sstevel@tonic-gate 
372*7c478bd9Sstevel@tonic-gate 	/* for reporting sleeping system calls */
373*7c478bd9Sstevel@tonic-gate 	if (what == 0 && (Lsp->pr_flags & (PR_ASLEEP|PR_VFORKP)))
374*7c478bd9Sstevel@tonic-gate 		what = Lsp->pr_syscall;
375*7c478bd9Sstevel@tonic-gate 
376*7c478bd9Sstevel@tonic-gate 	/* protect ourself from operating system error */
377*7c478bd9Sstevel@tonic-gate 	if (what <= 0 || what > PRMAXSYS)
378*7c478bd9Sstevel@tonic-gate 		what = 0;
379*7c478bd9Sstevel@tonic-gate 
380*7c478bd9Sstevel@tonic-gate 	/*
381*7c478bd9Sstevel@tonic-gate 	 * Set up the system call arguments (pri->sys_nargs & pri->sys_args[]).
382*7c478bd9Sstevel@tonic-gate 	 */
383*7c478bd9Sstevel@tonic-gate 	setupsysargs(pri, what);
384*7c478bd9Sstevel@tonic-gate 	nargs = pri->sys_nargs;
385*7c478bd9Sstevel@tonic-gate 
386*7c478bd9Sstevel@tonic-gate 	/* get systable entry for this syscall */
387*7c478bd9Sstevel@tonic-gate 	subcode = getsubcode(pri);
388*7c478bd9Sstevel@tonic-gate 	stp = subsys(what, subcode);
389*7c478bd9Sstevel@tonic-gate 
390*7c478bd9Sstevel@tonic-gate 	if (nargs > stp->nargs)
391*7c478bd9Sstevel@tonic-gate 		nargs = stp->nargs;
392*7c478bd9Sstevel@tonic-gate 	pri->sys_nargs = nargs;
393*7c478bd9Sstevel@tonic-gate 
394*7c478bd9Sstevel@tonic-gate 	/* fetch and remember first argument if it's a string */
395*7c478bd9Sstevel@tonic-gate 	pri->sys_valid = FALSE;
396*7c478bd9Sstevel@tonic-gate 	if (nargs > 0 && stp->arg[0] == STG) {
397*7c478bd9Sstevel@tonic-gate 		long offset;
398*7c478bd9Sstevel@tonic-gate 		uint32_t offset32;
399*7c478bd9Sstevel@tonic-gate 
400*7c478bd9Sstevel@tonic-gate 		/*
401*7c478bd9Sstevel@tonic-gate 		 * Special case for exit from exec().
402*7c478bd9Sstevel@tonic-gate 		 * The address in pri->sys_args[0] refers to the old process
403*7c478bd9Sstevel@tonic-gate 		 * image.  We must fetch the string from the new image.
404*7c478bd9Sstevel@tonic-gate 		 */
405*7c478bd9Sstevel@tonic-gate 		if (Lsp->pr_why == PR_SYSEXIT &&
406*7c478bd9Sstevel@tonic-gate 		    (Lsp->pr_what == SYS_execve ||
407*7c478bd9Sstevel@tonic-gate 		    Lsp->pr_what == SYS_exec)) {
408*7c478bd9Sstevel@tonic-gate 			psinfo_t psinfo;
409*7c478bd9Sstevel@tonic-gate 			long argv;
410*7c478bd9Sstevel@tonic-gate 			auxv_t auxv[32];
411*7c478bd9Sstevel@tonic-gate 			int naux;
412*7c478bd9Sstevel@tonic-gate 
413*7c478bd9Sstevel@tonic-gate 			offset = 0;
414*7c478bd9Sstevel@tonic-gate 			naux = proc_get_auxv(pid, auxv, 32);
415*7c478bd9Sstevel@tonic-gate 			for (i = 0; i < naux; i++) {
416*7c478bd9Sstevel@tonic-gate 				if (auxv[i].a_type == AT_SUN_EXECNAME) {
417*7c478bd9Sstevel@tonic-gate 					offset = (long)auxv[i].a_un.a_ptr;
418*7c478bd9Sstevel@tonic-gate 					break;
419*7c478bd9Sstevel@tonic-gate 				}
420*7c478bd9Sstevel@tonic-gate 			}
421*7c478bd9Sstevel@tonic-gate 			if (offset == 0 &&
422*7c478bd9Sstevel@tonic-gate 			    proc_get_psinfo(pid, &psinfo) == 0) {
423*7c478bd9Sstevel@tonic-gate 				argv = (long)psinfo.pr_argv;
424*7c478bd9Sstevel@tonic-gate 				if (data_model == PR_MODEL_LP64)
425*7c478bd9Sstevel@tonic-gate 					(void) Pread(Proc, &offset,
426*7c478bd9Sstevel@tonic-gate 						sizeof (offset), argv);
427*7c478bd9Sstevel@tonic-gate 				else {
428*7c478bd9Sstevel@tonic-gate 					offset32 = 0;
429*7c478bd9Sstevel@tonic-gate 					(void) Pread(Proc, &offset32,
430*7c478bd9Sstevel@tonic-gate 						sizeof (offset32), argv);
431*7c478bd9Sstevel@tonic-gate 					offset = offset32;
432*7c478bd9Sstevel@tonic-gate 				}
433*7c478bd9Sstevel@tonic-gate 			}
434*7c478bd9Sstevel@tonic-gate 		} else {
435*7c478bd9Sstevel@tonic-gate 			offset = pri->sys_args[0];
436*7c478bd9Sstevel@tonic-gate 		}
437*7c478bd9Sstevel@tonic-gate 		if ((s = fetchstring(pri, offset, PATH_MAX)) != NULL) {
438*7c478bd9Sstevel@tonic-gate 			pri->sys_valid = TRUE;
439*7c478bd9Sstevel@tonic-gate 			len = strlen(s);
440*7c478bd9Sstevel@tonic-gate 			/* reallocate if necessary */
441*7c478bd9Sstevel@tonic-gate 			while (len >= pri->sys_psize) {
442*7c478bd9Sstevel@tonic-gate 				free(pri->sys_path);
443*7c478bd9Sstevel@tonic-gate 				pri->sys_path = my_malloc(pri->sys_psize *= 2,
444*7c478bd9Sstevel@tonic-gate 					"pathname buffer");
445*7c478bd9Sstevel@tonic-gate 			}
446*7c478bd9Sstevel@tonic-gate 			(void) strcpy(pri->sys_path, s); /* remember pathname */
447*7c478bd9Sstevel@tonic-gate 		}
448*7c478bd9Sstevel@tonic-gate 	}
449*7c478bd9Sstevel@tonic-gate 
450*7c478bd9Sstevel@tonic-gate 	istraced = dotrace && prismember(&trace, what);
451*7c478bd9Sstevel@tonic-gate 	raw = prismember(&rawout, what);
452*7c478bd9Sstevel@tonic-gate 
453*7c478bd9Sstevel@tonic-gate 	/* force tracing of read/write buffer dump syscalls */
454*7c478bd9Sstevel@tonic-gate 	if (!istraced && nargs > 2) {
455*7c478bd9Sstevel@tonic-gate 		int fdp1 = (int)pri->sys_args[0] + 1;
456*7c478bd9Sstevel@tonic-gate 
457*7c478bd9Sstevel@tonic-gate 		if (ISREAD(what)) {
458*7c478bd9Sstevel@tonic-gate 			if (prismember(&readfd, fdp1))
459*7c478bd9Sstevel@tonic-gate 				istraced = TRUE;
460*7c478bd9Sstevel@tonic-gate 		} else if (ISWRITE(what)) {
461*7c478bd9Sstevel@tonic-gate 			if (prismember(&writefd, fdp1))
462*7c478bd9Sstevel@tonic-gate 				istraced = TRUE;
463*7c478bd9Sstevel@tonic-gate 		}
464*7c478bd9Sstevel@tonic-gate 	}
465*7c478bd9Sstevel@tonic-gate 
466*7c478bd9Sstevel@tonic-gate 	pri->sys_leng = 0;
467*7c478bd9Sstevel@tonic-gate 	if (cflag || !istraced)		/* just counting */
468*7c478bd9Sstevel@tonic-gate 		*pri->sys_string = 0;
469*7c478bd9Sstevel@tonic-gate 	else {
470*7c478bd9Sstevel@tonic-gate 		int argprinted = FALSE;
471*7c478bd9Sstevel@tonic-gate 		const char *name;
472*7c478bd9Sstevel@tonic-gate 
473*7c478bd9Sstevel@tonic-gate 		name = sysname(pri, what, raw ? -1 : subcode);
474*7c478bd9Sstevel@tonic-gate 		grow(pri, strlen(name) + 1);
475*7c478bd9Sstevel@tonic-gate 		pri->sys_leng = snprintf(pri->sys_string, pri->sys_ssize,
476*7c478bd9Sstevel@tonic-gate 			"%s(", name);
477*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < nargs; i++) {
478*7c478bd9Sstevel@tonic-gate 			arg = pri->sys_args[i];
479*7c478bd9Sstevel@tonic-gate 			x = stp->arg[i];
480*7c478bd9Sstevel@tonic-gate 
481*7c478bd9Sstevel@tonic-gate 			if (x == STG && !raw &&
482*7c478bd9Sstevel@tonic-gate 			    i == 0 && pri->sys_valid) {	/* already fetched */
483*7c478bd9Sstevel@tonic-gate 				escape_string(pri, pri->sys_path);
484*7c478bd9Sstevel@tonic-gate 				argprinted = TRUE;
485*7c478bd9Sstevel@tonic-gate 			} else if (x != HID || raw) {
486*7c478bd9Sstevel@tonic-gate 				if (argprinted)
487*7c478bd9Sstevel@tonic-gate 					outstring(pri, ", ");
488*7c478bd9Sstevel@tonic-gate 				if (x == LLO)
489*7c478bd9Sstevel@tonic-gate 					(*Print[x])(pri, raw, arg,
490*7c478bd9Sstevel@tonic-gate 						pri->sys_args[++i]);
491*7c478bd9Sstevel@tonic-gate 				else
492*7c478bd9Sstevel@tonic-gate 					(*Print[x])(pri, raw, arg);
493*7c478bd9Sstevel@tonic-gate 				/*
494*7c478bd9Sstevel@tonic-gate 				 * if nothing printed, then don't print ", "
495*7c478bd9Sstevel@tonic-gate 				 */
496*7c478bd9Sstevel@tonic-gate 				if (x == NOV)
497*7c478bd9Sstevel@tonic-gate 					argprinted = FALSE;
498*7c478bd9Sstevel@tonic-gate 				else
499*7c478bd9Sstevel@tonic-gate 					argprinted = TRUE;
500*7c478bd9Sstevel@tonic-gate 			}
501*7c478bd9Sstevel@tonic-gate 		}
502*7c478bd9Sstevel@tonic-gate 		outstring(pri, ")");
503*7c478bd9Sstevel@tonic-gate 	}
504*7c478bd9Sstevel@tonic-gate 
505*7c478bd9Sstevel@tonic-gate 	return (istraced);
506*7c478bd9Sstevel@tonic-gate }
507*7c478bd9Sstevel@tonic-gate #undef	ISREAD
508*7c478bd9Sstevel@tonic-gate #undef	ISWRITE
509*7c478bd9Sstevel@tonic-gate 
510*7c478bd9Sstevel@tonic-gate /*
511*7c478bd9Sstevel@tonic-gate  * sysexit() returns non-zero if anything was printed.
512*7c478bd9Sstevel@tonic-gate  */
513*7c478bd9Sstevel@tonic-gate int
514*7c478bd9Sstevel@tonic-gate sysexit(private_t *pri, int dotrace)
515*7c478bd9Sstevel@tonic-gate {
516*7c478bd9Sstevel@tonic-gate 	const lwpstatus_t *Lsp = pri->lwpstat;
517*7c478bd9Sstevel@tonic-gate 	int what = Lsp->pr_what;
518*7c478bd9Sstevel@tonic-gate 	struct syscount *scp;
519*7c478bd9Sstevel@tonic-gate 	const struct systable *stp;
520*7c478bd9Sstevel@tonic-gate 	int subcode;
521*7c478bd9Sstevel@tonic-gate 	int istraced;
522*7c478bd9Sstevel@tonic-gate 	int raw;
523*7c478bd9Sstevel@tonic-gate 
524*7c478bd9Sstevel@tonic-gate 	/* protect ourself from operating system error */
525*7c478bd9Sstevel@tonic-gate 	if (what <= 0 || what > PRMAXSYS)
526*7c478bd9Sstevel@tonic-gate 		return (0);
527*7c478bd9Sstevel@tonic-gate 
528*7c478bd9Sstevel@tonic-gate 	/*
529*7c478bd9Sstevel@tonic-gate 	 * If we aren't supposed to be tracing this one, then
530*7c478bd9Sstevel@tonic-gate 	 * delete it from the traced signal set.  We got here
531*7c478bd9Sstevel@tonic-gate 	 * because the process was sleeping in an untraced syscall.
532*7c478bd9Sstevel@tonic-gate 	 */
533*7c478bd9Sstevel@tonic-gate 	if (!prismember(&traceeven, what)) {
534*7c478bd9Sstevel@tonic-gate 		(void) Psysexit(Proc, what, FALSE);
535*7c478bd9Sstevel@tonic-gate 		return (0);
536*7c478bd9Sstevel@tonic-gate 	}
537*7c478bd9Sstevel@tonic-gate 
538*7c478bd9Sstevel@tonic-gate 	/* pick up registers & set pri->Errno before anything else */
539*7c478bd9Sstevel@tonic-gate 	pri->Errno = Lsp->pr_errno;
540*7c478bd9Sstevel@tonic-gate 	pri->ErrPriv = Lsp->pr_errpriv;
541*7c478bd9Sstevel@tonic-gate 	pri->Rval1 = Lsp->pr_rval1;
542*7c478bd9Sstevel@tonic-gate 	pri->Rval2 = Lsp->pr_rval2;
543*7c478bd9Sstevel@tonic-gate 
544*7c478bd9Sstevel@tonic-gate 	switch (what) {
545*7c478bd9Sstevel@tonic-gate 	case SYS_exit:		/* these are traced on entry */
546*7c478bd9Sstevel@tonic-gate 	case SYS_lwp_exit:
547*7c478bd9Sstevel@tonic-gate 	case SYS_evtrapret:
548*7c478bd9Sstevel@tonic-gate 	case SYS_context:
549*7c478bd9Sstevel@tonic-gate 		istraced = dotrace && prismember(&trace, what);
550*7c478bd9Sstevel@tonic-gate 		break;
551*7c478bd9Sstevel@tonic-gate 	case SYS_exec:		/* these are normally traced on entry */
552*7c478bd9Sstevel@tonic-gate 	case SYS_execve:
553*7c478bd9Sstevel@tonic-gate 		istraced = dotrace && prismember(&trace, what);
554*7c478bd9Sstevel@tonic-gate 		if (pri->exec_string && *pri->exec_string) {
555*7c478bd9Sstevel@tonic-gate 			if (!cflag && istraced) { /* print exec() string now */
556*7c478bd9Sstevel@tonic-gate 				if (pri->exec_pname[0] != '\0')
557*7c478bd9Sstevel@tonic-gate 					(void) fputs(pri->exec_pname, stdout);
558*7c478bd9Sstevel@tonic-gate 				timestamp(pri);
559*7c478bd9Sstevel@tonic-gate 				(void) fputs(pri->exec_string, stdout);
560*7c478bd9Sstevel@tonic-gate 			}
561*7c478bd9Sstevel@tonic-gate 			pri->exec_pname[0] = '\0';
562*7c478bd9Sstevel@tonic-gate 			pri->exec_string[0] = '\0';
563*7c478bd9Sstevel@tonic-gate 			break;
564*7c478bd9Sstevel@tonic-gate 		}
565*7c478bd9Sstevel@tonic-gate 		/* FALLTHROUGH */
566*7c478bd9Sstevel@tonic-gate 	default:
567*7c478bd9Sstevel@tonic-gate 		/* we called sysentry() in main() for these */
568*7c478bd9Sstevel@tonic-gate 		if (what == SYS_open || what == SYS_open64)
569*7c478bd9Sstevel@tonic-gate 			istraced = dotrace && prismember(&trace, what);
570*7c478bd9Sstevel@tonic-gate 		else
571*7c478bd9Sstevel@tonic-gate 			istraced = sysentry(pri, dotrace) && dotrace;
572*7c478bd9Sstevel@tonic-gate 		pri->length = 0;
573*7c478bd9Sstevel@tonic-gate 		if (!cflag && istraced) {
574*7c478bd9Sstevel@tonic-gate 			putpname(pri);
575*7c478bd9Sstevel@tonic-gate 			timestamp(pri);
576*7c478bd9Sstevel@tonic-gate 			pri->length += printf("%s", pri->sys_string);
577*7c478bd9Sstevel@tonic-gate 		}
578*7c478bd9Sstevel@tonic-gate 		pri->sys_leng = 0;
579*7c478bd9Sstevel@tonic-gate 		*pri->sys_string = '\0';
580*7c478bd9Sstevel@tonic-gate 		break;
581*7c478bd9Sstevel@tonic-gate 	}
582*7c478bd9Sstevel@tonic-gate 
583*7c478bd9Sstevel@tonic-gate 	/* get systable entry for this syscall */
584*7c478bd9Sstevel@tonic-gate 	subcode = getsubcode(pri);
585*7c478bd9Sstevel@tonic-gate 	stp = subsys(what, subcode);
586*7c478bd9Sstevel@tonic-gate 
587*7c478bd9Sstevel@tonic-gate 	if (cflag && istraced) {
588*7c478bd9Sstevel@tonic-gate 		(void) mutex_lock(&count_lock);
589*7c478bd9Sstevel@tonic-gate 		scp = Cp->syscount[what];
590*7c478bd9Sstevel@tonic-gate 		if (subcode != -1 &&
591*7c478bd9Sstevel@tonic-gate 		    (what != SYS_open && what != SYS_open64 &&
592*7c478bd9Sstevel@tonic-gate 		    what != SYS_lwp_create))
593*7c478bd9Sstevel@tonic-gate 			scp += subcode;
594*7c478bd9Sstevel@tonic-gate 		scp->count++;
595*7c478bd9Sstevel@tonic-gate 		accumulate(&scp->stime, &Lsp->pr_stime, &pri->syslast);
596*7c478bd9Sstevel@tonic-gate 		accumulate(&Cp->usrtotal, &Lsp->pr_utime, &pri->usrlast);
597*7c478bd9Sstevel@tonic-gate 		pri->syslast = Lsp->pr_stime;
598*7c478bd9Sstevel@tonic-gate 		pri->usrlast = Lsp->pr_utime;
599*7c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&count_lock);
600*7c478bd9Sstevel@tonic-gate 	}
601*7c478bd9Sstevel@tonic-gate 
602*7c478bd9Sstevel@tonic-gate 	if (!cflag && istraced) {
603*7c478bd9Sstevel@tonic-gate 		if ((what == SYS_forkall ||
604*7c478bd9Sstevel@tonic-gate 		    what == SYS_vfork ||
605*7c478bd9Sstevel@tonic-gate 		    what == SYS_fork1) &&
606*7c478bd9Sstevel@tonic-gate 		    pri->Errno == 0 && pri->Rval2 != 0) {
607*7c478bd9Sstevel@tonic-gate 			pri->length &= ~07;
608*7c478bd9Sstevel@tonic-gate 			if (what == SYS_forkall)
609*7c478bd9Sstevel@tonic-gate 				pri->length -= 8;
610*7c478bd9Sstevel@tonic-gate 			else
611*7c478bd9Sstevel@tonic-gate 				(void) fputc('\t', stdout);
612*7c478bd9Sstevel@tonic-gate 			pri->length +=
613*7c478bd9Sstevel@tonic-gate 				15 + printf("\t(returning as child ...)");
614*7c478bd9Sstevel@tonic-gate 		}
615*7c478bd9Sstevel@tonic-gate 		if (what == SYS_lwp_create &&
616*7c478bd9Sstevel@tonic-gate 		    pri->Errno == 0 && pri->Rval1 == 0) {
617*7c478bd9Sstevel@tonic-gate 			pri->length &= ~07;
618*7c478bd9Sstevel@tonic-gate 			pri->length +=
619*7c478bd9Sstevel@tonic-gate 				7 + printf("\t(returning as new lwp ...)");
620*7c478bd9Sstevel@tonic-gate 		}
621*7c478bd9Sstevel@tonic-gate 		if (pri->Errno != 0 ||
622*7c478bd9Sstevel@tonic-gate 		    (what != SYS_exec && what != SYS_execve)) {
623*7c478bd9Sstevel@tonic-gate 			/* prepare to print the return code */
624*7c478bd9Sstevel@tonic-gate 			pri->length >>= 3;
625*7c478bd9Sstevel@tonic-gate 			if (pri->length >= 6)
626*7c478bd9Sstevel@tonic-gate 				(void) fputc(' ', stdout);
627*7c478bd9Sstevel@tonic-gate 			for (; pri->length < 6; pri->length++)
628*7c478bd9Sstevel@tonic-gate 				(void) fputc('\t', stdout);
629*7c478bd9Sstevel@tonic-gate 		}
630*7c478bd9Sstevel@tonic-gate 	}
631*7c478bd9Sstevel@tonic-gate 	pri->length = 0;
632*7c478bd9Sstevel@tonic-gate 
633*7c478bd9Sstevel@tonic-gate 	raw = prismember(&rawout, what);
634*7c478bd9Sstevel@tonic-gate 
635*7c478bd9Sstevel@tonic-gate 	if (pri->Errno != 0) {		/* error in syscall */
636*7c478bd9Sstevel@tonic-gate 		if (istraced) {
637*7c478bd9Sstevel@tonic-gate 			if (cflag)
638*7c478bd9Sstevel@tonic-gate 				scp->error++;
639*7c478bd9Sstevel@tonic-gate 			else {
640*7c478bd9Sstevel@tonic-gate 				const char *ename = errname(pri->Errno);
641*7c478bd9Sstevel@tonic-gate 				const char *privname;
642*7c478bd9Sstevel@tonic-gate 
643*7c478bd9Sstevel@tonic-gate 				(void) printf("Err#%d", pri->Errno);
644*7c478bd9Sstevel@tonic-gate 				if (ename != NULL) {
645*7c478bd9Sstevel@tonic-gate 					(void) fputc(' ', stdout);
646*7c478bd9Sstevel@tonic-gate 					(void) fputs(ename, stdout);
647*7c478bd9Sstevel@tonic-gate 				}
648*7c478bd9Sstevel@tonic-gate 				switch (pri->ErrPriv) {
649*7c478bd9Sstevel@tonic-gate 				case PRIV_NONE:
650*7c478bd9Sstevel@tonic-gate 					privname = NULL;
651*7c478bd9Sstevel@tonic-gate 					break;
652*7c478bd9Sstevel@tonic-gate 				case PRIV_ALL:
653*7c478bd9Sstevel@tonic-gate 					privname = "ALL";
654*7c478bd9Sstevel@tonic-gate 					break;
655*7c478bd9Sstevel@tonic-gate 				case PRIV_MULTIPLE:
656*7c478bd9Sstevel@tonic-gate 					privname = "MULTIPLE";
657*7c478bd9Sstevel@tonic-gate 					break;
658*7c478bd9Sstevel@tonic-gate 				case PRIV_ALLZONE:
659*7c478bd9Sstevel@tonic-gate 					privname = "ZONE";
660*7c478bd9Sstevel@tonic-gate 					break;
661*7c478bd9Sstevel@tonic-gate 				default:
662*7c478bd9Sstevel@tonic-gate 					privname = priv_getbynum(pri->ErrPriv);
663*7c478bd9Sstevel@tonic-gate 					break;
664*7c478bd9Sstevel@tonic-gate 				}
665*7c478bd9Sstevel@tonic-gate 				if (privname != NULL)
666*7c478bd9Sstevel@tonic-gate 					(void) printf(" [%s]", privname);
667*7c478bd9Sstevel@tonic-gate 
668*7c478bd9Sstevel@tonic-gate 				(void) fputc('\n', stdout);
669*7c478bd9Sstevel@tonic-gate 			}
670*7c478bd9Sstevel@tonic-gate 		}
671*7c478bd9Sstevel@tonic-gate 	} else {
672*7c478bd9Sstevel@tonic-gate 		/* show arguments on successful exec */
673*7c478bd9Sstevel@tonic-gate 		if (what == SYS_exec || what == SYS_execve) {
674*7c478bd9Sstevel@tonic-gate 			if (!cflag && istraced)
675*7c478bd9Sstevel@tonic-gate 				showargs(pri, raw);
676*7c478bd9Sstevel@tonic-gate 		} else if (!cflag && istraced) {
677*7c478bd9Sstevel@tonic-gate 			const char *fmt = NULL;
678*7c478bd9Sstevel@tonic-gate 			long rv1 = pri->Rval1;
679*7c478bd9Sstevel@tonic-gate 			long rv2 = pri->Rval2;
680*7c478bd9Sstevel@tonic-gate 
681*7c478bd9Sstevel@tonic-gate #ifdef _LP64
682*7c478bd9Sstevel@tonic-gate 			/*
683*7c478bd9Sstevel@tonic-gate 			 * 32-bit system calls return 32-bit values. We
684*7c478bd9Sstevel@tonic-gate 			 * later mask out the upper bits if we want to
685*7c478bd9Sstevel@tonic-gate 			 * print these as unsigned values.
686*7c478bd9Sstevel@tonic-gate 			 */
687*7c478bd9Sstevel@tonic-gate 			if (data_model == PR_MODEL_ILP32) {
688*7c478bd9Sstevel@tonic-gate 				rv1 = (int)rv1;
689*7c478bd9Sstevel@tonic-gate 				rv2 = (int)rv2;
690*7c478bd9Sstevel@tonic-gate 			}
691*7c478bd9Sstevel@tonic-gate #endif
692*7c478bd9Sstevel@tonic-gate 
693*7c478bd9Sstevel@tonic-gate 			switch (what) {
694*7c478bd9Sstevel@tonic-gate 			case SYS_llseek:
695*7c478bd9Sstevel@tonic-gate 				rv1 &= 0xffffffff;
696*7c478bd9Sstevel@tonic-gate 				rv2 &= 0xffffffff;
697*7c478bd9Sstevel@tonic-gate #ifdef _LONG_LONG_LTOH	/* first long of a longlong is the low order */
698*7c478bd9Sstevel@tonic-gate 				if (rv2 != 0) {
699*7c478bd9Sstevel@tonic-gate 					long temp = rv1;
700*7c478bd9Sstevel@tonic-gate 					fmt = "= 0x%lX%.8lX";
701*7c478bd9Sstevel@tonic-gate 					rv1 = rv2;
702*7c478bd9Sstevel@tonic-gate 					rv2 = temp;
703*7c478bd9Sstevel@tonic-gate 					break;
704*7c478bd9Sstevel@tonic-gate 				}
705*7c478bd9Sstevel@tonic-gate #else	/* the other way around */
706*7c478bd9Sstevel@tonic-gate 				if (rv1 != 0) {
707*7c478bd9Sstevel@tonic-gate 					fmt = "= 0x%lX%.8lX";
708*7c478bd9Sstevel@tonic-gate 					break;
709*7c478bd9Sstevel@tonic-gate 				}
710*7c478bd9Sstevel@tonic-gate 				rv1 = rv2;	/* ugly */
711*7c478bd9Sstevel@tonic-gate #endif
712*7c478bd9Sstevel@tonic-gate 				/* FALLTHROUGH */
713*7c478bd9Sstevel@tonic-gate 			case SYS_lseek:
714*7c478bd9Sstevel@tonic-gate 			case SYS_ulimit:
715*7c478bd9Sstevel@tonic-gate 				if (rv1 & 0xff000000) {
716*7c478bd9Sstevel@tonic-gate #ifdef _LP64
717*7c478bd9Sstevel@tonic-gate 					if (data_model == PR_MODEL_ILP32)
718*7c478bd9Sstevel@tonic-gate 						rv1 &= 0xffffffff;
719*7c478bd9Sstevel@tonic-gate #endif
720*7c478bd9Sstevel@tonic-gate 					fmt = "= 0x%.8lX";
721*7c478bd9Sstevel@tonic-gate 				}
722*7c478bd9Sstevel@tonic-gate 				break;
723*7c478bd9Sstevel@tonic-gate 			case SYS_signal:
724*7c478bd9Sstevel@tonic-gate 				if (raw)
725*7c478bd9Sstevel@tonic-gate 					/* EMPTY */;
726*7c478bd9Sstevel@tonic-gate 				else if (rv1 == (int)SIG_DFL)
727*7c478bd9Sstevel@tonic-gate 					fmt = "= SIG_DFL";
728*7c478bd9Sstevel@tonic-gate 				else if (rv1 == (int)SIG_IGN)
729*7c478bd9Sstevel@tonic-gate 					fmt = "= SIG_IGN";
730*7c478bd9Sstevel@tonic-gate 				else if (rv1 == (int)SIG_HOLD)
731*7c478bd9Sstevel@tonic-gate 					fmt = "= SIG_HOLD";
732*7c478bd9Sstevel@tonic-gate 				break;
733*7c478bd9Sstevel@tonic-gate 			case SYS_sigtimedwait:
734*7c478bd9Sstevel@tonic-gate 				if (raw)
735*7c478bd9Sstevel@tonic-gate 					/* EMPTY */;
736*7c478bd9Sstevel@tonic-gate 				else if ((fmt = rawsigname(pri, rv1)) != NULL) {
737*7c478bd9Sstevel@tonic-gate 					rv1 = (long)fmt;	/* filthy */
738*7c478bd9Sstevel@tonic-gate 					fmt = "= %s";
739*7c478bd9Sstevel@tonic-gate 				}
740*7c478bd9Sstevel@tonic-gate 				break;
741*7c478bd9Sstevel@tonic-gate 			case SYS_port:
742*7c478bd9Sstevel@tonic-gate #ifdef _LP64
743*7c478bd9Sstevel@tonic-gate 				if (data_model == PR_MODEL_LP64) {
744*7c478bd9Sstevel@tonic-gate 					rv2 = rv1 & 0xffffffff;
745*7c478bd9Sstevel@tonic-gate 					rv1 = rv1 >> 32;
746*7c478bd9Sstevel@tonic-gate 				}
747*7c478bd9Sstevel@tonic-gate #endif
748*7c478bd9Sstevel@tonic-gate 				break;
749*7c478bd9Sstevel@tonic-gate 			}
750*7c478bd9Sstevel@tonic-gate 
751*7c478bd9Sstevel@tonic-gate 			if (fmt == NULL) {
752*7c478bd9Sstevel@tonic-gate 				switch (stp->rval[0]) {
753*7c478bd9Sstevel@tonic-gate 				case HEX:
754*7c478bd9Sstevel@tonic-gate #ifdef _LP64
755*7c478bd9Sstevel@tonic-gate 					if (data_model == PR_MODEL_ILP32)
756*7c478bd9Sstevel@tonic-gate 						rv1 &= 0xffffffff;
757*7c478bd9Sstevel@tonic-gate #endif
758*7c478bd9Sstevel@tonic-gate 					fmt = "= 0x%.8lX";
759*7c478bd9Sstevel@tonic-gate 					break;
760*7c478bd9Sstevel@tonic-gate 				case HHX:
761*7c478bd9Sstevel@tonic-gate #ifdef _LP64
762*7c478bd9Sstevel@tonic-gate 					if (data_model == PR_MODEL_ILP32)
763*7c478bd9Sstevel@tonic-gate 						rv1 &= 0xffffffff;
764*7c478bd9Sstevel@tonic-gate #endif
765*7c478bd9Sstevel@tonic-gate 					fmt = "= 0x%.4lX";
766*7c478bd9Sstevel@tonic-gate 					break;
767*7c478bd9Sstevel@tonic-gate 				case OCT:
768*7c478bd9Sstevel@tonic-gate #ifdef _LP64
769*7c478bd9Sstevel@tonic-gate 					if (data_model == PR_MODEL_ILP32)
770*7c478bd9Sstevel@tonic-gate 						rv1 &= 0xffffffff;
771*7c478bd9Sstevel@tonic-gate #endif
772*7c478bd9Sstevel@tonic-gate 					fmt = "= %#lo";
773*7c478bd9Sstevel@tonic-gate 					break;
774*7c478bd9Sstevel@tonic-gate 				default:
775*7c478bd9Sstevel@tonic-gate 					fmt = "= %ld";
776*7c478bd9Sstevel@tonic-gate 					break;
777*7c478bd9Sstevel@tonic-gate 				}
778*7c478bd9Sstevel@tonic-gate 			}
779*7c478bd9Sstevel@tonic-gate 
780*7c478bd9Sstevel@tonic-gate 			(void) printf(fmt, rv1, rv2);
781*7c478bd9Sstevel@tonic-gate 
782*7c478bd9Sstevel@tonic-gate 			switch (stp->rval[1]) {
783*7c478bd9Sstevel@tonic-gate 			case NOV:
784*7c478bd9Sstevel@tonic-gate 				fmt = NULL;
785*7c478bd9Sstevel@tonic-gate 				break;
786*7c478bd9Sstevel@tonic-gate 			case HEX:
787*7c478bd9Sstevel@tonic-gate #ifdef _LP64
788*7c478bd9Sstevel@tonic-gate 				if (data_model == PR_MODEL_ILP32)
789*7c478bd9Sstevel@tonic-gate 					rv2 &= 0xffffffff;
790*7c478bd9Sstevel@tonic-gate #endif
791*7c478bd9Sstevel@tonic-gate 				fmt = " [0x%.8lX]";
792*7c478bd9Sstevel@tonic-gate 				break;
793*7c478bd9Sstevel@tonic-gate 			case HHX:
794*7c478bd9Sstevel@tonic-gate #ifdef _LP64
795*7c478bd9Sstevel@tonic-gate 				if (data_model == PR_MODEL_ILP32)
796*7c478bd9Sstevel@tonic-gate 					rv2 &= 0xffffffff;
797*7c478bd9Sstevel@tonic-gate #endif
798*7c478bd9Sstevel@tonic-gate 				fmt = " [0x%.4lX]";
799*7c478bd9Sstevel@tonic-gate 				break;
800*7c478bd9Sstevel@tonic-gate 			case OCT:
801*7c478bd9Sstevel@tonic-gate #ifdef _LP64
802*7c478bd9Sstevel@tonic-gate 				if (data_model == PR_MODEL_ILP32)
803*7c478bd9Sstevel@tonic-gate 					rv2 &= 0xffffffff;
804*7c478bd9Sstevel@tonic-gate #endif
805*7c478bd9Sstevel@tonic-gate 				fmt = " [%#lo]";
806*7c478bd9Sstevel@tonic-gate 				break;
807*7c478bd9Sstevel@tonic-gate 			default:
808*7c478bd9Sstevel@tonic-gate 				fmt = " [%ld]";
809*7c478bd9Sstevel@tonic-gate 				break;
810*7c478bd9Sstevel@tonic-gate 			}
811*7c478bd9Sstevel@tonic-gate 
812*7c478bd9Sstevel@tonic-gate 			if (fmt != NULL)
813*7c478bd9Sstevel@tonic-gate 				(void) printf(fmt, rv2);
814*7c478bd9Sstevel@tonic-gate 			(void) fputc('\n', stdout);
815*7c478bd9Sstevel@tonic-gate 		}
816*7c478bd9Sstevel@tonic-gate 
817*7c478bd9Sstevel@tonic-gate 		if (what == SYS_forkall ||
818*7c478bd9Sstevel@tonic-gate 		    what == SYS_vfork ||
819*7c478bd9Sstevel@tonic-gate 		    what == SYS_fork1) {
820*7c478bd9Sstevel@tonic-gate 			if (pri->Rval2 == 0)		/* child was created */
821*7c478bd9Sstevel@tonic-gate 				pri->child = pri->Rval1;
822*7c478bd9Sstevel@tonic-gate 			else if (cflag && istraced)	/* this is the child */
823*7c478bd9Sstevel@tonic-gate 				scp->count--;
824*7c478bd9Sstevel@tonic-gate 		}
825*7c478bd9Sstevel@tonic-gate 		if (what == SYS_lwp_create && pri->Rval1 == 0 &&
826*7c478bd9Sstevel@tonic-gate 		    cflag && istraced)		/* this is the created lwp */
827*7c478bd9Sstevel@tonic-gate 			scp->count--;
828*7c478bd9Sstevel@tonic-gate 	}
829*7c478bd9Sstevel@tonic-gate 
830*7c478bd9Sstevel@tonic-gate #define	ISREAD(code) \
831*7c478bd9Sstevel@tonic-gate 	((code) == SYS_read || (code) == SYS_pread || (code) == SYS_pread64 || \
832*7c478bd9Sstevel@tonic-gate 	(code) == SYS_recv || (code) == SYS_recvfrom)
833*7c478bd9Sstevel@tonic-gate #define	ISWRITE(code) \
834*7c478bd9Sstevel@tonic-gate 	((code) == SYS_write || (code) == SYS_pwrite || \
835*7c478bd9Sstevel@tonic-gate 	(code) == SYS_pwrite64 || (code) == SYS_send || (code) == SYS_sendto)
836*7c478bd9Sstevel@tonic-gate 
837*7c478bd9Sstevel@tonic-gate 	if (!cflag && istraced) {
838*7c478bd9Sstevel@tonic-gate 		int fdp1 = (int)pri->sys_args[0] + 1; /* filedescriptor + 1 */
839*7c478bd9Sstevel@tonic-gate 
840*7c478bd9Sstevel@tonic-gate 		if (raw) {
841*7c478bd9Sstevel@tonic-gate 			if (what != SYS_exec && what != SYS_execve)
842*7c478bd9Sstevel@tonic-gate 				showpaths(pri, stp);
843*7c478bd9Sstevel@tonic-gate 			if (ISREAD(what) || ISWRITE(what)) {
844*7c478bd9Sstevel@tonic-gate 				if (pri->iob_buf[0] != '\0')
845*7c478bd9Sstevel@tonic-gate 					(void) printf("%s     0x%.8lX: %s\n",
846*7c478bd9Sstevel@tonic-gate 						pri->pname, pri->sys_args[1],
847*7c478bd9Sstevel@tonic-gate 						pri->iob_buf);
848*7c478bd9Sstevel@tonic-gate 			}
849*7c478bd9Sstevel@tonic-gate 		}
850*7c478bd9Sstevel@tonic-gate 
851*7c478bd9Sstevel@tonic-gate 		/*
852*7c478bd9Sstevel@tonic-gate 		 * Show buffer contents for read()/pread() or write()/pwrite().
853*7c478bd9Sstevel@tonic-gate 		 * IOBSIZE bytes have already been shown;
854*7c478bd9Sstevel@tonic-gate 		 * don't show them again unless there's more.
855*7c478bd9Sstevel@tonic-gate 		 */
856*7c478bd9Sstevel@tonic-gate 		if ((ISREAD(what) && pri->Errno == 0 &&
857*7c478bd9Sstevel@tonic-gate 		    prismember(&readfd, fdp1)) ||
858*7c478bd9Sstevel@tonic-gate 		    (ISWRITE(what) && prismember(&writefd, fdp1))) {
859*7c478bd9Sstevel@tonic-gate 			long nb = ISWRITE(what) ? pri->sys_args[2] : pri->Rval1;
860*7c478bd9Sstevel@tonic-gate 
861*7c478bd9Sstevel@tonic-gate 			if (nb > IOBSIZE) {
862*7c478bd9Sstevel@tonic-gate 				/* enter region of lengthy output */
863*7c478bd9Sstevel@tonic-gate 				if (nb > MYBUFSIZ / 4)
864*7c478bd9Sstevel@tonic-gate 					Eserialize();
865*7c478bd9Sstevel@tonic-gate 
866*7c478bd9Sstevel@tonic-gate 				showbuffer(pri, pri->sys_args[1], nb);
867*7c478bd9Sstevel@tonic-gate 
868*7c478bd9Sstevel@tonic-gate 				/* exit region of lengthy output */
869*7c478bd9Sstevel@tonic-gate 				if (nb > MYBUFSIZ / 4)
870*7c478bd9Sstevel@tonic-gate 					Xserialize();
871*7c478bd9Sstevel@tonic-gate 			}
872*7c478bd9Sstevel@tonic-gate 		}
873*7c478bd9Sstevel@tonic-gate #undef	ISREAD
874*7c478bd9Sstevel@tonic-gate #undef	ISWRITE
875*7c478bd9Sstevel@tonic-gate 		/*
876*7c478bd9Sstevel@tonic-gate 		 * Do verbose interpretation if requested.
877*7c478bd9Sstevel@tonic-gate 		 * If buffer contents for read or write have been requested and
878*7c478bd9Sstevel@tonic-gate 		 * this is a readv() or writev(), force verbose interpretation.
879*7c478bd9Sstevel@tonic-gate 		 */
880*7c478bd9Sstevel@tonic-gate /* XXX add SYS_sendmsg and SYS_recvmsg */
881*7c478bd9Sstevel@tonic-gate 		if (prismember(&verbose, what) ||
882*7c478bd9Sstevel@tonic-gate 		    (what == SYS_readv && pri->Errno == 0 &&
883*7c478bd9Sstevel@tonic-gate 		    prismember(&readfd, fdp1)) ||
884*7c478bd9Sstevel@tonic-gate 		    ((what == SYS_writev || what == SYS_sendfilev) &&
885*7c478bd9Sstevel@tonic-gate 		    prismember(&writefd, fdp1)))
886*7c478bd9Sstevel@tonic-gate 			expound(pri, pri->Rval1, raw);
887*7c478bd9Sstevel@tonic-gate 	}
888*7c478bd9Sstevel@tonic-gate 
889*7c478bd9Sstevel@tonic-gate 	return (!cflag && istraced);
890*7c478bd9Sstevel@tonic-gate }
891*7c478bd9Sstevel@tonic-gate 
892*7c478bd9Sstevel@tonic-gate void
893*7c478bd9Sstevel@tonic-gate showpaths(private_t *pri, const struct systable *stp)
894*7c478bd9Sstevel@tonic-gate {
895*7c478bd9Sstevel@tonic-gate 	int i;
896*7c478bd9Sstevel@tonic-gate 
897*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < pri->sys_nargs; i++) {
898*7c478bd9Sstevel@tonic-gate 		if ((stp->arg[i] == STG) ||
899*7c478bd9Sstevel@tonic-gate 		    (stp->arg[i] == RST && !pri->Errno) ||
900*7c478bd9Sstevel@tonic-gate 		    (stp->arg[i] == RLK && !pri->Errno && pri->Rval1 > 0)) {
901*7c478bd9Sstevel@tonic-gate 			long addr = pri->sys_args[i];
902*7c478bd9Sstevel@tonic-gate 			int maxleng =
903*7c478bd9Sstevel@tonic-gate 			    (stp->arg[i] == RLK)? (int)pri->Rval1 : PATH_MAX;
904*7c478bd9Sstevel@tonic-gate 			char *s;
905*7c478bd9Sstevel@tonic-gate 
906*7c478bd9Sstevel@tonic-gate 			if (i == 0 && pri->sys_valid)	/* already fetched */
907*7c478bd9Sstevel@tonic-gate 				s = pri->sys_path;
908*7c478bd9Sstevel@tonic-gate 			else
909*7c478bd9Sstevel@tonic-gate 				s = fetchstring(pri, addr,
910*7c478bd9Sstevel@tonic-gate 				    maxleng > PATH_MAX ? PATH_MAX : maxleng);
911*7c478bd9Sstevel@tonic-gate 
912*7c478bd9Sstevel@tonic-gate 			if (s != (char *)NULL)
913*7c478bd9Sstevel@tonic-gate 				(void) printf("%s     0x%.8lX: \"%s\"\n",
914*7c478bd9Sstevel@tonic-gate 					pri->pname, addr, s);
915*7c478bd9Sstevel@tonic-gate 		}
916*7c478bd9Sstevel@tonic-gate 	}
917*7c478bd9Sstevel@tonic-gate }
918*7c478bd9Sstevel@tonic-gate 
919*7c478bd9Sstevel@tonic-gate /*
920*7c478bd9Sstevel@tonic-gate  * Display arguments to successful exec().
921*7c478bd9Sstevel@tonic-gate  */
922*7c478bd9Sstevel@tonic-gate void
923*7c478bd9Sstevel@tonic-gate showargs(private_t *pri, int raw)
924*7c478bd9Sstevel@tonic-gate {
925*7c478bd9Sstevel@tonic-gate 	const lwpstatus_t *Lsp = pri->lwpstat;
926*7c478bd9Sstevel@tonic-gate 	int nargs;
927*7c478bd9Sstevel@tonic-gate 	long ap;
928*7c478bd9Sstevel@tonic-gate 	int ptrsize;
929*7c478bd9Sstevel@tonic-gate 	int fail;
930*7c478bd9Sstevel@tonic-gate 
931*7c478bd9Sstevel@tonic-gate 	pri->length = 0;
932*7c478bd9Sstevel@tonic-gate 	ptrsize = (data_model == PR_MODEL_LP64)? 8 : 4;
933*7c478bd9Sstevel@tonic-gate 
934*7c478bd9Sstevel@tonic-gate #if defined(__i386) || defined(__amd64)	/* XX64 */
935*7c478bd9Sstevel@tonic-gate 	ap = (long)Lsp->pr_reg[R_SP];
936*7c478bd9Sstevel@tonic-gate 	fail = (Pread(Proc, &nargs, sizeof (nargs), ap) != sizeof (nargs));
937*7c478bd9Sstevel@tonic-gate 	ap += ptrsize;
938*7c478bd9Sstevel@tonic-gate #endif /* i386 */
939*7c478bd9Sstevel@tonic-gate 
940*7c478bd9Sstevel@tonic-gate #if sparc
941*7c478bd9Sstevel@tonic-gate 	if (data_model == PR_MODEL_LP64) {
942*7c478bd9Sstevel@tonic-gate 		int64_t xnargs;
943*7c478bd9Sstevel@tonic-gate 		ap = (long)(Lsp->pr_reg[R_SP]) + 16 * sizeof (int64_t)
944*7c478bd9Sstevel@tonic-gate 			+ STACK_BIAS;
945*7c478bd9Sstevel@tonic-gate 		fail = (Pread(Proc, &xnargs, sizeof (xnargs), ap) !=
946*7c478bd9Sstevel@tonic-gate 			sizeof (xnargs));
947*7c478bd9Sstevel@tonic-gate 		nargs = (int)xnargs;
948*7c478bd9Sstevel@tonic-gate 	} else {
949*7c478bd9Sstevel@tonic-gate 		ap = (long)(Lsp->pr_reg[R_SP]) + 16 * sizeof (int32_t);
950*7c478bd9Sstevel@tonic-gate 		fail = (Pread(Proc, &nargs, sizeof (nargs), ap) !=
951*7c478bd9Sstevel@tonic-gate 			sizeof (nargs));
952*7c478bd9Sstevel@tonic-gate 	}
953*7c478bd9Sstevel@tonic-gate 	ap += ptrsize;
954*7c478bd9Sstevel@tonic-gate #endif /* sparc */
955*7c478bd9Sstevel@tonic-gate 
956*7c478bd9Sstevel@tonic-gate 	if (fail) {
957*7c478bd9Sstevel@tonic-gate 		(void) printf("\n%s\t*** Bad argument list? ***\n", pri->pname);
958*7c478bd9Sstevel@tonic-gate 		return;
959*7c478bd9Sstevel@tonic-gate 	}
960*7c478bd9Sstevel@tonic-gate 
961*7c478bd9Sstevel@tonic-gate 	(void) printf("  argc = %d\n", nargs);
962*7c478bd9Sstevel@tonic-gate 	if (raw)
963*7c478bd9Sstevel@tonic-gate 		showpaths(pri, &systable[SYS_exec]);
964*7c478bd9Sstevel@tonic-gate 
965*7c478bd9Sstevel@tonic-gate 	show_cred(pri, FALSE);
966*7c478bd9Sstevel@tonic-gate 
967*7c478bd9Sstevel@tonic-gate 	if (aflag || eflag) {		/* dump args or environment */
968*7c478bd9Sstevel@tonic-gate 
969*7c478bd9Sstevel@tonic-gate 		/* enter region of (potentially) lengthy output */
970*7c478bd9Sstevel@tonic-gate 		Eserialize();
971*7c478bd9Sstevel@tonic-gate 
972*7c478bd9Sstevel@tonic-gate 		if (aflag)		/* dump the argument list */
973*7c478bd9Sstevel@tonic-gate 			dumpargs(pri, ap, "argv:");
974*7c478bd9Sstevel@tonic-gate 		ap += (nargs+1) * ptrsize;
975*7c478bd9Sstevel@tonic-gate 		if (eflag)		/* dump the environment */
976*7c478bd9Sstevel@tonic-gate 			dumpargs(pri, ap, "envp:");
977*7c478bd9Sstevel@tonic-gate 
978*7c478bd9Sstevel@tonic-gate 		/* exit region of lengthy output */
979*7c478bd9Sstevel@tonic-gate 		Xserialize();
980*7c478bd9Sstevel@tonic-gate 	}
981*7c478bd9Sstevel@tonic-gate }
982*7c478bd9Sstevel@tonic-gate 
983*7c478bd9Sstevel@tonic-gate void
984*7c478bd9Sstevel@tonic-gate dumpargs(private_t *pri, long ap, const char *str)
985*7c478bd9Sstevel@tonic-gate {
986*7c478bd9Sstevel@tonic-gate 	char *string;
987*7c478bd9Sstevel@tonic-gate 	unsigned int leng = 0;
988*7c478bd9Sstevel@tonic-gate 	int ptrsize;
989*7c478bd9Sstevel@tonic-gate 	long arg = 0;
990*7c478bd9Sstevel@tonic-gate 	char *argaddr;
991*7c478bd9Sstevel@tonic-gate 	char badaddr[32];
992*7c478bd9Sstevel@tonic-gate 
993*7c478bd9Sstevel@tonic-gate 	if (interrupt)
994*7c478bd9Sstevel@tonic-gate 		return;
995*7c478bd9Sstevel@tonic-gate 
996*7c478bd9Sstevel@tonic-gate #ifdef _LP64
997*7c478bd9Sstevel@tonic-gate 	if (data_model == PR_MODEL_LP64) {
998*7c478bd9Sstevel@tonic-gate 		argaddr = (char *)&arg;
999*7c478bd9Sstevel@tonic-gate 		ptrsize = 8;
1000*7c478bd9Sstevel@tonic-gate 	} else {
1001*7c478bd9Sstevel@tonic-gate #if defined(_LITTLE_ENDIAN)
1002*7c478bd9Sstevel@tonic-gate 		argaddr = (char *)&arg;
1003*7c478bd9Sstevel@tonic-gate #else
1004*7c478bd9Sstevel@tonic-gate 		argaddr = (char *)&arg + 4;
1005*7c478bd9Sstevel@tonic-gate #endif
1006*7c478bd9Sstevel@tonic-gate 		ptrsize = 4;
1007*7c478bd9Sstevel@tonic-gate 	}
1008*7c478bd9Sstevel@tonic-gate #else
1009*7c478bd9Sstevel@tonic-gate 	argaddr = (char *)&arg;
1010*7c478bd9Sstevel@tonic-gate 	ptrsize = 4;
1011*7c478bd9Sstevel@tonic-gate #endif
1012*7c478bd9Sstevel@tonic-gate 	putpname(pri);
1013*7c478bd9Sstevel@tonic-gate 	(void) fputc(' ', stdout);
1014*7c478bd9Sstevel@tonic-gate 	(void) fputs(str, stdout);
1015*7c478bd9Sstevel@tonic-gate 	leng += 1 + strlen(str);
1016*7c478bd9Sstevel@tonic-gate 
1017*7c478bd9Sstevel@tonic-gate 	while (!interrupt) {
1018*7c478bd9Sstevel@tonic-gate 		if (Pread(Proc, argaddr, ptrsize, ap) != ptrsize) {
1019*7c478bd9Sstevel@tonic-gate 			(void) printf("\n%s\t*** Bad argument list? ***\n",
1020*7c478bd9Sstevel@tonic-gate 				pri->pname);
1021*7c478bd9Sstevel@tonic-gate 			return;
1022*7c478bd9Sstevel@tonic-gate 		}
1023*7c478bd9Sstevel@tonic-gate 		ap += ptrsize;
1024*7c478bd9Sstevel@tonic-gate 
1025*7c478bd9Sstevel@tonic-gate 		if (arg == 0)
1026*7c478bd9Sstevel@tonic-gate 			break;
1027*7c478bd9Sstevel@tonic-gate 		string = fetchstring(pri, arg, PATH_MAX);
1028*7c478bd9Sstevel@tonic-gate 		if (string == NULL) {
1029*7c478bd9Sstevel@tonic-gate 			(void) sprintf(badaddr, "BadAddress:0x%.8lX", arg);
1030*7c478bd9Sstevel@tonic-gate 			string = badaddr;
1031*7c478bd9Sstevel@tonic-gate 		}
1032*7c478bd9Sstevel@tonic-gate 		if ((leng += strlen(string)) < 63) {
1033*7c478bd9Sstevel@tonic-gate 			(void) fputc(' ', stdout);
1034*7c478bd9Sstevel@tonic-gate 			leng++;
1035*7c478bd9Sstevel@tonic-gate 		} else {
1036*7c478bd9Sstevel@tonic-gate 			(void) fputc('\n', stdout);
1037*7c478bd9Sstevel@tonic-gate 			leng = 0;
1038*7c478bd9Sstevel@tonic-gate 			putpname(pri);
1039*7c478bd9Sstevel@tonic-gate 			(void) fputs("  ", stdout);
1040*7c478bd9Sstevel@tonic-gate 			leng += 2 + strlen(string);
1041*7c478bd9Sstevel@tonic-gate 		}
1042*7c478bd9Sstevel@tonic-gate 		(void) fputs(string, stdout);
1043*7c478bd9Sstevel@tonic-gate 	}
1044*7c478bd9Sstevel@tonic-gate 	(void) fputc('\n', stdout);
1045*7c478bd9Sstevel@tonic-gate }
1046*7c478bd9Sstevel@tonic-gate 
1047*7c478bd9Sstevel@tonic-gate /*
1048*7c478bd9Sstevel@tonic-gate  * Display contents of read() or write() buffer.
1049*7c478bd9Sstevel@tonic-gate  */
1050*7c478bd9Sstevel@tonic-gate void
1051*7c478bd9Sstevel@tonic-gate showbuffer(private_t *pri, long offset, long count)
1052*7c478bd9Sstevel@tonic-gate {
1053*7c478bd9Sstevel@tonic-gate 	char buffer[320];
1054*7c478bd9Sstevel@tonic-gate 	int nbytes;
1055*7c478bd9Sstevel@tonic-gate 	char *buf;
1056*7c478bd9Sstevel@tonic-gate 	int n;
1057*7c478bd9Sstevel@tonic-gate 
1058*7c478bd9Sstevel@tonic-gate 	while (count > 0 && !interrupt) {
1059*7c478bd9Sstevel@tonic-gate 		nbytes = (count < sizeof (buffer))? count : sizeof (buffer);
1060*7c478bd9Sstevel@tonic-gate 		if ((nbytes = Pread(Proc, buffer, nbytes, offset)) <= 0)
1061*7c478bd9Sstevel@tonic-gate 			break;
1062*7c478bd9Sstevel@tonic-gate 		count -= nbytes;
1063*7c478bd9Sstevel@tonic-gate 		offset += nbytes;
1064*7c478bd9Sstevel@tonic-gate 		buf = buffer;
1065*7c478bd9Sstevel@tonic-gate 		while (nbytes > 0 && !interrupt) {
1066*7c478bd9Sstevel@tonic-gate 			char obuf[65];
1067*7c478bd9Sstevel@tonic-gate 
1068*7c478bd9Sstevel@tonic-gate 			n = (nbytes < 32)? nbytes : 32;
1069*7c478bd9Sstevel@tonic-gate 			showbytes(buf, n, obuf);
1070*7c478bd9Sstevel@tonic-gate 
1071*7c478bd9Sstevel@tonic-gate 			putpname(pri);
1072*7c478bd9Sstevel@tonic-gate 			(void) fputs("  ", stdout);
1073*7c478bd9Sstevel@tonic-gate 			(void) fputs(obuf, stdout);
1074*7c478bd9Sstevel@tonic-gate 			(void) fputc('\n', stdout);
1075*7c478bd9Sstevel@tonic-gate 			nbytes -= n;
1076*7c478bd9Sstevel@tonic-gate 			buf += n;
1077*7c478bd9Sstevel@tonic-gate 		}
1078*7c478bd9Sstevel@tonic-gate 	}
1079*7c478bd9Sstevel@tonic-gate }
1080*7c478bd9Sstevel@tonic-gate 
1081*7c478bd9Sstevel@tonic-gate void
1082*7c478bd9Sstevel@tonic-gate showbytes(const char *buf, int n, char *obuf)
1083*7c478bd9Sstevel@tonic-gate {
1084*7c478bd9Sstevel@tonic-gate 	int c;
1085*7c478bd9Sstevel@tonic-gate 
1086*7c478bd9Sstevel@tonic-gate 	while (--n >= 0) {
1087*7c478bd9Sstevel@tonic-gate 		int c1 = '\\';
1088*7c478bd9Sstevel@tonic-gate 		int c2;
1089*7c478bd9Sstevel@tonic-gate 
1090*7c478bd9Sstevel@tonic-gate 		switch (c = (*buf++ & 0xff)) {
1091*7c478bd9Sstevel@tonic-gate 		case '\0':
1092*7c478bd9Sstevel@tonic-gate 			c2 = '0';
1093*7c478bd9Sstevel@tonic-gate 			break;
1094*7c478bd9Sstevel@tonic-gate 		case '\b':
1095*7c478bd9Sstevel@tonic-gate 			c2 = 'b';
1096*7c478bd9Sstevel@tonic-gate 			break;
1097*7c478bd9Sstevel@tonic-gate 		case '\t':
1098*7c478bd9Sstevel@tonic-gate 			c2 = 't';
1099*7c478bd9Sstevel@tonic-gate 			break;
1100*7c478bd9Sstevel@tonic-gate 		case '\n':
1101*7c478bd9Sstevel@tonic-gate 			c2 = 'n';
1102*7c478bd9Sstevel@tonic-gate 			break;
1103*7c478bd9Sstevel@tonic-gate 		case '\v':
1104*7c478bd9Sstevel@tonic-gate 			c2 = 'v';
1105*7c478bd9Sstevel@tonic-gate 			break;
1106*7c478bd9Sstevel@tonic-gate 		case '\f':
1107*7c478bd9Sstevel@tonic-gate 			c2 = 'f';
1108*7c478bd9Sstevel@tonic-gate 			break;
1109*7c478bd9Sstevel@tonic-gate 		case '\r':
1110*7c478bd9Sstevel@tonic-gate 			c2 = 'r';
1111*7c478bd9Sstevel@tonic-gate 			break;
1112*7c478bd9Sstevel@tonic-gate 		default:
1113*7c478bd9Sstevel@tonic-gate 			if (isprint(c)) {
1114*7c478bd9Sstevel@tonic-gate 				c1 = ' ';
1115*7c478bd9Sstevel@tonic-gate 				c2 = c;
1116*7c478bd9Sstevel@tonic-gate 			} else {
1117*7c478bd9Sstevel@tonic-gate 				c1 = c>>4;
1118*7c478bd9Sstevel@tonic-gate 				c1 += (c1 < 10)? '0' : 'A'-10;
1119*7c478bd9Sstevel@tonic-gate 				c2 = c&0xf;
1120*7c478bd9Sstevel@tonic-gate 				c2 += (c2 < 10)? '0' : 'A'-10;
1121*7c478bd9Sstevel@tonic-gate 			}
1122*7c478bd9Sstevel@tonic-gate 			break;
1123*7c478bd9Sstevel@tonic-gate 		}
1124*7c478bd9Sstevel@tonic-gate 		*obuf++ = (char)c1;
1125*7c478bd9Sstevel@tonic-gate 		*obuf++ = (char)c2;
1126*7c478bd9Sstevel@tonic-gate 	}
1127*7c478bd9Sstevel@tonic-gate 
1128*7c478bd9Sstevel@tonic-gate 	*obuf = '\0';
1129*7c478bd9Sstevel@tonic-gate }
1130