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