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