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