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