Home | History | Annotate | Download | only in truss
      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 2009 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 	/* fetch and remember first argument if it's a string */
    392 	pri->sys_valid = FALSE;
    393 	if (nargs > 0 && stp->arg[0] == STG) {
    394 		long offset;
    395 		uint32_t offset32;
    396 
    397 		/*
    398 		 * Special case for exit from exec().
    399 		 * The address in pri->sys_args[0] refers to the old process
    400 		 * image.  We must fetch the string from the new image.
    401 		 */
    402 		if (Lsp->pr_why == PR_SYSEXIT &&
    403 		    (Lsp->pr_what == SYS_execve ||
    404 		    Lsp->pr_what == SYS_exec)) {
    405 			psinfo_t psinfo;
    406 			long argv;
    407 			auxv_t auxv[32];
    408 			int naux;
    409 
    410 			offset = 0;
    411 			naux = proc_get_auxv(pid, auxv, 32);
    412 			for (i = 0; i < naux; i++) {
    413 				if (auxv[i].a_type == AT_SUN_EXECNAME) {
    414 					offset = (long)auxv[i].a_un.a_ptr;
    415 					break;
    416 				}
    417 			}
    418 			if (offset == 0 &&
    419 			    proc_get_psinfo(pid, &psinfo) == 0) {
    420 				argv = (long)psinfo.pr_argv;
    421 				if (data_model == PR_MODEL_LP64)
    422 					(void) Pread(Proc, &offset,
    423 					    sizeof (offset), argv);
    424 				else {
    425 					offset32 = 0;
    426 					(void) Pread(Proc, &offset32,
    427 					    sizeof (offset32), argv);
    428 					offset = offset32;
    429 				}
    430 			}
    431 		} else {
    432 			offset = pri->sys_args[0];
    433 		}
    434 		if ((s = fetchstring(pri, offset, PATH_MAX)) != NULL) {
    435 			pri->sys_valid = TRUE;
    436 			len = strlen(s);
    437 			/* reallocate if necessary */
    438 			while (len >= pri->sys_psize) {
    439 				free(pri->sys_path);
    440 				pri->sys_path = my_malloc(pri->sys_psize *= 2,
    441 				    "pathname buffer");
    442 			}
    443 			(void) strcpy(pri->sys_path, s); /* remember pathname */
    444 		}
    445 	}
    446 
    447 	istraced = dotrace && prismember(&trace, what);
    448 	raw = prismember(&rawout, what);
    449 
    450 	/* force tracing of read/write buffer dump syscalls */
    451 	if (!istraced && nargs > 2) {
    452 		int fdp1 = (int)pri->sys_args[0] + 1;
    453 
    454 		if (ISREAD(what)) {
    455 			if (prismember(&readfd, fdp1))
    456 				istraced = TRUE;
    457 		} else if (ISWRITE(what)) {
    458 			if (prismember(&writefd, fdp1))
    459 				istraced = TRUE;
    460 		}
    461 	}
    462 
    463 	pri->sys_leng = 0;
    464 	if (cflag || !istraced)		/* just counting */
    465 		*pri->sys_string = 0;
    466 	else {
    467 		int argprinted = FALSE;
    468 		const char *name;
    469 
    470 		name = sysname(pri, what, raw? -1 : subcode);
    471 		grow(pri, strlen(name) + 1);
    472 		pri->sys_leng = snprintf(pri->sys_string, pri->sys_ssize,
    473 		    "%s(", name);
    474 		for (i = 0; i < nargs; i++) {
    475 			arg = pri->sys_args[i];
    476 			x = stp->arg[i];
    477 
    478 			if (x == STG && !raw &&
    479 			    i == 0 && pri->sys_valid) {	/* already fetched */
    480 				escape_string(pri, pri->sys_path);
    481 				argprinted = TRUE;
    482 			} else if (x != HID || raw) {
    483 				if (argprinted)
    484 					outstring(pri, ", ");
    485 				if (x == LLO)
    486 					(*Print[x])(pri, raw, arg,
    487 					    pri->sys_args[++i]);
    488 				else
    489 					(*Print[x])(pri, raw, arg);
    490 				/*
    491 				 * if nothing printed, then don't print ", "
    492 				 */
    493 				if (x == NOV)
    494 					argprinted = FALSE;
    495 				else
    496 					argprinted = TRUE;
    497 			}
    498 		}
    499 		outstring(pri, ")");
    500 	}
    501 
    502 	return (istraced);
    503 }
    504 #undef	ISREAD
    505 #undef	ISWRITE
    506 
    507 /*
    508  * sysexit() returns non-zero if anything was printed.
    509  */
    510 int
    511 sysexit(private_t *pri, int dotrace)
    512 {
    513 	const lwpstatus_t *Lsp = pri->lwpstat;
    514 	int what = Lsp->pr_what;
    515 	struct syscount *scp;
    516 	const struct systable *stp;
    517 	int subcode;
    518 	int istraced;
    519 	int raw;
    520 
    521 	/* protect ourself from operating system error */
    522 	if (what <= 0 || what > PRMAXSYS)
    523 		return (0);
    524 
    525 	/*
    526 	 * If we aren't supposed to be tracing this one, then
    527 	 * delete it from the traced signal set.  We got here
    528 	 * because the process was sleeping in an untraced syscall.
    529 	 */
    530 	if (!prismember(&traceeven, what)) {
    531 		(void) Psysexit(Proc, what, FALSE);
    532 		return (0);
    533 	}
    534 
    535 	/* pick up registers & set pri->Errno before anything else */
    536 	pri->Errno = Lsp->pr_errno;
    537 	pri->ErrPriv = Lsp->pr_errpriv;
    538 	pri->Rval1 = Lsp->pr_rval1;
    539 	pri->Rval2 = Lsp->pr_rval2;
    540 
    541 	switch (what) {
    542 	case SYS_exit:		/* these are traced on entry */
    543 	case SYS_lwp_exit:
    544 	case SYS_evtrapret:
    545 	case SYS_context:
    546 		istraced = dotrace && prismember(&trace, what);
    547 		break;
    548 	case SYS_exec:		/* these are normally traced on entry */
    549 	case SYS_execve:
    550 		istraced = dotrace && prismember(&trace, what);
    551 		if (pri->exec_string && *pri->exec_string) {
    552 			if (!cflag && istraced) { /* print exec() string now */
    553 				if (pri->exec_pname[0] != '\0')
    554 					(void) fputs(pri->exec_pname, stdout);
    555 				timestamp(pri);
    556 				(void) fputs(pri->exec_string, stdout);
    557 			}
    558 			pri->exec_pname[0] = '\0';
    559 			pri->exec_string[0] = '\0';
    560 			break;
    561 		}
    562 		/* FALLTHROUGH */
    563 	default:
    564 		/* we called sysentry() in main() for these */
    565 		if (what == SYS_open || what == SYS_open64)
    566 			istraced = dotrace && prismember(&trace, what);
    567 		else
    568 			istraced = sysentry(pri, dotrace) && dotrace;
    569 		pri->length = 0;
    570 		if (!cflag && istraced) {
    571 			putpname(pri);
    572 			timestamp(pri);
    573 			pri->length += printf("%s", pri->sys_string);
    574 		}
    575 		pri->sys_leng = 0;
    576 		*pri->sys_string = '\0';
    577 		break;
    578 	}
    579 
    580 	/* get systable entry for this syscall */
    581 	subcode = getsubcode(pri);
    582 	stp = subsys(what, subcode);
    583 
    584 	if (cflag && istraced) {
    585 		(void) mutex_lock(&count_lock);
    586 		scp = Cp->syscount[what];
    587 		if (what == SYS_forksys && subcode >= 3)
    588 			scp += subcode - 3;
    589 		else if (subcode != -1 &&
    590 		    (what != SYS_open && what != SYS_open64 &&
    591 		    what != SYS_lwp_create))
    592 			scp += subcode;
    593 		scp->count++;
    594 		accumulate(&scp->stime, &Lsp->pr_stime, &pri->syslast);
    595 		accumulate(&Cp->usrtotal, &Lsp->pr_utime, &pri->usrlast);
    596 		pri->syslast = Lsp->pr_stime;
    597 		pri->usrlast = Lsp->pr_utime;
    598 		(void) mutex_unlock(&count_lock);
    599 	}
    600 
    601 	raw = prismember(&rawout, what);
    602 
    603 	if (!cflag && istraced) {
    604 		if ((what == SYS_forkall ||
    605 		    what == SYS_vfork ||
    606 		    what == SYS_fork1 ||
    607 		    what == SYS_forksys) &&
    608 		    pri->Errno == 0 && pri->Rval2 != 0) {
    609 			pri->length &= ~07;
    610 			if (strlen(sysname(pri, what, raw? -1 : subcode)) < 6) {
    611 				(void) fputc('\t', stdout);
    612 				pri->length += 8;
    613 			}
    614 			pri->length +=
    615 			    7 + printf("\t(returning as child ...)");
    616 		}
    617 		if (what == SYS_lwp_create &&
    618 		    pri->Errno == 0 && pri->Rval1 == 0) {
    619 			pri->length &= ~07;
    620 			pri->length +=
    621 			    7 + printf("\t(returning as new lwp ...)");
    622 		}
    623 		if (pri->Errno != 0 ||
    624 		    (what != SYS_exec && what != SYS_execve)) {
    625 			/* prepare to print the return code */
    626 			pri->length >>= 3;
    627 			if (pri->length >= 6)
    628 				(void) fputc(' ', stdout);
    629 			for (; pri->length < 6; pri->length++)
    630 				(void) fputc('\t', stdout);
    631 		}
    632 	}
    633 	pri->length = 0;
    634 
    635 	if (pri->Errno != 0) {		/* error in syscall */
    636 		if (istraced) {
    637 			if (cflag)
    638 				scp->error++;
    639 			else {
    640 				const char *ename = errname(pri->Errno);
    641 				const char *privname;
    642 
    643 				(void) printf("Err#%d", pri->Errno);
    644 				if (ename != NULL) {
    645 					(void) fputc(' ', stdout);
    646 					(void) fputs(ename, stdout);
    647 				}
    648 				switch (pri->ErrPriv) {
    649 				case PRIV_NONE:
    650 					privname = NULL;
    651 					break;
    652 				case PRIV_ALL:
    653 					privname = "ALL";
    654 					break;
    655 				case PRIV_MULTIPLE:
    656 					privname = "MULTIPLE";
    657 					break;
    658 				case PRIV_ALLZONE:
    659 					privname = "ZONE";
    660 					break;
    661 				default:
    662 					privname = priv_getbynum(pri->ErrPriv);
    663 					break;
    664 				}
    665 				if (privname != NULL)
    666 					(void) printf(" [%s]", privname);
    667 
    668 				(void) fputc('\n', stdout);
    669 			}
    670 		}
    671 	} else {
    672 		/* show arguments on successful exec */
    673 		if (what == SYS_exec || what == SYS_execve) {
    674 			if (!cflag && istraced)
    675 				showargs(pri, raw);
    676 		} else if (!cflag && istraced) {
    677 			const char *fmt = NULL;
    678 			long rv1 = pri->Rval1;
    679 			long rv2 = pri->Rval2;
    680 
    681 #ifdef _LP64
    682 			/*
    683 			 * 32-bit system calls return 32-bit values. We
    684 			 * later mask out the upper bits if we want to
    685 			 * print these as unsigned values.
    686 			 */
    687 			if (data_model == PR_MODEL_ILP32) {
    688 				rv1 = (int)rv1;
    689 				rv2 = (int)rv2;
    690 			}
    691 #endif
    692 
    693 			switch (what) {
    694 			case SYS_llseek:
    695 				rv1 &= 0xffffffff;
    696 				rv2 &= 0xffffffff;
    697 #ifdef _LONG_LONG_LTOH	/* first long of a longlong is the low order */
    698 				if (rv2 != 0) {
    699 					long temp = rv1;
    700 					fmt = "= 0x%lX%.8lX";
    701 					rv1 = rv2;
    702 					rv2 = temp;
    703 					break;
    704 				}
    705 #else	/* the other way around */
    706 				if (rv1 != 0) {
    707 					fmt = "= 0x%lX%.8lX";
    708 					break;
    709 				}
    710 				rv1 = rv2;	/* ugly */
    711 #endif
    712 				/* FALLTHROUGH */
    713 			case SYS_lseek:
    714 			case SYS_ulimit:
    715 				if (rv1 & 0xff000000) {
    716 #ifdef _LP64
    717 					if (data_model == PR_MODEL_ILP32)
    718 						rv1 &= 0xffffffff;
    719 #endif
    720 					fmt = "= 0x%.8lX";
    721 				}
    722 				break;
    723 			case SYS_sigtimedwait:
    724 				if (raw)
    725 					/* EMPTY */;
    726 				else if ((fmt = rawsigname(pri, rv1)) != NULL) {
    727 					rv1 = (long)fmt;	/* filthy */
    728 					fmt = "= %s";
    729 				}
    730 				break;
    731 			case SYS_port:
    732 #ifdef _LP64
    733 				if (data_model == PR_MODEL_LP64) {
    734 					rv2 = rv1 & 0xffffffff;
    735 					rv1 = rv1 >> 32;
    736 				}
    737 #endif
    738 				break;
    739 			}
    740 
    741 			if (fmt == NULL) {
    742 				switch (stp->rval[0]) {
    743 				case HEX:
    744 #ifdef _LP64
    745 					if (data_model == PR_MODEL_ILP32)
    746 						rv1 &= 0xffffffff;
    747 #endif
    748 					fmt = "= 0x%.8lX";
    749 					break;
    750 				case HHX:
    751 #ifdef _LP64
    752 					if (data_model == PR_MODEL_ILP32)
    753 						rv1 &= 0xffffffff;
    754 #endif
    755 					fmt = "= 0x%.4lX";
    756 					break;
    757 				case OCT:
    758 #ifdef _LP64
    759 					if (data_model == PR_MODEL_ILP32)
    760 						rv1 &= 0xffffffff;
    761 #endif
    762 					fmt = "= %#lo";
    763 					break;
    764 				case UNS:
    765 #ifdef _LP64
    766 					if (data_model == PR_MODEL_ILP32)
    767 						rv1 &= 0xffffffff;
    768 #endif
    769 					fmt = "= %lu";
    770 					break;
    771 				default:
    772 					fmt = "= %ld";
    773 					break;
    774 				}
    775 			}
    776 
    777 			(void) printf(fmt, rv1, rv2);
    778 
    779 			switch (stp->rval[1]) {
    780 			case NOV:
    781 				fmt = NULL;
    782 				break;
    783 			case HEX:
    784 #ifdef _LP64
    785 				if (data_model == PR_MODEL_ILP32)
    786 					rv2 &= 0xffffffff;
    787 #endif
    788 				fmt = " [0x%.8lX]";
    789 				break;
    790 			case HHX:
    791 #ifdef _LP64
    792 				if (data_model == PR_MODEL_ILP32)
    793 					rv2 &= 0xffffffff;
    794 #endif
    795 				fmt = " [0x%.4lX]";
    796 				break;
    797 			case OCT:
    798 #ifdef _LP64
    799 				if (data_model == PR_MODEL_ILP32)
    800 					rv2 &= 0xffffffff;
    801 #endif
    802 				fmt = " [%#lo]";
    803 				break;
    804 			case UNS:
    805 #ifdef _LP64
    806 				if (data_model == PR_MODEL_ILP32)
    807 					rv2 &= 0xffffffff;
    808 #endif
    809 				fmt = " [%lu]";
    810 				break;
    811 			default:
    812 				fmt = " [%ld]";
    813 				break;
    814 			}
    815 
    816 			if (fmt != NULL)
    817 				(void) printf(fmt, rv2);
    818 			(void) fputc('\n', stdout);
    819 		}
    820 
    821 		if (what == SYS_forkall ||
    822 		    what == SYS_vfork ||
    823 		    what == SYS_fork1 ||
    824 		    what == SYS_forksys) {
    825 			if (pri->Rval2 == 0)		/* child was created */
    826 				pri->child = pri->Rval1;
    827 			else if (cflag && istraced)	/* this is the child */
    828 				scp->count--;
    829 		}
    830 		if (what == SYS_lwp_create && pri->Rval1 == 0 &&
    831 		    cflag && istraced)		/* this is the created lwp */
    832 			scp->count--;
    833 	}
    834 
    835 #define	ISREAD(code) \
    836 	((code) == SYS_read || (code) == SYS_pread || (code) == SYS_pread64 || \
    837 	(code) == SYS_recv || (code) == SYS_recvfrom)
    838 #define	ISWRITE(code) \
    839 	((code) == SYS_write || (code) == SYS_pwrite || \
    840 	(code) == SYS_pwrite64 || (code) == SYS_send || (code) == SYS_sendto)
    841 
    842 	if (!cflag && istraced) {
    843 		int fdp1 = (int)pri->sys_args[0] + 1; /* filedescriptor + 1 */
    844 
    845 		if (raw) {
    846 			if (what != SYS_exec && what != SYS_execve)
    847 				showpaths(pri, stp);
    848 			if (ISREAD(what) || ISWRITE(what)) {
    849 				if (pri->iob_buf[0] != '\0')
    850 					(void) printf("%s     0x%.8lX: %s\n",
    851 					    pri->pname, pri->sys_args[1],
    852 					    pri->iob_buf);
    853 			}
    854 		}
    855 
    856 		/*
    857 		 * Show buffer contents for read()/pread() or write()/pwrite().
    858 		 * IOBSIZE bytes have already been shown;
    859 		 * don't show them again unless there's more.
    860 		 */
    861 		if ((ISREAD(what) && pri->Errno == 0 &&
    862 		    prismember(&readfd, fdp1)) ||
    863 		    (ISWRITE(what) && prismember(&writefd, fdp1))) {
    864 			long nb = ISWRITE(what) ? pri->sys_args[2] : pri->Rval1;
    865 
    866 			if (nb > IOBSIZE) {
    867 				/* enter region of lengthy output */
    868 				if (nb > MYBUFSIZ / 4)
    869 					Eserialize();
    870 
    871 				showbuffer(pri, pri->sys_args[1], nb);
    872 
    873 				/* exit region of lengthy output */
    874 				if (nb > MYBUFSIZ / 4)
    875 					Xserialize();
    876 			}
    877 		}
    878 #undef	ISREAD
    879 #undef	ISWRITE
    880 		/*
    881 		 * Do verbose interpretation if requested.
    882 		 * If buffer contents for read or write have been requested and
    883 		 * this is a readv() or writev(), force verbose interpretation.
    884 		 */
    885 		if (prismember(&verbose, what) ||
    886 		    ((what == SYS_readv || what == SYS_recvmsg) &&
    887 		    pri->Errno == 0 && prismember(&readfd, fdp1)) ||
    888 		    ((what == SYS_writev || what == SYS_sendfilev ||
    889 		    what == SYS_sendmsg) &&
    890 		    prismember(&writefd, fdp1)))
    891 			expound(pri, pri->Rval1, raw);
    892 	}
    893 
    894 	return (!cflag && istraced);
    895 }
    896 
    897 void
    898 showpaths(private_t *pri, const struct systable *stp)
    899 {
    900 	int i;
    901 
    902 	for (i = 0; i < pri->sys_nargs; i++) {
    903 		if ((stp->arg[i] == STG) ||
    904 		    (stp->arg[i] == RST && !pri->Errno) ||
    905 		    (stp->arg[i] == RLK && !pri->Errno && pri->Rval1 > 0)) {
    906 			long addr = pri->sys_args[i];
    907 			int maxleng =
    908 			    (stp->arg[i] == RLK)? (int)pri->Rval1 : PATH_MAX;
    909 			char *s;
    910 
    911 			if (i == 0 && pri->sys_valid)	/* already fetched */
    912 				s = pri->sys_path;
    913 			else
    914 				s = fetchstring(pri, addr,
    915 				    maxleng > PATH_MAX ? PATH_MAX : maxleng);
    916 
    917 			if (s != (char *)NULL)
    918 				(void) printf("%s     0x%.8lX: \"%s\"\n",
    919 				    pri->pname, addr, s);
    920 		}
    921 	}
    922 }
    923 
    924 /*
    925  * Display arguments to successful exec().
    926  */
    927 void
    928 showargs(private_t *pri, int raw)
    929 {
    930 	const lwpstatus_t *Lsp = pri->lwpstat;
    931 	int nargs;
    932 	long ap;
    933 	int ptrsize;
    934 	int fail;
    935 
    936 	pri->length = 0;
    937 	ptrsize = (data_model == PR_MODEL_LP64)? 8 : 4;
    938 
    939 #if defined(__i386) || defined(__amd64)	/* XX64 */
    940 	ap = (long)Lsp->pr_reg[R_SP];
    941 	fail = (Pread(Proc, &nargs, sizeof (nargs), ap) != sizeof (nargs));
    942 	ap += ptrsize;
    943 #endif /* i386 */
    944 
    945 #if sparc
    946 	if (data_model == PR_MODEL_LP64) {
    947 		int64_t xnargs;
    948 		ap = (long)(Lsp->pr_reg[R_SP]) + 16 * sizeof (int64_t)
    949 		    + STACK_BIAS;
    950 		fail = (Pread(Proc, &xnargs, sizeof (xnargs), ap) !=
    951 		    sizeof (xnargs));
    952 		nargs = (int)xnargs;
    953 	} else {
    954 		ap = (long)(Lsp->pr_reg[R_SP]) + 16 * sizeof (int32_t);
    955 		fail = (Pread(Proc, &nargs, sizeof (nargs), ap) !=
    956 		    sizeof (nargs));
    957 	}
    958 	ap += ptrsize;
    959 #endif /* sparc */
    960 
    961 	if (fail) {
    962 		(void) printf("\n%s\t*** Bad argument list? ***\n", pri->pname);
    963 		return;
    964 	}
    965 
    966 	(void) printf("  argc = %d\n", nargs);
    967 	if (raw)
    968 		showpaths(pri, &systable[SYS_exec]);
    969 
    970 	show_cred(pri, FALSE);
    971 
    972 	if (aflag || eflag) {		/* dump args or environment */
    973 
    974 		/* enter region of (potentially) lengthy output */
    975 		Eserialize();
    976 
    977 		if (aflag)		/* dump the argument list */
    978 			dumpargs(pri, ap, "argv:");
    979 		ap += (nargs+1) * ptrsize;
    980 		if (eflag)		/* dump the environment */
    981 			dumpargs(pri, ap, "envp:");
    982 
    983 		/* exit region of lengthy output */
    984 		Xserialize();
    985 	}
    986 }
    987 
    988 void
    989 dumpargs(private_t *pri, long ap, const char *str)
    990 {
    991 	char *string;
    992 	unsigned int leng = 0;
    993 	int ptrsize;
    994 	long arg = 0;
    995 	char *argaddr;
    996 	char badaddr[32];
    997 
    998 	if (interrupt)
    999 		return;
   1000 
   1001 #ifdef _LP64
   1002 	if (data_model == PR_MODEL_LP64) {
   1003 		argaddr = (char *)&arg;
   1004 		ptrsize = 8;
   1005 	} else {
   1006 #if defined(_LITTLE_ENDIAN)
   1007 		argaddr = (char *)&arg;
   1008 #else
   1009 		argaddr = (char *)&arg + 4;
   1010 #endif
   1011 		ptrsize = 4;
   1012 	}
   1013 #else
   1014 	argaddr = (char *)&arg;
   1015 	ptrsize = 4;
   1016 #endif
   1017 	putpname(pri);
   1018 	(void) fputc(' ', stdout);
   1019 	(void) fputs(str, stdout);
   1020 	leng += 1 + strlen(str);
   1021 
   1022 	while (!interrupt) {
   1023 		if (Pread(Proc, argaddr, ptrsize, ap) != ptrsize) {
   1024 			(void) printf("\n%s\t*** Bad argument list? ***\n",
   1025 			    pri->pname);
   1026 			return;
   1027 		}
   1028 		ap += ptrsize;
   1029 
   1030 		if (arg == 0)
   1031 			break;
   1032 		string = fetchstring(pri, arg, PATH_MAX);
   1033 		if (string == NULL) {
   1034 			(void) sprintf(badaddr, "BadAddress:0x%.8lX", arg);
   1035 			string = badaddr;
   1036 		}
   1037 		if ((leng += strlen(string)) < 63) {
   1038 			(void) fputc(' ', stdout);
   1039 			leng++;
   1040 		} else {
   1041 			(void) fputc('\n', stdout);
   1042 			leng = 0;
   1043 			putpname(pri);
   1044 			(void) fputs("  ", stdout);
   1045 			leng += 2 + strlen(string);
   1046 		}
   1047 		(void) fputs(string, stdout);
   1048 	}
   1049 	(void) fputc('\n', stdout);
   1050 }
   1051 
   1052 /*
   1053  * Display contents of read() or write() buffer.
   1054  */
   1055 void
   1056 showbuffer(private_t *pri, long offset, long count)
   1057 {
   1058 	char buffer[320];
   1059 	int nbytes;
   1060 	char *buf;
   1061 	int n;
   1062 
   1063 	while (count > 0 && !interrupt) {
   1064 		nbytes = (count < sizeof (buffer))? count : sizeof (buffer);
   1065 		if ((nbytes = Pread(Proc, buffer, nbytes, offset)) <= 0)
   1066 			break;
   1067 		count -= nbytes;
   1068 		offset += nbytes;
   1069 		buf = buffer;
   1070 		while (nbytes > 0 && !interrupt) {
   1071 			char obuf[65];
   1072 
   1073 			n = (nbytes < 32)? nbytes : 32;
   1074 			showbytes(buf, n, obuf);
   1075 
   1076 			putpname(pri);
   1077 			(void) fputs("  ", stdout);
   1078 			(void) fputs(obuf, stdout);
   1079 			(void) fputc('\n', stdout);
   1080 			nbytes -= n;
   1081 			buf += n;
   1082 		}
   1083 	}
   1084 }
   1085 
   1086 void
   1087 showbytes(const char *buf, int n, char *obuf)
   1088 {
   1089 	int c;
   1090 
   1091 	while (--n >= 0) {
   1092 		int c1 = '\\';
   1093 		int c2;
   1094 
   1095 		switch (c = (*buf++ & 0xff)) {
   1096 		case '\0':
   1097 			c2 = '0';
   1098 			break;
   1099 		case '\b':
   1100 			c2 = 'b';
   1101 			break;
   1102 		case '\t':
   1103 			c2 = 't';
   1104 			break;
   1105 		case '\n':
   1106 			c2 = 'n';
   1107 			break;
   1108 		case '\v':
   1109 			c2 = 'v';
   1110 			break;
   1111 		case '\f':
   1112 			c2 = 'f';
   1113 			break;
   1114 		case '\r':
   1115 			c2 = 'r';
   1116 			break;
   1117 		default:
   1118 			if (isprint(c)) {
   1119 				c1 = ' ';
   1120 				c2 = c;
   1121 			} else {
   1122 				c1 = c>>4;
   1123 				c1 += (c1 < 10)? '0' : 'A'-10;
   1124 				c2 = c&0xf;
   1125 				c2 += (c2 < 10)? '0' : 'A'-10;
   1126 			}
   1127 			break;
   1128 		}
   1129 		*obuf++ = (char)c1;
   1130 		*obuf++ = (char)c2;
   1131 	}
   1132 
   1133 	*obuf = '\0';
   1134 }
   1135