xref: /titanic_50/usr/src/cmd/truss/actions.c (revision d51e90740114c60620c0febffd4d3ce6e280a107)
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 2006 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 				default:
777 					fmt = "= %ld";
778 					break;
779 				}
780 			}
781 
782 			(void) printf(fmt, rv1, rv2);
783 
784 			switch (stp->rval[1]) {
785 			case NOV:
786 				fmt = NULL;
787 				break;
788 			case HEX:
789 #ifdef _LP64
790 				if (data_model == PR_MODEL_ILP32)
791 					rv2 &= 0xffffffff;
792 #endif
793 				fmt = " [0x%.8lX]";
794 				break;
795 			case HHX:
796 #ifdef _LP64
797 				if (data_model == PR_MODEL_ILP32)
798 					rv2 &= 0xffffffff;
799 #endif
800 				fmt = " [0x%.4lX]";
801 				break;
802 			case OCT:
803 #ifdef _LP64
804 				if (data_model == PR_MODEL_ILP32)
805 					rv2 &= 0xffffffff;
806 #endif
807 				fmt = " [%#lo]";
808 				break;
809 			default:
810 				fmt = " [%ld]";
811 				break;
812 			}
813 
814 			if (fmt != NULL)
815 				(void) printf(fmt, rv2);
816 			(void) fputc('\n', stdout);
817 		}
818 
819 		if (what == SYS_forkall ||
820 		    what == SYS_vfork ||
821 		    what == SYS_fork1 ||
822 		    what == SYS_forksys) {
823 			if (pri->Rval2 == 0)		/* child was created */
824 				pri->child = pri->Rval1;
825 			else if (cflag && istraced)	/* this is the child */
826 				scp->count--;
827 		}
828 		if (what == SYS_lwp_create && pri->Rval1 == 0 &&
829 		    cflag && istraced)		/* this is the created lwp */
830 			scp->count--;
831 	}
832 
833 #define	ISREAD(code) \
834 	((code) == SYS_read || (code) == SYS_pread || (code) == SYS_pread64 || \
835 	(code) == SYS_recv || (code) == SYS_recvfrom)
836 #define	ISWRITE(code) \
837 	((code) == SYS_write || (code) == SYS_pwrite || \
838 	(code) == SYS_pwrite64 || (code) == SYS_send || (code) == SYS_sendto)
839 
840 	if (!cflag && istraced) {
841 		int fdp1 = (int)pri->sys_args[0] + 1; /* filedescriptor + 1 */
842 
843 		if (raw) {
844 			if (what != SYS_exec && what != SYS_execve)
845 				showpaths(pri, stp);
846 			if (ISREAD(what) || ISWRITE(what)) {
847 				if (pri->iob_buf[0] != '\0')
848 					(void) printf("%s     0x%.8lX: %s\n",
849 						pri->pname, pri->sys_args[1],
850 						pri->iob_buf);
851 			}
852 		}
853 
854 		/*
855 		 * Show buffer contents for read()/pread() or write()/pwrite().
856 		 * IOBSIZE bytes have already been shown;
857 		 * don't show them again unless there's more.
858 		 */
859 		if ((ISREAD(what) && pri->Errno == 0 &&
860 		    prismember(&readfd, fdp1)) ||
861 		    (ISWRITE(what) && prismember(&writefd, fdp1))) {
862 			long nb = ISWRITE(what) ? pri->sys_args[2] : pri->Rval1;
863 
864 			if (nb > IOBSIZE) {
865 				/* enter region of lengthy output */
866 				if (nb > MYBUFSIZ / 4)
867 					Eserialize();
868 
869 				showbuffer(pri, pri->sys_args[1], nb);
870 
871 				/* exit region of lengthy output */
872 				if (nb > MYBUFSIZ / 4)
873 					Xserialize();
874 			}
875 		}
876 #undef	ISREAD
877 #undef	ISWRITE
878 		/*
879 		 * Do verbose interpretation if requested.
880 		 * If buffer contents for read or write have been requested and
881 		 * this is a readv() or writev(), force verbose interpretation.
882 		 */
883 		if (prismember(&verbose, what) ||
884 		    ((what == SYS_readv || what == SYS_recvmsg) &&
885 		    pri->Errno == 0 && prismember(&readfd, fdp1)) ||
886 		    ((what == SYS_writev || what == SYS_sendfilev ||
887 		    what == SYS_sendmsg) &&
888 		    prismember(&writefd, fdp1)))
889 			expound(pri, pri->Rval1, raw);
890 	}
891 
892 	return (!cflag && istraced);
893 }
894 
895 void
896 showpaths(private_t *pri, const struct systable *stp)
897 {
898 	int i;
899 
900 	for (i = 0; i < pri->sys_nargs; i++) {
901 		if ((stp->arg[i] == STG) ||
902 		    (stp->arg[i] == RST && !pri->Errno) ||
903 		    (stp->arg[i] == RLK && !pri->Errno && pri->Rval1 > 0)) {
904 			long addr = pri->sys_args[i];
905 			int maxleng =
906 			    (stp->arg[i] == RLK)? (int)pri->Rval1 : PATH_MAX;
907 			char *s;
908 
909 			if (i == 0 && pri->sys_valid)	/* already fetched */
910 				s = pri->sys_path;
911 			else
912 				s = fetchstring(pri, addr,
913 				    maxleng > PATH_MAX ? PATH_MAX : maxleng);
914 
915 			if (s != (char *)NULL)
916 				(void) printf("%s     0x%.8lX: \"%s\"\n",
917 					pri->pname, addr, s);
918 		}
919 	}
920 }
921 
922 /*
923  * Display arguments to successful exec().
924  */
925 void
926 showargs(private_t *pri, int raw)
927 {
928 	const lwpstatus_t *Lsp = pri->lwpstat;
929 	int nargs;
930 	long ap;
931 	int ptrsize;
932 	int fail;
933 
934 	pri->length = 0;
935 	ptrsize = (data_model == PR_MODEL_LP64)? 8 : 4;
936 
937 #if defined(__i386) || defined(__amd64)	/* XX64 */
938 	ap = (long)Lsp->pr_reg[R_SP];
939 	fail = (Pread(Proc, &nargs, sizeof (nargs), ap) != sizeof (nargs));
940 	ap += ptrsize;
941 #endif /* i386 */
942 
943 #if sparc
944 	if (data_model == PR_MODEL_LP64) {
945 		int64_t xnargs;
946 		ap = (long)(Lsp->pr_reg[R_SP]) + 16 * sizeof (int64_t)
947 			+ STACK_BIAS;
948 		fail = (Pread(Proc, &xnargs, sizeof (xnargs), ap) !=
949 			sizeof (xnargs));
950 		nargs = (int)xnargs;
951 	} else {
952 		ap = (long)(Lsp->pr_reg[R_SP]) + 16 * sizeof (int32_t);
953 		fail = (Pread(Proc, &nargs, sizeof (nargs), ap) !=
954 			sizeof (nargs));
955 	}
956 	ap += ptrsize;
957 #endif /* sparc */
958 
959 	if (fail) {
960 		(void) printf("\n%s\t*** Bad argument list? ***\n", pri->pname);
961 		return;
962 	}
963 
964 	(void) printf("  argc = %d\n", nargs);
965 	if (raw)
966 		showpaths(pri, &systable[SYS_exec]);
967 
968 	show_cred(pri, FALSE);
969 
970 	if (aflag || eflag) {		/* dump args or environment */
971 
972 		/* enter region of (potentially) lengthy output */
973 		Eserialize();
974 
975 		if (aflag)		/* dump the argument list */
976 			dumpargs(pri, ap, "argv:");
977 		ap += (nargs+1) * ptrsize;
978 		if (eflag)		/* dump the environment */
979 			dumpargs(pri, ap, "envp:");
980 
981 		/* exit region of lengthy output */
982 		Xserialize();
983 	}
984 }
985 
986 void
987 dumpargs(private_t *pri, long ap, const char *str)
988 {
989 	char *string;
990 	unsigned int leng = 0;
991 	int ptrsize;
992 	long arg = 0;
993 	char *argaddr;
994 	char badaddr[32];
995 
996 	if (interrupt)
997 		return;
998 
999 #ifdef _LP64
1000 	if (data_model == PR_MODEL_LP64) {
1001 		argaddr = (char *)&arg;
1002 		ptrsize = 8;
1003 	} else {
1004 #if defined(_LITTLE_ENDIAN)
1005 		argaddr = (char *)&arg;
1006 #else
1007 		argaddr = (char *)&arg + 4;
1008 #endif
1009 		ptrsize = 4;
1010 	}
1011 #else
1012 	argaddr = (char *)&arg;
1013 	ptrsize = 4;
1014 #endif
1015 	putpname(pri);
1016 	(void) fputc(' ', stdout);
1017 	(void) fputs(str, stdout);
1018 	leng += 1 + strlen(str);
1019 
1020 	while (!interrupt) {
1021 		if (Pread(Proc, argaddr, ptrsize, ap) != ptrsize) {
1022 			(void) printf("\n%s\t*** Bad argument list? ***\n",
1023 				pri->pname);
1024 			return;
1025 		}
1026 		ap += ptrsize;
1027 
1028 		if (arg == 0)
1029 			break;
1030 		string = fetchstring(pri, arg, PATH_MAX);
1031 		if (string == NULL) {
1032 			(void) sprintf(badaddr, "BadAddress:0x%.8lX", arg);
1033 			string = badaddr;
1034 		}
1035 		if ((leng += strlen(string)) < 63) {
1036 			(void) fputc(' ', stdout);
1037 			leng++;
1038 		} else {
1039 			(void) fputc('\n', stdout);
1040 			leng = 0;
1041 			putpname(pri);
1042 			(void) fputs("  ", stdout);
1043 			leng += 2 + strlen(string);
1044 		}
1045 		(void) fputs(string, stdout);
1046 	}
1047 	(void) fputc('\n', stdout);
1048 }
1049 
1050 /*
1051  * Display contents of read() or write() buffer.
1052  */
1053 void
1054 showbuffer(private_t *pri, long offset, long count)
1055 {
1056 	char buffer[320];
1057 	int nbytes;
1058 	char *buf;
1059 	int n;
1060 
1061 	while (count > 0 && !interrupt) {
1062 		nbytes = (count < sizeof (buffer))? count : sizeof (buffer);
1063 		if ((nbytes = Pread(Proc, buffer, nbytes, offset)) <= 0)
1064 			break;
1065 		count -= nbytes;
1066 		offset += nbytes;
1067 		buf = buffer;
1068 		while (nbytes > 0 && !interrupt) {
1069 			char obuf[65];
1070 
1071 			n = (nbytes < 32)? nbytes : 32;
1072 			showbytes(buf, n, obuf);
1073 
1074 			putpname(pri);
1075 			(void) fputs("  ", stdout);
1076 			(void) fputs(obuf, stdout);
1077 			(void) fputc('\n', stdout);
1078 			nbytes -= n;
1079 			buf += n;
1080 		}
1081 	}
1082 }
1083 
1084 void
1085 showbytes(const char *buf, int n, char *obuf)
1086 {
1087 	int c;
1088 
1089 	while (--n >= 0) {
1090 		int c1 = '\\';
1091 		int c2;
1092 
1093 		switch (c = (*buf++ & 0xff)) {
1094 		case '\0':
1095 			c2 = '0';
1096 			break;
1097 		case '\b':
1098 			c2 = 'b';
1099 			break;
1100 		case '\t':
1101 			c2 = 't';
1102 			break;
1103 		case '\n':
1104 			c2 = 'n';
1105 			break;
1106 		case '\v':
1107 			c2 = 'v';
1108 			break;
1109 		case '\f':
1110 			c2 = 'f';
1111 			break;
1112 		case '\r':
1113 			c2 = 'r';
1114 			break;
1115 		default:
1116 			if (isprint(c)) {
1117 				c1 = ' ';
1118 				c2 = c;
1119 			} else {
1120 				c1 = c>>4;
1121 				c1 += (c1 < 10)? '0' : 'A'-10;
1122 				c2 = c&0xf;
1123 				c2 += (c2 < 10)? '0' : 'A'-10;
1124 			}
1125 			break;
1126 		}
1127 		*obuf++ = (char)c1;
1128 		*obuf++ = (char)c2;
1129 	}
1130 
1131 	*obuf = '\0';
1132 }
1133