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