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