summaryrefslogtreecommitdiff
path: root/usr/src/cmd/truss
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/truss')
-rw-r--r--usr/src/cmd/truss/actions.c1135
-rw-r--r--usr/src/cmd/truss/codes.c2372
-rw-r--r--usr/src/cmd/truss/expound.c5605
-rw-r--r--usr/src/cmd/truss/fcall.c1911
-rw-r--r--usr/src/cmd/truss/htbl.c262
-rw-r--r--usr/src/cmd/truss/htbl.h95
-rw-r--r--usr/src/cmd/truss/ipc.c417
-rw-r--r--usr/src/cmd/truss/listopts.c661
-rw-r--r--usr/src/cmd/truss/main.c2718
-rw-r--r--usr/src/cmd/truss/print.c2850
-rw-r--r--usr/src/cmd/truss/print.h154
-rw-r--r--usr/src/cmd/truss/procset.c137
-rw-r--r--usr/src/cmd/truss/proto.h154
-rw-r--r--usr/src/cmd/truss/ramdata.c137
-rw-r--r--usr/src/cmd/truss/ramdata.h317
-rw-r--r--usr/src/cmd/truss/stat.c192
-rw-r--r--usr/src/cmd/truss/systable.c1736
-rw-r--r--usr/src/cmd/truss/systable.h74
18 files changed, 20927 insertions, 0 deletions
diff --git a/usr/src/cmd/truss/actions.c b/usr/src/cmd/truss/actions.c
new file mode 100644
index 0000000..52c75e5
--- /dev/null
+++ b/usr/src/cmd/truss/actions.c
@@ -0,0 +1,1135 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
+ */
+
+/* Copyright (c) 1988 AT&T */
+/* All Rights Reserved */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <string.h>
+#include <memory.h>
+#include <errno.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/stack.h>
+#include <signal.h>
+#include <sys/isa_defs.h>
+#include <libproc.h>
+#include <priv.h>
+#include "ramdata.h"
+#include "systable.h"
+#include "print.h"
+#include "proto.h"
+
+/*
+ * Actions to take when process stops.
+ */
+
+/*
+ * Function prototypes for static routines in this module.
+ */
+int stopsig(private_t *);
+void showpaths(private_t *, const struct systable *);
+void showargs(private_t *, int);
+void dumpargs(private_t *, long, const char *);
+
+/*
+ * Report an lwp to be sleeping (if true).
+ */
+void
+report_sleeping(private_t *pri, int dotrace)
+{
+ const lwpstatus_t *Lsp = pri->lwpstat;
+ int sys = Lsp->pr_syscall;
+
+ if (!prismember(&trace, sys) || !dotrace ||
+ !(Lsp->pr_flags & (PR_ASLEEP|PR_VFORKP))) {
+ /* Make sure we catch sysexit even if we're not tracing it. */
+ (void) Psysexit(Proc, sys, TRUE);
+ return;
+ }
+
+ pri->length = 0;
+ pri->Errno = 0;
+ pri->ErrPriv = PRIV_NONE;
+ pri->Rval1 = pri->Rval2 = 0;
+ (void) sysentry(pri, dotrace);
+ make_pname(pri, 0);
+ putpname(pri);
+ timestamp(pri);
+ pri->length += printf("%s", pri->sys_string);
+ pri->sys_leng = 0;
+ *pri->sys_string = '\0';
+ pri->length >>= 3;
+ if (Lsp->pr_flags & PR_VFORKP)
+ pri->length += 2;
+ if (pri->length >= 4)
+ (void) fputc(' ', stdout);
+ for (; pri->length < 4; pri->length++)
+ (void) fputc('\t', stdout);
+ if (Lsp->pr_flags & PR_VFORKP)
+ (void) fputs("(waiting for child to exit()/exec()...)\n",
+ stdout);
+ else
+ (void) fputs("(sleeping...)\n", stdout);
+ pri->length = 0;
+ if (prismember(&verbose, sys)) {
+ int raw = prismember(&rawout, sys);
+ pri->Errno = 1;
+ expound(pri, 0, raw);
+ pri->Errno = 0;
+ }
+ Flush();
+}
+
+/*
+ * requested() gets called for these reasons:
+ * flag == JOBSIG: report nothing; change state to JOBSTOP
+ * flag == JOBSTOP: report "Continued ..."
+ * default: report sleeping system call
+ *
+ * It returns a new flag: JOBSTOP or SLEEPING or 0.
+ */
+int
+requested(private_t *pri, int flag, int dotrace)
+{
+ const lwpstatus_t *Lsp = pri->lwpstat;
+ int sig = Lsp->pr_cursig;
+ int newflag = 0;
+
+ switch (flag) {
+ case JOBSIG:
+ return (JOBSTOP);
+
+ case JOBSTOP:
+ if (dotrace && !cflag && prismember(&signals, sig)) {
+ pri->length = 0;
+ putpname(pri);
+ timestamp(pri);
+ (void) printf(" Continued with signal #%d, %s",
+ sig, signame(pri, sig));
+ if (Lsp->pr_action.sa_handler == SIG_DFL)
+ (void) printf(" [default]");
+ else if (Lsp->pr_action.sa_handler == SIG_IGN)
+ (void) printf(" [ignored]");
+ else
+ (void) printf(" [caught]");
+ (void) fputc('\n', stdout);
+ Flush();
+ }
+ newflag = 0;
+ break;
+
+ default:
+ newflag = SLEEPING;
+ if (!cflag)
+ report_sleeping(pri, dotrace);
+ break;
+ }
+
+ return (newflag);
+}
+
+int
+jobcontrol(private_t *pri, int dotrace)
+{
+ const lwpstatus_t *Lsp = pri->lwpstat;
+ int sig = stopsig(pri);
+
+ if (sig == 0)
+ return (0);
+
+ if (dotrace && !cflag && /* not just counting */
+ prismember(&signals, sig)) { /* tracing this signal */
+ int sys;
+
+ pri->length = 0;
+ putpname(pri);
+ timestamp(pri);
+ (void) printf(" Stopped by signal #%d, %s",
+ sig, signame(pri, sig));
+ if ((Lsp->pr_flags & PR_ASLEEP) &&
+ (sys = Lsp->pr_syscall) > 0 && sys <= PRMAXSYS)
+ (void) printf(", in %s()",
+ sysname(pri, sys, getsubcode(pri)));
+ (void) fputc('\n', stdout);
+ Flush();
+ }
+
+ return (JOBSTOP);
+}
+
+/*
+ * Return the signal the process stopped on iff process is already stopped on
+ * PR_JOBCONTROL or is stopped on PR_SIGNALLED or PR_REQUESTED with a current
+ * signal that will cause a JOBCONTROL stop when the process is set running.
+ */
+int
+stopsig(private_t *pri)
+{
+ const lwpstatus_t *Lsp = pri->lwpstat;
+ int sig = 0;
+
+ if (Lsp->pr_flags & PR_STOPPED) {
+ switch (Lsp->pr_why) {
+ case PR_JOBCONTROL:
+ sig = Lsp->pr_what;
+ if (sig < 0 || sig > PRMAXSIG)
+ sig = 0;
+ break;
+ case PR_SIGNALLED:
+ case PR_REQUESTED:
+ if (Lsp->pr_action.sa_handler == SIG_DFL) {
+ switch (Lsp->pr_cursig) {
+ case SIGSTOP:
+ sig = SIGSTOP;
+ break;
+ case SIGTSTP:
+ case SIGTTIN:
+ case SIGTTOU:
+ if (!(Lsp->pr_flags & PR_ORPHAN))
+ sig = Lsp->pr_cursig;
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+ return (sig);
+}
+
+int
+signalled(private_t *pri, int flag, int dotrace)
+{
+ const lwpstatus_t *Lsp = pri->lwpstat;
+ int sig = Lsp->pr_what;
+
+ if (sig <= 0 || sig > PRMAXSIG) /* check bounds */
+ return (0);
+
+ if (dotrace && cflag) { /* just counting */
+ (void) mutex_lock(&count_lock);
+ Cp->sigcount[sig]++;
+ (void) mutex_unlock(&count_lock);
+ }
+
+ if (sig == SIGCONT && (flag == JOBSIG || flag == JOBSTOP))
+ flag = requested(pri, JOBSTOP, dotrace);
+ else if ((flag = jobcontrol(pri, dotrace)) == 0 &&
+ !cflag && dotrace &&
+ prismember(&signals, sig)) {
+ int sys;
+
+ pri->length = 0;
+ putpname(pri);
+ timestamp(pri);
+ (void) printf(" Received signal #%d, %s",
+ sig, signame(pri, sig));
+ if ((Lsp->pr_flags & PR_ASLEEP) &&
+ (sys = Lsp->pr_syscall) > 0 && sys <= PRMAXSYS)
+ (void) printf(", in %s()",
+ sysname(pri, sys, getsubcode(pri)));
+ if (Lsp->pr_action.sa_handler == SIG_DFL)
+ (void) printf(" [default]");
+ else if (Lsp->pr_action.sa_handler == SIG_IGN)
+ (void) printf(" [ignored]");
+ else
+ (void) printf(" [caught]");
+ (void) fputc('\n', stdout);
+ if (Lsp->pr_info.si_code != 0 ||
+ Lsp->pr_info.si_pid != 0)
+ print_siginfo(pri, &Lsp->pr_info);
+ Flush();
+ }
+
+ if (flag == JOBSTOP)
+ flag = JOBSIG;
+ return (flag);
+}
+
+int
+faulted(private_t *pri, int dotrace)
+{
+ const lwpstatus_t *Lsp = pri->lwpstat;
+ int flt = Lsp->pr_what;
+
+ if ((uint_t)flt > PRMAXFAULT || !prismember(&faults, flt) || !dotrace)
+ return (0);
+
+ (void) mutex_lock(&count_lock);
+ Cp->fltcount[flt]++;
+ (void) mutex_unlock(&count_lock);
+
+ if (cflag) /* just counting */
+ return (1);
+
+ pri->length = 0;
+ putpname(pri);
+ timestamp(pri);
+
+ (void) printf(" Incurred fault #%d, %s %%pc = 0x%.8lX",
+ flt, proc_fltname(flt, pri->flt_name, sizeof (pri->flt_name)),
+ (long)Lsp->pr_reg[R_PC]);
+
+ if (flt == FLTPAGE)
+ (void) printf(" addr = 0x%.8lX",
+ (long)Lsp->pr_info.si_addr);
+ (void) fputc('\n', stdout);
+ if (Lsp->pr_info.si_signo != 0)
+ print_siginfo(pri, &Lsp->pr_info);
+ Flush();
+ return (1);
+}
+
+/*
+ * Set up pri->sys_nargs and pri->sys_args[] (syscall args).
+ */
+void
+setupsysargs(private_t *pri, int what)
+{
+ const lwpstatus_t *Lsp = pri->lwpstat;
+ int nargs;
+ int i;
+
+#if sparc
+ /* determine whether syscall is indirect */
+ pri->sys_indirect = (Lsp->pr_reg[R_G1] == SYS_syscall)? 1 : 0;
+#else
+ pri->sys_indirect = 0;
+#endif
+
+ (void) memset(pri->sys_args, 0, sizeof (pri->sys_args));
+ if (what != Lsp->pr_syscall) { /* assertion */
+ (void) printf("%s\t*** Inconsistent syscall: %d vs %d ***\n",
+ pri->pname, what, Lsp->pr_syscall);
+ }
+ nargs = Lsp->pr_nsysarg;
+ for (i = 0;
+ i < nargs && i < sizeof (pri->sys_args) / sizeof (pri->sys_args[0]);
+ i++)
+ pri->sys_args[i] = Lsp->pr_sysarg[i];
+ pri->sys_nargs = nargs;
+}
+
+#define ISREAD(code) \
+ ((code) == SYS_read || (code) == SYS_pread || \
+ (code) == SYS_pread64 || (code) == SYS_readv || \
+ (code) == SYS_recv || (code) == SYS_recvfrom)
+#define ISWRITE(code) \
+ ((code) == SYS_write || (code) == SYS_pwrite || \
+ (code) == SYS_pwrite64 || (code) == SYS_writev || \
+ (code) == SYS_send || (code) == SYS_sendto)
+
+/*
+ * Return TRUE iff syscall is being traced.
+ */
+int
+sysentry(private_t *pri, int dotrace)
+{
+ pid_t pid = Pstatus(Proc)->pr_pid;
+ const lwpstatus_t *Lsp = pri->lwpstat;
+ long arg;
+ int nargs;
+ int i;
+ int x;
+ int len;
+ char *s;
+ const struct systable *stp;
+ int what = Lsp->pr_what;
+ int subcode;
+ int istraced;
+ int raw;
+
+ /* for reporting sleeping system calls */
+ if (what == 0 && (Lsp->pr_flags & (PR_ASLEEP|PR_VFORKP)))
+ what = Lsp->pr_syscall;
+
+ /* protect ourself from operating system error */
+ if (what <= 0 || what > PRMAXSYS)
+ what = 0;
+
+ /*
+ * Set up the system call arguments (pri->sys_nargs & pri->sys_args[]).
+ */
+ setupsysargs(pri, what);
+ nargs = pri->sys_nargs;
+
+ /* get systable entry for this syscall */
+ subcode = getsubcode(pri);
+ stp = subsys(what, subcode);
+
+ if (nargs > stp->nargs)
+ nargs = stp->nargs;
+ pri->sys_nargs = nargs;
+
+ /*
+ * Fetch and remember first argument if it's a string,
+ * or second argument if SYS_openat or SYS_openat64.
+ */
+ pri->sys_valid = FALSE;
+ if ((nargs > 0 && stp->arg[0] == STG) ||
+ (nargs > 1 && (what == SYS_openat || what == SYS_openat64))) {
+ long offset;
+ uint32_t offset32;
+
+ /*
+ * Special case for exit from exec().
+ * The address in pri->sys_args[0] refers to the old process
+ * image. We must fetch the string from the new image.
+ */
+ if (Lsp->pr_why == PR_SYSEXIT && what == SYS_execve) {
+ psinfo_t psinfo;
+ long argv;
+ auxv_t auxv[32];
+ int naux;
+
+ offset = 0;
+ naux = proc_get_auxv(pid, auxv, 32);
+ for (i = 0; i < naux; i++) {
+ if (auxv[i].a_type == AT_SUN_EXECNAME) {
+ offset = (long)auxv[i].a_un.a_ptr;
+ break;
+ }
+ }
+ if (offset == 0 &&
+ proc_get_psinfo(pid, &psinfo) == 0) {
+ argv = (long)psinfo.pr_argv;
+ if (data_model == PR_MODEL_LP64)
+ (void) Pread(Proc, &offset,
+ sizeof (offset), argv);
+ else {
+ offset32 = 0;
+ (void) Pread(Proc, &offset32,
+ sizeof (offset32), argv);
+ offset = offset32;
+ }
+ }
+ } else if (stp->arg[0] == STG) {
+ offset = pri->sys_args[0];
+ } else {
+ offset = pri->sys_args[1];
+ }
+ if ((s = fetchstring(pri, offset, PATH_MAX)) != NULL) {
+ pri->sys_valid = TRUE;
+ len = strlen(s);
+ /* reallocate if necessary */
+ while (len >= pri->sys_psize) {
+ free(pri->sys_path);
+ pri->sys_path = my_malloc(pri->sys_psize *= 2,
+ "pathname buffer");
+ }
+ (void) strcpy(pri->sys_path, s); /* remember pathname */
+ }
+ }
+
+ istraced = dotrace && prismember(&trace, what);
+ raw = prismember(&rawout, what);
+
+ /* force tracing of read/write buffer dump syscalls */
+ if (!istraced && nargs > 2) {
+ int fdp1 = (int)pri->sys_args[0] + 1;
+
+ if (ISREAD(what)) {
+ if (prismember(&readfd, fdp1))
+ istraced = TRUE;
+ } else if (ISWRITE(what)) {
+ if (prismember(&writefd, fdp1))
+ istraced = TRUE;
+ }
+ }
+
+ pri->sys_leng = 0;
+ if (cflag || !istraced) /* just counting */
+ *pri->sys_string = 0;
+ else {
+ int argprinted = FALSE;
+ const char *name;
+
+ name = sysname(pri, what, raw? -1 : subcode);
+ grow(pri, strlen(name) + 1);
+ pri->sys_leng = snprintf(pri->sys_string, pri->sys_ssize,
+ "%s(", name);
+ for (i = 0; i < nargs; i++) {
+ arg = pri->sys_args[i];
+ x = stp->arg[i];
+
+ if (!raw && pri->sys_valid &&
+ ((i == 0 && x == STG) ||
+ (i == 1 && (what == SYS_openat ||
+ what == SYS_openat64)))) { /* already fetched */
+ if (argprinted)
+ outstring(pri, ", ");
+ escape_string(pri, pri->sys_path);
+ argprinted = TRUE;
+ } else if (x != NOV && (x != HID || raw)) {
+ if (argprinted)
+ outstring(pri, ", ");
+ if (x == LLO)
+ (*Print[x])(pri, raw, arg,
+ pri->sys_args[++i]);
+ else
+ (*Print[x])(pri, raw, arg);
+ argprinted = TRUE;
+ }
+ }
+ outstring(pri, ")");
+ }
+
+ return (istraced);
+}
+#undef ISREAD
+#undef ISWRITE
+
+/*
+ * sysexit() returns non-zero if anything was printed.
+ */
+int
+sysexit(private_t *pri, int dotrace)
+{
+ const lwpstatus_t *Lsp = pri->lwpstat;
+ int what = Lsp->pr_what;
+ struct syscount *scp;
+ const struct systable *stp;
+ int subcode;
+ int istraced;
+ int raw;
+
+ /* protect ourself from operating system error */
+ if (what <= 0 || what > PRMAXSYS)
+ return (0);
+
+ /*
+ * If we aren't supposed to be tracing this one, then
+ * delete it from the traced signal set. We got here
+ * because the process was sleeping in an untraced syscall.
+ */
+ if (!prismember(&traceeven, what)) {
+ (void) Psysexit(Proc, what, FALSE);
+ return (0);
+ }
+
+ /* pick up registers & set pri->Errno before anything else */
+ pri->Errno = Lsp->pr_errno;
+ pri->ErrPriv = Lsp->pr_errpriv;
+ pri->Rval1 = Lsp->pr_rval1;
+ pri->Rval2 = Lsp->pr_rval2;
+
+ switch (what) {
+ case SYS_exit: /* these are traced on entry */
+ case SYS_lwp_exit:
+ case SYS_context:
+ istraced = dotrace && prismember(&trace, what);
+ break;
+ case SYS_execve: /* this is normally traced on entry */
+ istraced = dotrace && prismember(&trace, what);
+ if (pri->exec_string && *pri->exec_string) {
+ if (!cflag && istraced) { /* print exec() string now */
+ if (pri->exec_pname[0] != '\0')
+ (void) fputs(pri->exec_pname, stdout);
+ timestamp(pri);
+ (void) fputs(pri->exec_string, stdout);
+ }
+ pri->exec_pname[0] = '\0';
+ pri->exec_string[0] = '\0';
+ break;
+ }
+ /* FALLTHROUGH */
+ default:
+ /* we called sysentry() in main() for these */
+ if (what == SYS_openat || what == SYS_openat64 ||
+ what == SYS_open || what == SYS_open64)
+ istraced = dotrace && prismember(&trace, what);
+ else
+ istraced = sysentry(pri, dotrace) && dotrace;
+ pri->length = 0;
+ if (!cflag && istraced) {
+ putpname(pri);
+ timestamp(pri);
+ pri->length += printf("%s", pri->sys_string);
+ }
+ pri->sys_leng = 0;
+ *pri->sys_string = '\0';
+ break;
+ }
+
+ /* get systable entry for this syscall */
+ subcode = getsubcode(pri);
+ stp = subsys(what, subcode);
+
+ if (cflag && istraced) {
+ (void) mutex_lock(&count_lock);
+ scp = Cp->syscount[what];
+ if (what == SYS_forksys && subcode >= 3)
+ scp += subcode - 3;
+ else if (subcode != -1 &&
+ (what != SYS_openat && what != SYS_openat64 &&
+ what != SYS_open && what != SYS_open64 &&
+ what != SYS_lwp_create))
+ scp += subcode;
+ scp->count++;
+ accumulate(&scp->stime, &Lsp->pr_stime, &pri->syslast);
+ accumulate(&Cp->usrtotal, &Lsp->pr_utime, &pri->usrlast);
+ pri->syslast = Lsp->pr_stime;
+ pri->usrlast = Lsp->pr_utime;
+ (void) mutex_unlock(&count_lock);
+ }
+
+ raw = prismember(&rawout, what);
+
+ if (!cflag && istraced) {
+ if ((what == SYS_vfork || what == SYS_forksys) &&
+ pri->Errno == 0 && pri->Rval2 != 0) {
+ pri->length &= ~07;
+ if (strlen(sysname(pri, what, raw? -1 : subcode)) < 6) {
+ (void) fputc('\t', stdout);
+ pri->length += 8;
+ }
+ pri->length +=
+ 7 + printf("\t(returning as child ...)");
+ }
+ if (what == SYS_lwp_create &&
+ pri->Errno == 0 && pri->Rval1 == 0) {
+ pri->length &= ~07;
+ pri->length +=
+ 7 + printf("\t(returning as new lwp ...)");
+ }
+ if (pri->Errno != 0 || what != SYS_execve) {
+ /* prepare to print the return code */
+ pri->length >>= 3;
+ if (pri->length >= 6)
+ (void) fputc(' ', stdout);
+ for (; pri->length < 6; pri->length++)
+ (void) fputc('\t', stdout);
+ }
+ }
+ pri->length = 0;
+
+ if (pri->Errno != 0) { /* error in syscall */
+ if (istraced) {
+ if (cflag)
+ scp->error++;
+ else {
+ const char *ename = errname(pri->Errno);
+ const char *privname;
+
+ (void) printf("Err#%d", pri->Errno);
+ if (ename != NULL) {
+ (void) fputc(' ', stdout);
+ (void) fputs(ename, stdout);
+ }
+ switch (pri->ErrPriv) {
+ case PRIV_NONE:
+ privname = NULL;
+ break;
+ case PRIV_ALL:
+ privname = "ALL";
+ break;
+ case PRIV_MULTIPLE:
+ privname = "MULTIPLE";
+ break;
+ case PRIV_ALLZONE:
+ privname = "ZONE";
+ break;
+ default:
+ privname = priv_getbynum(pri->ErrPriv);
+ break;
+ }
+ if (privname != NULL)
+ (void) printf(" [%s]", privname);
+
+ (void) fputc('\n', stdout);
+ }
+ }
+ } else {
+ /* show arguments on successful exec */
+ if (what == SYS_execve) {
+ if (!cflag && istraced)
+ showargs(pri, raw);
+ } else if (!cflag && istraced) {
+ const char *fmt = NULL;
+ long rv1 = pri->Rval1;
+ long rv2 = pri->Rval2;
+
+#ifdef _LP64
+ /*
+ * 32-bit system calls return 32-bit values. We
+ * later mask out the upper bits if we want to
+ * print these as unsigned values.
+ */
+ if (data_model == PR_MODEL_ILP32) {
+ rv1 = (int)rv1;
+ rv2 = (int)rv2;
+ }
+#endif
+
+ switch (what) {
+ case SYS_llseek:
+ rv1 &= 0xffffffff;
+ rv2 &= 0xffffffff;
+#ifdef _LONG_LONG_LTOH /* first long of a longlong is the low order */
+ if (rv2 != 0) {
+ long temp = rv1;
+ fmt = "= 0x%lX%.8lX";
+ rv1 = rv2;
+ rv2 = temp;
+ break;
+ }
+#else /* the other way around */
+ if (rv1 != 0) {
+ fmt = "= 0x%lX%.8lX";
+ break;
+ }
+ rv1 = rv2; /* ugly */
+#endif
+ /* FALLTHROUGH */
+ case SYS_lseek:
+ case SYS_ulimit:
+ if (rv1 & 0xff000000) {
+#ifdef _LP64
+ if (data_model == PR_MODEL_ILP32)
+ rv1 &= 0xffffffff;
+#endif
+ fmt = "= 0x%.8lX";
+ }
+ break;
+ case SYS_sigtimedwait:
+ if (raw)
+ /* EMPTY */;
+ else if ((fmt = rawsigname(pri, rv1)) != NULL) {
+ rv1 = (long)fmt; /* filthy */
+ fmt = "= %s";
+ }
+ break;
+ case SYS_port:
+#ifdef _LP64
+ if (data_model == PR_MODEL_LP64) {
+ rv2 = rv1 & 0xffffffff;
+ rv1 = rv1 >> 32;
+ }
+#endif
+ break;
+ }
+
+ if (fmt == NULL) {
+ switch (stp->rval[0]) {
+ case HEX:
+#ifdef _LP64
+ if (data_model == PR_MODEL_ILP32)
+ rv1 &= 0xffffffff;
+#endif
+ fmt = "= 0x%.8lX";
+ break;
+ case HHX:
+#ifdef _LP64
+ if (data_model == PR_MODEL_ILP32)
+ rv1 &= 0xffffffff;
+#endif
+ fmt = "= 0x%.4lX";
+ break;
+ case OCT:
+#ifdef _LP64
+ if (data_model == PR_MODEL_ILP32)
+ rv1 &= 0xffffffff;
+#endif
+ fmt = "= %#lo";
+ break;
+ case UNS:
+#ifdef _LP64
+ if (data_model == PR_MODEL_ILP32)
+ rv1 &= 0xffffffff;
+#endif
+ fmt = "= %lu";
+ break;
+ default:
+ fmt = "= %ld";
+ break;
+ }
+ }
+
+ (void) printf(fmt, rv1, rv2);
+
+ switch (stp->rval[1]) {
+ case NOV:
+ fmt = NULL;
+ break;
+ case HEX:
+#ifdef _LP64
+ if (data_model == PR_MODEL_ILP32)
+ rv2 &= 0xffffffff;
+#endif
+ fmt = " [0x%.8lX]";
+ break;
+ case HHX:
+#ifdef _LP64
+ if (data_model == PR_MODEL_ILP32)
+ rv2 &= 0xffffffff;
+#endif
+ fmt = " [0x%.4lX]";
+ break;
+ case OCT:
+#ifdef _LP64
+ if (data_model == PR_MODEL_ILP32)
+ rv2 &= 0xffffffff;
+#endif
+ fmt = " [%#lo]";
+ break;
+ case UNS:
+#ifdef _LP64
+ if (data_model == PR_MODEL_ILP32)
+ rv2 &= 0xffffffff;
+#endif
+ fmt = " [%lu]";
+ break;
+ default:
+ fmt = " [%ld]";
+ break;
+ }
+
+ if (fmt != NULL)
+ (void) printf(fmt, rv2);
+ (void) fputc('\n', stdout);
+ }
+
+ if (what == SYS_vfork || what == SYS_forksys) {
+ if (pri->Rval2 == 0) /* child was created */
+ pri->child = pri->Rval1;
+ else if (cflag && istraced) /* this is the child */
+ scp->count--;
+ }
+ if (what == SYS_lwp_create && pri->Rval1 == 0 &&
+ cflag && istraced) /* this is the created lwp */
+ scp->count--;
+ }
+
+#define ISREAD(code) \
+ ((code) == SYS_read || (code) == SYS_pread || (code) == SYS_pread64 || \
+ (code) == SYS_recv || (code) == SYS_recvfrom)
+#define ISWRITE(code) \
+ ((code) == SYS_write || (code) == SYS_pwrite || \
+ (code) == SYS_pwrite64 || (code) == SYS_send || (code) == SYS_sendto)
+
+ if (!cflag && istraced) {
+ int fdp1 = (int)pri->sys_args[0] + 1; /* filedescriptor + 1 */
+
+ if (raw) {
+ if (what != SYS_execve)
+ showpaths(pri, stp);
+ if (ISREAD(what) || ISWRITE(what)) {
+ if (pri->iob_buf[0] != '\0')
+ (void) printf("%s 0x%.8lX: %s\n",
+ pri->pname, pri->sys_args[1],
+ pri->iob_buf);
+ }
+ }
+
+ /*
+ * Show buffer contents for read()/pread() or write()/pwrite().
+ * IOBSIZE bytes have already been shown;
+ * don't show them again unless there's more.
+ */
+ if ((ISREAD(what) && pri->Errno == 0 &&
+ prismember(&readfd, fdp1)) ||
+ (ISWRITE(what) && prismember(&writefd, fdp1))) {
+ long nb = ISWRITE(what) ? pri->sys_args[2] : pri->Rval1;
+
+ if (nb > IOBSIZE) {
+ /* enter region of lengthy output */
+ if (nb > MYBUFSIZ / 4)
+ Eserialize();
+
+ showbuffer(pri, pri->sys_args[1], nb);
+
+ /* exit region of lengthy output */
+ if (nb > MYBUFSIZ / 4)
+ Xserialize();
+ }
+ }
+#undef ISREAD
+#undef ISWRITE
+ /*
+ * Do verbose interpretation if requested.
+ * If buffer contents for read or write have been requested and
+ * this is a readv() or writev(), force verbose interpretation.
+ */
+ if (prismember(&verbose, what) ||
+ ((what == SYS_readv || what == SYS_recvmsg) &&
+ pri->Errno == 0 && prismember(&readfd, fdp1)) ||
+ ((what == SYS_writev || what == SYS_sendfilev ||
+ what == SYS_sendmsg) &&
+ prismember(&writefd, fdp1)))
+ expound(pri, pri->Rval1, raw);
+ }
+
+ return (!cflag && istraced);
+}
+
+void
+showpaths(private_t *pri, const struct systable *stp)
+{
+ int what = pri->lwpstat->pr_what;
+ int i;
+
+ for (i = 0; i < pri->sys_nargs; i++) {
+ if (stp->arg[i] == ATC && (int)pri->sys_args[i] == AT_FDCWD) {
+ (void) printf("%s 0x%.8X: AT_FDCWD\n",
+ pri->pname, AT_FDCWD);
+ } else if ((stp->arg[i] == STG) ||
+ (stp->arg[i] == RST && !pri->Errno) ||
+ (stp->arg[i] == RLK && !pri->Errno && pri->Rval1 > 0)) {
+ long addr = pri->sys_args[i];
+ int maxleng =
+ (stp->arg[i] == RLK)? (int)pri->Rval1 : PATH_MAX;
+ char *s;
+
+ if (pri->sys_valid &&
+ ((i == 0 && stp->arg[0] == STG) ||
+ (i == 1 && (what == SYS_openat ||
+ what == SYS_openat64)))) /* already fetched */
+ s = pri->sys_path;
+ else
+ s = fetchstring(pri, addr,
+ maxleng > PATH_MAX ? PATH_MAX : maxleng);
+
+ if (s != (char *)NULL)
+ (void) printf("%s 0x%.8lX: \"%s\"\n",
+ pri->pname, addr, s);
+ }
+ }
+}
+
+/*
+ * Display arguments to successful exec().
+ */
+void
+showargs(private_t *pri, int raw)
+{
+ const lwpstatus_t *Lsp = pri->lwpstat;
+ int nargs;
+ long ap;
+ int ptrsize;
+ int fail;
+
+ pri->length = 0;
+ ptrsize = (data_model == PR_MODEL_LP64)? 8 : 4;
+
+#if defined(__i386) || defined(__amd64) /* XX64 */
+ ap = (long)Lsp->pr_reg[R_SP];
+ fail = (Pread(Proc, &nargs, sizeof (nargs), ap) != sizeof (nargs));
+ ap += ptrsize;
+#endif /* i386 */
+
+#if sparc
+ if (data_model == PR_MODEL_LP64) {
+ int64_t xnargs;
+ ap = (long)(Lsp->pr_reg[R_SP]) + 16 * sizeof (int64_t)
+ + STACK_BIAS;
+ fail = (Pread(Proc, &xnargs, sizeof (xnargs), ap) !=
+ sizeof (xnargs));
+ nargs = (int)xnargs;
+ } else {
+ ap = (long)(Lsp->pr_reg[R_SP]) + 16 * sizeof (int32_t);
+ fail = (Pread(Proc, &nargs, sizeof (nargs), ap) !=
+ sizeof (nargs));
+ }
+ ap += ptrsize;
+#endif /* sparc */
+
+ if (fail) {
+ (void) printf("\n%s\t*** Bad argument list? ***\n", pri->pname);
+ return;
+ }
+
+ (void) printf(" argc = %d\n", nargs);
+ if (raw)
+ showpaths(pri, &systable[SYS_execve]);
+
+ show_cred(pri, FALSE, FALSE);
+
+ if (aflag || eflag) { /* dump args or environment */
+
+ /* enter region of (potentially) lengthy output */
+ Eserialize();
+
+ if (aflag) /* dump the argument list */
+ dumpargs(pri, ap, "argv:");
+ ap += (nargs+1) * ptrsize;
+ if (eflag) /* dump the environment */
+ dumpargs(pri, ap, "envp:");
+
+ /* exit region of lengthy output */
+ Xserialize();
+ }
+}
+
+void
+dumpargs(private_t *pri, long ap, const char *str)
+{
+ char *string;
+ unsigned int leng = 0;
+ int ptrsize;
+ long arg = 0;
+ char *argaddr;
+ char badaddr[32];
+
+ if (interrupt)
+ return;
+
+#ifdef _LP64
+ if (data_model == PR_MODEL_LP64) {
+ argaddr = (char *)&arg;
+ ptrsize = 8;
+ } else {
+#if defined(_LITTLE_ENDIAN)
+ argaddr = (char *)&arg;
+#else
+ argaddr = (char *)&arg + 4;
+#endif
+ ptrsize = 4;
+ }
+#else
+ argaddr = (char *)&arg;
+ ptrsize = 4;
+#endif
+ putpname(pri);
+ (void) fputc(' ', stdout);
+ (void) fputs(str, stdout);
+ leng += 1 + strlen(str);
+
+ while (!interrupt) {
+ if (Pread(Proc, argaddr, ptrsize, ap) != ptrsize) {
+ (void) printf("\n%s\t*** Bad argument list? ***\n",
+ pri->pname);
+ return;
+ }
+ ap += ptrsize;
+
+ if (arg == 0)
+ break;
+ string = fetchstring(pri, arg, PATH_MAX);
+ if (string == NULL) {
+ (void) sprintf(badaddr, "BadAddress:0x%.8lX", arg);
+ string = badaddr;
+ }
+ if ((leng += strlen(string)) < 63) {
+ (void) fputc(' ', stdout);
+ leng++;
+ } else {
+ (void) fputc('\n', stdout);
+ leng = 0;
+ putpname(pri);
+ (void) fputs(" ", stdout);
+ leng += 2 + strlen(string);
+ }
+ (void) fputs(string, stdout);
+ }
+ (void) fputc('\n', stdout);
+}
+
+/*
+ * Display contents of read() or write() buffer.
+ */
+void
+showbuffer(private_t *pri, long offset, long count)
+{
+ char buffer[320];
+ int nbytes;
+ char *buf;
+ int n;
+
+ while (count > 0 && !interrupt) {
+ nbytes = (count < sizeof (buffer))? count : sizeof (buffer);
+ if ((nbytes = Pread(Proc, buffer, nbytes, offset)) <= 0)
+ break;
+ count -= nbytes;
+ offset += nbytes;
+ buf = buffer;
+ while (nbytes > 0 && !interrupt) {
+ char obuf[65];
+
+ n = (nbytes < 32)? nbytes : 32;
+ showbytes(buf, n, obuf);
+
+ putpname(pri);
+ (void) fputs(" ", stdout);
+ (void) fputs(obuf, stdout);
+ (void) fputc('\n', stdout);
+ nbytes -= n;
+ buf += n;
+ }
+ }
+}
+
+void
+showbytes(const char *buf, int n, char *obuf)
+{
+ int c;
+
+ while (--n >= 0) {
+ int c1 = '\\';
+ int c2;
+
+ switch (c = (*buf++ & 0xff)) {
+ case '\0':
+ c2 = '0';
+ break;
+ case '\b':
+ c2 = 'b';
+ break;
+ case '\t':
+ c2 = 't';
+ break;
+ case '\n':
+ c2 = 'n';
+ break;
+ case '\v':
+ c2 = 'v';
+ break;
+ case '\f':
+ c2 = 'f';
+ break;
+ case '\r':
+ c2 = 'r';
+ break;
+ default:
+ if (isprint(c)) {
+ c1 = ' ';
+ c2 = c;
+ } else {
+ c1 = c>>4;
+ c1 += (c1 < 10)? '0' : 'A'-10;
+ c2 = c&0xf;
+ c2 += (c2 < 10)? '0' : 'A'-10;
+ }
+ break;
+ }
+ *obuf++ = (char)c1;
+ *obuf++ = (char)c2;
+ }
+
+ *obuf = '\0';
+}
diff --git a/usr/src/cmd/truss/codes.c b/usr/src/cmd/truss/codes.c
new file mode 100644
index 0000000..069268d
--- /dev/null
+++ b/usr/src/cmd/truss/codes.c
@@ -0,0 +1,2372 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
+ * Copyright (c) 2012, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2014, OmniTI Computer Consulting, Inc. All rights reserved.
+ */
+
+/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
+/* All Rights Reserved */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <libproc.h>
+
+#include <ctype.h>
+#include <string.h>
+#include <sys/dlpi.h>
+#include <sys/ipc.h>
+#include <sys/ipc_impl.h>
+#include <sys/msg.h>
+#include <sys/sem.h>
+#include <sys/shm.h>
+#include <sys/fstyp.h>
+#if defined(__i386) || defined(__amd64)
+#include <sys/sysi86.h>
+#endif /* __i386 */
+#include <sys/unistd.h>
+#include <sys/file.h>
+#include <sys/tiuser.h>
+#include <sys/timod.h>
+#include <sys/stream.h>
+#include <sys/stropts.h>
+#include <sys/termios.h>
+#include <sys/termiox.h>
+#include <sys/jioctl.h>
+#include <sys/filio.h>
+#include <fcntl.h>
+#include <sys/termio.h>
+#include <sys/stermio.h>
+#include <sys/ttold.h>
+#include <sys/mount.h>
+#include <sys/utssys.h>
+#include <sys/sysconfig.h>
+#include <sys/statvfs.h>
+#include <sys/kstat.h>
+#include <sys/audio.h>
+#include <sys/mixer.h>
+#include <sys/cpc_impl.h>
+#include <sys/devpoll.h>
+#include <sys/strredir.h>
+#include <sys/sockio.h>
+#include <netinet/ip_mroute.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <sys/ptyvar.h>
+#include <sys/des.h>
+#include <sys/prnio.h>
+#include <sys/dtrace.h>
+#include <sys/crypto/ioctladmin.h>
+#include <sys/crypto/ioctl.h>
+#include <sys/kbio.h>
+#include <sys/ptms.h>
+#include <sys/aggr.h>
+#include <sys/dld.h>
+#include <net/simnet.h>
+#include <sys/vnic.h>
+#include <sys/fs/zfs.h>
+#include <inet/kssl/kssl.h>
+#include <sys/dkio.h>
+#include <sys/fdio.h>
+#include <sys/cdio.h>
+#include <sys/scsi/impl/uscsi.h>
+#include <sys/devinfo_impl.h>
+#include <sys/dumpadm.h>
+#include <sys/mntio.h>
+#include <inet/iptun.h>
+#include <sys/zcons.h>
+#include <sys/usb/clients/hid/hid.h>
+#include <sys/pm.h>
+#include <sys/soundcard.h>
+
+#include "ramdata.h"
+#include "proto.h"
+
+#define FCNTLMIN F_DUPFD
+#define FCNTLMAX F_BADFD
+const char *const FCNTLname[] = {
+ "F_DUPFD",
+ "F_GETFD",
+ "F_SETFD",
+ "F_GETFL",
+ "F_SETFL",
+ "F_O_GETLK",
+ "F_SETLK",
+ "F_SETLKW",
+ "F_CHKFL",
+ "F_DUP2FD",
+ "F_ALLOCSP",
+ "F_FREESP",
+ NULL, /* 12 */
+ NULL, /* 13 */
+ "F_GETLK",
+ NULL, /* 15 */
+ NULL, /* 16 */
+ NULL, /* 17 */
+ NULL, /* 18 */
+ NULL, /* 19 */
+ NULL, /* 20 */
+ NULL, /* 21 */
+ NULL, /* 22 */
+ "F_GETOWN",
+ "F_SETOWN",
+ "F_REVOKE",
+ "F_HASREMOTELOCKS",
+ "F_FREESP64",
+ NULL, /* 28 */
+ NULL, /* 29 */
+ NULL, /* 30 */
+ NULL, /* 31 */
+ NULL, /* 32 */
+ "F_GETLK64",
+ "F_SETLK64",
+ "F_SETLKW64",
+ "F_DUP2FD_CLOEXEC",
+ "F_DUPFD_CLOEXEC",
+ NULL, /* 38 */
+ NULL, /* 39 */
+ "F_SHARE",
+ "F_UNSHARE",
+ "F_SETLK_NBMAND",
+ "F_SHARE_NBMAND",
+ "F_SETLK64_NBMAND",
+ NULL, /* 45 */
+ "F_BADFD"
+};
+
+#define SYSFSMIN GETFSIND
+#define SYSFSMAX GETNFSTYP
+const char *const SYSFSname[] = {
+ "GETFSIND",
+ "GETFSTYP",
+ "GETNFSTYP"
+};
+
+#define SCONFMIN _CONFIG_NGROUPS
+#define SCONFMAX _CONFIG_EPHID_MAX
+const char *const SCONFname[] = {
+ "_CONFIG_NGROUPS", /* 2 */
+ "_CONFIG_CHILD_MAX", /* 3 */
+ "_CONFIG_OPEN_FILES", /* 4 */
+ "_CONFIG_POSIX_VER", /* 5 */
+ "_CONFIG_PAGESIZE", /* 6 */
+ "_CONFIG_CLK_TCK", /* 7 */
+ "_CONFIG_XOPEN_VER", /* 8 */
+ "_CONFIG_HRESCLK_TCK", /* 9 */
+ "_CONFIG_PROF_TCK", /* 10 */
+ "_CONFIG_NPROC_CONF", /* 11 */
+ "_CONFIG_NPROC_ONLN", /* 12 */
+ "_CONFIG_AIO_LISTIO_MAX", /* 13 */
+ "_CONFIG_AIO_MAX", /* 14 */
+ "_CONFIG_AIO_PRIO_DELTA_MAX", /* 15 */
+ "_CONFIG_DELAYTIMER_MAX", /* 16 */
+ "_CONFIG_MQ_OPEN_MAX", /* 17 */
+ "_CONFIG_MQ_PRIO_MAX", /* 18 */
+ "_CONFIG_RTSIG_MAX", /* 19 */
+ "_CONFIG_SEM_NSEMS_MAX", /* 20 */
+ "_CONFIG_SEM_VALUE_MAX", /* 21 */
+ "_CONFIG_SIGQUEUE_MAX", /* 22 */
+ "_CONFIG_SIGRT_MIN", /* 23 */
+ "_CONFIG_SIGRT_MAX", /* 24 */
+ "_CONFIG_TIMER_MAX", /* 25 */
+ "_CONFIG_PHYS_PAGES", /* 26 */
+ "_CONFIG_AVPHYS_PAGES", /* 27 */
+ "_CONFIG_COHERENCY", /* 28 */
+ "_CONFIG_SPLIT_CACHE", /* 29 */
+ "_CONFIG_ICACHESZ", /* 30 */
+ "_CONFIG_DCACHESZ", /* 31 */
+ "_CONFIG_ICACHELINESZ", /* 32 */
+ "_CONFIG_DCACHELINESZ", /* 33 */
+ "_CONFIG_ICACHEBLKSZ", /* 34 */
+ "_CONFIG_DCACHEBLKSZ", /* 35 */
+ "_CONFIG_DCACHETBLKSZ", /* 36 */
+ "_CONFIG_ICACHE_ASSOC", /* 37 */
+ "_CONFIG_DCACHE_ASSOC", /* 38 */
+ NULL, /* 39 */
+ NULL, /* 40 */
+ NULL, /* 41 */
+ "_CONFIG_MAXPID", /* 42 */
+ "_CONFIG_STACK_PROT", /* 43 */
+ "_CONFIG_NPROC_MAX", /* 44 */
+ "_CONFIG_CPUID_MAX", /* 45 */
+ "_CONFIG_SYMLOOP_MAX", /* 46 */
+ "_CONFIG_EPHID_MAX", /* 47 */
+};
+
+#define PATHCONFMIN _PC_LINK_MAX
+#define PATHCONFMAX _PC_XATTR_EXISTS
+const char *const PATHCONFname[] = {
+ "_PC_LINK_MAX", /* 1 */
+ "_PC_MAX_CANON", /* 2 */
+ "_PC_MAX_INPUT", /* 3 */
+ "_PC_NAME_MAX", /* 4 */
+ "_PC_PATH_MAX", /* 5 */
+ "_PC_PIPE_BUF", /* 6 */
+ "_PC_NO_TRUNC", /* 7 */
+ "_PC_VDISABLE", /* 8 */
+ "_PC_CHOWN_RESTRICTED", /* 9 */
+ "_PC_ASYNC_IO", /* 10 */
+ "_PC_PRIO_IO", /* 11 */
+ "_PC_SYNC_IO", /* 12 */
+ "_PC_ALLOC_SIZE_MIN", /* 13 */
+ "_PC_REC_INCR_XFER_SIZE", /* 14 */
+ "_PC_REC_MAX_XFER_SIZE", /* 15 */
+ "_PC_REC_MIN_XFER_SIZE", /* 16 */
+ "_PC_REC_XFER_ALIGN", /* 17 */
+ "_PC_SYMLINK_MAX", /* 18 */
+ "_PC_2_SYMLINKS", /* 19 */
+ "_PC_ACL_ENABLED", /* 20 */
+ "_PC_MIN_HOLE_SIZE", /* 21 */
+ "_PC_CASE_BEHAVIOR", /* 22 */
+ "_PC_SATTR_ENABLED", /* 23 */
+ "_PC_SATTR_EXISTS", /* 24 */
+ "_PC_ACCESS_FILTERING", /* 25 */
+ "_PC_TIMESTAMP_RESOLUTION", /* 26 */
+ NULL, /* 27 */
+ NULL, /* 28 */
+ NULL, /* 29 */
+ NULL, /* 30 */
+ NULL, /* 31 */
+ NULL, /* 32 */
+ NULL, /* 33 */
+ NULL, /* 34 */
+ NULL, /* 35 */
+ NULL, /* 36 */
+ NULL, /* 37 */
+ NULL, /* 38 */
+ NULL, /* 39 */
+ NULL, /* 40 */
+ NULL, /* 41 */
+ NULL, /* 42 */
+ NULL, /* 43 */
+ NULL, /* 44 */
+ NULL, /* 45 */
+ NULL, /* 46 */
+ NULL, /* 47 */
+ NULL, /* 48 */
+ NULL, /* 49 */
+ NULL, /* 50 */
+ NULL, /* 51 */
+ NULL, /* 52 */
+ NULL, /* 53 */
+ NULL, /* 54 */
+ NULL, /* 55 */
+ NULL, /* 56 */
+ NULL, /* 57 */
+ NULL, /* 58 */
+ NULL, /* 59 */
+ NULL, /* 60 */
+ NULL, /* 61 */
+ NULL, /* 62 */
+ NULL, /* 63 */
+ NULL, /* 64 */
+ NULL, /* 65 */
+ NULL, /* 66 */
+ "_PC_FILESIZEBITS", /* 67 */
+ NULL, /* 68 */
+ NULL, /* 69 */
+ NULL, /* 70 */
+ NULL, /* 71 */
+ NULL, /* 72 */
+ NULL, /* 73 */
+ NULL, /* 74 */
+ NULL, /* 75 */
+ NULL, /* 76 */
+ NULL, /* 77 */
+ NULL, /* 78 */
+ NULL, /* 79 */
+ NULL, /* 80 */
+ NULL, /* 81 */
+ NULL, /* 82 */
+ NULL, /* 83 */
+ NULL, /* 84 */
+ NULL, /* 85 */
+ NULL, /* 86 */
+ NULL, /* 87 */
+ NULL, /* 88 */
+ NULL, /* 89 */
+ NULL, /* 90 */
+ NULL, /* 91 */
+ NULL, /* 92 */
+ NULL, /* 93 */
+ NULL, /* 94 */
+ NULL, /* 95 */
+ NULL, /* 96 */
+ NULL, /* 97 */
+ NULL, /* 98 */
+ NULL, /* 99 */
+ "_PC_XATTR_ENABLED", /* 100 */
+ "_PC_XATTR_EXISTS", /* 101, _PC_LAST */
+};
+
+const struct ioc {
+ uint_t code;
+ const char *name;
+ const char *datastruct;
+} ioc[] = {
+ { (uint_t)TCGETA, "TCGETA", NULL },
+ { (uint_t)TCSETA, "TCSETA", NULL },
+ { (uint_t)TCSETAW, "TCSETAW", NULL },
+ { (uint_t)TCSETAF, "TCSETAF", NULL },
+ { (uint_t)TCFLSH, "TCFLSH", NULL },
+ { (uint_t)TIOCKBON, "TIOCKBON", NULL },
+ { (uint_t)TIOCKBOF, "TIOCKBOF", NULL },
+ { (uint_t)KBENABLED, "KBENABLED", NULL },
+ { (uint_t)TCGETS, "TCGETS", NULL },
+ { (uint_t)TCSETS, "TCSETS", NULL },
+ { (uint_t)TCSETSW, "TCSETSW", NULL },
+ { (uint_t)TCSETSF, "TCSETSF", NULL },
+ { (uint_t)TCXONC, "TCXONC", NULL },
+ { (uint_t)TCSBRK, "TCSBRK", NULL },
+ { (uint_t)TCDSET, "TCDSET", NULL },
+ { (uint_t)RTS_TOG, "RTS_TOG", NULL },
+ { (uint_t)TIOCSWINSZ, "TIOCSWINSZ", NULL },
+ { (uint_t)TIOCGWINSZ, "TIOCGWINSZ", NULL },
+ { (uint_t)TIOCGETD, "TIOCGETD", NULL },
+ { (uint_t)TIOCSETD, "TIOCSETD", NULL },
+ { (uint_t)TIOCHPCL, "TIOCHPCL", NULL },
+ { (uint_t)TIOCGETP, "TIOCGETP", NULL },
+ { (uint_t)TIOCSETP, "TIOCSETP", NULL },
+ { (uint_t)TIOCSETN, "TIOCSETN", NULL },
+ { (uint_t)TIOCEXCL, "TIOCEXCL", NULL },
+ { (uint_t)TIOCNXCL, "TIOCNXCL", NULL },
+ { (uint_t)TIOCFLUSH, "TIOCFLUSH", NULL },
+ { (uint_t)TIOCSETC, "TIOCSETC", NULL },
+ { (uint_t)TIOCGETC, "TIOCGETC", NULL },
+ { (uint_t)TIOCGPGRP, "TIOCGPGRP", NULL },
+ { (uint_t)TIOCSPGRP, "TIOCSPGRP", NULL },
+ { (uint_t)TIOCGSID, "TIOCGSID", NULL },
+ { (uint_t)TIOCSTI, "TIOCSTI", NULL },
+ { (uint_t)TIOCMSET, "TIOCMSET", NULL },
+ { (uint_t)TIOCMBIS, "TIOCMBIS", NULL },
+ { (uint_t)TIOCMBIC, "TIOCMBIC", NULL },
+ { (uint_t)TIOCMGET, "TIOCMGET", NULL },
+ { (uint_t)TIOCREMOTE, "TIOCREMOTE", NULL },
+ { (uint_t)TIOCSIGNAL, "TIOCSIGNAL", NULL },
+ { (uint_t)TIOCSTART, "TIOCSTART", NULL },
+ { (uint_t)TIOCSTOP, "TIOCSTOP", NULL },
+ { (uint_t)TIOCNOTTY, "TIOCNOTTY", NULL },
+ { (uint_t)TIOCSCTTY, "TIOCSCTTY", NULL },
+ { (uint_t)TIOCOUTQ, "TIOCOUTQ", NULL },
+ { (uint_t)TIOCGLTC, "TIOCGLTC", NULL },
+ { (uint_t)TIOCSLTC, "TIOCSLTC", NULL },
+ { (uint_t)TIOCCDTR, "TIOCCDTR", NULL },
+ { (uint_t)TIOCSDTR, "TIOCSDTR", NULL },
+ { (uint_t)TIOCCBRK, "TIOCCBRK", NULL },
+ { (uint_t)TIOCSBRK, "TIOCSBRK", NULL },
+ { (uint_t)TIOCLGET, "TIOCLGET", NULL },
+ { (uint_t)TIOCLSET, "TIOCLSET", NULL },
+ { (uint_t)TIOCLBIC, "TIOCLBIC", NULL },
+ { (uint_t)TIOCLBIS, "TIOCLBIS", NULL },
+
+ { (uint_t)TIOCSILOOP, "TIOCSILOOP", NULL },
+ { (uint_t)TIOCCILOOP, "TIOCSILOOP", NULL },
+
+ { (uint_t)TIOCGPPS, "TIOCGPPS", NULL },
+ { (uint_t)TIOCSPPS, "TIOCSPPS", NULL },
+ { (uint_t)TIOCGPPSEV, "TIOCGPPSEV", NULL },
+
+ { (uint_t)TIOCPKT, "TIOCPKT", NULL }, /* ptyvar.h */
+ { (uint_t)TIOCUCNTL, "TIOCUCNTL", NULL },
+ { (uint_t)TIOCTCNTL, "TIOCTCNTL", NULL },
+ { (uint_t)TIOCISPACE, "TIOCISPACE", NULL },
+ { (uint_t)TIOCISIZE, "TIOCISIZE", NULL },
+ { (uint_t)TIOCSSIZE, "TIOCSSIZE", "ttysize" },
+ { (uint_t)TIOCGSIZE, "TIOCGSIZE", "ttysize" },
+
+ /*
+ * Unfortunately, the DLIOC and LDIOC codes overlap. Since the LDIOC
+ * ioctls (for xenix compatibility) are far less likely to be used, we
+ * give preference to DLIOC.
+ */
+ { (uint_t)DLIOCRAW, "DLIOCRAW", NULL },
+ { (uint_t)DLIOCNATIVE, "DLIOCNATIVE", NULL },
+ { (uint_t)DLIOCIPNETINFO, "DLIOCIPNETINFO", NULL},
+ { (uint_t)DLIOCLOWLINK, "DLIOCLOWLINK", NULL },
+
+ { (uint_t)LDOPEN, "LDOPEN", NULL },
+ { (uint_t)LDCLOSE, "LDCLOSE", NULL },
+ { (uint_t)LDCHG, "LDCHG", NULL },
+ { (uint_t)LDGETT, "LDGETT", NULL },
+ { (uint_t)LDSETT, "LDSETT", NULL },
+ { (uint_t)LDSMAP, "LDSMAP", NULL },
+ { (uint_t)LDGMAP, "LDGMAP", NULL },
+ { (uint_t)LDNMAP, "LDNMAP", NULL },
+ { (uint_t)TCGETX, "TCGETX", NULL },
+ { (uint_t)TCSETX, "TCSETX", NULL },
+ { (uint_t)TCSETXW, "TCSETXW", NULL },
+ { (uint_t)TCSETXF, "TCSETXF", NULL },
+ { (uint_t)FIORDCHK, "FIORDCHK", NULL },
+ { (uint_t)FIOCLEX, "FIOCLEX", NULL },
+ { (uint_t)FIONCLEX, "FIONCLEX", NULL },
+ { (uint_t)FIONREAD, "FIONREAD", NULL },
+ { (uint_t)FIONBIO, "FIONBIO", NULL },
+ { (uint_t)FIOASYNC, "FIOASYNC", NULL },
+ { (uint_t)FIOSETOWN, "FIOSETOWN", NULL },
+ { (uint_t)FIOGETOWN, "FIOGETOWN", NULL },
+#ifdef DIOCGETP
+ { (uint_t)DIOCGETP, "DIOCGETP", NULL },
+ { (uint_t)DIOCSETP, "DIOCSETP", NULL },
+#endif
+#ifdef DIOCGETC
+ { (uint_t)DIOCGETC, "DIOCGETC", NULL },
+ { (uint_t)DIOCGETB, "DIOCGETB", NULL },
+ { (uint_t)DIOCSETE, "DIOCSETE", NULL },
+#endif
+#ifdef IFFORMAT
+ { (uint_t)IFFORMAT, "IFFORMAT", NULL },
+ { (uint_t)IFBCHECK, "IFBCHECK", NULL },
+ { (uint_t)IFCONFIRM, "IFCONFIRM", NULL },
+#endif
+#ifdef LIOCGETP
+ { (uint_t)LIOCGETP, "LIOCGETP", NULL },
+ { (uint_t)LIOCSETP, "LIOCSETP", NULL },
+ { (uint_t)LIOCGETS, "LIOCGETS", NULL },
+ { (uint_t)LIOCSETS, "LIOCSETS", NULL },
+#endif
+#ifdef JBOOT
+ { (uint_t)JBOOT, "JBOOT", NULL },
+ { (uint_t)JTERM, "JTERM", NULL },
+ { (uint_t)JMPX, "JMPX", NULL },
+#ifdef JTIMO
+ { (uint_t)JTIMO, "JTIMO", NULL },
+#endif
+ { (uint_t)JWINSIZE, "JWINSIZE", NULL },
+ { (uint_t)JTIMOM, "JTIMOM", NULL },
+ { (uint_t)JZOMBOOT, "JZOMBOOT", NULL },
+ { (uint_t)JAGENT, "JAGENT", NULL },
+ { (uint_t)JTRUN, "JTRUN", NULL },
+ { (uint_t)JXTPROTO, "JXTPROTO", NULL },
+#endif
+ { (uint_t)KSTAT_IOC_CHAIN_ID, "KSTAT_IOC_CHAIN_ID", NULL },
+ { (uint_t)KSTAT_IOC_READ, "KSTAT_IOC_READ", NULL },
+ { (uint_t)KSTAT_IOC_WRITE, "KSTAT_IOC_WRITE", NULL },
+ { (uint_t)STGET, "STGET", NULL },
+ { (uint_t)STSET, "STSET", NULL },
+ { (uint_t)STTHROW, "STTHROW", NULL },
+ { (uint_t)STWLINE, "STWLINE", NULL },
+ { (uint_t)STTSV, "STTSV", NULL },
+ { (uint_t)I_NREAD, "I_NREAD", NULL },
+ { (uint_t)I_PUSH, "I_PUSH", NULL },
+ { (uint_t)I_POP, "I_POP", NULL },
+ { (uint_t)I_LOOK, "I_LOOK", NULL },
+ { (uint_t)I_FLUSH, "I_FLUSH", NULL },
+ { (uint_t)I_SRDOPT, "I_SRDOPT", NULL },
+ { (uint_t)I_GRDOPT, "I_GRDOPT", NULL },
+ { (uint_t)I_STR, "I_STR", NULL },
+ { (uint_t)I_SETSIG, "I_SETSIG", NULL },
+ { (uint_t)I_GETSIG, "I_GETSIG", NULL },
+ { (uint_t)I_FIND, "I_FIND", NULL },
+ { (uint_t)I_LINK, "I_LINK", NULL },
+ { (uint_t)I_UNLINK, "I_UNLINK", NULL },
+ { (uint_t)I_PEEK, "I_PEEK", NULL },
+ { (uint_t)I_FDINSERT, "I_FDINSERT", NULL },
+ { (uint_t)I_SENDFD, "I_SENDFD", NULL },
+ { (uint_t)I_RECVFD, "I_RECVFD", NULL },
+ { (uint_t)I_SWROPT, "I_SWROPT", NULL },
+ { (uint_t)I_GWROPT, "I_GWROPT", NULL },
+ { (uint_t)I_LIST, "I_LIST", NULL },
+ { (uint_t)I_PLINK, "I_PLINK", NULL },
+ { (uint_t)I_PUNLINK, "I_PUNLINK", NULL },
+ { (uint_t)I_FLUSHBAND, "I_FLUSHBAND", NULL },
+ { (uint_t)I_CKBAND, "I_CKBAND", NULL },
+ { (uint_t)I_GETBAND, "I_GETBAND", NULL },
+ { (uint_t)I_ATMARK, "I_ATMARK", NULL },
+ { (uint_t)I_SETCLTIME, "I_SETCLTIME", NULL },
+ { (uint_t)I_GETCLTIME, "I_GETCLTIME", NULL },
+ { (uint_t)I_CANPUT, "I_CANPUT", NULL },
+ { (uint_t)I_ANCHOR, "I_ANCHOR", NULL },
+ { (uint_t)_I_CMD, "_I_CMD", NULL },
+#ifdef TI_GETINFO
+ { (uint_t)TI_GETINFO, "TI_GETINFO", NULL },
+ { (uint_t)TI_OPTMGMT, "TI_OPTMGMT", NULL },
+ { (uint_t)TI_BIND, "TI_BIND", NULL },
+ { (uint_t)TI_UNBIND, "TI_UNBIND", NULL },
+#endif
+#ifdef TI_CAPABILITY
+ { (uint_t)TI_CAPABILITY, "TI_CAPABILITY", NULL },
+#endif
+#ifdef TI_GETMYNAME
+ { (uint_t)TI_GETMYNAME, "TI_GETMYNAME", NULL },
+ { (uint_t)TI_GETPEERNAME, "TI_GETPEERNAME", NULL },
+ { (uint_t)TI_SETMYNAME, "TI_SETMYNAME", NULL },
+ { (uint_t)TI_SETPEERNAME, "TI_SETPEERNAME", NULL },
+#endif
+#ifdef V_PREAD
+ { (uint_t)V_PREAD, "V_PREAD", NULL },
+ { (uint_t)V_PWRITE, "V_PWRITE", NULL },
+ { (uint_t)V_PDREAD, "V_PDREAD", NULL },
+ { (uint_t)V_PDWRITE, "V_PDWRITE", NULL },
+#if !defined(__i386) && !defined(__amd64)
+ { (uint_t)V_GETSSZ, "V_GETSSZ", NULL },
+#endif /* !__i386 */
+#endif
+ /* audio */
+ { (uint_t)AUDIO_GETINFO, "AUDIO_GETINFO", NULL },
+ { (uint_t)AUDIO_SETINFO, "AUDIO_SETINFO", NULL },
+ { (uint_t)AUDIO_DRAIN, "AUDIO_DRAIN", NULL },
+ { (uint_t)AUDIO_GETDEV, "AUDIO_GETDEV", NULL },
+ { (uint_t)AUDIO_DIAG_LOOPBACK, "AUDIO_DIAG_LOOPBACK", NULL },
+ { (uint_t)AUDIO_GET_CH_NUMBER, "AUDIO_GET_CH_NUMBER", NULL },
+ { (uint_t)AUDIO_GET_CH_TYPE, "AUDIO_GET_CH_TYPE", NULL },
+ { (uint_t)AUDIO_GET_NUM_CHS, "AUDIO_GET_NUM_CHS", NULL },
+ { (uint_t)AUDIO_GET_AD_DEV, "AUDIO_GET_AD_DEV", NULL },
+ { (uint_t)AUDIO_GET_APM_DEV, "AUDIO_GET_APM_DEV", NULL },
+ { (uint_t)AUDIO_GET_AS_DEV, "AUDIO_GET_AS_DEV", NULL },
+ { (uint_t)AUDIO_MIXER_MULTIPLE_OPEN, "AUDIO_MIXER_MULTIPLE_OPEN",
+ NULL },
+ { (uint_t)AUDIO_MIXER_SINGLE_OPEN, "AUDIO_MIXER_SINGLE_OPEN",
+ NULL },
+ { (uint_t)AUDIO_MIXER_GET_SAMPLE_RATES, "AUDIO_MIXER_GET_SAMPLE_RATES",
+ NULL },
+ { (uint_t)AUDIO_MIXERCTL_GETINFO, "AUDIO_MIXERCTL_GETINFO",
+ NULL },
+ { (uint_t)AUDIO_MIXERCTL_SETINFO, "AUDIO_MIXERCTL_SETINFO",
+ NULL },
+ { (uint_t)AUDIO_MIXERCTL_GET_CHINFO, "AUDIO_MIXERCTL_GET_CHINFO",
+ NULL },
+ { (uint_t)AUDIO_MIXERCTL_SET_CHINFO, "AUDIO_MIXERCTL_SET_CHINFO",
+ NULL },
+ { (uint_t)AUDIO_MIXERCTL_GET_MODE, "AUDIO_MIXERCTL_GET_MODE",
+ NULL },
+ { (uint_t)AUDIO_MIXERCTL_SET_MODE, "AUDIO_MIXERCTL_SET_MODE",
+ NULL },
+ /* new style Boomer (OSS) ioctls */
+ { (uint_t)SNDCTL_SYSINFO, "SNDCTL_SYSINFO", NULL },
+ { (uint_t)SNDCTL_AUDIOINFO, "SNDCTL_AUDIOINFO", NULL },
+ { (uint_t)SNDCTL_AUDIOINFO_EX, "SNDCTL_AUDIOINFO_EX", NULL },
+ { (uint_t)SNDCTL_MIXERINFO, "SNDCTL_MIXERINFO", NULL },
+ { (uint_t)SNDCTL_CARDINFO, "SNDCTL_CARDINFO", NULL },
+ { (uint_t)SNDCTL_ENGINEINFO, "SNDCTL_ENGINEINFO", NULL },
+ { (uint_t)SNDCTL_MIX_NRMIX, "SNDCTL_MIX_NRMIX", NULL },
+ { (uint_t)SNDCTL_MIX_NREXT, "SNDCTL_MIX_NREXT", NULL },
+ { (uint_t)SNDCTL_MIX_EXTINFO, "SNDCTL_MIX_EXTINFO", NULL },
+ { (uint_t)SNDCTL_MIX_READ, "SNDCTL_MIX_READ", NULL },
+ { (uint_t)SNDCTL_MIX_WRITE, "SNDCTL_MIX_WRITE", NULL },
+ { (uint_t)SNDCTL_MIX_ENUMINFO, "SNDCTL_MIX_ENUMINFO", NULL },
+ { (uint_t)SNDCTL_MIX_DESCRIPTION, "SNDCTL_MIX_DESCRIPTION",
+ NULL },
+ { (uint_t)SNDCTL_SETSONG, "SNDCTL_SETSONG", NULL },
+ { (uint_t)SNDCTL_GETSONG, "SNDCTL_GETSONG", NULL },
+ { (uint_t)SNDCTL_SETNAME, "SNDCTL_SETNAME", NULL },
+ { (uint_t)SNDCTL_SETLABEL, "SNDCTL_SETLABEL", NULL },
+ { (uint_t)SNDCTL_GETLABEL, "SNDCTL_GETLABEL", NULL },
+ { (uint_t)SNDCTL_DSP_HALT, "SNDCTL_DSP_HALT", NULL },
+ { (uint_t)SNDCTL_DSP_RESET, "SNDCTL_DSP_RESET", NULL },
+ { (uint_t)SNDCTL_DSP_SYNC, "SNDCTL_DSP_SYNC", NULL },
+ { (uint_t)SNDCTL_DSP_SPEED, "SNDCTL_DSP_SPEED", NULL },
+ { (uint_t)SNDCTL_DSP_STEREO, "SNDCTL_DSP_STEREO", NULL },
+ { (uint_t)SNDCTL_DSP_GETBLKSIZE, "SNDCTL_DSP_GETBLKSIZE",
+ NULL },
+ { (uint_t)SNDCTL_DSP_SAMPLESIZE, "SNDCTL_DSP_SAMPLESIZE",
+ NULL },
+ { (uint_t)SNDCTL_DSP_CHANNELS, "SNDCTL_DSP_CHANNELS", NULL },
+ { (uint_t)SNDCTL_DSP_POST, "SNDCTL_DSP_POST", NULL },
+ { (uint_t)SNDCTL_DSP_SUBDIVIDE, "SNDCTL_DSP_SUBDIVIDE", NULL },
+ { (uint_t)SNDCTL_DSP_SETFRAGMENT, "SNDCTL_DSP_SETFRAGMENT",
+ NULL },
+ { (uint_t)SNDCTL_DSP_GETFMTS, "SNDCTL_DSP_GETFMTS", NULL },
+ { (uint_t)SNDCTL_DSP_SETFMT, "SNDCTL_DSP_SETFMT", NULL },
+ { (uint_t)SNDCTL_DSP_GETOSPACE, "SNDCTL_DSP_GETOSPACE", NULL },
+ { (uint_t)SNDCTL_DSP_GETISPACE, "SNDCTL_DSP_GETISPACE", NULL },
+ { (uint_t)SNDCTL_DSP_GETCAPS, "SNDCTL_DSP_CAPS", NULL },
+ { (uint_t)SNDCTL_DSP_GETTRIGGER, "SNDCTL_DSP_GETTRIGGER",
+ NULL },
+ { (uint_t)SNDCTL_DSP_SETTRIGGER, "SNDCTL_DSP_SETTRIGGER",
+ NULL },
+ { (uint_t)SNDCTL_DSP_GETIPTR, "SNDCTL_DSP_GETIPTR", NULL },
+ { (uint_t)SNDCTL_DSP_GETOPTR, "SNDCTL_DSP_GETOPTR", NULL },
+ { (uint_t)SNDCTL_DSP_SETSYNCRO, "SNDCTL_DSP_SETSYNCRO", NULL },
+ { (uint_t)SNDCTL_DSP_SETDUPLEX, "SNDCTL_DSP_SETDUPLEX", NULL },
+ { (uint_t)SNDCTL_DSP_PROFILE, "SNDCTL_DSP_PROFILE", NULL },
+ { (uint_t)SNDCTL_DSP_GETODELAY, "SNDCTL_DSP_GETODELAY", NULL },
+ { (uint_t)SNDCTL_DSP_GETPLAYVOL, "SNDCTL_DSP_GETPLAYVOL",
+ NULL },
+ { (uint_t)SNDCTL_DSP_SETPLAYVOL, "SNDCTL_DSP_SETPLAYVOL",
+ NULL },
+ { (uint_t)SNDCTL_DSP_GETERROR, "SNDCTL_DSP_GETERROR", NULL },
+ { (uint_t)SNDCTL_DSP_READCTL, "SNDCTL_DSP_READCTL", NULL },
+ { (uint_t)SNDCTL_DSP_WRITECTL, "SNDCTL_DSP_WRITECTL", NULL },
+ { (uint_t)SNDCTL_DSP_SYNCGROUP, "SNDCTL_DSP_SYNCGROUP", NULL },
+ { (uint_t)SNDCTL_DSP_SYNCSTART, "SNDCTL_DSP_SYNCSTART", NULL },
+ { (uint_t)SNDCTL_DSP_COOKEDMODE, "SNDCTL_DSP_COOKEDMODE",
+ NULL },
+ { (uint_t)SNDCTL_DSP_SILENCE, "SNDCTL_DSP_SILENCE", NULL },
+ { (uint_t)SNDCTL_DSP_SKIP, "SNDCTL_DSP_SKIP", NULL },
+ { (uint_t)SNDCTL_DSP_HALT_INPUT, "SNDCTL_DSP_HALT_INPUT",
+ NULL },
+ { (uint_t)SNDCTL_DSP_HALT_OUTPUT, "SNDCTL_DSP_HALT_OUTPUT",
+ NULL },
+ { (uint_t)SNDCTL_DSP_LOW_WATER, "SNDCTL_DSP_LOW_WATER", NULL },
+ { (uint_t)SNDCTL_DSP_CURRENT_OPTR, "SNDCTL_DSP_CURRENT_OPTR",
+ NULL },
+ { (uint_t)SNDCTL_DSP_CURRENT_IPTR, "SNDCTL_DSP_CURRENT_IPTR",
+ NULL },
+ { (uint_t)SNDCTL_DSP_GET_RECSRC_NAMES, "SNDCTL_DSP_GET_RECSRC_NAMES",
+ NULL },
+ { (uint_t)SNDCTL_DSP_GET_RECSRC, "SNDCTL_DSP_GET_RECSRC",
+ NULL },
+ { (uint_t)SNDCTL_DSP_SET_RECSRC, "SNDCTL_DSP_SET_RECSRC",
+ NULL },
+ { (uint_t)SNDCTL_DSP_GET_PLAYTGT_NAMES, "SNDCTL_DSP_GET_PLAYTGT_NAMES",
+ NULL },
+ { (uint_t)SNDCTL_DSP_GET_PLAYTGT, "SNDCTL_DSP_GET_PLAYTGT",
+ NULL },
+ { (uint_t)SNDCTL_DSP_SET_PLAYTGT, "SNDCTL_DSP_SET_PLAYTGT",
+ NULL },
+ { (uint_t)SNDCTL_DSP_GETRECVOL, "SNDCTL_DSP_GETRECVOL",
+ NULL },
+ { (uint_t)SNDCTL_DSP_SETRECVOL, "SNDCTL_DSP_SETRECVOL",
+ NULL },
+ { (uint_t)SNDCTL_DSP_GET_CHNORDER, "SNDCTL_DSP_GET_CHNORDER",
+ NULL },
+ { (uint_t)SNDCTL_DSP_SET_CHNORDER, "SNDCTL_DSP_SET_CHNORDER",
+ NULL },
+ { (uint_t)SNDCTL_DSP_GETIPEAKS, "SNDCTL_DSP_GETIPEAKS", NULL },
+ { (uint_t)SNDCTL_DSP_GETOPEAKS, "SNDCTL_DSP_GETOPEAKS", NULL },
+ { (uint_t)SNDCTL_DSP_POLICY, "SNDCTL_DSP_POLICY", NULL },
+ { (uint_t)SNDCTL_DSP_GETCHANNELMASK, "SNDCTL_DSP_GETCHANNELMASK",
+ NULL },
+ { (uint_t)SNDCTL_DSP_BIND_CHANNEL, "SNDCTL_DSP_BIND_CHANNEL",
+ NULL },
+ { (uint_t)SOUND_MIXER_READ_VOLUME, "SOUND_MIXER_READ_VOLUME",
+ NULL },
+ { (uint_t)SOUND_MIXER_READ_OGAIN, "SOUND_MIXER_READ_OGAIN",
+ NULL },
+ { (uint_t)SOUND_MIXER_READ_PCM, "SOUND_MIXER_READ_PCM", NULL },
+ { (uint_t)SOUND_MIXER_READ_IGAIN, "SOUND_MIXER_READ_IGAIN",
+ NULL },
+ { (uint_t)SOUND_MIXER_READ_RECLEV, "SOUND_MIXER_READ_RECLEV",
+ NULL },
+ { (uint_t)SOUND_MIXER_READ_RECSRC, "SOUND_MIXER_READ_RECSRC",
+ NULL },
+ { (uint_t)SOUND_MIXER_READ_DEVMASK, "SOUND_MIXER_READ_DEVMASK",
+ NULL },
+ { (uint_t)SOUND_MIXER_READ_RECMASK, "SOUND_MIXER_READ_RECMASK",
+ NULL },
+ { (uint_t)SOUND_MIXER_READ_CAPS, "SOUND_MIXER_READ_CAPS",
+ NULL },
+ { (uint_t)SOUND_MIXER_READ_STEREODEVS, "SOUND_MIXER_READ_STEREODEVS",
+ NULL },
+ { (uint_t)SOUND_MIXER_READ_RECGAIN, "SOUND_MIXER_READ_RECGAIN",
+ NULL },
+ { (uint_t)SOUND_MIXER_READ_MONGAIN, "SOUND_MIXER_READ_MONGAIN",
+ NULL },
+ { (uint_t)SOUND_MIXER_WRITE_VOLUME, "SOUND_MIXER_WRITE_VOLUME",
+ NULL },
+ { (uint_t)SOUND_MIXER_WRITE_OGAIN, "SOUND_MIXER_WRITE_OGAIN",
+ NULL },
+ { (uint_t)SOUND_MIXER_WRITE_PCM, "SOUND_MIXER_WRITE_PCM",
+ NULL },
+ { (uint_t)SOUND_MIXER_WRITE_IGAIN, "SOUND_MIXER_WRITE_IGAIN",
+ NULL },
+ { (uint_t)SOUND_MIXER_WRITE_RECLEV, "SOUND_MIXER_WRITE_RECLEV",
+ NULL },
+ { (uint_t)SOUND_MIXER_WRITE_RECSRC, "SOUND_MIXER_WRITE_RECSRC",
+ NULL },
+ { (uint_t)SOUND_MIXER_WRITE_RECGAIN, "SOUND_MIXER_WRITE_RECGAIN",
+ NULL },
+ { (uint_t)SOUND_MIXER_WRITE_MONGAIN, "SOUND_MIXER_WRITE_MONGAIN",
+ NULL },
+
+ /* STREAMS redirection ioctls */
+ { (uint_t)SRIOCSREDIR, "SRIOCSREDIR", NULL },
+ { (uint_t)SRIOCISREDIR, "SRIOCISREDIR", NULL },
+ { (uint_t)CPCIO_BIND, "CPCIO_BIND", NULL },
+ { (uint_t)CPCIO_SAMPLE, "CPCIO_SAMPLE", NULL },
+ { (uint_t)CPCIO_RELE, "CPCIO_RELE", NULL },
+ /* /dev/poll ioctl() control codes */
+ { (uint_t)DP_POLL, "DP_POLL", NULL },
+ { (uint_t)DP_ISPOLLED, "DP_ISPOLLED", NULL },
+ /* the old /proc ioctl() control codes */
+#define PIOC ('q'<<8)
+ { (uint_t)(PIOC|1), "PIOCSTATUS", NULL },
+ { (uint_t)(PIOC|2), "PIOCSTOP", NULL },
+ { (uint_t)(PIOC|3), "PIOCWSTOP", NULL },
+ { (uint_t)(PIOC|4), "PIOCRUN", NULL },
+ { (uint_t)(PIOC|5), "PIOCGTRACE", NULL },
+ { (uint_t)(PIOC|6), "PIOCSTRACE", NULL },
+ { (uint_t)(PIOC|7), "PIOCSSIG", NULL },
+ { (uint_t)(PIOC|8), "PIOCKILL", NULL },
+ { (uint_t)(PIOC|9), "PIOCUNKILL", NULL },
+ { (uint_t)(PIOC|10), "PIOCGHOLD", NULL },
+ { (uint_t)(PIOC|11), "PIOCSHOLD", NULL },
+ { (uint_t)(PIOC|12), "PIOCMAXSIG", NULL },
+ { (uint_t)(PIOC|13), "PIOCACTION", NULL },
+ { (uint_t)(PIOC|14), "PIOCGFAULT", NULL },
+ { (uint_t)(PIOC|15), "PIOCSFAULT", NULL },
+ { (uint_t)(PIOC|16), "PIOCCFAULT", NULL },
+ { (uint_t)(PIOC|17), "PIOCGENTRY", NULL },
+ { (uint_t)(PIOC|18), "PIOCSENTRY", NULL },
+ { (uint_t)(PIOC|19), "PIOCGEXIT", NULL },
+ { (uint_t)(PIOC|20), "PIOCSEXIT", NULL },
+ { (uint_t)(PIOC|21), "PIOCSFORK", NULL },
+ { (uint_t)(PIOC|22), "PIOCRFORK", NULL },
+ { (uint_t)(PIOC|23), "PIOCSRLC", NULL },
+ { (uint_t)(PIOC|24), "PIOCRRLC", NULL },
+ { (uint_t)(PIOC|25), "PIOCGREG", NULL },
+ { (uint_t)(PIOC|26), "PIOCSREG", NULL },
+ { (uint_t)(PIOC|27), "PIOCGFPREG", NULL },
+ { (uint_t)(PIOC|28), "PIOCSFPREG", NULL },
+ { (uint_t)(PIOC|29), "PIOCNICE", NULL },
+ { (uint_t)(PIOC|30), "PIOCPSINFO", NULL },
+ { (uint_t)(PIOC|31), "PIOCNMAP", NULL },
+ { (uint_t)(PIOC|32), "PIOCMAP", NULL },
+ { (uint_t)(PIOC|33), "PIOCOPENM", NULL },
+ { (uint_t)(PIOC|34), "PIOCCRED", NULL },
+ { (uint_t)(PIOC|35), "PIOCGROUPS", NULL },
+ { (uint_t)(PIOC|36), "PIOCGETPR", NULL },
+ { (uint_t)(PIOC|37), "PIOCGETU", NULL },
+ { (uint_t)(PIOC|38), "PIOCSET", NULL },
+ { (uint_t)(PIOC|39), "PIOCRESET", NULL },
+ { (uint_t)(PIOC|43), "PIOCUSAGE", NULL },
+ { (uint_t)(PIOC|44), "PIOCOPENPD", NULL },
+ { (uint_t)(PIOC|45), "PIOCLWPIDS", NULL },
+ { (uint_t)(PIOC|46), "PIOCOPENLWP", NULL },
+ { (uint_t)(PIOC|47), "PIOCLSTATUS", NULL },
+ { (uint_t)(PIOC|48), "PIOCLUSAGE", NULL },
+ { (uint_t)(PIOC|49), "PIOCNAUXV", NULL },
+ { (uint_t)(PIOC|50), "PIOCAUXV", NULL },
+ { (uint_t)(PIOC|51), "PIOCGXREGSIZE", NULL },
+ { (uint_t)(PIOC|52), "PIOCGXREG", NULL },
+ { (uint_t)(PIOC|53), "PIOCSXREG", NULL },
+ { (uint_t)(PIOC|101), "PIOCGWIN", NULL },
+ { (uint_t)(PIOC|103), "PIOCNLDT", NULL },
+ { (uint_t)(PIOC|104), "PIOCLDT", NULL },
+
+ /* ioctl's applicable on sockets */
+ { (uint_t)SIOCSHIWAT, "SIOCSHIWAT", NULL },
+ { (uint_t)SIOCGHIWAT, "SIOCGHIWAT", NULL },
+ { (uint_t)SIOCSLOWAT, "SIOCSLOWAT", NULL },
+ { (uint_t)SIOCGLOWAT, "SIOCGLOWAT", NULL },
+ { (uint_t)SIOCATMARK, "SIOCATMARK", NULL },
+ { (uint_t)SIOCSPGRP, "SIOCSPGRP", NULL },
+ { (uint_t)SIOCGPGRP, "SIOCGPGRP", NULL },
+ { (uint_t)SIOCADDRT, "SIOCADDRT", "rtentry" },
+ { (uint_t)SIOCDELRT, "SIOCDELRT", "rtentry" },
+ { (uint_t)SIOCGETVIFCNT, "SIOCGETVIFCNT", "sioc_vif_req" },
+ { (uint_t)SIOCGETSGCNT, "SIOCGETSGCNT", "sioc_sg_req" },
+ { (uint_t)SIOCGETLSGCNT, "SIOCGETLSGCNT", "sioc_lsg_req" },
+ { (uint_t)SIOCSIFADDR, "SIOCSIFADDR", "ifreq" },
+ { (uint_t)SIOCGIFADDR, "SIOCGIFADDR", "ifreq" },
+ { (uint_t)SIOCSIFDSTADDR, "SIOCSIFDSTADDR", "ifreq" },
+ { (uint_t)SIOCGIFDSTADDR, "SIOCGIFDSTADDR", "ifreq" },
+ { (uint_t)SIOCSIFFLAGS, "SIOCSIFFLAGS", "ifreq" },
+ { (uint_t)SIOCGIFFLAGS, "SIOCGIFFLAGS", "ifreq" },
+ { (uint_t)SIOCSIFMEM, "SIOCSIFMEM", "ifreq" },
+ { (uint_t)SIOCGIFMEM, "SIOCGIFMEM", "ifreq" },
+ { (uint_t)SIOCGIFCONF, "SIOCGIFCONF", "ifconf" },
+ { (uint_t)SIOCSIFMTU, "SIOCSIFMTU", "ifreq" },
+ { (uint_t)SIOCGIFMTU, "SIOCGIFMTU", "ifreq" },
+ { (uint_t)SIOCGIFBRDADDR, "SIOCGIFBRDADDR", "ifreq" },
+ { (uint_t)SIOCSIFBRDADDR, "SIOCSIFBRDADDR", "ifreq" },
+ { (uint_t)SIOCGIFNETMASK, "SIOCGIFNETMASK", "ifreq" },
+ { (uint_t)SIOCSIFNETMASK, "SIOCSIFNETMASK", "ifreq" },
+ { (uint_t)SIOCGIFMETRIC, "SIOCGIFMETRIC", "ifreq" },
+ { (uint_t)SIOCSIFMETRIC, "SIOCSIFMETRIC", "ifreq" },
+ { (uint_t)SIOCSARP, "SIOCSARP", "arpreq" },
+ { (uint_t)SIOCGARP, "SIOCGARP", "arpreq" },
+ { (uint_t)SIOCDARP, "SIOCDARP", "arpreq" },
+ { (uint_t)SIOCUPPER, "SIOCUPPER", "ifreq" },
+ { (uint_t)SIOCLOWER, "SIOCLOWER", "ifreq" },
+ { (uint_t)SIOCSETSYNC, "SIOCSETSYNC", "ifreq" },
+ { (uint_t)SIOCGETSYNC, "SIOCGETSYNC", "ifreq" },
+ { (uint_t)SIOCSSDSTATS, "SIOCSSDSTATS", "ifreq" },
+ { (uint_t)SIOCSSESTATS, "SIOCSSESTATS", "ifreq" },
+ { (uint_t)SIOCSPROMISC, "SIOCSPROMISC", NULL },
+ { (uint_t)SIOCADDMULTI, "SIOCADDMULTI", "ifreq" },
+ { (uint_t)SIOCDELMULTI, "SIOCDELMULTI", "ifreq" },
+ { (uint_t)SIOCGETNAME, "SIOCGETNAME", "sockaddr" },
+ { (uint_t)SIOCGETPEER, "SIOCGETPEER", "sockaddr" },
+ { (uint_t)IF_UNITSEL, "IF_UNITSEL", NULL },
+ { (uint_t)SIOCXPROTO, "SIOCXPROTO", NULL },
+ { (uint_t)SIOCIFDETACH, "SIOCIFDETACH", "ifreq" },
+ { (uint_t)SIOCGENPSTATS, "SIOCGENPSTATS", "ifreq" },
+ { (uint_t)SIOCX25XMT, "SIOCX25XMT", "ifreq" },
+ { (uint_t)SIOCX25RCV, "SIOCX25RCV", "ifreq" },
+ { (uint_t)SIOCX25TBL, "SIOCX25TBL", "ifreq" },
+ { (uint_t)SIOCSLGETREQ, "SIOCSLGETREQ", "ifreq" },
+ { (uint_t)SIOCSLSTAT, "SIOCSLSTAT", "ifreq" },
+ { (uint_t)SIOCSIFNAME, "SIOCSIFNAME", "ifreq" },
+ { (uint_t)SIOCGENADDR, "SIOCGENADDR", "ifreq" },
+ { (uint_t)SIOCGIFNUM, "SIOCGIFNUM", NULL },
+ { (uint_t)SIOCGIFMUXID, "SIOCGIFMUXID", "ifreq" },
+ { (uint_t)SIOCSIFMUXID, "SIOCSIFMUXID", "ifreq" },
+ { (uint_t)SIOCGIFINDEX, "SIOCGIFINDEX", "ifreq" },
+ { (uint_t)SIOCSIFINDEX, "SIOCSIFINDEX", "ifreq" },
+ { (uint_t)SIOCLIFREMOVEIF, "SIOCLIFREMOVEIF", "lifreq" },
+ { (uint_t)SIOCLIFADDIF, "SIOCLIFADDIF", "lifreq" },
+ { (uint_t)SIOCSLIFADDR, "SIOCSLIFADDR", "lifreq" },
+ { (uint_t)SIOCGLIFADDR, "SIOCGLIFADDR", "lifreq" },
+ { (uint_t)SIOCSLIFDSTADDR, "SIOCSLIFDSTADDR", "lifreq" },
+ { (uint_t)SIOCGLIFDSTADDR, "SIOCGLIFDSTADDR", "lifreq" },
+ { (uint_t)SIOCSLIFFLAGS, "SIOCSLIFFLAGS", "lifreq" },
+ { (uint_t)SIOCGLIFFLAGS, "SIOCGLIFFLAGS", "lifreq" },
+ { (uint_t)SIOCGLIFCONF, "SIOCGLIFCONF", "lifconf" },
+ { (uint_t)SIOCSLIFMTU, "SIOCSLIFMTU", "lifreq" },
+ { (uint_t)SIOCGLIFMTU, "SIOCGLIFMTU", "lifreq" },
+ { (uint_t)SIOCGLIFBRDADDR, "SIOCGLIFBRDADDR", "lifreq" },
+ { (uint_t)SIOCSLIFBRDADDR, "SIOCSLIFBRDADDR", "lifreq" },
+ { (uint_t)SIOCGLIFNETMASK, "SIOCGLIFNETMASK", "lifreq" },
+ { (uint_t)SIOCSLIFNETMASK, "SIOCSLIFNETMASK", "lifreq" },
+ { (uint_t)SIOCGLIFMETRIC, "SIOCGLIFMETRIC", "lifreq" },
+ { (uint_t)SIOCSLIFMETRIC, "SIOCSLIFMETRIC", "lifreq" },
+ { (uint_t)SIOCSLIFNAME, "SIOCSLIFNAME", "lifreq" },
+ { (uint_t)SIOCGLIFNUM, "SIOCGLIFNUM", "lifnum" },
+ { (uint_t)SIOCGLIFMUXID, "SIOCGLIFMUXID", "lifreq" },
+ { (uint_t)SIOCSLIFMUXID, "SIOCSLIFMUXID", "lifreq" },
+ { (uint_t)SIOCGLIFINDEX, "SIOCGLIFINDEX", "lifreq" },
+ { (uint_t)SIOCSLIFINDEX, "SIOCSLIFINDEX", "lifreq" },
+ { (uint_t)SIOCSLIFTOKEN, "SIOCSLIFTOKEN", "lifreq" },
+ { (uint_t)SIOCGLIFTOKEN, "SIOCGLIFTOKEN", "lifreq" },
+ { (uint_t)SIOCSLIFSUBNET, "SIOCSLIFSUBNET", "lifreq" },
+ { (uint_t)SIOCGLIFSUBNET, "SIOCGLIFSUBNET", "lifreq" },
+ { (uint_t)SIOCSLIFLNKINFO, "SIOCSLIFLNKINFO", "lifreq" },
+ { (uint_t)SIOCGLIFLNKINFO, "SIOCGLIFLNKINFO", "lifreq" },
+ { (uint_t)SIOCLIFDELND, "SIOCLIFDELND", "lifreq" },
+ { (uint_t)SIOCLIFGETND, "SIOCLIFGETND", "lifreq" },
+ { (uint_t)SIOCLIFSETND, "SIOCLIFSETND", "lifreq" },
+ { (uint_t)SIOCTMYADDR, "SIOCTMYADDR", "sioc_addrreq" },
+ { (uint_t)SIOCTONLINK, "SIOCTONLINK", "sioc_addrreq" },
+ { (uint_t)SIOCTMYSITE, "SIOCTMYSITE", "sioc_addrreq" },
+ { (uint_t)SIOCGLIFBINDING, "SIOCGLIFBINDING", "lifreq" },
+ { (uint_t)SIOCSLIFGROUPNAME, "SIOCSLIFGROUPNAME", "lifreq" },
+ { (uint_t)SIOCGLIFGROUPNAME, "SIOCGLIFGROUPNAME", "lifreq" },
+ { (uint_t)SIOCGLIFGROUPINFO, "SIOCGLIFGROUPINFO", "lifgroupinfo" },
+ { (uint_t)SIOCGDSTINFO, "SIOCGDSTINFO", NULL },
+ { (uint_t)SIOCGIP6ADDRPOLICY, "SIOCGIP6ADDRPOLICY", NULL },
+ { (uint_t)SIOCSIP6ADDRPOLICY, "SIOCSIP6ADDRPOLICY", NULL },
+ { (uint_t)SIOCSXARP, "SIOCSXARP", "xarpreq" },
+ { (uint_t)SIOCGXARP, "SIOCGXARP", "xarpreq" },
+ { (uint_t)SIOCDXARP, "SIOCDXARP", "xarpreq" },
+ { (uint_t)SIOCGLIFZONE, "SIOCGLIFZONE", "lifreq" },
+ { (uint_t)SIOCSLIFZONE, "SIOCSLIFZONE", "lifreq" },
+ { (uint_t)SIOCSCTPSOPT, "SIOCSCTPSOPT", NULL },
+ { (uint_t)SIOCSCTPGOPT, "SIOCSCTPGOPT", NULL },
+ { (uint_t)SIOCSCTPPEELOFF, "SIOPCSCTPPEELOFF", "int" },
+ { (uint_t)SIOCGLIFUSESRC, "SIOCGLIFUSESRC", "lifreq" },
+ { (uint_t)SIOCSLIFUSESRC, "SIOCSLIFUSESRC", "lifreq" },
+ { (uint_t)SIOCGLIFSRCOF, "SIOCGLIFSRCOF", "lifsrcof" },
+ { (uint_t)SIOCGMSFILTER, "SIOCGMSFILTER", "group_filter" },
+ { (uint_t)SIOCSMSFILTER, "SIOCSMSFILTER", "group_filter" },
+ { (uint_t)SIOCGIPMSFILTER, "SIOCGIPMSFILTER", "ip_msfilter" },
+ { (uint_t)SIOCSIPMSFILTER, "SIOCSIPMSFILTER", "ip_msfilter" },
+ { (uint_t)SIOCGLIFDADSTATE, "SIOCGLIFDADSTATE", "lifreq" },
+ { (uint_t)SIOCSLIFPREFIX, "SIOCSLIFPREFIX", "lifreq" },
+ { (uint_t)SIOCGSTAMP, "SIOCGSTAMP", "timeval" },
+ { (uint_t)SIOCGIFHWADDR, "SIOCGIFHWADDR", "ifreq" },
+ { (uint_t)SIOCGLIFHWADDR, "SIOCGLIFHWADDR", "lifreq" },
+
+ /* DES encryption */
+ { (uint_t)DESIOCBLOCK, "DESIOCBLOCK", "desparams" },
+ { (uint_t)DESIOCQUICK, "DESIOCQUICK", "desparams" },
+
+ /* Printing system */
+ { (uint_t)PRNIOC_GET_IFCAP, "PRNIOC_GET_IFCAP", NULL },
+ { (uint_t)PRNIOC_SET_IFCAP, "PRNIOC_SET_IFCAP", NULL },
+ { (uint_t)PRNIOC_GET_IFINFO, "PRNIOC_GET_IFINFO",
+ "prn_interface_info" },
+ { (uint_t)PRNIOC_GET_STATUS, "PRNIOC_GET_STATUS", NULL },
+ { (uint_t)PRNIOC_GET_1284_DEVID, "PRNIOC_GET_1284_DEVID",
+ "prn_1284_device_id" },
+ { (uint_t)PRNIOC_GET_1284_STATUS,
+ "PRNIOC_GET_IFCANIOC_GET_1284_STATUS", NULL },
+ { (uint_t)PRNIOC_GET_TIMEOUTS, "PRNIOC_GET_TIMEOUTS",
+ "prn_timeouts" },
+ { (uint_t)PRNIOC_SET_TIMEOUTS, "PRNIOC_SET_TIMEOUTS",
+ "prn_timeouts" },
+ { (uint_t)PRNIOC_RESET, "PRNIOC_RESET", NULL },
+
+ /* DTrace */
+ { (uint_t)DTRACEIOC_PROVIDER, "DTRACEIOC_PROVIDER", NULL },
+ { (uint_t)DTRACEIOC_PROBES, "DTRACEIOC_PROBES", NULL },
+ { (uint_t)DTRACEIOC_BUFSNAP, "DTRACEIOC_BUFSNAP", NULL },
+ { (uint_t)DTRACEIOC_PROBEMATCH, "DTRACEIOC_PROBEMATCH", NULL },
+ { (uint_t)DTRACEIOC_ENABLE, "DTRACEIOC_ENABLE", NULL },
+ { (uint_t)DTRACEIOC_AGGSNAP, "DTRACEIOC_AGGSNAP", NULL },
+ { (uint_t)DTRACEIOC_EPROBE, "DTRACEIOC_EPROBE", NULL },
+ { (uint_t)DTRACEIOC_PROBEARG, "DTRACEIOC_PROBEARG", NULL },
+ { (uint_t)DTRACEIOC_CONF, "DTRACEIOC_CONF", NULL },
+ { (uint_t)DTRACEIOC_STATUS, "DTRACEIOC_STATUS", NULL },
+ { (uint_t)DTRACEIOC_GO, "DTRACEIOC_GO", NULL },
+ { (uint_t)DTRACEIOC_STOP, "DTRACEIOC_STOP", NULL },
+ { (uint_t)DTRACEIOC_AGGDESC, "DTRACEIOC_AGGDESC", NULL },
+ { (uint_t)DTRACEIOC_FORMAT, "DTRACEIOC_FORMAT", NULL },
+ { (uint_t)DTRACEIOC_DOFGET, "DTRACEIOC_DOFGET", NULL },
+ { (uint_t)DTRACEIOC_REPLICATE, "DTRACEIOC_REPLICATE", NULL },
+
+ { (uint_t)DTRACEHIOC_ADD, "DTRACEHIOC_ADD", NULL },
+ { (uint_t)DTRACEHIOC_REMOVE, "DTRACEHIOC_REMOVE", NULL },
+ { (uint_t)DTRACEHIOC_ADDDOF, "DTRACEHIOC_ADDDOF", NULL },
+
+ /* /dev/cryptoadm ioctl() control codes */
+ { (uint_t)CRYPTO_GET_VERSION, "CRYPTO_GET_VERSION", NULL },
+ { (uint_t)CRYPTO_GET_DEV_LIST, "CRYPTO_GET_DEV_LIST", NULL },
+ { (uint_t)CRYPTO_GET_SOFT_LIST, "CRYPTO_GET_SOFT_LIST", NULL },
+ { (uint_t)CRYPTO_GET_DEV_INFO, "CRYPTO_GET_DEV_INFO", NULL },
+ { (uint_t)CRYPTO_GET_SOFT_INFO, "CRYPTO_GET_SOFT_INFO", NULL },
+ { (uint_t)CRYPTO_LOAD_DEV_DISABLED, "CRYPTO_LOAD_DEV_DISABLED",
+ NULL },
+ { (uint_t)CRYPTO_LOAD_SOFT_DISABLED, "CRYPTO_LOAD_SOFT_DISABLED",
+ NULL },
+ { (uint_t)CRYPTO_UNLOAD_SOFT_MODULE, "CRYPTO_UNLOAD_SOFT_MODULE",
+ NULL },
+ { (uint_t)CRYPTO_LOAD_SOFT_CONFIG, "CRYPTO_LOAD_SOFT_CONFIG",
+ NULL },
+ { (uint_t)CRYPTO_POOL_CREATE, "CRYPTO_POOL_CREATE", NULL },
+ { (uint_t)CRYPTO_POOL_WAIT, "CRYPTO_POOL_WAIT", NULL },
+ { (uint_t)CRYPTO_POOL_RUN, "CRYPTO_POOL_RUN", NULL },
+ { (uint_t)CRYPTO_LOAD_DOOR, "CRYPTO_LOAD_DOOR", NULL },
+
+ /* /dev/crypto ioctl() control codes */
+ { (uint_t)CRYPTO_GET_FUNCTION_LIST, "CRYPTO_GET_FUNCTION_LIST",
+ NULL },
+ { (uint_t)CRYPTO_GET_MECHANISM_NUMBER, "CRYPTO_GET_MECHANISM_NUMBER",
+ NULL },
+ { (uint_t)CRYPTO_OPEN_SESSION, "CRYPTO_OPEN_SESSION", NULL },
+ { (uint_t)CRYPTO_CLOSE_SESSION, "CRYPTO_CLOSE_SESSION", NULL },
+ { (uint_t)CRYPTO_CLOSE_ALL_SESSIONS, "CRYPTO_CLOSE_ALL_SESSIONS",
+ NULL },
+ { (uint_t)CRYPTO_LOGIN, "CRYPTO_LOGIN", NULL },
+ { (uint_t)CRYPTO_LOGOUT, "CRYPTO_LOGOUT", NULL },
+ { (uint_t)CRYPTO_ENCRYPT, "CRYPTO_ENCRYPT", NULL },
+ { (uint_t)CRYPTO_ENCRYPT_INIT, "CRYPTO_ENCRYPT_INIT", NULL },
+ { (uint_t)CRYPTO_ENCRYPT_UPDATE, "CRYPTO_ENCRYPT_UPDATE",
+ NULL },
+ { (uint_t)CRYPTO_ENCRYPT_FINAL, "CRYPTO_ENCRYPT_FINAL", NULL },
+ { (uint_t)CRYPTO_DECRYPT, "CRYPTO_DECRYPT", NULL },
+ { (uint_t)CRYPTO_DECRYPT_INIT, "CRYPTO_DECRYPT_INIT", NULL },
+ { (uint_t)CRYPTO_DECRYPT_UPDATE, "CRYPTO_DECRYPT_UPDATE",
+ NULL },
+ { (uint_t)CRYPTO_DECRYPT_FINAL, "CRYPTO_DECRYPT_FINAL", NULL },
+ { (uint_t)CRYPTO_DIGEST, "CRYPTO_DIGEST", NULL },
+ { (uint_t)CRYPTO_DIGEST_INIT, "CRYPTO_DIGEST_INIT", NULL },
+ { (uint_t)CRYPTO_DIGEST_UPDATE, "CRYPTO_DIGEST_UPDATE", NULL },
+ { (uint_t)CRYPTO_DIGEST_KEY, "CRYPTO_DIGEST_KEY", NULL },
+ { (uint_t)CRYPTO_DIGEST_FINAL, "CRYPTO_DIGEST_FINAL", NULL },
+ { (uint_t)CRYPTO_MAC, "CRYPTO_MAC", NULL },
+ { (uint_t)CRYPTO_MAC_INIT, "CRYPTO_MAC_INIT", NULL },
+ { (uint_t)CRYPTO_MAC_UPDATE, "CRYPTO_MAC_UPDATE", NULL },
+ { (uint_t)CRYPTO_MAC_FINAL, "CRYPTO_MAC_FINAL", NULL },
+ { (uint_t)CRYPTO_SIGN, "CRYPTO_SIGN", NULL },
+ { (uint_t)CRYPTO_SIGN_INIT, "CRYPTO_SIGN_INIT", NULL },
+ { (uint_t)CRYPTO_SIGN_UPDATE, "CRYPTO_SIGN_UPDATE", NULL },
+ { (uint_t)CRYPTO_SIGN_FINAL, "CRYPTO_SIGN_FINAL", NULL },
+ { (uint_t)CRYPTO_SIGN_RECOVER_INIT, "CRYPTO_SIGN_RECOVER_INIT",
+ NULL },
+ { (uint_t)CRYPTO_SIGN_RECOVER, "CRYPTO_SIGN_RECOVER", NULL },
+ { (uint_t)CRYPTO_VERIFY, "CRYPTO_VERIFY", NULL },
+ { (uint_t)CRYPTO_VERIFY_INIT, "CRYPTO_VERIFY_INIT", NULL },
+ { (uint_t)CRYPTO_VERIFY_UPDATE, "CRYPTO_VERIFY_UPDATE", NULL },
+ { (uint_t)CRYPTO_VERIFY_FINAL, "CRYPTO_VERIFY_FINAL", NULL },
+ { (uint_t)CRYPTO_VERIFY_RECOVER_INIT, "CRYPTO_VERIFY_RECOVER_INIT",
+ NULL },
+ { (uint_t)CRYPTO_VERIFY_RECOVER, "CRYPTO_VERIFY_RECOVER",
+ NULL },
+ { (uint_t)CRYPTO_DIGEST_ENCRYPT_UPDATE, "CRYPTO_DIGEST_ENCRYPT_UPDATE",
+ NULL },
+ { (uint_t)CRYPTO_DECRYPT_DIGEST_UPDATE, "CRYPTO_DECRYPT_DIGEST_UPDATE",
+ NULL },
+ { (uint_t)CRYPTO_SIGN_ENCRYPT_UPDATE, "CRYPTO_SIGN_ENCRYPT_UPDATE",
+ NULL },
+ { (uint_t)CRYPTO_DECRYPT_VERIFY_UPDATE, "CRYPTO_DECRYPT_VERIFY_UPDATE",
+ NULL },
+ { (uint_t)CRYPTO_SEED_RANDOM, "CRYPTO_SEED_RANDOM", NULL },
+ { (uint_t)CRYPTO_GENERATE_RANDOM, "CRYPTO_GENERATE_RANDOM",
+ NULL },
+ { (uint_t)CRYPTO_OBJECT_CREATE, "CRYPTO_OBJECT_CREATE", NULL },
+ { (uint_t)CRYPTO_OBJECT_COPY, "CRYPTO_OBJECT_COPY", NULL },
+ { (uint_t)CRYPTO_OBJECT_DESTROY, "CRYPTO_OBJECT_DESTROY",
+ NULL },
+ { (uint_t)CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE,
+ "CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE", NULL },
+ { (uint_t)CRYPTO_OBJECT_GET_SIZE, "CRYPTO_OBJECT_GET_SIZE", NULL },
+ { (uint_t)CRYPTO_OBJECT_SET_ATTRIBUTE_VALUE,
+ "CRYPTO_OBJECT_SET_ATTRIBUTE_VALUE", NULL },
+ { (uint_t)CRYPTO_OBJECT_FIND_INIT, "CRYPTO_OBJECT_FIND_INIT",
+ NULL },
+ { (uint_t)CRYPTO_OBJECT_FIND_UPDATE, "CRYPTO_OBJECT_FIND_UPDATE",
+ NULL },
+ { (uint_t)CRYPTO_OBJECT_FIND_FINAL, "CRYPTO_OBJECT_FIND_FINAL",
+ NULL },
+ { (uint_t)CRYPTO_GENERATE_KEY, "CRYPTO_GENERATE_KEY", NULL },
+ { (uint_t)CRYPTO_GENERATE_KEY_PAIR, "CRYPTO_GENERATE_KEY_PAIR",
+ NULL },
+ { (uint_t)CRYPTO_WRAP_KEY, "CRYPTO_WRAP_KEY", NULL },
+ { (uint_t)CRYPTO_UNWRAP_KEY, "CRYPTO_UNWRAP_KEY", NULL },
+ { (uint_t)CRYPTO_DERIVE_KEY, "CRYPTO_DERIVE_KEY", NULL },
+ { (uint_t)CRYPTO_GET_PROVIDER_LIST, "CRYPTO_GET_PROVIDER_LIST",
+ NULL },
+ { (uint_t)CRYPTO_GET_PROVIDER_INFO, "CRYPTO_GET_PROVIDER_INFO",
+ NULL },
+ { (uint_t)CRYPTO_GET_PROVIDER_MECHANISMS,
+ "CRYPTO_GET_PROVIDER_MECHANISMS", NULL },
+ { (uint_t)CRYPTO_GET_PROVIDER_MECHANISM_INFO,
+ "CRYPTO_GET_PROVIDER_MECHANISM_INFO", NULL },
+ { (uint_t)CRYPTO_INIT_TOKEN, "CRYPTO_INIT_TOKEN", NULL },
+ { (uint_t)CRYPTO_INIT_PIN, "CRYPTO_INIT_PIN", NULL },
+ { (uint_t)CRYPTO_SET_PIN, "CRYPTO_SET_PIN", NULL },
+ { (uint_t)CRYPTO_NOSTORE_GENERATE_KEY,
+ "CRYPTO_NOSTORE_GENERATE_KEY", NULL },
+ { (uint_t)CRYPTO_NOSTORE_GENERATE_KEY_PAIR,
+ "CRYPTO_NOSTORE_GENERATE_KEY_PAIR", NULL },
+ { (uint_t)CRYPTO_NOSTORE_DERIVE_KEY,
+ "CRYPTO_NOSTORE_DERIVE_KEY", NULL },
+ { (uint_t)CRYPTO_FIPS140_STATUS, "CRYPTO_FIPS140_STATUS", NULL },
+ { (uint_t)CRYPTO_FIPS140_SET, "CRYPTO_FIPS140_SET", NULL },
+
+ /* kbio ioctls */
+ { (uint_t)KIOCTRANS, "KIOCTRANS", NULL },
+ { (uint_t)KIOCGTRANS, "KIOCGTRANS", NULL },
+ { (uint_t)KIOCTRANSABLE, "KIOCTRANSABLE", NULL },
+ { (uint_t)KIOCGTRANSABLE, "KIOCGTRANSABLE", NULL },
+ { (uint_t)KIOCSETKEY, "KIOCSETKEY", NULL },
+ { (uint_t)KIOCGETKEY, "KIOCGETKEY", NULL },
+ { (uint_t)KIOCCMD, "KIOCCMD", NULL },
+ { (uint_t)KIOCTYPE, "KIOCTYPE", NULL },
+ { (uint_t)KIOCSDIRECT, "KIOCSDIRECT", NULL },
+ { (uint_t)KIOCGDIRECT, "KIOCGDIRECT", NULL },
+ { (uint_t)KIOCSKEY, "KIOCSKEY", NULL },
+ { (uint_t)KIOCGKEY, "KIOCGKEY", NULL },
+ { (uint_t)KIOCSLED, "KIOCSLED", NULL },
+ { (uint_t)KIOCGLED, "KIOCGLED", NULL },
+ { (uint_t)KIOCSCOMPAT, "KIOCSCOMPAT", NULL },
+ { (uint_t)KIOCGCOMPAT, "KIOCGCOMPAT", NULL },
+ { (uint_t)KIOCSLAYOUT, "KIOCSLAYOUT", NULL },
+ { (uint_t)KIOCLAYOUT, "KIOCLAYOUT", NULL },
+ { (uint_t)KIOCSKABORTEN, "KIOCSKABORTEN", NULL },
+ { (uint_t)KIOCGRPTDELAY, "KIOCGRPTDELAY", NULL },
+ { (uint_t)KIOCSRPTDELAY, "KIOCSRPTDELAY", NULL },
+ { (uint_t)KIOCGRPTRATE, "KIOCGRPTRATE", NULL },
+ { (uint_t)KIOCSRPTRATE, "KIOCSRPTRATE", NULL },
+ { (uint_t)KIOCSETFREQ, "KIOCSETFREQ", NULL },
+ { (uint_t)KIOCMKTONE, "KIOCMKTONE", NULL },
+
+ /* ptm/pts driver I_STR ioctls */
+ { (uint_t)ISPTM, "ISPTM", NULL},
+ { (uint_t)UNLKPT, "UNLKPT", NULL},
+ { (uint_t)PTSSTTY, "PTSSTTY", NULL},
+ { (uint_t)ZONEPT, "ZONEPT", NULL},
+ { (uint_t)OWNERPT, "OWNERPT", NULL},
+
+ /* aggr link aggregation pseudo driver ioctls */
+ { (uint_t)LAIOC_CREATE, "LAIOC_CREATE", "laioc_create"},
+ { (uint_t)LAIOC_DELETE, "LAIOC_DELETE", "laioc_delete"},
+ { (uint_t)LAIOC_INFO, "LAIOC_INFO", "laioc_info"},
+ { (uint_t)LAIOC_ADD, "LAIOC_ADD",
+ "laioc_add_rem"},
+ { (uint_t)LAIOC_REMOVE, "LAIOC_REMOVE",
+ "laioc_add_rem"},
+ { (uint_t)LAIOC_MODIFY, "LAIOC_MODIFY", "laioc_modify"},
+
+ /* dld data-link ioctls */
+ { (uint_t)DLDIOC_ATTR, "DLDIOC_ATTR", "dld_ioc_attr"},
+ { (uint_t)DLDIOC_PHYS_ATTR, "DLDIOC_PHYS_ATTR",
+ "dld_ioc_phys_attr"},
+ { (uint_t)DLDIOC_DOORSERVER, "DLDIOC_DOORSERVER", "dld_ioc_door"},
+ { (uint_t)DLDIOC_RENAME, "DLDIOC_RENAME", "dld_ioc_rename"},
+ { (uint_t)DLDIOC_SECOBJ_GET, "DLDIOC_SECOBJ_GET",
+ "dld_ioc_secobj_get"},
+ { (uint_t)DLDIOC_SECOBJ_SET, "DLDIOC_SECOBJ_SET",
+ "dld_ioc_secobj_set"},
+ { (uint_t)DLDIOC_SECOBJ_UNSET, "DLDIOC_SECOBJ_UNSET",
+ "dld_ioc_secobj_unset"},
+ { (uint_t)DLDIOC_MACADDRGET, "DLDIOC_MACADDRGET",
+ "dld_ioc_macaddrget"},
+ { (uint_t)DLDIOC_SETMACPROP, "DLDIOC_SETMACPROP",
+ "dld_ioc_macprop_s"},
+ { (uint_t)DLDIOC_GETMACPROP, "DLDIOC_GETMACPROP",
+ "dld_ioc_macprop_s"},
+ { (uint_t)DLDIOC_ADDFLOW, "DLDIOC_ADDFLOW",
+ "dld_ioc_addflow"},
+ { (uint_t)DLDIOC_REMOVEFLOW, "DLDIOC_REMOVEFLOW",
+ "dld_ioc_removeflow"},
+ { (uint_t)DLDIOC_MODIFYFLOW, "DLDIOC_MODIFYFLOW",
+ "dld_ioc_modifyflow"},
+ { (uint_t)DLDIOC_WALKFLOW, "DLDIOC_WALKFLOW",
+ "dld_ioc_walkflow"},
+ { (uint_t)DLDIOC_USAGELOG, "DLDIOC_USAGELOG",
+ "dld_ioc_usagelog"},
+
+ /* simnet ioctls */
+ { (uint_t)SIMNET_IOC_CREATE, "SIMNET_IOC_CREATE",
+ "simnet_ioc_create"},
+ { (uint_t)SIMNET_IOC_DELETE, "SIMNET_IOC_DELETE",
+ "simnet_ioc_delete"},
+ { (uint_t)SIMNET_IOC_INFO, "SIMNET_IOC_INFO",
+ "simnet_ioc_info"},
+ { (uint_t)SIMNET_IOC_MODIFY, "SIMNET_IOC_MODIFY",
+ "simnet_ioc_info"},
+
+ /* vnic ioctls */
+ { (uint_t)VNIC_IOC_CREATE, "VNIC_IOC_CREATE",
+ "vnic_ioc_create"},
+ { (uint_t)VNIC_IOC_DELETE, "VNIC_IOC_DELETE",
+ "vnic_ioc_delete"},
+ { (uint_t)VNIC_IOC_INFO, "VNIC_IOC_INFO",
+ "vnic_ioc_info"},
+
+ /* ZFS ioctls */
+ { (uint_t)ZFS_IOC_POOL_CREATE, "ZFS_IOC_POOL_CREATE",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_POOL_DESTROY, "ZFS_IOC_POOL_DESTROY",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_POOL_IMPORT, "ZFS_IOC_POOL_IMPORT",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_POOL_EXPORT, "ZFS_IOC_POOL_EXPORT",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_POOL_CONFIGS, "ZFS_IOC_POOL_CONFIGS",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_POOL_STATS, "ZFS_IOC_POOL_STATS",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_POOL_TRYIMPORT, "ZFS_IOC_POOL_TRYIMPORT",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_POOL_SCAN, "ZFS_IOC_POOL_SCAN",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_POOL_FREEZE, "ZFS_IOC_POOL_FREEZE",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_POOL_UPGRADE, "ZFS_IOC_POOL_UPGRADE",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_POOL_GET_HISTORY, "ZFS_IOC_POOL_GET_HISTORY",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_VDEV_ADD, "ZFS_IOC_VDEV_ADD",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_VDEV_REMOVE, "ZFS_IOC_VDEV_REMOVE",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_VDEV_SET_STATE, "ZFS_IOC_VDEV_SET_STATE",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_VDEV_ATTACH, "ZFS_IOC_VDEV_ATTACH",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_VDEV_DETACH, "ZFS_IOC_VDEV_DETACH",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_VDEV_SETPATH, "ZFS_IOC_VDEV_SETPATH",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_VDEV_SETFRU, "ZFS_IOC_VDEV_SETFRU",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_OBJSET_STATS, "ZFS_IOC_OBJSET_STATS",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_OBJSET_ZPLPROPS, "ZFS_IOC_OBJSET_ZPLPROPS",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_DATASET_LIST_NEXT, "ZFS_IOC_DATASET_LIST_NEXT",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_SNAPSHOT_LIST_NEXT, "ZFS_IOC_SNAPSHOT_LIST_NEXT",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_SET_PROP, "ZFS_IOC_SET_PROP",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_CREATE, "ZFS_IOC_CREATE",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_DESTROY, "ZFS_IOC_DESTROY",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_ROLLBACK, "ZFS_IOC_ROLLBACK",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_RENAME, "ZFS_IOC_RENAME",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_RECV, "ZFS_IOC_RECV",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_SEND, "ZFS_IOC_SEND",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_INJECT_FAULT, "ZFS_IOC_INJECT_FAULT",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_CLEAR_FAULT, "ZFS_IOC_CLEAR_FAULT",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_INJECT_LIST_NEXT, "ZFS_IOC_INJECT_LIST_NEXT",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_ERROR_LOG, "ZFS_IOC_ERROR_LOG",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_CLEAR, "ZFS_IOC_CLEAR",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_PROMOTE, "ZFS_IOC_PROMOTE",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_SNAPSHOT, "ZFS_IOC_SNAPSHOT",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_DSOBJ_TO_DSNAME, "ZFS_IOC_DSOBJ_TO_DSNAME",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_OBJ_TO_PATH, "ZFS_IOC_OBJ_TO_PATH",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_POOL_SET_PROPS, "ZFS_IOC_POOL_SET_PROPS",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_POOL_GET_PROPS, "ZFS_IOC_POOL_GET_PROPS",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_SET_FSACL, "ZFS_IOC_SET_FSACL",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_GET_FSACL, "ZFS_IOC_GET_FSACL",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_SHARE, "ZFS_IOC_SHARE",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_INHERIT_PROP, "ZFS_IOC_INHERIT_PROP",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_SMB_ACL, "ZFS_IOC_SMB_ACL",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_USERSPACE_ONE, "ZFS_IOC_USERSPACE_ONE",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_USERSPACE_MANY, "ZFS_IOC_USERSPACE_MANY",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_USERSPACE_UPGRADE, "ZFS_IOC_USERSPACE_UPGRADE",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_HOLD, "ZFS_IOC_HOLD",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_RELEASE, "ZFS_IOC_RELEASE",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_GET_HOLDS, "ZFS_IOC_GET_HOLDS",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_OBJSET_RECVD_PROPS, "ZFS_IOC_OBJSET_RECVD_PROPS",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_VDEV_SPLIT, "ZFS_IOC_VDEV_SPLIT",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_NEXT_OBJ, "ZFS_IOC_NEXT_OBJ",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_DIFF, "ZFS_IOC_DIFF",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_TMP_SNAPSHOT, "ZFS_IOC_TMP_SNAPSHOT",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_OBJ_TO_STATS, "ZFS_IOC_OBJ_TO_STATS",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_SPACE_WRITTEN, "ZFS_IOC_SPACE_WRITTEN",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_DESTROY_SNAPS, "ZFS_IOC_DESTROY_SNAPS",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_POOL_REGUID, "ZFS_IOC_POOL_REGUID",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_POOL_REOPEN, "ZFS_IOC_POOL_REOPEN",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_SEND_PROGRESS, "ZFS_IOC_SEND_PROGRESS",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_LOG_HISTORY, "ZFS_IOC_LOG_HISTORY",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_SEND_NEW, "ZFS_IOC_SEND_NEW",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_SEND_SPACE, "ZFS_IOC_SEND_SPACE",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_CLONE, "ZFS_IOC_CLONE",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_BOOKMARK, "ZFS_IOC_BOOKMARK",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_GET_BOOKMARKS, "ZFS_IOC_GET_BOOKMARKS",
+ "zfs_cmd_t" },
+ { (uint_t)ZFS_IOC_DESTROY_BOOKMARKS, "ZFS_IOC_DESTROY_BOOKMARKS",
+ "zfs_cmd_t" },
+
+ /* kssl ioctls */
+ { (uint_t)KSSL_ADD_ENTRY, "KSSL_ADD_ENTRY",
+ "kssl_params_t"},
+ { (uint_t)KSSL_DELETE_ENTRY, "KSSL_DELETE_ENTRY",
+ "sockaddr_in"},
+
+ /* disk ioctls - (0x04 << 8) - dkio.h */
+ { (uint_t)DKIOCGGEOM, "DKIOCGGEOM",
+ "struct dk_geom"},
+ { (uint_t)DKIOCINFO, "DKIOCINFO",
+ "struct dk_info"},
+ { (uint_t)DKIOCEJECT, "DKIOCEJECT",
+ NULL},
+ { (uint_t)DKIOCGVTOC, "DKIOCGVTOC",
+ "struct vtoc"},
+ { (uint_t)DKIOCSVTOC, "DKIOCSVTOC",
+ "struct vtoc"},
+ { (uint_t)DKIOCGEXTVTOC, "DKIOCGEXTVTOC",
+ "struct extvtoc"},
+ { (uint_t)DKIOCSEXTVTOC, "DKIOCSEXTVTOC",
+ "struct extvtoc"},
+ { (uint_t)DKIOCFLUSHWRITECACHE, "DKIOCFLUSHWRITECACHE",
+ NULL},
+ { (uint_t)DKIOCGETWCE, "DKIOCGETWCE",
+ NULL},
+ { (uint_t)DKIOCSETWCE, "DKIOCSETWCE",
+ NULL},
+ { (uint_t)DKIOCSGEOM, "DKIOCSGEOM",
+ "struct dk_geom"},
+ { (uint_t)DKIOCSAPART, "DKIOCSAPART",
+ "struct dk_allmap"},
+ { (uint_t)DKIOCGAPART, "DKIOCGAPART",
+ "struct dk_allmap"},
+ { (uint_t)DKIOCG_PHYGEOM, "DKIOCG_PHYGEOM",
+ "struct dk_geom"},
+ { (uint_t)DKIOCG_VIRTGEOM, "DKIOCG_VIRTGEOM",
+ "struct dk_geom"},
+ { (uint_t)DKIOCLOCK, "DKIOCLOCK",
+ NULL},
+ { (uint_t)DKIOCUNLOCK, "DKIOCUNLOCK",
+ NULL},
+ { (uint_t)DKIOCSTATE, "DKIOCSTATE",
+ NULL},
+ { (uint_t)DKIOCREMOVABLE, "DKIOCREMOVABLE",
+ NULL},
+ { (uint_t)DKIOCHOTPLUGGABLE, "DKIOCHOTPLUGGABLE",
+ NULL},
+ { (uint_t)DKIOCADDBAD, "DKIOCADDBAD",
+ NULL},
+ { (uint_t)DKIOCGETDEF, "DKIOCGETDEF",
+ NULL},
+ { (uint_t)DKIOCPARTINFO, "DKIOCPARTINFO",
+ "struct part_info"},
+ { (uint_t)DKIOCEXTPARTINFO, "DKIOCEXTPARTINFO",
+ "struct extpart_info"},
+ { (uint_t)DKIOCGMEDIAINFO, "DKIOCGMEDIAINFO",
+ "struct dk_minfo"},
+ { (uint_t)DKIOCGMBOOT, "DKIOCGMBOOT",
+ NULL},
+ { (uint_t)DKIOCSMBOOT, "DKIOCSMBOOT",
+ NULL},
+ { (uint_t)DKIOCSETEFI, "DKIOCSETEFI",
+ "struct dk_efi"},
+ { (uint_t)DKIOCGETEFI, "DKIOCGETEFI",
+ "struct dk_efi"},
+ { (uint_t)DKIOCPARTITION, "DKIOCPARTITION",
+ "struct partition64"},
+ { (uint_t)DKIOCGETVOLCAP, "DKIOCGETVOLCAP",
+ "struct volcap_t"},
+ { (uint_t)DKIOCSETVOLCAP, "DKIOCSETVOLCAP",
+ "struct volcap_t"},
+ { (uint_t)DKIOCDMR, "DKIOCDMR",
+ "struct vol_directed_rd"},
+ { (uint_t)DKIOCDUMPINIT, "DKIOCDUMPINIT",
+ NULL},
+ { (uint_t)DKIOCDUMPFINI, "DKIOCDUMPFINI",
+ NULL},
+ { (uint_t)DKIOCREADONLY, "DKIOCREADONLY",
+ NULL},
+
+ /* disk ioctls - (0x04 << 8) - fdio.h */
+ { (uint_t)FDIOGCHAR, "FDIOGCHAR",
+ "struct fd_char"},
+ { (uint_t)FDIOSCHAR, "FDIOSCHAR",
+ "struct fd_char"},
+ { (uint_t)FDEJECT, "FDEJECT",
+ NULL},
+ { (uint_t)FDGETCHANGE, "FDGETCHANGE",
+ NULL},
+ { (uint_t)FDGETDRIVECHAR, "FDGETDRIVECHAR",
+ "struct fd_drive"},
+ { (uint_t)FDSETDRIVECHAR, "FDSETDRIVECHAR",
+ "struct fd_drive"},
+ { (uint_t)FDGETSEARCH, "FDGETSEARCH",
+ NULL},
+ { (uint_t)FDSETSEARCH, "FDSETSEARCH",
+ NULL},
+ { (uint_t)FDIOCMD, "FDIOCMD",
+ "struct fd_cmd"},
+ { (uint_t)FDRAW, "FDRAW",
+ "struct fd_raw"},
+ { (uint_t)FDDEFGEOCHAR, "FDDEFGEOCHAR",
+ NULL},
+
+ /* disk ioctls - (0x04 << 8) - cdio.h */
+ { (uint_t)CDROMPAUSE, "CDROMPAUSE",
+ NULL},
+ { (uint_t)CDROMRESUME, "CDROMRESUME",
+ NULL},
+ { (uint_t)CDROMPLAYMSF, "CDROMPLAYMSF",
+ "struct cdrom_msf"},
+ { (uint_t)CDROMPLAYTRKIND, "CDROMPLAYTRKIND",
+ "struct cdrom_ti"},
+ { (uint_t)CDROMREADTOCHDR, "CDROMREADTOCHDR",
+ "struct cdrom_tochdr"},
+ { (uint_t)CDROMREADTOCENTRY, "CDROMREADTOCENTRY",
+ "struct cdrom_tocentry"},
+ { (uint_t)CDROMSTOP, "CDROMSTOP",
+ NULL},
+ { (uint_t)CDROMSTART, "CDROMSTART",
+ NULL},
+ { (uint_t)CDROMEJECT, "CDROMEJECT",
+ NULL},
+ { (uint_t)CDROMVOLCTRL, "CDROMVOLCTRL",
+ "struct cdrom_volctrl"},
+ { (uint_t)CDROMSUBCHNL, "CDROMSUBCHNL",
+ "struct cdrom_subchnl"},
+ { (uint_t)CDROMREADMODE2, "CDROMREADMODE2",
+ "struct cdrom_read"},
+ { (uint_t)CDROMREADMODE1, "CDROMREADMODE1",
+ "struct cdrom_read"},
+ { (uint_t)CDROMREADOFFSET, "CDROMREADOFFSET",
+ NULL},
+ { (uint_t)CDROMGBLKMODE, "CDROMGBLKMODE",
+ NULL},
+ { (uint_t)CDROMSBLKMODE, "CDROMSBLKMODE",
+ NULL},
+ { (uint_t)CDROMCDDA, "CDROMCDDA",
+ "struct cdrom_cdda"},
+ { (uint_t)CDROMCDXA, "CDROMCDXA",
+ "struct cdrom_cdxa"},
+ { (uint_t)CDROMSUBCODE, "CDROMSUBCODE",
+ "struct cdrom_subcode"},
+ { (uint_t)CDROMGDRVSPEED, "CDROMGDRVSPEED",
+ NULL},
+ { (uint_t)CDROMSDRVSPEED, "CDROMSDRVSPEED",
+ NULL},
+ { (uint_t)CDROMCLOSETRAY, "CDROMCLOSETRAY",
+ NULL},
+
+ /* disk ioctls - (0x04 << 8) - uscsi.h */
+ { (uint_t)USCSICMD, "USCSICMD",
+ "struct uscsi_cmd"},
+
+ /* dumpadm ioctls - (0xdd << 8) */
+ { (uint_t)DIOCGETDEV, "DIOCGETDEV",
+ NULL},
+
+ /* mntio ioctls - ('m' << 8) */
+ { (uint_t)MNTIOC_NMNTS, "MNTIOC_NMNTS",
+ NULL},
+ { (uint_t)MNTIOC_GETDEVLIST, "MNTIOC_GETDEVLIST",
+ NULL},
+ { (uint_t)MNTIOC_SETTAG, "MNTIOC_SETTAG",
+ "struct mnttagdesc"},
+ { (uint_t)MNTIOC_CLRTAG, "MNTIOC_CLRTAG",
+ "struct mnttagdesc"},
+ { (uint_t)MNTIOC_SHOWHIDDEN, "MNTIOC_SHOWHIDDEN",
+ NULL},
+ { (uint_t)MNTIOC_GETMNTENT, "MNTIOC_GETMNTENT",
+ "struct mnttab"},
+ { (uint_t)MNTIOC_GETEXTMNTENT, "MNTIOC_GETEXTMNTENT",
+ "struct extmnttab"},
+ { (uint_t)MNTIOC_GETMNTANY, "MNTIOC_GETMNTANY",
+ "struct mnttab"},
+
+ /* devinfo ioctls - ('df' << 8) - devinfo_impl.h */
+ { (uint_t)DINFOUSRLD, "DINFOUSRLD",
+ NULL},
+ { (uint_t)DINFOLODRV, "DINFOLODRV",
+ NULL},
+ { (uint_t)DINFOIDENT, "DINFOIDENT",
+ NULL},
+
+ { (uint_t)IPTUN_CREATE, "IPTUN_CREATE", "iptun_kparams_t"},
+ { (uint_t)IPTUN_DELETE, "IPTUN_DELETE", "datalink_id_t"},
+ { (uint_t)IPTUN_MODIFY, "IPTUN_MODIFY", "iptun_kparams_t"},
+ { (uint_t)IPTUN_INFO, "IPTUN_INFO", NULL},
+ { (uint_t)IPTUN_SET_6TO4RELAY, "IPTUN_SET_6TO4RELAY", NULL},
+ { (uint_t)IPTUN_GET_6TO4RELAY, "IPTUN_GET_6TO4RELAY", NULL},
+
+ /* zcons ioctls */
+ { (uint_t)ZC_HOLDSLAVE, "ZC_HOLDSLAVE", NULL },
+ { (uint_t)ZC_RELEASESLAVE, "ZC_RELEASESLAVE", NULL },
+
+ /* hid ioctls - ('h' << 8) - hid.h */
+ { (uint_t)HIDIOCKMGDIRECT, "HIDIOCKMGDIRECT", NULL },
+ { (uint_t)HIDIOCKMSDIRECT, "HIDIOCKMSDIRECT", NULL },
+
+ /* pm ioctls */
+ { (uint_t)PM_SCHEDULE, "PM_SCHEDULE", NULL },
+ { (uint_t)PM_GET_IDLE_TIME, "PM_GET_IDLE_TIME", NULL },
+ { (uint_t)PM_GET_NUM_CMPTS, "PM_GET_NUM_CMPTS", NULL },
+ { (uint_t)PM_GET_THRESHOLD, "PM_GET_THRESHOLD", NULL },
+ { (uint_t)PM_SET_THRESHOLD, "PM_SET_THRESHOLD", NULL },
+ { (uint_t)PM_GET_NORM_PWR, "PM_GET_NORM_PWR", NULL },
+ { (uint_t)PM_SET_CUR_PWR, "PM_SET_CUR_PWR", NULL },
+ { (uint_t)PM_GET_CUR_PWR, "PM_GET_CUR_PWR", NULL },
+ { (uint_t)PM_GET_NUM_DEPS, "PM_GET_NUM_DEPS", NULL },
+ { (uint_t)PM_GET_DEP, "PM_GET_DEP", NULL },
+ { (uint_t)PM_ADD_DEP, "PM_ADD_DEP", NULL },
+ { (uint_t)PM_REM_DEP, "PM_REM_DEP", NULL },
+ { (uint_t)PM_REM_DEVICE, "PM_REM_DEVICE", NULL },
+ { (uint_t)PM_REM_DEVICES, "PM_REM_DEVICES", NULL },
+ { (uint_t)PM_DISABLE_AUTOPM, "PM_DISABLE_AUTOPM", NULL },
+ { (uint_t)PM_REENABLE_AUTOPM, "PM_REENABLE_AUTOPM", NULL },
+ { (uint_t)PM_SET_NORM_PWR, "PM_SET_NORM_PWR", NULL },
+ { (uint_t)PM_GET_SYSTEM_THRESHOLD, "PM_GET_SYSTEM_THRESHOLD",
+ NULL },
+ { (uint_t)PM_GET_DEFAULT_SYSTEM_THRESHOLD,
+ "PM_GET_DEFAULT_SYSTEM_THRESHOLD", NULL },
+ { (uint_t)PM_SET_SYSTEM_THRESHOLD, "PM_SET_SYSTEM_THRESHOLD",
+ NULL },
+ { (uint_t)PM_START_PM, "PM_START_PM", NULL },
+ { (uint_t)PM_STOP_PM, "PM_STOP_PM", NULL },
+ { (uint_t)PM_RESET_PM, "PM_RESET_PM", NULL },
+ { (uint_t)PM_GET_PM_STATE, "PM_GET_PM_STATE", NULL },
+ { (uint_t)PM_GET_AUTOS3_STATE, "PM_GET_AUTOS3_STATE", NULL },
+ { (uint_t)PM_GET_S3_SUPPORT_STATE, "PM_GET_S3_SUPPORT_STATE",
+ NULL },
+ { (uint_t)PM_IDLE_DOWN, "PM_IDLE_DOWN", NULL },
+ { (uint_t)PM_START_CPUPM, "PM_START_CPUPM", NULL },
+ { (uint_t)PM_START_CPUPM_EV, "PM_START_CPUPM_EV", NULL },
+ { (uint_t)PM_START_CPUPM_POLL, "PM_START_CPUPM_POLL", NULL },
+ { (uint_t)PM_STOP_CPUPM, "PM_STOP_CPUPM", NULL },
+ { (uint_t)PM_GET_CPU_THRESHOLD, "PM_GET_CPU_THRESHOLD", NULL },
+ { (uint_t)PM_SET_CPU_THRESHOLD, "PM_SET_CPU_THRESHOLD", NULL },
+ { (uint_t)PM_GET_CPUPM_STATE, "PM_GET_CPUPM_STATE", NULL },
+ { (uint_t)PM_START_AUTOS3, "PM_START_AUTOS3", NULL },
+ { (uint_t)PM_STOP_AUTOS3, "PM_STOP_AUTOS3", NULL },
+ { (uint_t)PM_ENABLE_S3, "PM_ENABLE_S3", NULL },
+ { (uint_t)PM_DISABLE_S3, "PM_DISABLE_S3", NULL },
+ { (uint_t)PM_ENTER_S3, "PM_ENTER_S3", NULL },
+ { (uint_t)PM_DISABLE_CPU_DEEP_IDLE, "PM_DISABLE_CPU_DEEP_IDLE",
+ NULL },
+ { (uint_t)PM_ENABLE_CPU_DEEP_IDLE, "PM_START_CPU_DEEP_IDLE",
+ NULL },
+ { (uint_t)PM_DEFAULT_CPU_DEEP_IDLE, "PM_DFLT_CPU_DEEP_IDLE",
+ NULL },
+#ifdef _SYSCALL32
+ { (uint_t)PM_GET_STATE_CHANGE, "PM_GET_STATE_CHANGE",
+ "pm_state_change32_t" },
+ { (uint_t)PM_GET_STATE_CHANGE_WAIT, "PM_GET_STATE_CHANGE_WAIT",
+ "pm_state_change32_t" },
+ { (uint_t)PM_DIRECT_NOTIFY, "PM_DIRECT_NOTIFY",
+ "pm_state_change32_t" },
+ { (uint_t)PM_DIRECT_NOTIFY_WAIT, "PM_DIRECT_NOTIFY_WAIT",
+ "pm_state_change32_t" },
+ { (uint_t)PM_REPARSE_PM_PROPS, "PM_REPARSE_PM_PROPS",
+ "pm_req32_t" },
+ { (uint_t)PM_SET_DEVICE_THRESHOLD, "PM_SET_DEVICE_THRESHOLD",
+ "pm_req32_t" },
+ { (uint_t)PM_GET_STATS, "PM_GET_STATS",
+ "pm_req32_t" },
+ { (uint_t)PM_GET_DEVICE_THRESHOLD, "PM_GET_DEVICE_THRESHOLD",
+ "pm_req32_t" },
+ { (uint_t)PM_GET_POWER_NAME, "PM_GET_POWER_NAME",
+ "pm_req32_t" },
+ { (uint_t)PM_GET_POWER_LEVELS, "PM_GET_POWER_LEVELS",
+ "pm_req32_t" },
+ { (uint_t)PM_GET_NUM_COMPONENTS, "PM_GET_NUM_COMPONENTS",
+ "pm_req32_t" },
+ { (uint_t)PM_GET_COMPONENT_NAME, "PM_GET_COMPONENT_NAME",
+ "pm_req32_t" },
+ { (uint_t)PM_GET_NUM_POWER_LEVELS, "PM_GET_NUM_POWER_LEVELS",
+ "pm_req32_t" },
+ { (uint_t)PM_DIRECT_PM, "PM_DIRECT_PM",
+ "pm_req32_t" },
+ { (uint_t)PM_RELEASE_DIRECT_PM, "PM_RELEASE_DIRECT_PM",
+ "pm_req32_t" },
+ { (uint_t)PM_RESET_DEVICE_THRESHOLD, "PM_RESET_DEVICE_THRESHOLD",
+ "pm_req32_t" },
+ { (uint_t)PM_GET_DEVICE_TYPE, "PM_GET_DEVICE_TYPE",
+ "pm_req32_t" },
+ { (uint_t)PM_SET_COMPONENT_THRESHOLDS, "PM_SET_COMPONENT_THRESHOLDS",
+ "pm_req32_t" },
+ { (uint_t)PM_GET_COMPONENT_THRESHOLDS, "PM_GET_COMPONENT_THRESHOLDS",
+ "pm_req32_t" },
+ { (uint_t)PM_GET_DEVICE_THRESHOLD_BASIS,
+ "PM_GET_DEVICE_THRESHOLD_BASIS", "pm_req32_t" },
+ { (uint_t)PM_SET_CURRENT_POWER, "PM_SET_CURRENT_POWER",
+ "pm_req32_t" },
+ { (uint_t)PM_GET_CURRENT_POWER, "PM_GET_CURRENT_POWER",
+ "pm_req32_t" },
+ { (uint_t)PM_GET_FULL_POWER, "PM_GET_FULL_POWER",
+ "pm_req32_t" },
+ { (uint_t)PM_ADD_DEPENDENT, "PM_ADD_DEPENDENT",
+ "pm_req32_t" },
+ { (uint_t)PM_GET_TIME_IDLE, "PM_GET_TIME_IDLE",
+ "pm_req32_t" },
+ { (uint_t)PM_ADD_DEPENDENT_PROPERTY, "PM_ADD_DEPENDENT_PROPERTY",
+ "pm_req32_t" },
+ { (uint_t)PM_GET_CMD_NAME, "PM_GET_CMD_NAME",
+ "pm_req32_t" },
+ { (uint_t)PM_SEARCH_LIST, "PM_SEARCH_LIST",
+ "pm_searchargs32_t" },
+#else /* _SYSCALL32 */
+ { (uint_t)PM_GET_STATE_CHANGE, "PM_GET_STATE_CHANGE",
+ "pm_state_change_t" },
+ { (uint_t)PM_GET_STATE_CHANGE_WAIT, "PM_GET_STATE_CHANGE_WAIT",
+ "pm_state_change_t" },
+ { (uint_t)PM_DIRECT_NOTIFY, "PM_DIRECT_NOTIFY",
+ "pm_state_change_t" },
+ { (uint_t)PM_DIRECT_NOTIFY_WAIT, "PM_DIRECT_NOTIFY_WAIT",
+ "pm_state_change_t" },
+ { (uint_t)PM_REPARSE_PM_PROPS, "PM_REPARSE_PM_PROPS",
+ "pm_req_t" },
+ { (uint_t)PM_SET_DEVICE_THRESHOLD, "PM_SET_DEVICE_THRESHOLD",
+ "pm_req_t" },
+ { (uint_t)PM_GET_STATS, "PM_GET_STATS",
+ "pm_req_t" },
+ { (uint_t)PM_GET_DEVICE_THRESHOLD, "PM_GET_DEVICE_THRESHOLD",
+ "pm_req_t" },
+ { (uint_t)PM_GET_POWER_NAME, "PM_GET_POWER_NAME",
+ "pm_req_t" },
+ { (uint_t)PM_GET_POWER_LEVELS, "PM_GET_POWER_LEVELS",
+ "pm_req_t" },
+ { (uint_t)PM_GET_NUM_COMPONENTS, "PM_GET_NUM_COMPONENTS",
+ "pm_req_t" },
+ { (uint_t)PM_GET_COMPONENT_NAME, "PM_GET_COMPONENT_NAME",
+ "pm_req_t" },
+ { (uint_t)PM_GET_NUM_POWER_LEVELS, "PM_GET_NUM_POWER_LEVELS",
+ "pm_req_t" },
+ { (uint_t)PM_DIRECT_PM, "PM_DIRECT_PM",
+ "pm_req_t" },
+ { (uint_t)PM_RELEASE_DIRECT_PM, "PM_RELEASE_DIRECT_PM",
+ "pm_req_t" },
+ { (uint_t)PM_RESET_DEVICE_THRESHOLD, "PM_RESET_DEVICE_THRESHOLD",
+ "pm_req_t" },
+ { (uint_t)PM_GET_DEVICE_TYPE, "PM_GET_DEVICE_TYPE",
+ "pm_req_t" },
+ { (uint_t)PM_SET_COMPONENT_THRESHOLDS, "PM_SET_COMPONENT_THRESHOLDS",
+ "pm_req_t" },
+ { (uint_t)PM_GET_COMPONENT_THRESHOLDS, "PM_GET_COMPONENT_THRESHOLDS",
+ "pm_req_t" },
+ { (uint_t)PM_GET_DEVICE_THRESHOLD_BASIS,
+ "PM_GET_DEVICE_THRESHOLD_BASIS", "pm_req_t" },
+ { (uint_t)PM_SET_CURRENT_POWER, "PM_SET_CURRENT_POWER",
+ "pm_req_t" },
+ { (uint_t)PM_GET_CURRENT_POWER, "PM_GET_CURRENT_POWER",
+ "pm_req_t" },
+ { (uint_t)PM_GET_FULL_POWER, "PM_GET_FULL_POWER",
+ "pm_req_t" },
+ { (uint_t)PM_ADD_DEPENDENT, "PM_ADD_DEPENDENT",
+ "pm_req_t" },
+ { (uint_t)PM_GET_TIME_IDLE, "PM_GET_TIME_IDLE",
+ "pm_req_t" },
+ { (uint_t)PM_ADD_DEPENDENT_PROPERTY, "PM_ADD_DEPENDENT_PROPERTY",
+ "pm_req_t" },
+ { (uint_t)PM_GET_CMD_NAME, "PM_GET_CMD_NAME",
+ "pm_req_t" },
+ { (uint_t)PM_SEARCH_LIST, "PM_SEARCH_LIST",
+ "pm_searchargs_t" },
+#endif /* _SYSCALL */
+
+ { (uint_t)0, NULL, NULL }
+};
+
+void
+ioctl_ioccom(char *buf, size_t size, uint_t code, int nbytes, int x, int y)
+{
+ const char *inoutstr;
+
+ if (code & IOC_VOID)
+ inoutstr = "";
+ else if ((code & IOC_INOUT) == IOC_INOUT)
+ inoutstr = "WR";
+ else
+ inoutstr = code & IOC_IN ? "W" : "R";
+
+ if (isascii(x) && isprint(x))
+ (void) snprintf(buf, size, "_IO%sN('%c', %d, %d)", inoutstr,
+ x, y, nbytes);
+ else
+ (void) snprintf(buf, size, "_IO%sN(0x%x, %d, %d)", inoutstr,
+ x, y, nbytes);
+}
+
+
+const char *
+ioctlname(private_t *pri, uint_t code)
+{
+ const struct ioc *ip;
+ const char *str = NULL;
+
+ for (ip = &ioc[0]; ip->name; ip++) {
+ if (code == ip->code) {
+ str = ip->name;
+ break;
+ }
+ }
+
+ /*
+ * Developers hide ascii ioctl names in the ioctl subcode; for example
+ * 0x445210 should be printed 'D'<<16|'R'<<8|10. We allow for all
+ * three high order bytes (called hi, mid and lo) to contain ascii
+ * characters.
+ */
+ if (str == NULL) {
+ int c_hi = code >> 24;
+ int c_mid = (code >> 16) & 0xff;
+ int c_mid_nm = (code >> 16);
+ int c_lo = (code >> 8) & 0xff;
+ int c_lo_nm = code >> 8;
+
+ if (isascii(c_lo) && isprint(c_lo) &&
+ isascii(c_mid) && isprint(c_mid) &&
+ isascii(c_hi) && isprint(c_hi))
+ (void) sprintf(pri->code_buf,
+ "(('%c'<<24)|('%c'<<16)|('%c'<<8)|%d)",
+ c_hi, c_mid, c_lo, code & 0xff);
+ else if (isascii(c_lo) && isprint(c_lo) &&
+ isascii(c_mid_nm) && isprint(c_mid_nm))
+ (void) sprintf(pri->code_buf,
+ "(('%c'<<16)|('%c'<<8)|%d)", c_mid, c_lo,
+ code & 0xff);
+ else if (isascii(c_lo_nm) && isprint(c_lo_nm))
+ (void) sprintf(pri->code_buf, "(('%c'<<8)|%d)",
+ c_lo_nm, code & 0xff);
+ else if (code & (IOC_VOID|IOC_INOUT))
+ ioctl_ioccom(pri->code_buf, sizeof (pri->code_buf),
+ code, c_mid, c_lo, code & 0xff);
+ else
+ (void) sprintf(pri->code_buf, "0x%.4X", code);
+ str = (const char *)pri->code_buf;
+ }
+
+ return (str);
+}
+
+
+const char *
+ioctldatastruct(uint_t code)
+{
+ const struct ioc *ip;
+ const char *str = NULL;
+
+ for (ip = &ioc[0]; ip->name != NULL; ip++) {
+ if (code == ip->code) {
+ str = ip->datastruct;
+ break;
+ }
+ }
+ return (str);
+}
+
+
+const char *
+fcntlname(int code)
+{
+ const char *str = NULL;
+
+ if (code >= FCNTLMIN && code <= FCNTLMAX)
+ str = FCNTLname[code-FCNTLMIN];
+ return (str);
+}
+
+const char *
+sfsname(int code)
+{
+ const char *str = NULL;
+
+ if (code >= SYSFSMIN && code <= SYSFSMAX)
+ str = SYSFSname[code-SYSFSMIN];
+ return (str);
+}
+
+/* ARGSUSED */
+const char *
+si86name(int code)
+{
+ const char *str = NULL;
+
+#if defined(__i386) || defined(__amd64)
+ switch (code) {
+ case SI86SWPI: str = "SI86SWPI"; break;
+ case SI86SYM: str = "SI86SYM"; break;
+ case SI86CONF: str = "SI86CONF"; break;
+ case SI86BOOT: str = "SI86BOOT"; break;
+ case SI86AUTO: str = "SI86AUTO"; break;
+ case SI86EDT: str = "SI86EDT"; break;
+ case SI86SWAP: str = "SI86SWAP"; break;
+ case SI86FPHW: str = "SI86FPHW"; break;
+ case SI86FPSTART: str = "SI86FPSTART"; break;
+ case GRNON: str = "GRNON"; break;
+ case GRNFLASH: str = "GRNFLASH"; break;
+ case STIME: str = "STIME"; break;
+ case SETNAME: str = "SETNAME"; break;
+ case RNVR: str = "RNVR"; break;
+ case WNVR: str = "WNVR"; break;
+ case RTODC: str = "RTODC"; break;
+ case CHKSER: str = "CHKSER"; break;
+ case SI86NVPRT: str = "SI86NVPRT"; break;
+ case SANUPD: str = "SANUPD"; break;
+ case SI86KSTR: str = "SI86KSTR"; break;
+ case SI86MEM: str = "SI86MEM"; break;
+ case SI86TODEMON: str = "SI86TODEMON"; break;
+ case SI86CCDEMON: str = "SI86CCDEMON"; break;
+ case SI86CACHE: str = "SI86CACHE"; break;
+ case SI86DELMEM: str = "SI86DELMEM"; break;
+ case SI86ADDMEM: str = "SI86ADDMEM"; break;
+/* 71 through 74 reserved for VPIX */
+ case SI86V86: str = "SI86V86"; break;
+ case SI86SLTIME: str = "SI86SLTIME"; break;
+ case SI86DSCR: str = "SI86DSCR"; break;
+ case RDUBLK: str = "RDUBLK"; break;
+/* NFA entry point */
+ case SI86NFA: str = "SI86NFA"; break;
+ case SI86VM86: str = "SI86VM86"; break;
+ case SI86VMENABLE: str = "SI86VMENABLE"; break;
+ case SI86LIMUSER: str = "SI86LIMUSER"; break;
+ case SI86RDID: str = "SI86RDID"; break;
+ case SI86RDBOOT: str = "SI86RDBOOT"; break;
+/* Merged Product defines */
+ case SI86SHFIL: str = "SI86SHFIL"; break;
+ case SI86PCHRGN: str = "SI86PCHRGN"; break;
+ case SI86BADVISE: str = "SI86BADVISE"; break;
+ case SI86SHRGN: str = "SI86SHRGN"; break;
+ case SI86CHIDT: str = "SI86CHIDT"; break;
+ case SI86EMULRDA: str = "SI86EMULRDA"; break;
+/* RTC commands */
+ case WTODC: str = "WTODC"; break;
+ case SGMTL: str = "SGMTL"; break;
+ case GGMTL: str = "GGMTL"; break;
+ case RTCSYNC: str = "RTCSYNC"; break;
+ }
+#endif /* __i386 */
+
+ return (str);
+}
+
+const char *
+utscode(int code)
+{
+ const char *str = NULL;
+
+ switch (code) {
+ case UTS_UNAME: str = "UNAME"; break;
+ case UTS_USTAT: str = "USTAT"; break;
+ case UTS_FUSERS: str = "FUSERS"; break;
+ }
+
+ return (str);
+}
+
+const char *
+rctlsyscode(int code)
+{
+ const char *str = NULL;
+ switch (code) {
+ case 0: str = "GETRCTL"; break;
+ case 1: str = "SETRCTL"; break;
+ case 2: str = "RCTLSYS_LST"; break;
+ case 3: str = "RCTLSYS_CTL"; break;
+ case 4: str = "RCTLSYS_SETPROJ"; break;
+ default: str = "UNKNOWN"; break;
+ }
+ return (str);
+}
+
+const char *
+rctl_local_action(private_t *pri, uint_t val)
+{
+ uint_t action = val & (~RCTL_LOCAL_ACTION_MASK);
+
+ char *s = pri->code_buf;
+
+ *s = '\0';
+
+ if (action & RCTL_LOCAL_NOACTION) {
+ action ^= RCTL_LOCAL_NOACTION;
+ (void) strlcat(s, "|RCTL_LOCAL_NOACTION",
+ sizeof (pri->code_buf));
+ }
+ if (action & RCTL_LOCAL_SIGNAL) {
+ action ^= RCTL_LOCAL_SIGNAL;
+ (void) strlcat(s, "|RCTL_LOCAL_SIGNAL",
+ sizeof (pri->code_buf));
+ }
+ if (action & RCTL_LOCAL_DENY) {
+ action ^= RCTL_LOCAL_DENY;
+ (void) strlcat(s, "|RCTL_LOCAL_DENY",
+ sizeof (pri->code_buf));
+ }
+
+ if ((action & (~RCTL_LOCAL_ACTION_MASK)) != 0)
+ return (NULL);
+ else if (*s != '\0')
+ return (s+1);
+ else
+ return (NULL);
+}
+
+
+const char *
+rctl_local_flags(private_t *pri, uint_t val)
+{
+ uint_t pval = val & RCTL_LOCAL_ACTION_MASK;
+ char *s = pri->code_buf;
+
+ *s = '\0';
+
+ if (pval & RCTL_LOCAL_MAXIMAL) {
+ pval ^= RCTL_LOCAL_MAXIMAL;
+ (void) strlcat(s, "|RCTL_LOCAL_MAXIMAL",
+ sizeof (pri->code_buf));
+ }
+
+ if ((pval & RCTL_LOCAL_ACTION_MASK) != 0)
+ return (NULL);
+ else if (*s != '\0')
+ return (s+1);
+ else
+ return (NULL);
+}
+
+
+const char *
+sconfname(int code)
+{
+ const char *str = NULL;
+
+ if (code >= SCONFMIN && code <= SCONFMAX)
+ str = SCONFname[code-SCONFMIN];
+ return (str);
+}
+
+const char *
+pathconfname(int code)
+{
+ const char *str = NULL;
+
+ if (code >= PATHCONFMIN && code <= PATHCONFMAX)
+ str = PATHCONFname[code-PATHCONFMIN];
+ return (str);
+}
+
+#define ALL_O_FLAGS \
+ (O_NDELAY|O_APPEND|O_SYNC|O_DSYNC|O_NONBLOCK|O_CREAT|O_TRUNC\
+ |O_EXCL|O_NOCTTY|O_LARGEFILE|O_RSYNC|O_XATTR|O_NOFOLLOW|O_NOLINKS\
+ |O_CLOEXEC|FXATTRDIROPEN)
+
+const char *
+openarg(private_t *pri, int arg)
+{
+ char *str = pri->code_buf;
+
+ if ((arg & ~(O_ACCMODE | ALL_O_FLAGS)) != 0)
+ return (NULL);
+
+ switch (arg & O_ACCMODE) {
+ default:
+ return (NULL);
+ case O_RDONLY:
+ (void) strcpy(str, "O_RDONLY");
+ break;
+ case O_WRONLY:
+ (void) strcpy(str, "O_WRONLY");
+ break;
+ case O_RDWR:
+ (void) strcpy(str, "O_RDWR");
+ break;
+ case O_SEARCH:
+ (void) strcpy(str, "O_SEARCH");
+ break;
+ case O_EXEC:
+ (void) strcpy(str, "O_EXEC");
+ break;
+ }
+
+ if (arg & O_NDELAY)
+ (void) strlcat(str, "|O_NDELAY", sizeof (pri->code_buf));
+ if (arg & O_APPEND)
+ (void) strlcat(str, "|O_APPEND", sizeof (pri->code_buf));
+ if (arg & O_SYNC)
+ (void) strlcat(str, "|O_SYNC", sizeof (pri->code_buf));
+ if (arg & O_DSYNC)
+ (void) strlcat(str, "|O_DSYNC", sizeof (pri->code_buf));
+ if (arg & O_NONBLOCK)
+ (void) strlcat(str, "|O_NONBLOCK", sizeof (pri->code_buf));
+ if (arg & O_CREAT)
+ (void) strlcat(str, "|O_CREAT", sizeof (pri->code_buf));
+ if (arg & O_TRUNC)
+ (void) strlcat(str, "|O_TRUNC", sizeof (pri->code_buf));
+ if (arg & O_EXCL)
+ (void) strlcat(str, "|O_EXCL", sizeof (pri->code_buf));
+ if (arg & O_NOCTTY)
+ (void) strlcat(str, "|O_NOCTTY", sizeof (pri->code_buf));
+ if (arg & O_LARGEFILE)
+ (void) strlcat(str, "|O_LARGEFILE", sizeof (pri->code_buf));
+ if (arg & O_RSYNC)
+ (void) strlcat(str, "|O_RSYNC", sizeof (pri->code_buf));
+ if (arg & O_XATTR)
+ (void) strlcat(str, "|O_XATTR", sizeof (pri->code_buf));
+ if (arg & O_NOFOLLOW)
+ (void) strlcat(str, "|O_NOFOLLOW", sizeof (pri->code_buf));
+ if (arg & O_NOLINKS)
+ (void) strlcat(str, "|O_NOLINKS", sizeof (pri->code_buf));
+ if (arg & O_CLOEXEC)
+ (void) strlcat(str, "|O_CLOEXEC", sizeof (pri->code_buf));
+ if (arg & FXATTRDIROPEN)
+ (void) strlcat(str, "|FXATTRDIROPEN", sizeof (pri->code_buf));
+
+ return ((const char *)str);
+}
+
+const char *
+whencearg(int arg)
+{
+ const char *str = NULL;
+
+ switch (arg) {
+ case SEEK_SET: str = "SEEK_SET"; break;
+ case SEEK_CUR: str = "SEEK_CUR"; break;
+ case SEEK_END: str = "SEEK_END"; break;
+ case SEEK_DATA: str = "SEEK_DATA"; break;
+ case SEEK_HOLE: str = "SEEK_HOLE"; break;
+ }
+
+ return (str);
+}
+
+#define IPC_FLAGS (IPC_ALLOC|IPC_CREAT|IPC_EXCL|IPC_NOWAIT)
+
+char *
+ipcflags(private_t *pri, int arg)
+{
+ char *str = pri->code_buf;
+
+ if (arg & 0777)
+ (void) sprintf(str, "0%.3o", arg&0777);
+ else
+ *str = '\0';
+
+ if (arg & IPC_ALLOC)
+ (void) strcat(str, "|IPC_ALLOC");
+ if (arg & IPC_CREAT)
+ (void) strcat(str, "|IPC_CREAT");
+ if (arg & IPC_EXCL)
+ (void) strcat(str, "|IPC_EXCL");
+ if (arg & IPC_NOWAIT)
+ (void) strcat(str, "|IPC_NOWAIT");
+
+ return (str);
+}
+
+const char *
+msgflags(private_t *pri, int arg)
+{
+ char *str;
+
+ if (arg == 0 || (arg & ~(IPC_FLAGS|MSG_NOERROR|0777)) != 0)
+ return ((char *)NULL);
+
+ str = ipcflags(pri, arg);
+
+ if (arg & MSG_NOERROR)
+ (void) strcat(str, "|MSG_NOERROR");
+
+ if (*str == '|')
+ str++;
+ return ((const char *)str);
+}
+
+const char *
+semflags(private_t *pri, int arg)
+{
+ char *str;
+
+ if (arg == 0 || (arg & ~(IPC_FLAGS|SEM_UNDO|0777)) != 0)
+ return ((char *)NULL);
+
+ str = ipcflags(pri, arg);
+
+ if (arg & SEM_UNDO)
+ (void) strcat(str, "|SEM_UNDO");
+
+ if (*str == '|')
+ str++;
+ return ((const char *)str);
+}
+
+const char *
+shmflags(private_t *pri, int arg)
+{
+ char *str;
+
+ if (arg == 0 || (arg & ~(IPC_FLAGS|SHM_RDONLY|SHM_RND|0777)) != 0)
+ return ((char *)NULL);
+
+ str = ipcflags(pri, arg);
+
+ if (arg & SHM_RDONLY)
+ (void) strcat(str, "|SHM_RDONLY");
+ if (arg & SHM_RND)
+ (void) strcat(str, "|SHM_RND");
+
+ if (*str == '|')
+ str++;
+ return ((const char *)str);
+}
+
+#define MSGCMDMIN 0
+#define MSGCMDMAX IPC_STAT64
+const char *const MSGCMDname[MSGCMDMAX+1] = {
+ NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL,
+ "IPC_RMID", /* 10 */
+ "IPC_SET", /* 11 */
+ "IPC_STAT", /* 12 */
+ "IPC_SET64", /* 13 */
+ "IPC_STAT64", /* 14 */
+};
+
+#define SEMCMDMIN 0
+#define SEMCMDMAX IPC_STAT64
+const char *const SEMCMDname[SEMCMDMAX+1] = {
+ NULL, /* 0 */
+ NULL, /* 1 */
+ NULL, /* 2 */
+ "GETNCNT", /* 3 */
+ "GETPID", /* 4 */
+ "GETVAL", /* 5 */
+ "GETALL", /* 6 */
+ "GETZCNT", /* 7 */
+ "SETVAL", /* 8 */
+ "SETALL", /* 9 */
+ "IPC_RMID", /* 10 */
+ "IPC_SET", /* 11 */
+ "IPC_STAT", /* 12 */
+ "IPC_SET64", /* 13 */
+ "IPC_STAT64", /* 14 */
+};
+
+#define SHMCMDMIN 0
+#define SHMCMDMAX IPC_STAT64
+const char *const SHMCMDname[SHMCMDMAX+1] = {
+ NULL, /* 0 */
+ NULL, /* 1 */
+ NULL, /* 2 */
+ "SHM_LOCK", /* 3 */
+ "SHM_UNLOCK", /* 4 */
+ NULL, NULL, NULL, NULL, NULL, /* 5 NULLs */
+ "IPC_RMID", /* 10 */
+ "IPC_SET", /* 11 */
+ "IPC_STAT", /* 12 */
+ "IPC_SET64", /* 13 */
+ "IPC_STAT64", /* 14 */
+};
+
+const char *
+msgcmd(int arg)
+{
+ const char *str = NULL;
+
+ if (arg >= MSGCMDMIN && arg <= MSGCMDMAX)
+ str = MSGCMDname[arg-MSGCMDMIN];
+ return (str);
+}
+
+const char *
+semcmd(int arg)
+{
+ const char *str = NULL;
+
+ if (arg >= SEMCMDMIN && arg <= SEMCMDMAX)
+ str = SEMCMDname[arg-SEMCMDMIN];
+ return (str);
+}
+
+const char *
+shmcmd(int arg)
+{
+ const char *str = NULL;
+
+ if (arg >= SHMCMDMIN && arg <= SHMCMDMAX)
+ str = SHMCMDname[arg-SHMCMDMIN];
+ return (str);
+}
+
+const char *
+strrdopt(int arg) /* streams read option (I_SRDOPT I_GRDOPT) */
+{
+ const char *str = NULL;
+
+ switch (arg) {
+ case RNORM: str = "RNORM"; break;
+ case RMSGD: str = "RMSGD"; break;
+ case RMSGN: str = "RMSGN"; break;
+ }
+
+ return (str);
+}
+
+/* bit map of streams events (I_SETSIG & I_GETSIG) */
+const char *
+strevents(private_t *pri, int arg)
+{
+ char *str = pri->code_buf;
+
+ if (arg & ~(S_INPUT|S_HIPRI|S_OUTPUT|S_MSG|S_ERROR|S_HANGUP))
+ return ((char *)NULL);
+
+ *str = '\0';
+ if (arg & S_INPUT)
+ (void) strcat(str, "|S_INPUT");
+ if (arg & S_HIPRI)
+ (void) strcat(str, "|S_HIPRI");
+ if (arg & S_OUTPUT)
+ (void) strcat(str, "|S_OUTPUT");
+ if (arg & S_MSG)
+ (void) strcat(str, "|S_MSG");
+ if (arg & S_ERROR)
+ (void) strcat(str, "|S_ERROR");
+ if (arg & S_HANGUP)
+ (void) strcat(str, "|S_HANGUP");
+
+ return ((const char *)(str+1));
+}
+
+const char *
+tiocflush(private_t *pri, int arg) /* bit map passsed by TIOCFLUSH */
+{
+ char *str = pri->code_buf;
+
+ if (arg & ~(FREAD|FWRITE))
+ return ((char *)NULL);
+
+ *str = '\0';
+ if (arg & FREAD)
+ (void) strcat(str, "|FREAD");
+ if (arg & FWRITE)
+ (void) strcat(str, "|FWRITE");
+
+ return ((const char *)(str+1));
+}
+
+const char *
+strflush(int arg) /* streams flush option (I_FLUSH) */
+{
+ const char *str = NULL;
+
+ switch (arg) {
+ case FLUSHR: str = "FLUSHR"; break;
+ case FLUSHW: str = "FLUSHW"; break;
+ case FLUSHRW: str = "FLUSHRW"; break;
+ }
+
+ return (str);
+}
+
+#define ALL_MOUNT_FLAGS (MS_RDONLY|MS_FSS|MS_DATA|MS_NOSUID|MS_REMOUNT| \
+ MS_NOTRUNC|MS_OVERLAY|MS_OPTIONSTR|MS_GLOBAL|MS_FORCE|MS_NOMNTTAB)
+
+const char *
+mountflags(private_t *pri, int arg) /* bit map of mount syscall flags */
+{
+ char *str = pri->code_buf;
+ size_t used = 0;
+
+ if (arg & ~ALL_MOUNT_FLAGS)
+ return ((char *)NULL);
+
+ *str = '\0';
+ if (arg & MS_RDONLY)
+ used = strlcat(str, "|MS_RDONLY", sizeof (pri->code_buf));
+ if (arg & MS_FSS)
+ used = strlcat(str, "|MS_FSS", sizeof (pri->code_buf));
+ if (arg & MS_DATA)
+ used = strlcat(str, "|MS_DATA", sizeof (pri->code_buf));
+ if (arg & MS_NOSUID)
+ used = strlcat(str, "|MS_NOSUID", sizeof (pri->code_buf));
+ if (arg & MS_REMOUNT)
+ used = strlcat(str, "|MS_REMOUNT", sizeof (pri->code_buf));
+ if (arg & MS_NOTRUNC)
+ used = strlcat(str, "|MS_NOTRUNC", sizeof (pri->code_buf));
+ if (arg & MS_OVERLAY)
+ used = strlcat(str, "|MS_OVERLAY", sizeof (pri->code_buf));
+ if (arg & MS_OPTIONSTR)
+ used = strlcat(str, "|MS_OPTIONSTR", sizeof (pri->code_buf));
+ if (arg & MS_GLOBAL)
+ used = strlcat(str, "|MS_GLOBAL", sizeof (pri->code_buf));
+ if (arg & MS_FORCE)
+ used = strlcat(str, "|MS_FORCE", sizeof (pri->code_buf));
+ if (arg & MS_NOMNTTAB)
+ used = strlcat(str, "|MS_NOMNTTAB", sizeof (pri->code_buf));
+
+ if (used == 0 || used >= sizeof (pri->code_buf))
+ return ((char *)NULL); /* use prt_hex() */
+
+ return ((const char *)(str+1));
+}
+
+const char *
+svfsflags(private_t *pri, ulong_t arg) /* bit map of statvfs syscall flags */
+{
+ char *str = pri->code_buf;
+
+ if (arg & ~(ST_RDONLY|ST_NOSUID|ST_NOTRUNC)) {
+ (void) sprintf(str, "0x%lx", arg);
+ return (str);
+ }
+ *str = '\0';
+ if (arg & ST_RDONLY)
+ (void) strcat(str, "|ST_RDONLY");
+ if (arg & ST_NOSUID)
+ (void) strcat(str, "|ST_NOSUID");
+ if (arg & ST_NOTRUNC)
+ (void) strcat(str, "|ST_NOTRUNC");
+ if (*str == '\0')
+ (void) strcat(str, "|0");
+ return ((const char *)(str+1));
+}
+
+const char *
+fuiname(int arg) /* fusers() input argument */
+{
+ const char *str = NULL;
+
+ switch (arg) {
+ case F_FILE_ONLY: str = "F_FILE_ONLY"; break;
+ case F_CONTAINED: str = "F_CONTAINED"; break;
+ }
+
+ return (str);
+}
+
+const char *
+fuflags(private_t *pri, int arg) /* fusers() output flags */
+{
+ char *str = pri->code_buf;
+
+ if (arg & ~(F_CDIR|F_RDIR|F_TEXT|F_MAP|F_OPEN|F_TRACE|F_TTY)) {
+ (void) sprintf(str, "0x%x", arg);
+ return (str);
+ }
+ *str = '\0';
+ if (arg & F_CDIR)
+ (void) strcat(str, "|F_CDIR");
+ if (arg & F_RDIR)
+ (void) strcat(str, "|F_RDIR");
+ if (arg & F_TEXT)
+ (void) strcat(str, "|F_TEXT");
+ if (arg & F_MAP)
+ (void) strcat(str, "|F_MAP");
+ if (arg & F_OPEN)
+ (void) strcat(str, "|F_OPEN");
+ if (arg & F_TRACE)
+ (void) strcat(str, "|F_TRACE");
+ if (arg & F_TTY)
+ (void) strcat(str, "|F_TTY");
+ if (*str == '\0')
+ (void) strcat(str, "|0");
+ return ((const char *)(str+1));
+}
+
+
+const char *
+ipprotos(int arg) /* IP protocols cf. netinet/in.h */
+{
+ switch (arg) {
+ case IPPROTO_IP: return ("IPPROTO_IP");
+ case IPPROTO_ICMP: return ("IPPROTO_ICMP");
+ case IPPROTO_IGMP: return ("IPPROTO_IGMP");
+ case IPPROTO_GGP: return ("IPPROTO_GGP");
+ case IPPROTO_ENCAP: return ("IPPROTO_ENCAP");
+ case IPPROTO_TCP: return ("IPPROTO_TCP");
+ case IPPROTO_EGP: return ("IPPROTO_EGP");
+ case IPPROTO_PUP: return ("IPPROTO_PUP");
+ case IPPROTO_UDP: return ("IPPROTO_UDP");
+ case IPPROTO_IDP: return ("IPPROTO_IDP");
+ case IPPROTO_IPV6: return ("IPPROTO_IPV6");
+ case IPPROTO_ROUTING: return ("IPPROTO_ROUTING");
+ case IPPROTO_FRAGMENT: return ("IPPROTO_FRAGMENT");
+ case IPPROTO_RSVP: return ("IPPROTO_RSVP");
+ case IPPROTO_ESP: return ("IPPROTO_ESP");
+ case IPPROTO_AH: return ("IPPROTO_AH");
+ case IPPROTO_ICMPV6: return ("IPPROTO_ICMPV6");
+ case IPPROTO_NONE: return ("IPPROTO_NONE");
+ case IPPROTO_DSTOPTS: return ("IPPROTO_DSTOPTS");
+ case IPPROTO_HELLO: return ("IPPROTO_HELLO");
+ case IPPROTO_ND: return ("IPPROTO_ND");
+ case IPPROTO_EON: return ("IPPROTO_EON");
+ case IPPROTO_PIM: return ("IPPROTO_PIM");
+ case IPPROTO_SCTP: return ("IPPROTO_SCTP");
+ case IPPROTO_RAW: return ("IPPROTO_RAW");
+ default: return (NULL);
+ }
+}
diff --git a/usr/src/cmd/truss/expound.c b/usr/src/cmd/truss/expound.c
new file mode 100644
index 0000000..915ec46
--- /dev/null
+++ b/usr/src/cmd/truss/expound.c
@@ -0,0 +1,5605 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
+ * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ */
+
+/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
+/* All Rights Reserved */
+
+#define _SYSCALL32
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <libproc.h>
+#include <string.h>
+#include <limits.h>
+#include <sys/statfs.h>
+#include <sys/times.h>
+#include <sys/timex.h>
+#include <sys/utssys.h>
+#include <sys/utsname.h>
+#include <sys/ipc.h>
+#include <sys/ipc_impl.h>
+#include <sys/msg.h>
+#include <sys/msg_impl.h>
+#include <sys/sem.h>
+#include <sys/sem_impl.h>
+#include <sys/shm.h>
+#include <sys/shm_impl.h>
+#include <sys/dirent.h>
+#include <ustat.h>
+#include <fcntl.h>
+#include <time.h>
+#include <sys/termios.h>
+#include <sys/termiox.h>
+#include <sys/termio.h>
+#include <sys/ttold.h>
+#include <sys/jioctl.h>
+#include <sys/filio.h>
+#include <stropts.h>
+#include <poll.h>
+#include <sys/uio.h>
+#include <sys/resource.h>
+#include <sys/statvfs.h>
+#include <sys/time.h>
+#include <sys/aio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/un.h>
+#include <sys/byteorder.h>
+#include <arpa/inet.h>
+#include <sys/audioio.h>
+#include <sys/cladm.h>
+#include <sys/synch.h>
+#include <sys/synch32.h>
+#include <sys/sysmacros.h>
+#include <sys/sendfile.h>
+#include <priv.h>
+#include <ucred.h>
+#include <sys/ucred.h>
+#include <sys/port_impl.h>
+#include <sys/zone.h>
+#include <sys/priv_impl.h>
+#include <sys/priv.h>
+#include <tsol/label.h>
+#include <sys/nvpair.h>
+#include <libnvpair.h>
+#include <sys/rctl_impl.h>
+#include <sys/socketvar.h>
+#include <sys/fs/zfs.h>
+#include <sys/zfs_ioctl.h>
+
+#include "ramdata.h"
+#include "systable.h"
+#include "proto.h"
+
+void show_sigset(private_t *, long, const char *);
+void show_ioctl(private_t *, int, long);
+void show_zfs_ioc(private_t *, long);
+
+static void
+mk_ctime(char *str, size_t maxsize, time_t value)
+{
+ (void) strftime(str, maxsize, "%b %e %H:%M:%S %Z %Y",
+ localtime(&value));
+}
+
+void
+prtime(private_t *pri, const char *name, time_t value)
+{
+ char str[80];
+
+ mk_ctime(str, sizeof (str), value);
+ (void) printf("%s\t%s%s [ %lu ]\n",
+ pri->pname,
+ name,
+ str,
+ value);
+}
+
+void
+prtimeval(private_t *pri, const char *name, struct timeval *value)
+{
+ char str[80];
+
+ mk_ctime(str, sizeof (str), value->tv_sec);
+ (void) printf("%s\t%s%s [ %lu.%6.6lu ]\n",
+ pri->pname,
+ name,
+ str,
+ value->tv_sec,
+ value->tv_usec);
+}
+
+void
+prtimestruc(private_t *pri, const char *name, timestruc_t *value)
+{
+ char str[80];
+
+ mk_ctime(str, sizeof (str), value->tv_sec);
+ (void) printf("%s\t%s%s [ %lu.%9.9lu ]\n",
+ pri->pname,
+ name,
+ str,
+ value->tv_sec,
+ value->tv_nsec);
+}
+
+static void
+show_utimens(private_t *pri, long offset)
+{
+ struct {
+ timespec_t atime;
+ timespec_t mtime;
+ } utimbuf;
+
+ if (offset == 0)
+ return;
+
+ if (data_model == PR_MODEL_NATIVE) {
+ if (Pread(Proc, &utimbuf, sizeof (utimbuf), offset)
+ != sizeof (utimbuf))
+ return;
+ } else {
+ struct {
+ timespec32_t atime;
+ timespec32_t mtime;
+ } utimbuf32;
+
+ if (Pread(Proc, &utimbuf32, sizeof (utimbuf32), offset)
+ != sizeof (utimbuf32))
+ return;
+
+ TIMESPEC32_TO_TIMESPEC(&utimbuf.atime, &utimbuf32.atime);
+ TIMESPEC32_TO_TIMESPEC(&utimbuf.mtime, &utimbuf32.mtime);
+ }
+
+ /* print access and modification times */
+ if (utimbuf.atime.tv_nsec == UTIME_OMIT)
+ (void) printf("%s\tat = UTIME_OMIT\n", pri->pname);
+ else if (utimbuf.atime.tv_nsec == UTIME_NOW)
+ (void) printf("%s\tat = UTIME_NOW\n", pri->pname);
+ else
+ prtimestruc(pri, "at = ", &utimbuf.atime);
+ if (utimbuf.mtime.tv_nsec == UTIME_OMIT)
+ (void) printf("%s\tmt = UTIME_OMIT\n", pri->pname);
+ else if (utimbuf.mtime.tv_nsec == UTIME_NOW)
+ (void) printf("%s\tmt = UTIME_NOW\n", pri->pname);
+ else
+ prtimestruc(pri, "mt = ", &utimbuf.mtime);
+}
+
+void
+show_timeofday(private_t *pri)
+{
+ struct timeval tod;
+ long offset;
+
+ if (pri->sys_nargs < 1 || (offset = pri->sys_args[0]) == NULL)
+ return;
+
+ if (data_model == PR_MODEL_NATIVE) {
+ if (Pread(Proc, &tod, sizeof (tod), offset)
+ != sizeof (tod))
+ return;
+ } else {
+ struct timeval32 tod32;
+
+ if (Pread(Proc, &tod32, sizeof (tod32), offset)
+ != sizeof (tod32))
+ return;
+
+ TIMEVAL32_TO_TIMEVAL(&tod, &tod32);
+ }
+
+ prtimeval(pri, "time: ", &tod);
+}
+
+void
+show_itimerval(private_t *pri, long offset, const char *name)
+{
+ struct itimerval itimerval;
+
+ if (offset == 0)
+ return;
+
+ if (data_model == PR_MODEL_NATIVE) {
+ if (Pread(Proc, &itimerval, sizeof (itimerval), offset)
+ != sizeof (itimerval))
+ return;
+ } else {
+ struct itimerval32 itimerval32;
+
+ if (Pread(Proc, &itimerval32, sizeof (itimerval32), offset)
+ != sizeof (itimerval32))
+ return;
+
+ ITIMERVAL32_TO_ITIMERVAL(&itimerval, &itimerval32);
+ }
+
+ (void) printf(
+ "%s\t%s: interval: %4ld.%6.6ld sec value: %4ld.%6.6ld sec\n",
+ pri->pname,
+ name,
+ itimerval.it_interval.tv_sec,
+ itimerval.it_interval.tv_usec,
+ itimerval.it_value.tv_sec,
+ itimerval.it_value.tv_usec);
+}
+
+void
+show_timeval(private_t *pri, long offset, const char *name)
+{
+ struct timeval timeval;
+
+ if (offset == 0)
+ return;
+
+ if (data_model == PR_MODEL_NATIVE) {
+ if (Pread(Proc, &timeval, sizeof (timeval), offset)
+ != sizeof (timeval))
+ return;
+ } else {
+ struct timeval32 timeval32;
+
+ if (Pread(Proc, &timeval32, sizeof (timeval32), offset)
+ != sizeof (timeval32))
+ return;
+
+ TIMEVAL32_TO_TIMEVAL(&timeval, &timeval32);
+ }
+
+ (void) printf(
+ "%s\t%s: %ld.%6.6ld sec\n",
+ pri->pname,
+ name,
+ timeval.tv_sec,
+ timeval.tv_usec);
+}
+
+void
+show_timestruc(private_t *pri, long offset, const char *name)
+{
+ timestruc_t timestruc;
+
+ if (offset == 0)
+ return;
+
+ if (data_model == PR_MODEL_NATIVE) {
+ if (Pread(Proc, &timestruc, sizeof (timestruc), offset)
+ != sizeof (timestruc))
+ return;
+ } else {
+ timestruc32_t timestruc32;
+
+ if (Pread(Proc, &timestruc32, sizeof (timestruc32), offset)
+ != sizeof (timestruc32))
+ return;
+
+ TIMESPEC32_TO_TIMESPEC(&timestruc, &timestruc32);
+ }
+
+ (void) printf(
+ "%s\t%s: %ld.%9.9ld sec\n",
+ pri->pname,
+ name,
+ timestruc.tv_sec,
+ timestruc.tv_nsec);
+}
+
+void
+show_stime(private_t *pri)
+{
+ if (pri->sys_nargs >= 1) {
+ /* print new system time */
+ prtime(pri, "systime = ", (time_t)pri->sys_args[0]);
+ }
+}
+
+void
+show_times(private_t *pri)
+{
+ long hz = sysconf(_SC_CLK_TCK);
+ long offset;
+ struct tms tms;
+
+ if (pri->sys_nargs < 1 || (offset = pri->sys_args[0]) == NULL)
+ return;
+
+ if (data_model == PR_MODEL_NATIVE) {
+ if (Pread(Proc, &tms, sizeof (tms), offset)
+ != sizeof (tms))
+ return;
+ } else {
+ struct tms32 tms32;
+
+ if (Pread(Proc, &tms32, sizeof (tms32), offset)
+ != sizeof (tms32))
+ return;
+
+ /*
+ * This looks a bit odd (since the values are actually
+ * signed), but we need to suppress sign extension to
+ * preserve compatibility (we've always printed these
+ * numbers as unsigned quantities).
+ */
+ tms.tms_utime = (unsigned)tms32.tms_utime;
+ tms.tms_stime = (unsigned)tms32.tms_stime;
+ tms.tms_cutime = (unsigned)tms32.tms_cutime;
+ tms.tms_cstime = (unsigned)tms32.tms_cstime;
+ }
+
+ (void) printf(
+ "%s\tutim=%-6lu stim=%-6lu cutim=%-6lu cstim=%-6lu (HZ=%ld)\n",
+ pri->pname,
+ tms.tms_utime,
+ tms.tms_stime,
+ tms.tms_cutime,
+ tms.tms_cstime,
+ hz);
+}
+
+void
+show_uname(private_t *pri, long offset)
+{
+ /*
+ * Old utsname buffer (no longer accessible in <sys/utsname.h>).
+ */
+ struct {
+ char sysname[9];
+ char nodename[9];
+ char release[9];
+ char version[9];
+ char machine[9];
+ } ubuf;
+
+ if (offset != NULL &&
+ Pread(Proc, &ubuf, sizeof (ubuf), offset) == sizeof (ubuf)) {
+ (void) printf(
+ "%s\tsys=%-9.9snod=%-9.9srel=%-9.9sver=%-9.9smch=%.9s\n",
+ pri->pname,
+ ubuf.sysname,
+ ubuf.nodename,
+ ubuf.release,
+ ubuf.version,
+ ubuf.machine);
+ }
+}
+
+/* XX64 -- definition of 'struct ustat' is strange -- check out the defn */
+void
+show_ustat(private_t *pri, long offset)
+{
+ struct ustat ubuf;
+
+ if (offset != NULL &&
+ Pread(Proc, &ubuf, sizeof (ubuf), offset) == sizeof (ubuf)) {
+ (void) printf(
+ "%s\ttfree=%-6ld tinode=%-5lu fname=%-6.6s fpack=%-.6s\n",
+ pri->pname,
+ ubuf.f_tfree,
+ ubuf.f_tinode,
+ ubuf.f_fname,
+ ubuf.f_fpack);
+ }
+}
+
+#ifdef _LP64
+void
+show_ustat32(private_t *pri, long offset)
+{
+ struct ustat32 ubuf;
+
+ if (offset != NULL &&
+ Pread(Proc, &ubuf, sizeof (ubuf), offset) == sizeof (ubuf)) {
+ (void) printf(
+ "%s\ttfree=%-6d tinode=%-5u fname=%-6.6s fpack=%-.6s\n",
+ pri->pname,
+ ubuf.f_tfree,
+ ubuf.f_tinode,
+ ubuf.f_fname,
+ ubuf.f_fpack);
+ }
+}
+#endif /* _LP64 */
+
+void
+show_fusers(private_t *pri, long offset, long nproc)
+{
+ f_user_t fubuf;
+ int serial = (nproc > 4);
+
+ if (offset == 0)
+ return;
+
+ /* enter region of lengthy output */
+ if (serial)
+ Eserialize();
+
+ while (nproc > 0 &&
+ Pread(Proc, &fubuf, sizeof (fubuf), offset) == sizeof (fubuf)) {
+ (void) printf("%s\tpid=%-5d uid=%-5u flags=%s\n",
+ pri->pname,
+ (int)fubuf.fu_pid,
+ fubuf.fu_uid,
+ fuflags(pri, fubuf.fu_flags));
+ nproc--;
+ offset += sizeof (fubuf);
+ }
+
+ /* exit region of lengthy output */
+ if (serial)
+ Xserialize();
+}
+
+void
+show_utssys(private_t *pri, long r0)
+{
+ if (pri->sys_nargs >= 3) {
+ switch (pri->sys_args[2]) {
+ case UTS_UNAME:
+ show_uname(pri, (long)pri->sys_args[0]);
+ break;
+ case UTS_USTAT:
+ show_ustat(pri, (long)pri->sys_args[0]);
+ break;
+ case UTS_FUSERS:
+ show_fusers(pri, (long)pri->sys_args[3], r0);
+ break;
+ }
+ }
+}
+
+#ifdef _LP64
+void
+show_utssys32(private_t *pri, long r0)
+{
+ if (pri->sys_nargs >= 3) {
+ switch (pri->sys_args[2]) {
+ case UTS_UNAME:
+ show_uname(pri, (long)pri->sys_args[0]);
+ break;
+ case UTS_USTAT:
+ show_ustat32(pri, (long)pri->sys_args[0]);
+ break;
+ case UTS_FUSERS:
+ show_fusers(pri, (long)pri->sys_args[3], r0);
+ break;
+ }
+ }
+}
+#endif /* _LP64 */
+
+void
+show_cladm(private_t *pri, int code, int function, long offset)
+{
+ int arg;
+
+ switch (code) {
+ case CL_INITIALIZE:
+ switch (function) {
+ case CL_GET_BOOTFLAG:
+ if (Pread(Proc, &arg, sizeof (arg), offset)
+ == sizeof (arg)) {
+ if (arg & CLUSTER_CONFIGURED)
+ (void) printf("%s\tbootflags="
+ "CLUSTER_CONFIGURED", pri->pname);
+ if (arg & CLUSTER_BOOTED)
+ (void) printf("|CLUSTER_BOOTED\n");
+ }
+ break;
+ }
+ break;
+ case CL_CONFIG:
+ switch (function) {
+ case CL_NODEID:
+ case CL_HIGHEST_NODEID:
+ if (Pread(Proc, &arg, sizeof (arg), offset)
+ == sizeof (arg))
+ (void) printf("%s\tnodeid=%d\n",
+ pri->pname, arg);
+ }
+ break;
+ }
+}
+
+#define ALL_LOCK_TYPES \
+ (USYNC_PROCESS | LOCK_ERRORCHECK | LOCK_RECURSIVE | \
+ LOCK_PRIO_INHERIT | LOCK_PRIO_PROTECT | LOCK_ROBUST | \
+ USYNC_PROCESS_ROBUST)
+
+/* return cv and mutex types */
+const char *
+synch_type(private_t *pri, uint_t type)
+{
+ char *str = pri->code_buf;
+
+ if (type & USYNC_PROCESS)
+ (void) strcpy(str, "USYNC_PROCESS");
+ else
+ (void) strcpy(str, "USYNC_THREAD");
+
+ if (type & LOCK_ERRORCHECK)
+ (void) strcat(str, "|LOCK_ERRORCHECK");
+ if (type & LOCK_RECURSIVE)
+ (void) strcat(str, "|LOCK_RECURSIVE");
+ if (type & LOCK_PRIO_INHERIT)
+ (void) strcat(str, "|LOCK_PRIO_INHERIT");
+ if (type & LOCK_PRIO_PROTECT)
+ (void) strcat(str, "|LOCK_PRIO_PROTECT");
+ if (type & LOCK_ROBUST)
+ (void) strcat(str, "|LOCK_ROBUST");
+ if (type & USYNC_PROCESS_ROBUST)
+ (void) strcat(str, "|USYNC_PROCESS_ROBUST");
+
+ if ((type &= ~ALL_LOCK_TYPES) != 0)
+ (void) sprintf(str + strlen(str), "|0x%.4X", type);
+
+ return ((const char *)str);
+}
+
+void
+show_mutex(private_t *pri, long offset)
+{
+ lwp_mutex_t mutex;
+
+ if (Pread(Proc, &mutex, sizeof (mutex), offset) == sizeof (mutex)) {
+ (void) printf("%s\tmutex type: %s\n",
+ pri->pname,
+ synch_type(pri, mutex.mutex_type));
+ }
+}
+
+void
+show_condvar(private_t *pri, long offset)
+{
+ lwp_cond_t condvar;
+
+ if (Pread(Proc, &condvar, sizeof (condvar), offset)
+ == sizeof (condvar)) {
+ (void) printf("%s\tcondvar type: %s\n",
+ pri->pname,
+ synch_type(pri, condvar.cond_type));
+ }
+}
+
+void
+show_sema(private_t *pri, long offset)
+{
+ lwp_sema_t sema;
+
+ if (Pread(Proc, &sema, sizeof (sema), offset) == sizeof (sema)) {
+ (void) printf("%s\tsema type: %s count = %u\n",
+ pri->pname,
+ synch_type(pri, sema.sema_type),
+ sema.sema_count);
+ }
+}
+
+void
+show_rwlock(private_t *pri, long offset)
+{
+ lwp_rwlock_t rwlock;
+
+ if (Pread(Proc, &rwlock, sizeof (rwlock), offset) == sizeof (rwlock)) {
+ (void) printf("%s\trwlock type: %s readers = %d\n",
+ pri->pname,
+ synch_type(pri, rwlock.rwlock_type),
+ rwlock.rwlock_readers);
+ }
+}
+
+/* represent character as itself ('c') or octal (012) */
+char *
+show_char(char *buf, int c)
+{
+ const char *fmt;
+
+ if (c >= ' ' && c < 0177)
+ fmt = "'%c'";
+ else
+ fmt = "%.3o";
+
+ (void) sprintf(buf, fmt, c&0xff);
+ return (buf);
+}
+
+void
+show_termio(private_t *pri, long offset)
+{
+ struct termio termio;
+ char cbuf[8];
+ int i;
+
+ if (Pread(Proc, &termio, sizeof (termio), offset) == sizeof (termio)) {
+ (void) printf(
+ "%s\tiflag=0%.6o oflag=0%.6o cflag=0%.6o lflag=0%.6o line=%d\n",
+ pri->pname,
+ termio.c_iflag,
+ termio.c_oflag,
+ termio.c_cflag,
+ termio.c_lflag,
+ termio.c_line);
+ (void) printf("%s\t cc: ", pri->pname);
+ for (i = 0; i < NCC; i++)
+ (void) printf(" %s",
+ show_char(cbuf, (int)termio.c_cc[i]));
+ (void) fputc('\n', stdout);
+ }
+}
+
+void
+show_termios(private_t *pri, long offset)
+{
+ struct termios termios;
+ char cbuf[8];
+ int i;
+
+ if (Pread(Proc, &termios, sizeof (termios), offset)
+ == sizeof (termios)) {
+ (void) printf(
+ "%s\tiflag=0%.6o oflag=0%.6o cflag=0%.6o lflag=0%.6o\n",
+ pri->pname,
+ termios.c_iflag,
+ termios.c_oflag,
+ termios.c_cflag,
+ termios.c_lflag);
+ (void) printf("%s\t cc: ", pri->pname);
+ for (i = 0; i < NCCS; i++) {
+ if (i == NCC) /* show new chars on new line */
+ (void) printf("\n%s\t\t", pri->pname);
+ (void) printf(" %s",
+ show_char(cbuf, (int)termios.c_cc[i]));
+ }
+ (void) fputc('\n', stdout);
+ }
+}
+
+void
+show_termiox(private_t *pri, long offset)
+{
+ struct termiox termiox;
+ int i;
+
+ if (Pread(Proc, &termiox, sizeof (termiox), offset)
+ == sizeof (termiox)) {
+ (void) printf("%s\thflag=0%.3o cflag=0%.3o rflag=0%.3o",
+ pri->pname,
+ termiox.x_hflag,
+ termiox.x_cflag,
+ termiox.x_rflag[0]);
+ for (i = 1; i < NFF; i++)
+ (void) printf(",0%.3o", termiox.x_rflag[i]);
+ (void) printf(" sflag=0%.3o\n",
+ termiox.x_sflag);
+ }
+}
+
+void
+show_sgttyb(private_t *pri, long offset)
+{
+ struct sgttyb sgttyb;
+
+ if (Pread(Proc, &sgttyb, sizeof (sgttyb), offset) == sizeof (sgttyb)) {
+ char erase[8];
+ char kill[8];
+
+ (void) printf(
+ "%s\tispeed=%-2d ospeed=%-2d erase=%s kill=%s flags=0x%.8x\n",
+ pri->pname,
+ sgttyb.sg_ispeed&0xff,
+ sgttyb.sg_ospeed&0xff,
+ show_char(erase, sgttyb.sg_erase),
+ show_char(kill, sgttyb.sg_kill),
+ sgttyb.sg_flags);
+ }
+}
+
+void
+show_ltchars(private_t *pri, long offset)
+{
+ struct ltchars ltchars;
+ char *p;
+ char cbuf[8];
+ int i;
+
+ if (Pread(Proc, &ltchars, sizeof (ltchars), offset)
+ == sizeof (ltchars)) {
+ (void) printf("%s\t cc: ", pri->pname);
+ for (p = (char *)&ltchars, i = 0; i < sizeof (ltchars); i++)
+ (void) printf(" %s", show_char(cbuf, (int)*p++));
+ (void) fputc('\n', stdout);
+ }
+}
+
+void
+show_tchars(private_t *pri, long offset)
+{
+ struct tchars tchars;
+ char *p;
+ char cbuf[8];
+ int i;
+
+ if (Pread(Proc, &tchars, sizeof (tchars), offset) == sizeof (tchars)) {
+ (void) printf("%s\t cc: ", pri->pname);
+ for (p = (char *)&tchars, i = 0; i < sizeof (tchars); i++)
+ (void) printf(" %s", show_char(cbuf, (int)*p++));
+ (void) fputc('\n', stdout);
+ }
+}
+
+void
+show_termcb(private_t *pri, long offset)
+{
+ struct termcb termcb;
+
+ if (Pread(Proc, &termcb, sizeof (termcb), offset) == sizeof (termcb)) {
+ (void) printf(
+ "%s\tflgs=0%.2o termt=%d crow=%d ccol=%d vrow=%d lrow=%d\n",
+ pri->pname,
+ termcb.st_flgs&0xff,
+ termcb.st_termt&0xff,
+ termcb.st_crow&0xff,
+ termcb.st_ccol&0xff,
+ termcb.st_vrow&0xff,
+ termcb.st_lrow&0xff);
+ }
+}
+
+/* integer value pointed to by ioctl() arg */
+void
+show_strint(private_t *pri, int code, long offset)
+{
+ int val;
+
+ if (Pread(Proc, &val, sizeof (val), offset) == sizeof (val)) {
+ const char *s = NULL;
+
+ switch (code) { /* interpret these symbolically */
+ case I_GRDOPT:
+ s = strrdopt(val);
+ break;
+ case I_GETSIG:
+ s = strevents(pri, val);
+ break;
+ case TIOCFLUSH:
+ s = tiocflush(pri, val);
+ break;
+ }
+
+ if (s == NULL)
+ (void) printf("%s\t0x%.8lX: %d\n",
+ pri->pname, offset, val);
+ else
+ (void) printf("%s\t0x%.8lX: %s\n",
+ pri->pname, offset, s);
+ }
+}
+
+void
+show_strioctl(private_t *pri, long offset)
+{
+ struct strioctl strioctl;
+
+ if (Pread(Proc, &strioctl, sizeof (strioctl), offset) ==
+ sizeof (strioctl)) {
+ (void) printf(
+ "%s\tcmd=%s timout=%d len=%d dp=0x%.8lX\n",
+ pri->pname,
+ ioctlname(pri, strioctl.ic_cmd),
+ strioctl.ic_timout,
+ strioctl.ic_len,
+ (long)strioctl.ic_dp);
+
+ if (pri->recur++ == 0) /* avoid indefinite recursion */
+ show_ioctl(pri, strioctl.ic_cmd,
+ (long)strioctl.ic_dp);
+ --pri->recur;
+ }
+}
+
+#ifdef _LP64
+void
+show_strioctl32(private_t *pri, long offset)
+{
+ struct strioctl32 strioctl;
+
+ if (Pread(Proc, &strioctl, sizeof (strioctl), offset) ==
+ sizeof (strioctl)) {
+ (void) printf(
+ "%s\tcmd=%s timout=%d len=%d dp=0x%.8lX\n",
+ pri->pname,
+ ioctlname(pri, strioctl.ic_cmd),
+ strioctl.ic_timout,
+ strioctl.ic_len,
+ (long)strioctl.ic_dp);
+
+ if (pri->recur++ == 0) /* avoid indefinite recursion */
+ show_ioctl(pri, strioctl.ic_cmd,
+ (long)strioctl.ic_dp);
+ --pri->recur;
+ }
+}
+#endif /* _LP64 */
+
+void
+print_strbuf(private_t *pri, struct strbuf *sp, const char *name, int dump)
+{
+ (void) printf(
+ "%s\t%s: maxlen=%-4d len=%-4d buf=0x%.8lX",
+ pri->pname,
+ name,
+ sp->maxlen,
+ sp->len,
+ (long)sp->buf);
+ /*
+ * Should we show the buffer contents?
+ * Keyed to the '-r fds' and '-w fds' options?
+ */
+ if (sp->buf == NULL || sp->len <= 0)
+ (void) fputc('\n', stdout);
+ else {
+ int nb = (sp->len > 8)? 8 : sp->len;
+ char buffer[8];
+ char obuf[40];
+
+ if (Pread(Proc, buffer, (size_t)nb, (long)sp->buf) == nb) {
+ (void) strcpy(obuf, ": \"");
+ showbytes(buffer, nb, obuf+3);
+ (void) strcat(obuf,
+ (nb == sp->len)?
+ (const char *)"\"" : (const char *)"\"..");
+ (void) fputs(obuf, stdout);
+ }
+ (void) fputc('\n', stdout);
+ if (dump && sp->len > 8)
+ showbuffer(pri, (long)sp->buf, (long)sp->len);
+ }
+}
+
+#ifdef _LP64
+void
+print_strbuf32(private_t *pri, struct strbuf32 *sp, const char *name, int dump)
+{
+ (void) printf(
+ "%s\t%s: maxlen=%-4d len=%-4d buf=0x%.8lX",
+ pri->pname,
+ name,
+ sp->maxlen,
+ sp->len,
+ (long)sp->buf);
+ /*
+ * Should we show the buffer contents?
+ * Keyed to the '-r fds' and '-w fds' options?
+ */
+ if (sp->buf == NULL || sp->len <= 0)
+ (void) fputc('\n', stdout);
+ else {
+ int nb = (sp->len > 8)? 8 : sp->len;
+ char buffer[8];
+ char obuf[40];
+
+ if (Pread(Proc, buffer, (size_t)nb, (long)sp->buf) == nb) {
+ (void) strcpy(obuf, ": \"");
+ showbytes(buffer, nb, obuf+3);
+ (void) strcat(obuf,
+ (nb == sp->len)?
+ (const char *)"\"" : (const char *)"\"..");
+ (void) fputs(obuf, stdout);
+ }
+ (void) fputc('\n', stdout);
+ if (dump && sp->len > 8)
+ showbuffer(pri, (long)sp->buf, (long)sp->len);
+ }
+}
+#endif /* _LP64 */
+
+/* strpeek and strfdinsert flags word */
+const char *
+strflags(private_t *pri, int flags)
+{
+ const char *s;
+
+ switch (flags) {
+ case 0:
+ s = "0";
+ break;
+ case RS_HIPRI:
+ s = "RS_HIPRI";
+ break;
+ default:
+ (void) sprintf(pri->code_buf, "0x%.4X", flags);
+ s = pri->code_buf;
+ }
+
+ return (s);
+}
+
+void
+show_strpeek(private_t *pri, long offset)
+{
+ struct strpeek strpeek;
+
+ if (Pread(Proc, &strpeek, sizeof (strpeek), offset)
+ == sizeof (strpeek)) {
+
+ print_strbuf(pri, &strpeek.ctlbuf, "ctl", FALSE);
+ print_strbuf(pri, &strpeek.databuf, "dat", FALSE);
+
+ (void) printf("%s\tflags=%s\n",
+ pri->pname,
+ strflags(pri, strpeek.flags));
+ }
+}
+
+#ifdef _LP64
+void
+show_strpeek32(private_t *pri, long offset)
+{
+ struct strpeek32 strpeek;
+
+ if (Pread(Proc, &strpeek, sizeof (strpeek), offset)
+ == sizeof (strpeek)) {
+
+ print_strbuf32(pri, &strpeek.ctlbuf, "ctl", FALSE);
+ print_strbuf32(pri, &strpeek.databuf, "dat", FALSE);
+
+ (void) printf("%s\tflags=%s\n",
+ pri->pname,
+ strflags(pri, strpeek.flags));
+ }
+}
+#endif /* _LP64 */
+
+void
+show_strfdinsert(private_t *pri, long offset)
+{
+ struct strfdinsert strfdinsert;
+
+ if (Pread(Proc, &strfdinsert, sizeof (strfdinsert), offset) ==
+ sizeof (strfdinsert)) {
+
+ print_strbuf(pri, &strfdinsert.ctlbuf, "ctl", FALSE);
+ print_strbuf(pri, &strfdinsert.databuf, "dat", FALSE);
+
+ (void) printf("%s\tflags=%s fildes=%d offset=%d\n",
+ pri->pname,
+ strflags(pri, strfdinsert.flags),
+ strfdinsert.fildes,
+ strfdinsert.offset);
+ }
+}
+
+#ifdef _LP64
+void
+show_strfdinsert32(private_t *pri, long offset)
+{
+ struct strfdinsert32 strfdinsert;
+
+ if (Pread(Proc, &strfdinsert, sizeof (strfdinsert), offset) ==
+ sizeof (strfdinsert)) {
+
+ print_strbuf32(pri, &strfdinsert.ctlbuf, "ctl", FALSE);
+ print_strbuf32(pri, &strfdinsert.databuf, "dat", FALSE);
+
+ (void) printf("%s\tflags=%s fildes=%d offset=%d\n",
+ pri->pname,
+ strflags(pri, strfdinsert.flags),
+ strfdinsert.fildes,
+ strfdinsert.offset);
+ }
+}
+#endif /* _LP64 */
+
+void
+show_strrecvfd(private_t *pri, long offset)
+{
+ struct strrecvfd strrecvfd;
+
+ if (Pread(Proc, &strrecvfd, sizeof (strrecvfd), offset) ==
+ sizeof (strrecvfd)) {
+ (void) printf(
+ "%s\tfd=%-5d uid=%-5u gid=%u\n",
+ pri->pname,
+ strrecvfd.fd,
+ strrecvfd.uid,
+ strrecvfd.gid);
+ }
+}
+
+void
+show_strlist(private_t *pri, long offset)
+{
+ struct str_list strlist;
+ struct str_mlist list;
+ int count;
+
+ if (Pread(Proc, &strlist, sizeof (strlist), offset) ==
+ sizeof (strlist)) {
+ (void) printf("%s\tnmods=%d modlist=0x%.8lX\n",
+ pri->pname,
+ strlist.sl_nmods,
+ (long)strlist.sl_modlist);
+
+ count = strlist.sl_nmods;
+ offset = (long)strlist.sl_modlist;
+ while (!interrupt && --count >= 0) {
+ if (Pread(Proc, &list, sizeof (list), offset) !=
+ sizeof (list))
+ break;
+ (void) printf("%s\t\t\"%.*s\"\n",
+ pri->pname,
+ (int)sizeof (list.l_name),
+ list.l_name);
+ offset += sizeof (struct str_mlist);
+ }
+ }
+}
+
+#ifdef _LP64
+void
+show_strlist32(private_t *pri, long offset)
+{
+ struct str_list32 strlist;
+ struct str_mlist list;
+ int count;
+
+ if (Pread(Proc, &strlist, sizeof (strlist), offset) ==
+ sizeof (strlist)) {
+ (void) printf("%s\tnmods=%d modlist=0x%.8lX\n",
+ pri->pname,
+ strlist.sl_nmods,
+ (long)strlist.sl_modlist);
+
+ count = strlist.sl_nmods;
+ offset = (long)strlist.sl_modlist;
+ while (!interrupt && --count >= 0) {
+ if (Pread(Proc, &list, sizeof (list), offset) !=
+ sizeof (list))
+ break;
+ (void) printf("%s\t\t\"%.*s\"\n",
+ pri->pname,
+ (int)sizeof (list.l_name),
+ list.l_name);
+ offset += sizeof (struct str_mlist);
+ }
+ }
+}
+#endif /* _LP64 */
+
+void
+show_jwinsize(private_t *pri, long offset)
+{
+ struct jwinsize jwinsize;
+
+ if (Pread(Proc, &jwinsize, sizeof (jwinsize), offset) ==
+ sizeof (jwinsize)) {
+ (void) printf(
+ "%s\tbytesx=%-3u bytesy=%-3u bitsx=%-3u bitsy=%-3u\n",
+ pri->pname,
+ (unsigned)jwinsize.bytesx,
+ (unsigned)jwinsize.bytesy,
+ (unsigned)jwinsize.bitsx,
+ (unsigned)jwinsize.bitsy);
+ }
+}
+
+void
+show_winsize(private_t *pri, long offset)
+{
+ struct winsize winsize;
+
+ if (Pread(Proc, &winsize, sizeof (winsize), offset)
+ == sizeof (winsize)) {
+ (void) printf(
+ "%s\trow=%-3d col=%-3d xpixel=%-3d ypixel=%-3d\n",
+ pri->pname,
+ winsize.ws_row,
+ winsize.ws_col,
+ winsize.ws_xpixel,
+ winsize.ws_ypixel);
+ }
+}
+
+struct audio_stuff {
+ uint_t bit;
+ const char *str;
+};
+
+const struct audio_stuff audio_output_ports[] = {
+ { AUDIO_SPEAKER, "SPEAKER" },
+ { AUDIO_HEADPHONE, "HEADPHONE" },
+ { AUDIO_LINE_OUT, "LINE_OUT" },
+ { AUDIO_SPDIF_OUT, "SPDIF_OUT" },
+ { AUDIO_AUX1_OUT, "AUX1_OUT" },
+ { AUDIO_AUX2_OUT, "AUX2_OUT" },
+ { 0, NULL }
+};
+
+const struct audio_stuff audio_input_ports[] = {
+ { AUDIO_MICROPHONE, "MICROPHONE" },
+ { AUDIO_LINE_IN, "LINE_IN" },
+ { AUDIO_CD, "CD" },
+ { AUDIO_SPDIF_IN, "SPDIF_IN" },
+ { AUDIO_AUX1_IN, "AUX1_IN" },
+ { AUDIO_AUX2_IN, "AUX2_IN" },
+ { AUDIO_CODEC_LOOPB_IN, "CODEC_LOOPB_IN" },
+ { AUDIO_SUNVTS, "SUNVTS" },
+ { 0, NULL }
+};
+
+static const struct audio_stuff audio_hw_features[] = {
+ { AUDIO_HWFEATURE_DUPLEX, "DUPLEX" },
+ { AUDIO_HWFEATURE_MSCODEC, "MSCODEC" },
+ { AUDIO_HWFEATURE_IN2OUT, "IN2OUT" },
+ { AUDIO_HWFEATURE_PLAY, "PLAY" },
+ { AUDIO_HWFEATURE_RECORD, "RECORD" },
+ { 0, NULL }
+};
+
+static const struct audio_stuff audio_sw_features[] = {
+ { AUDIO_SWFEATURE_MIXER, "MIXER" },
+ { 0, NULL }
+};
+
+void
+show_audio_features(const private_t *pri,
+ const struct audio_stuff *audio_porttab, uint_t features,
+ const char *name)
+{
+ (void) printf("%s\t%s=", pri->pname, name);
+ if (features == 0) {
+ (void) printf("0\n");
+ return;
+ }
+
+ for (; audio_porttab->bit != 0; ++audio_porttab) {
+ if (features & audio_porttab->bit) {
+ (void) printf(audio_porttab->str);
+ features &= ~audio_porttab->bit;
+ if (features)
+ (void) putchar('|');
+ }
+ }
+ if (features)
+ (void) printf("0x%x", features);
+ (void) putchar('\n');
+}
+
+void
+show_audio_ports(private_t *pri, const char *mode,
+ const char *field, uint_t ports)
+{
+ const struct audio_stuff *audio_porttab;
+
+ (void) printf("%s\t%s\t%s=", pri->pname, mode, field);
+ if (ports == 0) {
+ (void) printf("0\n");
+ return;
+ }
+ if (*mode == 'p')
+ audio_porttab = audio_output_ports;
+ else
+ audio_porttab = audio_input_ports;
+ for (; audio_porttab->bit != 0; ++audio_porttab) {
+ if (ports & audio_porttab->bit) {
+ (void) printf(audio_porttab->str);
+ ports &= ~audio_porttab->bit;
+ if (ports)
+ (void) putchar('|');
+ }
+ }
+ if (ports)
+ (void) printf("0x%x", ports);
+ (void) putchar('\n');
+}
+
+void
+show_audio_prinfo(private_t *pri, const char *mode, struct audio_prinfo *au_pr)
+{
+ const char *s;
+
+ /*
+ * The following values describe the audio data encoding.
+ */
+
+ (void) printf("%s\t%s\tsample_rate=%u channels=%u precision=%u\n",
+ pri->pname, mode,
+ au_pr->sample_rate,
+ au_pr->channels,
+ au_pr->precision);
+
+ s = NULL;
+ switch (au_pr->encoding) {
+ case AUDIO_ENCODING_NONE: s = "NONE"; break;
+ case AUDIO_ENCODING_ULAW: s = "ULAW"; break;
+ case AUDIO_ENCODING_ALAW: s = "ALAW"; break;
+ case AUDIO_ENCODING_LINEAR: s = "LINEAR"; break;
+ case AUDIO_ENCODING_DVI: s = "DVI"; break;
+ case AUDIO_ENCODING_LINEAR8: s = "LINEAR8"; break;
+ }
+ if (s)
+ (void) printf("%s\t%s\tencoding=%s\n", pri->pname, mode, s);
+ else {
+ (void) printf("%s\t%s\tencoding=%u\n",
+ pri->pname, mode, au_pr->encoding);
+ }
+
+ /*
+ * The following values control audio device configuration
+ */
+
+ (void) printf(
+ "%s\t%s\tgain=%u buffer_size=%u\n",
+ pri->pname, mode,
+ au_pr->gain,
+ au_pr->buffer_size);
+ show_audio_ports(pri, mode, "port", au_pr->port);
+ show_audio_ports(pri, mode, "avail_ports", au_pr->avail_ports);
+ show_audio_ports(pri, mode, "mod_ports", au_pr->mod_ports);
+
+ /*
+ * The following values describe driver state
+ */
+
+ (void) printf("%s\t%s\tsamples=%u eof=%u pause=%u error=%u\n",
+ pri->pname, mode,
+ au_pr->samples,
+ au_pr->eof,
+ au_pr->pause,
+ au_pr->error);
+ (void) printf("%s\t%s\twaiting=%u balance=%u minordev=%u\n",
+ pri->pname, mode,
+ au_pr->waiting,
+ au_pr->balance,
+ au_pr->minordev);
+
+ /*
+ * The following values are read-only state flags
+ */
+ (void) printf("%s\t%s\topen=%u active=%u\n",
+ pri->pname, mode,
+ au_pr->open,
+ au_pr->active);
+}
+
+void
+show_audio_info(private_t *pri, long offset)
+{
+ struct audio_info au;
+
+ if (Pread(Proc, &au, sizeof (au), offset) == sizeof (au)) {
+ show_audio_prinfo(pri, "play", &au.play);
+ show_audio_prinfo(pri, "record", &au.record);
+ (void) printf("%s\tmonitor_gain=%u output_muted=%u\n",
+ pri->pname, au.monitor_gain, au.output_muted);
+ show_audio_features(pri, audio_hw_features, au.hw_features,
+ "hw_features");
+ show_audio_features(pri, audio_sw_features, au.sw_features,
+ "sw_features");
+ show_audio_features(pri, audio_sw_features,
+ au.sw_features_enabled, "sw_features_enabled");
+ }
+}
+
+void
+show_ioctl(private_t *pri, int code, long offset)
+{
+ int lp64 = (data_model == PR_MODEL_LP64);
+ int err = pri->Errno; /* don't display output parameters */
+ /* for a failed system call */
+#ifndef _LP64
+ if (lp64)
+ return;
+#endif
+ if (offset == 0)
+ return;
+
+ switch (code) {
+ case TCGETA:
+ if (err)
+ break;
+ /*FALLTHROUGH*/
+ case TCSETA:
+ case TCSETAW:
+ case TCSETAF:
+ show_termio(pri, offset);
+ break;
+ case TCGETS:
+ if (err)
+ break;
+ /*FALLTHROUGH*/
+ case TCSETS:
+ case TCSETSW:
+ case TCSETSF:
+ show_termios(pri, offset);
+ break;
+ case TCGETX:
+ if (err)
+ break;
+ /*FALLTHROUGH*/
+ case TCSETX:
+ case TCSETXW:
+ case TCSETXF:
+ show_termiox(pri, offset);
+ break;
+ case TIOCGETP:
+ if (err)
+ break;
+ /*FALLTHROUGH*/
+ case TIOCSETN:
+ case TIOCSETP:
+ show_sgttyb(pri, offset);
+ break;
+ case TIOCGLTC:
+ if (err)
+ break;
+ /*FALLTHROUGH*/
+ case TIOCSLTC:
+ show_ltchars(pri, offset);
+ break;
+ case TIOCGETC:
+ if (err)
+ break;
+ /*FALLTHROUGH*/
+ case TIOCSETC:
+ show_tchars(pri, offset);
+ break;
+ case LDGETT:
+ if (err)
+ break;
+ /*FALLTHROUGH*/
+ case LDSETT:
+ show_termcb(pri, offset);
+ break;
+ /* streams ioctl()s */
+#if 0
+ /* these are displayed as strings in the arg list */
+ /* by prt_ioa(). don't display them again here */
+ case I_PUSH:
+ case I_LOOK:
+ case I_FIND:
+ /* these are displayed as decimal in the arg list */
+ /* by prt_ioa(). don't display them again here */
+ case I_LINK:
+ case I_UNLINK:
+ case I_SENDFD:
+ /* these are displayed symbolically in the arg list */
+ /* by prt_ioa(). don't display them again here */
+ case I_SRDOPT:
+ case I_SETSIG:
+ case I_FLUSH:
+ break;
+ /* this one just ignores the argument */
+ case I_POP:
+ break;
+#endif
+ /* these return something in an int pointed to by arg */
+ case I_NREAD:
+ case I_GRDOPT:
+ case I_GETSIG:
+ case TIOCGSID:
+ case TIOCGPGRP:
+ case TIOCLGET:
+ case FIONREAD:
+ case FIORDCHK:
+ if (err)
+ break;
+ /*FALLTHROUGH*/
+ /* these pass something in an int pointed to by arg */
+ case TIOCSPGRP:
+ case TIOCFLUSH:
+ case TIOCLBIS:
+ case TIOCLBIC:
+ case TIOCLSET:
+ show_strint(pri, code, offset);
+ break;
+ /* these all point to structures */
+ case I_STR:
+#ifdef _LP64
+ if (lp64)
+ show_strioctl(pri, offset);
+ else
+ show_strioctl32(pri, offset);
+#else
+ show_strioctl(pri, offset);
+#endif
+ break;
+ case I_PEEK:
+#ifdef _LP64
+ if (lp64)
+ show_strpeek(pri, offset);
+ else
+ show_strpeek32(pri, offset);
+#else
+ show_strpeek(pri, offset);
+#endif
+ break;
+ case I_FDINSERT:
+#ifdef _LP64
+ if (lp64)
+ show_strfdinsert(pri, offset);
+ else
+ show_strfdinsert32(pri, offset);
+#else
+ show_strfdinsert(pri, offset);
+#endif
+ break;
+ case I_RECVFD:
+ if (err)
+ break;
+ show_strrecvfd(pri, offset);
+ break;
+ case I_LIST:
+ if (err)
+ break;
+#ifdef _LP64
+ if (lp64)
+ show_strlist(pri, offset);
+ else
+ show_strlist32(pri, offset);
+#else
+ show_strlist(pri, offset);
+#endif
+ break;
+ case JWINSIZE:
+ if (err)
+ break;
+ show_jwinsize(pri, offset);
+ break;
+ case TIOCGWINSZ:
+ if (err)
+ break;
+ /*FALLTHROUGH*/
+ case TIOCSWINSZ:
+ show_winsize(pri, offset);
+ break;
+ case AUDIO_GETINFO:
+ case (int)AUDIO_SETINFO:
+ show_audio_info(pri, offset);
+ break;
+
+ default:
+ if ((code & ~0xff) == ZFS_IOC) {
+ show_zfs_ioc(pri, offset);
+ break;
+ }
+
+ if (code & IOC_INOUT) {
+ const char *str = ioctldatastruct(code);
+
+ (void) printf("\t\t%s",
+ (code & IOC_INOUT) == IOC_INOUT ? "write/read" :
+ code & IOC_IN ? "write" : "read");
+ if (str != NULL) {
+ (void) printf(" (struct %s)\n", str);
+ } else {
+ (void) printf(" %d bytes\n",
+ (code >> 16) & IOCPARM_MASK);
+ }
+ }
+ }
+}
+
+void
+show_statvfs(private_t *pri)
+{
+ long offset;
+ struct statvfs statvfs;
+ char *cp;
+
+ if (pri->sys_nargs > 1 && (offset = pri->sys_args[1]) != NULL &&
+ Pread(Proc, &statvfs, sizeof (statvfs), offset)
+ == sizeof (statvfs)) {
+ (void) printf(
+ "%s\tbsize=%-10lu frsize=%-9lu blocks=%-8llu bfree=%-9llu\n",
+ pri->pname,
+ statvfs.f_bsize,
+ statvfs.f_frsize,
+ (u_longlong_t)statvfs.f_blocks,
+ (u_longlong_t)statvfs.f_bfree);
+ (void) printf(
+ "%s\tbavail=%-9llu files=%-10llu ffree=%-9llu favail=%-9llu\n",
+ pri->pname,
+ (u_longlong_t)statvfs.f_bavail,
+ (u_longlong_t)statvfs.f_files,
+ (u_longlong_t)statvfs.f_ffree,
+ (u_longlong_t)statvfs.f_favail);
+ (void) printf(
+ "%s\tfsid=0x%-9.4lX basetype=%-7.16s namemax=%ld\n",
+ pri->pname,
+ statvfs.f_fsid,
+ statvfs.f_basetype,
+ (long)statvfs.f_namemax);
+ (void) printf(
+ "%s\tflag=%s\n",
+ pri->pname,
+ svfsflags(pri, (ulong_t)statvfs.f_flag));
+ cp = statvfs.f_fstr + strlen(statvfs.f_fstr);
+ if (cp < statvfs.f_fstr + sizeof (statvfs.f_fstr) - 1 &&
+ *(cp+1) != '\0')
+ *cp = ' ';
+ (void) printf("%s\tfstr=\"%.*s\"\n",
+ pri->pname,
+ (int)sizeof (statvfs.f_fstr),
+ statvfs.f_fstr);
+ }
+}
+
+#ifdef _LP64
+void
+show_statvfs32(private_t *pri)
+{
+ long offset;
+ struct statvfs32 statvfs;
+ char *cp;
+
+ if (pri->sys_nargs > 1 && (offset = pri->sys_args[1]) != NULL &&
+ Pread(Proc, &statvfs, sizeof (statvfs), offset)
+ == sizeof (statvfs)) {
+ (void) printf(
+ "%s\tbsize=%-10u frsize=%-9u blocks=%-8u bfree=%-9u\n",
+ pri->pname,
+ statvfs.f_bsize,
+ statvfs.f_frsize,
+ statvfs.f_blocks,
+ statvfs.f_bfree);
+ (void) printf(
+ "%s\tbavail=%-9u files=%-10u ffree=%-9u favail=%-9u\n",
+ pri->pname,
+ statvfs.f_bavail,
+ statvfs.f_files,
+ statvfs.f_ffree,
+ statvfs.f_favail);
+ (void) printf(
+ "%s\tfsid=0x%-9.4X basetype=%-7.16s namemax=%d\n",
+ pri->pname,
+ statvfs.f_fsid,
+ statvfs.f_basetype,
+ (int)statvfs.f_namemax);
+ (void) printf(
+ "%s\tflag=%s\n",
+ pri->pname,
+ svfsflags(pri, (ulong_t)statvfs.f_flag));
+ cp = statvfs.f_fstr + strlen(statvfs.f_fstr);
+ if (cp < statvfs.f_fstr + sizeof (statvfs.f_fstr) - 1 &&
+ *(cp+1) != '\0')
+ *cp = ' ';
+ (void) printf("%s\tfstr=\"%.*s\"\n",
+ pri->pname,
+ (int)sizeof (statvfs.f_fstr),
+ statvfs.f_fstr);
+ }
+}
+#endif /* _LP64 */
+
+void
+show_statvfs64(private_t *pri)
+{
+ long offset;
+ struct statvfs64_32 statvfs;
+ char *cp;
+
+ if (pri->sys_nargs > 1 && (offset = pri->sys_args[1]) != NULL &&
+ Pread(Proc, &statvfs, sizeof (statvfs), offset)
+ == sizeof (statvfs)) {
+ (void) printf(
+ "%s\tbsize=%-10u frsize=%-9u blocks=%-8llu bfree=%-9llu\n",
+ pri->pname,
+ statvfs.f_bsize,
+ statvfs.f_frsize,
+ (u_longlong_t)statvfs.f_blocks,
+ (u_longlong_t)statvfs.f_bfree);
+ (void) printf(
+ "%s\tbavail=%-9llu files=%-10llu ffree=%-9llu favail=%-9llu\n",
+ pri->pname,
+ (u_longlong_t)statvfs.f_bavail,
+ (u_longlong_t)statvfs.f_files,
+ (u_longlong_t)statvfs.f_ffree,
+ (u_longlong_t)statvfs.f_favail);
+ (void) printf(
+ "%s\tfsid=0x%-9.4X basetype=%-7.16s namemax=%d\n",
+ pri->pname,
+ statvfs.f_fsid,
+ statvfs.f_basetype,
+ (int)statvfs.f_namemax);
+ (void) printf(
+ "%s\tflag=%s\n",
+ pri->pname,
+ svfsflags(pri, (ulong_t)statvfs.f_flag));
+ cp = statvfs.f_fstr + strlen(statvfs.f_fstr);
+ if (cp < statvfs.f_fstr + sizeof (statvfs.f_fstr) - 1 &&
+ *(cp+1) != '\0')
+ *cp = ' ';
+ (void) printf("%s\tfstr=\"%.*s\"\n",
+ pri->pname,
+ (int)sizeof (statvfs.f_fstr),
+ statvfs.f_fstr);
+ }
+}
+
+void
+show_statfs(private_t *pri)
+{
+ long offset;
+ struct statfs statfs;
+
+ if (pri->sys_nargs >= 2 && (offset = pri->sys_args[1]) != NULL &&
+ Pread(Proc, &statfs, sizeof (statfs), offset) == sizeof (statfs)) {
+ (void) printf(
+ "%s\tfty=%d bsz=%ld fsz=%ld blk=%ld bfr=%ld fil=%lu ffr=%lu\n",
+ pri->pname,
+ statfs.f_fstyp,
+ statfs.f_bsize,
+ statfs.f_frsize,
+ statfs.f_blocks,
+ statfs.f_bfree,
+ statfs.f_files,
+ statfs.f_ffree);
+ (void) printf("%s\t fname=%.6s fpack=%.6s\n",
+ pri->pname,
+ statfs.f_fname,
+ statfs.f_fpack);
+ }
+}
+
+#ifdef _LP64
+void
+show_statfs32(private_t *pri)
+{
+ long offset;
+ struct statfs32 statfs;
+
+ if (pri->sys_nargs >= 2 && (offset = pri->sys_args[1]) != NULL &&
+ Pread(Proc, &statfs, sizeof (statfs), offset) == sizeof (statfs)) {
+ (void) printf(
+ "%s\tfty=%d bsz=%d fsz=%d blk=%d bfr=%d fil=%u ffr=%u\n",
+ pri->pname,
+ statfs.f_fstyp,
+ statfs.f_bsize,
+ statfs.f_frsize,
+ statfs.f_blocks,
+ statfs.f_bfree,
+ statfs.f_files,
+ statfs.f_ffree);
+ (void) printf("%s\t fname=%.6s fpack=%.6s\n",
+ pri->pname,
+ statfs.f_fname,
+ statfs.f_fpack);
+ }
+}
+#endif /* _LP64 */
+
+void
+show_flock32(private_t *pri, long offset)
+{
+ struct flock32 flock;
+
+ if (Pread(Proc, &flock, sizeof (flock), offset) == sizeof (flock)) {
+ const char *str = NULL;
+
+ (void) printf("%s\ttyp=", pri->pname);
+
+ switch (flock.l_type) {
+ case F_RDLCK:
+ str = "F_RDLCK";
+ break;
+ case F_WRLCK:
+ str = "F_WRLCK";
+ break;
+ case F_UNLCK:
+ str = "F_UNLCK";
+ break;
+ }
+ if (str != NULL)
+ (void) printf("%s", str);
+ else
+ (void) printf("%-7d", flock.l_type);
+
+ str = whencearg(flock.l_whence);
+ if (str != NULL)
+ (void) printf(" whence=%s", str);
+ else
+ (void) printf(" whence=%-8u", flock.l_whence);
+
+ (void) printf(
+ " start=%-5d len=%-5d sys=%-2u pid=%d\n",
+ flock.l_start,
+ flock.l_len,
+ flock.l_sysid,
+ flock.l_pid);
+ }
+}
+
+void
+show_flock64(private_t *pri, long offset)
+{
+ struct flock64 flock;
+
+ if (Pread(Proc, &flock, sizeof (flock), offset) == sizeof (flock)) {
+ const char *str = NULL;
+
+ (void) printf("%s\ttyp=", pri->pname);
+
+ switch (flock.l_type) {
+ case F_RDLCK:
+ str = "F_RDLCK";
+ break;
+ case F_WRLCK:
+ str = "F_WRLCK";
+ break;
+ case F_UNLCK:
+ str = "F_UNLCK";
+ break;
+ }
+ if (str != NULL)
+ (void) printf("%s", str);
+ else
+ (void) printf("%-7d", flock.l_type);
+
+ str = whencearg(flock.l_whence);
+ if (str != NULL)
+ (void) printf(" whence=%s", str);
+ else
+ (void) printf(" whence=%-8u", flock.l_whence);
+
+ (void) printf(
+ " start=%-5lld len=%-5lld sys=%-2u pid=%d\n",
+ (long long)flock.l_start,
+ (long long)flock.l_len,
+ flock.l_sysid,
+ (int)flock.l_pid);
+ }
+}
+
+void
+show_share(private_t *pri, long offset)
+{
+ struct fshare fshare;
+
+ if (Pread(Proc, &fshare, sizeof (fshare), offset) == sizeof (fshare)) {
+ const char *str = NULL;
+ int manddny = 0;
+
+ (void) printf("%s\taccess=", pri->pname);
+
+ switch (fshare.f_access) {
+ case F_RDACC:
+ str = "F_RDACC";
+ break;
+ case F_WRACC:
+ str = "F_WRACC";
+ break;
+ case F_RWACC:
+ str = "F_RWACC";
+ break;
+ }
+ if (str != NULL)
+ (void) printf("%s", str);
+ else
+ (void) printf("%-7d", fshare.f_access);
+
+ str = NULL;
+ if (fshare.f_deny & F_MANDDNY) {
+ fshare.f_deny &= ~F_MANDDNY;
+ manddny = 1;
+ }
+ switch (fshare.f_deny) {
+ case F_NODNY:
+ str = "F_NODNY";
+ break;
+ case F_RDDNY:
+ str = "F_RDDNY";
+ break;
+ case F_WRDNY:
+ str = "F_WRDNY";
+ break;
+ case F_RWDNY:
+ str = "F_RWDNY";
+ break;
+ case F_COMPAT:
+ str = "F_COMPAT";
+ break;
+ }
+ if (str != NULL) {
+ if (manddny)
+ (void) printf(" deny=F_MANDDNY|%s", str);
+ else
+ (void) printf(" deny=%s", str);
+ } else {
+ (void) printf(" deny=0x%x", manddny?
+ fshare.f_deny | F_MANDDNY : fshare.f_deny);
+ }
+
+ (void) printf(" id=%x\n", fshare.f_id);
+ }
+}
+
+void
+show_ffg(private_t *pri)
+{
+ (void) putchar('\t');
+ (void) putchar('\t');
+ prt_ffg(pri, 0, pri->Rval1);
+ (void) puts(pri->sys_string);
+}
+
+/* print values in fcntl() pointed-to structure */
+void
+show_fcntl(private_t *pri)
+{
+ long offset;
+
+ if (pri->sys_nargs >= 2 && pri->sys_args[1] == F_GETFL) {
+ show_ffg(pri);
+ return;
+ }
+
+ if (pri->sys_nargs < 3 || (offset = pri->sys_args[2]) == NULL)
+ return;
+
+ switch (pri->sys_args[1]) {
+#ifdef _LP64
+ case F_GETLK:
+ case F_SETLK:
+ case F_SETLKW:
+ case F_FREESP:
+ case F_ALLOCSP:
+ case F_SETLK_NBMAND:
+ if (data_model == PR_MODEL_LP64)
+ show_flock64(pri, offset);
+ else
+ show_flock32(pri, offset);
+ break;
+ case 33: /* F_GETLK64 */
+ case 34: /* F_SETLK64 */
+ case 35: /* F_SETLKW64 */
+ case 27: /* F_FREESP64 */
+ case 28: /* F_ALLOCSP64 */
+ case 44: /* F_SETLK64_NBMAND */
+ show_flock64(pri, offset);
+ break;
+#else /* _LP64 */
+ case F_GETLK:
+ case F_SETLK:
+ case F_SETLKW:
+ case F_FREESP:
+ case F_ALLOCSP:
+ case F_SETLK_NBMAND:
+ show_flock32(pri, offset);
+ break;
+ case F_GETLK64:
+ case F_SETLK64:
+ case F_SETLKW64:
+ case F_FREESP64:
+ case F_ALLOCSP64:
+ case F_SETLK64_NBMAND:
+ show_flock64(pri, offset);
+ break;
+#endif /* _LP64 */
+ case F_SHARE:
+ case F_UNSHARE:
+ show_share(pri, offset);
+ break;
+ }
+}
+
+void
+show_strbuf(private_t *pri, long offset, const char *name, int dump)
+{
+ struct strbuf strbuf;
+
+ if (Pread(Proc, &strbuf, sizeof (strbuf), offset) == sizeof (strbuf))
+ print_strbuf(pri, &strbuf, name, dump);
+}
+
+#ifdef _LP64
+void
+show_strbuf32(private_t *pri, long offset, const char *name, int dump)
+{
+ struct strbuf32 strbuf;
+
+ if (Pread(Proc, &strbuf, sizeof (strbuf), offset) == sizeof (strbuf))
+ print_strbuf32(pri, &strbuf, name, dump);
+}
+#endif /* _LP64 */
+
+void
+show_gp_msg(private_t *pri, int what)
+{
+ long offset;
+ int dump = FALSE;
+ int fdp1 = pri->sys_args[0] + 1;
+
+ switch (what) {
+ case SYS_getmsg:
+ case SYS_getpmsg:
+ if (pri->Errno == 0 && prismember(&readfd, fdp1))
+ dump = TRUE;
+ break;
+ case SYS_putmsg:
+ case SYS_putpmsg:
+ if (prismember(&writefd, fdp1))
+ dump = TRUE;
+ break;
+ }
+
+ /* enter region of lengthy output */
+ if (dump)
+ Eserialize();
+
+#ifdef _LP64
+ if (pri->sys_nargs >= 2 && (offset = pri->sys_args[1]) != NULL) {
+ if (data_model == PR_MODEL_LP64)
+ show_strbuf(pri, offset, "ctl", dump);
+ else
+ show_strbuf32(pri, offset, "ctl", dump);
+ }
+ if (pri->sys_nargs >= 3 && (offset = pri->sys_args[2]) != NULL) {
+ if (data_model == PR_MODEL_LP64)
+ show_strbuf(pri, offset, "dat", dump);
+ else
+ show_strbuf32(pri, offset, "dat", dump);
+ }
+#else /* _LP64 */
+ if (pri->sys_nargs >= 2 && (offset = pri->sys_args[1]) != NULL)
+ show_strbuf(pri, offset, "ctl", dump);
+ if (pri->sys_nargs >= 3 && (offset = pri->sys_args[2]) != NULL)
+ show_strbuf(pri, offset, "dat", dump);
+#endif /* _LP64 */
+
+ /* exit region of lengthy output */
+ if (dump)
+ Xserialize();
+}
+
+void
+show_int(private_t *pri, long offset, const char *name)
+{
+ int value;
+
+ if (offset != 0 &&
+ Pread(Proc, &value, sizeof (value), offset) == sizeof (value))
+ (void) printf("%s\t%s:\t%d\n",
+ pri->pname,
+ name,
+ value);
+}
+
+void
+show_hhex_int(private_t *pri, long offset, const char *name)
+{
+ int value;
+
+ if (Pread(Proc, &value, sizeof (value), offset) == sizeof (value))
+ (void) printf("%s\t%s:\t0x%.4X\n",
+ pri->pname,
+ name,
+ value);
+}
+
+#define ALL_POLL_FLAGS (POLLIN|POLLPRI|POLLOUT| \
+ POLLRDNORM|POLLRDBAND|POLLWRBAND|POLLERR|POLLHUP|POLLNVAL)
+
+const char *
+pollevent(private_t *pri, int arg)
+{
+ char *str = pri->code_buf;
+
+ if (arg == 0)
+ return ("0");
+ if (arg & ~ALL_POLL_FLAGS) {
+ (void) sprintf(str, "0x%-5X", arg);
+ return ((const char *)str);
+ }
+
+ *str = '\0';
+ if (arg & POLLIN)
+ (void) strcat(str, "|POLLIN");
+ if (arg & POLLPRI)
+ (void) strcat(str, "|POLLPRI");
+ if (arg & POLLOUT)
+ (void) strcat(str, "|POLLOUT");
+ if (arg & POLLRDNORM)
+ (void) strcat(str, "|POLLRDNORM");
+ if (arg & POLLRDBAND)
+ (void) strcat(str, "|POLLRDBAND");
+ if (arg & POLLWRBAND)
+ (void) strcat(str, "|POLLWRBAND");
+ if (arg & POLLERR)
+ (void) strcat(str, "|POLLERR");
+ if (arg & POLLHUP)
+ (void) strcat(str, "|POLLHUP");
+ if (arg & POLLNVAL)
+ (void) strcat(str, "|POLLNVAL");
+
+ return ((const char *)(str+1));
+}
+
+static void
+show_one_pollfd(private_t *pri, struct pollfd *ppollfd)
+{
+ /*
+ * can't print both events and revents in same printf.
+ * pollevent() returns a pointer to a TSD location.
+ */
+ (void) printf("%s\tfd=%-2d ev=%s",
+ pri->pname, ppollfd->fd, pollevent(pri, ppollfd->events));
+ (void) printf(" rev=%s\n", pollevent(pri, ppollfd->revents));
+}
+
+static void
+show_all_pollfds(private_t *pri, long offset, int nfds)
+{
+ struct pollfd pollfd[2];
+ int skip = -1;
+
+ for (; nfds && !interrupt; nfds--, offset += sizeof (struct pollfd)) {
+ if (Pread(Proc, &pollfd[0], sizeof (struct pollfd), offset) !=
+ sizeof (struct pollfd))
+ continue;
+
+ if (skip >= 0 && pollfd[0].fd == pollfd[1].fd &&
+ pollfd[0].events == pollfd[1].events &&
+ pollfd[0].revents == pollfd[1].revents) {
+ skip++;
+ continue;
+ }
+
+ if (skip > 0)
+ (void) printf("%s\t...last pollfd structure"
+ " repeated %d time%s...\n",
+ pri->pname, skip, (skip == 1 ? "" : "s"));
+
+ skip = 0;
+ show_one_pollfd(pri, &pollfd[0]);
+ pollfd[1] = pollfd[0];
+ }
+
+ if (skip > 0)
+ (void) printf(
+ "%s\t...last pollfd structure repeated %d time%s...\n",
+ pri->pname, skip, (skip == 1 ? "" : "s"));
+}
+
+void
+show_pollsys(private_t *pri)
+{
+ long offset;
+ int nfds;
+ int serial = 0;
+
+ if (pri->sys_nargs < 2)
+ return;
+
+ offset = pri->sys_args[0];
+ nfds = pri->sys_args[1];
+
+ /* enter region of lengthy output */
+ if (offset != NULL && nfds > 32) {
+ Eserialize();
+ serial = 1;
+ }
+
+ if (offset != NULL && nfds > 0)
+ show_all_pollfds(pri, offset, nfds);
+
+ if (pri->sys_nargs > 2)
+ show_timestruc(pri, (long)pri->sys_args[2], "timeout");
+
+ if (pri->sys_nargs > 3)
+ show_sigset(pri, (long)pri->sys_args[3], "sigmask");
+
+ /* exit region of lengthy output */
+ if (serial)
+ Xserialize();
+}
+
+static void
+show_perm64(private_t *pri, struct ipc_perm64 *ip)
+{
+ (void) printf("%s\tu=%-5u g=%-5u cu=%-5u cg=%-5u z=%-5d "
+ "m=0%.6o key=%d projid=%-5d\n",
+ pri->pname,
+ ip->ipcx_uid,
+ ip->ipcx_gid,
+ ip->ipcx_cuid,
+ ip->ipcx_cgid,
+ (int)ip->ipcx_zoneid,
+ (unsigned int)ip->ipcx_mode,
+ ip->ipcx_key,
+ (int)ip->ipcx_projid);
+}
+
+void
+show_perm(private_t *pri, struct ipc_perm *ip)
+{
+ (void) printf(
+ "%s\tu=%-5u g=%-5u cu=%-5u cg=%-5u m=0%.6o seq=%u key=%d\n",
+ pri->pname,
+ ip->uid,
+ ip->gid,
+ ip->cuid,
+ ip->cgid,
+ (int)ip->mode,
+ ip->seq,
+ ip->key);
+}
+
+#ifdef _LP64
+void
+show_perm32(private_t *pri, struct ipc_perm32 *ip)
+{
+ (void) printf(
+ "%s\tu=%-5u g=%-5u cu=%-5u cg=%-5u m=0%.6o seq=%u key=%d\n",
+ pri->pname,
+ ip->uid,
+ ip->gid,
+ ip->cuid,
+ ip->cgid,
+ ip->mode,
+ ip->seq,
+ ip->key);
+}
+#endif /* _LP64 */
+
+static void
+show_msgctl64(private_t *pri, long offset)
+{
+ struct msqid_ds64 msgq;
+
+ if (offset != NULL &&
+ Pread(Proc, &msgq, sizeof (msgq), offset) == sizeof (msgq)) {
+ show_perm64(pri, &msgq.msgx_perm);
+
+ (void) printf("%s\tbytes=%-5llu msgs=%-5llu maxby=%-5llu "
+ "lspid=%-5d lrpid=%-5d\n", pri->pname,
+ (unsigned long long)msgq.msgx_cbytes,
+ (unsigned long long)msgq.msgx_qnum,
+ (unsigned long long)msgq.msgx_qbytes,
+ (int)msgq.msgx_lspid,
+ (int)msgq.msgx_lrpid);
+
+ prtime(pri, " st = ", (time_t)msgq.msgx_stime);
+ prtime(pri, " rt = ", (time_t)msgq.msgx_rtime);
+ prtime(pri, " ct = ", (time_t)msgq.msgx_ctime);
+ }
+}
+
+void
+show_msgctl(private_t *pri, long offset)
+{
+ struct msqid_ds msgq;
+
+ if (offset != NULL &&
+ Pread(Proc, &msgq, sizeof (msgq), offset) == sizeof (msgq)) {
+ show_perm(pri, &msgq.msg_perm);
+
+ (void) printf(
+ "%s\tbytes=%-5lu msgs=%-5lu maxby=%-5lu lspid=%-5u lrpid=%-5u\n",
+ pri->pname,
+ msgq.msg_cbytes,
+ msgq.msg_qnum,
+ msgq.msg_qbytes,
+ (int)msgq.msg_lspid,
+ (int)msgq.msg_lrpid);
+
+ prtime(pri, " st = ", msgq.msg_stime);
+ prtime(pri, " rt = ", msgq.msg_rtime);
+ prtime(pri, " ct = ", msgq.msg_ctime);
+ }
+}
+
+#ifdef _LP64
+void
+show_msgctl32(private_t *pri, long offset)
+{
+ struct msqid_ds32 msgq;
+
+ if (offset != NULL &&
+ Pread(Proc, &msgq, sizeof (msgq), offset) == sizeof (msgq)) {
+ show_perm32(pri, &msgq.msg_perm);
+
+ (void) printf(
+ "%s\tbytes=%-5u msgs=%-5u maxby=%-5u lspid=%-5u lrpid=%-5u\n",
+ pri->pname,
+ msgq.msg_cbytes,
+ msgq.msg_qnum,
+ msgq.msg_qbytes,
+ msgq.msg_lspid,
+ msgq.msg_lrpid);
+
+ prtime(pri, " st = ", msgq.msg_stime);
+ prtime(pri, " rt = ", msgq.msg_rtime);
+ prtime(pri, " ct = ", msgq.msg_ctime);
+ }
+}
+#endif /* _LP64 */
+
+void
+show_msgbuf(private_t *pri, long offset, long msgsz)
+{
+ struct msgbuf msgb;
+
+ if (offset != NULL &&
+ Pread(Proc, &msgb, sizeof (msgb.mtype), offset) ==
+ sizeof (msgb.mtype)) {
+ /* enter region of lengthy output */
+ if (msgsz > MYBUFSIZ / 4)
+ Eserialize();
+
+ (void) printf("%s\tmtype=%lu mtext[]=\n",
+ pri->pname,
+ msgb.mtype);
+ showbuffer(pri,
+ (long)(offset + sizeof (msgb.mtype)), msgsz);
+
+ /* exit region of lengthy output */
+ if (msgsz > MYBUFSIZ / 4)
+ Xserialize();
+ }
+}
+
+#ifdef _LP64
+void
+show_msgbuf32(private_t *pri, long offset, long msgsz)
+{
+ struct ipcmsgbuf32 msgb;
+
+ if (offset != NULL &&
+ Pread(Proc, &msgb, sizeof (msgb.mtype), offset) ==
+ sizeof (msgb.mtype)) {
+ /* enter region of lengthy output */
+ if (msgsz > MYBUFSIZ / 4)
+ Eserialize();
+
+ (void) printf("%s\tmtype=%u mtext[]=\n",
+ pri->pname,
+ msgb.mtype);
+ showbuffer(pri,
+ (long)(offset + sizeof (msgb.mtype)), msgsz);
+
+ /* exit region of lengthy output */
+ if (msgsz > MYBUFSIZ / 4)
+ Xserialize();
+ }
+}
+#endif /* _LP64 */
+
+#ifdef _LP64
+void
+show_msgsys(private_t *pri, long msgsz)
+{
+ switch (pri->sys_args[0]) {
+ case 0: /* msgget() */
+ break;
+ case 1: /* msgctl() */
+ if (pri->sys_nargs > 3) {
+ switch (pri->sys_args[2]) {
+ case IPC_STAT:
+ if (pri->Errno)
+ break;
+ /*FALLTHROUGH*/
+ case IPC_SET:
+ if (data_model == PR_MODEL_LP64)
+ show_msgctl(pri,
+ (long)pri->sys_args[3]);
+ else
+ show_msgctl32(pri,
+ (long)pri->sys_args[3]);
+ break;
+ case IPC_STAT64:
+ if (pri->Errno)
+ break;
+ /*FALLTHROUGH*/
+ case IPC_SET64:
+ show_msgctl64(pri, (long)pri->sys_args[3]);
+ break;
+ }
+ }
+ break;
+ case 2: /* msgrcv() */
+ if (!pri->Errno && pri->sys_nargs > 2) {
+ if (data_model == PR_MODEL_LP64)
+ show_msgbuf(pri, pri->sys_args[2], msgsz);
+ else
+ show_msgbuf32(pri, pri->sys_args[2], msgsz);
+ }
+ break;
+ case 3: /* msgsnd() */
+ if (pri->sys_nargs > 3) {
+ if (data_model == PR_MODEL_LP64)
+ show_msgbuf(pri, pri->sys_args[2],
+ pri->sys_args[3]);
+ else
+ show_msgbuf32(pri, pri->sys_args[2],
+ pri->sys_args[3]);
+ }
+ break;
+ case 4: /* msgids() */
+ case 5: /* msgsnap() */
+ default: /* unexpected subcode */
+ break;
+ }
+}
+#else /* _LP64 */
+void
+show_msgsys(private_t *pri, long msgsz)
+{
+ switch (pri->sys_args[0]) {
+ case 0: /* msgget() */
+ break;
+ case 1: /* msgctl() */
+ if (pri->sys_nargs > 3) {
+ switch (pri->sys_args[2]) {
+ case IPC_STAT:
+ if (pri->Errno)
+ break;
+ /*FALLTHROUGH*/
+ case IPC_SET:
+ show_msgctl(pri, (long)pri->sys_args[3]);
+ break;
+ case IPC_STAT64:
+ if (pri->Errno)
+ break;
+ /*FALLTHROUGH*/
+ case IPC_SET64:
+ show_msgctl64(pri, (long)pri->sys_args[3]);
+ break;
+ }
+ }
+ break;
+ case 2: /* msgrcv() */
+ if (!pri->Errno && pri->sys_nargs > 2)
+ show_msgbuf(pri, pri->sys_args[2], msgsz);
+ break;
+ case 3: /* msgsnd() */
+ if (pri->sys_nargs > 3)
+ show_msgbuf(pri, pri->sys_args[2],
+ pri->sys_args[3]);
+ break;
+ case 4: /* msgids() */
+ case 5: /* msgsnap() */
+ default: /* unexpected subcode */
+ break;
+ }
+}
+#endif /* _LP64 */
+
+static void
+show_semctl64(private_t *pri, long offset)
+{
+ struct semid_ds64 semds;
+
+ if (offset != NULL &&
+ Pread(Proc, &semds, sizeof (semds), offset) == sizeof (semds)) {
+ show_perm64(pri, &semds.semx_perm);
+
+ (void) printf("%s\tnsems=%u\n", pri->pname, semds.semx_nsems);
+
+ prtime(pri, " ot = ", (time_t)semds.semx_otime);
+ prtime(pri, " ct = ", (time_t)semds.semx_ctime);
+ }
+}
+
+void
+show_semctl(private_t *pri, long offset)
+{
+ struct semid_ds semds;
+
+ if (offset != NULL &&
+ Pread(Proc, &semds, sizeof (semds), offset) == sizeof (semds)) {
+ show_perm(pri, &semds.sem_perm);
+
+ (void) printf("%s\tnsems=%u\n",
+ pri->pname,
+ semds.sem_nsems);
+
+ prtime(pri, " ot = ", semds.sem_otime);
+ prtime(pri, " ct = ", semds.sem_ctime);
+ }
+}
+
+#ifdef _LP64
+void
+show_semctl32(private_t *pri, long offset)
+{
+ struct semid_ds32 semds;
+
+ if (offset != NULL &&
+ Pread(Proc, &semds, sizeof (semds), offset) == sizeof (semds)) {
+ show_perm32(pri, &semds.sem_perm);
+
+ (void) printf("%s\tnsems=%u\n",
+ pri->pname,
+ semds.sem_nsems);
+
+ prtime(pri, " ot = ", semds.sem_otime);
+ prtime(pri, " ct = ", semds.sem_ctime);
+ }
+}
+#endif /* _LP64 */
+
+void
+show_semop(private_t *pri, long offset, long nsops, long timeout)
+{
+ struct sembuf sembuf;
+ const char *str;
+
+ if (offset == 0)
+ return;
+
+ if (nsops > 40) /* let's not be ridiculous */
+ nsops = 40;
+
+ for (; nsops > 0 && !interrupt; --nsops, offset += sizeof (sembuf)) {
+ if (Pread(Proc, &sembuf, sizeof (sembuf), offset) !=
+ sizeof (sembuf))
+ break;
+
+ (void) printf("%s\tsemnum=%-5u semop=%-5d semflg=",
+ pri->pname,
+ sembuf.sem_num,
+ sembuf.sem_op);
+
+ if (sembuf.sem_flg == 0)
+ (void) printf("0\n");
+ else if ((str = semflags(pri, sembuf.sem_flg)) != NULL)
+ (void) printf("%s\n", str);
+ else
+ (void) printf("0%.6o\n", sembuf.sem_flg);
+ }
+ if (timeout)
+ show_timestruc(pri, timeout, "timeout");
+}
+
+void
+show_semsys(private_t *pri)
+{
+ switch (pri->sys_args[0]) {
+ case 0: /* semctl() */
+ if (pri->sys_nargs > 4) {
+ switch (pri->sys_args[3]) {
+ case IPC_STAT:
+ if (pri->Errno)
+ break;
+ /*FALLTHROUGH*/
+ case IPC_SET:
+#ifdef _LP64
+ if (data_model == PR_MODEL_LP64)
+ show_semctl(pri,
+ (long)pri->sys_args[4]);
+ else
+ show_semctl32(pri,
+ (long)pri->sys_args[4]);
+#else
+ show_semctl(pri, (long)pri->sys_args[4]);
+#endif
+ break;
+ case IPC_STAT64:
+ if (pri->Errno)
+ break;
+ /*FALLTHROUGH*/
+ case IPC_SET64:
+ show_semctl64(pri, (long)pri->sys_args[4]);
+ break;
+ }
+ }
+ break;
+ case 1: /* semget() */
+ break;
+ case 2: /* semop() */
+ if (pri->sys_nargs > 3)
+ show_semop(pri, (long)pri->sys_args[2],
+ pri->sys_args[3], 0);
+ break;
+ case 3: /* semids() */
+ break;
+ case 4: /* semtimedop() */
+ if (pri->sys_nargs > 4)
+ show_semop(pri, (long)pri->sys_args[2],
+ pri->sys_args[3], pri->sys_args[4]);
+ break;
+ default: /* unexpected subcode */
+ break;
+ }
+}
+
+static void
+show_shmctl64(private_t *pri, long offset)
+{
+ struct shmid_ds64 shmds;
+
+ if (offset != NULL &&
+ Pread(Proc, &shmds, sizeof (shmds), offset) == sizeof (shmds)) {
+ show_perm64(pri, &shmds.shmx_perm);
+
+ (void) printf(
+ "%s\tsize=%-6llu lpid=%-5d cpid=%-5d na=%-5llu cna=%llu\n",
+ pri->pname,
+ (unsigned long long)shmds.shmx_segsz,
+ (int)shmds.shmx_lpid,
+ (int)shmds.shmx_cpid,
+ (unsigned long long)shmds.shmx_nattch,
+ (unsigned long long)shmds.shmx_cnattch);
+
+ prtime(pri, " at = ", (time_t)shmds.shmx_atime);
+ prtime(pri, " dt = ", (time_t)shmds.shmx_dtime);
+ prtime(pri, " ct = ", (time_t)shmds.shmx_ctime);
+ }
+}
+
+void
+show_shmctl(private_t *pri, long offset)
+{
+ struct shmid_ds shmds;
+
+ if (offset != NULL &&
+ Pread(Proc, &shmds, sizeof (shmds), offset) == sizeof (shmds)) {
+ show_perm(pri, &shmds.shm_perm);
+
+ (void) printf(
+ "%s\tsize=%-6lu lpid=%-5u cpid=%-5u na=%-5lu cna=%lu\n",
+ pri->pname,
+ (ulong_t)shmds.shm_segsz,
+ (int)shmds.shm_lpid,
+ (int)shmds.shm_cpid,
+ shmds.shm_nattch,
+ shmds.shm_cnattch);
+
+ prtime(pri, " at = ", shmds.shm_atime);
+ prtime(pri, " dt = ", shmds.shm_dtime);
+ prtime(pri, " ct = ", shmds.shm_ctime);
+ }
+}
+
+#ifdef _LP64
+void
+show_shmctl32(private_t *pri, long offset)
+{
+ struct shmid_ds32 shmds;
+
+ if (offset != NULL &&
+ Pread(Proc, &shmds, sizeof (shmds), offset) == sizeof (shmds)) {
+ show_perm32(pri, &shmds.shm_perm);
+
+ (void) printf(
+ "%s\tsize=%-6u lpid=%-5u cpid=%-5u na=%-5u cna=%u\n",
+ pri->pname,
+ shmds.shm_segsz,
+ shmds.shm_lpid,
+ shmds.shm_cpid,
+ shmds.shm_nattch,
+ shmds.shm_cnattch);
+
+ prtime(pri, " at = ", shmds.shm_atime);
+ prtime(pri, " dt = ", shmds.shm_dtime);
+ prtime(pri, " ct = ", shmds.shm_ctime);
+ }
+}
+#endif /* _LP64 */
+
+void
+show_shmsys(private_t *pri)
+{
+ switch (pri->sys_args[0]) {
+ case 0: /* shmat() */
+ break;
+ case 1: /* shmctl() */
+ if (pri->sys_nargs > 3) {
+ switch (pri->sys_args[2]) {
+ case IPC_STAT:
+ if (pri->Errno)
+ break;
+ /*FALLTHROUGH*/
+ case IPC_SET:
+#ifdef _LP64
+ if (data_model == PR_MODEL_LP64)
+ show_shmctl(pri,
+ (long)pri->sys_args[3]);
+ else
+ show_shmctl32(pri,
+ (long)pri->sys_args[3]);
+#else
+ show_shmctl(pri, (long)pri->sys_args[3]);
+#endif
+ break;
+ case IPC_STAT64:
+ if (pri->Errno)
+ break;
+ /*FALLTHROUGH*/
+ case IPC_SET64:
+ show_shmctl64(pri, (long)pri->sys_args[3]);
+ break;
+ }
+ }
+ break;
+ case 2: /* shmdt() */
+ case 3: /* shmget() */
+ case 4: /* shmids() */
+ default: /* unexpected subcode */
+ break;
+ }
+}
+
+void
+show_groups(private_t *pri, long offset, long count)
+{
+ int groups[100];
+
+ if (count > 100)
+ count = 100;
+
+ if (count > 0 && offset != NULL &&
+ Pread(Proc, &groups[0], count*sizeof (int), offset) ==
+ count*sizeof (int)) {
+ int n;
+
+ (void) printf("%s\t", pri->pname);
+ for (n = 0; !interrupt && n < count; n++) {
+ if (n != 0 && n%10 == 0)
+ (void) printf("\n%s\t", pri->pname);
+ (void) printf(" %5d", groups[n]);
+ }
+ (void) fputc('\n', stdout);
+ }
+}
+
+/*
+ * This assumes that a sigset_t is simply an array of ints.
+ */
+char *
+sigset_string(private_t *pri, sigset_t *sp)
+{
+ char *s = pri->code_buf;
+ int n = sizeof (*sp) / sizeof (int32_t);
+ int32_t *lp = (int32_t *)sp;
+
+ while (--n >= 0) {
+ int32_t val = *lp++;
+
+ if (val == 0)
+ s += sprintf(s, " 0");
+ else
+ s += sprintf(s, " 0x%.8X", val);
+ }
+
+ return (pri->code_buf);
+}
+
+void
+show_sigset(private_t *pri, long offset, const char *name)
+{
+ sigset_t sigset;
+
+ if (offset != NULL &&
+ Pread(Proc, &sigset, sizeof (sigset), offset) == sizeof (sigset)) {
+ (void) printf("%s\t%s =%s\n",
+ pri->pname, name, sigset_string(pri, &sigset));
+ }
+}
+
+#ifdef _LP64
+void
+show_sigaltstack32(private_t *pri, long offset, const char *name)
+{
+ struct sigaltstack32 altstack;
+
+ if (offset != NULL &&
+ Pread(Proc, &altstack, sizeof (altstack), offset) ==
+ sizeof (altstack)) {
+ (void) printf("%s\t%s: sp=0x%.8X size=%u flags=0x%.4X\n",
+ pri->pname,
+ name,
+ altstack.ss_sp,
+ altstack.ss_size,
+ altstack.ss_flags);
+ }
+}
+#endif /* _LP64 */
+
+void
+show_sigaltstack(private_t *pri, long offset, const char *name)
+{
+ struct sigaltstack altstack;
+
+#ifdef _LP64
+ if (data_model != PR_MODEL_LP64) {
+ show_sigaltstack32(pri, offset, name);
+ return;
+ }
+#endif
+ if (offset != NULL &&
+ Pread(Proc, &altstack, sizeof (altstack), offset) ==
+ sizeof (altstack)) {
+ (void) printf("%s\t%s: sp=0x%.8lX size=%lu flags=0x%.4X\n",
+ pri->pname,
+ name,
+ (ulong_t)altstack.ss_sp,
+ (ulong_t)altstack.ss_size,
+ altstack.ss_flags);
+ }
+}
+
+#ifdef _LP64
+void
+show_sigaction32(private_t *pri, long offset, const char *name, long odisp)
+{
+ struct sigaction32 sigaction;
+
+ if (offset != NULL &&
+ Pread(Proc, &sigaction, sizeof (sigaction), offset) ==
+ sizeof (sigaction)) {
+ /* This is stupid, we shouldn't have to do this */
+ if (odisp != NULL)
+ sigaction.sa_handler = (caddr32_t)odisp;
+ (void) printf(
+ "%s %s: hand = 0x%.8X mask =%s flags = 0x%.4X\n",
+ pri->pname,
+ name,
+ sigaction.sa_handler,
+ sigset_string(pri, (sigset_t *)&sigaction.sa_mask),
+ sigaction.sa_flags);
+ }
+}
+#endif /* _LP64 */
+
+void
+show_sigaction(private_t *pri, long offset, const char *name, long odisp)
+{
+ struct sigaction sigaction;
+
+#ifdef _LP64
+ if (data_model != PR_MODEL_LP64) {
+ show_sigaction32(pri, offset, name, odisp);
+ return;
+ }
+#endif
+ if (offset != NULL &&
+ Pread(Proc, &sigaction, sizeof (sigaction), offset) ==
+ sizeof (sigaction)) {
+ /* This is stupid, we shouldn't have to do this */
+ if (odisp != NULL)
+ sigaction.sa_handler = (void (*)())odisp;
+ (void) printf(
+ "%s %s: hand = 0x%.8lX mask =%s flags = 0x%.4X\n",
+ pri->pname,
+ name,
+ (long)sigaction.sa_handler,
+ sigset_string(pri, &sigaction.sa_mask),
+ sigaction.sa_flags);
+ }
+}
+
+#ifdef _LP64
+void
+print_siginfo32(private_t *pri, const siginfo32_t *sip)
+{
+ const char *code = NULL;
+
+ (void) printf("%s siginfo: %s", pri->pname,
+ signame(pri, sip->si_signo));
+
+ if (sip->si_signo != 0 && SI_FROMUSER(sip) && sip->si_pid != 0) {
+ (void) printf(" pid=%d uid=%d", sip->si_pid, sip->si_uid);
+ if (sip->si_code != 0)
+ (void) printf(" code=%d", sip->si_code);
+ (void) fputc('\n', stdout);
+ return;
+ }
+
+ switch (sip->si_signo) {
+ default:
+ (void) fputc('\n', stdout);
+ return;
+ case SIGILL:
+ case SIGTRAP:
+ case SIGFPE:
+ case SIGSEGV:
+ case SIGBUS:
+ case SIGEMT:
+ case SIGCLD:
+ case SIGPOLL:
+ case SIGXFSZ:
+ break;
+ }
+
+ switch (sip->si_signo) {
+ case SIGILL:
+ switch (sip->si_code) {
+ case ILL_ILLOPC: code = "ILL_ILLOPC"; break;
+ case ILL_ILLOPN: code = "ILL_ILLOPN"; break;
+ case ILL_ILLADR: code = "ILL_ILLADR"; break;
+ case ILL_ILLTRP: code = "ILL_ILLTRP"; break;
+ case ILL_PRVOPC: code = "ILL_PRVOPC"; break;
+ case ILL_PRVREG: code = "ILL_PRVREG"; break;
+ case ILL_COPROC: code = "ILL_COPROC"; break;
+ case ILL_BADSTK: code = "ILL_BADSTK"; break;
+ }
+ break;
+ case SIGTRAP:
+ switch (sip->si_code) {
+ case TRAP_BRKPT: code = "TRAP_BRKPT"; break;
+ case TRAP_TRACE: code = "TRAP_TRACE"; break;
+ case TRAP_RWATCH: code = "TRAP_RWATCH"; break;
+ case TRAP_WWATCH: code = "TRAP_WWATCH"; break;
+ case TRAP_XWATCH: code = "TRAP_XWATCH"; break;
+ case TRAP_DTRACE: code = "TRAP_DTRACE"; break;
+ }
+ break;
+ case SIGFPE:
+ switch (sip->si_code) {
+ case FPE_INTDIV: code = "FPE_INTDIV"; break;
+ case FPE_INTOVF: code = "FPE_INTOVF"; break;
+ case FPE_FLTDIV: code = "FPE_FLTDIV"; break;
+ case FPE_FLTOVF: code = "FPE_FLTOVF"; break;
+ case FPE_FLTUND: code = "FPE_FLTUND"; break;
+ case FPE_FLTRES: code = "FPE_FLTRES"; break;
+ case FPE_FLTINV: code = "FPE_FLTINV"; break;
+ case FPE_FLTSUB: code = "FPE_FLTSUB"; break;
+#if defined(FPE_FLTDEN)
+ case FPE_FLTDEN: code = "FPE_FLTDEN"; break;
+#endif
+ }
+ break;
+ case SIGSEGV:
+ switch (sip->si_code) {
+ case SEGV_MAPERR: code = "SEGV_MAPERR"; break;
+ case SEGV_ACCERR: code = "SEGV_ACCERR"; break;
+ }
+ break;
+ case SIGEMT:
+ switch (sip->si_code) {
+#ifdef EMT_TAGOVF
+ case EMT_TAGOVF: code = "EMT_TAGOVF"; break;
+#endif
+ case EMT_CPCOVF: code = "EMT_CPCOVF"; break;
+ }
+ break;
+ case SIGBUS:
+ switch (sip->si_code) {
+ case BUS_ADRALN: code = "BUS_ADRALN"; break;
+ case BUS_ADRERR: code = "BUS_ADRERR"; break;
+ case BUS_OBJERR: code = "BUS_OBJERR"; break;
+ }
+ break;
+ case SIGCLD:
+ switch (sip->si_code) {
+ case CLD_EXITED: code = "CLD_EXITED"; break;
+ case CLD_KILLED: code = "CLD_KILLED"; break;
+ case CLD_DUMPED: code = "CLD_DUMPED"; break;
+ case CLD_TRAPPED: code = "CLD_TRAPPED"; break;
+ case CLD_STOPPED: code = "CLD_STOPPED"; break;
+ case CLD_CONTINUED: code = "CLD_CONTINUED"; break;
+ }
+ break;
+ case SIGPOLL:
+ switch (sip->si_code) {
+ case POLL_IN: code = "POLL_IN"; break;
+ case POLL_OUT: code = "POLL_OUT"; break;
+ case POLL_MSG: code = "POLL_MSG"; break;
+ case POLL_ERR: code = "POLL_ERR"; break;
+ case POLL_PRI: code = "POLL_PRI"; break;
+ case POLL_HUP: code = "POLL_HUP"; break;
+ }
+ break;
+ }
+
+ if (code == NULL) {
+ (void) sprintf(pri->code_buf, "code=%d", sip->si_code);
+ code = (const char *)pri->code_buf;
+ }
+
+ switch (sip->si_signo) {
+ case SIGILL:
+ case SIGTRAP:
+ case SIGFPE:
+ case SIGSEGV:
+ case SIGBUS:
+ case SIGEMT:
+ (void) printf(" %s addr=0x%.8X",
+ code,
+ sip->si_addr);
+ break;
+ case SIGCLD:
+ (void) printf(" %s pid=%d status=0x%.4X",
+ code,
+ sip->si_pid,
+ sip->si_status);
+ break;
+ case SIGPOLL:
+ case SIGXFSZ:
+ (void) printf(" %s fd=%d band=%d",
+ code,
+ sip->si_fd,
+ sip->si_band);
+ break;
+ }
+
+ if (sip->si_errno != 0) {
+ const char *ename = errname(sip->si_errno);
+
+ (void) printf(" errno=%d", sip->si_errno);
+ if (ename != NULL)
+ (void) printf("(%s)", ename);
+ }
+
+ (void) fputc('\n', stdout);
+}
+#endif /* _LP64 */
+
+void
+print_siginfo(private_t *pri, const siginfo_t *sip)
+{
+ const char *code = NULL;
+
+ (void) printf("%s siginfo: %s", pri->pname,
+ signame(pri, sip->si_signo));
+
+ if (sip->si_signo != 0 && SI_FROMUSER(sip) && sip->si_pid != 0) {
+ (void) printf(" pid=%d uid=%u",
+ (int)sip->si_pid,
+ sip->si_uid);
+ if (sip->si_code != 0)
+ (void) printf(" code=%d", sip->si_code);
+ (void) fputc('\n', stdout);
+ return;
+ }
+
+ switch (sip->si_signo) {
+ default:
+ (void) fputc('\n', stdout);
+ return;
+ case SIGILL:
+ case SIGTRAP:
+ case SIGFPE:
+ case SIGSEGV:
+ case SIGBUS:
+ case SIGEMT:
+ case SIGCLD:
+ case SIGPOLL:
+ case SIGXFSZ:
+ break;
+ }
+
+ switch (sip->si_signo) {
+ case SIGILL:
+ switch (sip->si_code) {
+ case ILL_ILLOPC: code = "ILL_ILLOPC"; break;
+ case ILL_ILLOPN: code = "ILL_ILLOPN"; break;
+ case ILL_ILLADR: code = "ILL_ILLADR"; break;
+ case ILL_ILLTRP: code = "ILL_ILLTRP"; break;
+ case ILL_PRVOPC: code = "ILL_PRVOPC"; break;
+ case ILL_PRVREG: code = "ILL_PRVREG"; break;
+ case ILL_COPROC: code = "ILL_COPROC"; break;
+ case ILL_BADSTK: code = "ILL_BADSTK"; break;
+ }
+ break;
+ case SIGTRAP:
+ switch (sip->si_code) {
+ case TRAP_BRKPT: code = "TRAP_BRKPT"; break;
+ case TRAP_TRACE: code = "TRAP_TRACE"; break;
+ case TRAP_RWATCH: code = "TRAP_RWATCH"; break;
+ case TRAP_WWATCH: code = "TRAP_WWATCH"; break;
+ case TRAP_XWATCH: code = "TRAP_XWATCH"; break;
+ case TRAP_DTRACE: code = "TRAP_DTRACE"; break;
+ }
+ break;
+ case SIGFPE:
+ switch (sip->si_code) {
+ case FPE_INTDIV: code = "FPE_INTDIV"; break;
+ case FPE_INTOVF: code = "FPE_INTOVF"; break;
+ case FPE_FLTDIV: code = "FPE_FLTDIV"; break;
+ case FPE_FLTOVF: code = "FPE_FLTOVF"; break;
+ case FPE_FLTUND: code = "FPE_FLTUND"; break;
+ case FPE_FLTRES: code = "FPE_FLTRES"; break;
+ case FPE_FLTINV: code = "FPE_FLTINV"; break;
+ case FPE_FLTSUB: code = "FPE_FLTSUB"; break;
+#if defined(FPE_FLTDEN)
+ case FPE_FLTDEN: code = "FPE_FLTDEN"; break;
+#endif
+ }
+ break;
+ case SIGSEGV:
+ switch (sip->si_code) {
+ case SEGV_MAPERR: code = "SEGV_MAPERR"; break;
+ case SEGV_ACCERR: code = "SEGV_ACCERR"; break;
+ }
+ break;
+ case SIGEMT:
+ switch (sip->si_code) {
+#ifdef EMT_TAGOVF
+ case EMT_TAGOVF: code = "EMT_TAGOVF"; break;
+#endif
+ case EMT_CPCOVF: code = "EMT_CPCOVF"; break;
+ }
+ break;
+ case SIGBUS:
+ switch (sip->si_code) {
+ case BUS_ADRALN: code = "BUS_ADRALN"; break;
+ case BUS_ADRERR: code = "BUS_ADRERR"; break;
+ case BUS_OBJERR: code = "BUS_OBJERR"; break;
+ }
+ break;
+ case SIGCLD:
+ switch (sip->si_code) {
+ case CLD_EXITED: code = "CLD_EXITED"; break;
+ case CLD_KILLED: code = "CLD_KILLED"; break;
+ case CLD_DUMPED: code = "CLD_DUMPED"; break;
+ case CLD_TRAPPED: code = "CLD_TRAPPED"; break;
+ case CLD_STOPPED: code = "CLD_STOPPED"; break;
+ case CLD_CONTINUED: code = "CLD_CONTINUED"; break;
+ }
+ break;
+ case SIGPOLL:
+ switch (sip->si_code) {
+ case POLL_IN: code = "POLL_IN"; break;
+ case POLL_OUT: code = "POLL_OUT"; break;
+ case POLL_MSG: code = "POLL_MSG"; break;
+ case POLL_ERR: code = "POLL_ERR"; break;
+ case POLL_PRI: code = "POLL_PRI"; break;
+ case POLL_HUP: code = "POLL_HUP"; break;
+ }
+ break;
+ }
+
+ if (code == NULL) {
+ (void) sprintf(pri->code_buf, "code=%d", sip->si_code);
+ code = (const char *)pri->code_buf;
+ }
+
+ switch (sip->si_signo) {
+ case SIGILL:
+ case SIGTRAP:
+ case SIGFPE:
+ case SIGSEGV:
+ case SIGBUS:
+ case SIGEMT:
+ (void) printf(" %s addr=0x%.8lX",
+ code,
+ (long)sip->si_addr);
+ break;
+ case SIGCLD:
+ (void) printf(" %s pid=%d status=0x%.4X",
+ code,
+ (int)sip->si_pid,
+ sip->si_status);
+ break;
+ case SIGPOLL:
+ case SIGXFSZ:
+ (void) printf(" %s fd=%d band=%ld",
+ code,
+ sip->si_fd,
+ sip->si_band);
+ break;
+ }
+
+ if (sip->si_errno != 0) {
+ const char *ename = errname(sip->si_errno);
+
+ (void) printf(" errno=%d", sip->si_errno);
+ if (ename != NULL)
+ (void) printf("(%s)", ename);
+ }
+
+ (void) fputc('\n', stdout);
+}
+
+#ifdef _LP64
+void
+show_siginfo32(private_t *pri, long offset)
+{
+ struct siginfo32 siginfo;
+
+ if (offset != NULL &&
+ Pread(Proc, &siginfo, sizeof (siginfo), offset) == sizeof (siginfo))
+ print_siginfo32(pri, &siginfo);
+}
+#endif /* _LP64 */
+
+void
+show_siginfo(private_t *pri, long offset)
+{
+ struct siginfo siginfo;
+
+#ifdef _LP64
+ if (data_model != PR_MODEL_LP64) {
+ show_siginfo32(pri, offset);
+ return;
+ }
+#endif
+ if (offset != NULL &&
+ Pread(Proc, &siginfo, sizeof (siginfo), offset) == sizeof (siginfo))
+ print_siginfo(pri, &siginfo);
+}
+
+void
+show_bool(private_t *pri, long offset, int count)
+{
+ int serial = (count > MYBUFSIZ / 4);
+
+ /* enter region of lengthy output */
+ if (serial)
+ Eserialize();
+
+ while (count > 0) {
+ char buf[32];
+ int nb = (count < 32)? count : 32;
+ int i;
+
+ if (Pread(Proc, buf, (size_t)nb, offset) != nb)
+ break;
+
+ (void) printf("%s ", pri->pname);
+ for (i = 0; i < nb; i++)
+ (void) printf(" %d", buf[i]);
+ (void) fputc('\n', stdout);
+
+ count -= nb;
+ offset += nb;
+ }
+
+ /* exit region of lengthy output */
+ if (serial)
+ Xserialize();
+}
+
+#ifdef _LP64
+void
+show_iovec32(private_t *pri, long offset, int niov, int showbuf, long count)
+{
+ iovec32_t iovec[16];
+ iovec32_t *ip;
+ long nb;
+ int serial = (count > MYBUFSIZ / 4 && showbuf);
+
+ if (niov > 16) /* is this the real limit? */
+ niov = 16;
+
+ if (offset != NULL && niov > 0 &&
+ Pread(Proc, &iovec[0], niov*sizeof (iovec32_t), offset)
+ == niov*sizeof (iovec32_t)) {
+ /* enter region of lengthy output */
+ if (serial)
+ Eserialize();
+
+ for (ip = &iovec[0]; niov-- && !interrupt; ip++) {
+ (void) printf("%s\tiov_base = 0x%.8X iov_len = %d\n",
+ pri->pname,
+ ip->iov_base,
+ ip->iov_len);
+ if ((nb = count) > 0) {
+ if (nb > ip->iov_len)
+ nb = ip->iov_len;
+ if (nb > 0)
+ count -= nb;
+ }
+ if (showbuf && nb > 0)
+ showbuffer(pri, (long)ip->iov_base, nb);
+ }
+
+ /* exit region of lengthy output */
+ if (serial)
+ Xserialize();
+ }
+}
+#endif /* _LP64 */
+
+void
+show_iovec(private_t *pri, long offset, long niov, int showbuf, long count)
+{
+ iovec_t iovec[16];
+ iovec_t *ip;
+ long nb;
+ int serial = (count > MYBUFSIZ / 4 && showbuf);
+
+#ifdef _LP64
+ if (data_model != PR_MODEL_LP64) {
+ show_iovec32(pri, offset, niov, showbuf, count);
+ return;
+ }
+#endif
+ if (niov > 16) /* is this the real limit? */
+ niov = 16;
+
+ if (offset != NULL && niov > 0 &&
+ Pread(Proc, &iovec[0], niov*sizeof (iovec_t), offset)
+ == niov*sizeof (iovec_t)) {
+ /* enter region of lengthy output */
+ if (serial)
+ Eserialize();
+
+ for (ip = &iovec[0]; niov-- && !interrupt; ip++) {
+ (void) printf("%s\tiov_base = 0x%.8lX iov_len = %lu\n",
+ pri->pname,
+ (long)ip->iov_base,
+ ip->iov_len);
+ if ((nb = count) > 0) {
+ if (nb > ip->iov_len)
+ nb = ip->iov_len;
+ if (nb > 0)
+ count -= nb;
+ }
+ if (showbuf && nb > 0)
+ showbuffer(pri, (long)ip->iov_base, nb);
+ }
+
+ /* exit region of lengthy output */
+ if (serial)
+ Xserialize();
+ }
+}
+
+void
+show_dents32(private_t *pri, long offset, long count)
+{
+ long buf[MYBUFSIZ / sizeof (long)];
+ struct dirent32 *dp;
+ int serial = (count > 100);
+
+ if (offset == 0)
+ return;
+
+ /* enter region of lengthy output */
+ if (serial)
+ Eserialize();
+
+ while (count > 0 && !interrupt) {
+ int nb = count < MYBUFSIZ? (int)count : MYBUFSIZ;
+
+ if ((nb = Pread(Proc, &buf[0], (size_t)nb, offset)) <= 0)
+ break;
+
+ dp = (struct dirent32 *)&buf[0];
+ if (nb < (int)(dp->d_name - (char *)dp))
+ break;
+ if ((unsigned)nb < dp->d_reclen) {
+ /* getdents() error? */
+ (void) printf(
+ "%s ino=%-5u off=%-4d rlen=%-3d\n",
+ pri->pname,
+ dp->d_ino,
+ dp->d_off,
+ dp->d_reclen);
+ break;
+ }
+
+ while (!interrupt &&
+ nb >= (int)(dp->d_name - (char *)dp) &&
+ (unsigned)nb >= dp->d_reclen) {
+ (void) printf(
+ "%s ino=%-5u off=%-4d rlen=%-3d \"%.*s\"\n",
+ pri->pname,
+ dp->d_ino,
+ dp->d_off,
+ dp->d_reclen,
+ dp->d_reclen - (int)(dp->d_name - (char *)dp),
+ dp->d_name);
+ nb -= dp->d_reclen;
+ count -= dp->d_reclen;
+ offset += dp->d_reclen;
+ /* LINTED improper alignment */
+ dp = (struct dirent32 *)((char *)dp + dp->d_reclen);
+ }
+ }
+
+ /* exit region of lengthy output */
+ if (serial)
+ Xserialize();
+}
+
+void
+show_dents64(private_t *pri, long offset, long count)
+{
+ long long buf[MYBUFSIZ / sizeof (long long)];
+ struct dirent64 *dp;
+ int serial = (count > 100);
+
+ if (offset == 0)
+ return;
+
+ /* enter region of lengthy output */
+ if (serial)
+ Eserialize();
+
+ while (count > 0 && !interrupt) {
+ int nb = count < MYBUFSIZ? (int)count : MYBUFSIZ;
+
+ if ((nb = Pread(Proc, &buf[0], (size_t)nb, offset)) <= 0)
+ break;
+
+ dp = (struct dirent64 *)&buf[0];
+ if (nb < (int)(dp->d_name - (char *)dp))
+ break;
+ if ((unsigned)nb < dp->d_reclen) {
+ /* getdents() error? */
+ (void) printf(
+ "%s ino=%-5llu off=%-4lld rlen=%-3d\n",
+ pri->pname,
+ (long long)dp->d_ino,
+ (long long)dp->d_off,
+ dp->d_reclen);
+ break;
+ }
+
+ while (!interrupt &&
+ nb >= (int)(dp->d_name - (char *)dp) &&
+ (unsigned)nb >= dp->d_reclen) {
+ (void) printf(
+ "%s ino=%-5llu off=%-4lld rlen=%-3d \"%.*s\"\n",
+ pri->pname,
+ (long long)dp->d_ino,
+ (long long)dp->d_off,
+ dp->d_reclen,
+ dp->d_reclen - (int)(dp->d_name - (char *)dp),
+ dp->d_name);
+ nb -= dp->d_reclen;
+ count -= dp->d_reclen;
+ offset += dp->d_reclen;
+ /* LINTED improper alignment */
+ dp = (struct dirent64 *)((char *)dp + dp->d_reclen);
+ }
+ }
+
+ /* exit region of lengthy output */
+ if (serial)
+ Xserialize();
+}
+
+void
+show_rlimit32(private_t *pri, long offset)
+{
+ struct rlimit32 rlimit;
+
+ if (offset != NULL &&
+ Pread(Proc, &rlimit, sizeof (rlimit), offset) == sizeof (rlimit)) {
+ (void) printf("%s\t", pri->pname);
+ switch (rlimit.rlim_cur) {
+ case RLIM32_INFINITY:
+ (void) fputs("cur = RLIM_INFINITY", stdout);
+ break;
+ case RLIM32_SAVED_MAX:
+ (void) fputs("cur = RLIM_SAVED_MAX", stdout);
+ break;
+ case RLIM32_SAVED_CUR:
+ (void) fputs("cur = RLIM_SAVED_CUR", stdout);
+ break;
+ default:
+ (void) printf("cur = %lu", (long)rlimit.rlim_cur);
+ break;
+ }
+ switch (rlimit.rlim_max) {
+ case RLIM32_INFINITY:
+ (void) fputs(" max = RLIM_INFINITY\n", stdout);
+ break;
+ case RLIM32_SAVED_MAX:
+ (void) fputs(" max = RLIM_SAVED_MAX\n", stdout);
+ break;
+ case RLIM32_SAVED_CUR:
+ (void) fputs(" max = RLIM_SAVED_CUR\n", stdout);
+ break;
+ default:
+ (void) printf(" max = %lu\n", (long)rlimit.rlim_max);
+ break;
+ }
+ }
+}
+
+void
+show_rlimit64(private_t *pri, long offset)
+{
+ struct rlimit64 rlimit;
+
+ if (offset != NULL &&
+ Pread(Proc, &rlimit, sizeof (rlimit), offset) == sizeof (rlimit)) {
+ (void) printf("%s\t", pri->pname);
+ switch (rlimit.rlim_cur) {
+ case RLIM64_INFINITY:
+ (void) fputs("cur = RLIM64_INFINITY", stdout);
+ break;
+ case RLIM64_SAVED_MAX:
+ (void) fputs("cur = RLIM64_SAVED_MAX", stdout);
+ break;
+ case RLIM64_SAVED_CUR:
+ (void) fputs("cur = RLIM64_SAVED_CUR", stdout);
+ break;
+ default:
+ (void) printf("cur = %llu",
+ (unsigned long long)rlimit.rlim_cur);
+ break;
+ }
+ switch (rlimit.rlim_max) {
+ case RLIM64_INFINITY:
+ (void) fputs(" max = RLIM64_INFINITY\n", stdout);
+ break;
+ case RLIM64_SAVED_MAX:
+ (void) fputs(" max = RLIM64_SAVED_MAX\n", stdout);
+ break;
+ case RLIM64_SAVED_CUR:
+ (void) fputs(" max = RLIM64_SAVED_CUR\n", stdout);
+ break;
+ default:
+ (void) printf(" max = %llu\n",
+ (unsigned long long)rlimit.rlim_max);
+ break;
+ }
+ }
+}
+
+void
+show_nuname(private_t *pri, long offset)
+{
+ struct utsname ubuf;
+
+ if (offset != NULL &&
+ Pread(Proc, &ubuf, sizeof (ubuf), offset) == sizeof (ubuf)) {
+ (void) printf(
+ "%s\tsys=%s nod=%s rel=%s ver=%s mch=%s\n",
+ pri->pname,
+ ubuf.sysname,
+ ubuf.nodename,
+ ubuf.release,
+ ubuf.version,
+ ubuf.machine);
+ }
+}
+
+void
+show_adjtime(private_t *pri, long off1, long off2)
+{
+ show_timeval(pri, off1, " delta");
+ show_timeval(pri, off2, "olddelta");
+}
+
+void
+show_sockaddr(private_t *pri,
+ const char *str, long addroff, long lenoff, long len)
+{
+ /*
+ * A buffer large enough for PATH_MAX size AF_UNIX address, which is
+ * also large enough to store a sockaddr_in or a sockaddr_in6.
+ */
+ long buf[(sizeof (short) + PATH_MAX + sizeof (long) - 1)
+ / sizeof (long)];
+ struct sockaddr *sa = (struct sockaddr *)buf;
+ struct sockaddr_in *sin = (struct sockaddr_in *)buf;
+ struct sockaddr_un *soun = (struct sockaddr_un *)buf;
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)buf;
+ char addrbuf[INET6_ADDRSTRLEN];
+
+ if (lenoff != 0) {
+ uint_t ilen;
+ if (Pread(Proc, &ilen, sizeof (ilen), lenoff) != sizeof (ilen))
+ return;
+ len = ilen;
+ }
+
+ if (len >= sizeof (buf)) /* protect against ridiculous length */
+ len = sizeof (buf) - 1;
+ if (Pread(Proc, buf, len, addroff) != len)
+ return;
+
+ switch (sa->sa_family) {
+ case AF_INET6:
+ (void) printf("%s\tAF_INET6 %s = %s port = %u\n",
+ pri->pname, str,
+ inet_ntop(AF_INET6, &sin6->sin6_addr, addrbuf,
+ sizeof (addrbuf)),
+ ntohs(sin6->sin6_port));
+ (void) printf("%s\tscope id = %u source id = 0x%x\n"
+ "%s\tflow class = 0x%02x flow label = 0x%05x\n",
+ pri->pname, ntohl(sin6->sin6_scope_id),
+ ntohl(sin6->__sin6_src_id),
+ pri->pname,
+ ntohl((sin6->sin6_flowinfo & IPV6_FLOWINFO_TCLASS) >> 20),
+ ntohl(sin6->sin6_flowinfo & IPV6_FLOWINFO_FLOWLABEL));
+ break;
+ case AF_INET:
+ (void) printf("%s\tAF_%s %s = %s port = %u\n",
+ pri->pname, "INET",
+ str, inet_ntop(AF_INET, &sin->sin_addr, addrbuf,
+ sizeof (addrbuf)), ntohs(sin->sin_port));
+ break;
+ case AF_UNIX:
+ len -= sizeof (soun->sun_family);
+ if (len >= 0) {
+ /* Null terminate */
+ soun->sun_path[len] = NULL;
+ (void) printf("%s\tAF_UNIX %s = %s\n", pri->pname,
+ str, soun->sun_path);
+ }
+ break;
+ }
+}
+
+void
+show_msghdr(private_t *pri, long offset)
+{
+ const lwpstatus_t *Lsp = pri->lwpstat;
+ int what = Lsp->pr_what;
+ int err = pri->Errno;
+ struct msghdr msg;
+ int showbuf = FALSE;
+ int i = pri->sys_args[0]+1;
+ long nb = (what == SYS_recvmsg)? pri->Rval1 : 32*1024;
+
+ if (Pread(Proc, &msg, sizeof (msg), offset) != sizeof (msg))
+ return;
+
+ if (msg.msg_name != NULL && msg.msg_namelen != 0)
+ show_sockaddr(pri, "msg_name",
+ (long)msg.msg_name, 0, (long)msg.msg_namelen);
+
+ /*
+ * Print the iovec if the syscall was successful and the fd is
+ * part of the set being traced.
+ */
+ if ((what == SYS_recvmsg && !err &&
+ prismember(&readfd, i)) ||
+ (what == SYS_sendmsg &&
+ prismember(&writefd, i)))
+ showbuf = TRUE;
+
+ show_iovec(pri, (long)msg.msg_iov, msg.msg_iovlen, showbuf, nb);
+
+}
+
+#ifdef _LP64
+void
+show_msghdr32(private_t *pri, long offset)
+{
+ struct msghdr32 {
+ caddr32_t msg_name;
+ uint32_t msg_namelen;
+ caddr32_t msg_iov;
+ int32_t msg_iovlen;
+ } msg;
+ const lwpstatus_t *Lsp = pri->lwpstat;
+ int what = Lsp->pr_what;
+ int err = pri->Errno;
+ int showbuf = FALSE;
+ int i = pri->sys_args[0]+1;
+ long nb = (what == SYS_recvmsg)? pri->Rval1 : 32*1024;
+
+ if (Pread(Proc, &msg, sizeof (msg), offset) != sizeof (msg))
+ return;
+
+ if (msg.msg_name != NULL && msg.msg_namelen != 0)
+ show_sockaddr(pri, "msg_name",
+ (long)msg.msg_name, 0, (long)msg.msg_namelen);
+ /*
+ * Print the iovec if the syscall was successful and the fd is
+ * part of the set being traced.
+ */
+ if ((what == SYS_recvmsg && !err &&
+ prismember(&readfd, i)) ||
+ (what == SYS_sendmsg &&
+ prismember(&writefd, i)))
+ showbuf = TRUE;
+
+ show_iovec32(pri, (long)msg.msg_iov, msg.msg_iovlen, showbuf, nb);
+
+}
+#endif /* _LP64 */
+
+static void
+show_doorargs(private_t *pri, long offset)
+{
+ door_arg_t args;
+
+ if (Pread(Proc, &args, sizeof (args), offset) == sizeof (args)) {
+ (void) printf("%s\tdata_ptr=0x%lX data_size=%lu\n",
+ pri->pname,
+ (ulong_t)args.data_ptr,
+ (ulong_t)args.data_size);
+ (void) printf("%s\tdesc_ptr=0x%lX desc_num=%u\n",
+ pri->pname,
+ (ulong_t)args.desc_ptr,
+ args.desc_num);
+ (void) printf("%s\trbuf=0x%lX rsize=%lu\n",
+ pri->pname,
+ (ulong_t)args.rbuf,
+ (ulong_t)args.rsize);
+ }
+}
+
+static void
+show_ucred_privsets(private_t *pri, ucred_t *uc)
+{
+ int i = 0;
+ const priv_set_t *s;
+ priv_ptype_t sn;
+ char *str;
+
+ while ((sn = priv_getsetbynum(i++)) != NULL) {
+ s = ucred_getprivset(uc, sn);
+
+ if (s == NULL)
+ continue;
+
+ (void) printf("%s\t%c: %s\n",
+ pri->pname,
+ *sn,
+ str = priv_set_to_str(s, ',', PRIV_STR_SHORT));
+
+ free(str);
+ }
+}
+
+static void
+show_ucred(private_t *pri, long offset)
+{
+ ucred_t *uc = _ucred_alloc();
+ size_t sz;
+
+ if (uc == NULL)
+ return;
+
+ sz = Pread(Proc, uc, uc->uc_size, offset);
+
+ /*
+ * A new uc_size is read, it could be smaller than the previously
+ * value. We accept short reads that fill the whole header.
+ */
+ if (sz >= sizeof (ucred_t) && sz >= uc->uc_size) {
+ (void) printf("%s\teuid=%u egid=%u\n",
+ pri->pname,
+ ucred_geteuid(uc),
+ ucred_getegid(uc));
+ (void) printf("%s\truid=%u rgid=%u\n",
+ pri->pname,
+ ucred_getruid(uc),
+ ucred_getrgid(uc));
+ (void) printf("%s\tpid=%d zoneid=%d\n",
+ pri->pname,
+ (int)ucred_getpid(uc),
+ (int)ucred_getzoneid(uc));
+ show_ucred_privsets(pri, uc);
+ }
+ ucred_free(uc);
+}
+
+static void
+show_privset(private_t *pri, long offset, size_t size, char *label)
+{
+ priv_set_t *tmp = priv_allocset();
+ size_t sz;
+
+ if (tmp == NULL)
+ return;
+
+ sz = Pread(Proc, tmp, size, offset);
+
+ if (sz == size) {
+ char *str = priv_set_to_str(tmp, ',', PRIV_STR_SHORT);
+ if (str != NULL) {
+ (void) printf("%s\t%s%s\n", pri->pname, label, str);
+ free(str);
+ }
+ }
+ priv_freeset(tmp);
+}
+
+static void
+show_doorinfo(private_t *pri, long offset)
+{
+ door_info_t info;
+ door_attr_t attr;
+
+ if (Pread(Proc, &info, sizeof (info), offset) != sizeof (info))
+ return;
+ (void) printf("%s\ttarget=%d proc=0x%llX data=0x%llX\n",
+ pri->pname,
+ (int)info.di_target,
+ info.di_proc,
+ info.di_data);
+ attr = info.di_attributes;
+ (void) printf("%s\tattributes=%s\n", pri->pname, door_flags(pri, attr));
+ (void) printf("%s\tuniquifier=%llu\n", pri->pname, info.di_uniquifier);
+}
+
+static void
+show_doorparam(private_t *pri, long offset)
+{
+ ulong_t val;
+
+ if (Pread(Proc, &val, sizeof (val), offset) == sizeof (val)) {
+ (void) printf("%s\tvalue=%lu\n",
+ pri->pname,
+ val);
+ }
+}
+
+#ifdef _LP64
+
+static void
+show_doorargs32(private_t *pri, long offset)
+{
+ struct door_arg32 args;
+
+ if (Pread(Proc, &args, sizeof (args), offset) == sizeof (args)) {
+ (void) printf("%s\tdata_ptr=%X data_size=%u\n",
+ pri->pname,
+ args.data_ptr,
+ args.data_size);
+ (void) printf("%s\tdesc_ptr=0x%X desc_num=%u\n",
+ pri->pname,
+ args.desc_ptr,
+ args.desc_num);
+ (void) printf("%s\trbuf=0x%X rsize=%u\n",
+ pri->pname,
+ args.rbuf,
+ args.rsize);
+ }
+}
+
+static void
+show_doorparam32(private_t *pri, long offset)
+{
+ uint_t val;
+
+ if (Pread(Proc, &val, sizeof (val), offset) == sizeof (val)) {
+ (void) printf("%s\tvalue=%u\n",
+ pri->pname,
+ val);
+ }
+}
+
+#endif /* _LP64 */
+
+static void
+show_doors(private_t *pri)
+{
+ switch (pri->sys_args[5]) {
+ case DOOR_CALL:
+#ifdef _LP64
+ if (data_model == PR_MODEL_LP64)
+ show_doorargs(pri, (long)pri->sys_args[1]);
+ else
+ show_doorargs32(pri, (long)pri->sys_args[1]);
+#else
+ show_doorargs(pri, (long)pri->sys_args[1]);
+#endif
+ break;
+ case DOOR_UCRED:
+ if (!pri->Errno)
+ show_ucred(pri, (long)pri->sys_args[0]);
+ break;
+ case DOOR_INFO:
+ if (!pri->Errno)
+ show_doorinfo(pri, (long)pri->sys_args[1]);
+ break;
+ case DOOR_GETPARAM:
+ if (!pri->Errno) {
+#ifdef _LP64
+ if (data_model == PR_MODEL_LP64)
+ show_doorparam(pri, (long)pri->sys_args[2]);
+ else
+ show_doorparam32(pri, (long)pri->sys_args[2]);
+#else
+ show_doorparam(pri, (long)pri->sys_args[2]);
+#endif
+ }
+ break;
+ }
+}
+
+static void
+show_portargs(private_t *pri, long offset)
+{
+ port_event_t args;
+
+ if (Pread(Proc, &args, sizeof (args), offset) == sizeof (args)) {
+ (void) printf("%s\tevents=0x%x source=%u\n",
+ pri->pname,
+ args.portev_events,
+ args.portev_source);
+ (void) printf("%s\tobject=0x%p user=0x%p\n",
+ pri->pname,
+ (void *)args.portev_object,
+ (void *)args.portev_user);
+ }
+}
+
+
+#ifdef _LP64
+
+static void
+show_portargs32(private_t *pri, long offset)
+{
+ port_event32_t args;
+
+ if (Pread(Proc, &args, sizeof (args), offset) == sizeof (args)) {
+ (void) printf("%s\tevents=0x%x source=%u\n",
+ pri->pname,
+ args.portev_events,
+ args.portev_source);
+ (void) printf("%s\tobject=0x%x user=0x%x\n",
+ pri->pname,
+ args.portev_object,
+ args.portev_user);
+ }
+}
+
+#endif /* _LP64 */
+
+static void
+show_ports(private_t *pri)
+{
+ switch (pri->sys_args[0]) {
+ case PORT_GET:
+#ifdef _LP64
+ if (data_model == PR_MODEL_LP64)
+ show_portargs(pri, (long)pri->sys_args[2]);
+ else
+ show_portargs32(pri, (long)pri->sys_args[2]);
+#else
+ show_portargs(pri, (long)pri->sys_args[2]);
+#endif
+ break;
+ }
+}
+
+#define MAX_SNDFL_PRD 16
+
+#ifdef _LP64
+
+static void
+show_ksendfilevec32(private_t *pri, int fd,
+ ksendfilevec32_t *sndvec, int sfvcnt)
+{
+ ksendfilevec32_t *snd_ptr, snd[MAX_SNDFL_PRD];
+ size_t cpy_rqst;
+
+ Eserialize();
+ while (sfvcnt > 0) {
+ cpy_rqst = MIN(sfvcnt, MAX_SNDFL_PRD);
+ sfvcnt -= cpy_rqst;
+ cpy_rqst *= sizeof (snd[0]);
+
+ if (Pread(Proc, snd, cpy_rqst, (uintptr_t)sndvec) != cpy_rqst)
+ break;
+
+ snd_ptr = &snd[0];
+
+ while (cpy_rqst) {
+ (void) printf(
+ "sfv_fd=%d\tsfv_flag=0x%x\t"
+ "sfv_off=%d\tsfv_len=%u\n",
+ snd_ptr->sfv_fd,
+ snd_ptr->sfv_flag,
+ snd_ptr->sfv_off,
+ snd_ptr->sfv_len);
+
+ if (snd_ptr->sfv_fd == SFV_FD_SELF &&
+ prismember(&writefd, fd)) {
+ showbuffer(pri,
+ (long)snd_ptr->sfv_off & 0xffffffff,
+ (long)snd_ptr->sfv_len);
+ }
+
+ cpy_rqst -= sizeof (snd[0]);
+ snd_ptr++;
+ }
+
+ sndvec += MAX_SNDFL_PRD;
+ }
+ Xserialize();
+}
+
+static void
+show_ksendfilevec64(private_t *pri, int fd,
+ ksendfilevec64_t *sndvec, int sfvcnt)
+{
+ ksendfilevec64_t *snd_ptr, snd[MAX_SNDFL_PRD];
+ size_t cpy_rqst;
+
+ Eserialize();
+ while (sfvcnt > 0) {
+ cpy_rqst = MIN(sfvcnt, MAX_SNDFL_PRD);
+ sfvcnt -= cpy_rqst;
+ cpy_rqst *= sizeof (snd[0]);
+
+ if (Pread(Proc, snd, cpy_rqst, (uintptr_t)sndvec) != cpy_rqst)
+ break;
+
+ snd_ptr = &snd[0];
+
+ while (cpy_rqst) {
+ (void) printf(
+ "sfv_fd=%d\tsfv_flag=0x%x\t"
+ "sfv_off=%ld\tsfv_len=%u\n",
+ snd_ptr->sfv_fd,
+ snd_ptr->sfv_flag,
+ snd_ptr->sfv_off,
+ snd_ptr->sfv_len);
+
+ if (snd_ptr->sfv_fd == SFV_FD_SELF &&
+ prismember(&writefd, fd)) {
+ showbuffer(pri,
+ (long)snd_ptr->sfv_off & 0xffffffff,
+ (long)snd_ptr->sfv_len);
+ }
+
+ cpy_rqst -= sizeof (snd[0]);
+ snd_ptr++;
+ }
+
+ sndvec += MAX_SNDFL_PRD;
+ }
+ Xserialize();
+}
+
+#endif /* _LP64 */
+
+/*ARGSUSED*/
+static void
+show_sendfilevec(private_t *pri, int fd, sendfilevec_t *sndvec, int sfvcnt)
+{
+ sendfilevec_t *snd_ptr, snd[MAX_SNDFL_PRD];
+ size_t cpy_rqst;
+
+#ifdef _LP64
+ if (data_model != PR_MODEL_LP64) {
+ show_ksendfilevec32(pri, fd,
+ (ksendfilevec32_t *)sndvec, sfvcnt);
+ return;
+ }
+#endif
+ Eserialize();
+ while (sfvcnt > 0) {
+ cpy_rqst = MIN(sfvcnt, MAX_SNDFL_PRD);
+ sfvcnt -= cpy_rqst;
+ cpy_rqst *= sizeof (snd[0]);
+
+ if (Pread(Proc, snd, cpy_rqst, (uintptr_t)sndvec) != cpy_rqst)
+ break;
+
+ snd_ptr = &snd[0];
+
+ while (cpy_rqst) {
+ (void) printf(
+ "sfv_fd=%d\tsfv_flag=0x%x\t"
+ "sfv_off=%ld\tsfv_len=%lu\n",
+ snd_ptr->sfv_fd,
+ snd_ptr->sfv_flag,
+ snd_ptr->sfv_off,
+ (ulong_t)snd_ptr->sfv_len);
+
+ if (snd_ptr->sfv_fd == SFV_FD_SELF &&
+ prismember(&writefd, fd)) {
+ showbuffer(pri, (long)snd_ptr->sfv_off,
+ (long)snd_ptr->sfv_len);
+ }
+
+ cpy_rqst -= sizeof (snd[0]);
+ snd_ptr++;
+ }
+
+ sndvec += MAX_SNDFL_PRD;
+ }
+ Xserialize();
+}
+
+/*ARGSUSED*/
+static void
+show_sendfilevec64(private_t *pri, int fd, sendfilevec64_t *sndvec, int sfvcnt)
+{
+ sendfilevec64_t *snd_ptr, snd[MAX_SNDFL_PRD];
+ size_t cpy_rqst;
+
+#ifdef _LP64
+ if (data_model != PR_MODEL_LP64) {
+ show_ksendfilevec64(pri, fd,
+ (ksendfilevec64_t *)sndvec, sfvcnt);
+ return;
+ }
+#endif
+
+ Eserialize();
+ while (sfvcnt > 0) {
+ cpy_rqst = MIN(sfvcnt, MAX_SNDFL_PRD);
+ sfvcnt -= cpy_rqst;
+ cpy_rqst *= sizeof (snd[0]);
+
+ if (Pread(Proc, snd, cpy_rqst, (uintptr_t)sndvec) != cpy_rqst)
+ break;
+
+ snd_ptr = &snd[0];
+
+ while (cpy_rqst) {
+ (void) printf(
+#ifdef _LP64
+ "sfv_fd=%d\tsfv_flag=0x%x\t"
+ "sfv_off=%ld\tsfv_len=%lu\n",
+#else
+ "sfv_fd=%d\tsfv_flag=0x%x\t"
+ "sfv_off=%lld\tsfv_len=%lu\n",
+#endif
+ snd_ptr->sfv_fd,
+ snd_ptr->sfv_flag,
+ snd_ptr->sfv_off,
+ (ulong_t)snd_ptr->sfv_len);
+
+ if (snd_ptr->sfv_fd == SFV_FD_SELF &&
+ prismember(&writefd, fd)) {
+ showbuffer(pri, (long)snd_ptr->sfv_off,
+ (long)snd_ptr->sfv_len);
+ }
+
+ cpy_rqst -= sizeof (snd[0]);
+ snd_ptr++;
+ }
+
+ sndvec += MAX_SNDFL_PRD;
+ }
+ Xserialize();
+}
+
+static void
+show_memcntl_mha(private_t *pri, long offset)
+{
+ struct memcntl_mha mha;
+ const char *s = NULL;
+
+ if (Pread(Proc, &mha, sizeof (mha), offset) == sizeof (mha)) {
+ switch (mha.mha_cmd) {
+ case MHA_MAPSIZE_VA: s = "MHA_MAPSIZE_VA"; break;
+ case MHA_MAPSIZE_BSSBRK: s = "MHA_MAPSIZE_BSSBRK"; break;
+ case MHA_MAPSIZE_STACK: s = "MHA_MAPSIZE_STACK"; break;
+ }
+ if (s)
+ (void) printf("%s\tmha_cmd=%s mha_flags=0x%x"
+ " mha_pagesize=%lu\n",
+ pri->pname, s, mha.mha_flags,
+ (ulong_t)mha.mha_pagesize);
+ else
+ (void) printf("%s\tmha_cmd=0x%.8x mha_flags=0x%x"
+ " mha_pagesize=%lu\n",
+ pri->pname, mha.mha_cmd, mha.mha_flags,
+ (ulong_t)mha.mha_pagesize);
+ }
+}
+
+#ifdef _LP64
+
+static void
+show_memcntl_mha32(private_t *pri, long offset)
+{
+ struct memcntl_mha32 mha32;
+ const char *s = NULL;
+
+ if (Pread(Proc, &mha32, sizeof (mha32), offset) ==
+ sizeof (mha32)) {
+ switch (mha32.mha_cmd) {
+ case MHA_MAPSIZE_VA: s = "MHA_MAPSIZE_VA"; break;
+ case MHA_MAPSIZE_BSSBRK: s = "MHA_MAPSIZE_BSSBRK"; break;
+ case MHA_MAPSIZE_STACK: s = "MHA_MAPSIZE_STACK"; break;
+ }
+ if (s)
+ (void) printf("%s\tmha_cmd=%s mha_flags=0x%x"
+ " mha_pagesize=%u\n",
+ pri->pname, s, mha32.mha_flags, mha32.mha_pagesize);
+ else
+ (void) printf("%s\tmha_cmd=0x%.8x mha_flags=0x%x"
+ " mha_pagesize=%u\n",
+ pri->pname, mha32.mha_cmd, mha32.mha_flags,
+ mha32.mha_pagesize);
+ }
+}
+
+#endif /* _LP64 */
+
+static void
+show_memcntl(private_t *pri)
+{
+
+ if ((int)pri->sys_args[2] != MC_HAT_ADVISE)
+ return;
+#ifdef _LP64
+ if (data_model == PR_MODEL_LP64)
+ show_memcntl_mha(pri, (long)pri->sys_args[3]);
+ else
+ show_memcntl_mha32(pri, (long)pri->sys_args[3]);
+#else
+ show_memcntl_mha(pri, (long)pri->sys_args[3]);
+#endif
+}
+
+void
+show_ids(private_t *pri, long offset, int count)
+{
+ id_t buf[MYBUFSIZ / sizeof (id_t)];
+ id_t *idp;
+ int serial = (count > MYBUFSIZ / 48);
+
+ if (offset == 0)
+ return;
+
+ /* enter region of lengthy output */
+ if (serial)
+ Eserialize();
+
+ while (count > 0 && !interrupt) {
+ ssize_t nb = (count * sizeof (id_t) < MYBUFSIZ)?
+ count * sizeof (id_t) : MYBUFSIZ;
+
+ if ((nb = Pread(Proc, &buf[0], (size_t)nb, offset)) < 0 ||
+ nb < sizeof (id_t))
+ break;
+
+ idp = buf;
+ while (!interrupt && nb >= sizeof (id_t)) {
+ (void) printf("%s\t%8d\n", pri->pname, (int)*idp);
+ offset += sizeof (id_t);
+ nb -= sizeof (id_t);
+ idp++;
+ count--;
+ }
+ }
+
+ /* exit region of lengthy output */
+ if (serial)
+ Xserialize();
+}
+
+void
+show_ntp_gettime(private_t *pri)
+{
+ struct ntptimeval ntv;
+ long offset;
+
+ if (pri->sys_nargs < 1 || (offset = pri->sys_args[0]) == NULL)
+ return;
+
+ if (data_model == PR_MODEL_NATIVE) {
+ if (Pread(Proc, &ntv, sizeof (ntv), offset)
+ != sizeof (ntv))
+ return;
+ } else {
+ struct ntptimeval32 ntv32;
+
+ if (Pread(Proc, &ntv32, sizeof (ntv32), offset)
+ != sizeof (ntv32))
+ return;
+
+ TIMEVAL32_TO_TIMEVAL(&ntv.time, &ntv32.time);
+ ntv.maxerror = ntv32.maxerror;
+ ntv.esterror = ntv32.esterror;
+ }
+
+ (void) printf("\ttime: %ld.%6.6ld sec\n",
+ ntv.time.tv_sec, ntv.time.tv_usec);
+ (void) printf("\tmaxerror: %11d usec\n", ntv.maxerror);
+ (void) printf("\testerror: %11d usec\n", ntv.esterror);
+}
+
+static char *
+get_timex_modes(private_t *pri, uint32_t val)
+{
+ char *str = pri->code_buf;
+ size_t used = 0;
+
+ *str = '\0';
+ if (val & MOD_OFFSET)
+ used = strlcat(str, "|MOD_OFFSET", sizeof (pri->code_buf));
+ if (val & MOD_FREQUENCY)
+ used = strlcat(str, "|MOD_FREQUENCY", sizeof (pri->code_buf));
+ if (val & MOD_MAXERROR)
+ used = strlcat(str, "|MOD_MAXERROR", sizeof (pri->code_buf));
+ if (val & MOD_ESTERROR)
+ used = strlcat(str, "|MOD_ESTERROR", sizeof (pri->code_buf));
+ if (val & MOD_STATUS)
+ used = strlcat(str, "|MOD_STATUS", sizeof (pri->code_buf));
+ if (val & MOD_TIMECONST)
+ used = strlcat(str, "|MOD_TIMECONST", sizeof (pri->code_buf));
+ if (val & MOD_CLKB)
+ used = strlcat(str, "|MOD_CLKB", sizeof (pri->code_buf));
+ if (val & MOD_CLKA)
+ used = strlcat(str, "|MOD_CLKA", sizeof (pri->code_buf));
+
+ if (used == 0 || used >= sizeof (pri->code_buf))
+ (void) snprintf(str, sizeof (pri->code_buf), " 0x%.4x", val);
+
+ return (str + 1);
+}
+
+static char *
+get_timex_status(private_t *pri, int32_t val)
+{
+ char *str = pri->code_buf;
+ size_t used = 0;
+
+ *str = '\0';
+ if (val & STA_PLL)
+ used = strlcat(str, "|STA_PLL", sizeof (pri->code_buf));
+ if (val & STA_PPSFREQ)
+ used = strlcat(str, "|STA_PPSFREQ", sizeof (pri->code_buf));
+ if (val & STA_PPSTIME)
+ used = strlcat(str, "|STA_PPSTIME", sizeof (pri->code_buf));
+ if (val & STA_FLL)
+ used = strlcat(str, "|STA_FLL", sizeof (pri->code_buf));
+
+ if (val & STA_INS)
+ used = strlcat(str, "|STA_INS", sizeof (pri->code_buf));
+ if (val & STA_DEL)
+ used = strlcat(str, "|STA_DEL", sizeof (pri->code_buf));
+ if (val & STA_UNSYNC)
+ used = strlcat(str, "|STA_UNSYNC", sizeof (pri->code_buf));
+ if (val & STA_FREQHOLD)
+ used = strlcat(str, "|STA_FREQHOLD", sizeof (pri->code_buf));
+
+ if (val & STA_PPSSIGNAL)
+ used = strlcat(str, "|STA_PPSSIGNAL", sizeof (pri->code_buf));
+ if (val & STA_PPSJITTER)
+ used = strlcat(str, "|STA_PPSJITTER", sizeof (pri->code_buf));
+ if (val & STA_PPSWANDER)
+ used = strlcat(str, "|STA_PPSWANDER", sizeof (pri->code_buf));
+ if (val & STA_PPSERROR)
+ used = strlcat(str, "|STA_PPSERROR", sizeof (pri->code_buf));
+
+ if (val & STA_CLOCKERR)
+ used = strlcat(str, "|STA_CLOCKERR", sizeof (pri->code_buf));
+
+ if (used == 0 || used >= sizeof (pri->code_buf))
+ (void) snprintf(str, sizeof (pri->code_buf), " 0x%.4x", val);
+
+ return (str + 1);
+}
+
+void
+show_ntp_adjtime(private_t *pri)
+{
+ struct timex timex;
+ long offset;
+
+ if (pri->sys_nargs < 1 || (offset = pri->sys_args[0]) == NULL)
+ return;
+
+ if (Pread(Proc, &timex, sizeof (timex), offset) != sizeof (timex))
+ return;
+
+ (void) printf("\tmodes: %s\n", get_timex_modes(pri, timex.modes));
+ (void) printf("\toffset: %11d usec\n", timex.offset);
+ (void) printf("\tfreq: %11d scaled ppm\n", timex.freq);
+ (void) printf("\tmaxerror: %11d usec\n", timex.maxerror);
+ (void) printf("\testerror: %11d usec\n", timex.esterror);
+ (void) printf("\tstatus: %s\n", get_timex_status(pri, timex.status));
+ (void) printf("\tconstant: %11d\n", timex.constant);
+ (void) printf("\tprecision: %11d usec\n", timex.precision);
+ (void) printf("\ttolerance: %11d scaled ppm\n", timex.tolerance);
+ (void) printf("\tppsfreq: %11d scaled ppm\n", timex.ppsfreq);
+ (void) printf("\tjitter: %11d usec\n", timex.jitter);
+ (void) printf("\tshift: %11d sec\n", timex.shift);
+ (void) printf("\tstabil: %11d scaled ppm\n", timex.stabil);
+ (void) printf("\tjitcnt: %11d\n", timex.jitcnt);
+ (void) printf("\tcalcnt: %11d\n", timex.calcnt);
+ (void) printf("\terrcnt: %11d\n", timex.errcnt);
+ (void) printf("\tstbcnt: %11d\n", timex.stbcnt);
+}
+
+void
+show_getrusage(long offset)
+{
+ struct rusage r;
+ if (Pread(Proc, &r, sizeof (r), offset) != sizeof (r))
+ return;
+ (void) printf("\t user time: %ld.%6.6ld sec\n",
+ r.ru_utime.tv_sec,
+ r.ru_utime.tv_usec);
+ (void) printf("\t system time: %ld.%6.6ld sec\n",
+ r.ru_stime.tv_sec,
+ r.ru_stime.tv_usec);
+ (void) printf("\t max rss: <unimpl> %ld\n",
+ r.ru_maxrss);
+ (void) printf("\t shared data: <unimpl> %ld\n",
+ r.ru_ixrss);
+ (void) printf("\t unshared data: <unimpl> %ld\n",
+ r.ru_idrss);
+ (void) printf("\t unshared stack: <unimpl> %ld\n",
+ r.ru_isrss);
+ (void) printf("\t minor faults: %ld\n",
+ r.ru_minflt);
+ (void) printf("\t major faults: %ld\n",
+ r.ru_majflt);
+ (void) printf("\t # of swaps: %ld\n",
+ r.ru_nswap);
+ (void) printf("\t blocked inputs: %ld\n",
+ r.ru_inblock);
+ (void) printf("\t blocked outputs: %ld\n",
+ r.ru_oublock);
+ (void) printf("\t msgs sent: %ld\n",
+ r.ru_msgsnd);
+ (void) printf("\t msgs rcv'd: %ld\n",
+ r.ru_msgrcv);
+ (void) printf("\t signals rcv'd: %ld\n",
+ r.ru_nsignals);
+ (void) printf("\tvol cntxt swtchs: %ld\n",
+ r.ru_nvcsw);
+ (void) printf("\tinv cntxt swtchs: %ld\n",
+ r.ru_nivcsw);
+}
+
+#ifdef _LP64
+void
+show_getrusage32(long offset)
+{
+ struct rusage32 r;
+ if (Pread(Proc, &r, sizeof (r), offset) != sizeof (r))
+ return;
+ (void) printf("\t user time: %d.%6.6d sec\n",
+ r.ru_utime.tv_sec,
+ r.ru_utime.tv_usec);
+ (void) printf("\t system time: %d.%6.6d sec\n",
+ r.ru_stime.tv_sec,
+ r.ru_stime.tv_usec);
+ (void) printf("\t max rss: <unimpl> %d\n",
+ r.ru_maxrss);
+ (void) printf("\t shared data: <unimpl> %d\n",
+ r.ru_ixrss);
+ (void) printf("\t unshared data: <unimpl> %d\n",
+ r.ru_idrss);
+ (void) printf("\t unshared stack: <unimpl> %d\n",
+ r.ru_isrss);
+ (void) printf("\t minor faults: %d\n",
+ r.ru_minflt);
+ (void) printf("\t major faults: %d\n",
+ r.ru_majflt);
+ (void) printf("\t # of swaps: %d\n",
+ r.ru_nswap);
+ (void) printf("\t blocked inputs: %d\n",
+ r.ru_inblock);
+ (void) printf("\t blocked outputs: %d\n",
+ r.ru_oublock);
+ (void) printf("\t msgs sent: %d\n",
+ r.ru_msgsnd);
+ (void) printf("\t msgs rcv'd: %d\n",
+ r.ru_msgrcv);
+ (void) printf("\t signals rcv'd: %d\n",
+ r.ru_nsignals);
+ (void) printf("\tvol cntxt swtchs: %d\n",
+ r.ru_nvcsw);
+ (void) printf("\tinv cntxt swtchs: %d\n",
+ r.ru_nivcsw);
+}
+#endif
+
+/*
+ * Utility function to print a packed nvlist by unpacking
+ * and calling the libnvpair pretty printer. Frees all
+ * allocated memory internally.
+ */
+static void
+show_packed_nvlist(private_t *pri, uintptr_t offset, size_t size)
+{
+ nvlist_t *nvl = NULL;
+ size_t readsize;
+ char *buf;
+
+ if ((offset == 0) || (size == 0)) {
+ return;
+ }
+
+ buf = my_malloc(size, "nvlist decode buffer");
+ readsize = Pread(Proc, buf, size, offset);
+ if (readsize != size) {
+ (void) printf("%s\t<?>", pri->pname);
+ } else {
+ int result;
+
+ result = nvlist_unpack(buf, size, &nvl, 0);
+ if (result == 0) {
+ dump_nvlist(nvl, 8);
+ nvlist_free(nvl);
+ } else {
+ (void) printf("%s\tunpack of nvlist"
+ " failed: %d\n", pri->pname, result);
+ }
+ }
+ free(buf);
+}
+
+static void
+show_zone_create_args(private_t *pri, long offset)
+{
+ zone_def args;
+ char zone_name[ZONENAME_MAX];
+ char zone_root[MAXPATHLEN];
+ char *zone_zfs = NULL;
+
+ if (Pread(Proc, &args, sizeof (args), offset) == sizeof (args)) {
+
+ if (Pread_string(Proc, zone_name, sizeof (zone_name),
+ (uintptr_t)args.zone_name) == -1)
+ (void) strcpy(zone_name, "<?>");
+
+ if (Pread_string(Proc, zone_root, sizeof (zone_root),
+ (uintptr_t)args.zone_root) == -1)
+ (void) strcpy(zone_root, "<?>");
+
+ if (args.zfsbufsz > 0) {
+ zone_zfs = malloc(MIN(4, args.zfsbufsz));
+ if (zone_zfs != NULL) {
+ if (Pread(Proc, zone_zfs, args.zfsbufsz,
+ (uintptr_t)args.zfsbuf) == -1)
+ (void) strcpy(zone_zfs, "<?>");
+ }
+ } else {
+ zone_zfs = "";
+ }
+
+ (void) printf("%s\t zone_name: %s\n", pri->pname,
+ zone_name);
+ (void) printf("%s\t zone_root: %s\n", pri->pname,
+ zone_root);
+
+ show_privset(pri, (uintptr_t)args.zone_privs,
+ args.zone_privssz, " zone_privs: ");
+
+ (void) printf("%s\t rctlbuf: 0x%p\n", pri->pname,
+ (void *)args.rctlbuf);
+ (void) printf("%s\t rctlbufsz: %lu\n", pri->pname,
+ (ulong_t)args.rctlbufsz);
+
+ show_packed_nvlist(pri, (uintptr_t)args.rctlbuf,
+ args.rctlbufsz);
+
+ (void) printf("%s\t zfs: %s\n", pri->pname, zone_zfs);
+
+ (void) printf("%s\textended_error: 0x%p\n", pri->pname,
+ (void *)args.extended_error);
+
+ if (is_system_labeled()) {
+ char *label_str = NULL;
+ bslabel_t zone_label;
+
+ (void) printf("%s\t match: %d\n", pri->pname,
+ args.match);
+ (void) printf("%s\t doi: %d\n", pri->pname,
+ args.doi);
+
+ if (Pread_string(Proc, (char *)&zone_label,
+ sizeof (zone_label), (uintptr_t)args.label) != -1) {
+ /* show the label as string */
+ if (label_to_str(&zone_label, &label_str,
+ M_LABEL, SHORT_NAMES) != 0) {
+ /* have to dump label as raw string */
+ (void) label_to_str(&zone_label,
+ &label_str, M_INTERNAL,
+ SHORT_NAMES);
+ }
+ }
+
+ (void) printf("%s\t label: %s\n",
+ pri->pname, label_str != NULL ? label_str : "<?>");
+ if (label_str)
+ free(label_str);
+ }
+
+ if (args.zfsbufsz > 0)
+ free(zone_zfs);
+ }
+}
+
+
+#ifdef _LP64
+
+static void
+show_zone_create_args32(private_t *pri, long offset)
+{
+ zone_def32 args;
+ char zone_name[ZONENAME_MAX];
+ char zone_root[MAXPATHLEN];
+ char *zone_zfs = NULL;
+
+ if (Pread(Proc, &args, sizeof (args), offset) == sizeof (args)) {
+
+ if (Pread_string(Proc, zone_name, sizeof (zone_name),
+ (uintptr_t)args.zone_name) == -1)
+ (void) strcpy(zone_name, "<?>");
+
+ if (Pread_string(Proc, zone_root, sizeof (zone_root),
+ (uintptr_t)args.zone_root) == -1)
+ (void) strcpy(zone_root, "<?>");
+
+ if (args.zfsbufsz > 0) {
+ zone_zfs = malloc(MIN(4, args.zfsbufsz));
+ if (zone_zfs != NULL) {
+ if (Pread(Proc, zone_zfs, args.zfsbufsz,
+ (uintptr_t)args.zfsbuf) == -1)
+ (void) strcpy(zone_zfs, "<?>");
+ }
+ } else {
+ zone_zfs = "";
+ }
+
+ (void) printf("%s\t zone_name: %s\n", pri->pname,
+ zone_name);
+ (void) printf("%s\t zone_root: %s\n", pri->pname,
+ zone_root);
+
+ show_privset(pri, (uintptr_t)args.zone_privs,
+ args.zone_privssz, " zone_privs: ");
+
+ (void) printf("%s\t rctlbuf: 0x%x\n", pri->pname,
+ (caddr32_t)args.rctlbuf);
+ (void) printf("%s\t rctlbufsz: %lu\n", pri->pname,
+ (ulong_t)args.rctlbufsz);
+
+ show_packed_nvlist(pri, (uintptr_t)args.rctlbuf,
+ args.rctlbufsz);
+
+ (void) printf("%s\t zfs: %s\n", pri->pname, zone_zfs);
+
+ (void) printf("%s\textended_error: 0x%x\n", pri->pname,
+ (caddr32_t)args.extended_error);
+
+ if (is_system_labeled()) {
+ char *label_str = NULL;
+ bslabel_t zone_label;
+
+ (void) printf("%s\t match: %d\n", pri->pname,
+ args.match);
+ (void) printf("%s\t doi: %d\n", pri->pname,
+ args.doi);
+
+ if (Pread_string(Proc, (char *)&zone_label,
+ sizeof (zone_label), (caddr32_t)args.label) != -1) {
+ /* show the label as string */
+ if (label_to_str(&zone_label, &label_str,
+ M_LABEL, SHORT_NAMES) != 0) {
+ /* have to dump label as raw string */
+ (void) label_to_str(&zone_label,
+ &label_str, M_INTERNAL,
+ SHORT_NAMES);
+ }
+ }
+ (void) printf("%s\t label: %s\n",
+ pri->pname, label_str != NULL ? label_str : "<?>");
+ if (label_str)
+ free(label_str);
+ }
+
+ if (args.zfsbufsz > 0)
+ free(zone_zfs);
+ }
+}
+
+#endif
+
+static void
+show_zones(private_t *pri)
+{
+ switch (pri->sys_args[0]) {
+ case ZONE_CREATE:
+#ifdef _LP64
+ if (data_model == PR_MODEL_LP64)
+ show_zone_create_args(pri, (long)pri->sys_args[1]);
+ else
+ show_zone_create_args32(pri, (long)pri->sys_args[1]);
+#else
+ show_zone_create_args(pri, (long)pri->sys_args[1]);
+#endif
+ break;
+ }
+}
+
+static void
+show_rctlblk(private_t *pri, long _rctlblk)
+{
+ rctlblk_t *blk;
+ int size = rctlblk_size();
+ size_t readsize;
+ const char *s;
+
+ blk = my_malloc(size, "rctlblk decode buffer");
+ readsize = Pread(Proc, blk, size, _rctlblk);
+ if (readsize != size) {
+ (void) printf("%s\t\t<?>", pri->pname);
+ } else {
+ (void) printf("%s\t\t Privilege: 0x%x\n",
+ pri->pname,
+ rctlblk_get_privilege(blk));
+ (void) printf("%s\t\t Value: %lld\n",
+ pri->pname,
+ rctlblk_get_value(blk));
+ (void) printf("%s\t\tEnforced Value: %lld\n",
+ pri->pname,
+ rctlblk_get_enforced_value(blk));
+
+ {
+ int sig, act;
+ act = rctlblk_get_local_action(blk, &sig);
+
+ s = rctl_local_action(pri, act);
+ if (s == NULL) {
+ (void) printf("%s\t\t Local action: 0x%x\n",
+ pri->pname, act);
+ } else {
+ (void) printf("%s\t\t Local action: %s\n",
+ pri->pname, s);
+ }
+
+ if (act & RCTL_LOCAL_SIGNAL) {
+ (void) printf("%s\t\t "
+ "For signal %s\n",
+ pri->pname, signame(pri, sig));
+ }
+ }
+
+ s = rctl_local_flags(pri, rctlblk_get_local_flags(blk));
+ if (s == NULL) {
+ (void) printf("%s\t\t Local flags: 0x%x\n",
+ pri->pname, rctlblk_get_local_flags(blk));
+ } else {
+ (void) printf("%s\t\t Local flags: %s\n",
+ pri->pname, s);
+ }
+
+#ifdef _LP64
+ (void) printf("%s\t\t Recipient PID: %d\n",
+ pri->pname,
+ rctlblk_get_recipient_pid(blk));
+#else
+ (void) printf("%s\t\t Recipient PID: %ld\n",
+ pri->pname,
+ rctlblk_get_recipient_pid(blk));
+#endif
+ (void) printf("%s\t\t Firing Time: %lld\n",
+ pri->pname,
+ rctlblk_get_firing_time(blk));
+ }
+ free(blk);
+}
+
+static void
+show_rctls(private_t *pri)
+{
+ int entry;
+
+ switch (pri->sys_args[0]) {
+ case 0: /* getrctl */
+ case 1: /* setrctl */
+ /*
+ * If these offsets look a little odd, remember that they're
+ * into the _raw_ system call
+ */
+ (void) printf("%s\tOld rctlblk: 0x%lx\n", pri->pname,
+ pri->sys_args[2]);
+ if (pri->sys_args[2] != NULL) {
+ show_rctlblk(pri, pri->sys_args[2]);
+ }
+ (void) printf("%s\tNew rctlblk: 0x%lx\n", pri->pname,
+ pri->sys_args[3]);
+ if (pri->sys_args[3] != NULL) {
+ show_rctlblk(pri, pri->sys_args[3]);
+ }
+ break;
+ case 4: /* setprojrctl */
+ for (entry = 0; entry < pri->sys_args[4]; entry++) {
+ (void) printf("%s\tNew rctlblk[%d]: 0x%lx\n",
+ pri->pname, entry,
+ (long)RCTLBLK_INC(pri->sys_args[3], entry));
+ if (RCTLBLK_INC(pri->sys_args[3], entry) != NULL) {
+ show_rctlblk(pri,
+ (long)RCTLBLK_INC(pri->sys_args[3], entry));
+ }
+ }
+ }
+}
+
+void
+show_utimesys(private_t *pri)
+{
+ switch (pri->sys_args[0]) {
+ case 0: /* futimens() */
+ if (pri->sys_nargs > 2)
+ show_utimens(pri, (long)pri->sys_args[2]);
+ break;
+ case 1: /* utimensat */
+ if (pri->sys_nargs > 3)
+ show_utimens(pri, (long)pri->sys_args[3]);
+ break;
+ default: /* unexpected subcode */
+ break;
+ }
+}
+
+#ifdef _LP64
+static void
+show_sockconfig_filter_prop32(private_t *pri, long addr)
+{
+ struct sockconfig_filter_props32 props;
+ const char *s = NULL;
+ char buf[MAX(FILNAME_MAX, MODMAXNAMELEN)];
+ sof_socktuple32_t *tup;
+ size_t sz;
+ int i;
+
+ if (Pread(Proc, &props, sizeof (props), addr) == sizeof (props)) {
+ if (Pread_string(Proc, buf, sizeof (buf),
+ (uintptr_t)props.sfp_modname) == -1)
+ (void) strcpy(buf, "<?>");
+ (void) printf("%s\tmodule name: %s\n", pri->pname, buf);
+ (void) printf("%s\tattach semantics: %s", pri->pname,
+ props.sfp_autoattach ? "automatic" : "progammatic");
+ if (props.sfp_autoattach) {
+ buf[0] = '\0';
+ switch (props.sfp_hint) {
+ case SOF_HINT_TOP: s = "top"; break;
+ case SOF_HINT_BOTTOM: s = "bottom"; break;
+ case SOF_HINT_BEFORE:
+ case SOF_HINT_AFTER:
+ s = (props.sfp_hint == SOF_HINT_BEFORE) ?
+ "before" : "after";
+ if (Pread_string(Proc, buf, sizeof (buf),
+ (uintptr_t)props.sfp_hintarg) == -1)
+ (void) strcpy(buf, "<?>");
+ }
+ if (s != NULL) {
+ (void) printf(", placement: %s %s", s, buf);
+ }
+ }
+ (void) printf("\n");
+ (void) printf("%s\tsocket tuples:\n", pri->pname);
+ if (props.sfp_socktuple_cnt == 0) {
+ (void) printf("\t\t<empty>\n");
+ return;
+ }
+ sz = props.sfp_socktuple_cnt * sizeof (*tup);
+ tup = my_malloc(sz, "socket tuple buffer");
+ if (Pread(Proc, tup, sz, (uintptr_t)props.sfp_socktuple) == sz)
+ for (i = 0; i < props.sfp_socktuple_cnt; i++) {
+ (void) printf(
+ "\t\tfamily: %d, type: %d, proto: %d\n",
+ tup[i].sofst_family, tup[i].sofst_type,
+ tup[i].sofst_protocol);
+ }
+ }
+}
+#endif /* _LP64 */
+static void
+show_sockconfig_filter_prop(private_t *pri, long addr)
+{
+ struct sockconfig_filter_props props;
+ const char *s = NULL;
+ char buf[MAX(FILNAME_MAX, MODMAXNAMELEN)];
+ sof_socktuple_t *tup;
+ size_t sz;
+ int i;
+
+ if (Pread(Proc, &props, sizeof (props), addr) == sizeof (props)) {
+ if (Pread_string(Proc, buf, sizeof (buf),
+ (uintptr_t)props.sfp_modname) == -1)
+ (void) strcpy(buf, "<?>");
+ (void) printf("%s\tmodule name: %s\n", pri->pname, buf);
+ (void) printf("%s\tattach semantics: %s", pri->pname,
+ props.sfp_autoattach ? "automatic" : "progammatic");
+ if (props.sfp_autoattach) {
+ buf[0] = '\0';
+ switch (props.sfp_hint) {
+ case SOF_HINT_TOP: s = "top"; break;
+ case SOF_HINT_BOTTOM: s = "bottom"; break;
+ case SOF_HINT_BEFORE:
+ case SOF_HINT_AFTER:
+ s = (props.sfp_hint == SOF_HINT_BEFORE) ?
+ "before" : "after";
+ if (Pread_string(Proc, buf, sizeof (buf),
+ (uintptr_t)props.sfp_hintarg) == -1)
+ (void) strcpy(buf, "<?>");
+ }
+ if (s != NULL) {
+ (void) printf(", placement: %s", s);
+ }
+ }
+ (void) printf("\n");
+ (void) printf("%s\tsocket tuples:\n", pri->pname);
+ if (props.sfp_socktuple_cnt == 0) {
+ (void) printf("\t\t<empty>\n");
+ return;
+ }
+ sz = props.sfp_socktuple_cnt * sizeof (*tup);
+ tup = my_malloc(sz, "socket tuple buffer");
+ if (Pread(Proc, tup, sz, (uintptr_t)props.sfp_socktuple) == sz)
+ for (i = 0; i < props.sfp_socktuple_cnt; i++) {
+ (void) printf(
+ "\t\tfamily: %d, type: %d, proto: %d\n",
+ tup[i].sofst_family, tup[i].sofst_type,
+ tup[i].sofst_protocol);
+ }
+ }
+}
+
+void
+show_sockconfig(private_t *pri)
+{
+ switch (pri->sys_args[0]) {
+ case SOCKCONFIG_ADD_FILTER:
+#ifdef _LP64
+ if (data_model == PR_MODEL_LP64)
+ show_sockconfig_filter_prop(pri,
+ (long)pri->sys_args[2]);
+ else
+ show_sockconfig_filter_prop32(pri,
+ (long)pri->sys_args[2]);
+#else
+ show_sockconfig_filter_prop(pri, (long)pri->sys_args[2]);
+#endif
+ break;
+ default:
+ break;
+ }
+}
+
+void
+show_zfs_ioc(private_t *pri, long addr)
+{
+ static const zfs_share_t zero_share = {0};
+ static const dmu_objset_stats_t zero_objstats = {0};
+ static const struct drr_begin zero_drrbegin = {0};
+ static const zinject_record_t zero_injectrec = {0};
+ static const zfs_stat_t zero_zstat = {0};
+ zfs_cmd_t zc;
+
+ if (Pread(Proc, &zc, sizeof (zc), addr) != sizeof (zc)) {
+ (void) printf(" zfs_ioctl read failed\n");
+ return;
+ }
+
+ if (zc.zc_name[0])
+ (void) printf(" zc_name=%s\n", zc.zc_name);
+ if (zc.zc_value[0])
+ (void) printf(" zc_value=%s\n", zc.zc_value);
+ if (zc.zc_string[0])
+ (void) printf(" zc_string=%s\n", zc.zc_string);
+ if (zc.zc_guid != 0) {
+ (void) printf(" zc_guid=%llu\n",
+ (u_longlong_t)zc.zc_guid);
+ }
+ if (zc.zc_nvlist_conf_size) {
+ (void) printf(" nvlist_conf:\n");
+ show_packed_nvlist(pri, zc.zc_nvlist_conf,
+ zc.zc_nvlist_conf_size);
+ }
+ if (zc.zc_nvlist_src_size) {
+ (void) printf(" nvlist_src:\n");
+ show_packed_nvlist(pri, zc.zc_nvlist_src,
+ zc.zc_nvlist_src_size);
+ }
+ if (zc.zc_nvlist_dst_size) {
+ (void) printf(" nvlist_dst:\n");
+ show_packed_nvlist(pri, zc.zc_nvlist_dst,
+ zc.zc_nvlist_dst_size);
+ }
+ if (zc.zc_cookie != 0) {
+ (void) printf(" zc_cookie=%llu\n",
+ (u_longlong_t)zc.zc_cookie);
+ }
+ if (zc.zc_objset_type != 0) {
+ (void) printf(" zc_objset_type=%llu\n",
+ (u_longlong_t)zc.zc_objset_type);
+ }
+ if (zc.zc_perm_action != 0) {
+ (void) printf(" zc_perm_action=%llu\n",
+ (u_longlong_t)zc.zc_perm_action);
+ }
+ if (zc.zc_history != 0) {
+ (void) printf(" zc_history=%llu\n",
+ (u_longlong_t)zc.zc_history);
+ }
+ if (zc.zc_obj != 0) {
+ (void) printf(" zc_obj=%llu\n",
+ (u_longlong_t)zc.zc_obj);
+ }
+ if (zc.zc_iflags != 0) {
+ (void) printf(" zc_obj=0x%llx\n",
+ (u_longlong_t)zc.zc_iflags);
+ }
+
+ if (memcmp(&zc.zc_share, &zero_share, sizeof (zc.zc_share))) {
+ zfs_share_t *z = &zc.zc_share;
+ (void) printf(" zc_share:\n");
+ if (z->z_exportdata) {
+ (void) printf("\tz_exportdata=0x%llx\n",
+ (u_longlong_t)z->z_exportdata);
+ }
+ if (z->z_sharedata) {
+ (void) printf("\tz_sharedata=0x%llx\n",
+ (u_longlong_t)z->z_sharedata);
+ }
+ if (z->z_sharetype) {
+ (void) printf("\tz_sharetype=%llu\n",
+ (u_longlong_t)z->z_sharetype);
+ }
+ if (z->z_sharemax) {
+ (void) printf("\tz_sharemax=%llu\n",
+ (u_longlong_t)z->z_sharemax);
+ }
+ }
+
+ if (memcmp(&zc.zc_objset_stats, &zero_objstats,
+ sizeof (zc.zc_objset_stats))) {
+ dmu_objset_stats_t *dds = &zc.zc_objset_stats;
+ (void) printf(" zc_objset_stats:\n");
+ if (dds->dds_num_clones) {
+ (void) printf("\tdds_num_clones=%llu\n",
+ (u_longlong_t)dds->dds_num_clones);
+ }
+ if (dds->dds_creation_txg) {
+ (void) printf("\tdds_creation_txg=%llu\n",
+ (u_longlong_t)dds->dds_creation_txg);
+ }
+ if (dds->dds_guid) {
+ (void) printf("\tdds_guid=%llu\n",
+ (u_longlong_t)dds->dds_guid);
+ }
+ if (dds->dds_type)
+ (void) printf("\tdds_type=%u\n", dds->dds_type);
+ if (dds->dds_is_snapshot) {
+ (void) printf("\tdds_is_snapshot=%u\n",
+ dds->dds_is_snapshot);
+ }
+ if (dds->dds_inconsistent) {
+ (void) printf("\tdds_inconsitent=%u\n",
+ dds->dds_inconsistent);
+ }
+ if (dds->dds_origin[0]) {
+ (void) printf("\tdds_origin=%s\n", dds->dds_origin);
+ }
+ }
+
+ if (memcmp(&zc.zc_begin_record, &zero_drrbegin,
+ sizeof (zc.zc_begin_record))) {
+ struct drr_begin *drr = &zc.zc_begin_record;
+ (void) printf(" zc_begin_record:\n");
+ if (drr->drr_magic) {
+ (void) printf("\tdrr_magic=%llu\n",
+ (u_longlong_t)drr->drr_magic);
+ }
+ if (drr->drr_versioninfo) {
+ (void) printf("\tdrr_versioninfo=%llu\n",
+ (u_longlong_t)drr->drr_versioninfo);
+ }
+ if (drr->drr_creation_time) {
+ (void) printf("\tdrr_creation_time=%llu\n",
+ (u_longlong_t)drr->drr_creation_time);
+ }
+ if (drr->drr_type)
+ (void) printf("\tdrr_type=%u\n", drr->drr_type);
+ if (drr->drr_flags)
+ (void) printf("\tdrr_flags=0x%x\n", drr->drr_flags);
+ if (drr->drr_toguid) {
+ (void) printf("\tdrr_toguid=%llu\n",
+ (u_longlong_t)drr->drr_toguid);
+ }
+ if (drr->drr_fromguid) {
+ (void) printf("\tdrr_fromguid=%llu\n",
+ (u_longlong_t)drr->drr_fromguid);
+ }
+ if (drr->drr_toname[0]) {
+ (void) printf("\tdrr_toname=%s\n", drr->drr_toname);
+ }
+ }
+
+ if (memcmp(&zc.zc_inject_record, &zero_injectrec,
+ sizeof (zc.zc_inject_record))) {
+ zinject_record_t *zi = &zc.zc_inject_record;
+ (void) printf(" zc_inject_record:\n");
+ if (zi->zi_objset) {
+ (void) printf("\tzi_objset=%llu\n",
+ (u_longlong_t)zi->zi_objset);
+ }
+ if (zi->zi_object) {
+ (void) printf("\tzi_object=%llu\n",
+ (u_longlong_t)zi->zi_object);
+ }
+ if (zi->zi_start) {
+ (void) printf("\tzi_start=%llu\n",
+ (u_longlong_t)zi->zi_start);
+ }
+ if (zi->zi_end) {
+ (void) printf("\tzi_end=%llu\n",
+ (u_longlong_t)zi->zi_end);
+ }
+ if (zi->zi_guid) {
+ (void) printf("\tzi_guid=%llu\n",
+ (u_longlong_t)zi->zi_guid);
+ }
+ if (zi->zi_level) {
+ (void) printf("\tzi_level=%lu\n",
+ (ulong_t)zi->zi_level);
+ }
+ if (zi->zi_error) {
+ (void) printf("\tzi_error=%lu\n",
+ (ulong_t)zi->zi_error);
+ }
+ if (zi->zi_type) {
+ (void) printf("\tzi_type=%llu\n",
+ (u_longlong_t)zi->zi_type);
+ }
+ if (zi->zi_freq) {
+ (void) printf("\tzi_freq=%lu\n",
+ (ulong_t)zi->zi_freq);
+ }
+ if (zi->zi_failfast) {
+ (void) printf("\tzi_failfast=%lu\n",
+ (ulong_t)zi->zi_failfast);
+ }
+ if (zi->zi_func[0])
+ (void) printf("\tzi_func=%s\n", zi->zi_func);
+ if (zi->zi_iotype) {
+ (void) printf("\tzi_iotype=%lu\n",
+ (ulong_t)zi->zi_iotype);
+ }
+ if (zi->zi_duration) {
+ (void) printf("\tzi_duration=%ld\n",
+ (long)zi->zi_duration);
+ }
+ if (zi->zi_timer) {
+ (void) printf("\tzi_timer=%llu\n",
+ (u_longlong_t)zi->zi_timer);
+ }
+ }
+
+ if (zc.zc_defer_destroy) {
+ (void) printf(" zc_defer_destroy=%d\n",
+ (int)zc.zc_defer_destroy);
+ }
+ if (zc.zc_flags) {
+ (void) printf(" zc_flags=0x%x\n",
+ zc.zc_flags);
+ }
+ if (zc.zc_action_handle) {
+ (void) printf(" zc_action_handle=%llu\n",
+ (u_longlong_t)zc.zc_action_handle);
+ }
+ if (zc.zc_cleanup_fd >= 0)
+ (void) printf(" zc_cleanup_fd=%d\n", zc.zc_cleanup_fd);
+ if (zc.zc_sendobj) {
+ (void) printf(" zc_sendobj=%llu\n",
+ (u_longlong_t)zc.zc_sendobj);
+ }
+ if (zc.zc_fromobj) {
+ (void) printf(" zc_fromobj=%llu\n",
+ (u_longlong_t)zc.zc_fromobj);
+ }
+ if (zc.zc_createtxg) {
+ (void) printf(" zc_createtxg=%llu\n",
+ (u_longlong_t)zc.zc_createtxg);
+ }
+
+ if (memcmp(&zc.zc_stat, &zero_zstat, sizeof (zc.zc_stat))) {
+ zfs_stat_t *zs = &zc.zc_stat;
+ (void) printf(" zc_stat:\n");
+ if (zs->zs_gen) {
+ (void) printf("\tzs_gen=%llu\n",
+ (u_longlong_t)zs->zs_gen);
+ }
+ if (zs->zs_mode) {
+ (void) printf("\tzs_mode=%llu\n",
+ (u_longlong_t)zs->zs_mode);
+ }
+ if (zs->zs_links) {
+ (void) printf("\tzs_links=%llu\n",
+ (u_longlong_t)zs->zs_links);
+ }
+ if (zs->zs_ctime[0]) {
+ (void) printf("\tzs_ctime[0]=%llu\n",
+ (u_longlong_t)zs->zs_ctime[0]);
+ }
+ if (zs->zs_ctime[1]) {
+ (void) printf("\tzs_ctime[1]=%llu\n",
+ (u_longlong_t)zs->zs_ctime[1]);
+ }
+ }
+}
+
+/* expound verbosely upon syscall arguments */
+/*ARGSUSED*/
+void
+expound(private_t *pri, long r0, int raw)
+{
+ const lwpstatus_t *Lsp = pri->lwpstat;
+ int lp64 = (data_model == PR_MODEL_LP64);
+ int what = Lsp->pr_what;
+ int err = pri->Errno; /* don't display output parameters */
+ /* for a failed system call */
+#ifndef _LP64
+ /* We are a 32-bit truss; we can't grok a 64-bit process */
+ if (lp64)
+ return;
+#endif
+ /* for reporting sleeping system calls */
+ if (what == 0 && (Lsp->pr_flags & (PR_ASLEEP|PR_VFORKP)))
+ what = Lsp->pr_syscall;
+
+ switch (what) {
+ case SYS_gettimeofday:
+ if (!err)
+ show_timeofday(pri);
+ break;
+ case SYS_getitimer:
+ if (!err && pri->sys_nargs > 1)
+ show_itimerval(pri, (long)pri->sys_args[1],
+ " value");
+ break;
+ case SYS_setitimer:
+ if (pri->sys_nargs > 1)
+ show_itimerval(pri, (long)pri->sys_args[1],
+ " value");
+ if (!err && pri->sys_nargs > 2)
+ show_itimerval(pri, (long)pri->sys_args[2],
+ "ovalue");
+ break;
+ case SYS_stime:
+ show_stime(pri);
+ break;
+ case SYS_times:
+ if (!err)
+ show_times(pri);
+ break;
+ case SYS_utssys:
+ if (err)
+ break;
+#ifdef _LP64
+ if (lp64)
+ show_utssys(pri, r0);
+ else
+ show_utssys32(pri, r0);
+#else
+ show_utssys(pri, r0);
+#endif
+ break;
+ case SYS_ioctl:
+ if (pri->sys_nargs >= 3) /* each case must decide for itself */
+ show_ioctl(pri, pri->sys_args[1],
+ (long)pri->sys_args[2]);
+ break;
+ case SYS_fstatat:
+ if (!err && pri->sys_nargs >= 3)
+ show_stat(pri, (long)pri->sys_args[2]);
+ break;
+ case SYS_fstatat64:
+ if (!err && pri->sys_nargs >= 3)
+ show_stat64_32(pri, (long)pri->sys_args[2]);
+ break;
+ case SYS_stat:
+ case SYS_fstat:
+ case SYS_lstat:
+ if (!err && pri->sys_nargs >= 2)
+ show_stat(pri, (long)pri->sys_args[1]);
+ break;
+ case SYS_stat64:
+ case SYS_fstat64:
+ case SYS_lstat64:
+ if (!err && pri->sys_nargs >= 2)
+ show_stat64_32(pri, (long)pri->sys_args[1]);
+ break;
+ case SYS_statvfs:
+ case SYS_fstatvfs:
+ if (err)
+ break;
+#ifdef _LP64
+ if (!lp64) {
+ show_statvfs32(pri);
+ break;
+ }
+#endif
+ show_statvfs(pri);
+ break;
+ case SYS_statvfs64:
+ case SYS_fstatvfs64:
+ if (err)
+ break;
+ show_statvfs64(pri);
+ break;
+ case SYS_statfs:
+ case SYS_fstatfs:
+ if (err)
+ break;
+#ifdef _LP64
+ if (lp64)
+ show_statfs(pri);
+ else
+ show_statfs32(pri);
+#else
+ show_statfs(pri);
+#endif
+ break;
+ case SYS_fcntl:
+ show_fcntl(pri);
+ break;
+ case SYS_msgsys:
+ show_msgsys(pri, r0); /* each case must decide for itself */
+ break;
+ case SYS_semsys:
+ show_semsys(pri); /* each case must decide for itself */
+ break;
+ case SYS_shmsys:
+ show_shmsys(pri); /* each case must decide for itself */
+ break;
+ case SYS_getdents:
+ if (err || pri->sys_nargs <= 1 || r0 <= 0)
+ break;
+#ifdef _LP64
+ if (!lp64) {
+ show_dents32(pri, (long)pri->sys_args[1], r0);
+ break;
+ }
+ /* FALLTHROUGH */
+#else
+ show_dents32(pri, (long)pri->sys_args[1], r0);
+ break;
+#endif
+ case SYS_getdents64:
+ if (err || pri->sys_nargs <= 1 || r0 <= 0)
+ break;
+ show_dents64(pri, (long)pri->sys_args[1], r0);
+ break;
+ case SYS_getmsg:
+ show_gp_msg(pri, what);
+ if (pri->sys_nargs > 3)
+ show_hhex_int(pri, (long)pri->sys_args[3], "flags");
+ break;
+ case SYS_getpmsg:
+ show_gp_msg(pri, what);
+ if (pri->sys_nargs > 3)
+ show_hhex_int(pri, (long)pri->sys_args[3], "band");
+ if (pri->sys_nargs > 4)
+ show_hhex_int(pri, (long)pri->sys_args[4], "flags");
+ break;
+ case SYS_putmsg:
+ case SYS_putpmsg:
+ show_gp_msg(pri, what);
+ break;
+ case SYS_pollsys:
+ show_pollsys(pri);
+ break;
+ case SYS_setgroups:
+ if (pri->sys_nargs > 1 && (r0 = pri->sys_args[0]) > 0)
+ show_groups(pri, (long)pri->sys_args[1], r0);
+ break;
+ case SYS_getgroups:
+ if (!err && pri->sys_nargs > 1 && pri->sys_args[0] > 0)
+ show_groups(pri, (long)pri->sys_args[1], r0);
+ break;
+ case SYS_sigprocmask:
+ if (pri->sys_nargs > 1)
+ show_sigset(pri, (long)pri->sys_args[1], " set");
+ if (!err && pri->sys_nargs > 2)
+ show_sigset(pri, (long)pri->sys_args[2], "oset");
+ break;
+ case SYS_sigsuspend:
+ case SYS_sigtimedwait:
+ if (pri->sys_nargs > 0)
+ show_sigset(pri, (long)pri->sys_args[0], "sigmask");
+ if (!err && pri->sys_nargs > 1)
+ show_siginfo(pri, (long)pri->sys_args[1]);
+ if (pri->sys_nargs > 2)
+ show_timestruc(pri, (long)pri->sys_args[2], "timeout");
+ break;
+ case SYS_sigaltstack:
+ if (pri->sys_nargs > 0)
+ show_sigaltstack(pri, (long)pri->sys_args[0],
+ "new");
+ if (!err && pri->sys_nargs > 1)
+ show_sigaltstack(pri, (long)pri->sys_args[1],
+ "old");
+ break;
+ case SYS_sigaction:
+ if (pri->sys_nargs > 1)
+ show_sigaction(pri, (long)pri->sys_args[1],
+ "new", NULL);
+ if (!err && pri->sys_nargs > 2)
+ show_sigaction(pri, (long)pri->sys_args[2],
+ "old", r0);
+ break;
+ case SYS_signotify:
+ if (pri->sys_nargs > 1)
+ show_siginfo(pri, (long)pri->sys_args[1]);
+ break;
+ case SYS_sigresend:
+ if (pri->sys_nargs > 1)
+ show_siginfo(pri, (long)pri->sys_args[1]);
+ if (pri->sys_nargs > 2)
+ show_sigset(pri, (long)pri->sys_args[2], "sigmask");
+ break;
+ case SYS_sigpending:
+ if (!err && pri->sys_nargs > 1)
+ show_sigset(pri, (long)pri->sys_args[1], "sigmask");
+ break;
+ case SYS_waitid:
+ if (!err && pri->sys_nargs > 2)
+ show_siginfo(pri, (long)pri->sys_args[2]);
+ break;
+ case SYS_sigsendsys:
+ if (pri->sys_nargs > 0)
+ show_procset(pri, (long)pri->sys_args[0]);
+ break;
+ case SYS_priocntlsys:
+ if (pri->sys_nargs > 1)
+ show_procset(pri, (long)pri->sys_args[1]);
+ break;
+ case SYS_mincore:
+ if (!err && pri->sys_nargs > 2)
+ show_bool(pri, (long)pri->sys_args[2],
+ (pri->sys_args[1] + pagesize - 1) / pagesize);
+ break;
+ case SYS_readv:
+ case SYS_writev:
+ if (pri->sys_nargs > 2) {
+ int i = pri->sys_args[0]+1;
+ int showbuf = FALSE;
+ long nb = (what == SYS_readv)? r0 : 32*1024;
+
+ if ((what == SYS_readv && !err &&
+ prismember(&readfd, i)) ||
+ (what == SYS_writev &&
+ prismember(&writefd, i)))
+ showbuf = TRUE;
+ show_iovec(pri, (long)pri->sys_args[1],
+ pri->sys_args[2], showbuf, nb);
+ }
+ break;
+ case SYS_getrlimit:
+ if (err)
+ break;
+ /*FALLTHROUGH*/
+ case SYS_setrlimit:
+ if (pri->sys_nargs <= 1)
+ break;
+#ifdef _LP64
+ if (lp64)
+ show_rlimit64(pri, (long)pri->sys_args[1]);
+ else
+ show_rlimit32(pri, (long)pri->sys_args[1]);
+#else
+ show_rlimit32(pri, (long)pri->sys_args[1]);
+#endif
+ break;
+ case SYS_getrlimit64:
+ if (err)
+ break;
+ /*FALLTHROUGH*/
+ case SYS_setrlimit64:
+ if (pri->sys_nargs <= 1)
+ break;
+ show_rlimit64(pri, (long)pri->sys_args[1]);
+ break;
+ case SYS_uname:
+ if (!err && pri->sys_nargs > 0)
+ show_nuname(pri, (long)pri->sys_args[0]);
+ break;
+ case SYS_adjtime:
+ if (!err && pri->sys_nargs > 1)
+ show_adjtime(pri, (long)pri->sys_args[0],
+ (long)pri->sys_args[1]);
+ break;
+ case SYS_lwp_info:
+ if (!err && pri->sys_nargs > 0)
+ show_timestruc(pri, (long)pri->sys_args[0], "cpu time");
+ break;
+ case SYS_lwp_wait:
+ if (!err && pri->sys_nargs > 1)
+ show_int(pri, (long)pri->sys_args[1], "lwpid");
+ break;
+ case SYS_lwp_mutex_wakeup:
+ case SYS_lwp_mutex_unlock:
+ case SYS_lwp_mutex_trylock:
+ case SYS_lwp_mutex_register:
+ if (pri->sys_nargs > 0)
+ show_mutex(pri, (long)pri->sys_args[0]);
+ break;
+ case SYS_lwp_mutex_timedlock:
+ if (pri->sys_nargs > 0)
+ show_mutex(pri, (long)pri->sys_args[0]);
+ if (pri->sys_nargs > 1)
+ show_timestruc(pri, (long)pri->sys_args[1], "timeout");
+ break;
+ case SYS_lwp_cond_wait:
+ if (pri->sys_nargs > 0)
+ show_condvar(pri, (long)pri->sys_args[0]);
+ if (pri->sys_nargs > 1)
+ show_mutex(pri, (long)pri->sys_args[1]);
+ if (pri->sys_nargs > 2)
+ show_timestruc(pri, (long)pri->sys_args[2], "timeout");
+ break;
+ case SYS_lwp_cond_signal:
+ case SYS_lwp_cond_broadcast:
+ if (pri->sys_nargs > 0)
+ show_condvar(pri, (long)pri->sys_args[0]);
+ break;
+ case SYS_lwp_sema_trywait:
+ case SYS_lwp_sema_post:
+ if (pri->sys_nargs > 0)
+ show_sema(pri, (long)pri->sys_args[0]);
+ break;
+ case SYS_lwp_sema_timedwait:
+ if (pri->sys_nargs > 0)
+ show_sema(pri, (long)pri->sys_args[0]);
+ if (pri->sys_nargs > 1)
+ show_timestruc(pri, (long)pri->sys_args[1], "timeout");
+ break;
+ case SYS_lwp_rwlock_sys:
+ if (pri->sys_nargs > 1)
+ show_rwlock(pri, (long)pri->sys_args[1]);
+ if (pri->sys_nargs > 2 &&
+ (pri->sys_args[0] == 0 || pri->sys_args[0] == 1))
+ show_timestruc(pri, (long)pri->sys_args[2], "timeout");
+ break;
+ case SYS_lwp_create:
+ /* XXX print some values in ucontext ??? */
+ if (!err && pri->sys_nargs > 2)
+ show_int(pri, (long)pri->sys_args[2], "lwpid");
+ break;
+ case SYS_kaio:
+ if (pri->sys_args[0] == AIOWAIT && !err && pri->sys_nargs > 1)
+ show_timeval(pri, (long)pri->sys_args[1], "timeout");
+ break;
+ case SYS_nanosleep:
+ if (pri->sys_nargs > 0)
+ show_timestruc(pri, (long)pri->sys_args[0], "tmout");
+ if (pri->sys_nargs > 1 && (err == 0 || err == EINTR))
+ show_timestruc(pri, (long)pri->sys_args[1], "resid");
+ break;
+ case SYS_privsys:
+ switch (pri->sys_args[0]) {
+ case PRIVSYS_SETPPRIV:
+ case PRIVSYS_GETPPRIV:
+ if (!err)
+ show_privset(pri, (long)pri->sys_args[3],
+ (size_t)pri->sys_args[4], "");
+ }
+ break;
+ case SYS_ucredsys:
+ switch (pri->sys_args[0]) {
+ case UCREDSYS_UCREDGET:
+ case UCREDSYS_GETPEERUCRED:
+ if (err == 0)
+ show_ucred(pri, (long)pri->sys_args[2]);
+ break;
+ }
+ break;
+ case SYS_bind:
+ case SYS_connect:
+ if (pri->sys_nargs > 2)
+ show_sockaddr(pri, "name", (long)pri->sys_args[1],
+ 0, (long)pri->sys_args[2]);
+ break;
+ case SYS_sendto:
+ if (pri->sys_nargs > 5)
+ show_sockaddr(pri, "to", (long)pri->sys_args[4], 0,
+ pri->sys_args[5]);
+ break;
+ case SYS_accept:
+ if (!err && pri->sys_nargs > 2)
+ show_sockaddr(pri, "name", (long)pri->sys_args[1],
+ (long)pri->sys_args[2], 0);
+ break;
+ case SYS_getsockname:
+ case SYS_getpeername:
+ if (!err && pri->sys_nargs > 2)
+ show_sockaddr(pri, "name", (long)pri->sys_args[1],
+ (long)pri->sys_args[2], 0);
+ break;
+ case SYS_cladm:
+ if (!err && pri->sys_nargs > 2)
+ show_cladm(pri, pri->sys_args[0], pri->sys_args[1],
+ (long)pri->sys_args[2]);
+ break;
+ case SYS_recvfrom:
+ if (!err && pri->sys_nargs > 5)
+ show_sockaddr(pri, "from", (long)pri->sys_args[4],
+ (long)pri->sys_args[5], 0);
+ break;
+ case SYS_recvmsg:
+ if (err)
+ break;
+ /* FALLTHROUGH */
+ case SYS_sendmsg:
+ if (pri->sys_nargs <= 2)
+ break;
+#ifdef _LP64
+ if (lp64)
+ show_msghdr(pri, pri->sys_args[1]);
+ else
+ show_msghdr32(pri, pri->sys_args[1]);
+#else
+ show_msghdr(pri, pri->sys_args[1]);
+#endif
+ break;
+ case SYS_door:
+ show_doors(pri);
+ break;
+ case SYS_sendfilev:
+ if (pri->sys_nargs != 5)
+ break;
+
+ if (pri->sys_args[0] == SENDFILEV) {
+ show_sendfilevec(pri, (int)pri->sys_args[1],
+ (sendfilevec_t *)pri->sys_args[2],
+ (int)pri->sys_args[3]);
+ } else if (pri->sys_args[0] == SENDFILEV64) {
+ show_sendfilevec64(pri, (int)pri->sys_args[1],
+ (sendfilevec64_t *)pri->sys_args[2],
+ (int)pri->sys_args[3]);
+ }
+ break;
+ case SYS_memcntl:
+ show_memcntl(pri);
+ break;
+ case SYS_lwp_park:
+ /*
+ * subcode 0: lwp_park(timespec_t *, id_t)
+ * subcode 4: lwp_set_park(timespec_t *, id_t)
+ */
+ if (pri->sys_nargs > 1 &&
+ (pri->sys_args[0] == 0 || pri->sys_args[0] == 4))
+ show_timestruc(pri, (long)pri->sys_args[1], "timeout");
+ /* subcode 2: lwp_unpark_all(id_t *, int) */
+ if (pri->sys_nargs > 2 && pri->sys_args[0] == 2)
+ show_ids(pri, (long)pri->sys_args[1],
+ (int)pri->sys_args[2]);
+ break;
+ case SYS_ntp_gettime:
+ if (!err)
+ show_ntp_gettime(pri);
+ break;
+ case SYS_ntp_adjtime:
+ if (!err)
+ show_ntp_adjtime(pri);
+ break;
+ case SYS_rusagesys:
+ if (!err)
+ if (pri->sys_args[0] == _RUSAGESYS_GETRUSAGE) {
+#ifdef _LP64
+ if (!lp64)
+ show_getrusage32(pri->sys_args[1]);
+ else
+#endif
+ show_getrusage(pri->sys_args[1]);
+ }
+ break;
+ case SYS_port:
+ show_ports(pri);
+ break;
+ case SYS_zone:
+ show_zones(pri);
+ break;
+ case SYS_rctlsys:
+ show_rctls(pri);
+ break;
+ case SYS_utimesys:
+ show_utimesys(pri);
+ break;
+ case SYS_sockconfig:
+ show_sockconfig(pri);
+ break;
+ }
+}
diff --git a/usr/src/cmd/truss/fcall.c b/usr/src/cmd/truss/fcall.c
new file mode 100644
index 0000000..e1fe503
--- /dev/null
+++ b/usr/src/cmd/truss/fcall.c
@@ -0,0 +1,1911 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#define _SYSCALL32
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <string.h>
+#include <memory.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stack.h>
+#include <signal.h>
+#include <limits.h>
+#include <sys/isa_defs.h>
+#include <proc_service.h>
+#include <dlfcn.h>
+#include <fnmatch.h>
+#include <libproc.h>
+#include "ramdata.h"
+#include "systable.h"
+#include "print.h"
+#include "proto.h"
+#include "htbl.h"
+
+/*
+ * Functions supporting library function call tracing.
+ */
+
+typedef struct {
+ prmap_t *pmap;
+ int nmap;
+} ph_map_t;
+
+/*
+ * static functions in this file.
+ */
+void function_entry(private_t *, struct bkpt *, struct callstack *);
+void function_return(private_t *, struct callstack *);
+int object_iter(void *, const prmap_t *, const char *);
+int object_present(void *, const prmap_t *, const char *);
+int symbol_iter(void *, const GElf_Sym *, const char *);
+uintptr_t get_return_address(uintptr_t *);
+int get_arguments(long *argp);
+uintptr_t previous_fp(uintptr_t, uintptr_t *);
+int lwp_stack_traps(void *cd, const lwpstatus_t *Lsp);
+int thr_stack_traps(const td_thrhandle_t *Thp, void *cd);
+struct bkpt *create_bkpt(uintptr_t, int, int);
+void set_deferred_breakpoints(void);
+
+#define DEF_MAXCALL 16 /* initial value of Stk->maxcall */
+
+#define FAULT_ADDR ((uintptr_t)(0-8))
+
+#define HASHSZ 2048
+#define bpt_hash(addr) ((((addr) >> 13) ^ ((addr) >> 2)) & 0x7ff)
+
+static void
+setup_thread_agent(void)
+{
+ struct bkpt *Bp;
+ td_notify_t notify;
+ td_thr_events_t events;
+
+ if (Thr_agent != NULL) /* only once */
+ return;
+ if (td_init() != TD_OK || td_ta_new(Proc, &Thr_agent) != TD_OK)
+ Thr_agent = NULL;
+ else {
+ td_event_emptyset(&events);
+ td_event_addset(&events, TD_CREATE);
+ if (td_ta_event_addr(Thr_agent, TD_CREATE, &notify) == TD_OK &&
+ notify.type == NOTIFY_BPT &&
+ td_ta_set_event(Thr_agent, &events) == TD_OK &&
+ (Bp = create_bkpt(notify.u.bptaddr, 0, 1)) != NULL)
+ Bp->flags |= BPT_TD_CREATE;
+ }
+}
+
+/*
+ * Delete all breakpoints in the range [base .. base+size)
+ * from the breakpoint hash table.
+ */
+static void
+delete_breakpoints(uintptr_t base, size_t size)
+{
+ struct bkpt **Bpp;
+ struct bkpt *Bp;
+ int i;
+
+ if (bpt_hashtable == NULL)
+ return;
+ for (i = 0; i < HASHSZ; i++) {
+ Bpp = &bpt_hashtable[i];
+ while ((Bp = *Bpp) != NULL) {
+ if (Bp->addr < base || Bp->addr >= base + size) {
+ Bpp = &Bp->next;
+ continue;
+ }
+ *Bpp = Bp->next;
+ if (Bp->sym_name)
+ free(Bp->sym_name);
+ free(Bp);
+ }
+ }
+}
+
+/*
+ * Establishment of breakpoints on traced library functions.
+ */
+void
+establish_breakpoints(void)
+{
+ if (Dynpat == NULL)
+ return;
+
+ /* allocate the breakpoint hash table */
+ if (bpt_hashtable == NULL) {
+ bpt_hashtable = my_malloc(HASHSZ * sizeof (struct bkpt *),
+ NULL);
+ (void) memset(bpt_hashtable, 0,
+ HASHSZ * sizeof (struct bkpt *));
+ }
+
+ /*
+ * Set special rtld_db event breakpoints, first time only.
+ */
+ if (Rdb_agent == NULL &&
+ (Rdb_agent = Prd_agent(Proc)) != NULL) {
+ rd_notify_t notify;
+ struct bkpt *Bp;
+
+ (void) rd_event_enable(Rdb_agent, 1);
+ if (rd_event_addr(Rdb_agent, RD_PREINIT, &notify) == RD_OK &&
+ (Bp = create_bkpt(notify.u.bptaddr, 0, 1)) != NULL)
+ Bp->flags |= BPT_PREINIT;
+ if (rd_event_addr(Rdb_agent, RD_POSTINIT, &notify) == RD_OK &&
+ (Bp = create_bkpt(notify.u.bptaddr, 0, 1)) != NULL)
+ Bp->flags |= BPT_POSTINIT;
+ if (rd_event_addr(Rdb_agent, RD_DLACTIVITY, &notify) == RD_OK &&
+ (Bp = create_bkpt(notify.u.bptaddr, 0, 1)) != NULL)
+ Bp->flags |= BPT_DLACTIVITY;
+ }
+
+ /*
+ * Set special thread event breakpoint, first time libc is seen.
+ */
+ if (Thr_agent == NULL)
+ setup_thread_agent();
+
+ /*
+ * Tell libproc to update its mappings.
+ */
+ Pupdate_maps(Proc);
+
+ /*
+ * If rtld_db told us a library was being deleted,
+ * first mark all of the dynlibs as not present, then
+ * iterate over the shared objects, marking only those
+ * present that really are present, and finally delete
+ * all of the not-present dynlibs.
+ */
+ if (delete_library) {
+ struct dynlib **Dpp;
+ struct dynlib *Dp;
+
+ for (Dp = Dynlib; Dp != NULL; Dp = Dp->next)
+ Dp->present = FALSE;
+ (void) Pobject_iter(Proc, object_present, NULL);
+ Dpp = &Dynlib;
+ while ((Dp = *Dpp) != NULL) {
+ if (Dp->present) {
+ Dpp = &Dp->next;
+ continue;
+ }
+ delete_breakpoints(Dp->base, Dp->size);
+ *Dpp = Dp->next;
+ free(Dp->lib_name);
+ free(Dp->match_name);
+ free(Dp->prt_name);
+ free(Dp);
+ }
+ delete_library = FALSE;
+ }
+
+ /*
+ * Iterate over the shared objects, creating breakpoints.
+ */
+ (void) Pobject_iter(Proc, object_iter, NULL);
+
+ /*
+ * Now actually set all the breakpoints we just created.
+ */
+ set_deferred_breakpoints();
+}
+
+/*
+ * Initial establishment of stacks in a newly-grabbed process.
+ * establish_breakpoints() has already been called.
+ */
+void
+establish_stacks(void)
+{
+ const pstatus_t *Psp = Pstatus(Proc);
+ char mapfile[64];
+ int mapfd;
+ struct stat statb;
+ prmap_t *Pmap = NULL;
+ int nmap = 0;
+ ph_map_t ph_map;
+
+ (void) sprintf(mapfile, "/proc/%d/rmap", (int)Psp->pr_pid);
+ if ((mapfd = open(mapfile, O_RDONLY)) < 0 ||
+ fstat(mapfd, &statb) != 0 ||
+ statb.st_size < sizeof (prmap_t) ||
+ (Pmap = my_malloc(statb.st_size, NULL)) == NULL ||
+ (nmap = pread(mapfd, Pmap, statb.st_size, 0L)) <= 0 ||
+ (nmap /= sizeof (prmap_t)) == 0) {
+ if (Pmap != NULL)
+ free(Pmap);
+ Pmap = NULL;
+ nmap = 0;
+ }
+ if (mapfd >= 0)
+ (void) close(mapfd);
+
+ /*
+ * Iterate over lwps, establishing stacks.
+ */
+ ph_map.pmap = Pmap;
+ ph_map.nmap = nmap;
+ (void) Plwp_iter(Proc, lwp_stack_traps, &ph_map);
+ if (Pmap != NULL)
+ free(Pmap);
+
+ if (Thr_agent == NULL)
+ return;
+
+ /*
+ * Iterate over unbound threads, establishing stacks.
+ */
+ (void) td_ta_thr_iter(Thr_agent, thr_stack_traps, NULL,
+ TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
+ TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
+}
+
+void
+do_symbol_iter(const char *object_name, struct dynpat *Dyp)
+{
+ if (*Dyp->Dp->prt_name == '\0')
+ object_name = PR_OBJ_EXEC;
+
+ /*
+ * Always search the dynamic symbol table.
+ */
+ (void) Psymbol_iter(Proc, object_name,
+ PR_DYNSYM, BIND_WEAK|BIND_GLOBAL|TYPE_FUNC,
+ symbol_iter, Dyp);
+
+ /*
+ * Search the static symbol table if this is the
+ * executable file or if we are being asked to
+ * report internal calls within the library.
+ */
+ if (object_name == PR_OBJ_EXEC || Dyp->internal)
+ (void) Psymbol_iter(Proc, object_name,
+ PR_SYMTAB, BIND_ANY|TYPE_FUNC,
+ symbol_iter, Dyp);
+}
+
+/* ARGSUSED */
+int
+object_iter(void *cd, const prmap_t *pmp, const char *object_name)
+{
+ char name[100];
+ struct dynpat *Dyp;
+ struct dynlib *Dp;
+ const char *str;
+ char *s;
+ int i;
+
+ if ((pmp->pr_mflags & MA_WRITE) || !(pmp->pr_mflags & MA_EXEC))
+ return (0);
+
+ /*
+ * Set special thread event breakpoint, first time libc is seen.
+ */
+ if (Thr_agent == NULL && strstr(object_name, "/libc.so.") != NULL)
+ setup_thread_agent();
+
+ for (Dp = Dynlib; Dp != NULL; Dp = Dp->next)
+ if (strcmp(object_name, Dp->lib_name) == 0 ||
+ (strcmp(Dp->lib_name, "a.out") == 0 &&
+ strcmp(pmp->pr_mapname, "a.out") == 0))
+ break;
+
+ if (Dp == NULL) {
+ Dp = my_malloc(sizeof (struct dynlib), NULL);
+ (void) memset(Dp, 0, sizeof (struct dynlib));
+ if (strcmp(pmp->pr_mapname, "a.out") == 0) {
+ Dp->lib_name = strdup(pmp->pr_mapname);
+ Dp->match_name = strdup(pmp->pr_mapname);
+ Dp->prt_name = strdup("");
+ } else {
+ Dp->lib_name = strdup(object_name);
+ if ((str = strrchr(object_name, '/')) != NULL)
+ str++;
+ else
+ str = object_name;
+ (void) strncpy(name, str, sizeof (name) - 2);
+ name[sizeof (name) - 2] = '\0';
+ if ((s = strstr(name, ".so")) != NULL)
+ *s = '\0';
+ Dp->match_name = strdup(name);
+ (void) strcat(name, ":");
+ Dp->prt_name = strdup(name);
+ }
+ Dp->next = Dynlib;
+ Dynlib = Dp;
+ }
+
+ if (Dp->built ||
+ (not_consist && strcmp(Dp->prt_name, "ld:") != 0)) /* kludge */
+ return (0);
+
+ if (hflag && not_consist)
+ (void) fprintf(stderr, "not_consist is TRUE, building %s\n",
+ Dp->lib_name);
+
+ Dp->base = pmp->pr_vaddr;
+ Dp->size = pmp->pr_size;
+
+ /*
+ * For every dynlib pattern that matches this library's name,
+ * iterate through all of the library's symbols looking for
+ * matching symbol name patterns.
+ */
+ for (Dyp = Dynpat; Dyp != NULL; Dyp = Dyp->next) {
+ if (interrupt|sigusr1)
+ break;
+ for (i = 0; i < Dyp->nlibpat; i++) {
+ if (interrupt|sigusr1)
+ break;
+ if (fnmatch(Dyp->libpat[i], Dp->match_name, 0) != 0)
+ continue; /* no match */
+
+ /*
+ * Require an exact match for the executable (a.out)
+ * and for the dynamic linker (ld.so.1).
+ */
+ if ((strcmp(Dp->match_name, "a.out") == 0 ||
+ strcmp(Dp->match_name, "ld") == 0) &&
+ strcmp(Dyp->libpat[i], Dp->match_name) != 0)
+ continue;
+
+ /*
+ * Set Dyp->Dp to Dp so symbol_iter() can use it.
+ */
+ Dyp->Dp = Dp;
+ do_symbol_iter(object_name, Dyp);
+ Dyp->Dp = NULL;
+ }
+ }
+
+ Dp->built = TRUE;
+ return (interrupt | sigusr1);
+}
+
+/* ARGSUSED */
+int
+object_present(void *cd, const prmap_t *pmp, const char *object_name)
+{
+ struct dynlib *Dp;
+
+ for (Dp = Dynlib; Dp != NULL; Dp = Dp->next) {
+ if (Dp->base == pmp->pr_vaddr)
+ Dp->present = TRUE;
+ }
+
+ return (0);
+}
+
+/*
+ * Search for an existing breakpoint at the 'pc' location.
+ */
+struct bkpt *
+get_bkpt(uintptr_t pc)
+{
+ struct bkpt *Bp;
+
+ for (Bp = bpt_hashtable[bpt_hash(pc)]; Bp != NULL; Bp = Bp->next)
+ if (pc == Bp->addr)
+ break;
+
+ return (Bp);
+}
+
+/*
+ * Create a breakpoint at 'pc', if one is not there already.
+ * 'ret' is true when creating a function return breakpoint, in which case
+ * fail and return NULL if the breakpoint would be created in writeable data.
+ * If 'set' it true, set the breakpoint in the process now.
+ */
+struct bkpt *
+create_bkpt(uintptr_t pc, int ret, int set)
+{
+ uint_t hix = bpt_hash(pc);
+ struct bkpt *Bp;
+ const prmap_t *pmp;
+
+ for (Bp = bpt_hashtable[hix]; Bp != NULL; Bp = Bp->next)
+ if (pc == Bp->addr)
+ return (Bp);
+
+ /*
+ * Don't set return breakpoints on writeable data
+ * or on any space other than executable text.
+ * Don't set breakpoints in the child of a vfork()
+ * because that would modify the parent's address space.
+ */
+ if (is_vfork_child ||
+ (ret &&
+ ((pmp = Paddr_to_text_map(Proc, pc)) == NULL ||
+ !(pmp->pr_mflags & MA_EXEC) ||
+ (pmp->pr_mflags & MA_WRITE))))
+ return (NULL);
+
+ /* create a new unnamed breakpoint */
+ Bp = my_malloc(sizeof (struct bkpt), NULL);
+ Bp->sym_name = NULL;
+ Bp->dyn = NULL;
+ Bp->addr = pc;
+ Bp->instr = 0;
+ Bp->flags = 0;
+ if (set && Psetbkpt(Proc, Bp->addr, &Bp->instr) == 0)
+ Bp->flags |= BPT_ACTIVE;
+ Bp->next = bpt_hashtable[hix];
+ bpt_hashtable[hix] = Bp;
+
+ return (Bp);
+}
+
+/*
+ * Set all breakpoints that haven't been set yet.
+ * Deactivate all breakpoints from modules that are not present any more.
+ */
+void
+set_deferred_breakpoints(void)
+{
+ struct bkpt *Bp;
+ int i;
+
+ if (is_vfork_child)
+ return;
+
+ for (i = 0; i < HASHSZ; i++) {
+ for (Bp = bpt_hashtable[i]; Bp != NULL; Bp = Bp->next) {
+ if (!(Bp->flags & BPT_ACTIVE)) {
+ if (!(Bp->flags & BPT_EXCLUDE) &&
+ Psetbkpt(Proc, Bp->addr, &Bp->instr) == 0)
+ Bp->flags |= BPT_ACTIVE;
+ } else if (Paddr_to_text_map(Proc, Bp->addr) == NULL) {
+ Bp->flags &= ~BPT_ACTIVE;
+ }
+ }
+ }
+}
+
+int
+symbol_iter(void *cd, const GElf_Sym *sym, const char *sym_name)
+{
+ struct dynpat *Dyp = cd;
+ struct dynlib *Dp = Dyp->Dp;
+ uintptr_t pc = sym->st_value;
+ struct bkpt *Bp;
+ int i;
+
+ /* ignore any undefined symbols */
+ if (sym->st_shndx == SHN_UNDEF)
+ return (0);
+
+ /*
+ * Arbitrarily omit "_start" from the executable.
+ * (Avoid indentation before main().)
+ */
+ if (*Dp->prt_name == '\0' && strcmp(sym_name, "_start") == 0)
+ return (0);
+
+ /*
+ * Arbitrarily omit "_rt_boot" from the dynamic linker.
+ * (Avoid indentation before main().)
+ */
+ if (strcmp(Dp->match_name, "ld") == 0 &&
+ strcmp(sym_name, "_rt_boot") == 0)
+ return (0);
+
+ /*
+ * Arbitrarily omit any symbols whose name starts with '.'.
+ * Apparantly putting a breakpoint on .umul causes a
+ * fatal error in libthread (%y is not restored correctly
+ * when a single step is taken). Looks like a /proc bug.
+ */
+ if (*sym_name == '.')
+ return (0);
+
+ /*
+ * For each pattern in the array of symbol patterns,
+ * if the pattern matches the symbol name, then
+ * create a breakpoint at the function in question.
+ */
+ for (i = 0; i < Dyp->nsympat; i++) {
+ if (interrupt|sigusr1)
+ break;
+ if (fnmatch(Dyp->sympat[i], sym_name, 0) != 0)
+ continue;
+
+ if ((Bp = create_bkpt(pc, 0, 0)) == NULL) /* can't fail */
+ return (0);
+
+ /*
+ * New breakpoints receive a name now.
+ * For existing breakpoints, prefer the subset name if possible,
+ * else prefer the shorter name.
+ */
+ if (Bp->sym_name == NULL) {
+ Bp->sym_name = strdup(sym_name);
+ } else if (strstr(Bp->sym_name, sym_name) != NULL ||
+ strlen(Bp->sym_name) > strlen(sym_name)) {
+ free(Bp->sym_name);
+ Bp->sym_name = strdup(sym_name);
+ }
+ Bp->dyn = Dp;
+ Bp->flags |= Dyp->flag;
+ if (Dyp->exclude)
+ Bp->flags |= BPT_EXCLUDE;
+ else if (Dyp->internal || *Dp->prt_name == '\0')
+ Bp->flags |= BPT_INTERNAL;
+ return (0);
+ }
+
+ return (interrupt | sigusr1);
+}
+
+/* For debugging only ---- */
+void
+report_htable_stats(void)
+{
+ const pstatus_t *Psp = Pstatus(Proc);
+ struct callstack *Stk;
+ struct bkpt *Bp;
+ uint_t Min = 1000000;
+ uint_t Max = 0;
+ uint_t Avg = 0;
+ uint_t Total = 0;
+ uint_t i, j;
+ uint_t bucket[HASHSZ];
+
+ if (Dynpat == NULL || !hflag)
+ return;
+
+ hflag = FALSE;
+ (void) memset(bucket, 0, sizeof (bucket));
+
+ for (i = 0; i < HASHSZ; i++) {
+ j = 0;
+ for (Bp = bpt_hashtable[i]; Bp != NULL; Bp = Bp->next)
+ j++;
+ if (j < Min)
+ Min = j;
+ if (j > Max)
+ Max = j;
+ if (j < HASHSZ)
+ bucket[j]++;
+ Total += j;
+ }
+ Avg = (Total + HASHSZ / 2) / HASHSZ;
+ (void) fprintf(stderr, "truss hash table statistics --------\n");
+ (void) fprintf(stderr, " Total = %u\n", Total);
+ (void) fprintf(stderr, " Min = %u\n", Min);
+ (void) fprintf(stderr, " Max = %u\n", Max);
+ (void) fprintf(stderr, " Avg = %u\n", Avg);
+ for (i = 0; i < HASHSZ; i++)
+ if (bucket[i])
+ (void) fprintf(stderr, " %3u buckets of size %d\n",
+ bucket[i], i);
+
+ (void) fprintf(stderr, "truss-detected stacks --------\n");
+ for (Stk = callstack; Stk != NULL; Stk = Stk->next) {
+ (void) fprintf(stderr,
+ " base = 0x%.8lx end = 0x%.8lx size = %ld\n",
+ (ulong_t)Stk->stkbase,
+ (ulong_t)Stk->stkend,
+ (ulong_t)(Stk->stkend - Stk->stkbase));
+ }
+ (void) fprintf(stderr, "primary unix stack --------\n");
+ (void) fprintf(stderr,
+ " base = 0x%.8lx end = 0x%.8lx size = %ld\n",
+ (ulong_t)Psp->pr_stkbase,
+ (ulong_t)(Psp->pr_stkbase + Psp->pr_stksize),
+ (ulong_t)Psp->pr_stksize);
+ (void) fprintf(stderr, "nthr_create = %u\n", nthr_create);
+}
+
+void
+make_lwp_stack(const lwpstatus_t *Lsp, prmap_t *Pmap, int nmap)
+{
+ const pstatus_t *Psp = Pstatus(Proc);
+ uintptr_t sp = Lsp->pr_reg[R_SP];
+ id_t lwpid = Lsp->pr_lwpid;
+ struct callstack *Stk;
+ td_thrhandle_t th;
+ td_thrinfo_t thrinfo;
+
+ if (data_model != PR_MODEL_LP64)
+ sp = (uint32_t)sp;
+
+ /* check to see if we already have this stack */
+ if (sp == 0)
+ return;
+ for (Stk = callstack; Stk != NULL; Stk = Stk->next)
+ if (sp >= Stk->stkbase && sp < Stk->stkend)
+ return;
+
+ Stk = my_malloc(sizeof (struct callstack), NULL);
+ Stk->next = callstack;
+ callstack = Stk;
+ nstack++;
+ Stk->tref = 0;
+ Stk->tid = 0;
+ Stk->nthr_create = 0;
+ Stk->ncall = 0;
+ Stk->maxcall = DEF_MAXCALL;
+ Stk->stack = my_malloc(DEF_MAXCALL * sizeof (*Stk->stack), NULL);
+
+ /* primary stack */
+ if (sp >= Psp->pr_stkbase && sp < Psp->pr_stkbase + Psp->pr_stksize) {
+ Stk->stkbase = Psp->pr_stkbase;
+ Stk->stkend = Stk->stkbase + Psp->pr_stksize;
+ return;
+ }
+
+ /* alternate stack */
+ if ((Lsp->pr_altstack.ss_flags & SS_ONSTACK) &&
+ sp >= (uintptr_t)Lsp->pr_altstack.ss_sp &&
+ sp < (uintptr_t)Lsp->pr_altstack.ss_sp
+ + Lsp->pr_altstack.ss_size) {
+ Stk->stkbase = (uintptr_t)Lsp->pr_altstack.ss_sp;
+ Stk->stkend = Stk->stkbase + Lsp->pr_altstack.ss_size;
+ return;
+ }
+
+ /* thread stacks? */
+ if (Thr_agent != NULL &&
+ td_ta_map_lwp2thr(Thr_agent, lwpid, &th) == TD_OK &&
+ td_thr_get_info(&th, &thrinfo) == TD_OK &&
+ sp >= (uintptr_t)thrinfo.ti_stkbase - thrinfo.ti_stksize &&
+ sp < (uintptr_t)thrinfo.ti_stkbase) {
+ /* The bloody fools got this backwards! */
+ Stk->stkend = (uintptr_t)thrinfo.ti_stkbase;
+ Stk->stkbase = Stk->stkend - thrinfo.ti_stksize;
+ return;
+ }
+
+ /* last chance -- try the raw memory map */
+ for (; nmap; nmap--, Pmap++) {
+ if (sp >= Pmap->pr_vaddr &&
+ sp < Pmap->pr_vaddr + Pmap->pr_size) {
+ Stk->stkbase = Pmap->pr_vaddr;
+ Stk->stkend = Pmap->pr_vaddr + Pmap->pr_size;
+ return;
+ }
+ }
+
+ callstack = Stk->next;
+ nstack--;
+ free(Stk->stack);
+ free(Stk);
+}
+
+void
+make_thr_stack(const td_thrhandle_t *Thp, prgregset_t reg)
+{
+ const pstatus_t *Psp = Pstatus(Proc);
+ td_thrinfo_t thrinfo;
+ uintptr_t sp = reg[R_SP];
+ struct callstack *Stk;
+
+ if (data_model != PR_MODEL_LP64)
+ sp = (uint32_t)sp;
+
+ /* check to see if we already have this stack */
+ if (sp == 0)
+ return;
+ for (Stk = callstack; Stk != NULL; Stk = Stk->next)
+ if (sp >= Stk->stkbase && sp < Stk->stkend)
+ return;
+
+ Stk = my_malloc(sizeof (struct callstack), NULL);
+ Stk->next = callstack;
+ callstack = Stk;
+ nstack++;
+ Stk->tref = 0;
+ Stk->tid = 0;
+ Stk->nthr_create = 0;
+ Stk->ncall = 0;
+ Stk->maxcall = DEF_MAXCALL;
+ Stk->stack = my_malloc(DEF_MAXCALL * sizeof (*Stk->stack), NULL);
+
+ /* primary stack */
+ if (sp >= Psp->pr_stkbase && sp < Psp->pr_stkbase + Psp->pr_stksize) {
+ Stk->stkbase = Psp->pr_stkbase;
+ Stk->stkend = Stk->stkbase + Psp->pr_stksize;
+ return;
+ }
+
+ if (td_thr_get_info(Thp, &thrinfo) == TD_OK &&
+ sp >= (uintptr_t)thrinfo.ti_stkbase - thrinfo.ti_stksize &&
+ sp < (uintptr_t)thrinfo.ti_stkbase) {
+ /* The bloody fools got this backwards! */
+ Stk->stkend = (uintptr_t)thrinfo.ti_stkbase;
+ Stk->stkbase = Stk->stkend - thrinfo.ti_stksize;
+ return;
+ }
+
+ callstack = Stk->next;
+ nstack--;
+ free(Stk->stack);
+ free(Stk);
+}
+
+struct callstack *
+find_lwp_stack(uintptr_t sp)
+{
+ const pstatus_t *Psp = Pstatus(Proc);
+ char mapfile[64];
+ int mapfd;
+ struct stat statb;
+ prmap_t *Pmap = NULL;
+ prmap_t *pmap = NULL;
+ int nmap = 0;
+ struct callstack *Stk = NULL;
+
+ /*
+ * Get the address space map.
+ */
+ (void) sprintf(mapfile, "/proc/%d/rmap", (int)Psp->pr_pid);
+ if ((mapfd = open(mapfile, O_RDONLY)) < 0 ||
+ fstat(mapfd, &statb) != 0 ||
+ statb.st_size < sizeof (prmap_t) ||
+ (Pmap = my_malloc(statb.st_size, NULL)) == NULL ||
+ (nmap = pread(mapfd, Pmap, statb.st_size, 0L)) <= 0 ||
+ (nmap /= sizeof (prmap_t)) == 0) {
+ if (Pmap != NULL)
+ free(Pmap);
+ if (mapfd >= 0)
+ (void) close(mapfd);
+ return (NULL);
+ }
+ (void) close(mapfd);
+
+ for (pmap = Pmap; nmap--; pmap++) {
+ if (sp >= pmap->pr_vaddr &&
+ sp < pmap->pr_vaddr + pmap->pr_size) {
+ Stk = my_malloc(sizeof (struct callstack), NULL);
+ Stk->next = callstack;
+ callstack = Stk;
+ nstack++;
+ Stk->stkbase = pmap->pr_vaddr;
+ Stk->stkend = pmap->pr_vaddr + pmap->pr_size;
+ Stk->tref = 0;
+ Stk->tid = 0;
+ Stk->nthr_create = 0;
+ Stk->ncall = 0;
+ Stk->maxcall = DEF_MAXCALL;
+ Stk->stack = my_malloc(
+ DEF_MAXCALL * sizeof (*Stk->stack), NULL);
+ break;
+ }
+ }
+
+ free(Pmap);
+ return (Stk);
+}
+
+struct callstack *
+find_stack(uintptr_t sp)
+{
+ const pstatus_t *Psp = Pstatus(Proc);
+ private_t *pri = get_private();
+ const lwpstatus_t *Lsp = pri->lwpstat;
+ id_t lwpid = Lsp->pr_lwpid;
+#if defined(__sparc)
+ prgreg_t tref = Lsp->pr_reg[R_G7];
+#elif defined(__amd64)
+ prgreg_t tref = Lsp->pr_reg[REG_FS];
+#elif defined(__i386)
+ prgreg_t tref = Lsp->pr_reg[GS];
+#endif
+ struct callstack *Stk = NULL;
+ td_thrhandle_t th;
+ td_thrinfo_t thrinfo;
+ td_err_e error;
+
+ /* primary stack */
+ if (sp >= Psp->pr_stkbase && sp < Psp->pr_stkbase + Psp->pr_stksize) {
+ Stk = my_malloc(sizeof (struct callstack), NULL);
+ Stk->next = callstack;
+ callstack = Stk;
+ nstack++;
+ Stk->stkbase = Psp->pr_stkbase;
+ Stk->stkend = Stk->stkbase + Psp->pr_stksize;
+ Stk->tref = 0;
+ Stk->tid = 0;
+ Stk->nthr_create = 0;
+ Stk->ncall = 0;
+ Stk->maxcall = DEF_MAXCALL;
+ Stk->stack = my_malloc(DEF_MAXCALL * sizeof (*Stk->stack),
+ NULL);
+ return (Stk);
+ }
+
+ /* alternate stack */
+ if ((Lsp->pr_altstack.ss_flags & SS_ONSTACK) &&
+ sp >= (uintptr_t)Lsp->pr_altstack.ss_sp &&
+ sp < (uintptr_t)Lsp->pr_altstack.ss_sp
+ + Lsp->pr_altstack.ss_size) {
+ Stk = my_malloc(sizeof (struct callstack), NULL);
+ Stk->next = callstack;
+ callstack = Stk;
+ nstack++;
+ Stk->stkbase = (uintptr_t)Lsp->pr_altstack.ss_sp;
+ Stk->stkend = Stk->stkbase + Lsp->pr_altstack.ss_size;
+ Stk->tref = 0;
+ Stk->tid = 0;
+ Stk->nthr_create = 0;
+ Stk->ncall = 0;
+ Stk->maxcall = DEF_MAXCALL;
+ Stk->stack = my_malloc(DEF_MAXCALL * sizeof (*Stk->stack),
+ NULL);
+ return (Stk);
+ }
+
+ if (Thr_agent == NULL)
+ return (find_lwp_stack(sp));
+
+ /* thread stacks? */
+ if ((error = td_ta_map_lwp2thr(Thr_agent, lwpid, &th)) != TD_OK) {
+ if (hflag)
+ (void) fprintf(stderr,
+ "cannot get thread handle for "
+ "lwp#%d, error=%d, tref=0x%.8lx\n",
+ (int)lwpid, error, (long)tref);
+ return (NULL);
+ }
+
+ if ((error = td_thr_get_info(&th, &thrinfo)) != TD_OK) {
+ if (hflag)
+ (void) fprintf(stderr,
+ "cannot get thread info for "
+ "lwp#%d, error=%d, tref=0x%.8lx\n",
+ (int)lwpid, error, (long)tref);
+ return (NULL);
+ }
+
+ if (sp >= (uintptr_t)thrinfo.ti_stkbase - thrinfo.ti_stksize &&
+ sp < (uintptr_t)thrinfo.ti_stkbase) {
+ Stk = my_malloc(sizeof (struct callstack), NULL);
+ Stk->next = callstack;
+ callstack = Stk;
+ nstack++;
+ /* The bloody fools got this backwards! */
+ Stk->stkend = (uintptr_t)thrinfo.ti_stkbase;
+ Stk->stkbase = Stk->stkend - thrinfo.ti_stksize;
+ Stk->tref = tref;
+ Stk->tid = thrinfo.ti_tid;
+ Stk->nthr_create = nthr_create;
+ Stk->ncall = 0;
+ Stk->maxcall = DEF_MAXCALL;
+ Stk->stack = my_malloc(DEF_MAXCALL * sizeof (*Stk->stack),
+ NULL);
+ return (Stk);
+ }
+
+ /* stack bounds failure -- complain bitterly */
+ if (hflag) {
+ (void) fprintf(stderr,
+ "sp not within thread stack: "
+ "sp=0x%.8lx stkbase=0x%.8lx stkend=0x%.8lx\n",
+ (ulong_t)sp,
+ /* The bloody fools got this backwards! */
+ (ulong_t)thrinfo.ti_stkbase - thrinfo.ti_stksize,
+ (ulong_t)thrinfo.ti_stkbase);
+ }
+
+ return (NULL);
+}
+
+void
+get_tid(struct callstack *Stk)
+{
+ private_t *pri = get_private();
+ const lwpstatus_t *Lsp = pri->lwpstat;
+ id_t lwpid = Lsp->pr_lwpid;
+#if defined(__sparc)
+ prgreg_t tref = Lsp->pr_reg[R_G7];
+#elif defined(__amd64)
+ prgreg_t tref = (data_model == PR_MODEL_LP64) ?
+ Lsp->pr_reg[REG_FS] : Lsp->pr_reg[REG_GS];
+#elif defined(__i386)
+ prgreg_t tref = Lsp->pr_reg[GS];
+#endif
+ td_thrhandle_t th;
+ td_thrinfo_t thrinfo;
+ td_err_e error;
+
+ if (Thr_agent == NULL) {
+ Stk->tref = 0;
+ Stk->tid = 0;
+ Stk->nthr_create = 0;
+ return;
+ }
+
+ /*
+ * Shortcut here --
+ * If we have a matching tref and no new threads have
+ * been created since the last time we encountered this
+ * stack, then we don't have to go through the overhead
+ * of calling td_ta_map_lwp2thr() to get the thread-id.
+ */
+ if (tref == Stk->tref && Stk->nthr_create == nthr_create)
+ return;
+
+ if ((error = td_ta_map_lwp2thr(Thr_agent, lwpid, &th)) != TD_OK) {
+ if (hflag)
+ (void) fprintf(stderr,
+ "cannot get thread handle for "
+ "lwp#%d, error=%d, tref=0x%.8lx\n",
+ (int)lwpid, error, (long)tref);
+ Stk->tref = 0;
+ Stk->tid = 0;
+ Stk->nthr_create = 0;
+ } else if ((error = td_thr_get_info(&th, &thrinfo)) != TD_OK) {
+ if (hflag)
+ (void) fprintf(stderr,
+ "cannot get thread info for "
+ "lwp#%d, error=%d, tref=0x%.8lx\n",
+ (int)lwpid, error, (long)tref);
+ Stk->tref = 0;
+ Stk->tid = 0;
+ Stk->nthr_create = 0;
+ } else {
+ Stk->tref = tref;
+ Stk->tid = thrinfo.ti_tid;
+ Stk->nthr_create = nthr_create;
+ }
+}
+
+struct callstack *
+callstack_info(uintptr_t sp, uintptr_t fp, int makeid)
+{
+ struct callstack *Stk;
+ uintptr_t trash;
+
+ if (sp == 0 ||
+ Pread(Proc, &trash, sizeof (trash), sp) != sizeof (trash))
+ return (NULL);
+
+ for (Stk = callstack; Stk != NULL; Stk = Stk->next)
+ if (sp >= Stk->stkbase && sp < Stk->stkend)
+ break;
+
+ /*
+ * If we didn't find the stack, do it the hard way.
+ */
+ if (Stk == NULL) {
+ uintptr_t stkbase = sp;
+ uintptr_t stkend;
+ uint_t minsize;
+
+#if defined(i386) || defined(__amd64)
+#ifdef _LP64
+ if (data_model == PR_MODEL_LP64)
+ minsize = 2 * sizeof (uintptr_t); /* fp + pc */
+ else
+#endif
+ minsize = 2 * sizeof (uint32_t);
+#else
+#ifdef _LP64
+ if (data_model != PR_MODEL_LP64)
+ minsize = SA32(MINFRAME32);
+ else
+ minsize = SA64(MINFRAME64);
+#else
+ minsize = SA(MINFRAME);
+#endif
+#endif /* i386 */
+ stkend = sp + minsize;
+
+ while (Stk == NULL && fp != 0 && fp >= sp) {
+ stkend = fp + minsize;
+ for (Stk = callstack; Stk != NULL; Stk = Stk->next)
+ if ((fp >= Stk->stkbase && fp < Stk->stkend) ||
+ (stkend > Stk->stkbase &&
+ stkend <= Stk->stkend))
+ break;
+ if (Stk == NULL)
+ fp = previous_fp(fp, NULL);
+ }
+
+ if (Stk != NULL) /* the stack grew */
+ Stk->stkbase = stkbase;
+ }
+
+ if (Stk == NULL && makeid) /* new stack */
+ Stk = find_stack(sp);
+
+ if (Stk == NULL)
+ return (NULL);
+
+ /*
+ * Ensure that there is room for at least one more entry.
+ */
+ if (Stk->ncall == Stk->maxcall) {
+ Stk->maxcall *= 2;
+ Stk->stack = my_realloc(Stk->stack,
+ Stk->maxcall * sizeof (*Stk->stack), NULL);
+ }
+
+ if (makeid)
+ get_tid(Stk);
+
+ return (Stk);
+}
+
+/*
+ * Reset the breakpoint information (called on successful exec()).
+ */
+void
+reset_breakpoints(void)
+{
+ struct dynlib *Dp;
+ struct bkpt *Bp;
+ struct callstack *Stk;
+ int i;
+
+ if (Dynpat == NULL)
+ return;
+
+ /* destroy all previous dynamic library information */
+ while ((Dp = Dynlib) != NULL) {
+ Dynlib = Dp->next;
+ free(Dp->lib_name);
+ free(Dp->match_name);
+ free(Dp->prt_name);
+ free(Dp);
+ }
+
+ /* destroy all previous breakpoint trap information */
+ if (bpt_hashtable != NULL) {
+ for (i = 0; i < HASHSZ; i++) {
+ while ((Bp = bpt_hashtable[i]) != NULL) {
+ bpt_hashtable[i] = Bp->next;
+ if (Bp->sym_name)
+ free(Bp->sym_name);
+ free(Bp);
+ }
+ }
+ }
+
+ /* destroy all the callstack information */
+ while ((Stk = callstack) != NULL) {
+ callstack = Stk->next;
+ free(Stk->stack);
+ free(Stk);
+ }
+
+ /* we are not a multi-threaded process anymore */
+ if (Thr_agent != NULL)
+ (void) td_ta_delete(Thr_agent);
+ Thr_agent = NULL;
+
+ /* tell libproc to clear out its mapping information */
+ Preset_maps(Proc);
+ Rdb_agent = NULL;
+
+ /* Reestablish the symbols from the executable */
+ (void) establish_breakpoints();
+}
+
+/*
+ * Clear breakpoints from the process (called before Prelease()).
+ * Don't actually destroy the breakpoint table;
+ * threads currently fielding breakpoints will need it.
+ */
+void
+clear_breakpoints(void)
+{
+ struct bkpt *Bp;
+ int i;
+
+ if (Dynpat == NULL)
+ return;
+
+ /*
+ * Change all breakpoint traps back to normal instructions.
+ * We attempt to remove a breakpoint from every address which
+ * may have ever contained a breakpoint to protect our victims.
+ */
+ report_htable_stats(); /* report stats first */
+ for (i = 0; i < HASHSZ; i++) {
+ for (Bp = bpt_hashtable[i]; Bp != NULL; Bp = Bp->next) {
+ if (Bp->flags & BPT_ACTIVE)
+ (void) Pdelbkpt(Proc, Bp->addr, Bp->instr);
+ Bp->flags &= ~BPT_ACTIVE;
+ }
+ }
+
+ if (Thr_agent != NULL) {
+ td_thr_events_t events;
+
+ td_event_fillset(&events);
+ (void) td_ta_clear_event(Thr_agent, &events);
+ (void) td_ta_delete(Thr_agent);
+ }
+ Thr_agent = NULL;
+}
+
+/*
+ * Reestablish the breakpoint traps in the process.
+ * Called after resuming from a vfork() in the parent.
+ */
+void
+reestablish_traps(void)
+{
+ struct bkpt *Bp;
+ ulong_t instr;
+ int i;
+
+ if (Dynpat == NULL || is_vfork_child)
+ return;
+
+ for (i = 0; i < HASHSZ; i++) {
+ for (Bp = bpt_hashtable[i]; Bp != NULL; Bp = Bp->next) {
+ if ((Bp->flags & BPT_ACTIVE) &&
+ Psetbkpt(Proc, Bp->addr, &instr) != 0)
+ Bp->flags &= ~BPT_ACTIVE;
+ }
+ }
+}
+
+void
+show_function_call(private_t *pri,
+ struct callstack *Stk, struct dynlib *Dp, struct bkpt *Bp)
+{
+ long arg[8];
+ int narg;
+ int i;
+
+ narg = get_arguments(arg);
+ make_pname(pri, (Stk != NULL)? Stk->tid : 0);
+ putpname(pri);
+ timestamp(pri);
+ if (Stk != NULL) {
+ for (i = 1; i < Stk->ncall; i++) {
+ (void) fputc(' ', stdout);
+ (void) fputc(' ', stdout);
+ }
+ }
+ (void) printf("-> %s%s(", Dp->prt_name, Bp->sym_name);
+ for (i = 0; i < narg; i++) {
+ (void) printf("0x%lx", arg[i]);
+ if (i < narg-1) {
+ (void) fputc(',', stdout);
+ (void) fputc(' ', stdout);
+ }
+ }
+ (void) printf(")\n");
+ Flush();
+}
+
+/* ARGSUSED */
+void
+show_function_return(private_t *pri, long rval, int stret,
+ struct callstack *Stk, struct dynlib *Dp, struct bkpt *Bp)
+{
+ int i;
+
+ make_pname(pri, Stk->tid);
+ putpname(pri);
+ timestamp(pri);
+ for (i = 0; i < Stk->ncall; i++) {
+ (void) fputc(' ', stdout);
+ (void) fputc(' ', stdout);
+ }
+ (void) printf("<- %s%s() = ", Dp->prt_name, Bp->sym_name);
+ if (stret) {
+ (void) printf("struct return\n");
+ } else if (data_model == PR_MODEL_LP64) {
+ if (rval >= (64 * 1024) || -rval >= (64 * 1024))
+ (void) printf("0x%lx\n", rval);
+ else
+ (void) printf("%ld\n", rval);
+ } else {
+ int rval32 = (int)rval;
+ if (rval32 >= (64 * 1024) || -rval32 >= (64 * 1024))
+ (void) printf("0x%x\n", rval32);
+ else
+ (void) printf("%d\n", rval32);
+ }
+ Flush();
+}
+
+/*
+ * Called to deal with function-call tracing.
+ * Return 0 on normal success, 1 to indicate a BPT_HANG success,
+ * and -1 on failure (not tracing functions or unknown breakpoint).
+ */
+int
+function_trace(private_t *pri, int first, int clear, int dotrace)
+{
+ struct ps_lwphandle *Lwp = pri->Lwp;
+ const lwpstatus_t *Lsp = pri->lwpstat;
+ uintptr_t pc = Lsp->pr_reg[R_PC];
+ uintptr_t sp = Lsp->pr_reg[R_SP];
+ uintptr_t fp = Lsp->pr_reg[R_FP];
+ struct bkpt *Bp;
+ struct dynlib *Dp;
+ struct callstack *Stk;
+ ulong_t instr;
+ int active;
+ int rval = 0;
+
+ if (Dynpat == NULL)
+ return (-1);
+
+ if (data_model != PR_MODEL_LP64) {
+ pc = (uint32_t)pc;
+ sp = (uint32_t)sp;
+ fp = (uint32_t)fp;
+ }
+
+ if ((Bp = get_bkpt(pc)) == NULL) {
+ if (hflag)
+ (void) fprintf(stderr,
+ "function_trace(): "
+ "cannot find breakpoint for pc: 0x%.8lx\n",
+ (ulong_t)pc);
+ return (-1);
+ }
+
+ if ((Bp->flags & (BPT_PREINIT|BPT_POSTINIT|BPT_DLACTIVITY)) && !clear) {
+ rd_event_msg_t event_msg;
+
+ if (hflag) {
+ if (Bp->flags & BPT_PREINIT)
+ (void) fprintf(stderr, "function_trace(): "
+ "RD_PREINIT breakpoint\n");
+ if (Bp->flags & BPT_POSTINIT)
+ (void) fprintf(stderr, "function_trace(): "
+ "RD_POSTINIT breakpoint\n");
+ if (Bp->flags & BPT_DLACTIVITY)
+ (void) fprintf(stderr, "function_trace(): "
+ "RD_DLACTIVITY breakpoint\n");
+ }
+ if (rd_event_getmsg(Rdb_agent, &event_msg) == RD_OK) {
+ if (event_msg.type == RD_DLACTIVITY) {
+ switch (event_msg.u.state) {
+ case RD_CONSISTENT:
+ establish_breakpoints();
+ break;
+ case RD_ADD:
+ not_consist = TRUE; /* kludge */
+ establish_breakpoints();
+ not_consist = FALSE;
+ break;
+ case RD_DELETE:
+ delete_library = TRUE;
+ break;
+ default:
+ break;
+ }
+ }
+ if (hflag) {
+ const char *et;
+ char buf[32];
+
+ switch (event_msg.type) {
+ case RD_NONE:
+ et = "RD_NONE";
+ break;
+ case RD_PREINIT:
+ et = "RD_PREINIT";
+ break;
+ case RD_POSTINIT:
+ et = "RD_POSTINIT";
+ break;
+ case RD_DLACTIVITY:
+ et = "RD_DLACTIVITY";
+ break;
+ default:
+ (void) sprintf(buf, "0x%x",
+ event_msg.type);
+ et = buf;
+ break;
+ }
+ (void) fprintf(stderr,
+ "event_msg.type = %s ", et);
+ switch (event_msg.u.state) {
+ case RD_NOSTATE:
+ et = "RD_NOSTATE";
+ break;
+ case RD_CONSISTENT:
+ et = "RD_CONSISTENT";
+ break;
+ case RD_ADD:
+ et = "RD_ADD";
+ break;
+ case RD_DELETE:
+ et = "RD_DELETE";
+ break;
+ default:
+ (void) sprintf(buf, "0x%x",
+ event_msg.u.state);
+ et = buf;
+ break;
+ }
+ (void) fprintf(stderr,
+ "event_msg.u.state = %s\n", et);
+ }
+ }
+ }
+
+ if ((Bp->flags & BPT_TD_CREATE) && !clear) {
+ nthr_create++;
+ if (hflag)
+ (void) fprintf(stderr, "function_trace(): "
+ "BPT_TD_CREATE breakpoint\n");
+ /* we don't care about the event message */
+ }
+
+ Dp = Bp->dyn;
+
+ if (dotrace) {
+ if ((Stk = callstack_info(sp, fp, 1)) == NULL) {
+ if (Dp != NULL && !clear) {
+ if (cflag) {
+ add_fcall(fcall_tbl, Dp->prt_name,
+ Bp->sym_name, (unsigned long)1);
+ }
+ else
+ show_function_call(pri, NULL, Dp, Bp);
+ if ((Bp->flags & BPT_HANG) && !first)
+ rval = 1;
+ }
+ } else if (!clear) {
+ if (Dp != NULL) {
+ function_entry(pri, Bp, Stk);
+ if ((Bp->flags & BPT_HANG) && !first)
+ rval = 1;
+ } else {
+ function_return(pri, Stk);
+ }
+ }
+ }
+
+ /*
+ * Single-step the traced instruction. Since it's possible that
+ * another thread has deactivated this breakpoint, we indicate
+ * that we have reactivated it by virtue of executing it.
+ *
+ * To avoid a deadlock with some other thread in the process
+ * performing a fork() or a thr_suspend() operation, we must
+ * drop and later reacquire truss_lock. Some fancy dancing here.
+ */
+ active = (Bp->flags & BPT_ACTIVE);
+ Bp->flags |= BPT_ACTIVE;
+ instr = Bp->instr;
+ (void) mutex_unlock(&truss_lock);
+ (void) Lxecbkpt(Lwp, instr);
+ (void) mutex_lock(&truss_lock);
+
+ if (rval || clear) { /* leave process stopped and abandoned */
+#if defined(__i386)
+ /*
+ * Leave it stopped in a state that a stack trace is reasonable.
+ */
+ /* XX64 needs to be updated for amd64 & gcc */
+ if (rval && instr == 0x55) { /* pushl %ebp */
+ /* step it over the movl %esp,%ebp */
+ (void) mutex_unlock(&truss_lock);
+ (void) Lsetrun(Lwp, 0, PRCFAULT|PRSTEP);
+ /* we're wrapping up; wait one second at most */
+ (void) Lwait(Lwp, MILLISEC);
+ (void) mutex_lock(&truss_lock);
+ }
+#endif
+ if (get_bkpt(pc) != Bp)
+ abend("function_trace: lost breakpoint", NULL);
+ (void) Pdelbkpt(Proc, Bp->addr, Bp->instr);
+ Bp->flags &= ~BPT_ACTIVE;
+ (void) mutex_unlock(&truss_lock);
+ (void) Lsetrun(Lwp, 0, PRCFAULT|PRSTOP);
+ /* we're wrapping up; wait one second at most */
+ (void) Lwait(Lwp, MILLISEC);
+ (void) mutex_lock(&truss_lock);
+ } else {
+ if (get_bkpt(pc) != Bp)
+ abend("function_trace: lost breakpoint", NULL);
+ if (!active || !(Bp->flags & BPT_ACTIVE)) {
+ (void) Pdelbkpt(Proc, Bp->addr, Bp->instr);
+ Bp->flags &= ~BPT_ACTIVE;
+ }
+ }
+ return (rval);
+}
+
+void
+function_entry(private_t *pri, struct bkpt *Bp, struct callstack *Stk)
+{
+ const lwpstatus_t *Lsp = pri->lwpstat;
+ uintptr_t sp = Lsp->pr_reg[R_SP];
+ uintptr_t rpc = get_return_address(&sp);
+ struct dynlib *Dp = Bp->dyn;
+ int oldframe = FALSE;
+ int i;
+
+#ifdef _LP64
+ if (data_model != PR_MODEL_LP64) {
+ sp = (uint32_t)sp;
+ rpc = (uint32_t)rpc;
+ }
+#endif
+
+ /*
+ * If the sp is not within the stack bounds, forget it.
+ * If the symbol's 'internal' flag is false,
+ * don't report internal calls within the library.
+ */
+ if (!(sp >= Stk->stkbase && sp < Stk->stkend) ||
+ (!(Bp->flags & BPT_INTERNAL) &&
+ rpc >= Dp->base && rpc < Dp->base + Dp->size))
+ return;
+
+ for (i = 0; i < Stk->ncall; i++) {
+ if (sp >= Stk->stack[i].sp) {
+ Stk->ncall = i;
+ if (sp == Stk->stack[i].sp)
+ oldframe = TRUE;
+ break;
+ }
+ }
+
+ /*
+ * Breakpoints for function returns are set here
+ * If we're counting function calls, there is no need to set
+ * a breakpoint upon return
+ */
+
+ if (!oldframe && !cflag) {
+ (void) create_bkpt(rpc, 1, 1); /* may or may not be set */
+ Stk->stack[Stk->ncall].sp = sp; /* record it anyeay */
+ Stk->stack[Stk->ncall].pc = rpc;
+ Stk->stack[Stk->ncall].fcn = Bp;
+ }
+ Stk->ncall++;
+ if (cflag) {
+ add_fcall(fcall_tbl, Dp->prt_name, Bp->sym_name,
+ (unsigned long)1);
+ } else {
+ show_function_call(pri, Stk, Dp, Bp);
+ }
+}
+
+/*
+ * We are here because we hit an unnamed breakpoint.
+ * Attempt to match this up with a return pc on the stack
+ * and report the function return.
+ */
+void
+function_return(private_t *pri, struct callstack *Stk)
+{
+ const lwpstatus_t *Lsp = pri->lwpstat;
+ uintptr_t sp = Lsp->pr_reg[R_SP];
+ uintptr_t fp = Lsp->pr_reg[R_FP];
+ int i;
+
+#ifdef _LP64
+ if (data_model != PR_MODEL_LP64) {
+ sp = (uint32_t)sp;
+ fp = (uint32_t)fp;
+ }
+#endif
+
+ if (fp < sp + 8)
+ fp = sp + 8;
+
+ for (i = Stk->ncall - 1; i >= 0; i--) {
+ if (sp <= Stk->stack[i].sp && fp > Stk->stack[i].sp) {
+ Stk->ncall = i;
+ break;
+ }
+ }
+
+#if defined(i386) || defined(__amd64)
+ if (i < 0) {
+ /* probably __mul64() or friends -- try harder */
+ int j;
+ for (j = 0; i < 0 && j < 8; j++) { /* up to 8 args */
+ sp -= 4;
+ for (i = Stk->ncall - 1; i >= 0; i--) {
+ if (sp <= Stk->stack[i].sp &&
+ fp > Stk->stack[i].sp) {
+ Stk->ncall = i;
+ break;
+ }
+ }
+ }
+ }
+#endif
+
+ if ((i >= 0) && (!cflag)) {
+ show_function_return(pri, Lsp->pr_reg[R_R0], 0,
+ Stk, Stk->stack[i].fcn->dyn, Stk->stack[i].fcn);
+ }
+}
+
+#if defined(__sparc)
+#define FPADJUST 0
+#elif defined(__amd64)
+#define FPADJUST 8
+#elif defined(__i386)
+#define FPADJUST 4
+#endif
+
+void
+trap_one_stack(prgregset_t reg)
+{
+ struct dynlib *Dp;
+ struct bkpt *Bp;
+ struct callstack *Stk;
+ GElf_Sym sym;
+ char sym_name[32];
+ uintptr_t sp = reg[R_SP];
+ uintptr_t pc = reg[R_PC];
+ uintptr_t fp;
+ uintptr_t rpc;
+ uint_t nframe = 0;
+ uint_t maxframe = 8;
+ struct {
+ uintptr_t sp; /* %sp within called function */
+ uintptr_t pc; /* %pc within called function */
+ uintptr_t rsp; /* the return sp */
+ uintptr_t rpc; /* the return pc */
+ } *frame = my_malloc(maxframe * sizeof (*frame), NULL);
+
+ /*
+ * Gather stack frames bottom to top.
+ */
+ while (sp != 0) {
+ fp = sp; /* remember higest non-null sp */
+ frame[nframe].sp = sp;
+ frame[nframe].pc = pc;
+ sp = previous_fp(sp, &pc);
+ frame[nframe].rsp = sp;
+ frame[nframe].rpc = pc;
+ if (++nframe == maxframe) {
+ maxframe *= 2;
+ frame = my_realloc(frame, maxframe * sizeof (*frame),
+ NULL);
+ }
+ }
+
+ /*
+ * Scan for function return breakpoints top to bottom.
+ */
+ while (nframe--) {
+ /* lookup the called function in the symbol tables */
+ if (Plookup_by_addr(Proc, frame[nframe].pc, sym_name,
+ sizeof (sym_name), &sym) != 0)
+ continue;
+
+ pc = sym.st_value; /* entry point of the function */
+ rpc = frame[nframe].rpc; /* caller's return pc */
+
+ /* lookup the function in the breakpoint table */
+ if ((Bp = get_bkpt(pc)) == NULL || (Dp = Bp->dyn) == NULL)
+ continue;
+
+ if (!(Bp->flags & BPT_INTERNAL) &&
+ rpc >= Dp->base && rpc < Dp->base + Dp->size)
+ continue;
+
+ sp = frame[nframe].rsp + FPADJUST; /* %sp at time of call */
+ if ((Stk = callstack_info(sp, fp, 0)) == NULL)
+ continue; /* can't happen? */
+
+ if (create_bkpt(rpc, 1, 1) != NULL) {
+ Stk->stack[Stk->ncall].sp = sp;
+ Stk->stack[Stk->ncall].pc = rpc;
+ Stk->stack[Stk->ncall].fcn = Bp;
+ Stk->ncall++;
+ }
+ }
+
+ free(frame);
+}
+
+int
+lwp_stack_traps(void *cd, const lwpstatus_t *Lsp)
+{
+ ph_map_t *ph_map = (ph_map_t *)cd;
+ prgregset_t reg;
+
+ (void) memcpy(reg, Lsp->pr_reg, sizeof (prgregset_t));
+ make_lwp_stack(Lsp, ph_map->pmap, ph_map->nmap);
+ trap_one_stack(reg);
+
+ return (interrupt | sigusr1);
+}
+
+/* ARGSUSED */
+int
+thr_stack_traps(const td_thrhandle_t *Thp, void *cd)
+{
+ prgregset_t reg;
+
+ /*
+ * We have already dealt with all the lwps.
+ * We only care about unbound threads here (TD_PARTIALREG).
+ */
+ if (td_thr_getgregs(Thp, reg) != TD_PARTIALREG)
+ return (0);
+
+ make_thr_stack(Thp, reg);
+ trap_one_stack(reg);
+
+ return (interrupt | sigusr1);
+}
+
+#if defined(__sparc)
+
+uintptr_t
+previous_fp(uintptr_t sp, uintptr_t *rpc)
+{
+ uintptr_t fp = 0;
+ uintptr_t pc = 0;
+
+#ifdef _LP64
+ if (data_model == PR_MODEL_LP64) {
+ struct rwindow64 rwin;
+ if (Pread(Proc, &rwin, sizeof (rwin), sp + STACK_BIAS)
+ == sizeof (rwin)) {
+ fp = (uintptr_t)rwin.rw_fp;
+ pc = (uintptr_t)rwin.rw_rtn;
+ }
+ if (fp != 0 &&
+ Pread(Proc, &rwin, sizeof (rwin), fp + STACK_BIAS)
+ != sizeof (rwin))
+ fp = pc = 0;
+ } else {
+ struct rwindow32 rwin;
+#else /* _LP64 */
+ struct rwindow rwin;
+#endif /* _LP64 */
+ if (Pread(Proc, &rwin, sizeof (rwin), sp) == sizeof (rwin)) {
+ fp = (uint32_t)rwin.rw_fp;
+ pc = (uint32_t)rwin.rw_rtn;
+ }
+ if (fp != 0 &&
+ Pread(Proc, &rwin, sizeof (rwin), fp) != sizeof (rwin))
+ fp = pc = 0;
+#ifdef _LP64
+ }
+#endif
+ if (rpc)
+ *rpc = pc;
+ return (fp);
+}
+
+/* ARGSUSED */
+uintptr_t
+get_return_address(uintptr_t *psp)
+{
+ instr_t inst;
+ private_t *pri = get_private();
+ const lwpstatus_t *Lsp = pri->lwpstat;
+ uintptr_t rpc;
+
+ rpc = (uintptr_t)Lsp->pr_reg[R_O7] + 8;
+ if (data_model != PR_MODEL_LP64)
+ rpc = (uint32_t)rpc;
+
+ /* check for structure return (bletch!) */
+ if (Pread(Proc, &inst, sizeof (inst), rpc) == sizeof (inst) &&
+ inst < 0x1000)
+ rpc += sizeof (instr_t);
+
+ return (rpc);
+}
+
+int
+get_arguments(long *argp)
+{
+ private_t *pri = get_private();
+ const lwpstatus_t *Lsp = pri->lwpstat;
+ int i;
+
+ if (data_model != PR_MODEL_LP64)
+ for (i = 0; i < 4; i++)
+ argp[i] = (uint_t)Lsp->pr_reg[R_O0+i];
+ else
+ for (i = 0; i < 4; i++)
+ argp[i] = (long)Lsp->pr_reg[R_O0+i];
+ return (4);
+}
+
+#endif /* __sparc */
+
+#if defined(__i386) || defined(__amd64)
+
+uintptr_t
+previous_fp(uintptr_t fp, uintptr_t *rpc)
+{
+ uintptr_t frame[2];
+ uintptr_t trash[2];
+
+ if (Pread(Proc, frame, sizeof (frame), fp) != sizeof (frame) ||
+ (frame[0] != 0 &&
+ Pread(Proc, trash, sizeof (trash), frame[0]) != sizeof (trash)))
+ frame[0] = frame[1] = 0;
+
+ if (rpc)
+ *rpc = frame[1];
+ return (frame[0]);
+}
+
+#endif
+
+#if defined(__amd64) || defined(__i386)
+
+/*
+ * Examine the instruction at the return location of a function call
+ * and return the byte count by which the stack is adjusted on return.
+ * It the instruction at the return location is an addl, as expected,
+ * then adjust the return pc by the size of that instruction so that
+ * we will place the return breakpoint on the following instruction.
+ * This allows programs that interrogate their own stacks and record
+ * function calls and arguments to work correctly even while we interfere.
+ * Return the count on success, -1 on failure.
+ */
+int
+return_count32(uint32_t *ppc)
+{
+ uintptr_t pc = *ppc;
+ struct bkpt *Bp;
+ int count;
+ uchar_t instr[6]; /* instruction at pc */
+
+ if ((count = Pread(Proc, instr, sizeof (instr), pc)) < 0)
+ return (-1);
+
+ /* find the replaced instruction at pc (if any) */
+ if ((Bp = get_bkpt(pc)) != NULL && (Bp->flags & BPT_ACTIVE))
+ instr[0] = (uchar_t)Bp->instr;
+
+ if (count != sizeof (instr) &&
+ (count < 3 || instr[0] != 0x83))
+ return (-1);
+
+ /*
+ * A bit of disassembly of the instruction is required here.
+ */
+ if (instr[1] != 0xc4) { /* not an addl mumble,%esp inctruction */
+ count = 0;
+ } else if (instr[0] == 0x81) { /* count is a longword */
+ count = instr[2]+(instr[3]<<8)+(instr[4]<<16)+(instr[5]<<24);
+ *ppc += 6;
+ } else if (instr[0] == 0x83) { /* count is a byte */
+ count = instr[2];
+ *ppc += 3;
+ } else { /* not an addl inctruction */
+ count = 0;
+ }
+
+ return (count);
+}
+
+uintptr_t
+get_return_address32(uintptr_t *psp)
+{
+ uint32_t sp = *psp;
+ uint32_t rpc;
+ int count;
+
+ *psp += 4; /* account for popping the stack on return */
+ if (Pread(Proc, &rpc, sizeof (rpc), sp) != sizeof (rpc))
+ return (0);
+ if ((count = return_count32(&rpc)) < 0)
+ count = 0;
+ *psp += count; /* expected sp on return */
+ return (rpc);
+}
+
+uintptr_t
+get_return_address(uintptr_t *psp)
+{
+#ifdef _LP64
+ uintptr_t rpc;
+ uintptr_t sp = *psp;
+
+ if (data_model == PR_MODEL_LP64) {
+ if (Pread(Proc, &rpc, sizeof (rpc), sp) != sizeof (rpc))
+ return (0);
+ /*
+ * Ignore arguments pushed on the stack. See comments in
+ * get_arguments().
+ */
+ return (rpc);
+ } else
+#endif
+ return (get_return_address32(psp));
+}
+
+
+int
+get_arguments32(long *argp)
+{
+ private_t *pri = get_private();
+ const lwpstatus_t *Lsp = pri->lwpstat;
+ uint32_t frame[5]; /* return pc + 4 args */
+ int narg;
+ int count;
+ int i;
+
+ narg = Pread(Proc, frame, sizeof (frame),
+ (uintptr_t)Lsp->pr_reg[R_SP]);
+ narg -= sizeof (greg32_t);
+ if (narg <= 0)
+ return (0);
+ narg /= sizeof (greg32_t); /* no more than 4 */
+
+ /*
+ * Given the return PC, determine the number of arguments.
+ */
+ if ((count = return_count32(&frame[0])) < 0)
+ narg = 0;
+ else {
+ count /= sizeof (greg32_t);
+ if (narg > count)
+ narg = count;
+ }
+
+ for (i = 0; i < narg; i++)
+ argp[i] = (long)frame[i+1];
+
+ return (narg);
+}
+
+int
+get_arguments(long *argp)
+{
+#ifdef _LP64
+ private_t *pri = get_private();
+ const lwpstatus_t *Lsp = pri->lwpstat;
+
+ if (data_model == PR_MODEL_LP64) {
+ /*
+ * On amd64, we do not know how many arguments are passed to
+ * each function. While it may be possible to detect if we
+ * have more than 6 arguments, it is of marginal value.
+ * Instead, assume that we always have 6 arguments, which are
+ * passed via registers.
+ */
+ argp[0] = Lsp->pr_reg[REG_RDI];
+ argp[1] = Lsp->pr_reg[REG_RSI];
+ argp[2] = Lsp->pr_reg[REG_RDX];
+ argp[3] = Lsp->pr_reg[REG_RCX];
+ argp[4] = Lsp->pr_reg[REG_R8];
+ argp[5] = Lsp->pr_reg[REG_R9];
+ return (6);
+ } else
+#endif
+ return (get_arguments32(argp));
+}
+
+#endif /* __amd64 || __i386 */
diff --git a/usr/src/cmd/truss/htbl.c b/usr/src/cmd/truss/htbl.c
new file mode 100644
index 0000000..b8f3184
--- /dev/null
+++ b/usr/src/cmd/truss/htbl.c
@@ -0,0 +1,262 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <synch.h>
+#include <thread.h>
+#include <memory.h>
+#include <assert.h>
+#include <libproc.h>
+#include "ramdata.h"
+#include "proto.h"
+#include "htbl.h"
+
+
+htbl_t *
+init_hash(unsigned int size)
+{
+ htbl_t *htp;
+ hashb_t *temp;
+ int i;
+
+ if ((size & (size - 1)) != 0)
+ abend("Size must be power of two", NULL);
+
+ htp = (htbl_t *)my_malloc(sizeof (htbl_t), NULL);
+ htp->size = size;
+ htp->tbl = (hashb_t *)
+ my_calloc((size_t)size, sizeof (hashb_t), NULL);
+
+ /* Init mutexes */
+ for (i = 0; i < size; i++) {
+ temp = &htp->tbl[i];
+ (void) mutex_init(&temp->block, USYNC_THREAD, NULL);
+ }
+
+ return (htp);
+}
+
+void
+destroy_hash(htbl_t *htp)
+{
+ int i;
+ hentry_t *tmp;
+ hentry_t *prev;
+ hashb_t *cur;
+
+ for (i = 0; i < htp->size; i++) {
+ cur = &htp->tbl[i];
+ (void) mutex_destroy(&cur->block);
+ tmp = cur->first;
+
+ while (tmp != NULL) {
+ prev = tmp;
+ tmp = tmp->next;
+
+ free(prev->key);
+ prev->key = NULL;
+ free(prev->lib);
+ prev->lib = NULL;
+
+ free((char *)prev);
+ if (tmp != NULL)
+ tmp->prev = NULL;
+ }
+ }
+ free((char *)htp->tbl);
+ htp->tbl = NULL;
+ free(htp);
+}
+
+static unsigned int
+hash_str(char *str, unsigned int sz)
+{
+ uint_t hash = 0;
+ uint_t g;
+ char *p;
+
+ assert(str != NULL);
+ for (p = str; *p != '\0'; p++) {
+ hash = (hash << 4) + *p;
+ if ((g = (hash & 0xf0000000)) != 0) {
+ hash ^= (g >> 24);
+ hash ^= g;
+ }
+ }
+
+ return (hash & (sz - 1));
+}
+
+
+void
+add_fcall(htbl_t *htp, char *lib, char *key, unsigned long cnt)
+{
+ unsigned int bucket;
+ hentry_t *tmp;
+ hentry_t *new;
+ hashb_t *cur;
+
+ bucket = hash_str(key, htp->size);
+ cur = &htp->tbl[bucket];
+
+ (void) mutex_lock(&cur->block);
+
+ tmp = cur->first;
+ while (tmp != NULL) {
+ if (strcmp(tmp->key, key) == 0) {
+ if (strcmp(tmp->lib, lib) == 0) {
+ tmp->count += cnt;
+ (void) mutex_unlock(&cur->block);
+ return;
+ }
+ }
+ tmp = tmp->next;
+ }
+
+ /*
+ * If we're still here, there was no such fcall recorded
+ * so we make a new entry and add it to the table
+ */
+
+ new = (hentry_t *)my_malloc(sizeof (hentry_t), NULL);
+ new->key = strdup(key);
+ if (new->key == NULL)
+ abend("Out of memory in htbl.c", NULL);
+ new->lib = strdup(lib);
+ if (new->lib == NULL)
+ abend("Out of memory in htbl.c", NULL);
+ new->count = cnt;
+ new->prev = NULL;
+ new->next = cur->first;
+ tmp = new->next;
+ if (tmp != NULL) {
+ tmp->prev = new;
+ }
+ cur->first = new;
+
+ (void) mutex_unlock(&cur->block);
+}
+
+/*
+ * iterate_hash locks the table and returns an enumeration struct
+ * using this it is possible to iterate through the entries of a hash table
+ * once finished, use iter_free to unlock the table and free the struct
+ */
+
+hiter_t *
+iterate_hash(htbl_t *tbl)
+{
+ int b;
+ int i;
+ hiter_t *new;
+ hashb_t *cur;
+ hentry_t *tmp = NULL;
+
+ new = (hiter_t *)my_malloc(sizeof (hiter_t), NULL);
+ new->table = tbl;
+
+ for (i = 0; i < tbl->size; i++) {
+ cur = &tbl->tbl[i];
+ (void) mutex_lock(&cur->block);
+ if (tmp == NULL) {
+ tmp = cur->first;
+ b = i;
+ }
+ }
+
+ new->next = tmp;
+ new->bucket = b;
+
+ return (new);
+}
+
+void
+iter_free(hiter_t *itr)
+{
+ int i;
+ hashb_t *cur;
+ htbl_t *tbl;
+
+ tbl = itr->table;
+ for (i = 0; i < tbl->size; i++) {
+ cur = &tbl->tbl[i];
+ (void) mutex_unlock(&cur->block);
+ }
+
+ free(itr);
+}
+
+hentry_t *
+iter_next(hiter_t *itr)
+{
+ int i;
+ hentry_t *tmp;
+ hentry_t *ret;
+ hashb_t *cur = NULL;
+ htbl_t *hash;
+
+ ret = itr->next;
+
+
+ if (ret == NULL)
+ return (ret);
+
+ hash = itr->table;
+ tmp = ret->next;
+ i = itr->bucket;
+
+ if (tmp == NULL) {
+ for (i = i + 1; i < hash->size; i++) {
+ cur = &hash->tbl[i];
+ tmp = cur->first;
+ if (tmp != NULL)
+ break;
+ }
+ }
+
+ itr->next = tmp;
+ itr->bucket = i;
+
+ return (ret);
+}
+
+size_t
+elements_in_table(htbl_t *tbl)
+{
+ size_t elem = 0;
+ hiter_t *itr = iterate_hash(tbl);
+ hentry_t *tmp = iter_next(itr);
+ while (tmp != NULL) {
+ elem++;
+ tmp = iter_next(itr);
+ }
+ iter_free(itr);
+ return (elem);
+}
diff --git a/usr/src/cmd/truss/htbl.h b/usr/src/cmd/truss/htbl.h
new file mode 100644
index 0000000..fa37988
--- /dev/null
+++ b/usr/src/cmd/truss/htbl.h
@@ -0,0 +1,95 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _HTBL_H
+#define _HTBL_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+
+typedef struct hentry {
+ struct hentry *next; /* next entry in hash chain */
+ struct hentry *prev; /* previous entry in hash chain */
+ char *lib; /* library name */
+ char *key; /* hash key (function name) */
+ unsigned long count; /* number of occurances of fn */
+} hentry_t;
+
+typedef struct hashb {
+ hentry_t *first; /* first entry in bucket */
+ mutex_t block; /* bucket lock */
+} hashb_t;
+
+typedef struct htbl {
+ unsigned int size; /* size of tbl in buckets */
+ hashb_t *tbl; /* ptr to buckets */
+} htbl_t;
+
+typedef struct hiter {
+ int bucket; /* bucket in current iteration */
+ hentry_t *next; /* next entry in iteration */
+ htbl_t *table; /* ptr to table */
+} hiter_t;
+
+/*
+ * HD_hashntry specifies that the entry written to disk contains information
+ * about function calls and is stored in the hash table. When read back from
+ * disk this is merged into the parent's hash table
+ *
+ * HD_cts_syscts specifies that the entry written to disk is a struct counts
+ * struct syscount pair. This contains information about system calls,
+ * signals, and faults. When read back from disk, the information is added
+ * to the struct count / struct syscount information kept by the parent.
+ */
+
+typedef enum hdtype { HD_hashntry, HD_cts_syscts } hdtype_t;
+
+typedef struct hdntry {
+ hdtype_t type; /* type of entry we've written to disk */
+ size_t sz_lib; /* size of library string on disk */
+ size_t sz_key; /* size of key string on disk */
+ unsigned long count; /* count of occurrances of key */
+} hdntry_t;
+
+
+extern htbl_t *init_hash(unsigned int);
+extern void destroy_hash(htbl_t *);
+extern hiter_t *iterate_hash(htbl_t *);
+extern hentry_t *iter_next(hiter_t *);
+extern void iter_free(hiter_t *);
+extern void add_fcall(htbl_t *, char *, char *, unsigned long);
+extern size_t elements_in_table(htbl_t *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _HTBL_H */
diff --git a/usr/src/cmd/truss/ipc.c b/usr/src/cmd/truss/ipc.c
new file mode 100644
index 0000000..2bb3465
--- /dev/null
+++ b/usr/src/cmd/truss/ipc.c
@@ -0,0 +1,417 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
+/* All Rights Reserved */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <string.h>
+#include <signal.h>
+#include <stropts.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/termio.h>
+#include <libproc.h>
+#include "ramdata.h"
+#include "proto.h"
+
+/*
+ * Routines related to interprocess communication
+ * among the truss processes which are controlling
+ * multiple traced processes.
+ */
+
+/*
+ * Function prototypes for static routines in this module.
+ */
+void Ecritical(int);
+void Xcritical(int);
+
+/*
+ * Ensure everyone keeps out of each other's way
+ * while writing lines of trace output.
+ */
+void
+Flush()
+{
+ /*
+ * Except for regions bounded by Eserialize()/Xserialize(),
+ * this is the only place anywhere in the program where a
+ * write() to the trace output file takes place, so here
+ * is where we detect errors writing to the output.
+ */
+
+ errno = 0;
+
+ Ecritical(0);
+ (void) fflush(stdout);
+ Xcritical(0);
+
+ if (ferror(stdout) && errno) /* error on write(), probably EPIPE */
+ interrupt = SIGTERM; /* post an interrupt */
+}
+
+/*
+ * Eserialize() and Xserialize() are used to bracket
+ * a region which may produce large amounts of output,
+ * such as showargs()/dumpargs().
+ */
+
+void
+Eserialize()
+{
+ /* serialize output */
+ Ecritical(0);
+}
+
+void
+Xserialize()
+{
+ (void) fflush(stdout);
+ Xcritical(0);
+}
+
+/*
+ * Enter critical region --- Wait on mutex, lock out other processes.
+ * Lock zero is used to serialize output in situations where multiple processes
+ * may be writing to stdout/stderr and order must be preserved. Most of these
+ * are in expound.c
+ * Lock one is used to protect the table of processes currently being traced
+ * every time a pid is added or removed from the table Ecritical(1)/Xcritical(1)
+ * get called.
+ */
+void
+Ecritical(int num)
+{
+ int rv;
+
+ if (num == 0)
+ rv = mutex_lock(&gps->ps_mutex0);
+ else if (num == 1)
+ rv = mutex_lock(&gps->ps_mutex1);
+ else
+ abend("Invalid mutex specified", NULL);
+
+ if (rv != 0) {
+ char mnum[2];
+ mnum[0] = '0' + num;
+ mnum[1] = '\0';
+ errno = rv;
+ perror(command);
+ errmsg("cannot grab mutex #", mnum);
+ }
+}
+
+/*
+ * Exit critical region ---
+ * Release other processes waiting on mutex.
+ */
+void
+Xcritical(int num)
+{
+ int rv;
+
+ if (num == 0)
+ rv = mutex_unlock(&gps->ps_mutex0);
+ else if (num == 1)
+ rv = mutex_unlock(&gps->ps_mutex1);
+ else
+ abend("Invalid mutex specified", NULL);
+
+
+ if (rv != 0) {
+ char mnum[2];
+ mnum[0] = '0' + num;
+ mnum[1] = '\0';
+ errno = rv;
+ perror(command);
+ errmsg("cannot release mutex #", mnum);
+ }
+}
+
+/*
+ * Add process to set of those being traced.
+ */
+void
+procadd(pid_t spid, const char *lwplist)
+{
+ int i;
+ int j = -1;
+
+ if (gps == NULL)
+ return;
+
+ Ecritical(1);
+ for (i = 0; i < sizeof (gps->tpid) / sizeof (gps->tpid[0]); i++) {
+ if (gps->tpid[i] == 0) {
+ if (j == -1) /* remember first vacant slot */
+ j = i;
+ if (gps->spid[i] == 0) /* this slot is better */
+ break;
+ }
+ }
+ if (i < sizeof (gps->tpid) / sizeof (gps->tpid[0]))
+ j = i;
+ if (j >= 0) {
+ gps->tpid[j] = getpid();
+ gps->spid[j] = spid;
+ gps->lwps[j] = lwplist;
+ }
+ Xcritical(1);
+}
+
+/*
+ * Delete process from set of those being traced.
+ */
+void
+procdel()
+{
+ int i;
+ pid_t tpid;
+
+ if (gps == NULL)
+ return;
+
+ tpid = getpid();
+
+ Ecritical(1);
+ for (i = 0; i < sizeof (gps->tpid) / sizeof (gps->tpid[0]); i++) {
+ if (gps->tpid[i] == tpid) {
+ gps->tpid[i] = 0;
+ break;
+ }
+ }
+ Xcritical(1);
+}
+
+/*
+ * Determine if the lwp for this process should be traced.
+ */
+int
+lwptrace(pid_t spid, lwpid_t lwpid)
+{
+ int i;
+ pid_t tpid;
+ const char *lwps;
+
+ if (gps == NULL)
+ return (0);
+
+ tpid = getpid();
+
+ Ecritical(1);
+ for (i = 0; i < sizeof (gps->tpid) / sizeof (gps->tpid[0]); i++) {
+ if (gps->tpid[i] == tpid &&
+ gps->spid[i] == spid)
+ break;
+ }
+ lwps = gps->lwps[i];
+ Xcritical(1);
+
+ return (proc_lwp_in_set(lwps, lwpid));
+}
+
+/*
+ * Check for open of a /proc/nnnnn file.
+ * Return 0 if this is not an open of a /proc file.
+ * Return 1 if the process opened itself.
+ * Return 2 if the process failed to open another process
+ * in truss's set of controlled processes.
+ * Return 3 if the process successfully opened another process
+ * in truss's set of controlled processes.
+ * We notify and wait for the other controlling truss process
+ * to terminate before returning in cases 2 and 3.
+ */
+/* ARGSUSED */
+int
+checkproc(private_t *pri)
+{
+ char *path = pri->sys_path;
+ const pstatus_t *Psp = Pstatus(Proc);
+ struct ps_lwphandle *Lwp = pri->Lwp;
+ const lwpstatus_t *Lsp = pri->lwpstat;
+ int what = Lsp->pr_what; /* one of the SYS_open* syscalls */
+ int err = Lsp->pr_errno;
+ int pid;
+ int i;
+ const char *dirname;
+ char *next;
+ char *sp1;
+ char *sp2;
+ prgreg_t pc;
+
+ /*
+ * A bit heuristic ...
+ * Test for the cases:
+ * 1234
+ * 1234/as
+ * 1234/ctl
+ * 1234/lwp/24/lwpctl
+ * .../1234
+ * .../1234/as
+ * .../1234/ctl
+ * .../1234/lwp/24/lwpctl
+ * Insert a '\0', if necessary, so the path becomes ".../1234".
+ *
+ * Along the way, watch out for /proc/self and /proc/1234/lwp/agent
+ */
+ if ((sp1 = strrchr(path, '/')) == NULL) /* last component */
+ /* EMPTY */;
+ else if (isdigit(*(sp1+1))) {
+ sp1 += strlen(sp1);
+ while (--sp1 > path && isdigit(*sp1))
+ ;
+ if (*sp1 != '/')
+ return (0);
+ } else if (strcmp(sp1+1, "as") == 0 ||
+ strcmp(sp1+1, "ctl") == 0) {
+ *sp1 = '\0';
+ } else if (strcmp(sp1+1, "lwpctl") == 0) {
+ /*
+ * .../1234/lwp/24/lwpctl
+ * ............ ^-- sp1
+ */
+ if (sp1-6 >= path && strncmp(sp1-6, "/agent", 6) == 0)
+ sp1 -= 6;
+ else {
+ while (--sp1 > path && isdigit(*sp1))
+ ;
+ }
+ if (*sp1 != '/' ||
+ (sp1 -= 4) <= path ||
+ strncmp(sp1, "/lwp", 4) != 0)
+ return (0);
+ *sp1 = '\0';
+ } else if (strcmp(sp1+1, "self") != 0) {
+ return (0);
+ }
+
+ if ((sp2 = strrchr(path, '/')) == NULL)
+ dirname = path;
+ else
+ dirname = sp2 + 1;
+
+ if (strcmp(dirname, "self") == 0) {
+ pid = Psp->pr_pid;
+ } else if ((pid = strtol(dirname, &next, 10)) < 0 ||
+ *next != '\0') { /* dirname not a number */
+ if (sp1 != NULL)
+ *sp1 = '/';
+ return (0);
+ }
+ if (sp2 == NULL)
+ dirname = ".";
+ else {
+ *sp2 = '\0';
+ dirname = path;
+ }
+
+ if (!Pisprocdir(Proc, dirname) || /* file not in a /proc directory */
+ pid == getpid() || /* process opened truss's /proc file */
+ pid == 0) { /* process opened process 0 */
+ if (sp1 != NULL)
+ *sp1 = '/';
+ if (sp2 != NULL)
+ *sp2 = '/';
+ return (0);
+ }
+ if (sp1 != NULL)
+ *sp1 = '/';
+ if (sp2 != NULL)
+ *sp2 = '/';
+
+ /*
+ * Process did open a /proc file ---
+ */
+ if (pid == Psp->pr_pid) { /* process opened its own /proc file */
+ /*
+ * In SunOS 5.6 and beyond, self-opens always succeed.
+ */
+ return (1);
+ }
+
+ /*
+ * Search for a matching pid in our set of controlled processes.
+ */
+ for (i = 0; i < sizeof (gps->tpid)/sizeof (gps->tpid[0]); i++) {
+ if (gps->spid[i] == pid) {
+ pid = gps->tpid[i];
+ break;
+ }
+ }
+ if (i >= sizeof (gps->tpid) / sizeof (gps->tpid[0])) {
+ /*
+ * The process opened a /proc file, but not one we care about.
+ */
+ return (0);
+ }
+
+ /*
+ * Notify and wait for the controlling process to terminate.
+ */
+ while (pid && gps->tpid[i] == pid) {
+ if (kill(pid, SIGUSR1) == -1)
+ break;
+ (void) usleep(1000000);
+ }
+ Ecritical(1);
+ if (gps->tpid[i] == 0)
+ gps->spid[i] = 0;
+ Xcritical(1);
+
+ if (err) { /* prepare to reissue the failed open() system call */
+#if defined(__sparc)
+ (void) Lgetareg(Lwp, R_PC, &pc);
+ if (pri->sys_indirect) {
+ (void) Lputareg(Lwp, R_G1, (prgreg_t)SYS_syscall);
+ (void) Lputareg(Lwp, R_O0, (prgreg_t)what);
+ for (i = 0; i < 5; i++)
+ (void) Lputareg(Lwp, R_O1+i, pri->sys_args[i]);
+ } else {
+ (void) Lputareg(Lwp, R_G1, (prgreg_t)what);
+ for (i = 0; i < 6; i++)
+ (void) Lputareg(Lwp, R_O0+i, pri->sys_args[i]);
+ }
+ (void) Lputareg(Lwp, R_nPC, pc);
+#elif defined(__amd64)
+ (void) Lgetareg(Lwp, R_PC, &pc);
+ (void) Lputareg(Lwp, REG_RAX, (prgreg_t)what);
+#elif defined(__i386)
+ (void) Lgetareg(Lwp, R_PC, &pc);
+ (void) Lputareg(Lwp, EAX, (prgreg_t)what);
+#else
+#error "unrecognized architecture"
+#endif
+ (void) Pissyscall_prev(Proc, pc, (uintptr_t *)&pc);
+ (void) Lputareg(Lwp, R_PC, pc);
+ return (2);
+ }
+
+ return (3);
+}
diff --git a/usr/src/cmd/truss/listopts.c b/usr/src/cmd/truss/listopts.c
new file mode 100644
index 0000000..17d9a50
--- /dev/null
+++ b/usr/src/cmd/truss/listopts.c
@@ -0,0 +1,661 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
+ */
+
+/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
+/* All Rights Reserved */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <string.h>
+#include <memory.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <libproc.h>
+#include "ramdata.h"
+#include "systable.h"
+#include "proto.h"
+
+/* XXX A bug in the <string.h> header file requires this */
+extern char *strtok_r(char *s1, const char *s2, char **lasts);
+
+/*
+ * option procesing ---
+ * Routines for scanning syscall, signal, fault
+ * and file descriptor lists.
+ */
+
+/*
+ * Function prototypes for static routines in this module.
+ */
+void upcase(char *);
+
+const char white[] = " \t\n"; /* white space characters */
+const char sepr[] = " ,\t\n"; /* list separator characters */
+const char csepr[] = " :,\t\n"; /* same, with ':' added */
+
+/*
+ * Scan list of syscall names.
+ * Return 0 on success, != 0 on any failure.
+ */
+int
+syslist(char *str, /* string of syscall names */
+ sysset_t *setp, /* syscall set */
+ int *fp) /* first-time flag */
+{
+ char *name;
+ int exclude = FALSE;
+ int rc = 0;
+ char *lasts;
+
+ name = strtok_r(str, sepr, &lasts);
+
+ if (name != NULL && *name == '!') { /* exclude from set */
+ exclude = TRUE;
+ if (*++name == '\0')
+ name = strtok_r(NULL, sepr, &lasts);
+ } else if (!*fp) { /* first time, clear the set */
+ premptyset(setp);
+ *fp = TRUE;
+ }
+
+ for (; name; name = strtok_r(NULL, sepr, &lasts)) {
+ int sys;
+ int sysx;
+ int sysxx;
+ int sys64;
+ char *next;
+
+ if (*name == '!') { /* exclude remainder from set */
+ exclude = TRUE;
+ while (*++name == '!')
+ /* empty */;
+ if (*name == '\0')
+ continue;
+ }
+
+ sys = strtol(name, &next, 0);
+ sysx = sysxx = sys64 = 0;
+ if (sys < 0 || sys > PRMAXSYS || *next != '\0')
+ sys = 0;
+ if (sys == 0) {
+ const struct systable *stp = systable;
+ for (; sys == 0 && stp->nargs >= 0; stp++)
+ if (stp->name && strcmp(stp->name, name) == 0)
+ sys = stp-systable;
+ }
+ if (sys == 0) {
+ const struct sysalias *sap = sysalias;
+ for (; sys == 0 && sap->name; sap++)
+ if (strcmp(sap->name, name) == 0)
+ sys = sap->number;
+ }
+ if (sys > 0 && sys <= PRMAXSYS) {
+ switch (sys) {
+ case SYS_fstatat: /* set both if either */
+ case SYS_fstatat64:
+ sys = SYS_fstatat;
+ sys64 = SYS_fstatat64;
+ goto def;
+
+ case SYS_stat: /* set all if either */
+ case SYS_stat64:
+ sys = SYS_stat;
+ sys64 = SYS_stat64;
+ sysx = SYS_fstatat;
+ sysxx = SYS_fstatat64;
+ goto def;
+
+ case SYS_lstat: /* set all if either */
+ case SYS_lstat64:
+ sys = SYS_lstat;
+ sys64 = SYS_lstat64;
+ sysx = SYS_fstatat;
+ sysxx = SYS_fstatat64;
+ goto def;
+
+ case SYS_fstat: /* set all if either */
+ case SYS_fstat64:
+ sys = SYS_fstat;
+ sys64 = SYS_fstat64;
+ sysx = SYS_fstatat;
+ sysxx = SYS_fstatat64;
+ goto def;
+
+ case SYS_getdents: /* set both if either */
+ case SYS_getdents64:
+ sys = SYS_getdents;
+ sys64 = SYS_getdents64;
+ goto def;
+
+ case SYS_mmap: /* set both if either */
+ case SYS_mmap64:
+ sys = SYS_mmap;
+ sys64 = SYS_mmap64;
+ goto def;
+
+ case SYS_statvfs: /* set both if either */
+ case SYS_statvfs64:
+ sys = SYS_statvfs;
+ sys64 = SYS_statvfs64;
+ goto def;
+
+ case SYS_fstatvfs: /* set both if either */
+ case SYS_fstatvfs64:
+ sys = SYS_fstatvfs;
+ sys64 = SYS_fstatvfs64;
+ goto def;
+
+ case SYS_setrlimit: /* set both if either */
+ case SYS_setrlimit64:
+ sys = SYS_setrlimit;
+ sys64 = SYS_setrlimit64;
+ goto def;
+
+ case SYS_getrlimit: /* set both if either */
+ case SYS_getrlimit64:
+ sys = SYS_getrlimit;
+ sys64 = SYS_getrlimit64;
+ goto def;
+
+ case SYS_pread: /* set both if either */
+ case SYS_pread64:
+ sys = SYS_pread;
+ sys64 = SYS_pread64;
+ goto def;
+
+ case SYS_pwrite: /* set both if either */
+ case SYS_pwrite64:
+ sys = SYS_pwrite;
+ sys64 = SYS_pwrite64;
+ goto def;
+
+ case SYS_openat: /* set all if any */
+ case SYS_openat64:
+ case SYS_open:
+ case SYS_open64:
+ sys = SYS_openat;
+ sys64 = SYS_openat64;
+ sysx = SYS_open;
+ sysxx = SYS_open64;
+ goto def;
+
+ case SYS_forksys: /* set both if either */
+ case SYS_vfork:
+ sysx = SYS_forksys;
+ sys = SYS_vfork;
+ goto def;
+
+ case SYS_sigprocmask: /* set both if either */
+ case SYS_lwp_sigmask:
+ sysx = SYS_sigprocmask;
+ sys = SYS_lwp_sigmask;
+ goto def;
+
+ case SYS_lseek: /* set both if either */
+ case SYS_llseek:
+ sysx = SYS_lseek;
+ sys = SYS_llseek;
+ goto def;
+
+ case SYS_rename: /* set both */
+ sysx = SYS_renameat;
+ goto def;
+
+ case SYS_link: /* set both */
+ sysx = SYS_linkat;
+ goto def;
+
+ case SYS_unlink: /* set both */
+ case SYS_rmdir: /* set both */
+ sysx = SYS_unlinkat;
+ goto def;
+
+ case SYS_symlink: /* set both */
+ sysx = SYS_symlinkat;
+ goto def;
+
+ case SYS_readlink: /* set both */
+ sysx = SYS_readlinkat;
+ goto def;
+
+ case SYS_chmod: /* set both */
+ case SYS_fchmod: /* set both */
+ sysx = SYS_fchmodat;
+ goto def;
+
+ case SYS_chown: /* set both */
+ case SYS_lchown: /* set both */
+ case SYS_fchown: /* set both */
+ sysx = SYS_fchownat;
+ goto def;
+
+ case SYS_mkdir: /* set both */
+ sysx = SYS_mkdirat;
+ goto def;
+
+ case SYS_mknod: /* set both */
+ sysx = SYS_mknodat;
+ goto def;
+
+ case SYS_access: /* set both */
+ sysx = SYS_faccessat;
+ goto def;
+
+ default:
+ def:
+ if (exclude) {
+ prdelset(setp, sys);
+ if (sysx)
+ prdelset(setp, sysx);
+ if (sysxx)
+ prdelset(setp, sysxx);
+ if (sys64)
+ prdelset(setp, sys64);
+ } else {
+ praddset(setp, sys);
+ if (sysx)
+ praddset(setp, sysx);
+ if (sysxx)
+ praddset(setp, sysxx);
+ if (sys64)
+ praddset(setp, sys64);
+ }
+ break;
+ }
+ } else if (strcmp(name, "all") == 0 ||
+ strcmp(name, "ALL") == 0) {
+ if (exclude) {
+ premptyset(setp);
+ } else {
+ prfillset(setp);
+ }
+ } else {
+ (void) fprintf(stderr,
+ "%s: unrecognized syscall: %s\n",
+ command, name);
+ rc = -1;
+ }
+ }
+
+ return (rc);
+}
+
+/*
+ * List of signals to trace.
+ * Return 0 on success, != 0 on any failure.
+ */
+int
+siglist(private_t *pri,
+ char *str, /* string of signal names */
+ sigset_t *setp, /* signal set */
+ int *fp) /* first-time flag */
+{
+ char *name;
+ int exclude = FALSE;
+ int rc = 0;
+ char *lasts;
+
+ upcase(str);
+ name = strtok_r(str, sepr, &lasts);
+
+ if (name != NULL && *name == '!') { /* exclude from set */
+ exclude = TRUE;
+ if (*++name == '\0')
+ name = strtok_r(NULL, sepr, &lasts);
+ } else if (!*fp) { /* first time, clear the set */
+ premptyset(setp);
+ *fp = TRUE;
+ }
+
+ for (; name; name = strtok_r(NULL, sepr, &lasts)) {
+ int sig;
+ char *next;
+
+ if (*name == '!') { /* exclude remainder from set */
+ exclude = TRUE;
+ while (*++name == '!')
+ /* empty */;
+ if (*name == '\0')
+ continue;
+ }
+
+ sig = strtol(name, &next, 0);
+ if (sig <= 0 || sig > PRMAXSIG || *next != '\0') {
+ for (sig = 1; sig <= PRMAXSIG; sig++) {
+ const char *sname = rawsigname(pri, sig);
+ if (sname == NULL)
+ continue;
+ if (strcmp(sname, name) == 0 ||
+ strcmp(sname+3, name) == 0)
+ break;
+ }
+ if (sig > PRMAXSIG)
+ sig = 0;
+ }
+ if (sig > 0 && sig <= PRMAXSIG) {
+ if (exclude) {
+ prdelset(setp, sig);
+ } else {
+ praddset(setp, sig);
+ }
+ } else if (strcmp(name, "ALL") == 0) {
+ if (exclude) {
+ premptyset(setp);
+ } else {
+ prfillset(setp);
+ }
+ } else {
+ (void) fprintf(stderr,
+ "%s: unrecognized signal name/number: %s\n",
+ command, name);
+ rc = -1;
+ }
+ }
+
+ return (rc);
+}
+
+/*
+ * List of faults to trace.
+ * return 0 on success, != 0 on any failure.
+ */
+int
+fltlist(char *str, /* string of fault names */
+ fltset_t *setp, /* fault set */
+ int *fp) /* first-time flag */
+{
+ char *name;
+ int exclude = FALSE;
+ int rc = 0;
+ char *lasts;
+
+ upcase(str);
+ name = strtok_r(str, sepr, &lasts);
+
+ if (name != NULL && *name == '!') { /* exclude from set */
+ exclude = TRUE;
+ if (*++name == '\0')
+ name = strtok_r(NULL, sepr, &lasts);
+ } else if (!*fp) { /* first time, clear the set */
+ premptyset(setp);
+ *fp = TRUE;
+ }
+
+ for (; name; name = strtok_r(NULL, sepr, &lasts)) {
+ int flt;
+ char *next;
+
+ if (*name == '!') { /* exclude remainder from set */
+ exclude = TRUE;
+ while (*++name == '!')
+ /* empty */;
+ if (*name == '\0')
+ continue;
+ }
+
+ flt = strtol(name, &next, 0);
+ if (flt <= 0 || flt > PRMAXFAULT || *next != '\0') {
+ for (flt = 1; flt <= PRMAXFAULT; flt++) {
+ char fname[32];
+
+ if (proc_fltname(flt, fname,
+ sizeof (fname)) == NULL)
+ continue;
+
+ if (strcmp(fname, name) == 0 ||
+ strcmp(fname+3, name) == 0)
+ break;
+ }
+ if (flt > PRMAXFAULT)
+ flt = 0;
+ }
+ if (flt > 0 && flt <= PRMAXFAULT) {
+ if (exclude) {
+ prdelset(setp, flt);
+ } else {
+ praddset(setp, flt);
+ }
+ } else if (strcmp(name, "ALL") == 0) {
+ if (exclude) {
+ premptyset(setp);
+ } else {
+ prfillset(setp);
+ }
+ } else {
+ (void) fprintf(stderr,
+ "%s: unrecognized fault name/number: %s\n",
+ command, name);
+ rc = -1;
+ }
+ }
+
+ return (rc);
+}
+
+/*
+ * Gather file descriptors to dump.
+ * Return 0 on success, != 0 on any failure.
+ */
+int
+fdlist(char *str, /* string of filedescriptors */
+ fileset_t *setp) /* set of boolean flags */
+{
+ char *name;
+ int exclude = FALSE;
+ int rc = 0;
+ char *lasts;
+
+ upcase(str);
+ name = strtok_r(str, sepr, &lasts);
+
+ if (name != NULL && *name == '!') { /* exclude from set */
+ exclude = TRUE;
+ if (*++name == '\0')
+ name = strtok_r(NULL, sepr, &lasts);
+ }
+
+ for (; name; name = strtok_r(NULL, sepr, &lasts)) {
+ int fd;
+ char *next;
+
+ if (*name == '!') { /* exclude remainder from set */
+ exclude = TRUE;
+ while (*++name == '!')
+ /* empty */;
+ if (*name == '\0')
+ continue;
+ }
+
+ fd = strtol(name, &next, 0);
+ if (fd >= 0 && fd < NOFILES_MAX && *next == '\0') {
+ fd++;
+ if (exclude) {
+ prdelset(setp, fd);
+ } else {
+ praddset(setp, fd);
+ }
+ } else if (strcmp(name, "ALL") == 0) {
+ if (exclude) {
+ premptyset(setp);
+ } else {
+ prfillset(setp);
+ }
+ } else {
+ (void) fprintf(stderr,
+ "%s: filedescriptor not in range[0..%d]: %s\n",
+ command, NOFILES_MAX-1, name);
+ rc = -1;
+ }
+ }
+
+ return (rc);
+}
+
+void
+upcase(char *str)
+{
+ int c;
+
+ while ((c = *str) != '\0')
+ *str++ = toupper(c);
+}
+
+/*
+ * 'arg' points to a string like:
+ * libc,libnsl,... : printf,read,write,...
+ * or
+ * libc,libnsl,... :: printf,read,write,...
+ * with possible filename pattern-matching metacharacters.
+ *
+ * Assumption: No library or function name can contain ',' or ':'.
+ */
+int
+liblist(char *arg, int hang)
+{
+ const char *star = "*";
+ struct dynpat *Dyp;
+ char *pat;
+ char *fpat;
+ char *lasts;
+ uint_t maxpat;
+
+ /* append a new dynpat structure to the end of the Dynpat list */
+ Dyp = my_malloc(sizeof (struct dynpat), NULL);
+ Dyp->next = NULL;
+ if (Lastpat == NULL)
+ Dynpat = Lastpat = Dyp;
+ else {
+ Lastpat->next = Dyp;
+ Lastpat = Dyp;
+ }
+ Dyp->flag = hang? BPT_HANG : 0;
+ Dyp->exclude_lib = 0;
+ Dyp->exclude = 0;
+ Dyp->internal = 0;
+ Dyp->Dp = NULL;
+
+ /*
+ * Find the beginning of the filename patterns
+ * and null-terminate the library name patterns.
+ */
+ if ((fpat = strchr(arg, ':')) != NULL)
+ *fpat++ = '\0';
+
+ /*
+ * Library name patterns.
+ */
+ pat = strtok_r(arg, sepr, &lasts);
+
+ /* '!' introduces an exclusion list */
+ if (pat != NULL && *pat == '!') {
+ Dyp->exclude_lib = 1;
+ pat += strspn(pat, "!");
+ if (*pat == '\0')
+ pat = strtok_r(NULL, sepr, &lasts);
+ /* force exclusion of all functions as well */
+ Dyp->exclude = 1;
+ Dyp->internal = 1;
+ fpat = NULL;
+ }
+
+ if (pat == NULL) {
+ /* empty list means all libraries */
+ Dyp->libpat = my_malloc(sizeof (char *), NULL);
+ Dyp->libpat[0] = star;
+ Dyp->nlibpat = 1;
+ } else {
+ /*
+ * We are now at the library list.
+ * Generate the list and count the library name patterns.
+ */
+ maxpat = 1;
+ Dyp->libpat = my_malloc(maxpat * sizeof (char *), NULL);
+ Dyp->nlibpat = 0;
+ Dyp->libpat[Dyp->nlibpat++] = pat;
+ while ((pat = strtok_r(NULL, sepr, &lasts)) != NULL) {
+ if (Dyp->nlibpat == maxpat) {
+ maxpat *= 2;
+ Dyp->libpat = my_realloc(Dyp->libpat,
+ maxpat * sizeof (char *), NULL);
+ }
+ Dyp->libpat[Dyp->nlibpat++] = pat;
+ }
+ }
+
+ /*
+ * Function name patterns.
+ */
+ if (fpat == NULL)
+ pat = NULL;
+ else {
+ /*
+ * We have already seen a ':'. Look for another.
+ * Double ':' means trace internal calls.
+ */
+ fpat += strspn(fpat, white);
+ if (*fpat == ':') {
+ Dyp->internal = 1;
+ *fpat++ = '\0';
+ }
+ pat = strtok_r(fpat, csepr, &lasts);
+ }
+
+ /* '!' introduces an exclusion list */
+ if (pat != NULL && *pat == '!') {
+ Dyp->exclude = 1;
+ Dyp->internal = 1;
+ pat += strspn(pat, "!");
+ if (*pat == '\0')
+ pat = strtok_r(NULL, sepr, &lasts);
+ }
+
+ if (pat == NULL) {
+ /* empty function list means exclude all functions */
+ Dyp->sympat = my_malloc(sizeof (char *), NULL);
+ Dyp->sympat[0] = star;
+ Dyp->nsympat = 1;
+ } else {
+ /*
+ * We are now at the function list.
+ * Generate the list and count the symbol name patterns.
+ */
+ maxpat = 1;
+ Dyp->sympat = my_malloc(maxpat * sizeof (char *), NULL);
+ Dyp->nsympat = 0;
+ Dyp->sympat[Dyp->nsympat++] = pat;
+ while ((pat = strtok_r(NULL, sepr, &lasts)) != NULL) {
+ if (Dyp->nsympat == maxpat) {
+ maxpat *= 2;
+ Dyp->sympat = my_realloc(Dyp->sympat,
+ maxpat * sizeof (char *), NULL);
+ }
+ Dyp->sympat[Dyp->nsympat++] = pat;
+ }
+ }
+
+ return (0);
+}
diff --git a/usr/src/cmd/truss/main.c b/usr/src/cmd/truss/main.c
new file mode 100644
index 0000000..151c749
--- /dev/null
+++ b/usr/src/cmd/truss/main.c
@@ -0,0 +1,2718 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
+ */
+
+/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
+
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <string.h>
+#include <memory.h>
+#include <signal.h>
+#include <wait.h>
+#include <limits.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/times.h>
+#include <sys/fstyp.h>
+#include <sys/fsid.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <sys/resource.h>
+#include <libproc.h>
+#include <priv.h>
+#include "ramdata.h"
+#include "proto.h"
+#include "htbl.h"
+
+/*
+ * The user can trace individual threads by using the 'pid/1,3-6,8-' syntax.
+ * This structure keeps track of pid/lwp specifications. If there are no LWPs
+ * specified, then 'lwps' will be NULL.
+ */
+typedef struct proc_set {
+ pid_t pid;
+ const char *lwps;
+} proc_set_t;
+
+/*
+ * Function prototypes for static routines in this file.
+ */
+void setup_basetime(hrtime_t, struct timeval *);
+int xcreat(char *);
+void setoutput(int);
+void report(private_t *, time_t);
+void prtim(timestruc_t *);
+void pids(char *, proc_set_t *);
+void psargs(private_t *);
+int control(private_t *, pid_t);
+int grabit(private_t *, proc_set_t *);
+void release(private_t *, pid_t);
+void intr(int);
+int wait4all(void);
+void letgo(private_t *);
+void child_to_file();
+void file_to_parent();
+void per_proc_init();
+int lib_sort(const void *, const void *);
+int key_sort(const void *, const void *);
+
+void *worker_thread(void *);
+void main_thread(int);
+
+/*
+ * Test for empty set.
+ * is_empty() should not be called directly.
+ */
+int is_empty(const uint32_t *, size_t);
+#define isemptyset(sp) \
+ is_empty((uint32_t *)(sp), sizeof (*(sp)) / sizeof (uint32_t))
+
+/*
+ * OR the second set into the first set.
+ * or_set() should not be called directly.
+ */
+void or_set(uint32_t *, const uint32_t *, size_t);
+#define prorset(sp1, sp2) \
+ or_set((uint32_t *)(sp1), (uint32_t *)(sp2), \
+ sizeof (*(sp1)) / sizeof (uint32_t))
+
+/* fetch or allocate thread-private data */
+private_t *
+get_private()
+{
+ void *value;
+ private_t *pri = NULL;
+
+ if (thr_getspecific(private_key, &value) == 0)
+ pri = value;
+ if (pri == NULL) {
+ pri = my_malloc(sizeof (*pri), NULL);
+ (void) memset(pri, 0, sizeof (*pri));
+ pri->sys_path = my_malloc(pri->sys_psize = 16, NULL);
+ pri->sys_string = my_malloc(pri->sys_ssize = 32, NULL);
+ if (thr_setspecific(private_key, pri) == ENOMEM)
+ abend("memory allocation failure", NULL);
+ }
+ return (pri);
+}
+
+/* destructor function for thread-private data */
+void
+free_private(void *value)
+{
+ private_t *pri = value;
+
+ if (pri->sys_path)
+ free(pri->sys_path);
+ if (pri->sys_string)
+ free(pri->sys_string);
+ if (pri->exec_string)
+ free(pri->exec_string);
+ if (pri->str_buffer)
+ free(pri->str_buffer);
+ free(pri);
+}
+
+/*
+ * This is called by the main thread (via create_thread())
+ * and is also called from other threads in worker_thread()
+ * while holding truss_lock. No further locking is required.
+ */
+void
+insert_lwpid(lwpid_t lwpid)
+{
+ int i;
+
+ truss_nlwp++;
+ for (i = 0; i < truss_maxlwp; i++) {
+ if (truss_lwpid[i] == 0)
+ break;
+ }
+ if (i == truss_maxlwp) {
+ /* double the size of the array */
+ truss_lwpid = my_realloc(truss_lwpid,
+ truss_maxlwp * 2 * sizeof (lwpid_t), NULL);
+ (void) memset(&truss_lwpid[truss_maxlwp], 0,
+ truss_maxlwp * sizeof (lwpid_t));
+ truss_maxlwp *= 2;
+ }
+ truss_lwpid[i] = lwpid;
+}
+
+/*
+ * This is called from the first worker thread to encounter one of
+ * (leave_hung || interrupt || sigusr1). It must notify all other
+ * worker threads of the same condition. truss_lock is held.
+ */
+void
+broadcast_signals(void)
+{
+ static int int_notified = FALSE;
+ static int usr1_notified = FALSE;
+ static int usr2_notified = FALSE;
+ lwpid_t my_id = thr_self();
+ lwpid_t lwpid;
+ int i;
+
+ if (interrupt && !int_notified) {
+ int_notified = TRUE;
+ for (i = 0; i < truss_maxlwp; i++) {
+ if ((lwpid = truss_lwpid[i]) != 0 && lwpid != my_id)
+ (void) thr_kill(lwpid, interrupt);
+ }
+ }
+ if (sigusr1 && !usr1_notified) {
+ usr1_notified = TRUE;
+ for (i = 0; i < truss_maxlwp; i++) {
+ if ((lwpid = truss_lwpid[i]) != 0 && lwpid != my_id)
+ (void) thr_kill(lwpid, SIGUSR1);
+ }
+ }
+ if (leave_hung && !usr2_notified) {
+ usr2_notified = TRUE;
+ for (i = 0; i < truss_maxlwp; i++) {
+ if ((lwpid = truss_lwpid[i]) != 0 && lwpid != my_id)
+ (void) thr_kill(lwpid, SIGUSR2);
+ }
+ }
+}
+
+static struct ps_lwphandle *
+grab_lwp(lwpid_t who)
+{
+ struct ps_lwphandle *Lwp;
+ int gcode;
+
+ if ((Lwp = Lgrab(Proc, who, &gcode)) == NULL) {
+ if (gcode != G_NOPROC) {
+ (void) fprintf(stderr,
+ "%s: cannot grab LWP %u in process %d,"
+ " reason: %s\n",
+ command, who, (int)Pstatus(Proc)->pr_pid,
+ Lgrab_error(gcode));
+ interrupt = SIGTERM; /* post an interrupt */
+ }
+ }
+ return (Lwp);
+}
+
+/*
+ * Iteration function called for each initial lwp in the controlled process.
+ */
+/* ARGSUSED */
+int
+create_thread(void *arg, const lwpstatus_t *Lsp)
+{
+ struct ps_lwphandle *new_Lwp;
+ lwpid_t lwpid;
+ int *count = arg;
+
+ if (lwptrace(Pstatus(Proc)->pr_pid, Lsp->pr_lwpid))
+ *count += 1;
+
+ if ((new_Lwp = grab_lwp(Lsp->pr_lwpid)) != NULL) {
+ if (thr_create(NULL, 0, worker_thread, new_Lwp,
+ THR_BOUND | THR_SUSPENDED, &lwpid) != 0)
+ abend("cannot create lwp to follow child lwp", NULL);
+ insert_lwpid(lwpid);
+ }
+ return (0);
+}
+
+int
+main(int argc, char *argv[])
+{
+ private_t *pri;
+ struct tms tms;
+ struct rlimit rlim;
+ int ofd = -1;
+ int opt;
+ int i;
+ int first;
+ int errflg = FALSE;
+ int badname = FALSE;
+ proc_set_t *grab = NULL;
+ const pstatus_t *Psp;
+ const lwpstatus_t *Lsp;
+ int sharedmem;
+
+ /* a few of these need to be initialized to NULL */
+ Cp = NULL;
+ fcall_tbl = NULL;
+
+ /*
+ * Make sure fd's 0, 1, and 2 are allocated,
+ * just in case truss was invoked from init.
+ */
+ while ((i = open("/dev/null", O_RDWR)) >= 0 && i < 2)
+ ;
+ if (i > 2)
+ (void) close(i);
+
+ starttime = times(&tms); /* for elapsed timing */
+
+ /* this should be per-traced-process */
+ pagesize = sysconf(_SC_PAGESIZE);
+
+ /* command name (e.g., "truss") */
+ if ((command = strrchr(argv[0], '/')) != NULL)
+ command++;
+ else
+ command = argv[0];
+
+ /* set up the initial private data */
+ (void) mutex_init(&truss_lock, USYNC_THREAD, NULL);
+ (void) mutex_init(&count_lock, USYNC_THREAD, NULL);
+ (void) cond_init(&truss_cv, USYNC_THREAD, NULL);
+ if (thr_keycreate(&private_key, free_private) == ENOMEM)
+ abend("memory allocation failure", NULL);
+ pri = get_private();
+
+ Euid = geteuid();
+ Egid = getegid();
+ Ruid = getuid();
+ Rgid = getgid();
+ ancestor = getpid();
+
+ prfillset(&trace); /* default: trace all system calls */
+ premptyset(&verbose); /* default: no syscall verbosity */
+ premptyset(&rawout); /* default: no raw syscall interpretation */
+
+ prfillset(&signals); /* default: trace all signals */
+
+ prfillset(&faults); /* default: trace all faults */
+ prdelset(&faults, FLTPAGE); /* except this one */
+
+ premptyset(&readfd); /* default: dump no buffers */
+ premptyset(&writefd);
+
+ premptyset(&syshang); /* default: hang on no system calls */
+ premptyset(&sighang); /* default: hang on no signals */
+ premptyset(&flthang); /* default: hang on no faults */
+
+ (void) sigemptyset(&emptyset); /* for unblocking all signals */
+ (void) sigfillset(&fillset); /* for blocking all signals */
+
+#define OPTIONS "FpfcaeildDEht:T:v:x:s:S:m:M:u:U:r:w:o:"
+ while ((opt = getopt(argc, argv, OPTIONS)) != EOF) {
+ switch (opt) {
+ case 'F': /* force grabbing (no O_EXCL) */
+ Fflag = PGRAB_FORCE;
+ break;
+ case 'p': /* grab processes */
+ pflag = TRUE;
+ break;
+ case 'f': /* follow children */
+ fflag = TRUE;
+ break;
+ case 'c': /* don't trace, just count */
+ cflag = TRUE;
+ iflag = TRUE; /* implies no interruptable syscalls */
+ break;
+ case 'a': /* display argument lists */
+ aflag = TRUE;
+ break;
+ case 'e': /* display environments */
+ eflag = TRUE;
+ break;
+ case 'i': /* don't show interruptable syscalls */
+ iflag = TRUE;
+ break;
+ case 'l': /* show lwp id for each syscall */
+ lflag = TRUE;
+ break;
+ case 'h': /* debugging: report hash stats */
+ hflag = TRUE;
+ break;
+ case 'd': /* show time stamps */
+ dflag = TRUE;
+ break;
+ case 'D': /* show time deltas */
+ Dflag = TRUE;
+ break;
+ case 'E':
+ Eflag = TRUE; /* show syscall times */
+ break;
+ case 't': /* system calls to trace */
+ if (syslist(optarg, &trace, &tflag))
+ badname = TRUE;
+ break;
+ case 'T': /* system calls to hang process */
+ if (syslist(optarg, &syshang, &Tflag))
+ badname = TRUE;
+ break;
+ case 'v': /* verbose interpretation of syscalls */
+ if (syslist(optarg, &verbose, &vflag))
+ badname = TRUE;
+ break;
+ case 'x': /* raw interpretation of syscalls */
+ if (syslist(optarg, &rawout, &xflag))
+ badname = TRUE;
+ break;
+ case 's': /* signals to trace */
+ if (siglist(pri, optarg, &signals, &sflag))
+ badname = TRUE;
+ break;
+ case 'S': /* signals to hang process */
+ if (siglist(pri, optarg, &sighang, &Sflag))
+ badname = TRUE;
+ break;
+ case 'm': /* machine faults to trace */
+ if (fltlist(optarg, &faults, &mflag))
+ badname = TRUE;
+ break;
+ case 'M': /* machine faults to hang process */
+ if (fltlist(optarg, &flthang, &Mflag))
+ badname = TRUE;
+ break;
+ case 'u': /* user library functions to trace */
+ if (liblist(optarg, 0))
+ badname = TRUE;
+ break;
+ case 'U': /* user library functions to hang */
+ if (liblist(optarg, 1))
+ badname = TRUE;
+ break;
+ case 'r': /* show contents of read(fd) */
+ if (fdlist(optarg, &readfd))
+ badname = TRUE;
+ break;
+ case 'w': /* show contents of write(fd) */
+ if (fdlist(optarg, &writefd))
+ badname = TRUE;
+ break;
+ case 'o': /* output file for trace */
+ oflag = TRUE;
+ if (ofd >= 0)
+ (void) close(ofd);
+ if ((ofd = xcreat(optarg)) < 0) {
+ perror(optarg);
+ badname = TRUE;
+ }
+ break;
+ default:
+ errflg = TRUE;
+ break;
+ }
+ }
+
+ if (badname)
+ exit(2);
+
+ /* if -a or -e was specified, force tracing of exec() */
+ if (aflag || eflag)
+ praddset(&trace, SYS_execve);
+
+ /*
+ * Make sure that all system calls, signals, and machine faults
+ * that hang the process are added to their trace sets.
+ */
+ prorset(&trace, &syshang);
+ prorset(&signals, &sighang);
+ prorset(&faults, &flthang);
+
+ argc -= optind;
+ argv += optind;
+
+ /* collect the specified process ids */
+ if (pflag && argc > 0) {
+ grab = my_malloc(argc * sizeof (proc_set_t),
+ "memory for process-ids");
+ while (argc-- > 0)
+ pids(*argv++, grab);
+ }
+
+ if (errflg || (argc <= 0 && ngrab <= 0)) {
+ (void) fprintf(stderr,
+ "usage:\t%s [-fcaeildDEF] [-[tTvx] [!]syscalls] [-[sS] [!]signals]\\\n",
+ command);
+ (void) fprintf(stderr,
+ "\t[-[mM] [!]faults] [-[rw] [!]fds] [-[uU] [!]libs:[:][!]funcs]\\\n");
+ (void) fprintf(stderr,
+ "\t[-o outfile] command | -p pid[/lwps] ...\n");
+ exit(2);
+ }
+
+ if (argc > 0) { /* create the controlled process */
+ int err;
+ char path[PATH_MAX];
+
+ Proc = Pcreate(argv[0], &argv[0], &err, path, sizeof (path));
+ if (Proc == NULL) {
+ switch (err) {
+ case C_PERM:
+ (void) fprintf(stderr,
+ "%s: cannot trace set-id or "
+ "unreadable object file: %s\n",
+ command, path);
+ break;
+ case C_LP64:
+ (void) fprintf(stderr,
+ "%s: cannot control _LP64 "
+ "program: %s\n",
+ command, path);
+ break;
+ case C_NOEXEC:
+ (void) fprintf(stderr,
+ "%s: cannot execute program: %s\n",
+ command, argv[0]);
+ break;
+ case C_NOENT:
+ (void) fprintf(stderr,
+ "%s: cannot find program: %s\n",
+ command, argv[0]);
+ break;
+ case C_STRANGE:
+ break;
+ default:
+ (void) fprintf(stderr, "%s: %s\n",
+ command, Pcreate_error(err));
+ break;
+ }
+ exit(2);
+ }
+ if (fflag || Dynpat != NULL)
+ (void) Psetflags(Proc, PR_FORK);
+ else
+ (void) Punsetflags(Proc, PR_FORK);
+ Psp = Pstatus(Proc);
+ Lsp = &Psp->pr_lwp;
+ pri->lwpstat = Lsp;
+ data_model = Psp->pr_dmodel;
+ created = Psp->pr_pid;
+ make_pname(pri, 0);
+ (void) sysentry(pri, 1);
+ pri->length = 0;
+ if (!cflag && prismember(&trace, SYS_execve)) {
+ pri->exec_string = my_realloc(pri->exec_string,
+ strlen(pri->sys_string) + 1, NULL);
+ (void) strcpy(pri->exec_pname, pri->pname);
+ (void) strcpy(pri->exec_string, pri->sys_string);
+ pri->length += strlen(pri->sys_string);
+ pri->exec_lwpid = pri->lwpstat->pr_lwpid;
+ pri->sys_leng = 0;
+ *pri->sys_string = '\0';
+ }
+ pri->syslast = Psp->pr_stime;
+ pri->usrlast = Psp->pr_utime;
+ }
+
+ /*
+ * Now that we have created the victim process,
+ * give ourself a million file descriptors.
+ * This is enough to deal with a multithreaded
+ * victim process that has half a million lwps.
+ */
+ rlim.rlim_cur = 1024 * 1024;
+ rlim.rlim_max = 1024 * 1024;
+ if ((Euid != 0 || setrlimit(RLIMIT_NOFILE, &rlim) != 0) &&
+ getrlimit(RLIMIT_NOFILE, &rlim) == 0) {
+ /*
+ * Failing the million, give ourself as many
+ * file descriptors as we can get.
+ */
+ rlim.rlim_cur = rlim.rlim_max;
+ (void) setrlimit(RLIMIT_NOFILE, &rlim);
+ }
+ (void) enable_extended_FILE_stdio(-1, -1);
+
+ setoutput(ofd); /* establish truss output */
+ istty = isatty(1);
+
+ if (setvbuf(stdout, (char *)NULL, _IOFBF, MYBUFSIZ) != 0)
+ abend("setvbuf() failure", NULL);
+
+ /*
+ * Set up signal dispositions.
+ */
+ if (created && (oflag || !istty)) { /* ignore interrupts */
+ (void) sigset(SIGHUP, SIG_IGN);
+ (void) sigset(SIGINT, SIG_IGN);
+ (void) sigset(SIGQUIT, SIG_IGN);
+ } else { /* receive interrupts */
+ if (sigset(SIGHUP, SIG_IGN) == SIG_DFL)
+ (void) sigset(SIGHUP, intr);
+ if (sigset(SIGINT, SIG_IGN) == SIG_DFL)
+ (void) sigset(SIGINT, intr);
+ if (sigset(SIGQUIT, SIG_IGN) == SIG_DFL)
+ (void) sigset(SIGQUIT, intr);
+ }
+ (void) sigset(SIGTERM, intr);
+ (void) sigset(SIGUSR1, intr);
+ (void) sigset(SIGUSR2, intr);
+ (void) sigset(SIGPIPE, intr);
+
+ /* don't accumulate zombie children */
+ (void) sigset(SIGCLD, SIG_IGN);
+
+ /* create shared mem space for global mutexes */
+
+ sharedmem = (fflag || Dynpat != NULL || ngrab > 1);
+ gps = (void *)mmap(NULL, sizeof (struct global_psinfo),
+ PROT_READ|PROT_WRITE,
+ MAP_ANON | (sharedmem? MAP_SHARED : MAP_PRIVATE),
+ -1, (off_t)0);
+ if (gps == MAP_FAILED)
+ abend("cannot allocate ", "memory for counts");
+ i = sharedmem? USYNC_PROCESS : USYNC_THREAD;
+ (void) mutex_init(&gps->ps_mutex0, i, NULL);
+ (void) mutex_init(&gps->ps_mutex1, i, NULL);
+ (void) mutex_init(&gps->fork_lock, i, NULL);
+ (void) cond_init(&gps->fork_cv, i, NULL);
+
+
+ /* config tmp file if counting and following */
+ if (fflag && cflag) {
+ char *tmps = tempnam("/var/tmp", "truss");
+ sfd = open(tmps, O_CREAT|O_APPEND|O_EXCL|O_RDWR, 0600);
+ if (sfd == -1)
+ abend("Error creating tmpfile", NULL);
+ if (unlink(tmps) == -1)
+ abend("Error unlinking tmpfile", NULL);
+ free(tmps);
+ tmps = NULL;
+ }
+
+ if (created) {
+ per_proc_init();
+ procadd(created, NULL);
+ show_cred(pri, TRUE, FALSE);
+ } else { /* grab the specified processes */
+ int gotone = FALSE;
+
+ i = 0;
+ while (i < ngrab) { /* grab first process */
+ if (grabit(pri, &grab[i++])) {
+ Psp = Pstatus(Proc);
+ Lsp = &Psp->pr_lwp;
+ gotone = TRUE;
+ break;
+ }
+ }
+ if (!gotone)
+ abend(NULL, NULL);
+ per_proc_init();
+ while (i < ngrab) { /* grab the remainder */
+ proc_set_t *set = &grab[i++];
+
+ (void) mutex_lock(&truss_lock);
+ switch (fork()) {
+ case -1:
+ (void) fprintf(stderr,
+ "%s: cannot fork to control process, pid# %d\n",
+ command, (int)set->pid);
+ /* FALLTHROUGH */
+ default:
+ (void) mutex_unlock(&truss_lock);
+ continue; /* parent carries on */
+
+ case 0: /* child grabs process */
+ (void) mutex_unlock(&truss_lock);
+ Pfree(Proc);
+ descendent = TRUE;
+ if (grabit(pri, set)) {
+ Psp = Pstatus(Proc);
+ Lsp = &Psp->pr_lwp;
+ per_proc_init();
+ break;
+ }
+ exit(2);
+ }
+ break;
+ }
+ free(grab);
+ }
+
+
+ /*
+ * If running setuid-root, become root for real to avoid
+ * affecting the per-user limitation on the maximum number
+ * of processes (one benefit of running setuid-root).
+ */
+ if (Rgid != Egid)
+ (void) setgid(Egid);
+ if (Ruid != Euid)
+ (void) setuid(Euid);
+
+ if (!created && aflag && prismember(&trace, SYS_execve)) {
+ psargs(pri);
+ Flush();
+ }
+
+ if (created && Pstate(Proc) != PS_STOP) /* assertion */
+ if (!(interrupt | sigusr1))
+ abend("ASSERT error: process is not stopped", NULL);
+
+ traceeven = trace; /* trace these system calls */
+
+ /* trace these regardless, even if we don't report results */
+ praddset(&traceeven, SYS_exit);
+ praddset(&traceeven, SYS_lwp_create);
+ praddset(&traceeven, SYS_lwp_exit);
+ praddset(&traceeven, SYS_execve);
+ praddset(&traceeven, SYS_openat);
+ praddset(&traceeven, SYS_openat64);
+ praddset(&traceeven, SYS_open);
+ praddset(&traceeven, SYS_open64);
+ praddset(&traceeven, SYS_vfork);
+ praddset(&traceeven, SYS_forksys);
+
+ /* for I/O buffer dumps, force tracing of read()s and write()s */
+ if (!isemptyset(&readfd)) {
+ praddset(&traceeven, SYS_read);
+ praddset(&traceeven, SYS_readv);
+ praddset(&traceeven, SYS_pread);
+ praddset(&traceeven, SYS_pread64);
+ praddset(&traceeven, SYS_recv);
+ praddset(&traceeven, SYS_recvfrom);
+ praddset(&traceeven, SYS_recvmsg);
+ }
+ if (!isemptyset(&writefd)) {
+ praddset(&traceeven, SYS_write);
+ praddset(&traceeven, SYS_writev);
+ praddset(&traceeven, SYS_pwrite);
+ praddset(&traceeven, SYS_pwrite64);
+ praddset(&traceeven, SYS_send);
+ praddset(&traceeven, SYS_sendto);
+ praddset(&traceeven, SYS_sendmsg);
+ }
+
+ if (cflag || Eflag) {
+ Psetsysentry(Proc, &traceeven);
+ }
+ Psetsysexit(Proc, &traceeven);
+
+ /* special case -- cannot trace sysexit because context is changed */
+ if (prismember(&trace, SYS_context)) {
+ (void) Psysentry(Proc, SYS_context, TRUE);
+ (void) Psysexit(Proc, SYS_context, FALSE);
+ prdelset(&traceeven, SYS_context);
+ }
+
+ /* special case -- trace exec() on entry to get the args */
+ (void) Psysentry(Proc, SYS_execve, TRUE);
+
+ /* special case -- sysexit never reached */
+ (void) Psysentry(Proc, SYS_exit, TRUE);
+ (void) Psysentry(Proc, SYS_lwp_exit, TRUE);
+ (void) Psysexit(Proc, SYS_exit, FALSE);
+ (void) Psysexit(Proc, SYS_lwp_exit, FALSE);
+
+ Psetsignal(Proc, &signals); /* trace these signals */
+ Psetfault(Proc, &faults); /* trace these faults */
+
+ /* for function call tracing */
+ if (Dynpat != NULL) {
+ /* trace these regardless, to deal with function calls */
+ (void) Pfault(Proc, FLTBPT, TRUE);
+ (void) Pfault(Proc, FLTTRACE, TRUE);
+
+ /* needed for x86 */
+ (void) Psetflags(Proc, PR_BPTADJ);
+
+ /*
+ * Find functions and set breakpoints on grabbed process.
+ * A process stopped on exec() gets its breakpoints set below.
+ */
+ if ((Lsp->pr_why != PR_SYSENTRY &&
+ Lsp->pr_why != PR_SYSEXIT) ||
+ Lsp->pr_what != SYS_execve) {
+ establish_breakpoints();
+ establish_stacks();
+ }
+ }
+
+ /*
+ * Use asynchronous-stop for multithreaded truss.
+ * truss runs one lwp for each lwp in the target process.
+ */
+ (void) Psetflags(Proc, PR_ASYNC);
+
+ /* flush out all tracing flags now. */
+ Psync(Proc);
+
+ /*
+ * If we grabbed a running process, set it running again.
+ * Since we are tracing lwp_create() and lwp_exit(), the
+ * lwps will not change in the process until we create all
+ * of the truss worker threads.
+ * We leave a created process stopped so its exec() can be reported.
+ */
+ first = created? FALSE : TRUE;
+ if (!created &&
+ ((Pstate(Proc) == PS_STOP && Lsp->pr_why == PR_REQUESTED) ||
+ (Lsp->pr_flags & PR_DSTOP)))
+ first = FALSE;
+
+ main_thread(first);
+ return (0);
+}
+
+/*
+ * Called from main() and from control() after fork().
+ */
+void
+main_thread(int first)
+{
+ private_t *pri = get_private();
+ struct tms tms;
+ int flags;
+ int retc;
+ int i;
+ int count;
+
+ /*
+ * Block all signals in the main thread.
+ * Some worker thread will receive signals.
+ */
+ (void) thr_sigsetmask(SIG_SETMASK, &fillset, NULL);
+
+ /*
+ * If we are dealing with a previously hung process,
+ * arrange not to leave it hung on the same system call.
+ */
+ primary_lwp = (first && Pstate(Proc) == PS_STOP)?
+ Pstatus(Proc)->pr_lwp.pr_lwpid : 0;
+
+ /*
+ * Create worker threads to match the lwps in the target process.
+ */
+ truss_nlwp = 0;
+ truss_maxlwp = 1;
+ truss_lwpid = my_realloc(truss_lwpid, sizeof (lwpid_t), NULL);
+ truss_lwpid[0] = 0;
+ count = 0;
+ (void) Plwp_iter(Proc, create_thread, &count);
+
+ if (count == 0) {
+ (void) printf("(Warning: no matching active LWPs found, "
+ "waiting)\n");
+ Flush();
+ }
+
+ /*
+ * Set all of the truss worker threads running now.
+ */
+ (void) mutex_lock(&truss_lock);
+ for (i = 0; i < truss_maxlwp; i++) {
+ if (truss_lwpid[i])
+ (void) thr_continue(truss_lwpid[i]);
+ }
+ (void) mutex_unlock(&truss_lock);
+
+ /*
+ * Wait until all worker threads terminate.
+ */
+ while (thr_join(0, NULL, NULL) == 0)
+ continue;
+
+ (void) Punsetflags(Proc, PR_ASYNC);
+ Psync(Proc);
+ if (sigusr1)
+ letgo(pri);
+ flags = PRELEASE_CLEAR;
+ if (leave_hung)
+ flags |= PRELEASE_HANG;
+ Prelease(Proc, flags);
+
+ procdel();
+ retc = (leave_hung? 0 : wait4all());
+
+ if (!descendent) {
+ interrupt = 0; /* another interrupt kills the report */
+ if (cflag) {
+ if (fflag)
+ file_to_parent();
+ report(pri, times(&tms) - starttime);
+ }
+ } else if (cflag && fflag) {
+ child_to_file();
+ }
+
+ exit(retc); /* exit with exit status of created process, else 0 */
+}
+
+void *
+worker_thread(void *arg)
+{
+ struct ps_lwphandle *Lwp = (struct ps_lwphandle *)arg;
+ const pstatus_t *Psp = Pstatus(Proc);
+ const lwpstatus_t *Lsp = Lstatus(Lwp);
+ struct syscount *scp;
+ lwpid_t who = Lsp->pr_lwpid;
+ int first = (who == primary_lwp);
+ private_t *pri = get_private();
+ int req_flag = 0;
+ int leave_it_hung = FALSE;
+ int reset_traps = FALSE;
+ int gcode;
+ int what;
+ int ow_in_effect = 0;
+ long ow_syscall = 0;
+ long ow_subcode = 0;
+ char *ow_string = NULL;
+ sysset_t full_set;
+ sysset_t running_set;
+ int dotrace = lwptrace(Psp->pr_pid, Lsp->pr_lwpid);
+
+ pri->Lwp = Lwp;
+ pri->lwpstat = Lsp;
+ pri->syslast = Lsp->pr_stime;
+ pri->usrlast = Lsp->pr_utime;
+ make_pname(pri, 0);
+
+ prfillset(&full_set);
+
+ /* we were created with all signals blocked; unblock them */
+ (void) thr_sigsetmask(SIG_SETMASK, &emptyset, NULL);
+
+ /*
+ * Run this loop until the victim lwp terminates or we receive
+ * a termination condition (leave_hung | interrupt | sigusr1).
+ */
+ for (;;) {
+ if (interrupt | sigusr1) {
+ (void) Lstop(Lwp, MILLISEC);
+ if (Lstate(Lwp) == PS_RUN)
+ break;
+ }
+ if (Lstate(Lwp) == PS_RUN) {
+ /* millisecond timeout is for sleeping syscalls */
+ uint_t tout = (iflag || req_flag)? 0 : MILLISEC;
+
+ /*
+ * If we are to leave this lwp stopped in sympathy
+ * with another lwp that has been left hung, or if
+ * we have been interrupted or instructed to release
+ * our victim process, and this lwp is stopped but
+ * not on an event of interest to /proc, then just
+ * leave it in that state.
+ */
+ if ((leave_hung | interrupt | sigusr1) &&
+ (Lsp->pr_flags & (PR_STOPPED|PR_ISTOP))
+ == PR_STOPPED)
+ break;
+
+ (void) Lwait(Lwp, tout);
+ if (Lstate(Lwp) == PS_RUN &&
+ tout != 0 && !(interrupt | sigusr1)) {
+ (void) mutex_lock(&truss_lock);
+ if ((Lsp->pr_flags & PR_STOPPED) &&
+ Lsp->pr_why == PR_JOBCONTROL)
+ req_flag = jobcontrol(pri, dotrace);
+ else
+ req_flag = requested(pri, req_flag,
+ dotrace);
+ (void) mutex_unlock(&truss_lock);
+ }
+ continue;
+ }
+ data_model = Psp->pr_dmodel;
+ if (Lstate(Lwp) == PS_UNDEAD)
+ break;
+ if (Lstate(Lwp) == PS_LOST) { /* we lost control */
+ /*
+ * After exec(), only one LWP remains in the process.
+ * /proc makes the thread following that LWP receive
+ * EAGAIN (PS_LOST) if the program being exec()ed
+ * is a set-id program. Every other controlling
+ * thread receives ENOENT (because its LWP vanished).
+ * We are the controlling thread for the exec()ing LWP.
+ * We must wait until all of our siblings terminate
+ * before attempting to reopen the process.
+ */
+ (void) mutex_lock(&truss_lock);
+ while (truss_nlwp > 1)
+ (void) cond_wait(&truss_cv, &truss_lock);
+ if (Preopen(Proc) == 0) { /* we got control back */
+ /*
+ * We have to free and re-grab the LWP.
+ * The process is guaranteed to be at exit
+ * from exec() or execve() and have only
+ * one LWP, namely this one, and the LWP
+ * is guaranteed to have lwpid == 1.
+ * This "cannot fail".
+ */
+ who = 1;
+ Lfree(Lwp);
+ pri->Lwp = Lwp =
+ Lgrab(Proc, who, &gcode);
+ if (Lwp == NULL)
+ abend("Lgrab error: ",
+ Lgrab_error(gcode));
+ pri->lwpstat = Lsp = Lstatus(Lwp);
+ (void) mutex_unlock(&truss_lock);
+ continue;
+ }
+
+ /* we really lost it */
+ if (pri->exec_string && *pri->exec_string) {
+ if (pri->exec_pname[0] != '\0')
+ (void) fputs(pri->exec_pname, stdout);
+ timestamp(pri);
+ (void) fputs(pri->exec_string, stdout);
+ (void) fputc('\n', stdout);
+ } else if (pri->length) {
+ (void) fputc('\n', stdout);
+ }
+ if (pri->sys_valid)
+ (void) printf(
+ "%s\t*** cannot trace across exec() of %s ***\n",
+ pri->pname, pri->sys_path);
+ else
+ (void) printf(
+ "%s\t*** lost control of process ***\n",
+ pri->pname);
+ pri->length = 0;
+ Flush();
+ (void) mutex_unlock(&truss_lock);
+ break;
+ }
+ if (Lstate(Lwp) != PS_STOP) {
+ (void) fprintf(stderr,
+ "%s: state = %d\n", command, Lstate(Lwp));
+ abend(pri->pname, "uncaught status of subject lwp");
+ }
+
+ make_pname(pri, 0);
+
+ (void) mutex_lock(&truss_lock);
+
+ what = Lsp->pr_what;
+ req_flag = 0;
+
+ switch (Lsp->pr_why) {
+ case PR_REQUESTED:
+ break;
+ case PR_SIGNALLED:
+ req_flag = signalled(pri, req_flag, dotrace);
+ if (Sflag && !first && prismember(&sighang, what))
+ leave_it_hung = TRUE;
+ break;
+ case PR_FAULTED:
+ if (what == FLTBPT) {
+ int rval;
+
+ (void) Pstop(Proc, 0);
+ rval = function_trace(pri, first, 0, dotrace);
+ if (rval == 1)
+ leave_it_hung = TRUE;
+ if (rval >= 0)
+ break;
+ }
+ if (faulted(pri, dotrace) &&
+ Mflag && !first && prismember(&flthang, what))
+ leave_it_hung = TRUE;
+ break;
+ case PR_JOBCONTROL: /* can't happen except first time */
+ req_flag = jobcontrol(pri, dotrace);
+ break;
+ case PR_SYSENTRY:
+ /* protect ourself from operating system error */
+ if (what <= 0 || what > PRMAXSYS)
+ what = PRMAXSYS;
+ pri->length = 0;
+ /*
+ * ow_in_effect checks to see whether or not we
+ * are attempting to quantify the time spent in
+ * a one way system call. This is necessary as
+ * some system calls never return, yet it is desireable
+ * to determine how much time the traced process
+ * spends in these calls. To do this, a one way
+ * flag is set on SYSENTRY when the call is recieved.
+ * After this, the call mask for the SYSENTRY events
+ * is filled so that the traced process will stop
+ * on the entry to the very next system call.
+ * This appears to the the best way to determine
+ * system time elapsed between a one way system call.
+ * Once the next call occurs, values that have been
+ * stashed are used to record the correct syscall
+ * and time, and the SYSENTRY event mask is restored
+ * so that the traced process may continue.
+ */
+ if (dotrace && ow_in_effect) {
+ if (cflag) {
+ (void) mutex_lock(&count_lock);
+ scp = Cp->syscount[ow_syscall];
+ if (ow_subcode != -1)
+ scp += ow_subcode;
+ scp->count++;
+ accumulate(&scp->stime,
+ &Lsp->pr_stime, &pri->syslast);
+ accumulate(&Cp->usrtotal,
+ &Lsp->pr_utime, &pri->usrlast);
+ pri->syslast = Lsp->pr_stime;
+ pri->usrlast = Lsp->pr_utime;
+ (void) mutex_unlock(&count_lock);
+ } else if (Eflag) {
+ putpname(pri);
+ timestamp(pri);
+ (void) printf("%s\n", ow_string);
+ free(ow_string);
+ ow_string = NULL;
+ pri->syslast = Lsp->pr_stime;
+ }
+ ow_in_effect = 0;
+ Psetsysentry(Proc, &running_set);
+ }
+
+ /*
+ * Special cases. Most syscalls are traced on exit.
+ */
+ switch (what) {
+ case SYS_exit: /* exit() */
+ case SYS_lwp_exit: /* lwp_exit() */
+ case SYS_context: /* [get|set]context() */
+ if (dotrace && cflag &&
+ prismember(&trace, what)) {
+ ow_in_effect = 1;
+ ow_syscall = what;
+ ow_subcode = getsubcode(pri);
+ pri->syslast = Lsp->pr_stime;
+ running_set =
+ (Pstatus(Proc))->pr_sysentry;
+ Psetsysentry(Proc, &full_set);
+ } else if (dotrace && Eflag &&
+ prismember(&trace, what)) {
+ (void) sysentry(pri, dotrace);
+ ow_in_effect = 1;
+ ow_string = my_malloc(
+ strlen(pri->sys_string) + 1, NULL);
+ (void) strcpy(ow_string,
+ pri->sys_string);
+ running_set =
+ (Pstatus(Proc))->pr_sysentry;
+ Psetsysentry(Proc, &full_set);
+ pri->syslast = Lsp->pr_stime;
+ } else if (dotrace &&
+ prismember(&trace, what)) {
+ (void) sysentry(pri, dotrace);
+ putpname(pri);
+ timestamp(pri);
+ pri->length +=
+ printf("%s\n", pri->sys_string);
+ Flush();
+ }
+ pri->sys_leng = 0;
+ *pri->sys_string = '\0';
+
+ if (what == SYS_exit)
+ exit_called = TRUE;
+ break;
+ case SYS_execve:
+ show_cred(pri, FALSE, TRUE);
+ (void) sysentry(pri, dotrace);
+ if (dotrace && !cflag &&
+ prismember(&trace, what)) {
+ pri->exec_string =
+ my_realloc(pri->exec_string,
+ strlen(pri->sys_string) + 1,
+ NULL);
+ (void) strcpy(pri->exec_pname,
+ pri->pname);
+ (void) strcpy(pri->exec_string,
+ pri->sys_string);
+ pri->length += strlen(pri->sys_string);
+ pri->exec_lwpid = Lsp->pr_lwpid;
+ }
+ pri->sys_leng = 0;
+ *pri->sys_string = '\0';
+ break;
+ default:
+ if (dotrace && (cflag || Eflag) &&
+ prismember(&trace, what)) {
+ pri->syslast = Lsp->pr_stime;
+ }
+ break;
+ }
+ if (dotrace && Tflag && !first &&
+ (prismember(&syshang, what) ||
+ (exit_called && prismember(&syshang, SYS_exit))))
+ leave_it_hung = TRUE;
+ break;
+ case PR_SYSEXIT:
+ /* check for write open of a /proc file */
+ if (what == SYS_openat || what == SYS_openat64 ||
+ what == SYS_open || what == SYS_open64) {
+ int readonly;
+
+ (void) sysentry(pri, dotrace);
+ pri->Errno = Lsp->pr_errno;
+ pri->ErrPriv = Lsp->pr_errpriv;
+ readonly =
+ ((what == SYS_openat ||
+ what == SYS_openat64) &&
+ pri->sys_nargs > 2 &&
+ (pri->sys_args[2]&0x3) == O_RDONLY) ||
+ ((what == SYS_open ||
+ what == SYS_open64) &&
+ pri->sys_nargs > 1 &&
+ (pri->sys_args[1]&0x3) == O_RDONLY);
+ if ((pri->Errno == 0 || pri->Errno == EBUSY) &&
+ pri->sys_valid && !readonly) {
+ int rv = checkproc(pri);
+ if (rv == 1 && Fflag != PGRAB_FORCE) {
+ /*
+ * The process opened itself
+ * and no -F flag was specified.
+ * Just print the open() call
+ * and let go of the process.
+ */
+ if (dotrace && !cflag &&
+ prismember(&trace, what)) {
+ putpname(pri);
+ timestamp(pri);
+ (void) printf("%s\n",
+ pri->sys_string);
+ Flush();
+ }
+ sigusr1 = TRUE;
+ (void) mutex_unlock(
+ &truss_lock);
+ goto out;
+ }
+ if (rv == 2) {
+ /*
+ * Process opened someone else.
+ * The open is being reissued.
+ * Don't report this one.
+ */
+ pri->sys_leng = 0;
+ *pri->sys_string = '\0';
+ pri->sys_nargs = 0;
+ break;
+ }
+ }
+ }
+ if (what == SYS_execve && pri->Errno == 0) {
+ /*
+ * Refresh the data model on exec() in case it
+ * is different from the parent. Lwait()
+ * doesn't update process-wide status, so we
+ * have to explicitly call Pstopstatus() to get
+ * the new state.
+ */
+ (void) Pstopstatus(Proc, PCNULL, 0);
+ data_model = Psp->pr_dmodel;
+ }
+ if (sysexit(pri, dotrace))
+ Flush();
+ if (what == SYS_lwp_create && pri->Rval1 != 0) {
+ struct ps_lwphandle *new_Lwp;
+ lwpid_t lwpid;
+
+ if ((new_Lwp = grab_lwp(pri->Rval1)) != NULL) {
+ (void) thr_sigsetmask(SIG_SETMASK,
+ &fillset, NULL);
+ if (thr_create(NULL, 0, worker_thread,
+ new_Lwp, THR_BOUND | THR_SUSPENDED,
+ &lwpid) != 0)
+ abend("cannot create lwp ",
+ "to follow child lwp");
+ insert_lwpid(lwpid);
+ (void) thr_continue(lwpid);
+ (void) thr_sigsetmask(SIG_SETMASK,
+ &emptyset, NULL);
+ }
+ }
+ pri->sys_nargs = 0;
+ if (dotrace && Tflag && !first &&
+ prismember(&syshang, what))
+ leave_it_hung = TRUE;
+ if (what == SYS_execve && pri->Errno == 0) {
+ is_vfork_child = FALSE;
+ reset_breakpoints();
+ /*
+ * exec() resets the calling LWP's lwpid to 1.
+ * If the LWP has changed its lwpid, then
+ * we have to free and re-grab the LWP
+ * in order to keep libproc consistent.
+ * This "cannot fail".
+ */
+ if (who != Lsp->pr_lwpid) {
+ /*
+ * We must wait for all of our
+ * siblings to terminate.
+ */
+ while (truss_nlwp > 1)
+ (void) cond_wait(&truss_cv,
+ &truss_lock);
+ who = Lsp->pr_lwpid;
+ Lfree(Lwp);
+ pri->Lwp = Lwp =
+ Lgrab(Proc, who, &gcode);
+ if (Lwp == NULL)
+ abend("Lgrab error: ",
+ Lgrab_error(gcode));
+ pri->lwpstat = Lsp = Lstatus(Lwp);
+ }
+ }
+ break;
+ default:
+ req_flag = 0;
+ (void) fprintf(stderr,
+ "unknown reason for stopping: %d/%d\n",
+ Lsp->pr_why, what);
+ abend(NULL, NULL);
+ }
+
+ if (pri->child) { /* controlled process fork()ed */
+ if (fflag || Dynpat != NULL) {
+ if (Lsp->pr_why == PR_SYSEXIT &&
+ (Lsp->pr_what == SYS_vfork ||
+ (Lsp->pr_what == SYS_forksys &&
+ Lsp->pr_sysarg[0] == 2))) {
+ is_vfork_child = TRUE;
+ (void) Pstop(Proc, 0);
+ }
+ if (control(pri, pri->child)) {
+ (void) mutex_unlock(&truss_lock);
+ pri->child = 0;
+ if (!fflag) {
+ /*
+ * If this is vfork(), then
+ * this clears the breakpoints
+ * in the parent's address space
+ * as well as in the child's.
+ */
+ clear_breakpoints();
+ Prelease(Proc, PRELEASE_CLEAR);
+ _exit(0);
+ }
+ main_thread(FALSE);
+ /* NOTREACHED */
+ }
+
+ /*
+ * Here, we are still the parent truss.
+ * If the child messes with the breakpoints and
+ * this is vfork(), we have to set them again.
+ */
+ if (Dynpat != NULL && is_vfork_child && !fflag)
+ reset_traps = TRUE;
+ is_vfork_child = FALSE;
+ }
+ pri->child = 0;
+ }
+
+ if (leave_it_hung) {
+ (void) mutex_unlock(&truss_lock);
+ break;
+ }
+
+ if (reset_traps) {
+ /*
+ * To recover from vfork, we must catch the lwp
+ * that issued the vfork() when it returns to user
+ * level, with all other lwps remaining stopped.
+ * For this purpose, we have directed all lwps to
+ * stop and we now set the vfork()ing lwp running
+ * with the PRSTEP flag. We expect to capture it
+ * when it stops again showing PR_FAULTED/FLTTRACE.
+ * We are holding truss_lock, so no other threads
+ * in truss will set any other lwps in the victim
+ * process running.
+ */
+ reset_traps = FALSE;
+ (void) Lsetrun(Lwp, 0, PRSTEP);
+ do {
+ (void) Lwait(Lwp, 0);
+ } while (Lstate(Lwp) == PS_RUN);
+ if (Lstate(Lwp) == PS_STOP &&
+ Lsp->pr_why == PR_FAULTED &&
+ Lsp->pr_what == FLTTRACE) {
+ reestablish_traps();
+ (void) Lsetrun(Lwp, 0, PRCFAULT|PRSTOP);
+ } else {
+ (void) printf("%s\t*** Expected PR_FAULTED/"
+ "FLTTRACE stop following vfork()\n",
+ pri->pname);
+ }
+ }
+
+ if (Lstate(Lwp) == PS_STOP) {
+ int flags = 0;
+
+ if (interrupt | sigusr1) {
+ (void) mutex_unlock(&truss_lock);
+ break;
+ }
+ /*
+ * If we must leave this lwp hung is sympathy with
+ * another lwp that is being left hung on purpose,
+ * then push the state onward toward PR_REQUESTED.
+ */
+ if (leave_hung) {
+ if (Lsp->pr_why == PR_REQUESTED) {
+ (void) mutex_unlock(&truss_lock);
+ break;
+ }
+ flags |= PRSTOP;
+ }
+ if (Lsetrun(Lwp, 0, flags) != 0 &&
+ Lstate(Lwp) != PS_LOST &&
+ Lstate(Lwp) != PS_UNDEAD) {
+ (void) mutex_unlock(&truss_lock);
+ perror("Lsetrun");
+ abend("cannot start subject lwp", NULL);
+ /* NOTREACHED */
+ }
+ }
+ first = FALSE;
+
+ (void) mutex_unlock(&truss_lock);
+ }
+
+out:
+ /* block all signals in preparation for exiting */
+ (void) thr_sigsetmask(SIG_SETMASK, &fillset, NULL);
+
+ if (Lstate(Lwp) == PS_UNDEAD || Lstate(Lwp) == PS_LOST)
+ (void) mutex_lock(&truss_lock);
+ else {
+ (void) Lstop(Lwp, MILLISEC);
+ (void) mutex_lock(&truss_lock);
+ if (Lstate(Lwp) == PS_STOP &&
+ Lsp->pr_why == PR_FAULTED &&
+ Lsp->pr_what == FLTBPT)
+ (void) function_trace(pri, 0, 1, dotrace);
+ }
+
+ if (dotrace && ow_in_effect) {
+ if (cflag) {
+ (void) mutex_lock(&count_lock);
+ scp = Cp->syscount[ow_syscall];
+ if (ow_subcode != -1)
+ scp += ow_subcode;
+ scp->count++;
+ accumulate(&scp->stime,
+ &Lsp->pr_stime, &pri->syslast);
+ accumulate(&Cp->usrtotal,
+ &Lsp->pr_utime, &pri->usrlast);
+ pri->syslast = Lsp->pr_stime;
+ pri->usrlast = Lsp->pr_utime;
+ (void) mutex_unlock(&count_lock);
+ } else if (Eflag) {
+ putpname(pri);
+ timestamp(pri);
+ (void) printf("%s\n", ow_string);
+ free(ow_string);
+ ow_string = NULL;
+ pri->syslast = Lsp->pr_stime;
+ }
+ ow_in_effect = 0;
+ Psetsysentry(Proc, &running_set);
+ }
+
+ if (Lstate(Lwp) == PS_UNDEAD || Lstate(Lwp) == PS_LOST) {
+ /*
+ * The victim thread has exited or we lost control of
+ * the process. Remove ourself from the list of all
+ * truss threads and notify everyone waiting for this.
+ */
+ lwpid_t my_id = thr_self();
+ int i;
+
+ for (i = 0; i < truss_maxlwp; i++) {
+ if (truss_lwpid[i] == my_id) {
+ truss_lwpid[i] = 0;
+ break;
+ }
+ }
+ if (--truss_nlwp != 0) {
+ (void) cond_broadcast(&truss_cv);
+ } else {
+ /*
+ * The last truss worker thread is terminating.
+ * The address space is gone (UNDEAD) or is
+ * inaccessible (LOST) so we cannot clear the
+ * breakpoints. Just report the htable stats.
+ */
+ report_htable_stats();
+ }
+ } else {
+ /*
+ * The victim thread is not a zombie thread, and we have not
+ * lost control of the process. We must have gotten here due
+ * to (leave_hung || leave_it_hung || interrupt || sigusr1).
+ * In these cases, we must carefully uninstrument the process
+ * and either set it running or leave it stopped and abandoned.
+ */
+ static int nstopped = 0;
+ static int cleared = 0;
+
+ if (leave_it_hung)
+ leave_hung = TRUE;
+ if ((leave_hung | interrupt | sigusr1) == 0)
+ abend("(leave_hung | interrupt | sigusr1) == 0", NULL);
+
+ /*
+ * The first truss thread through here needs to instruct all
+ * application threads to stop -- they're not necessarily
+ * going to stop on their own.
+ */
+ if (nstopped++ == 0)
+ (void) Pdstop(Proc);
+
+ /*
+ * Notify all other worker threads about the reason
+ * for being here (leave_hung || interrupt || sigusr1).
+ */
+ broadcast_signals();
+
+ /*
+ * Once the last thread has reached this point, then and
+ * only then is it safe to remove breakpoints and other
+ * instrumentation. Since breakpoints are executed without
+ * truss_lock held, a monitor thread can't exit until all
+ * breakpoints have been removed, and we can't be sure the
+ * procedure to execute a breakpoint won't temporarily
+ * reinstall a breakpont. Accordingly, we need to wait
+ * until all threads are in a known state.
+ */
+ while (nstopped != truss_nlwp)
+ (void) cond_wait(&truss_cv, &truss_lock);
+
+ /*
+ * All truss threads have reached this point.
+ * One of them clears the breakpoints and
+ * wakes up everybody else to finish up.
+ */
+ if (cleared++ == 0) {
+ /*
+ * All threads should already be stopped,
+ * but just to be safe...
+ */
+ (void) Pstop(Proc, MILLISEC);
+ clear_breakpoints();
+ (void) Psysexit(Proc, SYS_vfork, FALSE);
+ (void) Psysexit(Proc, SYS_forksys, FALSE);
+ (void) Punsetflags(Proc, PR_FORK);
+ Psync(Proc);
+ fflag = 0;
+ (void) cond_broadcast(&truss_cv);
+ }
+
+ if (!leave_hung && Lstate(Lwp) == PS_STOP)
+ (void) Lsetrun(Lwp, 0, 0);
+ }
+
+ (void) Lfree(Lwp);
+ (void) mutex_unlock(&truss_lock);
+ return (NULL);
+}
+
+/*
+ * Give a base date for time stamps, adjusted to the
+ * stop time of the selected (first or created) process.
+ */
+void
+setup_basetime(hrtime_t basehrtime, struct timeval *basedate)
+{
+ const pstatus_t *Psp = Pstatus(Proc);
+ (void) mutex_lock(&count_lock);
+ Cp->basetime = Psp->pr_lwp.pr_tstamp;
+ (void) mutex_unlock(&count_lock);
+
+ if ((dflag|Dflag) && !cflag) {
+ const struct tm *ptm;
+ const char *ptime;
+ const char *pdst;
+ hrtime_t delta = basehrtime -
+ ((hrtime_t)Cp->basetime.tv_sec * NANOSEC +
+ Cp->basetime.tv_nsec);
+
+ if (delta > 0) {
+ basedate->tv_sec -= (time_t)(delta / NANOSEC);
+ basedate->tv_usec -= (delta % NANOSEC) / 1000;
+ if (basedate->tv_usec < 0) {
+ basedate->tv_sec--;
+ basedate->tv_usec += MICROSEC;
+ }
+ }
+ ptm = localtime(&basedate->tv_sec);
+ ptime = asctime(ptm);
+ if ((pdst = tzname[ptm->tm_isdst ? 1 : 0]) == NULL)
+ pdst = "???";
+ if (dflag) {
+ (void) printf(
+ "Base time stamp: %ld.%4.4ld [ %.20s%s %.4s ]\n",
+ basedate->tv_sec, basedate->tv_usec / 100,
+ ptime, pdst, ptime + 20);
+ Flush();
+ }
+ }
+}
+
+/*
+ * Performs per-process initializations. If truss is following a victim
+ * process it will fork additional truss processes to follow new processes
+ * created. Here is where each new truss process gets its per-process data
+ * initialized.
+ */
+
+void
+per_proc_init()
+{
+ void *pmem;
+ struct timeval basedate;
+ hrtime_t basehrtime;
+ struct syscount *scp;
+ int i;
+ timestruc_t c_basetime;
+
+ /* Make sure we only configure the basetime for the first truss proc */
+
+ if (Cp == NULL) {
+ pmem = my_malloc(sizeof (struct counts) + maxsyscalls() *
+ sizeof (struct syscount), NULL);
+ Cp = (struct counts *)pmem;
+ basehrtime = gethrtime();
+ (void) gettimeofday(&basedate, NULL);
+ setup_basetime(basehrtime, &basedate);
+ }
+
+ c_basetime = Cp->basetime;
+
+ (void) memset(Cp, 0, sizeof (struct counts) + maxsyscalls() *
+ sizeof (struct syscount));
+
+ Cp->basetime = c_basetime;
+
+ if (fcall_tbl != NULL)
+ destroy_hash(fcall_tbl);
+ fcall_tbl = init_hash(4096);
+
+ (void) mutex_lock(&count_lock);
+ scp = (struct syscount *)(Cp + 1);
+ for (i = 0; i <= PRMAXSYS; i++) {
+ Cp->syscount[i] = scp;
+ scp += nsubcodes(i);
+ }
+ (void) mutex_unlock(&count_lock);
+}
+
+
+/*
+ * Writes child state to a tempfile where it can be read and
+ * accumulated by the parent process. The file descriptor is shared
+ * among the processes. Ordering of writes does not matter, it is, however,
+ * necessary to ensure that all writes are atomic.
+ */
+
+void
+child_to_file()
+{
+ hiter_t *itr;
+ hentry_t *ntry;
+ hdntry_t fentry;
+ char *s = NULL;
+ char *t = NULL;
+ unsigned char *buf = NULL;
+ size_t bufsz = 0;
+ size_t i = 0;
+ size_t j = 0;
+
+ /* ensure that we are in fact a child process */
+ if (!descendent)
+ return;
+
+ /* enumerate fcall_tbl (tbl locked until freed) */
+ if (Dynpat != NULL) {
+ itr = iterate_hash(fcall_tbl);
+
+ ntry = iter_next(itr);
+ while (ntry != NULL) {
+ fentry.type = HD_hashntry;
+ fentry.count = ntry->count;
+ s = ntry->key;
+ t = ntry->lib;
+ i = strlen(s) + 1;
+ j = strlen(t) + 1;
+ fentry.sz_key = i;
+ fentry.sz_lib = j;
+ if (i + sizeof (fentry) > bufsz) {
+ buf = my_realloc(buf, i + j + sizeof (fentry),
+ NULL);
+ bufsz = i + j + sizeof (fentry);
+ }
+ (void) memcpy(buf, &fentry, sizeof (fentry));
+ (void) strlcpy((char *)(buf + sizeof (fentry)), t, j);
+ (void) strlcpy((char *)(buf + sizeof (fentry) + j),
+ s, i);
+ if (write(sfd, buf, sizeof (fentry) + i + j) == -1)
+ abend("Error writing to tmp file", NULL);
+ ntry = iter_next(itr);
+ }
+ iter_free(itr);
+ }
+
+ /* Now write the count/syscount structs down */
+ bufsz = sizeof (fentry) + (sizeof (struct counts) + maxsyscalls() *
+ sizeof (struct syscount));
+ buf = my_realloc(buf, bufsz, NULL);
+ fentry.type = HD_cts_syscts;
+ fentry.count = 0; /* undefined, really */
+ fentry.sz_key = bufsz - sizeof (fentry);
+ fentry.sz_lib = 0; /* also undefined */
+ (void) memcpy(buf, &fentry, sizeof (fentry));
+ (void) memcpy((char *)(buf + sizeof (fentry)), Cp,
+ bufsz - sizeof (fentry));
+ if (write(sfd, buf, bufsz) == -1)
+ abend("Error writing cts/syscts to tmpfile", NULL);
+
+ free(buf);
+}
+
+/*
+ * The following reads entries from the tempfile back to the parent
+ * so that information can be collected and summed for overall statistics.
+ * This reads records out of the tempfile. If they are hash table entries,
+ * the record is merged with the hash table kept by the parent process.
+ * If the information is a struct count/struct syscount pair, they are
+ * copied and added into the count/syscount array kept by the parent.
+ */
+
+void
+file_to_parent()
+{
+ hdntry_t ntry;
+ char *s = NULL;
+ char *t = NULL;
+ size_t c_offset = 0;
+ size_t filesz;
+ size_t t_strsz = 0;
+ size_t s_strsz = 0;
+ struct stat fsi;
+
+ if (descendent)
+ return;
+
+ if (fstat(sfd, &fsi) == -1)
+ abend("Error stat-ing tempfile", NULL);
+ filesz = fsi.st_size;
+
+ while (c_offset < filesz) {
+ /* first get hdntry */
+ if (pread(sfd, &ntry, sizeof (hdntry_t), c_offset) !=
+ sizeof (hdntry_t))
+ abend("Unable to perform full read of hdntry", NULL);
+ c_offset += sizeof (hdntry_t);
+
+ switch (ntry.type) {
+ case HD_hashntry:
+
+ /* first get lib string */
+ if (ntry.sz_lib > t_strsz) {
+ t = my_realloc(t, ntry.sz_lib, NULL);
+ t_strsz = ntry.sz_lib;
+ }
+
+ (void) memset(t, 0, t_strsz);
+
+ /* now actually get the string */
+ if (pread(sfd, t, ntry.sz_lib, c_offset) != ntry.sz_lib)
+ abend("Unable to perform full read of lib str",
+ NULL);
+ c_offset += ntry.sz_lib;
+
+ /* now get key string */
+
+ if (ntry.sz_key > s_strsz) {
+ s = my_realloc(s, ntry.sz_key, NULL);
+ s_strsz = ntry.sz_key;
+ }
+ (void) memset(s, 0, s_strsz);
+ if (pread(sfd, s, ntry.sz_key, c_offset) != ntry.sz_key)
+ abend("Unable to perform full read of key str",
+ NULL);
+ c_offset += ntry.sz_key;
+
+ add_fcall(fcall_tbl, t, s, ntry.count);
+ break;
+
+ case HD_cts_syscts:
+ {
+ struct counts *ncp;
+ size_t bfsz = sizeof (struct counts) + maxsyscalls()
+ * sizeof (struct syscount);
+ int i;
+ struct syscount *sscp;
+
+ if (ntry.sz_key != bfsz)
+ abend("cts/syscts size does not sanity check",
+ NULL);
+ ncp = my_malloc(ntry.sz_key, NULL);
+
+ if (pread(sfd, ncp, ntry.sz_key, c_offset) !=
+ ntry.sz_key)
+ abend("Unable to perform full read of cts",
+ NULL);
+ c_offset += ntry.sz_key;
+
+ sscp = (struct syscount *)(ncp + 1);
+
+ (void) mutex_lock(&count_lock);
+
+ Cp->usrtotal.tv_sec += ncp->usrtotal.tv_sec;
+ Cp->usrtotal.tv_nsec += ncp->usrtotal.tv_nsec;
+ if (Cp->usrtotal.tv_nsec >= NANOSEC) {
+ Cp->usrtotal.tv_nsec -= NANOSEC;
+ Cp->usrtotal.tv_sec++;
+ }
+ for (i = 0; i <= PRMAXSYS; i++) {
+ ncp->syscount[i] = sscp;
+ sscp += nsubcodes(i);
+ }
+
+ for (i = 0; i <= PRMAXFAULT; i++) {
+ Cp->fltcount[i] += ncp->fltcount[i];
+ }
+
+ for (i = 0; i <= PRMAXSIG; i++) {
+ Cp->sigcount[i] += ncp->sigcount[i];
+ }
+
+ for (i = 0; i <= PRMAXSYS; i++) {
+ struct syscount *scp = Cp->syscount[i];
+ struct syscount *nscp = ncp->syscount[i];
+ int n = nsubcodes(i);
+ int subcode;
+
+ for (subcode = 0; subcode < n; subcode++,
+ scp++, nscp++) {
+ scp->count += nscp->count;
+ scp->error += nscp->error;
+ scp->stime.tv_sec += nscp->stime.tv_sec;
+ scp->stime.tv_nsec +=
+ nscp->stime.tv_nsec;
+ if (scp->stime.tv_nsec >= NANOSEC) {
+ scp->stime.tv_nsec -= NANOSEC;
+ scp->stime.tv_sec++;
+ }
+ }
+ }
+ (void) mutex_unlock(&count_lock);
+ free(ncp);
+ break;
+ }
+ default:
+
+ abend("Unknown file entry type encountered", NULL);
+ break;
+
+ }
+
+ if (fstat(sfd, &fsi) == -1)
+ abend("Error stat-ing tempfile", NULL);
+ filesz = fsi.st_size;
+ }
+ if (s != NULL)
+ free(s);
+ if (t != NULL)
+ free(t);
+}
+
+void
+make_pname(private_t *pri, id_t tid)
+{
+ if (!cflag) {
+ int ff = (fflag || ngrab > 1);
+ int lf = (lflag | tid | (Thr_agent != NULL) | (truss_nlwp > 1));
+ pid_t pid = Pstatus(Proc)->pr_pid;
+ id_t lwpid = pri->lwpstat->pr_lwpid;
+
+ if (ff != pri->pparam.ff ||
+ lf != pri->pparam.lf ||
+ pid != pri->pparam.pid ||
+ lwpid != pri->pparam.lwpid ||
+ tid != pri->pparam.tid) {
+ char *s = pri->pname;
+
+ if (ff)
+ s += sprintf(s, "%d", (int)pid);
+ if (lf)
+ s += sprintf(s, "/%d", (int)lwpid);
+ if (tid)
+ s += sprintf(s, "@%d", (int)tid);
+ if (ff || lf)
+ *s++ = ':', *s++ = '\t';
+ if (ff && lf && s < pri->pname + 9)
+ *s++ = '\t';
+ *s = '\0';
+ pri->pparam.ff = ff;
+ pri->pparam.lf = lf;
+ pri->pparam.pid = pid;
+ pri->pparam.lwpid = lwpid;
+ pri->pparam.tid = tid;
+ }
+ }
+}
+
+/*
+ * Print the pri->pname[] string, if any.
+ */
+void
+putpname(private_t *pri)
+{
+ if (pri->pname[0])
+ (void) fputs(pri->pname, stdout);
+}
+
+/*
+ * Print the timestamp, if requested (-d, -D, or -E).
+ */
+void
+timestamp(private_t *pri)
+{
+ const lwpstatus_t *Lsp = pri->lwpstat;
+ int seconds;
+ int fraction;
+
+ if (!(dflag|Dflag|Eflag) || !(Lsp->pr_flags & PR_STOPPED))
+ return;
+
+ seconds = Lsp->pr_tstamp.tv_sec - Cp->basetime.tv_sec;
+ fraction = Lsp->pr_tstamp.tv_nsec - Cp->basetime.tv_nsec;
+ if (fraction < 0) {
+ seconds--;
+ fraction += NANOSEC;
+ }
+ /* fraction in 1/10 milliseconds, rounded up */
+ fraction = (fraction + 50000) / 100000;
+ if (fraction >= (MILLISEC * 10)) {
+ seconds++;
+ fraction -= (MILLISEC * 10);
+ }
+
+ if (dflag) /* time stamp */
+ (void) printf("%2d.%4.4d\t", seconds, fraction);
+
+ if (Dflag) { /* time delta */
+ int oseconds = pri->seconds;
+ int ofraction = pri->fraction;
+
+ pri->seconds = seconds;
+ pri->fraction = fraction;
+ seconds -= oseconds;
+ fraction -= ofraction;
+ if (fraction < 0) {
+ seconds--;
+ fraction += (MILLISEC * 10);
+ }
+ (void) printf("%2d.%4.4d\t", seconds, fraction);
+ }
+
+ if (Eflag) {
+ seconds = Lsp->pr_stime.tv_sec - pri->syslast.tv_sec;
+ fraction = Lsp->pr_stime.tv_nsec - pri->syslast.tv_nsec;
+
+ if (fraction < 0) {
+ seconds--;
+ fraction += NANOSEC;
+ }
+ /* fraction in 1/10 milliseconds, rounded up */
+ fraction = (fraction + 50000) / 100000;
+ if (fraction >= (MILLISEC * 10)) {
+ seconds++;
+ fraction -= (MILLISEC * 10);
+ }
+ (void) printf("%2d.%4.4d\t", seconds, fraction);
+ }
+}
+
+/*
+ * Create output file, being careful about
+ * suid/sgid and file descriptor 0, 1, 2 issues.
+ */
+int
+xcreat(char *path)
+{
+ int fd;
+ int mode = 0666;
+
+ if (Euid == Ruid && Egid == Rgid) /* not set-id */
+ fd = creat(path, mode);
+ else if (access(path, F_OK) != 0) { /* file doesn't exist */
+ /* if directory permissions OK, create file & set ownership */
+
+ char *dir;
+ char *p;
+ char dot[4];
+
+ /* generate path for directory containing file */
+ if ((p = strrchr(path, '/')) == NULL) { /* no '/' */
+ p = dir = dot;
+ *p++ = '.'; /* current directory */
+ *p = '\0';
+ } else if (p == path) { /* leading '/' */
+ p = dir = dot;
+ *p++ = '/'; /* root directory */
+ *p = '\0';
+ } else { /* embedded '/' */
+ dir = path; /* directory path */
+ *p = '\0';
+ }
+
+ if (access(dir, W_OK|X_OK) != 0) {
+ /* not writeable/searchable */
+ *p = '/';
+ fd = -1;
+ } else { /* create file and set ownership correctly */
+ *p = '/';
+ if ((fd = creat(path, mode)) >= 0)
+ (void) chown(path, (int)Ruid, (int)Rgid);
+ }
+ } else if (access(path, W_OK) != 0) /* file not writeable */
+ fd = -1;
+ else
+ fd = creat(path, mode);
+
+ /*
+ * Make sure it's not one of 0, 1, or 2.
+ * This allows truss to work when spawned by init(1m).
+ */
+ if (0 <= fd && fd <= 2) {
+ int dfd = fcntl(fd, F_DUPFD, 3);
+ (void) close(fd);
+ fd = dfd;
+ }
+
+ /*
+ * Mark it close-on-exec so created processes don't inherit it.
+ */
+ if (fd >= 0)
+ (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
+
+ return (fd);
+}
+
+void
+setoutput(int ofd)
+{
+ if (ofd < 0) {
+ (void) close(1);
+ (void) fcntl(2, F_DUPFD, 1);
+ } else if (ofd != 1) {
+ (void) close(1);
+ (void) fcntl(ofd, F_DUPFD, 1);
+ (void) close(ofd);
+ /* if no stderr, make it the same file */
+ if ((ofd = dup(2)) < 0)
+ (void) fcntl(1, F_DUPFD, 2);
+ else
+ (void) close(ofd);
+ }
+}
+
+/*
+ * Accumulate time differencies: a += e - s;
+ */
+void
+accumulate(timestruc_t *ap, const timestruc_t *ep, const timestruc_t *sp)
+{
+ ap->tv_sec += ep->tv_sec - sp->tv_sec;
+ ap->tv_nsec += ep->tv_nsec - sp->tv_nsec;
+ if (ap->tv_nsec >= NANOSEC) {
+ ap->tv_nsec -= NANOSEC;
+ ap->tv_sec++;
+ } else if (ap->tv_nsec < 0) {
+ ap->tv_nsec += NANOSEC;
+ ap->tv_sec--;
+ }
+}
+
+int
+lib_sort(const void *p1, const void *p2)
+{
+ int cmpr = 0;
+ long i;
+ long j;
+
+ hentry_t *t1 = (hentry_t *)p1;
+ hentry_t *t2 = (hentry_t *)p2;
+
+ char *p = t1->lib;
+ char *q = t2->lib;
+
+ if ((cmpr = strcmp(p, q)) == 0) {
+ i = t1->count;
+ j = t2->count;
+ if (i > j)
+ return (-1);
+ else if (i < j)
+ return (1);
+ else {
+ p = t1->key;
+ q = t2->key;
+ return (strcmp(p, q));
+ }
+ } else
+ return (cmpr);
+}
+
+void
+report(private_t *pri, time_t lapse) /* elapsed time, clock ticks */
+{
+ int i;
+ long count;
+ const char *name;
+ long error;
+ long total;
+ long errtot;
+ timestruc_t tickzero;
+ timestruc_t ticks;
+ timestruc_t ticktot;
+
+ if (descendent)
+ return;
+
+ for (i = 0, total = 0; i <= PRMAXFAULT && !interrupt; i++) {
+ if ((count = Cp->fltcount[i]) != 0) {
+ if (total == 0) /* produce header */
+ (void) printf("faults -------------\n");
+
+ name = proc_fltname(i, pri->flt_name,
+ sizeof (pri->flt_name));
+
+ (void) printf("%s%s\t%4ld\n", name,
+ (((int)strlen(name) < 8)?
+ (const char *)"\t" : (const char *)""),
+ count);
+ total += count;
+ }
+ }
+ if (total && !interrupt)
+ (void) printf("total:\t\t%4ld\n\n", total);
+
+ for (i = 0, total = 0; i <= PRMAXSIG && !interrupt; i++) {
+ if ((count = Cp->sigcount[i]) != 0) {
+ if (total == 0) /* produce header */
+ (void) printf("signals ------------\n");
+ name = signame(pri, i);
+ (void) printf("%s%s\t%4ld\n", name,
+ (((int)strlen(name) < 8)?
+ (const char *)"\t" : (const char *)""),
+ count);
+ total += count;
+ }
+ }
+ if (total && !interrupt)
+ (void) printf("total:\t\t%4ld\n\n", total);
+
+ if ((Dynpat != NULL) && !interrupt) {
+ size_t elem = elements_in_table(fcall_tbl);
+ hiter_t *itr = iterate_hash(fcall_tbl);
+ hentry_t *tmp = iter_next(itr);
+ hentry_t *stbl = my_malloc(elem * sizeof (hentry_t), NULL);
+ i = 0;
+ while ((tmp != NULL) && (i < elem)) {
+ stbl[i].prev = tmp->prev;
+ stbl[i].next = tmp->next;
+ stbl[i].lib = tmp->lib;
+ stbl[i].key = tmp->key;
+ stbl[i].count = tmp->count;
+ tmp = iter_next(itr);
+ i++;
+ }
+ qsort((void *)stbl, elem, sizeof (hentry_t),
+ lib_sort);
+ (void) printf(
+ "\n%-20s %-40s %s\n", "Library:", "Function", "calls");
+ for (i = 0; i < elem; i++) {
+ (void) printf("%-20s %-40s %ld\n", stbl[i].lib,
+ stbl[i].key, stbl[i].count);
+ }
+ iter_free(itr);
+ free(stbl);
+ itr = NULL;
+ }
+
+ if (!interrupt)
+ (void) printf(
+ "\nsyscall seconds calls errors\n");
+
+ total = errtot = 0;
+ tickzero.tv_sec = ticks.tv_sec = ticktot.tv_sec = 0;
+ tickzero.tv_nsec = ticks.tv_nsec = ticktot.tv_nsec = 0;
+ for (i = 0; i <= PRMAXSYS && !interrupt; i++) {
+ struct syscount *scp = Cp->syscount[i];
+ int n = nsubcodes(i);
+ int subcode;
+
+ for (subcode = 0; subcode < n; subcode++, scp++) {
+ if ((count = scp->count) != 0 || scp->error) {
+ (void) printf("%-19.19s ",
+ sysname(pri, i, subcode));
+
+ ticks = scp->stime;
+ accumulate(&ticktot, &ticks, &tickzero);
+ prtim(&ticks);
+
+ (void) printf(" %7ld", count);
+ if ((error = scp->error) != 0)
+ (void) printf(" %7ld", error);
+ (void) fputc('\n', stdout);
+ total += count;
+ errtot += error;
+ }
+ }
+ }
+
+ if (!interrupt) {
+ (void) printf(
+ " -------- ------ ----\n");
+ (void) printf("sys totals: ");
+ prtim(&ticktot);
+ (void) printf(" %7ld %6ld\n", total, errtot);
+ }
+
+ if (!interrupt) {
+ (void) printf("usr time: ");
+ prtim(&Cp->usrtotal);
+ (void) fputc('\n', stdout);
+ }
+
+ if (!interrupt) {
+ int hz = (int)sysconf(_SC_CLK_TCK);
+
+ ticks.tv_sec = lapse / hz;
+ ticks.tv_nsec = (lapse % hz) * (1000000000 / hz);
+ (void) printf("elapsed: ");
+ prtim(&ticks);
+ (void) fputc('\n', stdout);
+ }
+}
+
+void
+prtim(timestruc_t *tp)
+{
+ time_t sec;
+
+ if ((sec = tp->tv_sec) != 0) /* whole seconds */
+ (void) printf("%5lu", sec);
+ else
+ (void) printf(" ");
+
+ (void) printf(".%3.3ld", tp->tv_nsec/1000000); /* fraction */
+}
+
+/*
+ * Gather process id's.
+ * Return 0 on success, != 0 on failure.
+ */
+void
+pids(char *arg, proc_set_t *grab)
+{
+ pid_t pid = -1;
+ int i;
+ const char *lwps = NULL;
+
+ if ((pid = proc_arg_xpsinfo(arg, PR_ARG_PIDS, NULL, &i, &lwps)) < 0) {
+ (void) fprintf(stderr, "%s: cannot trace '%s': %s\n",
+ command, arg, Pgrab_error(i));
+ return;
+ }
+
+ for (i = 0; i < ngrab; i++)
+ if (grab[i].pid == pid) /* duplicate */
+ break;
+
+ if (i == ngrab) {
+ grab[ngrab].pid = pid;
+ grab[ngrab].lwps = lwps;
+ ngrab++;
+ } else {
+ (void) fprintf(stderr, "%s: duplicate process-id ignored: %d\n",
+ command, (int)pid);
+ }
+}
+
+/*
+ * Report psargs string.
+ */
+void
+psargs(private_t *pri)
+{
+ pid_t pid = Pstatus(Proc)->pr_pid;
+ psinfo_t psinfo;
+
+ if (proc_get_psinfo(pid, &psinfo) == 0)
+ (void) printf("%spsargs: %.64s\n",
+ pri->pname, psinfo.pr_psargs);
+ else {
+ perror("psargs()");
+ (void) printf("%s\t*** Cannot read psinfo file for pid %d\n",
+ pri->pname, (int)pid);
+ }
+}
+
+char *
+fetchstring(private_t *pri, long addr, int maxleng)
+{
+ int nbyte;
+ int leng = 0;
+ char string[41];
+
+ string[40] = '\0';
+ if (pri->str_bsize == 0) /* initial allocation of string buffer */
+ pri->str_buffer =
+ my_malloc(pri->str_bsize = 16, "string buffer");
+ *pri->str_buffer = '\0';
+
+ for (nbyte = 40; nbyte == 40 && leng < maxleng; addr += 40) {
+ if ((nbyte = Pread(Proc, string, 40, addr)) <= 0)
+ return (leng? pri->str_buffer : NULL);
+ if (nbyte > 0 &&
+ (nbyte = strlen(string)) > 0) {
+ while (leng + nbyte >= pri->str_bsize)
+ pri->str_buffer =
+ my_realloc(pri->str_buffer,
+ pri->str_bsize *= 2, "string buffer");
+ (void) strcpy(pri->str_buffer+leng, string);
+ leng += nbyte;
+ }
+ }
+
+ if (leng > maxleng)
+ leng = maxleng;
+ pri->str_buffer[leng] = '\0';
+
+ return (pri->str_buffer);
+}
+
+static priv_set_t *
+getset(prpriv_t *p, priv_ptype_t set)
+{
+ return ((priv_set_t *)
+ &p->pr_sets[priv_getsetbyname(set) * p->pr_setsize]);
+}
+
+void
+show_cred(private_t *pri, int new, int loadonly)
+{
+ prcred_t cred;
+ prpriv_t *privs;
+
+ if (proc_get_cred(Pstatus(Proc)->pr_pid, &cred, 0) < 0) {
+ perror("show_cred() - credential");
+ (void) printf("%s\t*** Cannot get credentials\n", pri->pname);
+ return;
+ }
+ if ((privs = proc_get_priv(Pstatus(Proc)->pr_pid)) == NULL) {
+ perror("show_cred() - privileges");
+ (void) printf("%s\t*** Cannot get privileges\n", pri->pname);
+ return;
+ }
+
+ if (!loadonly && !cflag && prismember(&trace, SYS_execve)) {
+ if (new)
+ credentials = cred;
+ if ((new && cred.pr_ruid != cred.pr_suid) ||
+ cred.pr_ruid != credentials.pr_ruid ||
+ cred.pr_suid != credentials.pr_suid)
+ (void) printf(
+ "%s *** SUID: ruid/euid/suid = %d / %d / %d ***\n",
+ pri->pname,
+ (int)cred.pr_ruid,
+ (int)cred.pr_euid,
+ (int)cred.pr_suid);
+ if ((new && cred.pr_rgid != cred.pr_sgid) ||
+ cred.pr_rgid != credentials.pr_rgid ||
+ cred.pr_sgid != credentials.pr_sgid)
+ (void) printf(
+ "%s *** SGID: rgid/egid/sgid = %d / %d / %d ***\n",
+ pri->pname,
+ (int)cred.pr_rgid,
+ (int)cred.pr_egid,
+ (int)cred.pr_sgid);
+ if (privdata != NULL && cred.pr_euid != 0) {
+ priv_set_t *npset = getset(privs, PRIV_PERMITTED);
+ priv_set_t *opset = getset(privdata, PRIV_PERMITTED);
+ char *s, *t;
+ if (!priv_issubset(npset, opset)) {
+ /* Use the to be freed privdata as scratch */
+ priv_inverse(opset);
+ priv_intersect(npset, opset);
+ s = priv_set_to_str(opset, ',', PRIV_STR_SHORT);
+ t = priv_set_to_str(npset, ',', PRIV_STR_SHORT);
+ (void) printf("%s *** FPRIV: P/E: %s ***\n",
+ pri->pname,
+ strlen(s) > strlen(t) ? t : s);
+ free(s);
+ free(t);
+ }
+ }
+ }
+
+ if (privdata != NULL)
+ free(privdata);
+ credentials = cred;
+ privdata = privs;
+}
+
+/*
+ * Take control of a child process.
+ * We come here with truss_lock held.
+ */
+int
+control(private_t *pri, pid_t pid)
+{
+ const pstatus_t *Psp;
+ const lwpstatus_t *Lsp;
+ pid_t childpid = 0;
+ long flags;
+ int rc;
+
+ (void) mutex_lock(&gps->fork_lock);
+ while (gps->fork_pid != 0)
+ (void) cond_wait(&gps->fork_cv, &gps->fork_lock);
+ gps->fork_pid = getpid(); /* parent pid */
+ if ((childpid = fork()) == -1) {
+ (void) printf("%s\t*** Cannot fork() to control process #%d\n",
+ pri->pname, (int)pid);
+ Flush();
+ gps->fork_pid = 0;
+ (void) cond_broadcast(&gps->fork_cv);
+ (void) mutex_unlock(&gps->fork_lock);
+ release(pri, pid);
+ return (FALSE);
+ }
+
+ if (childpid != 0) {
+ /*
+ * The parent carries on, after a brief pause.
+ * The parent must wait until the child executes procadd(pid).
+ */
+ while (gps->fork_pid != childpid)
+ (void) cond_wait(&gps->fork_cv, &gps->fork_lock);
+ gps->fork_pid = 0;
+ (void) cond_broadcast(&gps->fork_cv);
+ (void) mutex_unlock(&gps->fork_lock);
+ return (FALSE);
+ }
+
+ childpid = getpid();
+ descendent = TRUE;
+ exit_called = FALSE;
+ Pfree(Proc); /* forget old process */
+
+ /*
+ * The parent process owns the shared gps->fork_lock.
+ * The child must grab it again.
+ */
+ (void) mutex_lock(&gps->fork_lock);
+
+ /*
+ * Child grabs the process and retains the tracing flags.
+ */
+ if ((Proc = Pgrab(pid, PGRAB_RETAIN, &rc)) == NULL) {
+ (void) fprintf(stderr,
+ "%s: cannot control child process, pid# %d: %s\n",
+ command, (int)pid, Pgrab_error(rc));
+ gps->fork_pid = childpid;
+ (void) cond_broadcast(&gps->fork_cv);
+ (void) mutex_unlock(&gps->fork_lock);
+ exit(2);
+ }
+
+ per_proc_init();
+ /*
+ * Add ourself to the set of truss processes
+ * and notify the parent to carry on.
+ */
+ procadd(pid, NULL);
+ gps->fork_pid = childpid;
+ (void) cond_broadcast(&gps->fork_cv);
+ (void) mutex_unlock(&gps->fork_lock);
+
+ /*
+ * We may have grabbed the child before it is fully stopped on exit
+ * from fork. Wait one second (at most) for it to settle down.
+ */
+ (void) Pwait(Proc, MILLISEC);
+ if (Rdb_agent != NULL)
+ Rdb_agent = Prd_agent(Proc);
+
+ Psp = Pstatus(Proc);
+ Lsp = &Psp->pr_lwp;
+ pri->lwpstat = Lsp;
+ data_model = Psp->pr_dmodel;
+
+ make_pname(pri, 0);
+
+ pri->syslast = Psp->pr_stime;
+ pri->usrlast = Psp->pr_utime;
+
+ flags = PR_FORK | PR_ASYNC;
+ if (Dynpat != NULL)
+ flags |= PR_BPTADJ; /* needed for x86 */
+ (void) Psetflags(Proc, flags);
+
+ return (TRUE);
+}
+
+/*
+ * Take control of an existing process.
+ */
+int
+grabit(private_t *pri, proc_set_t *set)
+{
+ const pstatus_t *Psp;
+ const lwpstatus_t *Lsp;
+ int gcode;
+
+ /*
+ * Don't force the takeover unless the -F option was specified.
+ */
+ if ((Proc = Pgrab(set->pid, Fflag, &gcode)) == NULL) {
+ (void) fprintf(stderr, "%s: %s: %d\n",
+ command, Pgrab_error(gcode), (int)set->pid);
+ pri->lwpstat = NULL;
+ return (FALSE);
+ }
+ Psp = Pstatus(Proc);
+ Lsp = &Psp->pr_lwp;
+ pri->lwpstat = Lsp;
+
+ make_pname(pri, 0);
+
+ data_model = Psp->pr_dmodel;
+ pri->syslast = Psp->pr_stime;
+ pri->usrlast = Psp->pr_utime;
+
+ if (fflag || Dynpat != NULL)
+ (void) Psetflags(Proc, PR_FORK);
+ else
+ (void) Punsetflags(Proc, PR_FORK);
+ procadd(set->pid, set->lwps);
+ show_cred(pri, TRUE, FALSE);
+ return (TRUE);
+}
+
+/*
+ * Release process from control.
+ */
+void
+release(private_t *pri, pid_t pid)
+{
+ /*
+ * The process in question is the child of a traced process.
+ * We are here to turn off the inherited tracing flags.
+ */
+ int fd;
+ char ctlname[100];
+ long ctl[2];
+
+ ctl[0] = PCSET;
+ ctl[1] = PR_RLC;
+
+ /* process is freshly forked, no need for exclusive open */
+ (void) sprintf(ctlname, "/proc/%d/ctl", (int)pid);
+ if ((fd = open(ctlname, O_WRONLY)) < 0 ||
+ write(fd, (char *)ctl, sizeof (ctl)) < 0) {
+ perror("release()");
+ (void) printf(
+ "%s\t*** Cannot release child process, pid# %d\n",
+ pri->pname, (int)pid);
+ Flush();
+ }
+ if (fd >= 0) /* run-on-last-close sets the process running */
+ (void) close(fd);
+}
+
+void
+intr(int sig)
+{
+ /*
+ * SIGUSR1 is special. It is used by one truss process to tell
+ * another truss process to release its controlled process.
+ * SIGUSR2 is also special. It is used to wake up threads waiting
+ * for a victim lwp to stop after an event that will leave the
+ * process hung (stopped and abandoned) has occurred.
+ */
+ if (sig == SIGUSR1) {
+ sigusr1 = TRUE;
+ } else if (sig == SIGUSR2) {
+ void *value;
+ private_t *pri;
+ struct ps_lwphandle *Lwp;
+
+ if (thr_getspecific(private_key, &value) == 0 &&
+ (pri = value) != NULL &&
+ (Lwp = pri->Lwp) != NULL)
+ (void) Lstop(Lwp, MILLISEC / 10);
+ } else {
+ interrupt = sig;
+ }
+}
+
+void
+errmsg(const char *s, const char *q)
+{
+ char msg[512];
+
+ if (s || q) {
+ msg[0] = '\0';
+ if (command) {
+ (void) strcpy(msg, command);
+ (void) strcat(msg, ": ");
+ }
+ if (s)
+ (void) strcat(msg, s);
+ if (q)
+ (void) strcat(msg, q);
+ (void) strcat(msg, "\n");
+ (void) write(2, msg, (size_t)strlen(msg));
+ }
+}
+
+void
+abend(const char *s, const char *q)
+{
+ (void) thr_sigsetmask(SIG_SETMASK, &fillset, NULL);
+ if (Proc) {
+ Flush();
+ errmsg(s, q);
+ clear_breakpoints();
+ (void) Punsetflags(Proc, PR_ASYNC);
+ Prelease(Proc, created? PRELEASE_KILL : PRELEASE_CLEAR);
+ procdel();
+ (void) wait4all();
+ } else {
+ errmsg(s, q);
+ }
+ exit(2);
+}
+
+/*
+ * Allocate memory.
+ * If allocation fails then print a message and abort.
+ */
+void *
+my_realloc(void *buf, size_t size, const char *msg)
+{
+ if ((buf = realloc(buf, size)) == NULL) {
+ if (msg != NULL)
+ abend("cannot allocate ", msg);
+ else
+ abend("memory allocation failure", NULL);
+ }
+
+ return (buf);
+}
+
+void *
+my_calloc(size_t nelem, size_t elsize, const char *msg)
+{
+ void *buf = NULL;
+
+ if ((buf = calloc(nelem, elsize)) == NULL) {
+ if (msg != NULL)
+ abend("cannot allocate ", msg);
+ else
+ abend("memory allocation failure", NULL);
+ }
+
+ return (buf);
+}
+
+void *
+my_malloc(size_t size, const char *msg)
+{
+ return (my_realloc(NULL, size, msg));
+}
+
+int
+wait4all()
+{
+ int i;
+ pid_t pid;
+ int rc = 0;
+ int status;
+
+ for (i = 0; i < 10; i++) {
+ while ((pid = wait(&status)) != -1) {
+ /* return exit() code of the created process */
+ if (pid == created) {
+ if (WIFEXITED(status))
+ rc = WEXITSTATUS(status);
+ else
+ rc |= 0x80; /* +128 to indicate sig */
+ }
+ }
+ if (errno != EINTR && errno != ERESTART)
+ break;
+ }
+
+ if (i >= 10) /* repeated interrupts */
+ rc = 2;
+
+ return (rc);
+}
+
+void
+letgo(private_t *pri)
+{
+ (void) printf("%s\t*** process otherwise traced, releasing ...\n",
+ pri->pname);
+}
+
+/*
+ * Test for empty set.
+ * support routine used by isemptyset() macro.
+ */
+int
+is_empty(const uint32_t *sp, /* pointer to set (array of int32's) */
+ size_t n) /* number of int32's in set */
+{
+ if (n) {
+ do {
+ if (*sp++)
+ return (FALSE);
+ } while (--n);
+ }
+
+ return (TRUE);
+}
+
+/*
+ * OR the second set into the first.
+ * The sets must be the same size.
+ */
+void
+or_set(uint32_t *sp1, const uint32_t *sp2, size_t n)
+{
+ if (n) {
+ do {
+ *sp1++ |= *sp2++;
+ } while (--n);
+ }
+}
diff --git a/usr/src/cmd/truss/print.c b/usr/src/cmd/truss/print.c
new file mode 100644
index 0000000..f49197a
--- /dev/null
+++ b/usr/src/cmd/truss/print.c
@@ -0,0 +1,2850 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
+ */
+
+/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
+/* All Rights Reserved */
+
+/* Copyright (c) 2013, OmniTI Computer Consulting, Inc. All rights reserved. */
+
+#define _SYSCALL32 /* make 32-bit compat headers visible */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <signal.h>
+#include <termio.h>
+#include <stddef.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/resource.h>
+#include <sys/ulimit.h>
+#include <sys/utsname.h>
+#include <sys/kstat.h>
+#include <sys/modctl.h>
+#include <sys/acl.h>
+#include <stropts.h>
+#include <sys/isa_defs.h>
+#include <sys/systeminfo.h>
+#include <sys/cladm.h>
+#include <sys/lwp.h>
+#include <bsm/audit.h>
+#include <libproc.h>
+#include <priv.h>
+#include <sys/aio.h>
+#include <sys/aiocb.h>
+#include <sys/corectl.h>
+#include <sys/cpc_impl.h>
+#include <sys/priocntl.h>
+#include <sys/tspriocntl.h>
+#include <sys/iapriocntl.h>
+#include <sys/rtpriocntl.h>
+#include <sys/fsspriocntl.h>
+#include <sys/fxpriocntl.h>
+#include <netdb.h>
+#include <nss_dbdefs.h>
+#include <sys/socketvar.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
+#include <netinet/sctp.h>
+#include <net/route.h>
+#include <sys/utrap.h>
+#include <sys/lgrp_user.h>
+#include <sys/door.h>
+#include <sys/tsol/tndb.h>
+#include <sys/rctl.h>
+#include <sys/rctl_impl.h>
+#include <sys/fork.h>
+#include <sys/task.h>
+#include "ramdata.h"
+#include "print.h"
+#include "proto.h"
+#include "systable.h"
+
+void grow(private_t *, int nbyte);
+
+#define GROW(nb) if (pri->sys_leng + (nb) >= pri->sys_ssize) grow(pri, (nb))
+
+
+/*ARGSUSED*/
+void
+prt_nov(private_t *pri, int raw, long val) /* print nothing */
+{
+}
+
+/*ARGSUSED*/
+void
+prt_dec(private_t *pri, int raw, long val) /* print as decimal */
+{
+ GROW(24);
+ if (data_model == PR_MODEL_ILP32)
+ pri->sys_leng += sprintf(pri->sys_string + pri->sys_leng,
+ "%d", (int)val);
+ else
+ pri->sys_leng += sprintf(pri->sys_string + pri->sys_leng,
+ "%ld", val);
+}
+
+/*ARGSUSED*/
+void
+prt_uns(private_t *pri, int raw, long val) /* print as unsigned decimal */
+{
+ GROW(24);
+ if (data_model == PR_MODEL_ILP32)
+ pri->sys_leng += sprintf(pri->sys_string + pri->sys_leng,
+ "%u", (int)val);
+ else
+ pri->sys_leng += sprintf(pri->sys_string + pri->sys_leng,
+ "%lu", val);
+}
+
+/* print as unsigned decimal, except for -1 */
+void
+prt_un1(private_t *pri, int raw, long val)
+{
+ if ((int)val == -1)
+ prt_dec(pri, raw, val);
+ else
+ prt_uns(pri, raw, val);
+}
+
+/*ARGSUSED*/
+void
+prt_oct(private_t *pri, int raw, long val) /* print as octal */
+{
+ GROW(24);
+ if (data_model == PR_MODEL_ILP32)
+ pri->sys_leng += sprintf(pri->sys_string + pri->sys_leng,
+ "%#o", (int)val);
+ else
+ pri->sys_leng += sprintf(pri->sys_string + pri->sys_leng,
+ "%#lo", val);
+}
+
+/*ARGSUSED*/
+void
+prt_hex(private_t *pri, int raw, long val) /* print as hexadecimal */
+{
+ GROW(20);
+ if (data_model == PR_MODEL_ILP32)
+ pri->sys_leng += sprintf(pri->sys_string + pri->sys_leng,
+ "0x%.8X", (int)val);
+ else
+ pri->sys_leng += sprintf(pri->sys_string + pri->sys_leng,
+ "0x%.8lX", val);
+}
+
+/* print as hexadecimal (half size) */
+/*ARGSUSED*/
+void
+prt_hhx(private_t *pri, int raw, long val)
+{
+ GROW(20);
+ if (data_model == PR_MODEL_ILP32)
+ pri->sys_leng += sprintf(pri->sys_string + pri->sys_leng,
+ "0x%.4X", (int)val);
+ else
+ pri->sys_leng += sprintf(pri->sys_string + pri->sys_leng,
+ "0x%.4lX", val);
+}
+
+/* print as decimal if small, else hexadecimal */
+/*ARGSUSED*/
+void
+prt_dex(private_t *pri, int raw, long val)
+{
+ if (val & 0xff000000)
+ prt_hex(pri, 0, val);
+ else
+ prt_dec(pri, 0, val);
+}
+
+/* print long long offset */
+/*ARGSUSED*/
+void
+prt_llo(private_t *pri, int raw, long val1, long val2)
+{
+ int hival;
+ int loval;
+
+#ifdef _LONG_LONG_LTOH
+ hival = (int)val2;
+ loval = (int)val1;
+#else
+ hival = (int)val1;
+ loval = (int)val2;
+#endif
+
+ if (hival == 0) {
+ prt_dex(pri, 0, loval);
+ } else {
+ GROW(18);
+ pri->sys_leng +=
+ sprintf(pri->sys_string + pri->sys_leng, "0x%.8X%.8X",
+ hival, loval);
+ }
+}
+
+void
+escape_string(private_t *pri, const char *s)
+{
+ /*
+ * We want to avoid outputting unprintable characters that may
+ * destroy the user's terminal. So we do one pass to find any
+ * unprintable characters, size the array appropriately, and
+ * then walk each character by hand. Those that are unprintable
+ * are replaced by a hex escape (\xNN). We also escape quotes for
+ * completeness.
+ */
+ int i, unprintable, quotes;
+ size_t len = strlen(s);
+ for (i = 0, unprintable = 0, quotes = 0; i < len; i++) {
+ if (!isprint(s[i]))
+ unprintable++;
+ if (s[i] == '"')
+ quotes++;
+ }
+
+ GROW(len + 3 * unprintable + quotes + 2);
+
+ pri->sys_string[pri->sys_leng++] = '"';
+ for (i = 0; i < len; i++) {
+ if (s[i] == '"')
+ pri->sys_string[pri->sys_leng++] = '\\';
+
+ if (isprint(s[i])) {
+ pri->sys_string[pri->sys_leng++] = s[i];
+ } else {
+ pri->sys_leng += sprintf(pri->sys_string +
+ pri->sys_leng, "\\x%02x", (uint8_t)s[i]);
+ }
+ }
+ pri->sys_string[pri->sys_leng++] = '"';
+}
+
+void
+prt_stg(private_t *pri, int raw, long val) /* print as string */
+{
+ char *s = raw? NULL : fetchstring(pri, (long)val, PATH_MAX);
+
+ if (s == NULL)
+ prt_hex(pri, 0, val);
+ else
+ escape_string(pri, s);
+}
+
+/* print as string returned from syscall */
+void
+prt_rst(private_t *pri, int raw, long val)
+{
+ char *s = (raw || pri->Errno)? NULL :
+ fetchstring(pri, (long)val, PATH_MAX);
+
+ if (s == NULL)
+ prt_hex(pri, 0, val);
+ else {
+ GROW((int)strlen(s) + 2);
+ pri->sys_leng += snprintf(pri->sys_string + pri->sys_leng,
+ pri->sys_ssize - pri->sys_leng, "\"%s\"", s);
+ }
+}
+
+/* print contents of readlink() buffer */
+void
+prt_rlk(private_t *pri, int raw, long val)
+{
+ char *s = (raw || pri->Errno || pri->Rval1 <= 0)? NULL :
+ fetchstring(pri, (long)val,
+ (pri->Rval1 > PATH_MAX)? PATH_MAX : (int)pri->Rval1);
+
+ if (s == NULL)
+ prt_hex(pri, 0, val);
+ else {
+ GROW((int)strlen(s) + 2);
+ pri->sys_leng += snprintf(pri->sys_string + pri->sys_leng,
+ pri->sys_ssize - pri->sys_leng, "\"%s\"", s);
+ }
+}
+
+void
+prt_ioc(private_t *pri, int raw, long val) /* print ioctl code */
+{
+ const char *s = raw? NULL : ioctlname(pri, (int)val);
+
+ if (s == NULL)
+ prt_hex(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+void
+prt_ioa(private_t *pri, int raw, long val) /* print ioctl argument */
+{
+ const char *s;
+
+ /* cheating -- look at the ioctl() code */
+ switch (pri->sys_args[1]) {
+
+ /* kstat ioctl()s */
+ case KSTAT_IOC_READ:
+ case KSTAT_IOC_WRITE:
+#ifdef _LP64
+ if (data_model == PR_MODEL_ILP32)
+ prt_stg(pri, raw,
+ val + offsetof(kstat32_t, ks_name[0]));
+ else
+#endif
+ prt_stg(pri, raw,
+ val + offsetof(kstat_t, ks_name[0]));
+ break;
+
+ /* streams ioctl()s */
+ case I_LOOK:
+ prt_rst(pri, raw, val);
+ break;
+ case I_PUSH:
+ case I_FIND:
+ prt_stg(pri, raw, val);
+ break;
+ case I_LINK:
+ case I_UNLINK:
+ case I_SENDFD:
+ prt_dec(pri, 0, val);
+ break;
+ case I_SRDOPT:
+ if (raw || (s = strrdopt(val)) == NULL)
+ prt_dec(pri, 0, val);
+ else
+ outstring(pri, s);
+ break;
+ case I_SETSIG:
+ if (raw || (s = strevents(pri, val)) == NULL)
+ prt_hex(pri, 0, val);
+ else
+ outstring(pri, s);
+ break;
+ case I_FLUSH:
+ if (raw || (s = strflush(val)) == NULL)
+ prt_dec(pri, 0, val);
+ else
+ outstring(pri, s);
+ break;
+
+ /* tty ioctl()s */
+ case TCSBRK:
+ case TCXONC:
+ case TCFLSH:
+ case TCDSET:
+ prt_dec(pri, 0, val);
+ break;
+
+ default:
+ prt_hex(pri, 0, val);
+ break;
+ }
+}
+
+void
+prt_pip(private_t *pri, int raw, long val) /* print pipe code */
+{
+ const char *s = NULL;
+
+ if (!raw) {
+ switch (val) {
+ case O_CLOEXEC:
+ s = "O_CLOEXEC";
+ break;
+ case O_NONBLOCK:
+ s = "O_NONBLOCK";
+ break;
+ case O_CLOEXEC|O_NONBLOCK:
+ s = "O_CLOEXEC|O_NONBLOCK";
+ break;
+ }
+ }
+
+ if (s == NULL)
+ prt_dex(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+void
+prt_pfd(private_t *pri, int raw, long val) /* print pipe code */
+{
+ int fds[2];
+ char str[32];
+
+ /* the fds only have meaning if the return value is 0 */
+ if (!raw &&
+ pri->Rval1 >= 0 &&
+ Pread(Proc, fds, sizeof (fds), (long)val) == sizeof (fds)) {
+ (void) snprintf(str, sizeof (str), "[%d,%d]", fds[0], fds[1]);
+ outstring(pri, str);
+ } else {
+ prt_hex(pri, 0, val);
+ }
+}
+
+void
+prt_fcn(private_t *pri, int raw, long val) /* print fcntl code */
+{
+ const char *s = raw? NULL : fcntlname(val);
+
+ if (s == NULL)
+ prt_dec(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+void
+prt_s86(private_t *pri, int raw, long val) /* print sysi86 code */
+{
+
+ const char *s = raw? NULL : si86name(val);
+
+ if (s == NULL)
+ prt_dec(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+void
+prt_uts(private_t *pri, int raw, long val) /* print utssys code */
+{
+ const char *s = raw? NULL : utscode(val);
+
+ if (s == NULL)
+ prt_dec(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+void
+prt_msc(private_t *pri, int raw, long val) /* print msgsys command */
+{
+ const char *s = raw? NULL : msgcmd(val);
+
+ if (s == NULL)
+ prt_dec(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+void
+prt_msf(private_t *pri, int raw, long val) /* print msgsys flags */
+{
+ const char *s = raw? NULL : msgflags(pri, (int)val);
+
+ if (s == NULL)
+ prt_oct(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+void
+prt_smc(private_t *pri, int raw, long val) /* print semsys command */
+{
+ const char *s = raw? NULL : semcmd(val);
+
+ if (s == NULL)
+ prt_dec(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+void
+prt_sef(private_t *pri, int raw, long val) /* print semsys flags */
+{
+ const char *s = raw? NULL : semflags(pri, (int)val);
+
+ if (s == NULL)
+ prt_oct(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+void
+prt_shc(private_t *pri, int raw, long val) /* print shmsys command */
+{
+ const char *s = raw? NULL : shmcmd(val);
+
+ if (s == NULL)
+ prt_dec(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+void
+prt_shf(private_t *pri, int raw, long val) /* print shmsys flags */
+{
+ const char *s = raw? NULL : shmflags(pri, (int)val);
+
+ if (s == NULL)
+ prt_oct(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+void
+prt_sfs(private_t *pri, int raw, long val) /* print sysfs code */
+{
+ const char *s = raw? NULL : sfsname(val);
+
+ if (s == NULL)
+ prt_dec(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+void
+prt_opn(private_t *pri, int raw, long val) /* print open code */
+{
+ const char *s = raw? NULL : openarg(pri, val);
+
+ if (s == NULL)
+ prt_oct(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+void
+prt_sig(private_t *pri, int raw, long val) /* print signal name */
+{
+ const char *s = raw? NULL : signame(pri, (int)val);
+
+ if (s == NULL)
+ prt_hex(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+void
+prt_smf(private_t *pri, int raw, long val) /* print streams message flags */
+{
+ switch (val) {
+ case 0:
+ prt_dec(pri, 0, val);
+ break;
+ case RS_HIPRI:
+ if (raw)
+ prt_hhx(pri, 0, val);
+ else
+ outstring(pri, "RS_HIPRI");
+ break;
+ default:
+ prt_hhx(pri, 0, val);
+ break;
+ }
+}
+
+void
+prt_mtf(private_t *pri, int raw, long val) /* print mount flags */
+{
+ const char *s = raw? NULL : mountflags(pri, val);
+
+ if (s == NULL)
+ prt_hex(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+void
+prt_mft(private_t *pri, int raw, long val) /* print mount file system type */
+{
+ if (val >= 0 && val < 256)
+ prt_dec(pri, 0, val);
+ else if (raw)
+ prt_hex(pri, 0, val);
+ else
+ prt_stg(pri, raw, val);
+}
+
+#define ISREAD(code) \
+ ((code) == SYS_read || (code) == SYS_pread || (code) == SYS_pread64 || \
+ (code) == SYS_recv || (code) == SYS_recvfrom)
+#define ISWRITE(code) \
+ ((code) == SYS_write || (code) == SYS_pwrite || \
+ (code) == SYS_pwrite64 || (code) == SYS_send || (code) == SYS_sendto)
+
+/* print contents of read() or write() I/O buffer */
+void
+prt_iob(private_t *pri, int raw, long val)
+{
+ const lwpstatus_t *Lsp = pri->lwpstat;
+ int syscall = Lsp->pr_what;
+ int fdp1 = pri->sys_args[0] + 1;
+ ssize_t nbyte = ISWRITE(syscall)? pri->sys_args[2] :
+ (pri->Errno? 0 : pri->Rval1);
+ int elsewhere = FALSE; /* TRUE iff dumped elsewhere */
+ char buffer[IOBSIZE];
+
+ pri->iob_buf[0] = '\0';
+
+ if (Lsp->pr_why == PR_SYSEXIT && nbyte > IOBSIZE) {
+ if (ISREAD(syscall))
+ elsewhere = prismember(&readfd, fdp1);
+ else
+ elsewhere = prismember(&writefd, fdp1);
+ }
+
+ if (nbyte <= 0 || elsewhere)
+ prt_hex(pri, 0, val);
+ else {
+ int nb = nbyte > IOBSIZE? IOBSIZE : (int)nbyte;
+
+ if (Pread(Proc, buffer, (size_t)nb, (long)val) != nb)
+ prt_hex(pri, 0, val);
+ else {
+ pri->iob_buf[0] = '"';
+ showbytes(buffer, nb, pri->iob_buf + 1);
+ (void) strlcat(pri->iob_buf,
+ (nb == nbyte)?
+ (const char *)"\"" : (const char *)"\"..",
+ sizeof (pri->iob_buf));
+ if (raw)
+ prt_hex(pri, 0, val);
+ else
+ outstring(pri, pri->iob_buf);
+ }
+ }
+}
+#undef ISREAD
+#undef ISWRITE
+
+void
+prt_idt(private_t *pri, int raw, long val) /* print idtype_t, waitid() arg */
+{
+ const char *s = raw? NULL : idtype_enum(pri, val);
+
+ if (s == NULL)
+ prt_dec(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+void
+prt_wop(private_t *pri, int raw, long val) /* print waitid() options */
+{
+ const char *s = raw? NULL : woptions(pri, (int)val);
+
+ if (s == NULL)
+ prt_oct(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+void
+prt_whn(private_t *pri, int raw, long val) /* print lseek() whence argument */
+{
+ const char *s = raw? NULL : whencearg(val);
+
+ if (s == NULL)
+ prt_dec(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+/*ARGSUSED*/
+void
+prt_spm(private_t *pri, int raw, long val) /* print sigprocmask argument */
+{
+ const char *s = NULL;
+
+ if (!raw) {
+ switch (val) {
+ case SIG_BLOCK: s = "SIG_BLOCK"; break;
+ case SIG_UNBLOCK: s = "SIG_UNBLOCK"; break;
+ case SIG_SETMASK: s = "SIG_SETMASK"; break;
+ }
+ }
+
+ if (s == NULL)
+ prt_dec(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+const char *
+mmap_protect(private_t *pri, long arg)
+{
+ char *str = pri->code_buf;
+
+ if (arg & ~(PROT_READ|PROT_WRITE|PROT_EXEC))
+ return ((char *)NULL);
+
+ if (arg == PROT_NONE)
+ return ("PROT_NONE");
+
+ *str = '\0';
+ if (arg & PROT_READ)
+ (void) strlcat(str, "|PROT_READ", sizeof (pri->code_buf));
+ if (arg & PROT_WRITE)
+ (void) strlcat(str, "|PROT_WRITE", sizeof (pri->code_buf));
+ if (arg & PROT_EXEC)
+ (void) strlcat(str, "|PROT_EXEC", sizeof (pri->code_buf));
+ return ((const char *)(str + 1));
+}
+
+const char *
+mmap_type(private_t *pri, long arg)
+{
+ char *str = pri->code_buf;
+ size_t used;
+
+#define CBSIZE sizeof (pri->code_buf)
+ switch (arg & MAP_TYPE) {
+ case MAP_SHARED:
+ used = strlcpy(str, "MAP_SHARED", CBSIZE);
+ break;
+ case MAP_PRIVATE:
+ used = strlcpy(str, "MAP_PRIVATE", CBSIZE);
+ break;
+ default:
+ used = snprintf(str, CBSIZE, "%ld", arg&MAP_TYPE);
+ break;
+ }
+
+ arg &= ~(_MAP_NEW|MAP_TYPE);
+
+ if (arg & ~(MAP_FIXED|MAP_RENAME|MAP_NORESERVE|MAP_ANON|MAP_ALIGN|
+ MAP_TEXT|MAP_INITDATA|MAP_32BIT))
+ (void) snprintf(str + used, sizeof (pri->code_buf) - used,
+ "|0x%lX", arg);
+ else {
+ if (arg & MAP_FIXED)
+ (void) strlcat(str, "|MAP_FIXED", CBSIZE);
+ if (arg & MAP_RENAME)
+ (void) strlcat(str, "|MAP_RENAME", CBSIZE);
+ if (arg & MAP_NORESERVE)
+ (void) strlcat(str, "|MAP_NORESERVE", CBSIZE);
+ if (arg & MAP_ANON)
+ (void) strlcat(str, "|MAP_ANON", CBSIZE);
+ if (arg & MAP_ALIGN)
+ (void) strlcat(str, "|MAP_ALIGN", CBSIZE);
+ if (arg & MAP_TEXT)
+ (void) strlcat(str, "|MAP_TEXT", CBSIZE);
+ if (arg & MAP_INITDATA)
+ (void) strlcat(str, "|MAP_INITDATA", CBSIZE);
+ if (arg & MAP_32BIT)
+ (void) strlcat(str, "|MAP_32BIT", CBSIZE);
+ }
+
+ return ((const char *)str);
+#undef CBSIZE
+}
+
+void
+prt_mpr(private_t *pri, int raw, long val) /* print mmap()/mprotect() flags */
+{
+ const char *s = raw? NULL : mmap_protect(pri, val);
+
+ if (s == NULL)
+ prt_hhx(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+void
+prt_mty(private_t *pri, int raw, long val) /* print mmap() mapping type flags */
+{
+ const char *s = raw? NULL : mmap_type(pri, val);
+
+ if (s == NULL)
+ prt_hhx(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+void
+prt_mob(private_t *pri, int raw, long val) /* print mmapobj() flags */
+{
+ if (val == 0)
+ prt_dec(pri, 0, val);
+ else if (raw || (val & ~(MMOBJ_PADDING|MMOBJ_INTERPRET)) != 0)
+ prt_hhx(pri, 0, val);
+ else {
+#define CBSIZE sizeof (pri->code_buf)
+ char *s = pri->code_buf;
+
+ *s = '\0';
+ if (val & MMOBJ_PADDING)
+ (void) strlcat(s, "|MMOBJ_PADDING", CBSIZE);
+ if (val & MMOBJ_INTERPRET)
+ (void) strlcat(s, "|MMOBJ_INTERPRET", CBSIZE);
+ outstring(pri, s + 1);
+#undef CBSIZE
+ }
+}
+
+/*ARGSUSED*/
+void
+prt_mcf(private_t *pri, int raw, long val) /* print memcntl() function */
+{
+ const char *s = NULL;
+
+ if (!raw) {
+ switch (val) {
+ case MC_SYNC: s = "MC_SYNC"; break;
+ case MC_LOCK: s = "MC_LOCK"; break;
+ case MC_UNLOCK: s = "MC_UNLOCK"; break;
+ case MC_ADVISE: s = "MC_ADVISE"; break;
+ case MC_LOCKAS: s = "MC_LOCKAS"; break;
+ case MC_UNLOCKAS: s = "MC_UNLOCKAS"; break;
+ case MC_HAT_ADVISE: s = "MC_HAT_ADVISE"; break;
+ }
+ }
+
+ if (s == NULL)
+ prt_dec(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+void
+prt_mad(private_t *pri, int raw, long val) /* print madvise() argument */
+{
+ const char *s = NULL;
+
+ if (!raw) {
+ switch (val) {
+ case MADV_NORMAL: s = "MADV_NORMAL"; break;
+ case MADV_RANDOM: s = "MADV_RANDOM"; break;
+ case MADV_SEQUENTIAL: s = "MADV_SEQUENTIAL"; break;
+ case MADV_WILLNEED: s = "MADV_WILLNEED"; break;
+ case MADV_DONTNEED: s = "MADV_DONTNEED"; break;
+ case MADV_FREE: s = "MADV_FREE"; break;
+ case MADV_ACCESS_DEFAULT: s = "MADV_ACCESS_DEFAULT"; break;
+ case MADV_ACCESS_LWP: s = "MADV_ACCESS_LWP"; break;
+ case MADV_ACCESS_MANY: s = "MADV_ACCESS_MANY"; break;
+ }
+ }
+
+ if (s == NULL)
+ prt_dec(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+void
+prt_mc4(private_t *pri, int raw, long val) /* print memcntl() (4th) argument */
+{
+ if (val == 0)
+ prt_dec(pri, 0, val);
+ else if (raw)
+ prt_hhx(pri, 0, val);
+ else {
+ char *s = NULL;
+
+#define CBSIZE sizeof (pri->code_buf)
+ /* cheating -- look at memcntl func */
+ switch (pri->sys_args[2]) {
+ case MC_ADVISE:
+ prt_mad(pri, 0, val);
+ return;
+
+ case MC_SYNC:
+ if ((val & ~(MS_SYNC|MS_ASYNC|MS_INVALIDATE)) == 0) {
+ *(s = pri->code_buf) = '\0';
+ if (val & MS_SYNC)
+ (void) strlcat(s, "|MS_SYNC", CBSIZE);
+ if (val & MS_ASYNC)
+ (void) strlcat(s, "|MS_ASYNC", CBSIZE);
+ if (val & MS_INVALIDATE)
+ (void) strlcat(s, "|MS_INVALIDATE",
+ CBSIZE);
+ }
+ break;
+
+ case MC_LOCKAS:
+ case MC_UNLOCKAS:
+ if ((val & ~(MCL_CURRENT|MCL_FUTURE)) == 0) {
+ *(s = pri->code_buf) = '\0';
+ if (val & MCL_CURRENT)
+ (void) strlcat(s, "|MCL_CURRENT",
+ CBSIZE);
+ if (val & MCL_FUTURE)
+ (void) strlcat(s, "|MCL_FUTURE",
+ CBSIZE);
+ }
+ break;
+ }
+#undef CBSIZE
+
+ if (s == NULL || *s == '\0')
+ prt_hhx(pri, 0, val);
+ else
+ outstring(pri, ++s);
+ }
+}
+
+void
+prt_mc5(private_t *pri, int raw, long val) /* print memcntl() (5th) argument */
+{
+ char *s;
+
+#define CBSIZE sizeof (pri->code_buf)
+ if (val == 0)
+ prt_dec(pri, 0, val);
+ else if (raw || (val & ~VALID_ATTR))
+ prt_hhx(pri, 0, val);
+ else {
+ s = pri->code_buf;
+ *s = '\0';
+ if (val & SHARED)
+ (void) strlcat(s, "|SHARED", CBSIZE);
+ if (val & PRIVATE)
+ (void) strlcat(s, "|PRIVATE", CBSIZE);
+ if (val & PROT_READ)
+ (void) strlcat(s, "|PROT_READ", CBSIZE);
+ if (val & PROT_WRITE)
+ (void) strlcat(s, "|PROT_WRITE", CBSIZE);
+ if (val & PROT_EXEC)
+ (void) strlcat(s, "|PROT_EXEC", CBSIZE);
+ if (*s == '\0')
+ prt_hhx(pri, 0, val);
+ else
+ outstring(pri, ++s);
+ }
+#undef CBSIZE
+}
+
+void
+prt_ulm(private_t *pri, int raw, long val) /* print ulimit() argument */
+{
+ const char *s = NULL;
+
+ if (!raw) {
+ switch (val) {
+ case UL_GFILLIM: s = "UL_GFILLIM"; break;
+ case UL_SFILLIM: s = "UL_SFILLIM"; break;
+ case UL_GMEMLIM: s = "UL_GMEMLIM"; break;
+ case UL_GDESLIM: s = "UL_GDESLIM"; break;
+ }
+ }
+
+ if (s == NULL)
+ prt_dec(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+void
+prt_rlm(private_t *pri, int raw, long val) /* print get/setrlimit() argument */
+{
+ const char *s = NULL;
+
+ if (!raw) {
+ switch (val) {
+ case RLIMIT_CPU: s = "RLIMIT_CPU"; break;
+ case RLIMIT_FSIZE: s = "RLIMIT_FSIZE"; break;
+ case RLIMIT_DATA: s = "RLIMIT_DATA"; break;
+ case RLIMIT_STACK: s = "RLIMIT_STACK"; break;
+ case RLIMIT_CORE: s = "RLIMIT_CORE"; break;
+ case RLIMIT_NOFILE: s = "RLIMIT_NOFILE"; break;
+ case RLIMIT_VMEM: s = "RLIMIT_VMEM"; break;
+ }
+ }
+
+ if (s == NULL)
+ prt_dec(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+void
+prt_cnf(private_t *pri, int raw, long val) /* print sysconfig code */
+{
+ const char *s = raw? NULL : sconfname(val);
+
+ if (s == NULL)
+ prt_dec(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+void
+prt_inf(private_t *pri, int raw, long val) /* print sysinfo code */
+{
+ const char *s = NULL;
+
+ if (!raw) {
+ switch (val) {
+ case SI_SYSNAME: s = "SI_SYSNAME"; break;
+ case SI_HOSTNAME: s = "SI_HOSTNAME"; break;
+ case SI_RELEASE: s = "SI_RELEASE"; break;
+ case SI_VERSION: s = "SI_VERSION"; break;
+ case SI_MACHINE: s = "SI_MACHINE"; break;
+ case SI_ARCHITECTURE: s = "SI_ARCHITECTURE"; break;
+ case SI_ARCHITECTURE_32:s = "SI_ARCHITECTURE_32"; break;
+ case SI_ARCHITECTURE_64:s = "SI_ARCHITECTURE_64"; break;
+ case SI_ARCHITECTURE_K: s = "SI_ARCHITECTURE_K"; break;
+ case SI_HW_SERIAL: s = "SI_HW_SERIAL"; break;
+ case SI_HW_PROVIDER: s = "SI_HW_PROVIDER"; break;
+ case SI_SRPC_DOMAIN: s = "SI_SRPC_DOMAIN"; break;
+ case SI_SET_HOSTNAME: s = "SI_SET_HOSTNAME"; break;
+ case SI_SET_SRPC_DOMAIN: s = "SI_SET_SRPC_DOMAIN"; break;
+ case SI_PLATFORM: s = "SI_PLATFORM"; break;
+ case SI_ISALIST: s = "SI_ISALIST"; break;
+ case SI_DHCP_CACHE: s = "SI_DHCP_CACHE"; break;
+ }
+ }
+
+ if (s == NULL)
+ prt_dec(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+void
+prt_ptc(private_t *pri, int raw, long val) /* print pathconf code */
+{
+ const char *s = raw? NULL : pathconfname(val);
+
+ if (s == NULL)
+ prt_dec(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+void
+prt_fui(private_t *pri, int raw, long val) /* print fusers() input argument */
+{
+ const char *s = raw? NULL : fuiname(val);
+
+ if (s == NULL)
+ prt_hhx(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+void
+prt_lwf(private_t *pri, int raw, long val) /* print lwp_create() flags */
+{
+ char *s;
+
+ if (val == 0)
+ prt_dec(pri, 0, val);
+ else if (raw ||
+ (val & ~(LWP_DAEMON|LWP_DETACHED|LWP_SUSPENDED)))
+ prt_hhx(pri, 0, val);
+ else {
+#define CBSIZE sizeof (pri->code_buf)
+ s = pri->code_buf;
+ *s = '\0';
+ if (val & LWP_DAEMON)
+ (void) strlcat(s, "|LWP_DAEMON", CBSIZE);
+ if (val & LWP_DETACHED)
+ (void) strlcat(s, "|LWP_DETACHED", CBSIZE);
+ if (val & LWP_SUSPENDED)
+ (void) strlcat(s, "|LWP_SUSPENDED", CBSIZE);
+ outstring(pri, ++s);
+#undef CBSIZE
+ }
+}
+
+void
+prt_itm(private_t *pri, int raw, long val) /* print [get|set]itimer() arg */
+{
+ const char *s = NULL;
+
+ if (!raw) {
+ switch (val) {
+ case ITIMER_REAL: s = "ITIMER_REAL"; break;
+ case ITIMER_VIRTUAL: s = "ITIMER_VIRTUAL"; break;
+ case ITIMER_PROF: s = "ITIMER_PROF"; break;
+#ifdef ITIMER_REALPROF
+ case ITIMER_REALPROF: s = "ITIMER_REALPROF"; break;
+#endif
+ }
+ }
+
+ if (s == NULL)
+ prt_dec(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+void
+prt_mod(private_t *pri, int raw, long val) /* print modctl() code */
+{
+ const char *s = NULL;
+
+ if (!raw) {
+ switch (val) {
+ case MODLOAD: s = "MODLOAD"; break;
+ case MODUNLOAD: s = "MODUNLOAD"; break;
+ case MODINFO: s = "MODINFO"; break;
+ case MODRESERVED: s = "MODRESERVED"; break;
+ case MODSETMINIROOT: s = "MODSETMINIROOT"; break;
+ case MODADDMAJBIND: s = "MODADDMAJBIND"; break;
+ case MODGETPATH: s = "MODGETPATH"; break;
+ case MODGETPATHLEN: s = "MODGETPATHLEN"; break;
+ case MODREADSYSBIND: s = "MODREADSYSBIND"; break;
+ case MODGETMAJBIND: s = "MODGETMAJBIND"; break;
+ case MODGETNAME: s = "MODGETNAME"; break;
+ case MODSIZEOF_DEVID: s = "MODSIZEOF_DEVID"; break;
+ case MODGETDEVID: s = "MODGETDEVID"; break;
+ case MODSIZEOF_MINORNAME: s = "MODSIZEOF_MINORNAME"; break;
+ case MODGETMINORNAME: s = "MODGETMINORNAME"; break;
+ case MODGETFBNAME: s = "MODGETFBNAME"; break;
+ case MODEVENTS: s = "MODEVENTS"; break;
+ case MODREREADDACF: s = "MODREREADDACF"; break;
+ case MODLOADDRVCONF: s = "MODLOADDRVCONF"; break;
+ case MODUNLOADDRVCONF: s = "MODUNLOADDRVCONF"; break;
+ case MODREMMAJBIND: s = "MODREMMAJBIND"; break;
+ case MODDEVT2INSTANCE: s = "MODDEVT2INSTANCE"; break;
+ case MODGETDEVFSPATH_LEN: s = "MODGETDEVFSPATH_LEN"; break;
+ case MODGETDEVFSPATH: s = "MODGETDEVFSPATH"; break;
+ case MODDEVID2PATHS: s = "MODDEVID2PATHS"; break;
+ case MODSETDEVPOLICY: s = "MODSETDEVPOLICY"; break;
+ case MODGETDEVPOLICY: s = "MODGETDEVPOLICY"; break;
+ case MODALLOCPRIV: s = "MODALLOCPRIV"; break;
+ case MODGETDEVPOLICYBYNAME:
+ s = "MODGETDEVPOLICYBYNAME"; break;
+ case MODLOADMINORPERM: s = "MODLOADMINORPERM"; break;
+ case MODADDMINORPERM: s = "MODADDMINORPERM"; break;
+ case MODREMMINORPERM: s = "MODREMMINORPERM"; break;
+ case MODREMDRVCLEANUP: s = "MODREMDRVCLEANUP"; break;
+ case MODDEVEXISTS: s = "MODDEVEXISTS"; break;
+ case MODDEVREADDIR: s = "MODDEVREADDIR"; break;
+ case MODDEVEMPTYDIR: s = "MODDEVEMPTYDIR"; break;
+ case MODDEVNAME: s = "MODDEVNAME"; break;
+ case MODGETDEVFSPATH_MI_LEN:
+ s = "MODGETDEVFSPATH_MI_LEN"; break;
+ case MODGETDEVFSPATH_MI:
+ s = "MODGETDEVFSPATH_MI"; break;
+ case MODREMDRVALIAS: s = "MODREMDRVALIAS"; break;
+ case MODHPOPS: s = "MODHPOPS"; break;
+ }
+ }
+
+ if (s == NULL)
+ prt_dec(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+void
+prt_acl(private_t *pri, int raw, long val) /* print acl() code */
+{
+ const char *s = NULL;
+
+ if (!raw) {
+ switch (val) {
+ case GETACL: s = "GETACL"; break;
+ case SETACL: s = "SETACL"; break;
+ case GETACLCNT: s = "GETACLCNT"; break;
+ case ACE_GETACL: s = "ACE_GETACL"; break;
+ case ACE_SETACL: s = "ACE_SETACL"; break;
+ case ACE_GETACLCNT: s = "ACE_GETACLCNT"; break;
+ }
+ }
+
+ if (s == NULL)
+ prt_dec(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+void
+prt_aio(private_t *pri, int raw, long val) /* print kaio() code */
+{
+ const char *s = NULL;
+ char buf[32];
+
+ if (!raw) {
+ switch (val & ~AIO_POLL_BIT) {
+ case AIOREAD: s = "AIOREAD"; break;
+ case AIOWRITE: s = "AIOWRITE"; break;
+ case AIOWAIT: s = "AIOWAIT"; break;
+ case AIOCANCEL: s = "AIOCANCEL"; break;
+ case AIONOTIFY: s = "AIONOTIFY"; break;
+ case AIOINIT: s = "AIOINIT"; break;
+ case AIOSTART: s = "AIOSTART"; break;
+ case AIOLIO: s = "AIOLIO"; break;
+ case AIOSUSPEND: s = "AIOSUSPEND"; break;
+ case AIOERROR: s = "AIOERROR"; break;
+ case AIOLIOWAIT: s = "AIOLIOWAIT"; break;
+ case AIOAREAD: s = "AIOAREAD"; break;
+ case AIOAWRITE: s = "AIOAWRITE"; break;
+ /*
+ * We have to hardcode the values for the 64-bit versions of
+ * these calls, because <sys/aio.h> defines them to be identical
+ * when compiled 64-bit. If our target is 32-bit, we still need
+ * to decode them correctly.
+ */
+ case 13: s = "AIOLIO64"; break;
+ case 14: s = "AIOSUSPEND64"; break;
+ case 15: s = "AUIOERROR64"; break;
+ case 16: s = "AIOLIOWAIT64"; break;
+ case 17: s = "AIOAREAD64"; break;
+ case 18: s = "AIOAWRITE64"; break;
+ case 19: s = "AIOCANCEL64"; break;
+
+ /*
+ * AIOFSYNC doesn't correspond to a syscall.
+ */
+ case AIOWAITN: s = "AIOWAITN"; break;
+ }
+ if (s != NULL && (val & AIO_POLL_BIT)) {
+ (void) strlcpy(buf, s, sizeof (buf));
+ (void) strlcat(buf, "|AIO_POLL_BIT", sizeof (buf));
+ s = (const char *)buf;
+ }
+ }
+
+ if (s == NULL)
+ prt_dec(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+void
+prt_aud(private_t *pri, int raw, long val) /* print auditsys() code */
+{
+ const char *s = NULL;
+
+ if (!raw) {
+ switch (val) {
+ case BSM_GETAUID: s = "BSM_GETAUID"; break;
+ case BSM_SETAUID: s = "BSM_SETAUID"; break;
+ case BSM_GETAUDIT: s = "BSM_GETAUDIT"; break;
+ case BSM_SETAUDIT: s = "BSM_SETAUDIT"; break;
+ case BSM_AUDIT: s = "BSM_AUDIT"; break;
+ case BSM_AUDITCTL: s = "BSM_AUDITCTL"; break;
+ case BSM_GETAUDIT_ADDR: s = "BSM_GETAUDIT_ADDR"; break;
+ case BSM_SETAUDIT_ADDR: s = "BSM_SETAUDIT_ADDR"; break;
+ }
+ }
+
+ if (s == NULL)
+ prt_dec(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+void
+prt_cor(private_t *pri, int raw, long val) /* print corectl() subcode */
+{
+ const char *s = NULL;
+
+ if (!raw) {
+ switch (val) {
+ case CC_SET_OPTIONS:
+ s = "CC_SET_OPTIONS"; break;
+ case CC_GET_OPTIONS:
+ s = "CC_GET_OPTIONS"; break;
+ case CC_SET_GLOBAL_PATH:
+ s = "CC_SET_GLOBAL_PATH"; break;
+ case CC_GET_GLOBAL_PATH:
+ s = "CC_GET_GLOBAL_PATH"; break;
+ case CC_SET_PROCESS_PATH:
+ s = "CC_SET_PROCESS_PATH"; break;
+ case CC_GET_PROCESS_PATH:
+ s = "CC_GET_PROCESS_PATH"; break;
+ case CC_SET_GLOBAL_CONTENT:
+ s = "CC_SET_GLOBAL_CONTENT"; break;
+ case CC_GET_GLOBAL_CONTENT:
+ s = "CC_GET_GLOBAL_CONTENT"; break;
+ case CC_SET_PROCESS_CONTENT:
+ s = "CC_SET_PROCESS_CONTENT"; break;
+ case CC_GET_PROCESS_CONTENT:
+ s = "CC_GET_PROCESS_CONTENT"; break;
+ case CC_SET_DEFAULT_PATH:
+ s = "CC_SET_DEFAULT_PATH"; break;
+ case CC_GET_DEFAULT_PATH:
+ s = "CC_GET_DEFAULT_PATH"; break;
+ case CC_SET_DEFAULT_CONTENT:
+ s = "CC_SET_DEFAULT_CONTENT"; break;
+ case CC_GET_DEFAULT_CONTENT:
+ s = "CC_GET_DEFAULT_CONTENT"; break;
+ }
+ }
+
+ if (s == NULL)
+ prt_dec(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+void
+prt_cco(private_t *pri, int raw, long val) /* print corectl() options */
+{
+ char *s;
+
+ if (val == 0)
+ prt_dec(pri, 0, val);
+ else if (raw || (val & ~CC_OPTIONS))
+ prt_hhx(pri, 0, val);
+ else {
+#define CBSIZE sizeof (pri->code_buf)
+ s = pri->code_buf;
+ *s = '\0';
+ if (val & CC_GLOBAL_PATH)
+ (void) strlcat(s, "|CC_GLOBAL_PATH", CBSIZE);
+ if (val & CC_PROCESS_PATH)
+ (void) strlcat(s, "|CC_PROCESS_PATH", CBSIZE);
+ if (val & CC_GLOBAL_SETID)
+ (void) strlcat(s, "|CC_GLOBAL_SETID", CBSIZE);
+ if (val & CC_PROCESS_SETID)
+ (void) strlcat(s, "|CC_PROCESS_SETID", CBSIZE);
+ if (val & CC_GLOBAL_LOG)
+ (void) strlcat(s, "|CC_GLOBAL_LOG", CBSIZE);
+ if (*s == '\0')
+ prt_hhx(pri, 0, val);
+ else
+ outstring(pri, ++s);
+#undef CBSIZE
+ }
+}
+
+void
+prt_ccc(private_t *pri, int raw, long val) /* print corectl() content */
+{
+ core_content_t ccc;
+
+ if (Pread(Proc, &ccc, sizeof (ccc), val) != sizeof (ccc))
+ prt_hex(pri, 0, val);
+ else if (!raw && proc_content2str(ccc, pri->code_buf,
+ sizeof (pri->code_buf)) >= 0)
+ outstring(pri, pri->code_buf);
+ else
+ prt_hhx(pri, 0, (long)ccc);
+}
+
+void
+prt_rcc(private_t *pri, int raw, long val) /* print corectl() ret. cont. */
+{
+ core_content_t ccc;
+
+ if (pri->Errno || Pread(Proc, &ccc, sizeof (ccc), val) != sizeof (ccc))
+ prt_hex(pri, 0, val);
+ else if (!raw && proc_content2str(ccc, pri->code_buf,
+ sizeof (pri->code_buf)) >= 0)
+ outstring(pri, pri->code_buf);
+ else
+ prt_hhx(pri, 0, (long)ccc);
+}
+
+void
+prt_cpc(private_t *pri, int raw, long val) /* print cpc() subcode */
+{
+ const char *s = NULL;
+
+ if (!raw) {
+ switch (val) {
+ case CPC_BIND: s = "CPC_BIND"; break;
+ case CPC_SAMPLE: s = "CPC_SAMPLE"; break;
+ case CPC_INVALIDATE: s = "CPC_INVALIDATE"; break;
+ case CPC_RELE: s = "CPC_RELE"; break;
+ case CPC_EVLIST_SIZE: s = "CPC_EVLIST_SIZE"; break;
+ case CPC_LIST_EVENTS: s = "CPC_LIST_EVENTS"; break;
+ case CPC_ATTRLIST_SIZE: s = "CPC_ATTRLIST_SIZE"; break;
+ case CPC_LIST_ATTRS: s = "CPC_LIST_ATTRS"; break;
+ case CPC_IMPL_NAME: s = "CPC_IMPL_NAME"; break;
+ case CPC_CPUREF: s = "CPC_CPUREF"; break;
+ case CPC_USR_EVENTS: s = "CPC_USR_EVENTS"; break;
+ case CPC_SYS_EVENTS: s = "CPC_SYS_EVENTS"; break;
+ case CPC_NPIC: s = "CPC_NPIC"; break;
+ case CPC_CAPS: s = "CPC_CAPS"; break;
+ case CPC_ENABLE: s = "CPC_ENABLE"; break;
+ case CPC_DISABLE: s = "CPC_DISABLE"; break;
+ }
+ }
+
+ if (s == NULL)
+ prt_dec(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+void
+outstring(private_t *pri, const char *s)
+{
+ int len = strlen(s);
+
+ GROW(len);
+ (void) strcpy(pri->sys_string + pri->sys_leng, s);
+ pri->sys_leng += len;
+}
+
+void
+grow(private_t *pri, int nbyte) /* reallocate format buffer if necessary */
+{
+ while (pri->sys_leng + nbyte >= pri->sys_ssize)
+ pri->sys_string = my_realloc(pri->sys_string,
+ pri->sys_ssize *= 2, "format buffer");
+}
+
+void
+prt_clc(private_t *pri, int raw, long val)
+{
+ const char *s = NULL;
+
+ if (!raw) {
+ switch (val) {
+ case CL_INITIALIZE: s = "CL_INITIALIZE"; break;
+ case CL_CONFIG: s = "CL_CONFIG"; break;
+ }
+ }
+
+ if (s == NULL)
+ prt_dec(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+void
+prt_clf(private_t *pri, int raw, long val)
+{
+ const char *s = NULL;
+
+ if (!raw) {
+ switch (pri->sys_args[0]) {
+ case CL_CONFIG:
+ switch (pri->sys_args[1]) {
+ case CL_NODEID:
+ s = "CL_NODEID"; break;
+ case CL_HIGHEST_NODEID:
+ s = "CL_HIGHEST_NODEID"; break;
+ }
+ break;
+ case CL_INITIALIZE:
+ switch (pri->sys_args[1]) {
+ case CL_GET_BOOTFLAG:
+ s = "CL_GET_BOOTFLAG"; break;
+ }
+ break;
+ }
+ }
+
+ if (s == NULL)
+ prt_dec(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+void
+prt_sqc(private_t *pri, int raw, long val) /* print sigqueue() si_code */
+{
+ const char *s = NULL;
+
+ if (!raw) {
+ switch ((int)val) {
+ case SI_QUEUE: s = "SI_QUEUE"; break;
+ case SI_TIMER: s = "SI_TIMER"; break;
+ case SI_ASYNCIO: s = "SI_ASYNCIO"; break;
+ case SI_MESGQ: s = "SI_MESGQ"; break;
+ }
+ }
+
+ if (s == NULL)
+ prt_dec(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+/*
+ * print priocntlsys() (key, value) pair key.
+ */
+void
+print_pck(private_t *pri, int raw, long val)
+{
+ const char *s = NULL;
+ char clname[PC_CLNMSZ];
+
+ if ((pri->sys_args[2] != PC_GETXPARMS &&
+ pri->sys_args[2] != PC_SETXPARMS) || val == 0 || raw) {
+ prt_dec(pri, 0, val);
+ return;
+ }
+
+ if (pri->sys_args[3] == NULL) {
+ if (val == PC_KY_CLNAME) {
+ s = "PC_KY_CLNAME";
+ outstring(pri, s);
+ } else
+ prt_dec(pri, 0, val);
+ return;
+ }
+
+ if (Pread(Proc, &clname, PC_CLNMSZ, pri->sys_args[3]) != PC_CLNMSZ) {
+ prt_dec(pri, 0, val);
+ return;
+ }
+
+ if (strcmp(clname, "TS") == 0) {
+ switch (val) {
+ case TS_KY_UPRILIM: s = "TS_KY_UPRILIM"; break;
+ case TS_KY_UPRI: s = "TS_KY_UPRI"; break;
+ default: break;
+ }
+ } else if (strcmp(clname, "IA") == 0) {
+ switch (val) {
+ case IA_KY_UPRILIM: s = "IA_KY_UPRILIM"; break;
+ case IA_KY_UPRI: s = "IA_KY_UPRI"; break;
+ case IA_KY_MODE: s = "IA_KY_MODE"; break;
+ default: break;
+ }
+ } else if (strcmp(clname, "RT") == 0) {
+ switch (val) {
+ case RT_KY_PRI: s = "RT_KY_PRI"; break;
+ case RT_KY_TQSECS: s = "RT_KY_TQSECS"; break;
+ case RT_KY_TQNSECS: s = "RT_KY_TQNSECS"; break;
+ case RT_KY_TQSIG: s = "RT_KY_TQSIG"; break;
+ default: break;
+ }
+ } else if (strcmp(clname, "FSS") == 0) {
+ switch (val) {
+ case FSS_KY_UPRILIM: s = "FSS_KY_UPRILIM"; break;
+ case FSS_KY_UPRI: s = "FSS_KY_UPRI"; break;
+ default: break;
+ }
+ } else if (strcmp(clname, "FX") == 0) {
+ switch (val) {
+ case FX_KY_UPRILIM: s = "FX_KY_UPRILIM"; break;
+ case FX_KY_UPRI: s = "FX_KY_UPRI"; break;
+ case FX_KY_TQSECS: s = "FX_KY_TQSECS"; break;
+ case FX_KY_TQNSECS: s = "FX_KY_TQNSECS"; break;
+ default: break;
+ }
+ }
+
+ if (s == NULL)
+ prt_dec(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+/*
+ * print priocntlsys() fourth argument.
+ */
+/*ARGSUSED*/
+void
+prt_pc4(private_t *pri, int raw, long val)
+{
+ /* look at pricntlsys function */
+ if ((pri->sys_args[2] != PC_GETXPARMS &&
+ pri->sys_args[2] != PC_SETXPARMS))
+ prt_hex(pri, 0, val);
+ else if (val)
+ prt_stg(pri, 0, val);
+ else
+ prt_dec(pri, 0, val);
+}
+
+/*
+ * print priocntlsys() (key, value) pairs (5th argument).
+ */
+/*ARGSUSED*/
+void
+prt_pc5(private_t *pri, int raw, long val)
+{
+ pc_vaparms_t prms;
+ pc_vaparm_t *vpp = &prms.pc_parms[0];
+ uint_t cnt;
+
+
+ /* look at pricntlsys function */
+ if ((pri->sys_args[2] != PC_GETXPARMS &&
+ pri->sys_args[2] != PC_SETXPARMS) || val == 0) {
+ prt_dec(pri, 0, 0);
+ return;
+ }
+
+ if (Pread(Proc, &prms, sizeof (prms), val) != sizeof (prms)) {
+ prt_hex(pri, 0, val);
+ return;
+ }
+
+ if ((cnt = prms.pc_vaparmscnt) > PC_VAPARMCNT)
+ return;
+
+ for (; cnt--; vpp++) {
+ print_pck(pri, 0, vpp->pc_key);
+ outstring(pri, ", ");
+ prt_hex(pri, 0, (long)vpp->pc_parm);
+ outstring(pri, ", ");
+ }
+
+ prt_dec(pri, 0, PC_KY_NULL);
+}
+
+/*
+ * Print processor set id, including logical expansion of "special" ids.
+ */
+void
+prt_pst(private_t *pri, int raw, long val)
+{
+ const char *s = NULL;
+
+ if (!raw) {
+ switch ((psetid_t)val) {
+ case PS_NONE: s = "PS_NONE"; break;
+ case PS_QUERY: s = "PS_QUERY"; break;
+ case PS_MYID: s = "PS_MYID"; break;
+ }
+ }
+
+ if (s == NULL)
+ prt_dec(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+/*
+ * Print meminfo() argument.
+ */
+/*ARGSUSED*/
+void
+prt_mif(private_t *pri, int raw, long val)
+{
+ struct meminfo minfo;
+
+#ifdef _LP64
+ if (data_model == PR_MODEL_ILP32) {
+ struct meminfo32 minfo32;
+
+ if (Pread(Proc, &minfo32, sizeof (struct meminfo32), val) !=
+ sizeof (struct meminfo32)) {
+ prt_dec(pri, 0, pri->sys_args[1]); /* addr_count */
+ outstring(pri, ", ");
+ prt_hex(pri, 0, val);
+ return;
+ }
+ /*
+ * arrange the arguments in the order that user calls with
+ */
+ prt_hex(pri, 0, minfo32.mi_inaddr);
+ outstring(pri, ", ");
+ prt_dec(pri, 0, pri->sys_args[1]); /* addr_count */
+ outstring(pri, ", ");
+ prt_hex(pri, 0, minfo32.mi_info_req);
+ outstring(pri, ", ");
+ prt_dec(pri, 0, minfo32.mi_info_count);
+ outstring(pri, ", ");
+ prt_hex(pri, 0, minfo32.mi_outdata);
+ outstring(pri, ", ");
+ prt_hex(pri, 0, minfo32.mi_validity);
+ return;
+ }
+#endif
+ if (Pread(Proc, &minfo, sizeof (struct meminfo), val) !=
+ sizeof (struct meminfo)) {
+ prt_dec(pri, 0, pri->sys_args[1]); /* addr_count */
+ outstring(pri, ", ");
+ prt_hex(pri, 0, val);
+ return;
+ }
+ /*
+ * arrange the arguments in the order that user calls with
+ */
+ prt_hex(pri, 0, (long)minfo.mi_inaddr);
+ outstring(pri, ", ");
+ prt_dec(pri, 0, pri->sys_args[1]); /* addr_count */
+ outstring(pri, ", ");
+ prt_hex(pri, 0, (long)minfo.mi_info_req);
+ outstring(pri, ", ");
+ prt_dec(pri, 0, minfo.mi_info_count);
+ outstring(pri, ", ");
+ prt_hex(pri, 0, (long)minfo.mi_outdata);
+ outstring(pri, ", ");
+ prt_hex(pri, 0, (long)minfo.mi_validity);
+}
+
+
+/*
+ * Print so_socket() 1st argument.
+ */
+/*ARGSUSED*/
+void
+prt_pfm(private_t *pri, int raw, long val)
+{
+ /* Protocol Families have same names as Address Families */
+ if ((ulong_t)val < MAX_AFCODES) {
+ outstring(pri, "PF_");
+ outstring(pri, afcodes[val]);
+ } else {
+ prt_dec(pri, 0, val);
+ }
+}
+
+/*
+ * Print sockconfig() subcode.
+ */
+/*ARGSUSED*/
+void
+prt_skc(private_t *pri, int raw, long val)
+{
+ const char *s = NULL;
+
+ if (!raw) {
+ switch (val) {
+ case SOCKCONFIG_ADD_SOCK:
+ s = "SOCKCONFIG_ADD_SOCK"; break;
+ case SOCKCONFIG_REMOVE_SOCK:
+ s = "SOCKCONFIG_REMOVE_SOCK"; break;
+ case SOCKCONFIG_ADD_FILTER:
+ s = "SOCKCONFIG_ADD_FILTER"; break;
+ case SOCKCONFIG_REMOVE_FILTER:
+ s = "SOCKCONFIG_REMOVE_FILTER"; break;
+ }
+ }
+ if (s == NULL)
+ prt_dec(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+/*
+ * Print so_socket() 2nd argument.
+ */
+/*ARGSUSED*/
+void
+prt_skt(private_t *pri, int raw, long val)
+{
+ const char *s;
+ long type = val & SOCK_TYPE_MASK;
+
+ if ((ulong_t)type <= MAX_SOCKTYPES &&
+ (s = socktype_codes[type]) != NULL) {
+ outstring(pri, s);
+ if ((val & SOCK_CLOEXEC) != 0) {
+ outstring(pri, "|SOCK_CLOEXEC");
+ }
+ } else {
+ prt_dec(pri, 0, val);
+ }
+}
+
+
+/*
+ * Print so_socket() 3rd argument.
+ */
+/*ARGSUSED*/
+void
+prt_skp(private_t *pri, int raw, long val)
+{
+ const char *s;
+
+ /* cheating -- look at the protocol-family */
+ switch (pri->sys_args[0]) {
+ case PF_INET6:
+ case PF_INET:
+ case PF_NCA: if ((s = ipprotos((int)val)) != NULL) {
+ outstring(pri, s);
+ break;
+ }
+ /* FALLTHROUGH */
+ default: prt_dec(pri, 0, val);
+ break;
+ }
+}
+
+
+/*
+ * Print so_socket() 5th argument.
+ */
+/*ARGSUSED*/
+void
+prt_skv(private_t *pri, int raw, long val)
+{
+ switch (val) {
+ case SOV_STREAM: outstring(pri, "SOV_STREAM"); break;
+ case SOV_DEFAULT: outstring(pri, "SOV_DEFAULT"); break;
+ case SOV_SOCKSTREAM: outstring(pri, "SOV_SOCKSTREAM"); break;
+ case SOV_SOCKBSD: outstring(pri, "SOV_SOCKBSD"); break;
+ case SOV_XPG4_2: outstring(pri, "SOV_XPG4_2"); break;
+ default: prt_dec(pri, 0, val); break;
+ }
+}
+
+/*
+ * Print accept4() flags argument.
+ */
+void
+prt_acf(private_t *pri, int raw, long val)
+{
+ int first = 1;
+ if (raw || !val ||
+ (val & ~(SOCK_CLOEXEC|SOCK_NDELAY|SOCK_NONBLOCK))) {
+ prt_dex(pri, 0, val);
+ return;
+ }
+
+ if (val & SOCK_CLOEXEC) {
+ outstring(pri, "|SOCK_CLOEXEC" + first);
+ first = 0;
+ }
+ if (val & SOCK_NDELAY) {
+ outstring(pri, "|SOCK_NDELAY" + first);
+ first = 0;
+ }
+ if (val & SOCK_NONBLOCK) {
+ outstring(pri, "|SOCK_NONBLOCK" + first);
+ }
+}
+
+
+/*
+ * Print setsockopt()/getsockopt() 2nd argument.
+ */
+/*ARGSUSED*/
+void
+prt_sol(private_t *pri, int raw, long val)
+{
+ if (val == SOL_SOCKET) {
+ outstring(pri, "SOL_SOCKET");
+ } else if (val == SOL_ROUTE) {
+ outstring(pri, "SOL_ROUTE");
+ } else {
+ const struct protoent *p;
+ struct protoent res;
+ char buf[NSS_BUFLEN_PROTOCOLS];
+
+ if ((p = getprotobynumber_r(val, &res,
+ (char *)buf, sizeof (buf))) != NULL)
+ outstring(pri, p->p_name);
+ else
+ prt_dec(pri, 0, val);
+ }
+}
+
+
+const char *
+sol_optname(private_t *pri, long val)
+{
+#define CBSIZE sizeof (pri->code_buf)
+ if (val >= SO_SNDBUF) {
+ switch (val) {
+ case SO_SNDBUF: return ("SO_SNDBUF");
+ case SO_RCVBUF: return ("SO_RCVBUF");
+ case SO_SNDLOWAT: return ("SO_SNDLOWAT");
+ case SO_RCVLOWAT: return ("SO_RCVLOWAT");
+ case SO_SNDTIMEO: return ("SO_SNDTIMEO");
+ case SO_RCVTIMEO: return ("SO_RCVTIMEO");
+ case SO_ERROR: return ("SO_ERROR");
+ case SO_TYPE: return ("SO_TYPE");
+ case SO_PROTOTYPE: return ("SO_PROTOTYPE");
+ case SO_ANON_MLP: return ("SO_ANON_MLP");
+ case SO_MAC_EXEMPT: return ("SO_MAC_EXEMPT");
+ case SO_ALLZONES: return ("SO_ALLZONES");
+ case SO_MAC_IMPLICIT: return ("SO_MAC_IMPLICIT");
+ case SO_VRRP: return ("SO_VRRP");
+ case SO_EXCLBIND: return ("SO_EXCLBIND");
+ case SO_DOMAIN: return ("SO_DOMAIN");
+
+ default: (void) snprintf(pri->code_buf, CBSIZE,
+ "0x%lx", val);
+ return (pri->code_buf);
+ }
+ } else {
+ char *s = pri->code_buf;
+ size_t used = 1;
+ long val2;
+
+ *s = '\0';
+ val2 = val & ~(SO_DEBUG|SO_ACCEPTCONN|SO_REUSEADDR|SO_KEEPALIVE|
+ SO_DONTROUTE|SO_BROADCAST|SO_USELOOPBACK|SO_LINGER|
+ SO_OOBINLINE|SO_DGRAM_ERRIND|SO_RECVUCRED);
+ if (val2)
+ used = snprintf(s, CBSIZE, "|0x%lx", val2);
+ if (val & SO_DEBUG)
+ used = strlcat(s, "|SO_DEBUG", CBSIZE);
+ if (val & SO_ACCEPTCONN)
+ used = strlcat(s, "|SO_ACCEPTCONN", CBSIZE);
+ if (val & SO_REUSEADDR)
+ used = strlcat(s, "|SO_REUSEADDR", CBSIZE);
+ if (val & SO_KEEPALIVE)
+ used = strlcat(s, "|SO_KEEPALIVE", CBSIZE);
+ if (val & SO_DONTROUTE)
+ used = strlcat(s, "|SO_DONTROUTE", CBSIZE);
+ if (val & SO_BROADCAST)
+ used = strlcat(s, "|SO_BROADCAST", CBSIZE);
+ if (val & SO_USELOOPBACK)
+ used = strlcat(s, "|SO_USELOOPBACK", CBSIZE);
+ if (val & SO_LINGER)
+ used = strlcat(s, "|SO_LINGER", CBSIZE);
+ if (val & SO_OOBINLINE)
+ used = strlcat(s, "|SO_OOBINLINE", CBSIZE);
+ if (val & SO_DGRAM_ERRIND)
+ used = strlcat(s, "|SO_DGRAM_ERRIND", CBSIZE);
+ if (val & SO_RECVUCRED)
+ used = strlcat(s, "|SO_RECVUCRED", CBSIZE);
+ if (used >= CBSIZE || val == 0)
+ (void) snprintf(s + 1, CBSIZE-1, "0x%lx", val);
+ return ((const char *)(s + 1));
+ }
+#undef CBSIZE
+}
+
+const char *
+route_optname(private_t *pri, long val)
+{
+ switch (val) {
+ case RT_AWARE:
+ return ("RT_AWARE");
+ default:
+ (void) snprintf(pri->code_buf, sizeof (pri->code_buf),
+ "0x%lx", val);
+ return (pri->code_buf);
+ }
+}
+
+const char *
+tcp_optname(private_t *pri, long val)
+{
+ switch (val) {
+ case TCP_NODELAY: return ("TCP_NODELAY");
+ case TCP_MAXSEG: return ("TCP_MAXSEG");
+ case TCP_KEEPALIVE: return ("TCP_KEEPALIVE");
+ case TCP_NOTIFY_THRESHOLD: return ("TCP_NOTIFY_THRESHOLD");
+ case TCP_ABORT_THRESHOLD: return ("TCP_ABORT_THRESHOLD");
+ case TCP_CONN_NOTIFY_THRESHOLD: return ("TCP_CONN_NOTIFY_THRESHOLD");
+ case TCP_CONN_ABORT_THRESHOLD: return ("TCP_CONN_ABORT_THRESHOLD");
+ case TCP_RECVDSTADDR: return ("TCP_RECVDSTADDR");
+ case TCP_ANONPRIVBIND: return ("TCP_ANONPRIVBIND");
+ case TCP_EXCLBIND: return ("TCP_EXCLBIND");
+ case TCP_INIT_CWND: return ("TCP_INIT_CWND");
+ case TCP_KEEPALIVE_THRESHOLD: return ("TCP_KEEPALIVE_THRESHOLD");
+ case TCP_KEEPALIVE_ABORT_THRESHOLD:
+ return ("TCP_KEEPALIVE_ABORT_THRESHOLD");
+ case TCP_CORK: return ("TCP_CORK");
+ case TCP_RTO_INITIAL: return ("TCP_RTO_INITIAL");
+ case TCP_RTO_MIN: return ("TCP_RTO_MIN");
+ case TCP_RTO_MAX: return ("TCP_RTO_MAX");
+ case TCP_LINGER2: return ("TCP_LINGER2");
+
+ default: (void) snprintf(pri->code_buf,
+ sizeof (pri->code_buf),
+ "0x%lx", val);
+ return (pri->code_buf);
+ }
+}
+
+
+const char *
+sctp_optname(private_t *pri, long val)
+{
+ switch (val) {
+ case SCTP_RTOINFO: return ("SCTP_RTOINFO");
+ case SCTP_ASSOCINFO: return ("SCTP_ASSOCINFO");
+ case SCTP_INITMSG: return ("SCTP_INITMSG");
+ case SCTP_NODELAY: return ("SCTP_NODELAY");
+ case SCTP_AUTOCLOSE: return ("SCTP_AUTOCLOSE");
+ case SCTP_SET_PEER_PRIMARY_ADDR:
+ return ("SCTP_SET_PEER_PRIMARY_ADDR");
+ case SCTP_PRIMARY_ADDR: return ("SCTP_PRIMARY_ADDR");
+ case SCTP_ADAPTATION_LAYER: return ("SCTP_ADAPTATION_LAYER");
+ case SCTP_DISABLE_FRAGMENTS: return ("SCTP_DISABLE_FRAGMENTS");
+ case SCTP_PEER_ADDR_PARAMS: return ("SCTP_PEER_ADDR_PARAMS");
+ case SCTP_DEFAULT_SEND_PARAM: return ("SCTP_DEFAULT_SEND_PARAM");
+ case SCTP_EVENTS: return ("SCTP_EVENTS");
+ case SCTP_I_WANT_MAPPED_V4_ADDR:
+ return ("SCTP_I_WANT_MAPPED_V4_ADDR");
+ case SCTP_MAXSEG: return ("SCTP_MAXSEG");
+ case SCTP_STATUS: return ("SCTP_STATUS");
+ case SCTP_GET_PEER_ADDR_INFO: return ("SCTP_GET_PEER_ADDR_INFO");
+
+ case SCTP_ADD_ADDR: return ("SCTP_ADD_ADDR");
+ case SCTP_REM_ADDR: return ("SCTP_REM_ADDR");
+
+ default: (void) snprintf(pri->code_buf,
+ sizeof (pri->code_buf),
+ "0x%lx", val);
+ return (pri->code_buf);
+ }
+}
+
+
+const char *
+udp_optname(private_t *pri, long val)
+{
+ switch (val) {
+ case UDP_CHECKSUM: return ("UDP_CHECKSUM");
+ case UDP_ANONPRIVBIND: return ("UDP_ANONPRIVBIND");
+ case UDP_EXCLBIND: return ("UDP_EXCLBIND");
+ case UDP_RCVHDR: return ("UDP_RCVHDR");
+ case UDP_NAT_T_ENDPOINT: return ("UDP_NAT_T_ENDPOINT");
+
+ default: (void) snprintf(pri->code_buf,
+ sizeof (pri->code_buf), "0x%lx",
+ val);
+ return (pri->code_buf);
+ }
+}
+
+
+/*
+ * Print setsockopt()/getsockopt() 3rd argument.
+ */
+/*ARGSUSED*/
+void
+prt_son(private_t *pri, int raw, long val)
+{
+ /* cheating -- look at the level */
+ switch (pri->sys_args[1]) {
+ case SOL_SOCKET: outstring(pri, sol_optname(pri, val));
+ break;
+ case SOL_ROUTE: outstring(pri, route_optname(pri, val));
+ break;
+ case IPPROTO_TCP: outstring(pri, tcp_optname(pri, val));
+ break;
+ case IPPROTO_UDP: outstring(pri, udp_optname(pri, val));
+ break;
+ case IPPROTO_SCTP: outstring(pri, sctp_optname(pri, val));
+ break;
+ default: prt_dec(pri, 0, val);
+ break;
+ }
+}
+
+
+/*
+ * Print utrap type
+ */
+/*ARGSUSED*/
+void
+prt_utt(private_t *pri, int raw, long val)
+{
+ const char *s = NULL;
+
+#ifdef __sparc
+ if (!raw) {
+ switch (val) {
+ case UT_INSTRUCTION_DISABLED:
+ s = "UT_INSTRUCTION_DISABLED"; break;
+ case UT_INSTRUCTION_ERROR:
+ s = "UT_INSTRUCTION_ERROR"; break;
+ case UT_INSTRUCTION_PROTECTION:
+ s = "UT_INSTRUCTION_PROTECTION"; break;
+ case UT_ILLTRAP_INSTRUCTION:
+ s = "UT_ILLTRAP_INSTRUCTION"; break;
+ case UT_ILLEGAL_INSTRUCTION:
+ s = "UT_ILLEGAL_INSTRUCTION"; break;
+ case UT_PRIVILEGED_OPCODE:
+ s = "UT_PRIVILEGED_OPCODE"; break;
+ case UT_FP_DISABLED:
+ s = "UT_FP_DISABLED"; break;
+ case UT_FP_EXCEPTION_IEEE_754:
+ s = "UT_FP_EXCEPTION_IEEE_754"; break;
+ case UT_FP_EXCEPTION_OTHER:
+ s = "UT_FP_EXCEPTION_OTHER"; break;
+ case UT_TAG_OVERFLOW:
+ s = "UT_TAG_OVERFLOW"; break;
+ case UT_DIVISION_BY_ZERO:
+ s = "UT_DIVISION_BY_ZERO"; break;
+ case UT_DATA_EXCEPTION:
+ s = "UT_DATA_EXCEPTION"; break;
+ case UT_DATA_ERROR:
+ s = "UT_DATA_ERROR"; break;
+ case UT_DATA_PROTECTION:
+ s = "UT_DATA_PROTECTION"; break;
+ case UT_MEM_ADDRESS_NOT_ALIGNED:
+ s = "UT_MEM_ADDRESS_NOT_ALIGNED"; break;
+ case UT_PRIVILEGED_ACTION:
+ s = "UT_PRIVILEGED_ACTION"; break;
+ case UT_ASYNC_DATA_ERROR:
+ s = "UT_ASYNC_DATA_ERROR"; break;
+ case UT_TRAP_INSTRUCTION_16:
+ s = "UT_TRAP_INSTRUCTION_16"; break;
+ case UT_TRAP_INSTRUCTION_17:
+ s = "UT_TRAP_INSTRUCTION_17"; break;
+ case UT_TRAP_INSTRUCTION_18:
+ s = "UT_TRAP_INSTRUCTION_18"; break;
+ case UT_TRAP_INSTRUCTION_19:
+ s = "UT_TRAP_INSTRUCTION_19"; break;
+ case UT_TRAP_INSTRUCTION_20:
+ s = "UT_TRAP_INSTRUCTION_20"; break;
+ case UT_TRAP_INSTRUCTION_21:
+ s = "UT_TRAP_INSTRUCTION_21"; break;
+ case UT_TRAP_INSTRUCTION_22:
+ s = "UT_TRAP_INSTRUCTION_22"; break;
+ case UT_TRAP_INSTRUCTION_23:
+ s = "UT_TRAP_INSTRUCTION_23"; break;
+ case UT_TRAP_INSTRUCTION_24:
+ s = "UT_TRAP_INSTRUCTION_24"; break;
+ case UT_TRAP_INSTRUCTION_25:
+ s = "UT_TRAP_INSTRUCTION_25"; break;
+ case UT_TRAP_INSTRUCTION_26:
+ s = "UT_TRAP_INSTRUCTION_26"; break;
+ case UT_TRAP_INSTRUCTION_27:
+ s = "UT_TRAP_INSTRUCTION_27"; break;
+ case UT_TRAP_INSTRUCTION_28:
+ s = "UT_TRAP_INSTRUCTION_28"; break;
+ case UT_TRAP_INSTRUCTION_29:
+ s = "UT_TRAP_INSTRUCTION_29"; break;
+ case UT_TRAP_INSTRUCTION_30:
+ s = "UT_TRAP_INSTRUCTION_30"; break;
+ case UT_TRAP_INSTRUCTION_31:
+ s = "UT_TRAP_INSTRUCTION_31"; break;
+ }
+ }
+#endif /* __sparc */
+
+ if (s == NULL)
+ prt_dec(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+
+/*
+ * Print utrap handler
+ */
+void
+prt_uth(private_t *pri, int raw, long val)
+{
+ const char *s = NULL;
+
+ if (!raw) {
+ switch (val) {
+ case (long)UTH_NOCHANGE: s = "UTH_NOCHANGE"; break;
+ }
+ }
+
+ if (s == NULL)
+ prt_hex(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+const char *
+access_flags(private_t *pri, long arg)
+{
+#define E_OK 010
+ char *str = pri->code_buf;
+
+ if (arg & ~(R_OK|W_OK|X_OK|E_OK))
+ return (NULL);
+
+ /* NB: F_OK == 0 */
+ if (arg == F_OK)
+ return ("F_OK");
+ if (arg == E_OK)
+ return ("F_OK|E_OK");
+
+ *str = '\0';
+ if (arg & R_OK)
+ (void) strlcat(str, "|R_OK", sizeof (pri->code_buf));
+ if (arg & W_OK)
+ (void) strlcat(str, "|W_OK", sizeof (pri->code_buf));
+ if (arg & X_OK)
+ (void) strlcat(str, "|X_OK", sizeof (pri->code_buf));
+ if (arg & E_OK)
+ (void) strlcat(str, "|E_OK", sizeof (pri->code_buf));
+ return ((const char *)(str + 1));
+#undef E_OK
+}
+
+/*
+ * Print access() flags.
+ */
+void
+prt_acc(private_t *pri, int raw, long val)
+{
+ const char *s = raw? NULL : access_flags(pri, val);
+
+ if (s == NULL)
+ prt_dex(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+/*
+ * Print shutdown() "how" (2nd) argument
+ */
+void
+prt_sht(private_t *pri, int raw, long val)
+{
+ if (raw) {
+ prt_dex(pri, 0, val);
+ return;
+ }
+ switch (val) {
+ case SHUT_RD: outstring(pri, "SHUT_RD"); break;
+ case SHUT_WR: outstring(pri, "SHUT_WR"); break;
+ case SHUT_RDWR: outstring(pri, "SHUT_RDWR"); break;
+ default: prt_dec(pri, 0, val); break;
+ }
+}
+
+/*
+ * Print fcntl() F_SETFL flags (3rd) argument or fdsync flag (2nd arg)
+ */
+static struct fcntl_flags {
+ long val;
+ const char *name;
+} fcntl_flags[] = {
+#define FC_FL(flag) { (long)flag, "|" # flag }
+ FC_FL(FREVOKED),
+ FC_FL(FREAD),
+ FC_FL(FWRITE),
+ FC_FL(FNDELAY),
+ FC_FL(FAPPEND),
+ FC_FL(FSYNC),
+ FC_FL(FDSYNC),
+ FC_FL(FRSYNC),
+ FC_FL(FOFFMAX),
+ FC_FL(FNONBLOCK),
+ FC_FL(FCREAT),
+ FC_FL(FTRUNC),
+ FC_FL(FEXCL),
+ FC_FL(FNOCTTY),
+ FC_FL(FXATTR),
+ FC_FL(FASYNC),
+ FC_FL(FNODSYNC)
+#undef FC_FL
+};
+
+void
+prt_ffg(private_t *pri, int raw, long val)
+{
+#define CBSIZE sizeof (pri->code_buf)
+ char *s = pri->code_buf;
+ size_t used = 1;
+ struct fcntl_flags *fp;
+
+ if (raw) {
+ (void) snprintf(s, CBSIZE, "0x%lx", val);
+ outstring(pri, s);
+ return;
+ }
+ if (val == 0) {
+ outstring(pri, "(no flags)");
+ return;
+ }
+
+ *s = '\0';
+ for (fp = fcntl_flags;
+ fp < &fcntl_flags[sizeof (fcntl_flags) / sizeof (*fp)]; fp++) {
+ if (val & fp->val) {
+ used = strlcat(s, fp->name, CBSIZE);
+ val &= ~fp->val;
+ }
+ }
+
+ if (val != 0 && used <= CBSIZE)
+ used += snprintf(s + used, CBSIZE - used, "|0x%lx", val);
+
+ if (used >= CBSIZE)
+ (void) snprintf(s + 1, CBSIZE-1, "0x%lx", val);
+ outstring(pri, s + 1);
+#undef CBSIZE
+}
+
+void
+prt_prs(private_t *pri, int raw, long val)
+{
+ static size_t setsize;
+ priv_set_t *set = priv_allocset();
+
+ if (setsize == 0) {
+ const priv_impl_info_t *info = getprivimplinfo();
+ if (info != NULL)
+ setsize = info->priv_setsize * sizeof (priv_chunk_t);
+ }
+
+ if (setsize != 0 && !raw && set != NULL &&
+ Pread(Proc, set, setsize, val) == setsize) {
+ int i;
+
+ outstring(pri, "{");
+ for (i = 0; i < setsize / sizeof (priv_chunk_t); i++) {
+ char buf[9]; /* 8 hex digits + '\0' */
+ (void) snprintf(buf, sizeof (buf), "%08x",
+ ((priv_chunk_t *)set)[i]);
+ outstring(pri, buf);
+ }
+
+ outstring(pri, "}");
+ } else {
+ prt_hex(pri, 0, val);
+ }
+
+ if (set != NULL)
+ priv_freeset(set);
+}
+
+/*
+ * Print privilege set operation.
+ */
+void
+prt_pro(private_t *pri, int raw, long val)
+{
+ const char *s = NULL;
+
+ if (!raw) {
+ switch ((priv_op_t)val) {
+ case PRIV_ON: s = "PRIV_ON"; break;
+ case PRIV_OFF: s = "PRIV_OFF"; break;
+ case PRIV_SET: s = "PRIV_SET"; break;
+ }
+ }
+
+ if (s == NULL)
+ prt_dec(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+/*
+ * Print privilege set name
+ */
+void
+prt_prn(private_t *pri, int raw, long val)
+{
+ const char *s = NULL;
+
+ if (!raw)
+ s = priv_getsetbynum((int)val);
+
+ if (s == NULL)
+ prt_dec(pri, 0, val);
+ else {
+ char *dup = strdup(s);
+ char *q;
+
+ /* Do the best we can in this case */
+ if (dup == NULL) {
+ outstring(pri, s);
+ return;
+ }
+
+ outstring(pri, "PRIV_");
+
+ q = dup;
+
+ while (*q != '\0') {
+ *q = toupper(*q);
+ q++;
+ }
+ outstring(pri, dup);
+ free(dup);
+ }
+}
+
+/*
+ * Print process flag names.
+ */
+void
+prt_pfl(private_t *pri, int raw, long val)
+{
+ const char *s = NULL;
+
+ if (!raw) {
+ switch ((int)val) {
+ case PRIV_DEBUG: s = "PRIV_DEBUG"; break;
+ case PRIV_AWARE: s = "PRIV_AWARE"; break;
+ case PRIV_XPOLICY: s = "PRIV_XPOLICY"; break;
+ case PRIV_AWARE_RESET: s = "PRIV_AWARE_RESET"; break;
+ case PRIV_PFEXEC: s = "PRIV_PFEXEC"; break;
+ case NET_MAC_AWARE: s = "NET_MAC_AWARE"; break;
+ case NET_MAC_AWARE_INHERIT:
+ s = "NET_MAC_AWARE_INHERIT";
+ break;
+ }
+ }
+
+ if (s == NULL)
+ prt_dec(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+/*
+ * Print lgrp_affinity_{get,set}() arguments.
+ */
+/*ARGSUSED*/
+void
+prt_laf(private_t *pri, int raw, long val)
+{
+ lgrp_affinity_args_t laff;
+
+ if (Pread(Proc, &laff, sizeof (lgrp_affinity_args_t), val) !=
+ sizeof (lgrp_affinity_args_t)) {
+ prt_hex(pri, 0, val);
+ return;
+ }
+ /*
+ * arrange the arguments in the order that user calls with
+ */
+ prt_dec(pri, 0, laff.idtype);
+ outstring(pri, ", ");
+ prt_dec(pri, 0, laff.id);
+ outstring(pri, ", ");
+ prt_dec(pri, 0, laff.lgrp);
+ outstring(pri, ", ");
+ if (pri->sys_args[0] == LGRP_SYS_AFFINITY_SET)
+ prt_dec(pri, 0, laff.aff);
+}
+
+/*
+ * Print a key_t as IPC_PRIVATE if it is 0.
+ */
+void
+prt_key(private_t *pri, int raw, long val)
+{
+ if (!raw && val == 0)
+ outstring(pri, "IPC_PRIVATE");
+ else
+ prt_dec(pri, 0, val);
+}
+
+
+/*
+ * Print zone_getattr() attribute types.
+ */
+void
+prt_zga(private_t *pri, int raw, long val)
+{
+ const char *s = NULL;
+
+ if (!raw) {
+ switch ((int)val) {
+ case ZONE_ATTR_NAME: s = "ZONE_ATTR_NAME"; break;
+ case ZONE_ATTR_ROOT: s = "ZONE_ATTR_ROOT"; break;
+ case ZONE_ATTR_STATUS: s = "ZONE_ATTR_STATUS"; break;
+ case ZONE_ATTR_PRIVSET: s = "ZONE_ATTR_PRIVSET"; break;
+ case ZONE_ATTR_UNIQID: s = "ZONE_ATTR_UNIQID"; break;
+ case ZONE_ATTR_POOLID: s = "ZONE_ATTR_POOLID"; break;
+ case ZONE_ATTR_INITPID: s = "ZONE_ATTR_INITPID"; break;
+ case ZONE_ATTR_SLBL: s = "ZONE_ATTR_SLBL"; break;
+ case ZONE_ATTR_INITNAME: s = "ZONE_ATTR_INITNAME"; break;
+ case ZONE_ATTR_BOOTARGS: s = "ZONE_ATTR_BOOTARGS"; break;
+ case ZONE_ATTR_BRAND: s = "ZONE_ATTR_BRAND"; break;
+ case ZONE_ATTR_FLAGS: s = "ZONE_ATTR_FLAGS"; break;
+ case ZONE_ATTR_PHYS_MCAP: s = "ZONE_ATTR_PHYS_MCAP"; break;
+ }
+ }
+
+ if (s == NULL)
+ prt_dec(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+/*
+ * Print a file descriptor as AT_FDCWD if necessary
+ */
+void
+prt_atc(private_t *pri, int raw, long val)
+{
+ if ((int)val == AT_FDCWD) {
+ if (raw)
+ prt_hex(pri, 0, (uint_t)AT_FDCWD);
+ else
+ outstring(pri, "AT_FDCWD");
+ } else {
+ prt_dec(pri, 0, val);
+ }
+}
+
+/*
+ * Print Trusted Networking database operation codes (labelsys; tn*)
+ */
+static void
+prt_tnd(private_t *pri, int raw, long val)
+{
+ const char *s = NULL;
+
+ if (!raw) {
+ switch ((tsol_dbops_t)val) {
+ case TNDB_NOOP: s = "TNDB_NOOP"; break;
+ case TNDB_LOAD: s = "TNDB_LOAD"; break;
+ case TNDB_DELETE: s = "TNDB_DELETE"; break;
+ case TNDB_FLUSH: s = "TNDB_FLUSH"; break;
+ case TNDB_GET: s = "TNDB_GET"; break;
+ }
+ }
+
+ if (s == NULL)
+ prt_dec(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+/*
+ * Print LIO_XX flags
+ */
+void
+prt_lio(private_t *pri, int raw, long val)
+{
+ if (raw)
+ prt_dec(pri, 0, val);
+ else if (val == LIO_WAIT)
+ outstring(pri, "LIO_WAIT");
+ else if (val == LIO_NOWAIT)
+ outstring(pri, "LIO_NOWAIT");
+ else
+ prt_dec(pri, 0, val);
+}
+
+const char *
+door_flags(private_t *pri, long val)
+{
+ door_attr_t attr = (door_attr_t)val;
+ char *str = pri->code_buf;
+
+ *str = '\0';
+#define PROCESS_FLAG(flg) \
+ if (attr & flg) { \
+ (void) strlcat(str, "|" #flg, sizeof (pri->code_buf)); \
+ attr &= ~flg; \
+ }
+
+ PROCESS_FLAG(DOOR_UNREF);
+ PROCESS_FLAG(DOOR_UNREF_MULTI);
+ PROCESS_FLAG(DOOR_PRIVATE);
+ PROCESS_FLAG(DOOR_REFUSE_DESC);
+ PROCESS_FLAG(DOOR_NO_CANCEL);
+ PROCESS_FLAG(DOOR_LOCAL);
+ PROCESS_FLAG(DOOR_REVOKED);
+ PROCESS_FLAG(DOOR_IS_UNREF);
+#undef PROCESS_FLAG
+
+ if (attr != 0 || *str == '\0') {
+ size_t len = strlen(str);
+ (void) snprintf(str + len, sizeof (pri->code_buf) - len,
+ "|0x%X", attr);
+ }
+
+ return (str + 1);
+}
+
+/*
+ * Print door_create() flags
+ */
+void
+prt_dfl(private_t *pri, int raw, long val)
+{
+ if (raw)
+ prt_hex(pri, 0, val);
+ else
+ outstring(pri, door_flags(pri, val));
+}
+
+/*
+ * Print door_*param() param argument
+ */
+void
+prt_dpm(private_t *pri, int raw, long val)
+{
+ if (raw)
+ prt_hex(pri, 0, val);
+ else if (val == DOOR_PARAM_DESC_MAX)
+ outstring(pri, "DOOR_PARAM_DESC_MAX");
+ else if (val == DOOR_PARAM_DATA_MIN)
+ outstring(pri, "DOOR_PARAM_DATA_MIN");
+ else if (val == DOOR_PARAM_DATA_MAX)
+ outstring(pri, "DOOR_PARAM_DATA_MAX");
+ else
+ prt_hex(pri, 0, val);
+}
+
+/*
+ * Print rctlsys subcodes
+ */
+void
+prt_rsc(private_t *pri, int raw, long val) /* print utssys code */
+{
+ const char *s = raw? NULL : rctlsyscode(val);
+
+ if (s == NULL)
+ prt_dec(pri, 0, val);
+ else
+ outstring(pri, s);
+}
+
+/*
+ * Print getrctl flags
+ */
+void
+prt_rgf(private_t *pri, int raw, long val)
+{
+ long action = val & (~RCTLSYS_ACTION_MASK);
+
+ if (raw)
+ prt_hex(pri, 0, val);
+ else if (action == RCTL_FIRST)
+ outstring(pri, "RCTL_FIRST");
+ else if (action == RCTL_NEXT)
+ outstring(pri, "RCTL_NEXT");
+ else if (action == RCTL_USAGE)
+ outstring(pri, "RCTL_USAGE");
+ else
+ prt_hex(pri, 0, val);
+}
+
+/*
+ * Print setrctl flags
+ */
+void
+prt_rsf(private_t *pri, int raw, long val)
+{
+ long action = val & (~RCTLSYS_ACTION_MASK);
+ long pval = val & RCTL_LOCAL_ACTION_MASK;
+ char *s = pri->code_buf;
+
+ if (raw) {
+ prt_hex(pri, 0, val);
+ return;
+ } else if (action == RCTL_INSERT)
+ (void) strcpy(s, "RCTL_INSERT");
+ else if (action == RCTL_DELETE)
+ (void) strcpy(s, "RCTL_DELETE");
+ else if (action == RCTL_REPLACE)
+ (void) strcpy(s, "RCTL_REPLACE");
+ else {
+ prt_hex(pri, 0, val);
+ return;
+ }
+
+ if (pval & RCTL_USE_RECIPIENT_PID) {
+ pval ^= RCTL_USE_RECIPIENT_PID;
+ (void) strlcat(s, "|RCTL_USE_RECIPIENT_PID",
+ sizeof (pri->code_buf));
+ }
+
+ if ((pval & RCTLSYS_ACTION_MASK) != 0)
+ prt_hex(pri, 0, val);
+ else if (*s != '\0')
+ outstring(pri, s);
+ else
+ prt_hex(pri, 0, val);
+}
+
+/*
+ * Print rctlctl flags
+ */
+void
+prt_rcf(private_t *pri, int raw, long val)
+{
+ long action = val & (~RCTLSYS_ACTION_MASK);
+
+ if (raw)
+ prt_hex(pri, 0, val);
+ else if (action == RCTLCTL_GET)
+ outstring(pri, "RCTLCTL_GET");
+ else if (action == RCTLCTL_SET)
+ outstring(pri, "RCTLCTL_SET");
+ else
+ prt_hex(pri, 0, val);
+}
+
+/*
+ * Print setprojrctl flags
+ */
+void
+prt_spf(private_t *pri, int raw, long val)
+{
+ long action = val & TASK_PROJ_MASK;
+
+ if (!raw && (action == TASK_PROJ_PURGE))
+ outstring(pri, "TASK_PROJ_PURGE");
+ else
+ prt_hex(pri, 0, val);
+}
+
+/*
+ * Print forkx() flags
+ */
+void
+prt_fxf(private_t *pri, int raw, long val)
+{
+ char *str;
+
+ if (val == 0)
+ outstring(pri, "0");
+ else if (raw || (val & ~(FORK_NOSIGCHLD | FORK_WAITPID)))
+ prt_hhx(pri, 0, val);
+ else {
+ str = pri->code_buf;
+ *str = '\0';
+ if (val & FORK_NOSIGCHLD)
+ (void) strlcat(str, "|FORK_NOSIGCHLD",
+ sizeof (pri->code_buf));
+ if (val & FORK_WAITPID)
+ (void) strlcat(str, "|FORK_WAITPID",
+ sizeof (pri->code_buf));
+ outstring(pri, str + 1);
+ }
+}
+
+/*
+ * Print faccessat() flag
+ */
+void
+prt_fat(private_t *pri, int raw, long val)
+{
+ if (val == 0)
+ outstring(pri, "0");
+ else if (!raw && val == AT_EACCESS)
+ outstring(pri, "AT_EACCESS");
+ else
+ prt_hex(pri, 0, val);
+}
+
+/*
+ * Print unlinkat() flag
+ */
+void
+prt_uat(private_t *pri, int raw, long val)
+{
+ if (val == 0)
+ outstring(pri, "0");
+ else if (!raw && val == AT_REMOVEDIR)
+ outstring(pri, "AT_REMOVEDIR");
+ else
+ prt_hex(pri, 0, val);
+}
+
+/*
+ * Print AT_SYMLINK_NOFOLLOW / AT_SYMLINK_FOLLOW flag
+ */
+void
+prt_snf(private_t *pri, int raw, long val)
+{
+ if (val == 0)
+ outstring(pri, "0");
+ else if (!raw && val == AT_SYMLINK_NOFOLLOW)
+ outstring(pri, "AT_SYMLINK_NOFOLLOW");
+ else if (!raw && val == AT_SYMLINK_FOLLOW)
+ outstring(pri, "AT_SYMLINK_FOLLOW");
+ else
+ prt_hex(pri, 0, val);
+}
+
+/*
+ * Array of pointers to print functions, one for each format.
+ */
+void (* const Print[])() = {
+ prt_nov, /* NOV -- no value */
+ prt_dec, /* DEC -- print value in decimal */
+ prt_oct, /* OCT -- print value in octal */
+ prt_hex, /* HEX -- print value in hexadecimal */
+ prt_dex, /* DEX -- print value in hexadecimal if big enough */
+ prt_stg, /* STG -- print value as string */
+ prt_ioc, /* IOC -- print ioctl code */
+ prt_fcn, /* FCN -- print fcntl code */
+ prt_s86, /* S86 -- print sysi86 code */
+ prt_uts, /* UTS -- print utssys code */
+ prt_opn, /* OPN -- print open code */
+ prt_sig, /* SIG -- print signal name plus flags */
+ prt_uat, /* UAT -- print unlinkat() flag */
+ prt_msc, /* MSC -- print msgsys command */
+ prt_msf, /* MSF -- print msgsys flags */
+ prt_smc, /* SMC -- print semsys command */
+ prt_sef, /* SEF -- print semsys flags */
+ prt_shc, /* SHC -- print shmsys command */
+ prt_shf, /* SHF -- print shmsys flags */
+ prt_fat, /* FAT -- print faccessat( flag */
+ prt_sfs, /* SFS -- print sysfs code */
+ prt_rst, /* RST -- print string returned by syscall */
+ prt_smf, /* SMF -- print streams message flags */
+ prt_ioa, /* IOA -- print ioctl argument */
+ prt_pip, /* PIP -- print pipe flags */
+ prt_mtf, /* MTF -- print mount flags */
+ prt_mft, /* MFT -- print mount file system type */
+ prt_iob, /* IOB -- print contents of I/O buffer */
+ prt_hhx, /* HHX -- print value in hexadecimal (half size) */
+ prt_wop, /* WOP -- print waitsys() options */
+ prt_spm, /* SPM -- print sigprocmask argument */
+ prt_rlk, /* RLK -- print readlink buffer */
+ prt_mpr, /* MPR -- print mmap()/mprotect() flags */
+ prt_mty, /* MTY -- print mmap() mapping type flags */
+ prt_mcf, /* MCF -- print memcntl() function */
+ prt_mc4, /* MC4 -- print memcntl() (fourth) argument */
+ prt_mc5, /* MC5 -- print memcntl() (fifth) argument */
+ prt_mad, /* MAD -- print madvise() argument */
+ prt_ulm, /* ULM -- print ulimit() argument */
+ prt_rlm, /* RLM -- print get/setrlimit() argument */
+ prt_cnf, /* CNF -- print sysconfig() argument */
+ prt_inf, /* INF -- print sysinfo() argument */
+ prt_ptc, /* PTC -- print pathconf/fpathconf() argument */
+ prt_fui, /* FUI -- print fusers() input argument */
+ prt_idt, /* IDT -- print idtype_t, waitid() argument */
+ prt_lwf, /* LWF -- print lwp_create() flags */
+ prt_itm, /* ITM -- print [get|set]itimer() arg */
+ prt_llo, /* LLO -- print long long offset arg */
+ prt_mod, /* MOD -- print modctl() subcode */
+ prt_whn, /* WHN -- print lseek() whence arguiment */
+ prt_acl, /* ACL -- print acl() code */
+ prt_aio, /* AIO -- print kaio() code */
+ prt_aud, /* AUD -- print auditsys() code */
+ prt_uns, /* DEC -- print value in unsigned decimal */
+ prt_clc, /* CLC -- print cladm command argument */
+ prt_clf, /* CLF -- print cladm flag argument */
+ prt_cor, /* COR -- print corectl() subcode */
+ prt_cco, /* CCO -- print corectl() options */
+ prt_ccc, /* CCC -- print corectl() content */
+ prt_rcc, /* RCC -- print corectl() returned content */
+ prt_cpc, /* CPC -- print cpc() subcode */
+ prt_sqc, /* SQC -- print sigqueue() si_code argument */
+ prt_pc4, /* PC4 -- print priocntlsys() (fourth) argument */
+ prt_pc5, /* PC5 -- print priocntlsys() (key, value) pairs */
+ prt_pst, /* PST -- print processor set id */
+ prt_mif, /* MIF -- print meminfo() arguments */
+ prt_pfm, /* PFM -- print so_socket() proto-family (1st) arg */
+ prt_skt, /* SKT -- print so_socket() socket-type (2nd) arg */
+ prt_skp, /* SKP -- print so_socket() protocol (3rd) arg */
+ prt_skv, /* SKV -- print socket version arg */
+ prt_sol, /* SOL -- print [sg]etsockopt() level (2nd) arg */
+ prt_son, /* SON -- print [sg]etsockopt() opt-name (3rd) arg */
+ prt_utt, /* UTT -- print utrap type */
+ prt_uth, /* UTH -- print utrap handler */
+ prt_acc, /* ACC -- print access() flags */
+ prt_sht, /* SHT -- print shutdown() how (2nd) argument */
+ prt_ffg, /* FFG -- print fcntl() flags (3rd) argument */
+ prt_prs, /* PRS -- print privilege set */
+ prt_pro, /* PRO -- print privilege set operation */
+ prt_prn, /* PRN -- print privilege set name */
+ prt_pfl, /* PFL -- print privilege/process flag name */
+ prt_laf, /* LAF -- print lgrp_affinity arguments */
+ prt_key, /* KEY -- print key_t 0 as IPC_PRIVATE */
+ prt_zga, /* ZGA -- print zone_getattr attribute types */
+ prt_atc, /* ATC -- print AT_FDCWD or file descriptor */
+ prt_lio, /* LIO -- print LIO_XX flags */
+ prt_dfl, /* DFL -- print door_create() flags */
+ prt_dpm, /* DPM -- print DOOR_PARAM_XX flags */
+ prt_tnd, /* TND -- print trusted network data base opcode */
+ prt_rsc, /* RSC -- print rctlsys() subcodes */
+ prt_rgf, /* RGF -- print getrctl() flags */
+ prt_rsf, /* RSF -- print setrctl() flags */
+ prt_rcf, /* RCF -- print rctlsys_ctl() flags */
+ prt_fxf, /* FXF -- print forkx() flags */
+ prt_spf, /* SPF -- print rctlsys_projset() flags */
+ prt_un1, /* UN1 -- as prt_uns except for -1 */
+ prt_mob, /* MOB -- print mmapobj() flags */
+ prt_snf, /* SNF -- print AT_SYMLINK_[NO]FOLLOW flag */
+ prt_skc, /* SKC -- print sockconfig() subcode */
+ prt_acf, /* ACF -- print accept4 flags */
+ prt_pfd, /* PFD -- print pipe fds */
+ prt_dec, /* HID -- hidden argument, make this the last one */
+};
diff --git a/usr/src/cmd/truss/print.h b/usr/src/cmd/truss/print.h
new file mode 100644
index 0000000..9a9a43b
--- /dev/null
+++ b/usr/src/cmd/truss/print.h
@@ -0,0 +1,154 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
+ */
+
+/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
+/* All Rights Reserved */
+
+/* Copyright (c) 2013, OmniTI Computer Consulting, Inc. All right reserved. */
+
+#ifndef _TRUSS_PRINT_H
+#define _TRUSS_PRINT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Argument & return value print codes.
+ */
+#define NOV 0 /* no value */
+#define DEC 1 /* print value in decimal */
+#define OCT 2 /* print value in octal */
+#define HEX 3 /* print value in hexadecimal */
+#define DEX 4 /* print value in hexadecimal if big enough */
+#define STG 5 /* print value as string */
+#define IOC 6 /* print ioctl code */
+#define FCN 7 /* print fcntl code */
+#define S86 8 /* print sysi86 code */
+#define UTS 9 /* print utssys code */
+#define OPN 10 /* print open code */
+#define SIG 11 /* print signal name plus flags */
+#define UAT 12 /* print unlinkat() flag */
+#define MSC 13 /* print msgsys command */
+#define MSF 14 /* print msgsys flags */
+#define SMC 15 /* print semsys command */
+#define SEF 16 /* print semsys flags */
+#define SHC 17 /* print shmsys command */
+#define SHF 18 /* print shmsys flags */
+#define FAT 19 /* print faccessat() flag */
+#define SFS 20 /* print sysfs code */
+#define RST 21 /* print string returned by sys call */
+#define SMF 22 /* print streams message flags */
+#define IOA 23 /* print ioctl argument */
+#define PIP 24 /* print pipe flags */
+#define MTF 25 /* print mount flags */
+#define MFT 26 /* print mount file system type */
+#define IOB 27 /* print contents of I/O buffer */
+#define HHX 28 /* print value in hexadecimal (half size) */
+#define WOP 29 /* print waitsys() options */
+#define SPM 30 /* print sigprocmask argument */
+#define RLK 31 /* print readlink buffer */
+#define MPR 32 /* print mmap()/mprotect() flags */
+#define MTY 33 /* print mmap() mapping type flags */
+#define MCF 34 /* print memcntl() function */
+#define MC4 35 /* print memcntl() (fourth) argument */
+#define MC5 36 /* print memcntl() (fifth) argument */
+#define MAD 37 /* print madvise() argument */
+#define ULM 38 /* print ulimit() argument */
+#define RLM 39 /* print get/setrlimit() argument */
+#define CNF 40 /* print sysconfig() argument */
+#define INF 41 /* print sysinfo() argument */
+#define PTC 42 /* print pathconf/fpathconf() argument */
+#define FUI 43 /* print fusers() input argument */
+#define IDT 44 /* print idtype_t, waitid() argument */
+#define LWF 45 /* print lwp_create() flags */
+#define ITM 46 /* print [get|set]itimer() arg */
+#define LLO 47 /* print long long offset */
+#define MOD 48 /* print modctl() code */
+#define WHN 49 /* print lseek() whence argument */
+#define ACL 50 /* print acl() code */
+#define AIO 51 /* print kaio() code */
+#define AUD 52 /* print auditsys() code */
+#define UNS 53 /* print value in unsigned decimal */
+#define CLC 54 /* print cladm() command argument */
+#define CLF 55 /* print cladm() flag argument */
+#define COR 56 /* print corectl() subcode */
+#define CCO 57 /* print corectl() options */
+#define CCC 58 /* print corectl() content */
+#define RCC 59 /* print corectl() content */
+#define CPC 60 /* print cpc() subcode */
+#define SQC 61 /* print sigqueue() si_code argument */
+#define PC4 62 /* print priocntlsys() (fourth) argument */
+#define PC5 63 /* print priocntlsys() (key-value) pairs */
+#define PST 64 /* print processor set id */
+#define MIF 65 /* print meminfo() argument */
+#define PFM 66 /* print so_socket() proto-family (1st) arg */
+#define SKT 67 /* print so_socket() socket type (2nd) arg */
+#define SKP 68 /* print so_socket() protocol (3rd) arg */
+#define SKV 69 /* print so_socket() version (5th) arg */
+#define SOL 70 /* print [sg]etsockopt() level (2nd) arg */
+#define SON 71 /* print [sg]etsockopt() name (3rd) arg */
+#define UTT 72 /* print utrap type */
+#define UTH 73 /* print utrap handler */
+#define ACC 74 /* print access flags */
+#define SHT 75 /* print shutdown() "how" (2nd) arg */
+#define FFG 76 /* print fcntl() flags (3rd) arg */
+#define PRS 77 /* privilege set */
+#define PRO 78 /* privilege set operation */
+#define PRN 79 /* privilege set name */
+#define PFL 80 /* privilege/process flag name */
+#define LAF 81 /* print lgrp_affinity arguments */
+#define KEY 82 /* print key_t 0 as IPC_PRIVATE */
+#define ZGA 83 /* print zone_getattr attribute types */
+#define ATC 84 /* print AT_FDCWD or file descriptor */
+#define LIO 85 /* print LIO_XX flags */
+#define DFL 86 /* print door_create() flags */
+#define DPM 87 /* print DOOR_PARAM_XX flags */
+#define TND 88 /* print trusted network data base opcode */
+#define RSC 89 /* print rctlsys subcode */
+#define RGF 90 /* print rctlsys_get flags */
+#define RSF 91 /* print rctlsys_set flags */
+#define RCF 92 /* print rctlsys_ctl flags */
+#define FXF 93 /* print forkx flags */
+#define SPF 94 /* print rctlsys_projset flags */
+#define UN1 95 /* unsigned except for -1 */
+#define MOB 96 /* print mmapobj() flags */
+#define SNF 97 /* print AT_SYMLINK_[NO]FOLLOW flag */
+#define SKC 98 /* print sockconfig subcode */
+#define ACF 99 /* accept4 flags */
+#define PFD 100 /* pipe fds[2] */
+#define HID 101 /* hidden argument, don't print */
+ /* make sure HID is always the last member */
+
+/*
+ * Print routines, indexed by print codes.
+ */
+extern void (* const Print[])();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _TRUSS_PRINT_H */
diff --git a/usr/src/cmd/truss/procset.c b/usr/src/cmd/truss/procset.c
new file mode 100644
index 0000000..4ba72bd
--- /dev/null
+++ b/usr/src/cmd/truss/procset.c
@@ -0,0 +1,137 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
+/* All Rights Reserved */
+
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <libproc.h>
+#include "ramdata.h"
+#include "proto.h"
+
+/*
+ * Function prototypes for static routines in this module.
+ */
+const char *idop_enum(private_t *, idop_t);
+
+void
+show_procset(private_t *pri, long offset)
+{
+ procset_t procset;
+ procset_t *psp = &procset;
+
+ if (Pread(Proc, psp, sizeof (*psp), offset) == sizeof (*psp)) {
+ (void) printf("%s\top=%s",
+ pri->pname, idop_enum(pri, psp->p_op));
+ (void) printf(" ltyp=%s lid=%ld",
+ idtype_enum(pri, psp->p_lidtype), (long)psp->p_lid);
+ (void) printf(" rtyp=%s rid=%ld\n",
+ idtype_enum(pri, psp->p_ridtype), (long)psp->p_rid);
+ }
+}
+
+const char *
+idop_enum(private_t *pri, idop_t arg)
+{
+ const char *str;
+
+ switch (arg) {
+ case POP_DIFF: str = "POP_DIFF"; break;
+ case POP_AND: str = "POP_AND"; break;
+ case POP_OR: str = "POP_OR"; break;
+ case POP_XOR: str = "POP_XOR"; break;
+ default:
+ (void) sprintf(pri->code_buf, "%d", arg);
+ str = (const char *)pri->code_buf;
+ break;
+ }
+
+ return (str);
+}
+
+const char *
+idtype_enum(private_t *pri, long arg)
+{
+ const char *str;
+
+ switch (arg) {
+ case P_PID: str = "P_PID"; break;
+ case P_PPID: str = "P_PPID"; break;
+ case P_PGID: str = "P_PGID"; break;
+ case P_SID: str = "P_SID"; break;
+ case P_CID: str = "P_CID"; break;
+ case P_UID: str = "P_UID"; break;
+ case P_GID: str = "P_GID"; break;
+ case P_ALL: str = "P_ALL"; break;
+ case P_LWPID: str = "P_LWPID"; break;
+ case P_TASKID: str = "P_TASKID"; break;
+ case P_PROJID: str = "P_PROJID"; break;
+ case P_ZONEID: str = "P_ZONEID"; break;
+ case P_CTID: str = "P_CTID"; break;
+ default:
+ (void) sprintf(pri->code_buf, "%ld", arg);
+ str = (const char *)pri->code_buf;
+ break;
+ }
+
+ return (str);
+}
+
+const char *
+woptions(private_t *pri, int arg)
+{
+ char *str = pri->code_buf;
+
+ if (arg == 0)
+ return ("0");
+ if (arg &
+ ~(WEXITED|WTRAPPED|WSTOPPED|WCONTINUED|WNOHANG|WNOWAIT))
+ return (NULL);
+
+ *str = '\0';
+ if (arg & WEXITED)
+ (void) strcat(str, "|WEXITED");
+ if (arg & WTRAPPED)
+ (void) strcat(str, "|WTRAPPED");
+ if (arg & WSTOPPED)
+ (void) strcat(str, "|WSTOPPED");
+ if (arg & WCONTINUED)
+ (void) strcat(str, "|WCONTINUED");
+ if (arg & WNOHANG)
+ (void) strcat(str, "|WNOHANG");
+ if (arg & WNOWAIT)
+ (void) strcat(str, "|WNOWAIT");
+
+ return ((const char *)(str+1));
+}
diff --git a/usr/src/cmd/truss/proto.h b/usr/src/cmd/truss/proto.h
new file mode 100644
index 0000000..670fe95
--- /dev/null
+++ b/usr/src/cmd/truss/proto.h
@@ -0,0 +1,154 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
+ */
+
+/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
+/* All Rights Reserved */
+
+#ifndef _PROTO_H
+#define _PROTO_H
+
+#include <sys/procset.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* avoid a bit of stdio locking */
+#define fputc putc_unlocked
+
+/* force (via setvbuf()) a reasonably large output file buffer size */
+#define MYBUFSIZ 8192
+
+/*
+ * Function prototypes for most external functions.
+ */
+
+extern private_t *get_private(void);
+extern void *my_malloc(size_t, const char *);
+extern void *my_realloc(void *, size_t, const char *);
+extern void *my_calloc(size_t, size_t, const char *);
+extern void make_pname(private_t *, id_t);
+extern int requested(private_t *, int, int);
+extern int jobcontrol(private_t *, int);
+extern int signalled(private_t *, int, int);
+extern int faulted(private_t *, int);
+extern int sysentry(private_t *, int);
+extern int sysexit(private_t *, int);
+extern void showbuffer(private_t *, long, long);
+extern void showbytes(const char *, int, char *);
+extern void accumulate(timestruc_t *,
+ const timestruc_t *, const timestruc_t *);
+
+extern const char *ioctlname(private_t *, uint_t);
+extern const char *ioctldatastruct(uint_t);
+extern const char *fcntlname(int);
+extern const char *sfsname(int);
+extern const char *si86name(int);
+extern const char *utscode(int);
+extern const char *openarg(private_t *, int);
+extern const char *whencearg(int);
+extern const char *msgflags(private_t *, int);
+extern const char *semflags(private_t *, int);
+extern const char *shmflags(private_t *, int);
+extern const char *msgcmd(int);
+extern const char *semcmd(int);
+extern const char *shmcmd(int);
+extern const char *strrdopt(int);
+extern const char *strevents(private_t *, int);
+extern const char *tiocflush(private_t *, int);
+extern const char *strflush(int);
+extern const char *mountflags(private_t *, int);
+extern const char *svfsflags(private_t *, ulong_t);
+extern const char *sconfname(int);
+extern const char *pathconfname(int);
+extern const char *fuiname(int);
+extern const char *fuflags(private_t *, int);
+extern const char *ipprotos(int);
+extern const char *rctlsyscode(int);
+extern const char *rctl_local_flags(private_t *, uint_t val);
+extern const char *rctl_local_action(private_t *, uint_t val);
+
+extern void expound(private_t *, long, int);
+extern void prtimestruc(private_t *, const char *, timestruc_t *);
+extern void print_siginfo(private_t *, const siginfo_t *);
+
+extern void Flush(void);
+extern void Eserialize(void);
+extern void Xserialize(void);
+extern void procadd(pid_t, const char *lwplist);
+extern int lwptrace(pid_t, lwpid_t);
+extern void procdel(void);
+extern int checkproc(private_t *);
+
+extern int syslist(char *, sysset_t *, int *);
+extern int siglist(private_t *, char *, sigset_t *, int *);
+extern int fltlist(char *, fltset_t *, int *);
+extern int fdlist(char *, fileset_t *);
+extern int liblist(char *, int);
+
+extern char *fetchstring(private_t *, long, int);
+extern void show_cred(private_t *, int, int);
+extern void errmsg(const char *, const char *);
+extern void abend(const char *, const char *);
+
+extern void outstring(private_t *, const char *);
+extern void grow(private_t *, int);
+
+extern void show_procset(private_t *, long);
+extern const char *idtype_enum(private_t *, long);
+extern const char *woptions(private_t *, int);
+
+extern void putpname(private_t *);
+extern void timestamp(private_t *);
+
+extern const char *errname(int);
+extern const char *sysname(private_t *, int, int);
+extern const char *rawsigname(private_t *, int);
+extern const char *signame(private_t *, int);
+
+extern int getsubcode(private_t *);
+extern int maxsyscalls(void);
+extern int nsubcodes(int);
+
+extern void show_stat(private_t *, long);
+extern void show_stat64_32(private_t *, long);
+
+extern void establish_breakpoints(void);
+extern void establish_stacks(void);
+extern void reset_breakpoints(void);
+extern void clear_breakpoints(void);
+extern int function_trace(private_t *, int, int, int);
+extern void reestablish_traps(void);
+extern void report_htable_stats(void);
+
+extern const char *door_flags(private_t *, long);
+extern void prt_ffg(private_t *, int, long);
+extern void escape_string(private_t *, const char *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PROTO_H */
diff --git a/usr/src/cmd/truss/ramdata.c b/usr/src/cmd/truss/ramdata.c
new file mode 100644
index 0000000..abb8ee2
--- /dev/null
+++ b/usr/src/cmd/truss/ramdata.c
@@ -0,0 +1,137 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
+ */
+
+/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
+/* All Rights Reserved */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <libproc.h>
+#include "ramdata.h"
+#include "proto.h"
+#include "htbl.h"
+
+/*
+ * ramdata.c -- read/write data definitions are collected here.
+ * Default initialization of zero applies in all cases.
+ */
+
+thread_key_t private_key; /* set by thr_keycreate() */
+char *command; /* name of command ("truss") */
+int interrupt; /* interrupt signal was received */
+int sigusr1; /* received SIGUSR1 (release process) */
+int sfd; /* shared tmp file descriptor */
+pid_t created; /* if process was created, its process id */
+uid_t Euid; /* truss's effective uid */
+uid_t Egid; /* truss's effective gid */
+uid_t Ruid; /* truss's real uid */
+uid_t Rgid; /* truss's real gid */
+prcred_t credentials; /* traced process credentials */
+prpriv_t *privdata; /* traced process privileges */
+int istty; /* TRUE iff output is a tty */
+time_t starttime; /* start time */
+
+int Fflag; /* option flags from getopt() */
+int fflag;
+int cflag;
+int aflag;
+int eflag;
+int iflag;
+int lflag;
+int tflag;
+int pflag;
+int sflag;
+int mflag;
+int oflag;
+int vflag;
+int xflag;
+int hflag;
+
+int dflag;
+int Dflag;
+int Eflag;
+int Tflag;
+int Sflag;
+int Mflag;
+
+sysset_t trace; /* sys calls to trace */
+sysset_t traceeven; /* sys calls to trace even if not reported */
+sysset_t verbose; /* sys calls to be verbose about */
+sysset_t rawout; /* sys calls to show in raw mode */
+sigset_t signals; /* signals to trace */
+fltset_t faults; /* faults to trace */
+fileset_t readfd; /* read() file descriptors to dump */
+fileset_t writefd; /* write() file descriptors to dump */
+
+mutex_t truss_lock; /* protects almost everything */
+cond_t truss_cv;
+mutex_t count_lock; /* lock protecting count struct Cp */
+
+htbl_t *fcall_tbl; /* ptr to hash tbl counting function calls */
+
+int truss_nlwp; /* number of truss lwps */
+int truss_maxlwp; /* number of entries in truss_lwpid */
+lwpid_t *truss_lwpid; /* array of truss lwpid's */
+
+struct counts *Cp; /* for counting: malloc() or shared memory */
+struct global_psinfo *gps; /* contains global process information */
+
+struct dynlib *Dynlib; /* for tracing functions in shared libraries */
+struct dynpat *Dynpat;
+struct dynpat *Lastpat;
+struct bkpt **bpt_hashtable; /* breakpoint hash table */
+uint_t nthr_create; /* number of thr_create() calls seen so far */
+struct callstack *callstack; /* the callstack array */
+uint_t nstack; /* number of detected stacks */
+rd_agent_t *Rdb_agent; /* run-time linker debug handle */
+td_thragent_t *Thr_agent; /* thread debug handle */
+int not_consist; /* used while rebuilding breakpoint table */
+int delete_library; /* used while rebuilding breakpoint table */
+
+pid_t ancestor; /* top-level parent process id */
+int descendent; /* TRUE iff descendent of top level */
+int is_vfork_child; /* TRUE iff process is a vfork()ed child */
+
+int ngrab; /* number of pid's that were grabbed */
+
+struct ps_prochandle *Proc; /* global reference to process */
+int data_model; /* PR_MODEL_LP64 or PR_MODEL_ILP32 */
+
+long pagesize; /* bytes per page; should be per-process */
+
+int exit_called; /* _exit() syscall was seen */
+
+lwpid_t primary_lwp; /* representative lwp on process grab */
+
+sysset_t syshang; /* sys calls to make process hang */
+sigset_t sighang; /* signals to make process hang */
+fltset_t flthang; /* faults to make process hang */
+
+sigset_t emptyset; /* no signals, for thr_sigsetmask() */
+sigset_t fillset; /* all signals, for thr_sigsetmask() */
+
+int leave_hung; /* if TRUE, leave the process hung */
diff --git a/usr/src/cmd/truss/ramdata.h b/usr/src/cmd/truss/ramdata.h
new file mode 100644
index 0000000..7884228
--- /dev/null
+++ b/usr/src/cmd/truss/ramdata.h
@@ -0,0 +1,317 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
+ */
+
+/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
+/* All Rights Reserved */
+
+#ifndef _RAMDATA_H
+#define _RAMDATA_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * ramdata.h -- read/write data declarations.
+ */
+
+#include <errno.h>
+#include <signal.h>
+#include <synch.h>
+#include <thread.h>
+#include <thread_db.h>
+#include "htbl.h"
+
+/*
+ * Set type for possible filedescriptors.
+ */
+#define NOFILES_MAX (64 * 1024)
+typedef struct {
+ uint32_t word[(NOFILES_MAX+31)/32];
+} fileset_t;
+
+/*
+ * Previous stop state enumeration (used by signalled() and requested()).
+ */
+#define SLEEPING 1
+#define JOBSIG 2
+#define JOBSTOP 3
+
+/*
+ * Simple convenience.
+ */
+#ifdef TRUE
+#undef TRUE
+#endif
+#ifdef FALSE
+#undef FALSE
+#endif
+#define TRUE 1
+#define FALSE 0
+
+/*
+ * Definition of private data. See get_private().
+ */
+
+#define IOBSIZE 12 /* number of bytes shown by prt_iob() */
+
+#define CACHE_LN_SZ 64
+
+typedef struct private {
+ struct ps_lwphandle *Lwp; /* non-NULL for each lwp controller */
+ const lwpstatus_t *lwpstat; /* lwp status information while stopped */
+ int length; /* length of printf() output so far */
+ pid_t child; /* pid of fork()ed child process */
+ char pname[32]; /* formatted pid/tid of controlled lwp */
+ struct { /* remembered parameters for make_pname() */
+ int ff;
+ int lf;
+ pid_t pid;
+ id_t lwpid;
+ id_t tid;
+ } pparam;
+ int Errno; /* errno for controlled process's syscall */
+ int ErrPriv; /* privilege missing for last syscall */
+ long Rval1; /* rval1 (%r0) for syscall */
+ long Rval2; /* rval2 (%r1) for syscall */
+ timestruc_t syslast; /* most recent value of stime */
+ timestruc_t usrlast; /* most recent value of utime */
+ long sys_args[9]; /* the arguments to the last syscall */
+ int sys_nargs; /* number of arguments to the last syscall */
+ int sys_indirect; /* if TRUE, this is an indirect system call */
+ char sys_name[12]; /* name of unknown system call */
+ char raw_sig_name[SIG2STR_MAX+4]; /* name of known signal */
+ char sig_name[12]; /* name of unknown signal */
+ char flt_name[12]; /* name of unknown fault */
+ char *sys_path; /* pathname given to syscall */
+ size_t sys_psize; /* sizeof(*sys_path) */
+ int sys_valid; /* pathname was fetched and is valid */
+ char *sys_string; /* buffer for formatted syscall string */
+ size_t sys_ssize; /* sizeof(*sys_string) */
+ size_t sys_leng; /* strlen(sys_string) */
+ char *exec_string; /* copy of sys_string for exec() only */
+ char exec_pname[32]; /* formatted pid for exec() only */
+ id_t exec_lwpid; /* lwpid that performed the exec */
+ char *str_buffer; /* fetchstring() buffer */
+ size_t str_bsize; /* sizeof(*str_buffer) */
+ char iob_buf[2*IOBSIZE+8]; /* where prt_iob() leaves its stuff */
+ char code_buf[160]; /* for symbolic arguments, e.g., ioctl codes */
+ int recur; /* show_strioctl() -- to prevent recursion */
+ int seconds; /* seconds, fraction for timestamps */
+ int fraction; /* fraction in 1/10 milliseconds */
+} private_t;
+
+extern thread_key_t private_key; /* set by thr_keycreate() */
+
+extern char *command; /* name of command ("truss") */
+extern int interrupt; /* interrupt signal was received */
+extern int sigusr1; /* received SIGUSR1 (release process) */
+extern int sfd; /* file descriptor to shared tmp file */
+extern pid_t created; /* if process was created, its process id */
+extern uid_t Euid; /* truss's effective uid */
+extern uid_t Egid; /* truss's effective gid */
+extern uid_t Ruid; /* truss's real uid */
+extern uid_t Rgid; /* truss's real gid */
+extern prcred_t credentials; /* traced process credentials */
+extern prpriv_t *privdata; /* traced process privileges */
+extern int istty; /* TRUE iff output is a tty */
+extern time_t starttime; /* start time */
+
+extern int Fflag; /* option flags from getopt() */
+extern int fflag;
+extern int cflag;
+extern int aflag;
+extern int eflag;
+extern int iflag;
+extern int lflag;
+extern int tflag;
+extern int pflag;
+extern int sflag;
+extern int mflag;
+extern int oflag;
+extern int vflag;
+extern int xflag;
+extern int hflag;
+
+extern int dflag;
+extern int Dflag;
+extern int Eflag;
+extern int Tflag;
+extern int Sflag;
+extern int Mflag;
+
+extern sysset_t trace; /* sys calls to trace */
+extern sysset_t traceeven; /* sys calls to trace even if not reported */
+extern sysset_t verbose; /* sys calls to be verbose about */
+extern sysset_t rawout; /* sys calls to show in raw mode */
+extern sigset_t signals; /* signals to trace */
+extern fltset_t faults; /* faults to trace */
+extern fileset_t readfd; /* read() file descriptors to dump */
+extern fileset_t writefd; /* write() file descriptors to dump */
+
+#pragma align CACHE_LN_SZ(truss_lock, count_lock)
+extern mutex_t truss_lock; /* protects almost everything */
+extern cond_t truss_cv; /* condition variable associated w truss_lock */
+extern mutex_t count_lock; /* lock protecting count struct Cp */
+
+extern htbl_t *fcall_tbl; /* function call hash table (per-proc) */
+
+extern int truss_nlwp; /* number of truss lwps */
+extern int truss_maxlwp; /* number of entries in truss_lwpid */
+extern lwpid_t *truss_lwpid; /* array of truss lwpid's */
+
+
+struct syscount {
+ long count; /* system call count */
+ long error; /* system call errors */
+ timestruc_t stime; /* time spent in system call */
+};
+
+struct counts { /* structure for keeping counts */
+ long sigcount[PRMAXSIG+1]; /* signals count [0..PRMAXSIG] */
+ long fltcount[PRMAXFAULT+1]; /* faults count [0..MAXFAULT] */
+ struct syscount *syscount[PRMAXSYS+1];
+ timestruc_t systotal; /* total time spent in kernel */
+ timestruc_t usrtotal; /* total time spent in user mode */
+ timestruc_t basetime; /* base time for timestamps */
+};
+
+struct global_psinfo {
+ mutex_t fork_lock; /* protects list of truss pids */
+ cond_t fork_cv;
+ char p1[CACHE_LN_SZ - (sizeof (mutex_t) + sizeof (cond_t))];
+ mutex_t ps_mutex0; /* see ipc.c:Ecritical */
+ char p2[CACHE_LN_SZ - sizeof (mutex_t)];
+ mutex_t ps_mutex1; /* see ipc.c:Ecritical */
+ char p3[CACHE_LN_SZ - sizeof (mutex_t)];
+ pid_t fork_pid;
+ pid_t tpid[1000]; /* truss process pid */
+ pid_t spid[1000]; /* subject process pid */
+ const char *lwps[1000]; /* optional lwp list */
+};
+
+extern struct counts *Cp; /* for counting: malloc() or shared memory */
+extern struct global_psinfo *gps; /* ptr to global_psinfo struct */
+
+struct bkpt { /* to describe one function's entry point */
+ struct bkpt *next; /* hash table linked list */
+ char *sym_name; /* function name */
+ struct dynlib *dyn; /* enclosing library */
+ uintptr_t addr; /* function address, breakpointed */
+ ulong_t instr; /* original instruction at addr */
+ int flags; /* see below */
+};
+#define BPT_HANG 0x01 /* leave stopped and abandoned when called */
+#define BPT_EXCLUDE 0x02 /* function found but is being excluded */
+#define BPT_INTERNAL 0x04 /* trace internal calls on this function */
+#define BPT_ACTIVE 0x08 /* function breakpoint is set in process */
+#define BPT_PREINIT 0x10 /* PREINIT event in ld.so.1 */
+#define BPT_POSTINIT 0x20 /* POSTINIT event in ld.so.1 */
+#define BPT_DLACTIVITY 0x40 /* DLACTIVITY event in ld.so.1 */
+#define BPT_TD_CREATE 0x80 /* TD_CREATE threading event */
+
+struct dynlib { /* structure for tracing functions */
+ struct dynlib *next;
+ char *lib_name; /* full library name */
+ char *match_name; /* library name used in name matching */
+ char *prt_name; /* library name for printing */
+ int built; /* if true, bkpt list has been built */
+ int present; /* true if library is still present */
+ uintptr_t base; /* library's mapping base */
+ size_t size; /* library's mapping size */
+};
+
+struct dynpat { /* structure specifying patterns for dynlib's */
+ struct dynpat *next;
+ const char **libpat; /* array of patterns for library names */
+ const char **sympat; /* array of patterns for symbol names */
+ int nlibpat; /* number of library patterns */
+ int nsympat; /* number of symbol patterns */
+ char flag; /* 0 or BPT_HANG */
+ char exclude_lib; /* if true, exclude these libraries */
+ char exclude; /* if true, exclude these functions */
+ char internal; /* if true, trace internal calls */
+ struct dynlib *Dp; /* set to the dynlib instance when searching */
+};
+
+extern struct dynlib *Dynlib; /* for tracing functions in shared libraries */
+extern struct dynpat *Dynpat;
+extern struct dynpat *Lastpat;
+extern struct bkpt **bpt_hashtable; /* breakpoint hash table */
+extern uint_t nthr_create; /* number of thr_create() calls seen so far */
+
+struct callstack {
+ struct callstack *next;
+ uintptr_t stkbase; /* stkbase < stkend */
+ uintptr_t stkend; /* stkend == base + size */
+ prgreg_t tref; /* %g7 (sparc) or %gs (intel) */
+ id_t tid; /* thread-id */
+ uint_t nthr_create; /* value of nthr_create last time we looked */
+ uint_t ncall; /* number of elements in stack */
+ uint_t maxcall; /* max elements in stack (malloc'd) */
+ struct {
+ uintptr_t sp; /* %sp for function call */
+ uintptr_t pc; /* value of the return %pc */
+ struct bkpt *fcn; /* name of function called */
+ } *stack; /* pointer to the call stack info */
+};
+
+extern struct callstack *callstack; /* the callstack list */
+extern uint_t nstack; /* number of detected stacks */
+extern rd_agent_t *Rdb_agent; /* run-time linker debug handle */
+extern td_thragent_t *Thr_agent; /* thread debug handle */
+extern int not_consist; /* used while rebuilding breakpoint table */
+extern int delete_library; /* used while rebuilding breakpoint table */
+
+extern pid_t ancestor; /* top-level parent process id */
+extern int descendent; /* TRUE iff descendent of top level */
+extern int is_vfork_child; /* TRUE iff process is a vfork()ed child */
+
+extern int ngrab; /* number of pid's that were grabbed */
+
+extern struct ps_prochandle *Proc; /* global reference to process */
+extern int data_model; /* PR_MODEL_LP64 or PR_MODEL_ILP32 */
+
+extern long pagesize; /* bytes per page; should be per-process */
+
+extern int exit_called; /* _exit() syscall was seen */
+
+extern lwpid_t primary_lwp; /* representative lwp on process grab */
+
+extern sysset_t syshang; /* sys calls to make process hang */
+extern sigset_t sighang; /* signals to make process hang */
+extern fltset_t flthang; /* faults to make process hang */
+
+extern sigset_t emptyset; /* no signals, for thr_sigsetmask() */
+extern sigset_t fillset; /* all signals, for thr_sigsetmask() */
+
+extern int leave_hung; /* if TRUE, leave the process hung */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RAMDATA_H */
diff --git a/usr/src/cmd/truss/stat.c b/usr/src/cmd/truss/stat.c
new file mode 100644
index 0000000..f5ecab0
--- /dev/null
+++ b/usr/src/cmd/truss/stat.c
@@ -0,0 +1,192 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
+/* All Rights Reserved */
+
+#define _SYSCALL32
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/signal.h>
+#include <sys/fault.h>
+#include <sys/syscall.h>
+#include <libproc.h>
+#include "ramdata.h"
+#include "proto.h"
+
+void show_stat32(private_t *, long);
+#ifdef _LP64
+void show_stat64(private_t *, long);
+#endif
+
+void
+show_stat(private_t *pri, long offset)
+{
+#ifdef _LP64
+ if (data_model == PR_MODEL_LP64)
+ show_stat64(pri, offset);
+ else
+ show_stat32(pri, offset);
+#else
+ show_stat32(pri, offset);
+#endif
+}
+
+void
+show_stat32(private_t *pri, long offset)
+{
+ struct stat32 statb;
+ timestruc_t ts;
+
+ if (offset != NULL &&
+ Pread(Proc, &statb, sizeof (statb), offset) == sizeof (statb)) {
+ (void) printf(
+ "%s d=0x%.8X i=%-5u m=0%.6o l=%-2u u=%-5u g=%-5u",
+ pri->pname,
+ statb.st_dev,
+ statb.st_ino,
+ statb.st_mode,
+ statb.st_nlink,
+ statb.st_uid,
+ statb.st_gid);
+
+ switch (statb.st_mode & S_IFMT) {
+ case S_IFCHR:
+ case S_IFBLK:
+ (void) printf(" rdev=0x%.8X\n", statb.st_rdev);
+ break;
+ default:
+ (void) printf(" sz=%u\n", statb.st_size);
+ break;
+ }
+
+ TIMESPEC32_TO_TIMESPEC(&ts, &statb.st_atim);
+ prtimestruc(pri, "at = ", &ts);
+ TIMESPEC32_TO_TIMESPEC(&ts, &statb.st_mtim);
+ prtimestruc(pri, "mt = ", &ts);
+ TIMESPEC32_TO_TIMESPEC(&ts, &statb.st_ctim);
+ prtimestruc(pri, "ct = ", &ts);
+
+ (void) printf(
+ "%s bsz=%-5d blks=%-5d fs=%.*s\n",
+ pri->pname,
+ statb.st_blksize,
+ statb.st_blocks,
+ _ST_FSTYPSZ,
+ statb.st_fstype);
+ }
+}
+
+void
+show_stat64_32(private_t *pri, long offset)
+{
+ struct stat64_32 statb;
+ timestruc_t ts;
+
+ if (offset != NULL &&
+ Pread(Proc, &statb, sizeof (statb), offset) == sizeof (statb)) {
+ (void) printf(
+ "%s d=0x%.8X i=%-5llu m=0%.6o l=%-2u u=%-5u g=%-5u",
+ pri->pname,
+ statb.st_dev,
+ (u_longlong_t)statb.st_ino,
+ statb.st_mode,
+ statb.st_nlink,
+ statb.st_uid,
+ statb.st_gid);
+
+ switch (statb.st_mode & S_IFMT) {
+ case S_IFCHR:
+ case S_IFBLK:
+ (void) printf(" rdev=0x%.8X\n", statb.st_rdev);
+ break;
+ default:
+ (void) printf(" sz=%llu\n", (long long)statb.st_size);
+ break;
+ }
+
+ TIMESPEC32_TO_TIMESPEC(&ts, &statb.st_atim);
+ prtimestruc(pri, "at = ", &ts);
+ TIMESPEC32_TO_TIMESPEC(&ts, &statb.st_mtim);
+ prtimestruc(pri, "mt = ", &ts);
+ TIMESPEC32_TO_TIMESPEC(&ts, &statb.st_ctim);
+ prtimestruc(pri, "ct = ", &ts);
+
+ (void) printf("%s bsz=%-5d blks=%-5lld fs=%.*s\n",
+ pri->pname,
+ statb.st_blksize,
+ (longlong_t)statb.st_blocks,
+ _ST_FSTYPSZ,
+ statb.st_fstype);
+ }
+}
+
+#ifdef _LP64
+void
+show_stat64(private_t *pri, long offset)
+{
+ struct stat64 statb;
+
+ if (offset != NULL &&
+ Pread(Proc, &statb, sizeof (statb), offset) == sizeof (statb)) {
+ (void) printf(
+ "%s d=0x%.16lX i=%-5lu m=0%.6o l=%-2u u=%-5u g=%-5u",
+ pri->pname,
+ statb.st_dev,
+ statb.st_ino,
+ statb.st_mode,
+ statb.st_nlink,
+ statb.st_uid,
+ statb.st_gid);
+
+ switch (statb.st_mode & S_IFMT) {
+ case S_IFCHR:
+ case S_IFBLK:
+ (void) printf(" rdev=0x%.16lX\n", statb.st_rdev);
+ break;
+ default:
+ (void) printf(" sz=%lu\n", statb.st_size);
+ break;
+ }
+
+ prtimestruc(pri, "at = ", (timestruc_t *)&statb.st_atim);
+ prtimestruc(pri, "mt = ", (timestruc_t *)&statb.st_mtim);
+ prtimestruc(pri, "ct = ", (timestruc_t *)&statb.st_ctim);
+
+ (void) printf(
+ "%s bsz=%-5d blks=%-5ld fs=%.*s\n",
+ pri->pname,
+ statb.st_blksize,
+ statb.st_blocks,
+ _ST_FSTYPSZ,
+ statb.st_fstype);
+ }
+}
+#endif /* _LP64 */
diff --git a/usr/src/cmd/truss/systable.c b/usr/src/cmd/truss/systable.c
new file mode 100644
index 0000000..3cd07c6
--- /dev/null
+++ b/usr/src/cmd/truss/systable.c
@@ -0,0 +1,1736 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
+ */
+
+/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
+/* All Rights Reserved */
+
+/* Copyright (c) 2013, OmniTI Computer Consulting, Inc. All rights reserved. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <libproc.h>
+#include <sys/aio.h>
+#include <sys/port_impl.h>
+#include "ramdata.h"
+#include "systable.h"
+#include "print.h"
+#include "proto.h"
+
+/*
+ * Tables of information about system calls - read-only data.
+ */
+
+const char *const errcode[] = { /* error code names */
+ NULL, /* 0 */
+ "EPERM", /* 1 */
+ "ENOENT", /* 2 */
+ "ESRCH", /* 3 */
+ "EINTR", /* 4 */
+ "EIO", /* 5 */
+ "ENXIO", /* 6 */
+ "E2BIG", /* 7 */
+ "ENOEXEC", /* 8 */
+ "EBADF", /* 9 */
+ "ECHILD", /* 10 */
+ "EAGAIN", /* 11 */
+ "ENOMEM", /* 12 */
+ "EACCES", /* 13 */
+ "EFAULT", /* 14 */
+ "ENOTBLK", /* 15 */
+ "EBUSY", /* 16 */
+ "EEXIST", /* 17 */
+ "EXDEV", /* 18 */
+ "ENODEV", /* 19 */
+ "ENOTDIR", /* 20 */
+ "EISDIR", /* 21 */
+ "EINVAL", /* 22 */
+ "ENFILE", /* 23 */
+ "EMFILE", /* 24 */
+ "ENOTTY", /* 25 */
+ "ETXTBSY", /* 26 */
+ "EFBIG", /* 27 */
+ "ENOSPC", /* 28 */
+ "ESPIPE", /* 29 */
+ "EROFS", /* 30 */
+ "EMLINK", /* 31 */
+ "EPIPE", /* 32 */
+ "EDOM", /* 33 */
+ "ERANGE", /* 34 */
+ "ENOMSG", /* 35 */
+ "EIDRM", /* 36 */
+ "ECHRNG", /* 37 */
+ "EL2NSYNC", /* 38 */
+ "EL3HLT", /* 39 */
+ "EL3RST", /* 40 */
+ "ELNRNG", /* 41 */
+ "EUNATCH", /* 42 */
+ "ENOCSI", /* 43 */
+ "EL2HLT", /* 44 */
+ "EDEADLK", /* 45 */
+ "ENOLCK", /* 46 */
+ "ECANCELED", /* 47 */
+ "ENOTSUP", /* 48 */
+ "EDQUOT", /* 49 */
+ "EBADE", /* 50 */
+ "EBADR", /* 51 */
+ "EXFULL", /* 52 */
+ "ENOANO", /* 53 */
+ "EBADRQC", /* 54 */
+ "EBADSLT", /* 55 */
+ "EDEADLOCK", /* 56 */
+ "EBFONT", /* 57 */
+ "EOWNERDEAD", /* 58 */
+ "ENOTRECOVERABLE", /* 59 */
+ "ENOSTR", /* 60 */
+ "ENODATA", /* 61 */
+ "ETIME", /* 62 */
+ "ENOSR", /* 63 */
+ "ENONET", /* 64 */
+ "ENOPKG", /* 65 */
+ "EREMOTE", /* 66 */
+ "ENOLINK", /* 67 */
+ "EADV", /* 68 */
+ "ESRMNT", /* 69 */
+ "ECOMM", /* 70 */
+ "EPROTO", /* 71 */
+ "ELOCKUNMAPPED", /* 72 */
+ "ENOTACTIVE", /* 73 */
+ "EMULTIHOP", /* 74 */
+ NULL, /* 75 */
+ NULL, /* 76 */
+ "EBADMSG", /* 77 */
+ "ENAMETOOLONG", /* 78 */
+ "EOVERFLOW", /* 79 */
+ "ENOTUNIQ", /* 80 */
+ "EBADFD", /* 81 */
+ "EREMCHG", /* 82 */
+ "ELIBACC", /* 83 */
+ "ELIBBAD", /* 84 */
+ "ELIBSCN", /* 85 */
+ "ELIBMAX", /* 86 */
+ "ELIBEXEC", /* 87 */
+ "EILSEQ", /* 88 */
+ "ENOSYS", /* 89 */
+ "ELOOP", /* 90 */
+ "ERESTART", /* 91 */
+ "ESTRPIPE", /* 92 */
+ "ENOTEMPTY", /* 93 */
+ "EUSERS", /* 94 */
+ "ENOTSOCK", /* 95 */
+ "EDESTADDRREQ", /* 96 */
+ "EMSGSIZE", /* 97 */
+ "EPROTOTYPE", /* 98 */
+ "ENOPROTOOPT", /* 99 */
+ NULL, /* 100 */
+ NULL, /* 101 */
+ NULL, /* 102 */
+ NULL, /* 103 */
+ NULL, /* 104 */
+ NULL, /* 105 */
+ NULL, /* 106 */
+ NULL, /* 107 */
+ NULL, /* 108 */
+ NULL, /* 109 */
+ NULL, /* 110 */
+ NULL, /* 111 */
+ NULL, /* 112 */
+ NULL, /* 113 */
+ NULL, /* 114 */
+ NULL, /* 115 */
+ NULL, /* 116 */
+ NULL, /* 117 */
+ NULL, /* 118 */
+ NULL, /* 119 */
+ "EPROTONOSUPPORT", /* 120 */
+ "ESOCKTNOSUPPORT", /* 121 */
+ "EOPNOTSUPP", /* 122 */
+ "EPFNOSUPPORT", /* 123 */
+ "EAFNOSUPPORT", /* 124 */
+ "EADDRINUSE", /* 125 */
+ "EADDRNOTAVAIL", /* 126 */
+ "ENETDOWN", /* 127 */
+ "ENETUNREACH", /* 128 */
+ "ENETRESET", /* 129 */
+ "ECONNABORTED", /* 130 */
+ "ECONNRESET", /* 131 */
+ "ENOBUFS", /* 132 */
+ "EISCONN", /* 133 */
+ "ENOTCONN", /* 134 */
+ NULL, /* 135 */
+ NULL, /* 136 */
+ NULL, /* 137 */
+ NULL, /* 138 */
+ NULL, /* 139 */
+ NULL, /* 140 */
+ NULL, /* 141 */
+ NULL, /* 142 */
+ "ESHUTDOWN", /* 143 */
+ "ETOOMANYREFS", /* 144 */
+ "ETIMEDOUT", /* 145 */
+ "ECONNREFUSED", /* 146 */
+ "EHOSTDOWN", /* 147 */
+ "EHOSTUNREACH", /* 148 */
+ "EALREADY", /* 149 */
+ "EINPROGRESS", /* 150 */
+ "ESTALE" /* 151 */
+};
+
+#define NERRCODE (sizeof (errcode) / sizeof (char *))
+
+
+const char *
+errname(int err) /* return the error code name (NULL if none) */
+{
+ const char *ename = NULL;
+
+ if (err >= 0 && err < NERRCODE)
+ ename = errcode[err];
+
+ return (ename);
+}
+
+
+const struct systable systable[] = {
+{ NULL, 8, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX},
+{"_exit", 1, DEC, NOV, DEC}, /* 1 */
+{ NULL, 8, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX},
+{"read", 3, DEC, NOV, DEC, IOB, UNS}, /* 3 */
+{"write", 3, DEC, NOV, DEC, IOB, UNS}, /* 4 */
+{"open", 3, DEC, NOV, STG, OPN, OCT}, /* 5 */
+{"close", 1, DEC, NOV, DEC}, /* 6 */
+{"linkat", 5, DEC, NOV, ATC, STG, ATC, STG, SNF}, /* 7 */
+{ NULL, 8, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX},
+{"link", 2, DEC, NOV, STG, STG}, /* 9 */
+{"unlink", 1, DEC, NOV, STG}, /* 10 */
+{"symlinkat", 3, DEC, NOV, STG, ATC, STG}, /* 11 */
+{"chdir", 1, DEC, NOV, STG}, /* 12 */
+{"time", 0, DEC, NOV}, /* 13 */
+{"mknod", 3, DEC, NOV, STG, OCT, HEX}, /* 14 */
+{"chmod", 2, DEC, NOV, STG, OCT}, /* 15 */
+{"chown", 3, DEC, NOV, STG, DEC, DEC}, /* 16 */
+{"brk", 1, DEC, NOV, HEX}, /* 17 */
+{"stat", 2, DEC, NOV, STG, HEX}, /* 18 */
+{"lseek", 3, DEC, NOV, DEC, DEX, WHN}, /* 19 */
+{"getpid", 0, DEC, DEC}, /* 20 */
+{"mount", 8, DEC, NOV, STG, STG, MTF, MFT, HEX, DEC, HEX, DEC}, /* 21 */
+{"readlinkat", 4, DEC, NOV, ATC, STG, RLK, UNS}, /* 22 */
+{"setuid", 1, DEC, NOV, UNS}, /* 23 */
+{"getuid", 0, UNS, UNS}, /* 24 */
+{"stime", 1, DEC, NOV, DEC}, /* 25 */
+{"pcsample", 2, DEC, NOV, HEX, DEC}, /* 26 */
+{"alarm", 1, DEC, NOV, UNS}, /* 27 */
+{"fstat", 2, DEC, NOV, DEC, HEX}, /* 28 */
+{"pause", 0, DEC, NOV}, /* 29 */
+{ NULL, 8, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX},
+{"stty", 2, DEC, NOV, DEC, DEC}, /* 31 */
+{"gtty", 2, DEC, NOV, DEC, DEC}, /* 32 */
+{"access", 2, DEC, NOV, STG, ACC}, /* 33 */
+{"nice", 1, DEC, NOV, DEC}, /* 34 */
+{"statfs", 4, DEC, NOV, STG, HEX, DEC, DEC}, /* 35 */
+{"sync", 0, DEC, NOV}, /* 36 */
+{"kill", 2, DEC, NOV, DEC, SIG}, /* 37 */
+{"fstatfs", 4, DEC, NOV, DEC, HEX, DEC, DEC}, /* 38 */
+{"pgrpsys", 3, DEC, NOV, DEC, DEC, DEC}, /* 39 */
+{"uucopystr", 3, DEC, NOV, STG, RST, UNS}, /* 40 */
+{ NULL, 8, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX},
+{"pipe", 2, DEC, NOV, PFD, PIP}, /* 42 */
+{"times", 1, DEC, NOV, HEX}, /* 43 */
+{"profil", 4, DEC, NOV, HEX, UNS, HEX, OCT}, /* 44 */
+{"faccessat", 4, DEC, NOV, ATC, STG, ACC, FAT}, /* 45 */
+{"setgid", 1, DEC, NOV, UNS}, /* 46 */
+{"getgid", 0, UNS, UNS}, /* 47 */
+{"mknodat", 4, DEC, NOV, ATC, STG, OCT, HEX}, /* 48 */
+{"msgsys", 6, DEC, NOV, DEC, DEC, DEC, DEC, DEC, DEC}, /* 49 */
+{"sysi86", 4, HEX, NOV, S86, HEX, HEX, HEX, DEC, DEC}, /* 50 */
+{"acct", 1, DEC, NOV, STG}, /* 51 */
+{"shmsys", 4, DEC, NOV, DEC, HEX, HEX, HEX}, /* 52 */
+{"semsys", 5, DEC, NOV, DEC, HEX, HEX, HEX, HEX}, /* 53 */
+{"ioctl", 3, DEC, NOV, DEC, IOC, IOA}, /* 54 */
+{"uadmin", 3, DEC, NOV, DEC, DEC, DEC}, /* 55 */
+{"fchownat", 5, DEC, NOV, ATC, STG, DEC, DEC, SNF}, /* 56 */
+{"utssys", 4, DEC, NOV, HEX, DEC, UTS, HEX}, /* 57 */
+{"fdsync", 2, DEC, NOV, DEC, FFG}, /* 58 */
+{"execve", 3, DEC, NOV, STG, HEX, HEX}, /* 59 */
+{"umask", 1, OCT, NOV, OCT}, /* 60 */
+{"chroot", 1, DEC, NOV, STG}, /* 61 */
+{"fcntl", 3, DEC, NOV, DEC, FCN, HEX}, /* 62 */
+{"ulimit", 2, DEX, NOV, ULM, DEC}, /* 63 */
+{"renameat", 4, DEC, NOV, ATC, STG, ATC, STG}, /* 64 */
+{"unlinkat", 3, DEC, NOV, ATC, STG, UAT}, /* 65 */
+{"fstatat", 4, DEC, NOV, ATC, STG, HEX, SNF}, /* 66 */
+{"fstatat64", 4, DEC, NOV, ATC, STG, HEX, SNF}, /* 67 */
+{"openat", 4, DEC, NOV, ATC, STG, OPN, OCT}, /* 68 */
+{"openat64", 4, DEC, NOV, ATC, STG, OPN, OCT}, /* 69 */
+{"tasksys", 5, DEC, NOV, DEC, DEC, DEC, HEX, DEC}, /* 70 */
+{"acctctl", 3, DEC, NOV, HEX, HEX, UNS}, /* 71 */
+{"exacctsys", 6, DEC, NOV, DEC, IDT, DEC, HEX, DEC, HEX}, /* 72 */
+{"getpagesizes", 2, DEC, NOV, HEX, DEC}, /* 73 */
+{"rctlsys", 6, DEC, NOV, RSC, STG, HEX, HEX, DEC, DEC}, /* 74 */
+{"sidsys", 4, UNS, UNS, DEC, DEC, DEC, DEC}, /* 75 */
+{ NULL, 8, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX},
+{"lwp_park", 3, DEC, NOV, DEC, HEX, DEC}, /* 77 */
+{"sendfilev", 5, DEC, NOV, DEC, DEC, HEX, DEC, HEX}, /* 78 */
+{"rmdir", 1, DEC, NOV, STG}, /* 79 */
+{"mkdir", 2, DEC, NOV, STG, OCT}, /* 80 */
+{"getdents", 3, DEC, NOV, DEC, HEX, UNS}, /* 81 */
+{"privsys", 5, HEX, NOV, DEC, DEC, DEC, HEX, DEC}, /* 82 */
+{"ucredsys", 3, DEC, NOV, DEC, DEC, HEX}, /* 83 */
+{"sysfs", 3, DEC, NOV, SFS, DEX, DEX}, /* 84 */
+{"getmsg", 4, DEC, NOV, DEC, HEX, HEX, HEX}, /* 85 */
+{"putmsg", 4, DEC, NOV, DEC, HEX, HEX, SMF}, /* 86 */
+{ NULL, 8, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX},
+{"lstat", 2, DEC, NOV, STG, HEX}, /* 88 */
+{"symlink", 2, DEC, NOV, STG, STG}, /* 89 */
+{"readlink", 3, DEC, NOV, STG, RLK, UNS}, /* 90 */
+{"setgroups", 2, DEC, NOV, DEC, HEX}, /* 91 */
+{"getgroups", 2, DEC, NOV, DEC, HEX}, /* 92 */
+{"fchmod", 2, DEC, NOV, DEC, OCT}, /* 93 */
+{"fchown", 3, DEC, NOV, DEC, DEC, DEC}, /* 94 */
+{"sigprocmask", 3, DEC, NOV, SPM, HEX, HEX}, /* 95 */
+{"sigsuspend", 1, DEC, NOV, HEX}, /* 96 */
+{"sigaltstack", 2, DEC, NOV, HEX, HEX}, /* 97 */
+{"sigaction", 3, DEC, NOV, SIG, HEX, HEX}, /* 98 */
+{"sigpendsys", 2, DEC, NOV, DEC, HEX}, /* 99 */
+{"context", 2, DEC, NOV, DEC, HEX}, /* 100 */
+{"fchmodat", 4, DEC, NOV, ATC, STG, OCT, SNF}, /* 101 */
+{"mkdirat", 3, DEC, NOV, ATC, STG, OCT}, /* 102 */
+{"statvfs", 2, DEC, NOV, STG, HEX}, /* 103 */
+{"fstatvfs", 2, DEC, NOV, DEC, HEX}, /* 104 */
+{"getloadavg", 2, DEC, NOV, HEX, DEC}, /* 105 */
+{"nfssys", 2, DEC, NOV, DEC, HEX}, /* 106 */
+{"waitid", 4, DEC, NOV, IDT, DEC, HEX, WOP}, /* 107 */
+{"sigsendsys", 2, DEC, NOV, HEX, SIG}, /* 108 */
+{"hrtsys", 5, DEC, NOV, DEC, HEX, HEX, HEX, HEX}, /* 109 */
+{"utimesys", 5, DEC, NOV, DEC, HEX, HEX, HEX, HEX}, /* 110 */
+{"sigresend", 3, DEC, NOV, SIG, HEX, HEX}, /* 111 */
+{"priocntlsys", 5, DEC, NOV, DEC, HEX, DEC, PC4, PC5}, /* 112 */
+{"pathconf", 2, DEC, NOV, STG, PTC}, /* 113 */
+{"mincore", 3, DEC, NOV, HEX, UNS, HEX}, /* 114 */
+{"mmap", 6, HEX, NOV, HEX, UNS, MPR, MTY, DEC, DEC}, /* 115 */
+{"mprotect", 3, DEC, NOV, HEX, UNS, MPR}, /* 116 */
+{"munmap", 2, DEC, NOV, HEX, UNS}, /* 117 */
+{"fpathconf", 2, DEC, NOV, DEC, PTC}, /* 118 */
+{"vfork", 0, DEC, NOV}, /* 119 */
+{"fchdir", 1, DEC, NOV, DEC}, /* 120 */
+{"readv", 3, DEC, NOV, DEC, HEX, DEC}, /* 121 */
+{"writev", 3, DEC, NOV, DEC, HEX, DEC}, /* 122 */
+{ NULL, 8, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX},
+{ NULL, 8, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX},
+{ NULL, 8, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX},
+{ NULL, 8, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX},
+{"mmapobj", 5, DEC, NOV, DEC, MOB, HEX, HEX, HEX}, /* 127 */
+{"setrlimit", 2, DEC, NOV, RLM, HEX}, /* 128 */
+{"getrlimit", 2, DEC, NOV, RLM, HEX}, /* 129 */
+{"lchown", 3, DEC, NOV, STG, DEC, DEC}, /* 130 */
+{"memcntl", 6, DEC, NOV, HEX, UNS, MCF, MC4, MC5, DEC}, /* 131 */
+{"getpmsg", 5, DEC, NOV, DEC, HEX, HEX, HEX, HEX}, /* 132 */
+{"putpmsg", 5, DEC, NOV, DEC, HEX, HEX, DEC, HHX}, /* 133 */
+{"rename", 2, DEC, NOV, STG, STG}, /* 134 */
+{"uname", 1, DEC, NOV, HEX}, /* 135 */
+{"setegid", 1, DEC, NOV, UNS}, /* 136 */
+{"sysconfig", 1, DEC, NOV, CNF}, /* 137 */
+{"adjtime", 2, DEC, NOV, HEX, HEX}, /* 138 */
+{"sysinfo", 3, DEC, NOV, INF, RST, DEC}, /* 139 */
+{"sharefs", 3, DEC, NOV, DEC, HEX, DEC}, /* 140 */
+{"seteuid", 1, DEC, NOV, UNS}, /* 141 */
+{"forksys", 2, DEC, NOV, DEC, HHX}, /* 142 */
+{ NULL, 8, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX},
+{"sigtimedwait", 3, DEC, NOV, HEX, HEX, HEX}, /* 144 */
+{"lwp_info", 1, DEC, NOV, HEX}, /* 145 */
+{"yield", 0, DEC, NOV}, /* 146 */
+{ NULL, 8, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX},
+{"lwp_sema_post", 1, DEC, NOV, HEX}, /* 148 */
+{"lwp_sema_trywait", 1, DEC, NOV, HEX}, /* 149 */
+{"lwp_detach", 1, DEC, NOV, DEC}, /* 150 */
+{"corectl", 4, DEC, NOV, DEC, HEX, HEX, HEX}, /* 151 */
+{"modctl", 5, DEC, NOV, MOD, HEX, HEX, HEX, HEX}, /* 152 */
+{"fchroot", 1, DEC, NOV, DEC}, /* 153 */
+{ NULL, 8, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX},
+{"vhangup", 0, DEC, NOV}, /* 155 */
+{"gettimeofday", 1, DEC, NOV, HEX}, /* 156 */
+{"getitimer", 2, DEC, NOV, ITM, HEX}, /* 157 */
+{"setitimer", 3, DEC, NOV, ITM, HEX, HEX}, /* 158 */
+{"lwp_create", 3, DEC, NOV, HEX, LWF, HEX}, /* 159 */
+{"lwp_exit", 0, DEC, NOV}, /* 160 */
+{"lwp_suspend", 1, DEC, NOV, DEC}, /* 161 */
+{"lwp_continue", 1, DEC, NOV, DEC}, /* 162 */
+{"lwp_kill", 2, DEC, NOV, DEC, SIG}, /* 163 */
+{"lwp_self", 0, DEC, NOV}, /* 164 */
+{"lwp_sigmask", 5, HEX, HEX, SPM, HEX, HEX, HEX, HEX}, /* 165 */
+{"lwp_private", 3, HEX, NOV, DEC, DEC, HEX}, /* 166 */
+{"lwp_wait", 2, DEC, NOV, DEC, HEX}, /* 167 */
+{"lwp_mutex_wakeup", 2, DEC, NOV, HEX, DEC}, /* 168 */
+{ NULL, 8, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX},
+{"lwp_cond_wait", 4, DEC, NOV, HEX, HEX, HEX, DEC}, /* 170 */
+{"lwp_cond_signal", 1, DEC, NOV, HEX}, /* 171 */
+{"lwp_cond_broadcast", 1, DEC, NOV, HEX}, /* 172 */
+{"pread", 4, DEC, NOV, DEC, IOB, UNS, DEX}, /* 173 */
+{"pwrite", 4, DEC, NOV, DEC, IOB, UNS, DEX}, /* 174 */
+{"llseek", 4, LLO, NOV, DEC, LLO, HID, WHN}, /* 175 */
+{"inst_sync", 2, DEC, NOV, STG, DEC}, /* 176 */
+{"brand", 6, DEC, NOV, DEC, HEX, HEX, HEX, HEX, HEX}, /* 177 */
+{"kaio", 7, DEC, NOV, AIO, HEX, HEX, HEX, HEX, HEX, HEX}, /* 178 */
+{"cpc", 5, DEC, NOV, CPC, DEC, HEX, HEX, HEX}, /* 179 */
+{"lgrpsys", 3, DEC, NOV, DEC, DEC, HEX}, /* 180 */
+{"rusagesys", 5, DEC, NOV, DEC, HEX, DEC, HEX, HEX}, /* 181 */
+{"portfs", 6, HEX, HEX, DEC, HEX, HEX, HEX, HEX, HEX}, /* 182 */
+{"pollsys", 4, DEC, NOV, HEX, DEC, HEX, HEX}, /* 183 */
+{"labelsys", 2, DEC, NOV, DEC, HEX}, /* 184 */
+{"acl", 4, DEC, NOV, STG, ACL, DEC, HEX}, /* 185 */
+{"auditsys", 4, DEC, NOV, AUD, HEX, HEX, HEX}, /* 186 */
+{"processor_bind", 4, DEC, NOV, IDT, DEC, DEC, HEX}, /* 187 */
+{"processor_info", 2, DEC, NOV, DEC, HEX}, /* 188 */
+{"p_online", 2, DEC, NOV, DEC, DEC}, /* 189 */
+{"sigqueue", 5, DEC, NOV, DEC, SIG, HEX, SQC, DEC}, /* 190 */
+{"clock_gettime", 2, DEC, NOV, DEC, HEX}, /* 191 */
+{"clock_settime", 2, DEC, NOV, DEC, HEX}, /* 192 */
+{"clock_getres", 2, DEC, NOV, DEC, HEX}, /* 193 */
+{"timer_create", 3, DEC, NOV, DEC, HEX, HEX}, /* 194 */
+{"timer_delete", 1, DEC, NOV, DEC}, /* 195 */
+{"timer_settime", 4, DEC, NOV, DEC, DEC, HEX, HEX}, /* 196 */
+{"timer_gettime", 2, DEC, NOV, DEC, HEX}, /* 197 */
+{"timer_getoverrun", 1, DEC, NOV, DEC}, /* 198 */
+{"nanosleep", 2, DEC, NOV, HEX, HEX}, /* 199 */
+{"facl", 4, DEC, NOV, DEC, ACL, DEC, HEX}, /* 200 */
+{"door", 6, DEC, NOV, DEC, HEX, HEX, HEX, HEX, DEC}, /* 201 */
+{"setreuid", 2, DEC, NOV, UN1, UN1}, /* 202 */
+{"setregid", 2, DEC, NOV, UN1, UN1}, /* 203 */
+{"install_utrap", 3, DEC, NOV, DEC, HEX, HEX}, /* 204 */
+{"signotify", 3, DEC, NOV, DEC, HEX, HEX}, /* 205 */
+{"schedctl", 0, HEX, NOV}, /* 206 */
+{"pset", 5, DEC, NOV, DEC, HEX, HEX, HEX, HEX}, /* 207 */
+{"sparc_utrap_install", 5, DEC, NOV, UTT, UTH, UTH, HEX, HEX}, /* 208 */
+{"resolvepath", 3, DEC, NOV, STG, RLK, DEC}, /* 209 */
+{"lwp_mutex_timedlock", 3, DEC, NOV, HEX, HEX, HEX}, /* 210 */
+{"lwp_sema_timedwait", 3, DEC, NOV, HEX, HEX, DEC}, /* 211 */
+{"lwp_rwlock_sys", 3, DEC, NOV, DEC, HEX, HEX}, /* 212 */
+{"getdents64", 3, DEC, NOV, DEC, HEX, UNS}, /* 213 */
+{"mmap64", 7, HEX, NOV, HEX, UNS, MPR, MTY, DEC, LLO, HID}, /* 214 */
+{"stat64", 2, DEC, NOV, STG, HEX}, /* 215 */
+{"lstat64", 2, DEC, NOV, STG, HEX}, /* 216 */
+{"fstat64", 2, DEC, NOV, DEC, HEX}, /* 217 */
+{"statvfs64", 2, DEC, NOV, STG, HEX}, /* 218 */
+{"fstatvfs64", 2, DEC, NOV, DEC, HEX}, /* 219 */
+{"setrlimit64", 2, DEC, NOV, RLM, HEX}, /* 220 */
+{"getrlimit64", 2, DEC, NOV, RLM, HEX}, /* 221 */
+{"pread64", 5, DEC, NOV, DEC, IOB, UNS, LLO, HID}, /* 222 */
+{"pwrite64", 5, DEC, NOV, DEC, IOB, UNS, LLO, HID}, /* 223 */
+{ NULL, 8, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX},
+{"open64", 3, DEC, NOV, STG, OPN, OCT}, /* 225 */
+{"rpcmod", 3, DEC, NOV, DEC, HEX}, /* 226 */
+{"zone", 5, DEC, NOV, DEC, HEX, HEX, HEX, HEX}, /* 227 */
+{"autofssys", 2, DEC, NOV, DEC, HEX}, /* 228 */
+{"getcwd", 3, DEC, NOV, RST, DEC}, /* 229 */
+{"so_socket", 5, DEC, NOV, PFM, SKT, SKP, STG, SKV}, /* 230 */
+{"so_socketpair", 1, DEC, NOV, HEX}, /* 231 */
+{"bind", 4, DEC, NOV, DEC, HEX, DEC, SKV}, /* 232 */
+{"listen", 3, DEC, NOV, DEC, DEC, SKV}, /* 233 */
+{"accept", 5, DEC, NOV, DEC, HEX, HEX, SKV, ACF}, /* 234 */
+{"connect", 4, DEC, NOV, DEC, HEX, DEC, SKV}, /* 235 */
+{"shutdown", 3, DEC, NOV, DEC, SHT, SKV}, /* 236 */
+{"recv", 4, DEC, NOV, DEC, IOB, DEC, DEC}, /* 237 */
+{"recvfrom", 6, DEC, NOV, DEC, IOB, DEC, DEC, HEX, HEX}, /* 238 */
+{"recvmsg", 3, DEC, NOV, DEC, HEX, DEC}, /* 239 */
+{"send", 4, DEC, NOV, DEC, IOB, DEC, DEC}, /* 240 */
+{"sendmsg", 3, DEC, NOV, DEC, HEX, DEC}, /* 241 */
+{"sendto", 6, DEC, NOV, DEC, IOB, DEC, DEC, HEX, DEC}, /* 242 */
+{"getpeername", 4, DEC, NOV, DEC, HEX, HEX, SKV}, /* 243 */
+{"getsockname", 4, DEC, NOV, DEC, HEX, HEX, SKV}, /* 244 */
+{"getsockopt", 6, DEC, NOV, DEC, SOL, SON, HEX, HEX, SKV}, /* 245 */
+{"setsockopt", 6, DEC, NOV, DEC, SOL, SON, HEX, DEC, SKV}, /* 246 */
+{"sockconfig", 5, DEC, NOV, DEC, HEX, HEX, HEX, HEX}, /* 247 */
+{"ntp_gettime", 1, DEC, NOV, HEX}, /* 248 */
+{"ntp_adjtime", 1, DEC, NOV, HEX}, /* 249 */
+{"lwp_mutex_unlock", 1, DEC, NOV, HEX}, /* 250 */
+{"lwp_mutex_trylock", 2, DEC, NOV, HEX, HEX}, /* 251 */
+{"lwp_mutex_register", 2, DEC, NOV, HEX, HEX}, /* 252 */
+{"cladm", 3, DEC, NOV, CLC, CLF, HEX}, /* 253 */
+{"uucopy", 3, DEC, NOV, HEX, HEX, UNS}, /* 254 */
+{"umount2", 2, DEC, NOV, STG, MTF}, /* 255 */
+{ NULL, -1, DEC, NOV},
+};
+
+/* SYSEND == max syscall number + 1 */
+#define SYSEND ((sizeof (systable) / sizeof (struct systable))-1)
+
+
+/*
+ * The following are for interpreting syscalls with sub-codes.
+ */
+
+const struct systable faccessattable[] = {
+{"faccessat", 4, DEC, NOV, ATC, STG, ACC, FAT}, /* 0 */
+{"access", 3, DEC, NOV, HID, STG, ACC}, /* 1 */
+};
+#define NACCESSCODE (sizeof (faccessattable) / sizeof (struct systable))
+
+const struct systable fchmodattable[] = {
+{"fchmodat", 4, DEC, NOV, ATC, STG, OCT, SNF}, /* 0 */
+{"chmod", 3, DEC, NOV, HID, STG, OCT}, /* 1 */
+{"fchmodat", 4, DEC, NOV, ATC, STG, OCT, SNF}, /* 2 */
+{"fchmod", 3, DEC, NOV, DEC, HID, OCT}, /* 3 */
+};
+#define NCHMODCODE (sizeof (fchmodattable) / sizeof (struct systable))
+
+const struct systable fchownattable[] = {
+{"fchownat", 5, DEC, NOV, ATC, STG, DEC, DEC, SNF}, /* 0 */
+{"chown", 4, DEC, NOV, HID, STG, DEC, DEC}, /* 1 */
+{"lchown", 4, DEC, NOV, HID, STG, DEC, DEC}, /* 2 */
+{"fchown", 4, DEC, NOV, DEC, HID, DEC, DEC}, /* 3 */
+};
+#define NCHOWNCODE (sizeof (fchownattable) / sizeof (struct systable))
+
+const struct systable mkdiratattable[] = {
+{"mkdirat", 3, DEC, NOV, ATC, STG, OCT}, /* 0 */
+{"mkdir", 3, DEC, NOV, HID, STG, OCT}, /* 1 */
+};
+#define NMKDIRCODE (sizeof (mkdiratattable) / sizeof (struct systable))
+
+const struct systable mknodatattable[] = {
+{"mknodat", 4, DEC, NOV, ATC, STG, OCT, HEX}, /* 0 */
+{"mknod", 4, DEC, NOV, HID, STG, OCT, HEX}, /* 1 */
+};
+#define NMKMODCODE (sizeof (mknodatattable) / sizeof (struct systable))
+
+const struct systable renameattable[] = {
+{"renameat", 4, DEC, NOV, ATC, STG, ATC, STG}, /* 0 */
+{"rename", 4, DEC, NOV, HID, STG, HID, STG}, /* 1 */
+};
+#define NRENAMECODE (sizeof (renameattable) / sizeof (struct systable))
+
+const struct systable linkattable[] = {
+{"linkat", 5, DEC, NOV, ATC, STG, ATC, STG, SNF}, /* 0 */
+{"link", 4, DEC, NOV, HID, STG, HID, STG}, /* 1 */
+};
+#define NLINKATCODE (sizeof (linkattable) / sizeof (struct systable))
+
+const struct systable unlinkattable[] = {
+{"unlinkat", 3, DEC, NOV, ATC, STG, UAT}, /* 0 */
+{"unlink", 2, DEC, NOV, HID, STG}, /* 1 */
+{"rmdir", 2, DEC, NOV, HID, STG}, /* 2 */
+};
+#define NUNLINKCODE (sizeof (unlinkattable) / sizeof (struct systable))
+
+const struct systable symlinkattable[] = {
+{"symlinkat", 3, DEC, NOV, STG, ATC, STG}, /* 0 */
+{"symlink", 3, DEC, NOV, STG, HID, STG}, /* 1 */
+};
+#define NSYMLINKCODE (sizeof (symlinkattable) / sizeof (struct systable))
+
+const struct systable readlinkattable[] = {
+{"readlinkat", 4, DEC, NOV, ATC, STG, RLK, UNS}, /* 0 */
+{"readlink", 4, DEC, NOV, HID, STG, RLK, UNS}, /* 1 */
+};
+#define NREADLINKCODE (sizeof (readlinkattable) / sizeof (struct systable))
+
+const struct systable fstatattable[] = {
+{"fstatat", 4, DEC, NOV, ATC, STG, HEX, SNF}, /* 0 */
+{"stat", 3, DEC, NOV, HID, STG, HEX}, /* 1 */
+{"lstat", 3, DEC, NOV, HID, STG, HEX}, /* 2 */
+{"fstat", 3, DEC, NOV, DEC, HID, HEX}, /* 3 */
+};
+#define NSTATCODE (sizeof (fstatattable) / sizeof (struct systable))
+
+const struct systable fstatat64table[] = {
+{"fstatat64", 4, DEC, NOV, ATC, STG, HEX, SNF}, /* 0 */
+{"stat64", 3, DEC, NOV, HID, STG, HEX}, /* 1 */
+{"lstat64", 3, DEC, NOV, HID, STG, HEX}, /* 2 */
+{"fstat64", 3, DEC, NOV, DEC, HID, HEX}, /* 3 */
+};
+#define NSTAT64CODE (sizeof (fstatat64table) / sizeof (struct systable))
+
+const struct systable openattable[] = {
+{"openat", 3, DEC, NOV, ATC, STG, OPN}, /* 0 */
+{"openat", 4, DEC, NOV, ATC, STG, OPN, OCT}, /* 1 */
+{"open", 3, DEC, NOV, HID, STG, OPN}, /* 2 */
+{"open", 4, DEC, NOV, HID, STG, OPN, OCT}, /* 3 */
+};
+#define NOPENATCODE (sizeof (openattable) / sizeof (struct systable))
+
+const struct systable openat64table[] = {
+{"openat64", 3, DEC, NOV, ATC, STG, OPN}, /* 0 */
+{"openat64", 4, DEC, NOV, ATC, STG, OPN, OCT}, /* 1 */
+{"open64", 3, DEC, NOV, HID, STG, OPN}, /* 2 */
+{"open64", 4, DEC, NOV, HID, STG, OPN, OCT}, /* 3 */
+};
+#define NOPENAT64CODE (sizeof (openat64table) / sizeof (struct systable))
+
+const struct systable opentable[] = {
+{"open", 2, DEC, NOV, STG, OPN}, /* 0 */
+{"open", 3, DEC, NOV, STG, OPN, OCT}, /* 1 */
+};
+#define NOPENCODE (sizeof (opentable) / sizeof (struct systable))
+
+const struct systable open64table[] = {
+{"open64", 2, DEC, NOV, STG, OPN}, /* 0 */
+{"open64", 3, DEC, NOV, STG, OPN, OCT}, /* 1 */
+};
+#define NOPEN64CODE (sizeof (open64table) / sizeof (struct systable))
+
+const struct systable fcntltable[] = {
+{"fcntl", 3, DEC, NOV, DEC, FCN, HEX}, /* 0: default */
+{"fcntl", 2, DEC, NOV, DEC, FCN}, /* 1: no arg */
+{"fcntl", 3, DEC, NOV, DEC, FCN, FFG}, /* 2: F_SETFL */
+};
+#define NFCNTLCODE (sizeof (fcntltable) / sizeof (struct systable))
+
+const struct systable msgtable[] = {
+{"msgget", 3, DEC, NOV, HID, KEY, MSF}, /* 0 */
+{"msgctl", 4, DEC, NOV, HID, DEC, MSC, HEX}, /* 1 */
+{"msgrcv", 6, DEC, NOV, HID, DEC, HEX, UNS, DEC, MSF}, /* 2 */
+{"msgsnd", 5, DEC, NOV, HID, DEC, HEX, UNS, MSF}, /* 3 */
+{"msgids", 4, DEC, NOV, HID, HEX, UNS, HEX}, /* 4 */
+{"msgsnap", 5, DEC, NOV, HID, DEC, HEX, UNS, DEC}, /* 5 */
+};
+#define NMSGCODE (sizeof (msgtable) / sizeof (struct systable))
+
+const struct systable semtable[] = {
+{"semctl", 5, DEC, NOV, HID, DEC, DEC, SMC, DEX}, /* 0 */
+{"semget", 4, DEC, NOV, HID, KEY, DEC, SEF}, /* 1 */
+{"semop", 4, DEC, NOV, HID, DEC, HEX, UNS}, /* 2 */
+{"semids", 4, DEC, NOV, HID, HEX, UNS, HEX}, /* 3 */
+{"semtimedop", 5, DEC, NOV, HID, DEC, HEX, UNS, HEX}, /* 4 */
+};
+#define NSEMCODE (sizeof (semtable) / sizeof (struct systable))
+
+const struct systable shmtable[] = {
+{"shmat", 4, HEX, NOV, HID, DEC, DEX, SHF}, /* 0 */
+{"shmctl", 4, DEC, NOV, HID, DEC, SHC, DEX}, /* 1 */
+{"shmdt", 2, DEC, NOV, HID, HEX}, /* 2 */
+{"shmget", 4, DEC, NOV, HID, KEY, UNS, SHF}, /* 3 */
+{"shmids", 4, DEC, NOV, HID, HEX, UNS, HEX}, /* 4 */
+};
+#define NSHMCODE (sizeof (shmtable) / sizeof (struct systable))
+
+const struct systable pidtable[] = {
+{"getpgrp", 1, DEC, NOV, HID}, /* 0 */
+{"setpgrp", 1, DEC, NOV, HID}, /* 1 */
+{"getsid", 2, DEC, NOV, HID, DEC}, /* 2 */
+{"setsid", 1, DEC, NOV, HID}, /* 3 */
+{"getpgid", 2, DEC, NOV, HID, DEC}, /* 4 */
+{"setpgid", 3, DEC, NOV, HID, DEC, DEC}, /* 5 */
+};
+#define NPIDCODE (sizeof (pidtable) / sizeof (struct systable))
+
+const struct systable sfstable[] = {
+{"sysfs", 3, DEC, NOV, SFS, DEX, DEX}, /* 0 */
+{"sysfs", 2, DEC, NOV, SFS, STG}, /* 1 */
+{"sysfs", 3, DEC, NOV, SFS, DEC, RST}, /* 2 */
+{"sysfs", 1, DEC, NOV, SFS}, /* 3 */
+};
+#define NSFSCODE (sizeof (sfstable) / sizeof (struct systable))
+
+const struct systable utstable[] = {
+{"utssys", 3, DEC, NOV, HEX, DEC, UTS}, /* 0 */
+{"utssys", 4, DEC, NOV, HEX, HEX, HEX, HEX}, /* err */
+{"utssys", 3, DEC, NOV, HEX, HHX, UTS}, /* 2 */
+{"utssys", 4, DEC, NOV, STG, FUI, UTS, HEX} /* 3 */
+};
+#define NUTSCODE (sizeof (utstable) / sizeof (struct systable))
+
+const struct systable rctltable[] = {
+{"getrctl", 6, DEC, NOV, HID, STG, HEX, HEX, HID, RGF}, /* 0 */
+{"setrctl", 6, DEC, NOV, HID, STG, HEX, HEX, HID, RSF}, /* 1 */
+{"rctlsys_lst", 6, DEC, NOV, HID, HID, HEX, HID, HEX, HID}, /* 2 */
+{"rctlsys_ctl", 6, DEC, NOV, HID, STG, HEX, HID, HID, RCF}, /* 3 */
+{"setprojrctl", 6, DEC, NOV, HID, STG, HID, HEX, HEX, SPF}, /* 4 */
+};
+#define NRCTLCODE (sizeof (rctltable) / sizeof (struct systable))
+
+const struct systable sgptable[] = {
+{"sigpendsys", 2, DEC, NOV, DEC, HEX}, /* err */
+{"sigpending", 2, DEC, NOV, HID, HEX}, /* 1 */
+{"sigfillset", 2, DEC, NOV, HID, HEX}, /* 2 */
+};
+#define NSGPCODE (sizeof (sgptable) / sizeof (struct systable))
+
+const struct systable ctxtable[] = {
+{"getcontext", 2, DEC, NOV, HID, HEX}, /* 0 */
+{"setcontext", 2, DEC, NOV, HID, HEX}, /* 1 */
+{"getustack", 2, DEC, NOV, HID, HEX}, /* 2 */
+{"setustack", 2, DEC, NOV, HID, HEX}, /* 3 */
+};
+#define NCTXCODE (sizeof (ctxtable) / sizeof (struct systable))
+
+const struct systable hrttable[] = {
+{"hrtcntl", 5, DEC, NOV, HID, DEC, DEC, HEX, HEX}, /* 0 */
+{"hrtalarm", 3, DEC, NOV, HID, HEX, DEC}, /* 1 */
+{"hrtsleep", 2, DEC, NOV, HID, HEX}, /* 2 */
+{"hrtcancel", 3, DEC, NOV, HID, HEX, DEC}, /* 3 */
+};
+#define NHRTCODE (sizeof (hrttable) / sizeof (struct systable))
+
+const struct systable cortable[] = {
+{"corectl", 4, DEC, NOV, COR, HEX, HEX, HEX}, /* 0 */
+{"corectl", 2, DEC, NOV, COR, CCO}, /* 1 */
+{"corectl", 1, HHX, NOV, COR}, /* 2 */
+{"corectl", 3, DEC, NOV, COR, STG, DEC}, /* 3 */
+{"corectl", 3, DEC, NOV, COR, RST, DEC}, /* 4 */
+{"corectl", 4, DEC, NOV, COR, STG, DEC, DEC}, /* 5 */
+{"corectl", 4, DEC, NOV, COR, RST, DEC, DEC}, /* 6 */
+{"corectl", 2, DEC, NOV, COR, CCC}, /* 7 */
+{"corectl", 2, DEC, NOV, COR, RCC}, /* 8 */
+{"corectl", 3, DEC, NOV, COR, CCC, DEC}, /* 9 */
+{"corectl", 3, DEC, NOV, COR, RCC, DEC}, /* 10 */
+{"corectl", 3, DEC, NOV, COR, STG, DEC}, /* 11 */
+{"corectl", 3, DEC, NOV, COR, RST, DEC}, /* 12 */
+{"corectl", 2, DEC, NOV, COR, CCC}, /* 13 */
+{"corectl", 2, DEC, NOV, COR, RCC}, /* 14 */
+};
+#define NCORCODE (sizeof (cortable) / sizeof (struct systable))
+
+const struct systable aiotable[] = {
+{"kaio", 7, DEC, NOV, AIO, DEC, HEX, DEC, LLO, HID, HEX}, /* 0 */
+{"kaio", 7, DEC, NOV, AIO, DEC, HEX, DEC, LLO, HID, HEX}, /* 1 */
+{"kaio", 3, DEC, NOV, AIO, HEX, DEC}, /* 2 */
+{"kaio", 3, DEC, NOV, AIO, DEC, HEX}, /* 3 */
+{"kaio", 1, DEC, NOV, AIO}, /* 4 */
+{"kaio", 1, DEC, NOV, AIO}, /* 5 */
+{"kaio", 1, DEC, NOV, AIO}, /* 6 */
+{"kaio", 5, DEC, NOV, AIO, LIO, HEX, DEC, HEX}, /* 7 */
+{"kaio", 5, DEC, NOV, AIO, HEX, DEC, HEX, DEC}, /* 8 */
+{"kaio", 2, DEC, NOV, AIO, HEX}, /* 9 */
+{"kaio", 5, DEC, NOV, AIO, LIO, HEX, DEC, HEX}, /* 10 */
+{"kaio", 2, DEC, NOV, AIO, HEX}, /* 11 */
+{"kaio", 2, DEC, NOV, AIO, HEX}, /* 12 */
+{"kaio", 5, DEC, NOV, AIO, LIO, HEX, DEC, HEX}, /* 13 */
+{"kaio", 5, DEC, NOV, AIO, HEX, DEC, HEX, DEC}, /* 14 */
+{"kaio", 2, DEC, NOV, AIO, HEX}, /* 15 */
+{"kaio", 5, DEC, NOV, AIO, LIO, HEX, DEC, HEX}, /* 16 */
+{"kaio", 2, DEC, NOV, AIO, HEX}, /* 17 */
+{"kaio", 2, DEC, NOV, AIO, HEX}, /* 18 */
+{"kaio", 3, DEC, NOV, AIO, DEC, HEX}, /* 19 */
+{"kaio", 1, DEC, NOV, AIO}, /* 20 */
+{"kaio", 5, DEC, NOV, AIO, HEX, DEC, HEX, HEX}, /* 21 */
+};
+#define NAIOCODE (sizeof (aiotable) / sizeof (struct systable))
+
+const struct systable doortable[] = {
+{"door_create", 3, DEC, NOV, HEX, HEX, DFL}, /* 0 */
+{"door_revoke", 1, DEC, NOV, DEC}, /* 1 */
+{"door_info", 2, DEC, NOV, DEC, HEX}, /* 2 */
+{"door_call", 2, DEC, NOV, DEC, HEX}, /* 3 */
+{"door_return", 4, DEC, NOV, HEX, DEC, HEX, DEC}, /* 4 (old) */
+{"door_cred", 1, DEC, NOV, HEX}, /* 5 (old) */
+{"door_bind", 1, DEC, NOV, DEC}, /* 6 */
+{"door_unbind", 0, DEC, NOV}, /* 7 */
+{"door_unref", 0, DEC, NOV}, /* 8 */
+{"door_ucred", 1, DEC, NOV, HEX}, /* 9 */
+{"door_return", 5, DEC, NOV, HEX, DEC, HEX, HEX, DEC}, /* 10 */
+{"door_getparam", 3, DEC, NOV, DEC, DPM, HEX}, /* 11 */
+{"door_setparam", 3, DEC, NOV, DEC, DPM, DEC}, /* 12 */
+};
+#define NDOORCODE (sizeof (doortable) / sizeof (struct systable))
+
+const struct systable psettable[] = {
+{"pset_create", 2, DEC, NOV, HID, HEX}, /* 0 */
+{"pset_destroy", 2, DEC, NOV, HID, PST}, /* 1 */
+{"pset_assign", 4, DEC, NOV, HID, PST, DEC, HEX}, /* 2 */
+{"pset_info", 5, DEC, NOV, HID, PST, HEX, HEX, HEX}, /* 3 */
+{"pset_bind", 5, DEC, NOV, HID, PST, IDT, DEC, HEX}, /* 4 */
+{"pset_getloadavg", 4, DEC, NOV, HID, PST, HEX, DEC}, /* 5 */
+{"pset_list", 3, DEC, NOV, HID, HEX, HEX}, /* 6 */
+{"pset_setattr", 3, DEC, NOV, HID, PST, HEX}, /* 7 */
+{"pset_getattr", 3, DEC, NOV, HID, PST, HEX}, /* 8 */
+{"pset_assign_forced", 4, DEC, NOV, HID, PST, DEC, HEX}, /* 9 */
+};
+#define NPSETCODE (sizeof (psettable) / sizeof (struct systable))
+
+const struct systable lwpcreatetable[] = {
+{"lwp_create", 3, DEC, NOV, HEX, LWF, HEX}, /* 0 */
+{"lwp_create", 0, DEC, NOV}, /* 1 */
+};
+#define NLWPCREATECODE (sizeof (lwpcreatetable) / sizeof (struct systable))
+
+static const struct systable tasksystable[] = {
+{"settaskid", 3, DEC, NOV, HID, DEC, HEX}, /* 0 */
+{"gettaskid", 1, DEC, NOV, HID}, /* 1 */
+{"getprojid", 1, DEC, NOV, HID}, /* 2 */
+};
+#define NTASKSYSCODE (sizeof (tasksystable) / sizeof (struct systable))
+
+static const struct systable privsystable[] = {
+{"setppriv", 4, DEC, NOV, HID, PRO, PRN, PRS}, /* 0 */
+{"getppriv", 4, DEC, NOV, HID, HID, PRN, PRS}, /* 1 */
+{"getprivimplinfo", 5, DEC, NOV, HID, HID, HID, HEX, DEC}, /* 2 */
+{"setpflags", 3, DEC, NOV, HID, PFL, DEC}, /* 3 */
+{"getpflags", 2, DEC, NOV, HID, PFL}, /* 4 */
+{"issetugid", 0, DEC, NOV, HID}, /* 5 */
+};
+#define NPRIVSYSCODE (sizeof (privsystable) / sizeof (struct systable))
+
+static const struct systable exacctsystable[] = {
+{"getacct", 5, DEC, NOV, HID, IDT, DEC, HEX, UNS}, /* 0 */
+{"putacct", 6, DEC, NOV, HID, IDT, DEC, HEX, UNS, HEX}, /* 1 */
+{"wracct", 4, DEC, NOV, HID, IDT, DEC, HEX}, /* 2 */
+};
+#define NEXACCTSYSCODE (sizeof (exacctsystable) / sizeof (struct systable))
+
+static const struct systable lwpparktable[] = {
+{"lwp_park", 3, DEC, NOV, HID, HEX, DEC}, /* 0 */
+{"lwp_unpark", 2, DEC, NOV, HID, DEC}, /* 1 */
+{"lwp_unpark_all", 3, DEC, NOV, HID, HEX, DEC}, /* 2 */
+{"lwp_unpark_cancel", 2, DEC, NOV, HID, DEC}, /* 3 */
+{"lwp_set_park", 3, DEC, NOV, HID, HEX, DEC}, /* 4 */
+};
+#define NLWPPARKCODE (sizeof (lwpparktable) / sizeof (struct systable))
+
+static const struct systable lwprwlocktable[] = {
+{"lwp_rwlock_rdlock", 3, DEC, NOV, HID, HEX, HEX}, /* 0 */
+{"lwp_rwlock_wrlock", 3, DEC, NOV, HID, HEX, HEX}, /* 1 */
+{"lwp_rwlock_tryrdlock", 2, DEC, NOV, HID, HEX}, /* 2 */
+{"lwp_rwlock_trywrlock", 2, DEC, NOV, HID, HEX}, /* 3 */
+{"lwp_rwlock_unlock", 2, DEC, NOV, HID, HEX}, /* 4 */
+};
+#define NLWPRWLOCKCODE (sizeof (lwprwlocktable) / sizeof (struct systable))
+
+static const struct systable sendfilevsystable[] = {
+{"sendfilev", 5, DEC, NOV, DEC, DEC, HEX, DEC, HEX}, /* 0 */
+{"sendfilev64", 5, DEC, NOV, DEC, DEC, HEX, DEC, HEX}, /* 1 */
+};
+#define NSENDFILESYSCODE \
+ (sizeof (sendfilevsystable) / sizeof (struct systable))
+
+static const struct systable lgrpsystable[] = {
+{"meminfo", 3, DEC, NOV, HID, NOV, MIF}, /* 0 */
+{"_lgrpsys", 3, DEC, NOV, DEC, DEC, NOV}, /* 1 */
+{"lgrp_version", 3, DEC, NOV, HID, DEC, NOV}, /* 2 */
+{"_lgrpsys", 3, DEC, NOV, DEC, HEX, HEX}, /* 3 */
+{"lgrp_affinity_get", 3, DEC, NOV, HID, NOV, LAF}, /* 4 */
+{"lgrp_affinity_set", 3, DEC, NOV, HID, NOV, LAF}, /* 5 */
+{"lgrp_latency", 3, DEC, NOV, HID, DEC, DEC}, /* 6 */
+};
+#define NLGRPSYSCODE (sizeof (lgrpsystable) / sizeof (struct systable))
+
+static const struct systable rusagesystable[] = {
+{"getrusage", 2, DEC, NOV, HID, HEX}, /* 0 */
+{"getrusage_chld", 2, DEC, NOV, HID, HEX}, /* 1 */
+{"getrusage_lwp", 2, DEC, NOV, HID, HEX}, /* 2 */
+{"getvmusage", 5, DEC, NOV, HID, HEX, DEC, HEX, HEX}, /* 3 */
+};
+#define NRUSAGESYSCODE \
+ (sizeof (rusagesystable) / sizeof (struct systable))
+
+static const struct systable ucredsystable[] = {
+{"ucred_get", 3, DEC, NOV, HID, DEC, HEX},
+{"getpeerucred", 3, DEC, NOV, HID, DEC, HEX},
+};
+#define NUCREDSYSCODE \
+ (sizeof (ucredsystable) / sizeof (struct systable))
+
+const struct systable portfstable[] = {
+{"port_create", 2, DEC, NOV, HID, DEC}, /* 0 */
+{"port_associate", 6, DEC, NOV, HID, DEC, DEC, HEX, HEX, HEX}, /* 1 */
+{"port_dissociate", 4, DEC, NOV, HID, DEC, DEC, HEX}, /* 2 */
+{"port_send", 4, DEC, NOV, HID, DEC, HEX, HEX}, /* 3 */
+{"port_sendn", 6, DEC, DEC, HID, HEX, HEX, DEC, HEX, HEX}, /* 4 */
+{"port_get", 4, DEC, NOV, HID, DEC, HEX, HEX}, /* 5 */
+{"port_getn", 6, DEC, DEC, HID, DEC, HEX, DEC, DEC, HEX}, /* 6 */
+{"port_alert", 5, DEC, NOV, HID, DEC, HEX, HEX, HEX}, /* 7 */
+{"port_dispatch", 6, DEC, NOV, HID, DEC, DEC, HEX, HEX, HEX}, /* 8 */
+};
+#define NPORTCODE (sizeof (portfstable) / sizeof (struct systable))
+
+static const struct systable zonetable[] = {
+{"zone_create", 2, DEC, NOV, HID, HEX}, /* 0 */
+{"zone_destroy", 2, DEC, NOV, HID, DEC}, /* 1 */
+{"zone_getattr", 5, DEC, NOV, HID, DEC, ZGA, HEX, DEC}, /* 2 */
+{"zone_enter", 2, DEC, NOV, HID, DEC}, /* 3 */
+{"zone_list", 3, DEC, NOV, HID, HEX, HEX}, /* 4 */
+{"zone_shutdown", 2, DEC, NOV, HID, DEC}, /* 5 */
+{"zone_lookup", 2, DEC, NOV, HID, STG}, /* 6 */
+{"zone_boot", 2, DEC, NOV, HID, DEC}, /* 7 */
+{"zone_version", 2, HEX, NOV, HID, DEC}, /* 8 */
+{"zone_setattr", 5, DEC, NOV, HID, DEC, ZGA, HEX, DEC}, /* 9 */
+{"zone_add_datalink", 3, DEC, NOV, HID, DEC, STG}, /* 10 */
+{"zone_remove_datalink", 3, DEC, NOV, HID, DEC, STG}, /* 11 */
+{"zone_check_datalink", 3, DEC, NOV, HID, HEX, STG}, /* 12 */
+{"zone_list_datalink", 4, DEC, NOV, HID, DEC, HEX, HEX}, /* 13 */
+};
+#define NZONECODE (sizeof (zonetable) / sizeof (struct systable))
+
+static const struct systable labeltable[] = {
+{"labelsys", 3, DEC, NOV, HID, HEX, HEX}, /* 0 */
+{"is_system_labeled", 1, DEC, NOV, HID}, /* 1 */
+{"tnrh", 3, DEC, NOV, HID, TND, HEX}, /* 2 */
+{"tnrhtp", 3, DEC, NOV, HID, TND, HEX}, /* 3 */
+{"tnmlp", 3, DEC, NOV, HID, TND, HEX}, /* 4 */
+{"getlabel", 3, DEC, NOV, HID, STG, HEX}, /* 5 */
+{"fgetlabel", 3, DEC, NOV, HID, DEC, HEX}, /* 6 */
+};
+#define NLABELCODE (sizeof (labeltable) / sizeof (struct systable))
+
+const struct systable forktable[] = {
+/* parent codes */
+{"forkx", 2, DEC, NOV, HID, FXF}, /* 0 */
+{"forkallx", 2, DEC, NOV, HID, FXF}, /* 1 */
+{"vforkx", 2, DEC, NOV, HID, FXF}, /* 2 */
+/* child codes */
+{"forkx", 0, DEC, NOV}, /* 3 */
+{"forkallx", 0, DEC, NOV}, /* 4 */
+{"vforkx", 0, DEC, NOV}, /* 5 */
+};
+#define NFORKCODE (sizeof (forktable) / sizeof (struct systable))
+
+const struct systable sidsystable[] = {
+{"allocids", 4, UNS, UNS, HID, DEC, DEC, DEC}, /* 0 */
+{"idmap_reg", 2, DEC, NOV, HID, DEC}, /* 1 */
+{"idmap_unreg", 2, DEC, NOV, HID, DEC}, /* 2 */
+};
+#define NSIDSYSCODE (sizeof (sidsystable) / sizeof (struct systable))
+
+const struct systable utimesystable[] = {
+{"futimens", 3, DEC, NOV, HID, DEC, HEX}, /* 0 */
+{"utimensat", 5, DEC, NOV, HID, ATC, STG, HEX, SNF}, /* 1 */
+};
+#define NUTIMESYSCODE (sizeof (utimesystable) / sizeof (struct systable))
+
+const struct systable sockconfigtable[] = {
+{"sockconfig", 5, DEC, NOV, SKC, DEC, DEC, DEC, STG}, /* 0 */
+{"sockconfig", 4, DEC, NOV, SKC, DEC, DEC, DEC}, /* 1 */
+{"sockconfig", 3, DEC, NOV, SKC, STG, HEX }, /* 2 */
+{"sockconfig", 2, DEC, NOV, SKC, STG }, /* 3 */
+};
+#define NSOCKCONFIGCODE (sizeof (sockconfigtable) / sizeof (struct systable))
+
+const struct sysalias sysalias[] = {
+ { "exit", SYS_exit },
+ { "fork", SYS_forksys },
+ { "fork1", SYS_forksys },
+ { "forkall", SYS_forksys },
+ { "forkx", SYS_forksys },
+ { "forkallx", SYS_forksys },
+ { "vforkx", SYS_forksys },
+ { "sbrk", SYS_brk },
+ { "getppid", SYS_getpid },
+ { "geteuid", SYS_getuid },
+ { "getpgrp", SYS_pgrpsys },
+ { "setpgrp", SYS_pgrpsys },
+ { "getsid", SYS_pgrpsys },
+ { "setsid", SYS_pgrpsys },
+ { "getpgid", SYS_pgrpsys },
+ { "setpgid", SYS_pgrpsys },
+ { "getegid", SYS_getgid },
+ { "msgget", SYS_msgsys },
+ { "msgctl", SYS_msgsys },
+ { "msgctl64", SYS_msgsys },
+ { "msgrcv", SYS_msgsys },
+ { "msgsnd", SYS_msgsys },
+ { "msgids", SYS_msgsys },
+ { "msgsnap", SYS_msgsys },
+ { "msgop", SYS_msgsys },
+ { "shmat", SYS_shmsys },
+ { "shmctl", SYS_shmsys },
+ { "shmctl64", SYS_shmsys },
+ { "shmdt", SYS_shmsys },
+ { "shmget", SYS_shmsys },
+ { "shmids", SYS_shmsys },
+ { "shmop", SYS_shmsys },
+ { "semctl", SYS_semsys },
+ { "semctl64", SYS_semsys },
+ { "semget", SYS_semsys },
+ { "semids", SYS_semsys },
+ { "semop", SYS_semsys },
+ { "semtimedop", SYS_semsys },
+ { "uname", SYS_utssys },
+ { "ustat", SYS_utssys },
+ { "fusers", SYS_utssys },
+ { "exec", SYS_execve },
+ { "execl", SYS_execve },
+ { "execv", SYS_execve },
+ { "execle", SYS_execve },
+ { "execlp", SYS_execve },
+ { "execvp", SYS_execve },
+ { "sigfillset", SYS_sigpending },
+ { "getcontext", SYS_context },
+ { "setcontext", SYS_context },
+ { "getustack", SYS_context },
+ { "setustack", SYS_context },
+ { "hrtcntl", SYS_hrtsys },
+ { "hrtalarm", SYS_hrtsys },
+ { "hrtsleep", SYS_hrtsys },
+ { "hrtcancel", SYS_hrtsys },
+ { "aioread", SYS_kaio },
+ { "aiowrite", SYS_kaio },
+ { "aiowait", SYS_kaio },
+ { "aiocancel", SYS_kaio },
+ { "aionotify", SYS_kaio },
+ { "audit", SYS_auditsys },
+ { "door_create", SYS_door },
+ { "door_revoke", SYS_door },
+ { "door_info", SYS_door },
+ { "door_call", SYS_door },
+ { "door_return", SYS_door },
+ { "door_bind", SYS_door },
+ { "door_unbind", SYS_door },
+ { "door_unref", SYS_door },
+ { "door_ucred", SYS_door },
+ { "door_getparam", SYS_door },
+ { "door_setparam", SYS_door },
+ { "pset_create", SYS_pset },
+ { "pset_destroy", SYS_pset },
+ { "pset_assign", SYS_pset },
+ { "pset_info", SYS_pset },
+ { "pset_bind", SYS_pset },
+ { "pset_getloadavg", SYS_pset },
+ { "pset_list", SYS_pset },
+ { "pset_setattr", SYS_pset },
+ { "pset_getattr", SYS_pset },
+ { "pset_assign_forced", SYS_pset },
+ { "settaskid", SYS_tasksys },
+ { "gettaskid", SYS_tasksys },
+ { "getprojid", SYS_tasksys },
+ { "setppriv", SYS_privsys },
+ { "getppriv", SYS_privsys },
+ { "getprivimplinfo", SYS_privsys },
+ { "setpflags", SYS_privsys },
+ { "getpflags", SYS_privsys },
+ { "getacct", SYS_exacctsys },
+ { "putacct", SYS_exacctsys },
+ { "wracct", SYS_exacctsys },
+ { "lwp_cond_timedwait", SYS_lwp_cond_wait },
+ { "lwp_sema_wait", SYS_lwp_sema_timedwait },
+ { "lwp_park", SYS_lwp_park },
+ { "lwp_unpark", SYS_lwp_park },
+ { "lwp_unpark_all", SYS_lwp_park },
+ { "lwp_rwlock_rdlock", SYS_lwp_rwlock_sys },
+ { "lwp_rwlock_wrlock", SYS_lwp_rwlock_sys },
+ { "lwp_rwlock_tryrdlock", SYS_lwp_rwlock_sys },
+ { "lwp_rwlock_trywrlock", SYS_lwp_rwlock_sys },
+ { "lwp_rwlock_unlock", SYS_lwp_rwlock_sys },
+ { "lwp_mutex_lock", SYS_lwp_mutex_timedlock },
+ { "sendfilev64", SYS_sendfilev },
+ { "creat", SYS_open },
+ { "creat64", SYS_open64 },
+ { "openattrdirat", SYS_openat },
+ { "lgrpsys", SYS_lgrpsys },
+ { "getrusage", SYS_rusagesys },
+ { "getrusage_chld", SYS_rusagesys },
+ { "getrusage_lwp", SYS_rusagesys },
+ { "getvmusage", SYS_rusagesys },
+ { "getpeerucred", SYS_ucredsys },
+ { "ucred_get", SYS_ucredsys },
+ { "port_create", SYS_port },
+ { "port_associate", SYS_port },
+ { "port_dissociate", SYS_port },
+ { "port_send", SYS_port },
+ { "port_sendn", SYS_port },
+ { "port_get", SYS_port },
+ { "port_getn", SYS_port },
+ { "port_alert", SYS_port },
+ { "port_dispatch", SYS_port },
+ { "zone_create", SYS_zone },
+ { "zone_destroy", SYS_zone },
+ { "zone_getattr", SYS_zone },
+ { "zone_setattr", SYS_zone },
+ { "zone_enter", SYS_zone },
+ { "getzoneid", SYS_zone },
+ { "zone_list", SYS_zone },
+ { "zone_shutdown", SYS_zone },
+ { "zone_add_datalink", SYS_zone },
+ { "zone_remove_datalink", SYS_zone },
+ { "zone_check_datalink", SYS_zone },
+ { "zone_list_datalink", SYS_zone },
+ { "is_system_labeled", SYS_labelsys },
+ { "tnrh", SYS_labelsys },
+ { "tnrhtp", SYS_labelsys },
+ { "tnmlp", SYS_labelsys },
+ { "getlabel", SYS_labelsys },
+ { "fgetlabel", SYS_labelsys },
+ { "getrctl", SYS_rctlsys },
+ { "setrctl", SYS_rctlsys },
+ { "rctlsys_lst", SYS_rctlsys },
+ { "rctlsys_ctl", SYS_rctlsys },
+ { "allocids", SYS_sidsys },
+ { "futimens", SYS_utimesys },
+ { "utimensat", SYS_utimesys },
+ { "poll", SYS_pollsys },
+ { "umount", SYS_umount2 },
+ { "wait", SYS_waitid },
+ { NULL, 0 } /* end-of-list */
+};
+
+/*
+ * Return structure to interpret system call with sub-codes.
+ */
+const struct systable *
+subsys(int syscall, int subcode)
+{
+ const struct systable *stp = NULL;
+
+ if (subcode != -1) {
+ switch (syscall) {
+ case SYS_faccessat:
+ if ((unsigned)subcode < NACCESSCODE)
+ stp = &faccessattable[subcode];
+ break;
+ case SYS_fchmodat:
+ if ((unsigned)subcode < NCHMODCODE)
+ stp = &fchmodattable[subcode];
+ break;
+ case SYS_fchownat:
+ if ((unsigned)subcode < NCHOWNCODE)
+ stp = &fchownattable[subcode];
+ break;
+ case SYS_mkdirat:
+ if ((unsigned)subcode < NMKDIRCODE)
+ stp = &mkdiratattable[subcode];
+ break;
+ case SYS_mknodat:
+ if ((unsigned)subcode < NMKMODCODE)
+ stp = &mknodatattable[subcode];
+ break;
+ case SYS_renameat:
+ if ((unsigned)subcode < NRENAMECODE)
+ stp = &renameattable[subcode];
+ break;
+ case SYS_linkat:
+ if ((unsigned)subcode < NLINKATCODE)
+ stp = &linkattable[subcode];
+ break;
+ case SYS_unlinkat:
+ if ((unsigned)subcode < NUNLINKCODE)
+ stp = &unlinkattable[subcode];
+ break;
+ case SYS_symlinkat:
+ if ((unsigned)subcode < NSYMLINKCODE)
+ stp = &symlinkattable[subcode];
+ break;
+ case SYS_readlinkat:
+ if ((unsigned)subcode < NREADLINKCODE)
+ stp = &readlinkattable[subcode];
+ break;
+ case SYS_fstatat:
+ if ((unsigned)subcode < NSTATCODE)
+ stp = &fstatattable[subcode];
+ break;
+ case SYS_fstatat64:
+ if ((unsigned)subcode < NSTAT64CODE)
+ stp = &fstatat64table[subcode];
+ break;
+ case SYS_openat:
+ if ((unsigned)subcode < NOPENATCODE)
+ stp = &openattable[subcode];
+ break;
+ case SYS_openat64:
+ if ((unsigned)subcode < NOPENAT64CODE)
+ stp = &openat64table[subcode];
+ break;
+ case SYS_open:
+ if ((unsigned)subcode < NOPENCODE)
+ stp = &opentable[subcode];
+ break;
+ case SYS_open64:
+ if ((unsigned)subcode < NOPEN64CODE)
+ stp = &open64table[subcode];
+ break;
+ case SYS_msgsys: /* msgsys() */
+ if ((unsigned)subcode < NMSGCODE)
+ stp = &msgtable[subcode];
+ break;
+ case SYS_semsys: /* semsys() */
+ if ((unsigned)subcode < NSEMCODE)
+ stp = &semtable[subcode];
+ break;
+ case SYS_shmsys: /* shmsys() */
+ if ((unsigned)subcode < NSHMCODE)
+ stp = &shmtable[subcode];
+ break;
+ case SYS_pgrpsys: /* pgrpsys() */
+ if ((unsigned)subcode < NPIDCODE)
+ stp = &pidtable[subcode];
+ break;
+ case SYS_utssys: /* utssys() */
+ if ((unsigned)subcode < NUTSCODE)
+ stp = &utstable[subcode];
+ break;
+ case SYS_sysfs: /* sysfs() */
+ if ((unsigned)subcode < NSFSCODE)
+ stp = &sfstable[subcode];
+ break;
+ case SYS_sigpending: /* sigpending()/sigfillset() */
+ if ((unsigned)subcode < NSGPCODE)
+ stp = &sgptable[subcode];
+ break;
+ case SYS_context: /* [get|set]context() */
+ if ((unsigned)subcode < NCTXCODE)
+ stp = &ctxtable[subcode];
+ break;
+ case SYS_hrtsys: /* hrtsys() */
+ if ((unsigned)subcode < NHRTCODE)
+ stp = &hrttable[subcode];
+ break;
+ case SYS_corectl: /* corectl() */
+ if ((unsigned)subcode < NCORCODE)
+ stp = &cortable[subcode];
+ break;
+ case SYS_kaio: /* kaio() */
+ if ((unsigned)subcode < NAIOCODE)
+ stp = &aiotable[subcode];
+ break;
+ case SYS_door: /* doors */
+ if ((unsigned)subcode < NDOORCODE)
+ stp = &doortable[subcode];
+ break;
+ case SYS_pset: /* pset() */
+ if ((unsigned)subcode < NPSETCODE)
+ stp = &psettable[subcode];
+ break;
+ case SYS_lwp_create: /* lwp_create() */
+ if ((unsigned)subcode < NLWPCREATECODE)
+ stp = &lwpcreatetable[subcode];
+ break;
+ case SYS_tasksys: /* tasks */
+ if ((unsigned)subcode < NTASKSYSCODE)
+ stp = &tasksystable[subcode];
+ break;
+ case SYS_exacctsys: /* exacct */
+ if ((unsigned)subcode < NEXACCTSYSCODE)
+ stp = &exacctsystable[subcode];
+ break;
+ case SYS_privsys: /* privileges */
+ if ((unsigned)subcode < NPRIVSYSCODE)
+ stp = &privsystable[subcode];
+ break;
+ case SYS_lwp_park: /* lwp_park */
+ if ((unsigned)subcode < NLWPPARKCODE)
+ stp = &lwpparktable[subcode];
+ break;
+ case SYS_lwp_rwlock_sys:
+ if ((unsigned)subcode < NLWPRWLOCKCODE)
+ stp = &lwprwlocktable[subcode];
+ break;
+ case SYS_sendfilev: /* sendfilev */
+ if ((unsigned)subcode < NSENDFILESYSCODE)
+ stp = &sendfilevsystable[subcode];
+ break;
+ case SYS_lgrpsys: /* lgrpsys */
+ if ((unsigned)subcode < NLGRPSYSCODE)
+ stp = &lgrpsystable[subcode];
+ break;
+ case SYS_rusagesys: /* rusagesys */
+ if ((unsigned)subcode < NRUSAGESYSCODE)
+ stp = &rusagesystable[subcode];
+ break;
+ case SYS_fcntl: /* fcntl */
+ if ((unsigned)subcode < NFCNTLCODE)
+ stp = &fcntltable[subcode];
+ break;
+ case SYS_ucredsys:
+ if ((unsigned)subcode < NUCREDSYSCODE)
+ stp = &ucredsystable[subcode];
+ break;
+ case SYS_port: /* portfs */
+ if ((unsigned)subcode < NPORTCODE)
+ stp = &portfstable[subcode];
+ break;
+ case SYS_zone: /* zone family */
+ if ((unsigned)subcode < NZONECODE)
+ stp = &zonetable[subcode];
+ break;
+ case SYS_labelsys: /* label family */
+ if ((unsigned)subcode < NLABELCODE)
+ stp = &labeltable[subcode];
+ break;
+ case SYS_rctlsys: /* rctl family */
+ if ((unsigned)subcode < NRCTLCODE)
+ stp = &rctltable[subcode];
+ break;
+ case SYS_forksys: /* fork family */
+ if ((unsigned)subcode < NFORKCODE)
+ stp = &forktable[subcode];
+ break;
+ case SYS_sidsys: /* SID family */
+ if ((unsigned)subcode < NSIDSYSCODE)
+ stp = &sidsystable[subcode];
+ break;
+ case SYS_utimesys: /* utime family */
+ if ((unsigned)subcode < NUTIMESYSCODE)
+ stp = &utimesystable[subcode];
+ break;
+ case SYS_sockconfig: /* sockconfig family */
+ if ((unsigned)subcode < NSOCKCONFIGCODE)
+ stp = &sockconfigtable[subcode];
+ break;
+ }
+ }
+
+ if (stp == NULL)
+ stp = &systable[((unsigned)syscall < SYSEND)? syscall : 0];
+
+ return (stp);
+}
+
+/*
+ * Return the name of the system call.
+ */
+const char *
+sysname(private_t *pri, int syscall, int subcode)
+{
+ const struct systable *stp = subsys(syscall, subcode);
+ const char *name = stp->name; /* may be NULL */
+
+ if (name == NULL) { /* manufacture a name */
+ (void) sprintf(pri->sys_name, "sys#%d", syscall);
+ name = pri->sys_name;
+ }
+
+ return (name);
+}
+
+/*
+ * Return the name of the signal.
+ * Return NULL if unknown signal.
+ */
+const char *
+rawsigname(private_t *pri, int sig)
+{
+ /*
+ * The C library function sig2str() omits the leading "SIG".
+ */
+ (void) strcpy(pri->raw_sig_name, "SIG");
+
+ if (sig > 0 && sig2str(sig, pri->raw_sig_name+3) == 0)
+ return (pri->raw_sig_name);
+ return (NULL);
+}
+
+/*
+ * Return the name of the signal.
+ * Manufacture a name for unknown signal.
+ */
+const char *
+signame(private_t *pri, int sig)
+{
+ const char *name = rawsigname(pri, sig);
+
+ if (name == NULL) { /* manufacture a name */
+ (void) sprintf(pri->sig_name, "SIG#%d", sig);
+ name = pri->sig_name;
+ }
+
+ return (name);
+}
+
+/*
+ * Determine the subcode for this syscall, if any.
+ */
+int
+getsubcode(private_t *pri)
+{
+ const lwpstatus_t *Lsp = pri->lwpstat;
+ int syscall = Lsp->pr_syscall;
+ int nsysarg = Lsp->pr_nsysarg;
+ int subcode = -1;
+ int arg0;
+
+ if (syscall > 0 && nsysarg > 0 && !prismember(&rawout, syscall)) {
+ arg0 = Lsp->pr_sysarg[0];
+ switch (syscall) {
+ case SYS_utssys: /* utssys() */
+ if (nsysarg > 2)
+ subcode = Lsp->pr_sysarg[2];
+ break;
+ case SYS_faccessat:
+ if (nsysarg > 3)
+ subcode = ((int)Lsp->pr_sysarg[0] == AT_FDCWD &&
+ Lsp->pr_sysarg[3] == 0)? 1 : 0;
+ break;
+ case SYS_fchmodat:
+ if (nsysarg > 1 && Lsp->pr_sysarg[1] == NULL) {
+ subcode = 3;
+ break;
+ }
+ if (nsysarg > 0 && (int)Lsp->pr_sysarg[0] != AT_FDCWD) {
+ subcode = 0;
+ break;
+ }
+ if (nsysarg > 3)
+ subcode = (Lsp->pr_sysarg[3] == 0)? 1 :
+ (Lsp->pr_sysarg[3] == AT_SYMLINK_NOFOLLOW)?
+ 2 : 0;
+ break;
+ case SYS_fchownat:
+ if (nsysarg > 1 && Lsp->pr_sysarg[1] == NULL) {
+ subcode = 3;
+ break;
+ }
+ if (nsysarg > 0 && (int)Lsp->pr_sysarg[0] != AT_FDCWD) {
+ subcode = 0;
+ break;
+ }
+ if (nsysarg > 4)
+ subcode = (Lsp->pr_sysarg[4] == 0)? 1 :
+ (Lsp->pr_sysarg[4] == AT_SYMLINK_NOFOLLOW)?
+ 2 : 0;
+ break;
+ case SYS_mkdirat:
+ case SYS_mknodat:
+ case SYS_readlinkat:
+ if (nsysarg > 0)
+ subcode = ((int)Lsp->pr_sysarg[0] == AT_FDCWD)?
+ 1 : 0;
+ break;
+ case SYS_renameat:
+ if (nsysarg > 2)
+ subcode = ((int)Lsp->pr_sysarg[0] == AT_FDCWD &&
+ (int)Lsp->pr_sysarg[2] == AT_FDCWD)? 1 : 0;
+ break;
+ case SYS_linkat:
+ if (nsysarg > 4)
+ subcode = ((int)Lsp->pr_sysarg[0] == AT_FDCWD &&
+ (int)Lsp->pr_sysarg[2] == AT_FDCWD &&
+ Lsp->pr_sysarg[4] == 0)? 1 : 0;
+ break;
+ case SYS_unlinkat:
+ if (nsysarg > 2)
+ subcode =
+ ((int)Lsp->pr_sysarg[0] != AT_FDCWD)? 0 :
+ (Lsp->pr_sysarg[2] == AT_REMOVEDIR)? 2 :
+ (Lsp->pr_sysarg[2] == 0)? 1 : 0;
+ break;
+ case SYS_symlinkat:
+ if (nsysarg > 1)
+ subcode = ((int)Lsp->pr_sysarg[1] == AT_FDCWD)?
+ 1 : 0;
+ break;
+ case SYS_fstatat:
+ case SYS_fstatat64:
+ if (nsysarg > 1 && Lsp->pr_sysarg[1] == NULL) {
+ subcode = 3;
+ break;
+ }
+ if (nsysarg > 0 && (int)Lsp->pr_sysarg[0] != AT_FDCWD) {
+ subcode = 0;
+ break;
+ }
+ if (nsysarg > 3)
+ subcode = (Lsp->pr_sysarg[3] == 0)? 1 :
+ (Lsp->pr_sysarg[3] == AT_SYMLINK_NOFOLLOW)?
+ 2 : 0;
+ break;
+ case SYS_openat: /* openat() w/ and w/o AT_FDCWD */
+ case SYS_openat64: /* and with and w/o O_CREAT */
+ if (nsysarg > 2)
+ subcode = ((int)Lsp->pr_sysarg[0] == AT_FDCWD)?
+ ((Lsp->pr_sysarg[2] & O_CREAT)? 3 : 2) :
+ ((Lsp->pr_sysarg[2] & O_CREAT)? 1 : 0);
+ break;
+ case SYS_open: /* open() w/ and w/o O_CREAT */
+ case SYS_open64:
+ if (nsysarg > 1)
+ subcode = (Lsp->pr_sysarg[1] & O_CREAT)? 1 : 0;
+ break;
+ case SYS_kaio: /* kaio() */
+ subcode = arg0 & ~AIO_POLL_BIT;
+ break;
+ case SYS_door: /* doors */
+ if (nsysarg > 5)
+ subcode = Lsp->pr_sysarg[5];
+ break;
+ case SYS_lwp_create: /* lwp_create() */
+ subcode = /* 0 for parent, 1 for child */
+ (Lsp->pr_why == PR_SYSEXIT && Lsp->pr_errno == 0 &&
+ Lsp->pr_rval1 == 0);
+ break;
+ case SYS_forksys: /* forksys */
+ subcode = arg0;
+ if (Lsp->pr_why == PR_SYSEXIT && Lsp->pr_errno == 0 &&
+ pri->Rval2 != 0) /* this is the child */
+ subcode += 3;
+ break;
+ case SYS_msgsys: /* msgsys() */
+ case SYS_semsys: /* semsys() */
+ case SYS_shmsys: /* shmsys() */
+ case SYS_pgrpsys: /* pgrpsys() */
+ case SYS_sysfs: /* sysfs() */
+ case SYS_sigpending: /* sigpending()/sigfillset() */
+ case SYS_context: /* [get|set]context() */
+ case SYS_hrtsys: /* hrtsys() */
+ case SYS_corectl: /* corectl() */
+ case SYS_pset: /* pset() */
+ case SYS_tasksys: /* tasks */
+ case SYS_privsys: /* privileges */
+ case SYS_exacctsys: /* exacct */
+ case SYS_lwp_park: /* lwp_park */
+ case SYS_lwp_rwlock_sys: /* lwp_rwlock_*() */
+ case SYS_sendfilev: /* sendfilev */
+ case SYS_lgrpsys: /* lgrpsys */
+ case SYS_rusagesys: /* rusagesys */
+ case SYS_ucredsys: /* ucredsys */
+ case SYS_zone: /* zone */
+ case SYS_labelsys: /* labelsys */
+ case SYS_rctlsys: /* rctlsys */
+ case SYS_sidsys: /* sidsys */
+ case SYS_utimesys: /* utimesys */
+ case SYS_sockconfig: /* sockconfig */
+ subcode = arg0;
+ break;
+ case SYS_fcntl: /* fcntl() */
+ if (nsysarg > 2) {
+ switch (Lsp->pr_sysarg[1]) {
+ default: subcode = 0; break;
+ case F_GETFL:
+ case F_GETOWN:
+ case F_GETXFL: subcode = 1; break;
+ case F_SETFL: subcode = 2; break;
+ }
+ }
+ break;
+ case SYS_port: /* portfs */
+ subcode = arg0 & PORT_CODE_MASK;
+ break;
+ }
+ }
+
+ return (subcode);
+}
+
+/*
+ * Return the maximum number of system calls, counting
+ * all system calls with subcodes as separate calls.
+ */
+int
+maxsyscalls()
+{
+ return (PRMAXSYS + 1
+ + NACCESSCODE - 1
+ + NCHMODCODE - 1
+ + NCHOWNCODE - 1
+ + NMKDIRCODE - 1
+ + NMKMODCODE - 1
+ + NRENAMECODE - 1
+ + NLINKATCODE - 1
+ + NUNLINKCODE - 1
+ + NSYMLINKCODE - 1
+ + NREADLINKCODE - 1
+ + NSTATCODE - 1
+ + NSTAT64CODE - 1
+ + NOPENATCODE - 1
+ + NOPENAT64CODE - 1
+ + NOPENCODE - 1
+ + NOPEN64CODE - 1
+ + NMSGCODE - 1
+ + NSEMCODE - 1
+ + NSHMCODE - 1
+ + NPIDCODE - 1
+ + NSFSCODE - 1
+ + NUTSCODE - 1
+ + NSGPCODE - 1
+ + NCTXCODE - 1
+ + NHRTCODE - 1
+ + NCORCODE - 1
+ + NAIOCODE - 1
+ + NDOORCODE - 1
+ + NPSETCODE - 1
+ + NLWPCREATECODE - 1
+ + NTASKSYSCODE - 1
+ + NEXACCTSYSCODE - 1
+ + NLWPPARKCODE - 1
+ + NLWPRWLOCKCODE - 1
+ + NSENDFILESYSCODE - 1
+ + NLGRPSYSCODE - 1
+ + NRUSAGESYSCODE - 1
+ + NFCNTLCODE - 1
+ + NPRIVSYSCODE - 1
+ + NUCREDSYSCODE - 1
+ + NPORTCODE - 1
+ + NZONECODE - 1
+ + NLABELCODE - 1
+ + NRCTLCODE - 1
+ + NFORKCODE - 1
+ + NSIDSYSCODE - 1
+ + NUTIMESYSCODE - 1
+ + NSOCKCONFIGCODE - 1);
+}
+
+/*
+ * Return the number of subcodes for the specified system call number.
+ */
+int
+nsubcodes(int syscall)
+{
+ switch (syscall) {
+ case SYS_faccessat:
+ return (NACCESSCODE);
+ case SYS_fchmodat:
+ return (NCHMODCODE);
+ case SYS_fchownat:
+ return (NCHOWNCODE);
+ case SYS_mkdirat:
+ return (NMKDIRCODE);
+ case SYS_mknodat:
+ return (NMKMODCODE);
+ case SYS_renameat:
+ return (NRENAMECODE);
+ case SYS_linkat:
+ return (NLINKATCODE);
+ case SYS_unlinkat:
+ return (NUNLINKCODE);
+ case SYS_symlinkat:
+ return (NSYMLINKCODE);
+ case SYS_readlinkat:
+ return (NREADLINKCODE);
+ case SYS_fstatat:
+ return (NSTATCODE);
+ case SYS_fstatat64:
+ return (NSTAT64CODE);
+ case SYS_openat:
+ return (NOPENATCODE);
+ case SYS_openat64:
+ return (NOPENAT64CODE);
+ case SYS_open:
+ return (NOPENCODE);
+ case SYS_open64:
+ return (NOPEN64CODE);
+ case SYS_msgsys:
+ return (NMSGCODE);
+ case SYS_semsys:
+ return (NSEMCODE);
+ case SYS_shmsys:
+ return (NSHMCODE);
+ case SYS_pgrpsys:
+ return (NPIDCODE);
+ case SYS_utssys:
+ return (NUTSCODE);
+ case SYS_sysfs:
+ return (NSFSCODE);
+ case SYS_sigpending:
+ return (NSGPCODE);
+ case SYS_context:
+ return (NCTXCODE);
+ case SYS_hrtsys:
+ return (NHRTCODE);
+ case SYS_corectl:
+ return (NCORCODE);
+ case SYS_kaio:
+ return (NAIOCODE);
+ case SYS_door:
+ return (NDOORCODE);
+ case SYS_pset:
+ return (NPSETCODE);
+ case SYS_lwp_create:
+ return (NLWPCREATECODE);
+ case SYS_tasksys:
+ return (NTASKSYSCODE);
+ case SYS_exacctsys:
+ return (NEXACCTSYSCODE);
+ case SYS_privsys:
+ return (NPRIVSYSCODE);
+ case SYS_lwp_park:
+ return (NLWPPARKCODE);
+ case SYS_lwp_rwlock_sys:
+ return (NLWPRWLOCKCODE);
+ case SYS_sendfilev:
+ return (NSENDFILESYSCODE);
+ case SYS_lgrpsys:
+ return (NLGRPSYSCODE);
+ case SYS_rusagesys:
+ return (NRUSAGESYSCODE);
+ case SYS_fcntl:
+ return (NFCNTLCODE);
+ case SYS_ucredsys:
+ return (NUCREDSYSCODE);
+ case SYS_port:
+ return (NPORTCODE);
+ case SYS_zone:
+ return (NZONECODE);
+ case SYS_labelsys:
+ return (NLABELCODE);
+ case SYS_rctlsys:
+ return (NRCTLCODE);
+ case SYS_forksys:
+ return (NFORKCODE);
+ case SYS_sidsys:
+ return (NSIDSYSCODE);
+ case SYS_utimesys:
+ return (NUTIMESYSCODE);
+ case SYS_sockconfig:
+ return (NSOCKCONFIGCODE);
+ default:
+ return (1);
+ }
+}
+
+
+
+/* Socket address families (and protocol families) */
+const char * const afcodes[] = {
+ "UNSPEC", /* 0 */
+ "UNIX", /* 1 */
+ "INET", /* 2 */
+ "IMPLINK", /* 3 */
+ "PUP", /* 4 */
+ "CHAOS", /* 5 */
+ "NS", /* 6 */
+ "NBS", /* 7 */
+ "ECMA", /* 8 */
+ "DATAKIT", /* 9 */
+ "CCITT", /* 10 */
+ "SNA", /* 11 */
+ "DECnet", /* 12 */
+ "DLI", /* 13 */
+ "LAT", /* 14 */
+ "HYLINK", /* 15 */
+ "APPLETALK", /* 16 */
+ "NIT", /* 17 */
+ "802", /* 18 */
+ "OSI", /* 19 */
+ "X25", /* 20 */
+ "OSINET", /* 21 */
+ "GOSIP", /* 22 */
+ "IPX", /* 23 */
+ "ROUTE", /* 24 */
+ "LINK", /* 25 */
+ "INET6", /* 26 */
+ "KEY", /* 27 */
+ "NCA", /* 28 */
+ "POLICY", /* 29 */
+ "RDS", /* 30 */
+ "TRILL", /* 31 */
+ "PACKET" /* 32 */
+};
+#if MAX_AFCODES != 33
+#error Need to update address-family table
+#endif
+
+
+const char * const socktype_codes[] = { /* cf socket.h */
+ NULL,
+ "SOCK_DGRAM", /* 1 */
+ "SOCK_STREAM", /* 2 */
+ NULL,
+ "SOCK_RAW", /* 4 */
+ "SOCK_RDM", /* 5 */
+ "SOCK_SEQPACKET" /* 6 */
+};
+#if MAX_SOCKTYPES != 7
+#error Need to update socket-type table
+#endif
diff --git a/usr/src/cmd/truss/systable.h b/usr/src/cmd/truss/systable.h
new file mode 100644
index 0000000..031c708
--- /dev/null
+++ b/usr/src/cmd/truss/systable.h
@@ -0,0 +1,74 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1992-2001 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
+/* All Rights Reserved */
+
+
+#ifndef _TRUSS_SYSTABLE_H
+#define _TRUSS_SYSTABLE_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/socket.h>
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct systable {
+ const char *name; /* name of system call */
+ short nargs; /* number of arguments */
+ char rval[2]; /* return value types */
+ char arg[8]; /* argument types */
+};
+
+/* the system call table */
+extern const struct systable systable[];
+
+
+struct sysalias {
+ const char *name; /* alias name of system call */
+ int number; /* number of system call */
+};
+
+extern const struct sysalias sysalias[];
+
+extern const struct systable *subsys(int, int);
+
+extern const char * const afcodes[];
+#define MAX_AFCODES (AF_MAX+1)
+
+extern const char * const socktype_codes[];
+#define MAX_SOCKTYPES 7
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _TRUSS_SYSTABLE_H */