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