# # 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 2012 Nexenta Systems, Inc. All rights reserved. # Copyright (c) 2016 by Delphix. All rights reserved. # Copyright 2019 Joyent, Inc. # Copyright 2023 Oxide Computer Co. # PROG= truss OBJS= \ main.o \ listopts.o \ ipc.o \ actions.o \ expound.o \ codes.o \ codes_bhyve.o \ print.o \ ramdata.o \ systable.o \ procset.o \ stat.o \ fcall.o \ htbl.o .PARALLEL: $(OBJS) include ../Makefile.cmd include ../Makefile.cmd.64 include ../Makefile.ctf CTF_MODE = link CFLAGS += $(CCVERBOSE) CERRWARN += $(CNOWARN_UNINIT) CERRWARN += -Wno-switch # not linted SMATCH=off CSTD= $(CSTD_GNU99) LDLIBS += -lproc -lrtld_db -lc_db -lnsl -lsocket -ltsol -lnvpair CPPFLAGS += -D_REENTRANT CPPFLAGS += -I$(SRC)/uts/common/fs/zfs CPPFLAGS += -I$(SRC)/uts/common codes_bhyve.o : CPPFLAGS += -I$(SRC)/compat/bhyve codes_bhyve.o : CPPFLAGS += -I$(SRC)/compat/bhyve/amd64 codes_bhyve.o : CPPFLAGS += -I$(SRC)/uts/intel # Hammerhead: ROOTLINK removed — ROOTBIN64 = ROOTBIN (path flattening) .KEEP_STATE: %.o: %.c $(COMPILE.c) $< $(POST_PROCESS_O) all: $(PROG) install: all $(ROOTPROG) $(PROG): $(OBJS) $(LINK.c) $(OBJS) -o $@ $(LDLIBS) $(POST_PROCESS) clean: $(RM) $(OBJS) include ../Makefile.targ /* * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #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; /* * 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; } 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) { if (data_model == PR_MODEL_ILP32) rv1 &= 0xffffffff; 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: if (data_model == PR_MODEL_LP64) { rv2 = rv1 & 0xffffffff; rv1 = rv1 >> 32; } break; } if (fmt == NULL) { switch (stp->rval[0]) { case HEX: if (data_model == PR_MODEL_ILP32) rv1 &= 0xffffffff; fmt = "= 0x%.8lX"; break; case HHX: if (data_model == PR_MODEL_ILP32) rv1 &= 0xffffffff; fmt = "= 0x%.4lX"; break; case OCT: if (data_model == PR_MODEL_ILP32) rv1 &= 0xffffffff; fmt = "= %#lo"; break; case UNS: if (data_model == PR_MODEL_ILP32) rv1 &= 0xffffffff; fmt = "= %lu"; break; default: fmt = "= %ld"; break; } } (void) printf(fmt, rv1, rv2); switch (stp->rval[1]) { case NOV: fmt = NULL; break; case HEX: if (data_model == PR_MODEL_ILP32) rv2 &= 0xffffffff; fmt = " [0x%.8lX]"; break; case HHX: if (data_model == PR_MODEL_ILP32) rv2 &= 0xffffffff; fmt = " [0x%.4lX]"; break; case OCT: if (data_model == PR_MODEL_ILP32) rv2 &= 0xffffffff; fmt = " [%#lo]"; break; case UNS: if (data_model == PR_MODEL_ILP32) rv2 &= 0xffffffff; 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; 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; } 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'; } /* * 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) 2011, 2017 by Delphix. All rights reserved. * Copyright 2011 Nexenta Systems, Inc. All rights reserved. * Copyright 2020 Joyent, Inc. * Copyright (c) 2014, OmniTI Computer Consulting, Inc. All rights reserved. * Copyright 2022 Garrett D'Amore * Copyright 2024 Oxide Computer Company */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(__x86) #include #endif /* __x86 */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "codes.h" #include "ramdata.h" #include "proto.h" #define FCNTLMIN F_DUPFD #define FCNTLMAX F_DUP3FD const char *const FCNTLname[] = { [0] = "F_DUPFD", [1] = "F_GETFD", [2] = "F_SETFD", [3] = "F_GETFL", [4] = "F_SETFL", [5] = "F_O_GETLK", [6] = "F_SETLK", [7] = "F_SETLKW", [8] = "F_CHKFL", [9] = "F_DUP2FD", [10] = "F_ALLOCSP", [11] = "F_FREESP", [13] = "F_ISSTREAM", [14] = "F_GETLK", [15] = "F_PRIV", [16] = "F_NPRIV", [17] = "F_QUOTACTL", [18] = "F_BLOCKS", [19] = "F_BLKSIZE", [23] = "F_GETOWN", [24] = "F_SETOWN", [25] = "F_REVOKE", [26] = "F_HASREMOTELOCKS", [27] = "F_FREESP64", [28] = "F_ALLOCSP64", [33] = "F_GETLK64", [34] = "F_SETLK64", [35] = "F_SETLKW64", [36] = "F_DUP2FD_CLOEXEC", [37] = "F_DUPFD_CLOEXEC", [40] = "F_SHARE", [41] = "F_UNSHARE", [42] = "F_SETLK_NBMAND", [43] = "F_SHARE_NBMAND", [44] = "F_SETLK64_NBMAND", [45] = "F_GETXFL", [46] = "F_BADFD", [47] = "F_OFD_GETLK", [48] = "F_OFD_SETLK", [49] = "F_OFD_SETLKW", [50] = "F_OFD_GETLK64", [51] = "F_OFD_SETLK64", [52] = "F_OFD_SETLKW64", [53] = "F_FLOCK", [54] = "F_FLOCKW", [55] = "F_FLOCK64", [56] = "F_FLOCKW64", [57] = "F_DUP2FD_CLOFORK", [58] = "F_DUPFD_CLOFORK", [59] = "F_DUP3FD" }; #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 Tioc[] = { /* ('T'<<8) */ { (uint_t)TCGETA, "TCGETA", NULL }, /* 1 */ { (uint_t)TCSETA, "TCSETA", NULL }, /* 2 */ { (uint_t)TCSETAW, "TCSETAW", NULL }, /* 3 */ { (uint_t)TCSETAF, "TCSETAF", NULL }, /* 4 */ { (uint_t)TCSBRK, "TCSBRK", NULL }, /* 5 */ { (uint_t)TCXONC, "TCXONC", NULL }, /* 6 */ { (uint_t)TCFLSH, "TCFLSH", NULL }, /* 7 */ { (uint_t)TIOCKBON, "TIOCKBON", NULL }, /* 8 */ { (uint_t)TIOCKBOF, "TIOCKBOF", NULL }, /* 9 */ { (uint_t)KBENABLED, "KBENABLED", NULL }, /* 10 */ { (uint_t)TCGETS, "TCGETS", NULL }, /* 13 */ { (uint_t)TCSETS, "TCSETS", NULL }, /* 14 */ { (uint_t)TCSETSW, "TCSETSW", NULL }, /* 15 */ { (uint_t)TCSETSF, "TCSETSF", NULL }, /* 16 */ { (uint_t)TCDSET, "TCDSET", NULL }, /* 32 */ { (uint_t)RTS_TOG, "RTS_TOG", NULL }, /* 33 */ { (uint_t)TIOCSWINSZ, "TIOCSWINSZ", NULL }, /* 103 */ { (uint_t)TIOCGWINSZ, "TIOCGWINSZ", NULL }, /* 104 */ { (uint_t)TIOCGPPS, "TIOCGPPS", NULL }, /* 125 */ { (uint_t)TIOCSPPS, "TIOCSPPS", NULL }, /* 126 */ { (uint_t)TIOCGPPSEV, "TIOCGPPSEV", NULL }, /* 127 */ }; const struct ioc tioc[] = { /* ('t'<<8) */ { (uint_t)TIOCGETD, "TIOCGETD", NULL }, /* 0 */ { (uint_t)TIOCSETD, "TIOCSETD", NULL }, /* 1 */ { (uint_t)TIOCHPCL, "TIOCHPCL", NULL }, /* 2 */ { (uint_t)TIOCGETP, "TIOCGETP", NULL }, /* 8 */ { (uint_t)TIOCSETP, "TIOCSETP", NULL }, /* 9 */ { (uint_t)TIOCSETN, "TIOCSETN", NULL }, /* 10 */ { (uint_t)TIOCEXCL, "TIOCEXCL", NULL }, /* 13 */ { (uint_t)TIOCNXCL, "TIOCNXCL", NULL }, /* 14 */ { (uint_t)TIOCFLUSH, "TIOCFLUSH", NULL }, /* 16 */ { (uint_t)TIOCSETC, "TIOCSETC", NULL }, /* 17 */ { (uint_t)TIOCGETC, "TIOCGETC", NULL }, /* 18 */ { (uint_t)TIOCGPGRP, "TIOCGPGRP", NULL }, /* 20 */ { (uint_t)TIOCSPGRP, "TIOCSPGRP", NULL }, /* 21 */ { (uint_t)TIOCGSID, "TIOCGSID", NULL }, /* 22 */ { (uint_t)TIOCSTI, "TIOCSTI", NULL }, /* 23 */ { (uint_t)TIOCMSET, "TIOCMSET", NULL }, /* 26 */ { (uint_t)TIOCMBIS, "TIOCMBIS", NULL }, /* 27 */ { (uint_t)TIOCMBIC, "TIOCMBIC", NULL }, /* 28 */ { (uint_t)TIOCMGET, "TIOCMGET", NULL }, /* 29 */ { (uint_t)TIOCREMOTE, "TIOCREMOTE", NULL }, /* 30 */ { (uint_t)TIOCSIGNAL, "TIOCSIGNAL", NULL }, /* 31 */ { (uint_t)TIOCCILOOP, "TIOCSILOOP", NULL }, /* 108 */ { (uint_t)TIOCSILOOP, "TIOCSILOOP", NULL }, /* 109 */ { (uint_t)TIOCSTART, "TIOCSTART", NULL }, /* 110 */ { (uint_t)TIOCSTOP, "TIOCSTOP", NULL }, /* 111 */ { (uint_t)TIOCNOTTY, "TIOCNOTTY", NULL }, /* 113 */ { (uint_t)TIOCOUTQ, "TIOCOUTQ", NULL }, /* 115 */ { (uint_t)TIOCGLTC, "TIOCGLTC", NULL }, /* 116 */ { (uint_t)TIOCSLTC, "TIOCSLTC", NULL }, /* 117 */ { (uint_t)TIOCCDTR, "TIOCCDTR", NULL }, /* 120 */ { (uint_t)TIOCSDTR, "TIOCSDTR", NULL }, /* 121 */ { (uint_t)TIOCCBRK, "TIOCCBRK", NULL }, /* 122 */ { (uint_t)TIOCSBRK, "TIOCSBRK", NULL }, /* 123 */ { (uint_t)TIOCLGET, "TIOCLGET", NULL }, /* 124 */ { (uint_t)TIOCLSET, "TIOCLSET", NULL }, /* 125 */ { (uint_t)TIOCLBIC, "TIOCLBIC", NULL }, /* 126 */ { (uint_t)TIOCLBIS, "TIOCLBIS", NULL }, /* 127 */ { (uint_t)TIOCSCTTY, "TIOCSCTTY", NULL }, /* 132 */ }; const struct ioc pty_ioc[] = { /* ('t'<<8) */ { (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" } }; const struct ioc dlpi_ioc[] = { /* ('D'<<8) */ /* * 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 }, /* 1 */ { (uint_t)DLIOCNATIVE, "DLIOCNATIVE", NULL }, /* 2 */ { (uint_t)DLIOCMARGININFO, "DLIOCMARGININFO", NULL }, /* 3 */ { (uint_t)DLIOCIPNETINFO, "DLIOCIPNETINFO", NULL}, /* 4 */ { (uint_t)DLIOCLOWLINK, "DLIOCLOWLINK", NULL }, /* 5 */ { (uint_t)DLIOCHDRINFO, "DLIOCHDRINFO", NULL }, /* 10 */ }; const struct ioc ldioc_ioc[] = { /* ('D'<<8) */ { (uint_t)LDOPEN, "LDOPEN", NULL }, /* 0 */ { (uint_t)LDCLOSE, "LDCLOSE", NULL }, /* 1 */ { (uint_t)LDCHG, "LDCHG", NULL }, /* 2 */ { (uint_t)LDGETT, "LDGETT", NULL }, /* 8 */ { (uint_t)LDSETT, "LDSETT", NULL }, /* 9 */ { (uint_t)LDSMAP, "LDSMAP", NULL }, /* 110 */ { (uint_t)LDGMAP, "LDGMAP", NULL }, /* 111 */ { (uint_t)LDNMAP, "LDNMAP", NULL }, /* 112 */ { (uint_t)LDEMAP, "LDEMAP", NULL }, /* 113 */ { (uint_t)LDDMAP, "LDDMAP", NULL }, /* 114 */ }; const struct ioc xioc_ioc[] = { /* ('X'<<8) */ { (uint_t)TCGETX, "TCGETX", NULL }, /* 1 */ { (uint_t)TCSETX, "TCSETX", NULL }, /* 2 */ { (uint_t)TCSETXW, "TCSETXW", NULL }, /* 3 */ { (uint_t)TCSETXF, "TCSETXF", NULL }, /* 4 */ }; const struct ioc fio_ioc[] = { /* ('f'<<8) */ { (uint_t)FIORDCHK, "FIORDCHK", NULL }, /* 3 */ }; const struct ioc fil_ioc[] = { { (uint_t)FIOCLEX, "FIOCLEX", NULL }, /* 1 */ { (uint_t)FIONCLEX, "FIONCLEX", NULL }, /* 2 */ { (uint_t)FIOGETOWN, "FIOGETOWN", NULL }, /* 123 */ { (uint_t)FIOSETOWN, "FIOSETOWN", NULL }, /* 124 */ { (uint_t)FIOASYNC, "FIOASYNC", NULL }, /* 125 */ { (uint_t)FIONBIO, "FIONBIO", NULL }, /* 126 */ { (uint_t)FIONREAD, "FIONREAD", NULL }, /* 127 */ }; const struct ioc dioc_ioc[] = { /* ('d'<<8) */ { (uint_t)DIOCGETC, "DIOCGETC", NULL }, /* 1 */ { (uint_t)DIOCGETB, "DIOCGETB", NULL }, /* 2 */ { (uint_t)DIOCSETE, "DIOCSETE", NULL }, /* 3 */ { (uint_t)DIOCGETP, "DIOCGETP", NULL }, /* 8 */ { (uint_t)DIOCSETP, "DIOCSETP", NULL }, /* 9 */ }; const struct ioc lioc_ioc[] = { /* ('l'<<8) */ { (uint_t)LIOCGETP, "LIOCGETP", NULL }, /* 1 */ { (uint_t)LIOCSETP, "LIOCSETP", NULL }, /* 2 */ { (uint_t)LIOCGETS, "LIOCGETS", NULL }, /* 5 */ { (uint_t)LIOCSETS, "LIOCSETS", NULL }, /* 6 */ }; const struct ioc jerq_ioc[] = { /* ('j'<<8) */ { (uint_t)JBOOT, "JBOOT", NULL }, /* 1 */ { (uint_t)JTERM, "JTERM", NULL }, /* 2 */ { (uint_t)JMPX, "JMPX", NULL }, /* 3 */ { (uint_t)JWINSIZE, "JWINSIZE", NULL }, /* 5 */ { (uint_t)JTIMOM, "JTIMOM", NULL }, /* 6 */ { (uint_t)JZOMBOOT, "JZOMBOOT", NULL }, /* 7 */ { (uint_t)JAGENT, "JAGENT", NULL }, /* 9 */ { (uint_t)JTRUN, "JTRUN", NULL }, /* 10 */ { (uint_t)JXTPROTO, "JXTPROTO", NULL }, /* 11 */ }; const struct ioc kstat_ioc[] = { /* ('K'<<8) */ { (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 }, }; const struct ioc stream_ioc[] = { /* ('X'<<8) */ { (uint_t)STGET, "STGET", NULL }, /* 0 */ { (uint_t)STSET, "STSET", NULL }, /* 1 */ { (uint_t)STTHROW, "STTHROW", NULL }, /* 2 */ { (uint_t)STWLINE, "STWLINE", NULL }, /* 3 */ { (uint_t)STTSV, "STTSV", NULL }, /* 4 */ }; const struct ioc str_ioc[] = { /* ('S'<<8) */ { (uint_t)I_NREAD, "I_NREAD", NULL }, /* 1 */ { (uint_t)I_PUSH, "I_PUSH", NULL }, /* 2 */ { (uint_t)I_POP, "I_POP", NULL }, /* 3 */ { (uint_t)I_LOOK, "I_LOOK", NULL }, /* 4 */ { (uint_t)I_FLUSH, "I_FLUSH", NULL }, /* 5 */ { (uint_t)I_SRDOPT, "I_SRDOPT", NULL }, /* 6 */ { (uint_t)I_GRDOPT, "I_GRDOPT", NULL }, /* 7 */ { (uint_t)I_STR, "I_STR", NULL }, /* 10 */ { (uint_t)I_SETSIG, "I_SETSIG", NULL }, /* 11 */ { (uint_t)I_GETSIG, "I_GETSIG", NULL }, /* 12 */ { (uint_t)I_FIND, "I_FIND", NULL }, /* 13 */ { (uint_t)I_LINK, "I_LINK", NULL }, /* 14 */ { (uint_t)I_UNLINK, "I_UNLINK", NULL }, /* 15 */ { (uint_t)I_PEEK, "I_PEEK", NULL }, /* 17 */ { (uint_t)I_FDINSERT, "I_FDINSERT", NULL }, /* 20 */ { (uint_t)I_SENDFD, "I_SENDFD", NULL }, /* 21 */ { (uint_t)I_RECVFD, "I_RECVFD", NULL }, /* 16 */ { (uint_t)I_SWROPT, "I_SWROPT", NULL }, /* 23 */ { (uint_t)I_GWROPT, "I_GWROPT", NULL }, /* 24 */ { (uint_t)I_LIST, "I_LIST", NULL }, /* 25 */ { (uint_t)I_PLINK, "I_PLINK", NULL }, /* 26 */ { (uint_t)I_PUNLINK, "I_PUNLINK", NULL }, /* 27 */ { (uint_t)I_ANCHOR, "I_ANCHOR", NULL }, /* 30 */ { (uint_t)I_FLUSHBAND, "I_FLUSHBAND", NULL }, /* 34 */ { (uint_t)I_CKBAND, "I_CKBAND", NULL }, /* 35 */ { (uint_t)I_GETBAND, "I_GETBAND", NULL }, /* 36 */ { (uint_t)I_ATMARK, "I_ATMARK", NULL }, /* 37 */ { (uint_t)I_SETCLTIME, "I_SETCLTIME", NULL }, /* 40 */ { (uint_t)I_GETCLTIME, "I_GETCLTIME", NULL }, /* 41 */ { (uint_t)I_CANPUT, "I_CANPUT", NULL }, /* 42 */ { (uint_t)I_SERROPT, "I_SERROPT", NULL }, /* 43 */ { (uint_t)I_GERROPT, "I_GERROPT", NULL }, /* 44 */ { (uint_t)I_ESETSIG, "I_ESETSIG", NULL }, /* 45 */ { (uint_t)I_EGETSIG, "I_EGETSIG", NULL }, /* 46 */ { (uint_t)_I_CMD, "_I_CMD", NULL }, /* 63 */ }; const struct ioc timod_ioc[] = { /* ('T'<<8) */ { (uint_t)TI_GETINFO, "TI_GETINFO", NULL }, /* 140 */ { (uint_t)TI_OPTMGMT, "TI_OPTMGMT", NULL }, /* 141 */ { (uint_t)TI_BIND, "TI_BIND", NULL }, /* 142 */ { (uint_t)TI_UNBIND, "TI_UNBIND", NULL }, /* 143 */ { (uint_t)TI_GETMYNAME, "TI_GETMYNAME", NULL }, /* 144 */ { (uint_t)TI_GETPEERNAME, "TI_GETPEERNAME", NULL }, /* 145 */ { (uint_t)TI_SETMYNAME, "TI_SETMYNAME", NULL }, /* 146 */ { (uint_t)TI_SETPEERNAME, "TI_SETPEERNAME", NULL }, /* 147 */ { (uint_t)TI_SYNC, "TI_SYNC", NULL }, /* 148 */ { (uint_t)TI_GETADDRS, "TI_GETADDRS", NULL }, /* 149 */ { (uint_t)TI_CAPABILITY, "TI_CAPABILITY", NULL }, /* 150 */ }; const struct ioc audio_ioc[] = { /* ('A'<<8) */ { (uint_t)AUDIO_GETINFO, "AUDIO_GETINFO", NULL }, /* 1 */ { (uint_t)AUDIO_SETINFO, "AUDIO_SETINFO", NULL }, /* 2 */ { (uint_t)AUDIO_DRAIN, "AUDIO_DRAIN", NULL }, /* 3 */ { (uint_t)AUDIO_GETDEV, "AUDIO_GETDEV", NULL }, /* 4 */ { (uint_t)AUDIO_DIAG_LOOPBACK, "AUDIO_DIAG_LOOPBACK", NULL }, /* 101 */ { (uint_t)AUDIO_GET_CH_NUMBER, "AUDIO_GET_CH_NUMBER", NULL }, /* 10 */ { (uint_t)AUDIO_GET_CH_TYPE, "AUDIO_GET_CH_TYPE", NULL }, /* 11 */ { (uint_t)AUDIO_GET_NUM_CHS, "AUDIO_GET_NUM_CHS", NULL }, /* 12 */ { (uint_t)AUDIO_GET_AD_DEV, "AUDIO_GET_AD_DEV", NULL }, /* 13 */ { (uint_t)AUDIO_GET_APM_DEV, "AUDIO_GET_APM_DEV", NULL }, /* 14 */ { (uint_t)AUDIO_GET_AS_DEV, "AUDIO_GET_AS_DEV", NULL }, /* 15 */ }; const struct ioc audiom_ioc[] = { /* ('M'<<8) */ { (uint_t)AUDIO_MIXER_MULTIPLE_OPEN, "AUDIO_MIXER_MULTIPLE_OPEN", NULL }, /* 10 */ { (uint_t)AUDIO_MIXER_SINGLE_OPEN, "AUDIO_MIXER_SINGLE_OPEN", NULL }, /* 11 */ { (uint_t)AUDIO_MIXER_GET_SAMPLE_RATES, "AUDIO_MIXER_GET_SAMPLE_RATES", NULL }, /* 12 */ { (uint_t)AUDIO_MIXERCTL_GETINFO, "AUDIO_MIXERCTL_GETINFO", NULL }, /* 13 */ { (uint_t)AUDIO_MIXERCTL_SETINFO, "AUDIO_MIXERCTL_SETINFO", NULL }, /* 14 */ { (uint_t)AUDIO_MIXERCTL_GET_CHINFO, "AUDIO_MIXERCTL_GET_CHINFO", NULL }, /* 15 */ { (uint_t)AUDIO_MIXERCTL_SET_CHINFO, "AUDIO_MIXERCTL_SET_CHINFO", NULL }, /* 16 */ { (uint_t)AUDIO_MIXERCTL_GET_MODE, "AUDIO_MIXERCTL_GET_MODE", NULL }, /* 17 */ { (uint_t)AUDIO_MIXERCTL_SET_MODE, "AUDIO_MIXERCTL_SET_MODE", NULL }, /* 18 */ }; const struct ioc ossx_ioc[] = { /* ('X'<<8) */ /* new style Boomer (OSS) ioctls */ { (uint_t)SNDCTL_SYSINFO, "SNDCTL_SYSINFO", NULL }, /* 1 */ { (uint_t)SNDCTL_MIX_NRMIX, "SNDCTL_MIX_NRMIX", NULL }, /* 2 */ { (uint_t)SNDCTL_MIX_NREXT, "SNDCTL_MIX_NREXT", NULL }, /* 3 */ { (uint_t)SNDCTL_MIX_EXTINFO, "SNDCTL_MIX_EXTINFO", NULL }, /* 4 */ { (uint_t)SNDCTL_MIX_READ, "SNDCTL_MIX_READ", NULL }, /* 5 */ { (uint_t)SNDCTL_MIX_WRITE, "SNDCTL_MIX_WRITE", NULL }, /* 6 */ { (uint_t)SNDCTL_AUDIOINFO, "SNDCTL_AUDIOINFO", NULL }, /* 7 */ { (uint_t)SNDCTL_MIX_ENUMINFO, "SNDCTL_MIX_ENUMINFO", NULL }, /* 8 */ { (uint_t)SNDCTL_MIDIINFO, "SNDCTL_MIDIINFO", NULL }, /* 9 */ { (uint_t)SNDCTL_MIXERINFO, "SNDCTL_MIXERINFO", NULL }, /* 10 */ { (uint_t)SNDCTL_CARDINFO, "SNDCTL_CARDINFO", NULL }, /* 11 */ { (uint_t)SNDCTL_ENGINEINFO, "SNDCTL_ENGINEINFO", NULL }, /* 12 */ { (uint_t)SNDCTL_AUDIOINFO_EX, "SNDCTL_AUDIOINFO_EX", NULL }, /* 13 */ { (uint_t)SNDCTL_MIX_DESCRIPTION, "SNDCTL_MIX_DESCRIPTION", NULL }, /* 14 */ }; const struct ioc ossy_ioc[] = { /* ('Y'<<8) */ { (uint_t)SNDCTL_SETSONG, "SNDCTL_SETSONG", NULL }, /* 2 */ { (uint_t)SNDCTL_GETSONG, "SNDCTL_GETSONG", NULL }, /* 2 */ { (uint_t)SNDCTL_SETNAME, "SNDCTL_SETNAME", NULL }, /* 3 */ { (uint_t)SNDCTL_SETLABEL, "SNDCTL_SETLABEL", NULL }, /* 4 */ { (uint_t)SNDCTL_GETLABEL, "SNDCTL_GETLABEL", NULL }, /* 4 */ }; const struct ioc ossp_ioc[] = { /* ('P'<<8) */ { (uint_t)SNDCTL_DSP_HALT, "SNDCTL_DSP_HALT", NULL }, /* 0 */ { (uint_t)SNDCTL_DSP_SYNC, "SNDCTL_DSP_SYNC", NULL }, /* 1 */ { (uint_t)SNDCTL_DSP_SPEED, "SNDCTL_DSP_SPEED", NULL }, /* 2 */ { (uint_t)SNDCTL_DSP_STEREO, "SNDCTL_DSP_STEREO", NULL }, /* 3 */ { (uint_t)SNDCTL_DSP_GETBLKSIZE, "SNDCTL_DSP_GETBLKSIZE", NULL }, /* 4 */ { (uint_t)SNDCTL_DSP_SAMPLESIZE, "SNDCTL_DSP_SAMPLESIZE", NULL }, /* 5 */ { (uint_t)SNDCTL_DSP_CHANNELS, "SNDCTL_DSP_CHANNELS", NULL }, /* 6 */ { (uint_t)SNDCTL_DSP_POST, "SNDCTL_DSP_POST", NULL }, /* 8 */ { (uint_t)SNDCTL_DSP_SUBDIVIDE, "SNDCTL_DSP_SUBDIVIDE", NULL }, /* 9 */ { (uint_t)SNDCTL_DSP_SETFRAGMENT, "SNDCTL_DSP_SETFRAGMENT", NULL }, /* 10 */ { (uint_t)SNDCTL_DSP_GETFMTS, "SNDCTL_DSP_GETFMTS", NULL }, /* 11 */ { (uint_t)SNDCTL_DSP_SETFMT, "SNDCTL_DSP_SETFMT", NULL }, /* 5 */ { (uint_t)SNDCTL_DSP_GETOSPACE, "SNDCTL_DSP_GETOSPACE", NULL }, /* 12 */ { (uint_t)SNDCTL_DSP_GETISPACE, "SNDCTL_DSP_GETISPACE", NULL }, /* 13 */ { (uint_t)SNDCTL_DSP_GETCAPS, "SNDCTL_DSP_CAPS", NULL }, /* 15 */ { (uint_t)SNDCTL_DSP_GETTRIGGER, "SNDCTL_DSP_GETTRIGGER", NULL }, /* 16 */ { (uint_t)SNDCTL_DSP_SETTRIGGER, "SNDCTL_DSP_SETTRIGGER", NULL }, /* 16 */ { (uint_t)SNDCTL_DSP_GETIPTR, "SNDCTL_DSP_GETIPTR", NULL }, /* 17 */ { (uint_t)SNDCTL_DSP_GETOPTR, "SNDCTL_DSP_GETOPTR", NULL }, /* 18 */ { (uint_t)SNDCTL_DSP_SETSYNCRO, "SNDCTL_DSP_SETSYNCRO", NULL }, /* 21 */ { (uint_t)SNDCTL_DSP_SETDUPLEX, "SNDCTL_DSP_SETDUPLEX", NULL }, /* 22 */ { (uint_t)SNDCTL_DSP_PROFILE, "SNDCTL_DSP_PROFILE", NULL }, /* 23 */ { (uint_t)SNDCTL_DSP_GETODELAY, "SNDCTL_DSP_GETODELAY", NULL }, /* 23 */ { (uint_t)SNDCTL_DSP_GETPLAYVOL, "SNDCTL_DSP_GETPLAYVOL", NULL }, /* 24 */ { (uint_t)SNDCTL_DSP_SETPLAYVOL, "SNDCTL_DSP_SETPLAYVOL", NULL }, /* 24 */ { (uint_t)SNDCTL_DSP_GETERROR, "SNDCTL_DSP_GETERROR", NULL }, /* 25 */ { (uint_t)SNDCTL_DSP_READCTL, "SNDCTL_DSP_READCTL", NULL }, /* 26 */ { (uint_t)SNDCTL_DSP_WRITECTL, "SNDCTL_DSP_WRITECTL", NULL }, /* 27 */ { (uint_t)SNDCTL_DSP_SYNCGROUP, "SNDCTL_DSP_SYNCGROUP", NULL }, /* 28 */ { (uint_t)SNDCTL_DSP_SYNCSTART, "SNDCTL_DSP_SYNCSTART", NULL }, /* 29 */ { (uint_t)SNDCTL_DSP_COOKEDMODE, "SNDCTL_DSP_COOKEDMODE", NULL }, /* 30 */ { (uint_t)SNDCTL_DSP_SILENCE, "SNDCTL_DSP_SILENCE", NULL }, /* 31 */ { (uint_t)SNDCTL_DSP_SKIP, "SNDCTL_DSP_SKIP", NULL }, /* 32 */ { (uint_t)SNDCTL_DSP_HALT_INPUT, "SNDCTL_DSP_HALT_INPUT", NULL }, /* 33 */ { (uint_t)SNDCTL_DSP_HALT_OUTPUT, "SNDCTL_DSP_HALT_OUTPUT", NULL }, /* 34 */ { (uint_t)SNDCTL_DSP_LOW_WATER, "SNDCTL_DSP_LOW_WATER", NULL }, /* 34 */ { (uint_t)SNDCTL_DSP_CURRENT_IPTR, "SNDCTL_DSP_CURRENT_IPTR", NULL }, /* 35 */ { (uint_t)SNDCTL_DSP_CURRENT_OPTR, "SNDCTL_DSP_CURRENT_OPTR", NULL }, /* 36 */ { (uint_t)SNDCTL_DSP_GET_RECSRC_NAMES, "SNDCTL_DSP_GET_RECSRC_NAMES", NULL }, /* 37 */ { (uint_t)SNDCTL_DSP_GET_RECSRC, "SNDCTL_DSP_GET_RECSRC", NULL }, /* 38 */ { (uint_t)SNDCTL_DSP_SET_RECSRC, "SNDCTL_DSP_SET_RECSRC", NULL }, /* 38 */ { (uint_t)SNDCTL_DSP_GET_PLAYTGT_NAMES, "SNDCTL_DSP_GET_PLAYTGT_NAMES", NULL }, /* 39 */ { (uint_t)SNDCTL_DSP_GET_PLAYTGT, "SNDCTL_DSP_GET_PLAYTGT", NULL }, /* 40 */ { (uint_t)SNDCTL_DSP_SET_PLAYTGT, "SNDCTL_DSP_SET_PLAYTGT", NULL }, /* 40 */ { (uint_t)SNDCTL_DSP_GETRECVOL, "SNDCTL_DSP_GETRECVOL", NULL }, /* 41 */ { (uint_t)SNDCTL_DSP_SETRECVOL, "SNDCTL_DSP_SETRECVOL", NULL }, /* 41 */ { (uint_t)SNDCTL_DSP_GET_CHNORDER, "SNDCTL_DSP_GET_CHNORDER", NULL }, /* 42 */ { (uint_t)SNDCTL_DSP_SET_CHNORDER, "SNDCTL_DSP_SET_CHNORDER", NULL }, /* 42 */ { (uint_t)SNDCTL_DSP_GETIPEAKS, "SNDCTL_DSP_GETIPEAKS", NULL }, /* 43 */ { (uint_t)SNDCTL_DSP_GETOPEAKS, "SNDCTL_DSP_GETOPEAKS", NULL }, /* 44 */ { (uint_t)SNDCTL_DSP_POLICY, "SNDCTL_DSP_POLICY", NULL }, /* 45 */ { (uint_t)SNDCTL_DSP_GETCHANNELMASK, "SNDCTL_DSP_GETCHANNELMASK", NULL }, /* 64 */ { (uint_t)SNDCTL_DSP_BIND_CHANNEL, "SNDCTL_DSP_BIND_CHANNEL", NULL }, /* 65 */ }; const struct ioc ossm_ioc[] = { /* ('M'<<8) */ { (uint_t)SOUND_MIXER_READ_VOLUME, "SOUND_MIXER_READ_VOLUME", NULL }, /* 0 */ { (uint_t)SOUND_MIXER_READ_OGAIN, "SOUND_MIXER_READ_OGAIN", NULL }, /* 13 */ { (uint_t)SOUND_MIXER_READ_PCM, "SOUND_MIXER_READ_PCM", NULL }, /* 4 */ { (uint_t)SOUND_MIXER_READ_IGAIN, "SOUND_MIXER_READ_IGAIN", NULL }, /* 12 */ { (uint_t)SOUND_MIXER_READ_RECLEV, "SOUND_MIXER_READ_RECLEV", NULL }, /* 11 */ { (uint_t)SOUND_MIXER_READ_RECSRC, "SOUND_MIXER_READ_RECSRC", NULL }, /* 0xff */ { (uint_t)SOUND_MIXER_READ_DEVMASK, "SOUND_MIXER_READ_DEVMASK", NULL }, /* 0xfe */ { (uint_t)SOUND_MIXER_READ_RECMASK, "SOUND_MIXER_READ_RECMASK", NULL }, /* 0xfd */ { (uint_t)SOUND_MIXER_READ_CAPS, "SOUND_MIXER_READ_CAPS", NULL }, /* 0xfc */ { (uint_t)SOUND_MIXER_READ_STEREODEVS, "SOUND_MIXER_READ_STEREODEVS", NULL }, /* 0xfb */ { (uint_t)SOUND_MIXER_READ_RECGAIN, "SOUND_MIXER_READ_RECGAIN", NULL }, /* 119 */ { (uint_t)SOUND_MIXER_READ_MONGAIN, "SOUND_MIXER_READ_MONGAIN", NULL }, /* 120 */ { (uint_t)SOUND_MIXER_WRITE_VOLUME, "SOUND_MIXER_WRITE_VOLUME", NULL }, /* 0 */ { (uint_t)SOUND_MIXER_WRITE_OGAIN, "SOUND_MIXER_WRITE_OGAIN", NULL }, /* 13 */ { (uint_t)SOUND_MIXER_WRITE_PCM, "SOUND_MIXER_WRITE_PCM", NULL }, /* 4 */ { (uint_t)SOUND_MIXER_WRITE_IGAIN, "SOUND_MIXER_WRITE_IGAIN", NULL }, /* 12 */ { (uint_t)SOUND_MIXER_WRITE_RECLEV, "SOUND_MIXER_WRITE_RECLEV", NULL }, /* 11 */ { (uint_t)SOUND_MIXER_WRITE_RECSRC, "SOUND_MIXER_WRITE_RECSRC", NULL }, /* 0xff */ { (uint_t)SOUND_MIXER_WRITE_RECGAIN, "SOUND_MIXER_WRITE_RECGAIN", NULL }, /* 119 */ { (uint_t)SOUND_MIXER_WRITE_MONGAIN, "SOUND_MIXER_WRITE_MONGAIN", NULL }, /* 120 */ }; const struct ioc strredir_ioc[] = { /* STRREDIR_MODID<<16 or 0 */ /* STREAMS redirection ioctls */ { (uint_t)SRIOCSREDIR, "SRIOCSREDIR", NULL }, /* 1 */ { (uint_t)SRIOCISREDIR, "SRIOCISREDIR", NULL }, /* 2 */ }; const struct ioc cpc_ioc[] = { /* (((('c'<<8)|'p')<<8)|'c')<<8 */ { (uint_t)CPCIO_BIND, "CPCIO_BIND", NULL }, /* 1 */ { (uint_t)CPCIO_SAMPLE, "CPCIO_SAMPLE", NULL }, /* 2 */ { (uint_t)CPCIO_RELE, "CPCIO_RELE", NULL }, /* 3 */ }; const struct ioc dp_ioc[] = { /* 0xD0<<8 */ /* /dev/poll ioctl() control codes */ { (uint_t)DP_POLL, "DP_POLL", NULL }, { (uint_t)DP_ISPOLLED, "DP_ISPOLLED", NULL }, { (uint_t)DP_PPOLL, "DP_PPOLL", NULL }, { (uint_t)DP_EPOLLCOMPAT, "DP_EPOLLCOMPAT", NULL }, }; const struct ioc p_ioc[] = { /* 'q'<<8 */ /* 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 }, }; const struct ioc socket_ioc[] = { /* 's'<<8 */ /* ioctl's applicable on sockets */ { (uint_t)SIOCSHIWAT, "SIOCSHIWAT", NULL }, /* 0 */ { (uint_t)SIOCGHIWAT, "SIOCGHIWAT", NULL }, /* 1 */ { (uint_t)SIOCSLOWAT, "SIOCSLOWAT", NULL }, /* 2 */ { (uint_t)SIOCGLOWAT, "SIOCGLOWAT", NULL }, /* 3 */ { (uint_t)SIOCATMARK, "SIOCATMARK", NULL }, /* 7 */ { (uint_t)SIOCSPGRP, "SIOCSPGRP", NULL }, /* 8 */ { (uint_t)SIOCGPGRP, "SIOCGPGRP", NULL }, /* 9 */ { (uint_t)SIOCGETNAME, "SIOCGETNAME", "sockaddr" }, /* 52 */ { (uint_t)SIOCGETPEER, "SIOCGETPEER", "sockaddr" }, /* 53 */ { (uint_t)IF_UNITSEL, "IF_UNITSEL", NULL }, /* 54 */ { (uint_t)SIOCXPROTO, "SIOCXPROTO", NULL }, /* 55 */ }; const struct ioc routing_ioc[] = { /* 'r'<<8 */ { (uint_t)SIOCADDRT, "SIOCADDRT", "rtentry" }, /* 10 */ { (uint_t)SIOCDELRT, "SIOCDELRT", "rtentry" }, /* 11 */ { (uint_t)SIOCGETVIFCNT, "SIOCGETVIFCNT", "sioc_vif_req" }, /* 20 */ { (uint_t)SIOCGETSGCNT, "SIOCGETSGCNT", "sioc_sg_req" }, /* 21 */ { (uint_t)SIOCGETLSGCNT, "SIOCGETLSGCNT", "sioc_lsg_req" }, /* 21 */ }; const struct ioc sockio_ioc[] = { /* 'i'<<8 */ { (uint_t)SIOCSIFADDR, "SIOCSIFADDR", "ifreq" }, /* 12 */ { (uint_t)SIOCGIFADDR, "SIOCGIFADDR", "ifreq" }, /* 13 */ { (uint_t)SIOCSIFDSTADDR, "SIOCSIFDSTADDR", "ifreq" }, /* 14 */ { (uint_t)SIOCGIFDSTADDR, "SIOCGIFDSTADDR", "ifreq" }, /* 15 */ { (uint_t)SIOCSIFFLAGS, "SIOCSIFFLAGS", "ifreq" }, /* 16 */ { (uint_t)SIOCGIFFLAGS, "SIOCGIFFLAGS", "ifreq" }, /* 17 */ { (uint_t)SIOCSIFMEM, "SIOCSIFMEM", "ifreq" }, /* 18 */ { (uint_t)SIOCGIFMEM, "SIOCGIFMEM", "ifreq" }, /* 19 */ { (uint_t)SIOCSIFMTU, "SIOCSIFMTU", "ifreq" }, /* 21 */ { (uint_t)SIOCGIFMTU, "SIOCGIFMTU", "ifreq" }, /* 22 */ { (uint_t)SIOCGIFBRDADDR, "SIOCGIFBRDADDR", "ifreq" }, /* 23 */ { (uint_t)SIOCSIFBRDADDR, "SIOCSIFBRDADDR", "ifreq" }, /* 24 */ { (uint_t)SIOCGIFNETMASK, "SIOCGIFNETMASK", "ifreq" }, /* 25 */ { (uint_t)SIOCSIFNETMASK, "SIOCSIFNETMASK", "ifreq" }, /* 26 */ { (uint_t)SIOCGIFMETRIC, "SIOCGIFMETRIC", "ifreq" }, /* 27 */ { (uint_t)SIOCSIFMETRIC, "SIOCSIFMETRIC", "ifreq" }, /* 28 */ { (uint_t)SIOCSARP, "SIOCSARP", "arpreq" }, /* 30 */ { (uint_t)SIOCGARP, "SIOCGARP", "arpreq" }, /* 31 */ { (uint_t)SIOCDARP, "SIOCDARP", "arpreq" }, /* 32 */ { (uint_t)SIOCUPPER, "SIOCUPPER", "ifreq" }, /* 40 */ { (uint_t)SIOCLOWER, "SIOCLOWER", "ifreq" }, /* 41 */ { (uint_t)SIOCSETSYNC, "SIOCSETSYNC", "ifreq" }, /* 44 */ { (uint_t)SIOCGETSYNC, "SIOCGETSYNC", "ifreq" }, /* 45 */ { (uint_t)SIOCSSDSTATS, "SIOCSSDSTATS", "ifreq" }, /* 46 */ { (uint_t)SIOCSSESTATS, "SIOCSSESTATS", "ifreq" }, /* 47 */ { (uint_t)SIOCSPROMISC, "SIOCSPROMISC", NULL }, /* 48 */ { (uint_t)SIOCADDMULTI, "SIOCADDMULTI", "ifreq" }, /* 49 */ { (uint_t)SIOCDELMULTI, "SIOCDELMULTI", "ifreq" }, /* 50 */ { (uint_t)SIOCIFDETACH, "SIOCIFDETACH", "ifreq" }, /* 56 */ { (uint_t)SIOCGENPSTATS, "SIOCGENPSTATS", "ifreq" }, /* 57 */ { (uint_t)SIOCX25XMT, "SIOCX25XMT", "ifreq" }, /* 59 */ { (uint_t)SIOCX25RCV, "SIOCX25RCV", "ifreq" }, /* 60 */ { (uint_t)SIOCX25TBL, "SIOCX25TBL", "ifreq" }, /* 61 */ { (uint_t)SIOCSLGETREQ, "SIOCSLGETREQ", "ifreq" }, /* 71 */ { (uint_t)SIOCSLSTAT, "SIOCSLSTAT", "ifreq" }, /* 72 */ { (uint_t)SIOCSIFNAME, "SIOCSIFNAME", "ifreq" }, /* 73 */ { (uint_t)SIOCGENADDR, "SIOCGENADDR", "ifreq" }, /* 85 */ { (uint_t)SIOCGIFNUM, "SIOCGIFNUM", NULL }, /* 87 */ { (uint_t)SIOCGIFMUXID, "SIOCGIFMUXID", "ifreq" }, /* 88 */ { (uint_t)SIOCSIFMUXID, "SIOCSIFMUXID", "ifreq" }, /* 89 */ { (uint_t)SIOCGIFINDEX, "SIOCGIFINDEX", "ifreq" }, /* 90 */ { (uint_t)SIOCSIFINDEX, "SIOCSIFINDEX", "ifreq" }, /* 91 */ { (uint_t)SIOCGIFCONF, "SIOCGIFCONF", "ifconf" }, /* 92 */ { (uint_t)SIOCLIFREMOVEIF, "SIOCLIFREMOVEIF", "lifreq" }, /* 110 */ { (uint_t)SIOCLIFADDIF, "SIOCLIFADDIF", "lifreq" }, /* 111 */ { (uint_t)SIOCSLIFADDR, "SIOCSLIFADDR", "lifreq" }, /* 112 */ { (uint_t)SIOCGLIFADDR, "SIOCGLIFADDR", "lifreq" }, /* 113 */ { (uint_t)SIOCSLIFDSTADDR, "SIOCSLIFDSTADDR", "lifreq" }, /* 114 */ { (uint_t)SIOCGLIFDSTADDR, "SIOCGLIFDSTADDR", "lifreq" }, /* 115 */ { (uint_t)SIOCSLIFFLAGS, "SIOCSLIFFLAGS", "lifreq" }, /* 116 */ { (uint_t)SIOCGLIFFLAGS, "SIOCGLIFFLAGS", "lifreq" }, /* 117 */ { (uint_t)SIOCSLIFMTU, "SIOCSLIFMTU", "lifreq" }, /* 121 */ { (uint_t)SIOCGLIFMTU, "SIOCGLIFMTU", "lifreq" }, /* 122 */ { (uint_t)SIOCGLIFBRDADDR, "SIOCGLIFBRDADDR", "lifreq" }, /* 123 */ { (uint_t)SIOCSLIFBRDADDR, "SIOCSLIFBRDADDR", "lifreq" }, /* 124 */ { (uint_t)SIOCGLIFNETMASK, "SIOCGLIFNETMASK", "lifreq" }, /* 125 */ { (uint_t)SIOCSLIFNETMASK, "SIOCSLIFNETMASK", "lifreq" }, /* 126 */ { (uint_t)SIOCGLIFMETRIC, "SIOCGLIFMETRIC", "lifreq" }, /* 127 */ { (uint_t)SIOCSLIFMETRIC, "SIOCSLIFMETRIC", "lifreq" }, /* 128 */ { (uint_t)SIOCSLIFNAME, "SIOCSLIFNAME", "lifreq" }, /* 129 */ { (uint_t)SIOCGLIFNUM, "SIOCGLIFNUM", "lifnum" }, /* 130 */ { (uint_t)SIOCGLIFMUXID, "SIOCGLIFMUXID", "lifreq" }, /* 131 */ { (uint_t)SIOCSLIFMUXID, "SIOCSLIFMUXID", "lifreq" }, /* 132 */ { (uint_t)SIOCGLIFINDEX, "SIOCGLIFINDEX", "lifreq" }, /* 133 */ { (uint_t)SIOCSLIFINDEX, "SIOCSLIFINDEX", "lifreq" }, /* 134 */ { (uint_t)SIOCSLIFTOKEN, "SIOCSLIFTOKEN", "lifreq" }, /* 135 */ { (uint_t)SIOCGLIFTOKEN, "SIOCGLIFTOKEN", "lifreq" }, /* 136 */ { (uint_t)SIOCSLIFSUBNET, "SIOCSLIFSUBNET", "lifreq" }, /* 137 */ { (uint_t)SIOCGLIFSUBNET, "SIOCGLIFSUBNET", "lifreq" }, /* 138 */ { (uint_t)SIOCSLIFLNKINFO, "SIOCSLIFLNKINFO", "lifreq" }, /* 139 */ { (uint_t)SIOCGLIFLNKINFO, "SIOCGLIFLNKINFO", "lifreq" }, /* 140 */ { (uint_t)SIOCLIFDELND, "SIOCLIFDELND", "lifreq" }, /* 141 */ { (uint_t)SIOCLIFGETND, "SIOCLIFGETND", "lifreq" }, /* 142 */ { (uint_t)SIOCLIFSETND, "SIOCLIFSETND", "lifreq" }, /* 143 */ { (uint_t)SIOCTMYADDR, "SIOCTMYADDR", "sioc_addrreq" }, /* 144 */ { (uint_t)SIOCTONLINK, "SIOCTONLINK", "sioc_addrreq" }, /* 145 */ { (uint_t)SIOCTMYSITE, "SIOCTMYSITE", "sioc_addrreq" }, /* 146 */ { (uint_t)SIOCGLIFBINDING, "SIOCGLIFBINDING", "lifreq" }, /* 154 */ { (uint_t)SIOCSLIFGROUPNAME, "SIOCSLIFGROUPNAME", "lifreq" }, /* 155 */ { (uint_t)SIOCGLIFGROUPNAME, "SIOCGLIFGROUPNAME", "lifreq" }, /* 156 */ { (uint_t)SIOCGLIFGROUPINFO, "SIOCGLIFGROUPINFO", "lifgroupinfo" }, /* 157 */ { (uint_t)SIOCGIP6ADDRPOLICY, "SIOCGIP6ADDRPOLICY", NULL }, /* 162 */ { (uint_t)SIOCSIP6ADDRPOLICY, "SIOCSIP6ADDRPOLICY", NULL }, /* 163 */ { (uint_t)SIOCGDSTINFO, "SIOCGDSTINFO", NULL }, /* 164 */ { (uint_t)SIOCGLIFCONF, "SIOCGLIFCONF", "lifconf" }, /* 165 */ { (uint_t)SIOCSXARP, "SIOCSXARP", "xarpreq" }, /* 166 */ { (uint_t)SIOCGXARP, "SIOCGXARP", "xarpreq" }, /* 167 */ { (uint_t)SIOCDXARP, "SIOCDXARP", "xarpreq" }, /* 168 */ { (uint_t)SIOCGLIFZONE, "SIOCGLIFZONE", "lifreq" }, /* 170 */ { (uint_t)SIOCSLIFZONE, "SIOCSLIFZONE", "lifreq" }, /* 171 */ { (uint_t)SIOCSCTPSOPT, "SIOCSCTPSOPT", NULL }, /* 172 */ { (uint_t)SIOCSCTPGOPT, "SIOCSCTPGOPT", NULL }, /* 173 */ { (uint_t)SIOCSCTPPEELOFF, "SIOPCSCTPPEELOFF", "int" }, /* 174 */ { (uint_t)SIOCGLIFUSESRC, "SIOCGLIFUSESRC", "lifreq" }, /* 175 */ { (uint_t)SIOCSLIFUSESRC, "SIOCSLIFUSESRC", "lifreq" }, /* 176 */ { (uint_t)SIOCGLIFSRCOF, "SIOCGLIFSRCOF", "lifsrcof" }, /* 177 */ { (uint_t)SIOCGMSFILTER, "SIOCGMSFILTER", "group_filter" }, /* 178 */ { (uint_t)SIOCSMSFILTER, "SIOCSMSFILTER", "group_filter" }, /* 179 */ { (uint_t)SIOCGIPMSFILTER, "SIOCGIPMSFILTER", "ip_msfilter" }, /* 180 */ { (uint_t)SIOCSIPMSFILTER, "SIOCSIPMSFILTER", "ip_msfilter" }, /* 181 */ { (uint_t)SIOCGIFHWADDR, "SIOCGIFHWADDR", "ifreq" }, /* 185 */ { (uint_t)SIOCGSTAMP, "SIOCGSTAMP", "timeval" }, /* 186 */ { (uint_t)SIOCGLIFDADSTATE, "SIOCGLIFDADSTATE", "lifreq" }, /* 190 */ { (uint_t)SIOCSLIFPREFIX, "SIOCSLIFPREFIX", "lifreq" }, /* 191 */ { (uint_t)SIOCGLIFHWADDR, "SIOCGLIFHWADDR", "lifreq" }, /* 192 */ }; const struct ioc des_ioc[] = { /* 'd'<<8 */ /* DES encryption */ { (uint_t)DESIOCBLOCK, "DESIOCBLOCK", "desparams" }, /* 6 */ { (uint_t)DESIOCQUICK, "DESIOCQUICK", "desparams" }, /* 7 */ }; const struct ioc prn_ioc[] = { /* 'p'<<8 */ /* Printing system */ { (uint_t)PRNIOC_GET_IFCAP, "PRNIOC_GET_IFCAP", NULL }, /* 90 */ { (uint_t)PRNIOC_SET_IFCAP, "PRNIOC_SET_IFCAP", NULL }, /* 91 */ { (uint_t)PRNIOC_GET_IFINFO, "PRNIOC_GET_IFINFO", "prn_interface_info" }, /* 92 */ { (uint_t)PRNIOC_GET_STATUS, "PRNIOC_GET_STATUS", NULL }, /* 93 */ { (uint_t)PRNIOC_GET_1284_DEVID, "PRNIOC_GET_1284_DEVID", "prn_1284_device_id" }, /* 94 */ { (uint_t)PRNIOC_GET_1284_STATUS, "PRNIOC_GET_IFCANIOC_GET_1284_STATUS", NULL }, /* 95 */ { (uint_t)PRNIOC_GET_TIMEOUTS, "PRNIOC_GET_TIMEOUTS", "prn_timeouts" }, /* 96 */ { (uint_t)PRNIOC_SET_TIMEOUTS, "PRNIOC_SET_TIMEOUTS", "prn_timeouts" }, /* 97 */ { (uint_t)PRNIOC_RESET, "PRNIOC_RESET", NULL }, /* 98 */ }; const struct ioc dtrace_ioc[] = { /* ('d' << 24) | ('t' << 16) | ('r' << 8) */ /* DTrace */ { (uint_t)DTRACEIOC_PROVIDER, "DTRACEIOC_PROVIDER", NULL }, /* 1 */ { (uint_t)DTRACEIOC_PROBES, "DTRACEIOC_PROBES", NULL }, /* 2 */ { (uint_t)DTRACEIOC_BUFSNAP, "DTRACEIOC_BUFSNAP", NULL }, /* 4 */ { (uint_t)DTRACEIOC_PROBEMATCH, "DTRACEIOC_PROBEMATCH", NULL }, /* 5 */ { (uint_t)DTRACEIOC_ENABLE, "DTRACEIOC_ENABLE", NULL }, /* 6 */ { (uint_t)DTRACEIOC_AGGSNAP, "DTRACEIOC_AGGSNAP", NULL }, /* 7 */ { (uint_t)DTRACEIOC_EPROBE, "DTRACEIOC_EPROBE", NULL }, /* 8 */ { (uint_t)DTRACEIOC_PROBEARG, "DTRACEIOC_PROBEARG", NULL }, /* 9 */ { (uint_t)DTRACEIOC_CONF, "DTRACEIOC_CONF", NULL }, /* 10 */ { (uint_t)DTRACEIOC_STATUS, "DTRACEIOC_STATUS", NULL }, /* 11 */ { (uint_t)DTRACEIOC_GO, "DTRACEIOC_GO", NULL }, /* 12 */ { (uint_t)DTRACEIOC_STOP, "DTRACEIOC_STOP", NULL }, /* 13 */ { (uint_t)DTRACEIOC_AGGDESC, "DTRACEIOC_AGGDESC", NULL }, /* 14 */ { (uint_t)DTRACEIOC_FORMAT, "DTRACEIOC_FORMAT", NULL }, /* 15 */ { (uint_t)DTRACEIOC_DOFGET, "DTRACEIOC_DOFGET", NULL }, /* 16 */ { (uint_t)DTRACEIOC_REPLICATE, "DTRACEIOC_REPLICATE", NULL }, /* 17 */ }; const struct ioc dtraceh_ioc[] = { /* ('d' << 24) | ('t' << 16) | ('h' << 8) */ { (uint_t)DTRACEHIOC_ADD, "DTRACEHIOC_ADD", NULL }, /* 1 */ { (uint_t)DTRACEHIOC_REMOVE, "DTRACEHIOC_REMOVE", NULL }, /* 2 */ { (uint_t)DTRACEHIOC_ADDDOF, "DTRACEHIOC_ADDDOF", NULL }, /* 3 */ }; const struct ioc crypto_ioc[] = { /* 'y'<<8 */ /* /dev/cryptoadm ioctl() control codes */ { (uint_t)CRYPTO_GET_VERSION, "CRYPTO_GET_VERSION", NULL }, /* 1 */ { (uint_t)CRYPTO_GET_DEV_LIST, "CRYPTO_GET_DEV_LIST", NULL }, /* 2 */ { (uint_t)CRYPTO_GET_SOFT_LIST, "CRYPTO_GET_SOFT_LIST", NULL }, /* 3 */ { (uint_t)CRYPTO_GET_DEV_INFO, "CRYPTO_GET_DEV_INFO", NULL }, /* 4 */ { (uint_t)CRYPTO_GET_SOFT_INFO, "CRYPTO_GET_SOFT_INFO", NULL }, /* 5 */ { (uint_t)CRYPTO_LOAD_DEV_DISABLED, "CRYPTO_LOAD_DEV_DISABLED", NULL }, /* 8 */ { (uint_t)CRYPTO_LOAD_SOFT_DISABLED, "CRYPTO_LOAD_SOFT_DISABLED", NULL }, /* 9 */ { (uint_t)CRYPTO_UNLOAD_SOFT_MODULE, "CRYPTO_UNLOAD_SOFT_MODULE", NULL }, /* 10 */ { (uint_t)CRYPTO_LOAD_SOFT_CONFIG, "CRYPTO_LOAD_SOFT_CONFIG", NULL }, /* 11 */ { (uint_t)CRYPTO_POOL_CREATE, "CRYPTO_POOL_CREATE", NULL }, /* 12 */ { (uint_t)CRYPTO_POOL_WAIT, "CRYPTO_POOL_WAIT", NULL }, /* 13 */ { (uint_t)CRYPTO_POOL_RUN, "CRYPTO_POOL_RUN", NULL }, /* 14 */ { (uint_t)CRYPTO_LOAD_DOOR, "CRYPTO_LOAD_DOOR", NULL }, /* 15 */ { (uint_t)CRYPTO_FIPS140_STATUS, "CRYPTO_FIPS140_STATUS", NULL }, /* 16 */ { (uint_t)CRYPTO_FIPS140_SET, "CRYPTO_FIPS140_SET", NULL }, /* 17 */ /* /dev/crypto ioctl() control codes */ { (uint_t)CRYPTO_GET_FUNCTION_LIST, "CRYPTO_GET_FUNCTION_LIST", NULL }, /* 20 */ { (uint_t)CRYPTO_GET_MECHANISM_NUMBER, "CRYPTO_GET_MECHANISM_NUMBER", NULL }, /* 21 */ { (uint_t)CRYPTO_OPEN_SESSION, "CRYPTO_OPEN_SESSION", NULL }, /* 30 */ { (uint_t)CRYPTO_CLOSE_SESSION, "CRYPTO_CLOSE_SESSION", NULL }, /* 31 */ { (uint_t)CRYPTO_CLOSE_ALL_SESSIONS, "CRYPTO_CLOSE_ALL_SESSIONS", NULL }, /* 32 */ { (uint_t)CRYPTO_LOGIN, "CRYPTO_LOGIN", NULL }, /* 40 */ { (uint_t)CRYPTO_LOGOUT, "CRYPTO_LOGOUT", NULL }, /* 41 */ { (uint_t)CRYPTO_ENCRYPT, "CRYPTO_ENCRYPT", NULL }, /* 50 */ { (uint_t)CRYPTO_ENCRYPT_INIT, "CRYPTO_ENCRYPT_INIT", NULL }, /* 51 */ { (uint_t)CRYPTO_ENCRYPT_UPDATE, "CRYPTO_ENCRYPT_UPDATE", NULL }, /* 52 */ { (uint_t)CRYPTO_ENCRYPT_FINAL, "CRYPTO_ENCRYPT_FINAL", NULL }, /* 53 */ { (uint_t)CRYPTO_DECRYPT, "CRYPTO_DECRYPT", NULL }, /* 54 */ { (uint_t)CRYPTO_DECRYPT_INIT, "CRYPTO_DECRYPT_INIT", NULL }, /* 55 */ { (uint_t)CRYPTO_DECRYPT_UPDATE, "CRYPTO_DECRYPT_UPDATE", NULL }, /* 56 */ { (uint_t)CRYPTO_DECRYPT_FINAL, "CRYPTO_DECRYPT_FINAL", NULL }, /* 57 */ { (uint_t)CRYPTO_DIGEST, "CRYPTO_DIGEST", NULL }, /* 58 */ { (uint_t)CRYPTO_DIGEST_INIT, "CRYPTO_DIGEST_INIT", NULL }, /* 59 */ { (uint_t)CRYPTO_DIGEST_UPDATE, "CRYPTO_DIGEST_UPDATE", NULL }, /* 60 */ { (uint_t)CRYPTO_DIGEST_KEY, "CRYPTO_DIGEST_KEY", NULL }, /* 61 */ { (uint_t)CRYPTO_DIGEST_FINAL, "CRYPTO_DIGEST_FINAL", NULL }, /* 62 */ { (uint_t)CRYPTO_MAC, "CRYPTO_MAC", NULL }, /* 63 */ { (uint_t)CRYPTO_MAC_INIT, "CRYPTO_MAC_INIT", NULL }, /* 64 */ { (uint_t)CRYPTO_MAC_UPDATE, "CRYPTO_MAC_UPDATE", NULL }, /* 65 */ { (uint_t)CRYPTO_MAC_FINAL, "CRYPTO_MAC_FINAL", NULL }, /* 66 */ { (uint_t)CRYPTO_SIGN, "CRYPTO_SIGN", NULL }, /* 67 */ { (uint_t)CRYPTO_SIGN_INIT, "CRYPTO_SIGN_INIT", NULL }, /* 68 */ { (uint_t)CRYPTO_SIGN_UPDATE, "CRYPTO_SIGN_UPDATE", NULL }, /* 69 */ { (uint_t)CRYPTO_SIGN_FINAL, "CRYPTO_SIGN_FINAL", NULL }, /* 70 */ { (uint_t)CRYPTO_SIGN_RECOVER_INIT, "CRYPTO_SIGN_RECOVER_INIT", NULL }, /* 71 */ { (uint_t)CRYPTO_SIGN_RECOVER, "CRYPTO_SIGN_RECOVER", NULL }, /* 72 */ { (uint_t)CRYPTO_VERIFY, "CRYPTO_VERIFY", NULL }, /* 73 */ { (uint_t)CRYPTO_VERIFY_INIT, "CRYPTO_VERIFY_INIT", NULL }, /* 74 */ { (uint_t)CRYPTO_VERIFY_UPDATE, "CRYPTO_VERIFY_UPDATE", NULL }, /* 75 */ { (uint_t)CRYPTO_VERIFY_FINAL, "CRYPTO_VERIFY_FINAL", NULL }, /* 76 */ { (uint_t)CRYPTO_VERIFY_RECOVER_INIT, "CRYPTO_VERIFY_RECOVER_INIT", NULL }, /* 77 */ { (uint_t)CRYPTO_VERIFY_RECOVER, "CRYPTO_VERIFY_RECOVER", NULL }, /* 78 */ { (uint_t)CRYPTO_DIGEST_ENCRYPT_UPDATE, "CRYPTO_DIGEST_ENCRYPT_UPDATE", NULL }, /* 79 */ { (uint_t)CRYPTO_DECRYPT_DIGEST_UPDATE, "CRYPTO_DECRYPT_DIGEST_UPDATE", NULL }, /* 80 */ { (uint_t)CRYPTO_SIGN_ENCRYPT_UPDATE, "CRYPTO_SIGN_ENCRYPT_UPDATE", NULL }, /* 81 */ { (uint_t)CRYPTO_DECRYPT_VERIFY_UPDATE, "CRYPTO_DECRYPT_VERIFY_UPDATE", NULL }, /* 82 */ { (uint_t)CRYPTO_SEED_RANDOM, "CRYPTO_SEED_RANDOM", NULL }, /* 90 */ { (uint_t)CRYPTO_GENERATE_RANDOM, "CRYPTO_GENERATE_RANDOM", NULL }, /* 91 */ { (uint_t)CRYPTO_OBJECT_CREATE, "CRYPTO_OBJECT_CREATE", NULL }, /* 100 */ { (uint_t)CRYPTO_OBJECT_COPY, "CRYPTO_OBJECT_COPY", NULL }, /* 101 */ { (uint_t)CRYPTO_OBJECT_DESTROY, "CRYPTO_OBJECT_DESTROY", NULL }, /* 102 */ { (uint_t)CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE, "CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE", NULL }, /* 103 */ { (uint_t)CRYPTO_OBJECT_GET_SIZE, "CRYPTO_OBJECT_GET_SIZE", NULL }, /* 104 */ { (uint_t)CRYPTO_OBJECT_SET_ATTRIBUTE_VALUE, "CRYPTO_OBJECT_SET_ATTRIBUTE_VALUE", NULL }, /* 105 */ { (uint_t)CRYPTO_OBJECT_FIND_INIT, "CRYPTO_OBJECT_FIND_INIT", NULL }, /* 106 */ { (uint_t)CRYPTO_OBJECT_FIND_UPDATE, "CRYPTO_OBJECT_FIND_UPDATE", NULL }, /* 107 */ { (uint_t)CRYPTO_OBJECT_FIND_FINAL, "CRYPTO_OBJECT_FIND_FINAL", NULL }, /* 108 */ { (uint_t)CRYPTO_GENERATE_KEY, "CRYPTO_GENERATE_KEY", NULL }, /* 110 */ { (uint_t)CRYPTO_GENERATE_KEY_PAIR, "CRYPTO_GENERATE_KEY_PAIR", NULL }, /* 111 */ { (uint_t)CRYPTO_WRAP_KEY, "CRYPTO_WRAP_KEY", NULL }, /* 112 */ { (uint_t)CRYPTO_UNWRAP_KEY, "CRYPTO_UNWRAP_KEY", NULL }, /* 113 */ { (uint_t)CRYPTO_DERIVE_KEY, "CRYPTO_DERIVE_KEY", NULL }, /* 114 */ { (uint_t)CRYPTO_GET_PROVIDER_LIST, "CRYPTO_GET_PROVIDER_LIST", NULL }, /* 120 */ { (uint_t)CRYPTO_GET_PROVIDER_INFO, "CRYPTO_GET_PROVIDER_INFO", NULL }, /* 121 */ { (uint_t)CRYPTO_GET_PROVIDER_MECHANISMS, "CRYPTO_GET_PROVIDER_MECHANISMS", NULL }, /* 122 */ { (uint_t)CRYPTO_GET_PROVIDER_MECHANISM_INFO, "CRYPTO_GET_PROVIDER_MECHANISM_INFO", NULL }, /* 123 */ { (uint_t)CRYPTO_INIT_TOKEN, "CRYPTO_INIT_TOKEN", NULL }, /* 124 */ { (uint_t)CRYPTO_INIT_PIN, "CRYPTO_INIT_PIN", NULL }, /* 125 */ { (uint_t)CRYPTO_SET_PIN, "CRYPTO_SET_PIN", NULL }, /* 126 */ { (uint_t)CRYPTO_NOSTORE_GENERATE_KEY, "CRYPTO_NOSTORE_GENERATE_KEY", NULL }, /* 127 */ { (uint_t)CRYPTO_NOSTORE_GENERATE_KEY_PAIR, "CRYPTO_NOSTORE_GENERATE_KEY_PAIR", NULL }, /* 128 */ { (uint_t)CRYPTO_NOSTORE_DERIVE_KEY, "CRYPTO_NOSTORE_DERIVE_KEY", NULL }, /* 129 */ { (uint_t)CRYPTO_GET_MECHANISM_LIST, "CRYPTO_GET_MECHANISM_LIST", NULL }, /* 140 */ { (uint_t)CRYPTO_GET_ALL_MECHANISM_INFO, "CRYPTO_GET_ALL_MECHANISM_INFO", NULL }, /* 141 */ { (uint_t)CRYPTO_GET_PROVIDER_BY_MECH, "CRYPTO_GET_PROVIDER_BY_MECH", NULL }, /* 142 */ }; const struct ioc kbd_ioc[] = { /* 'k'<<8 */ /* kbio ioctls */ { (uint_t)KIOCTRANS, "KIOCTRANS", NULL }, /* 30 */ { (uint_t)KIOCSETKEY, "KIOCSETKEY", NULL }, /* 31 */ { (uint_t)KIOCGETKEY, "KIOCGETKEY", NULL }, /* 32 */ { (uint_t)KIOCGTRANS, "KIOCGTRANS", NULL }, /* 35 */ { (uint_t)KIOCTRANSABLE, "KIOCTRANSABLE", NULL }, /* 36 */ { (uint_t)KIOCGTRANSABLE, "KIOCGTRANSABLE", NULL }, /* 37 */ { (uint_t)KIOCCMD, "KIOCCMD", NULL }, /* 8 */ { (uint_t)KIOCTYPE, "KIOCTYPE", NULL }, /* 9 */ { (uint_t)KIOCSDIRECT, "KIOCSDIRECT", NULL }, /* 10 */ { (uint_t)KIOCGDIRECT, "KIOCGDIRECT", NULL }, /* 41 */ { (uint_t)KIOCSKEY, "KIOCSKEY", NULL }, /* 42 */ { (uint_t)KIOCGKEY, "KIOCGKEY", NULL }, /* 13 */ { (uint_t)KIOCSLED, "KIOCSLED", NULL }, /* 14 */ { (uint_t)KIOCGLED, "KIOCGLED", NULL }, /* 15 */ { (uint_t)KIOCSCOMPAT, "KIOCSCOMPAT", NULL }, /* 16 */ { (uint_t)KIOCGCOMPAT, "KIOCGCOMPAT", NULL }, /* 17 */ { (uint_t)KIOCSLAYOUT, "KIOCSLAYOUT", NULL }, /* 19 */ { (uint_t)KIOCLAYOUT, "KIOCLAYOUT", NULL }, /* 20 */ { (uint_t)KIOCSKABORTEN, "KIOCSKABORTEN", NULL }, /* 21 */ { (uint_t)KIOCGRPTDELAY, "KIOCGRPTDELAY", NULL }, /* 22 */ { (uint_t)KIOCSRPTDELAY, "KIOCSRPTDELAY", NULL }, /* 23 */ { (uint_t)KIOCGRPTRATE, "KIOCGRPTRATE", NULL }, /* 24 */ { (uint_t)KIOCSRPTRATE, "KIOCSRPTRATE", NULL }, /* 25 */ { (uint_t)KIOCSETFREQ, "KIOCSETFREQ", NULL }, /* 26 */ { (uint_t)KIOCMKTONE, "KIOCMKTONE", NULL }, /* 27 */ { (uint_t)KIOCGRPTCOUNT, "KIOCGRPTCOUNT", NULL }, /* 28 */ { (uint_t)KIOCSRPTCOUNT, "KIOCSRPTCOUNT", NULL }, /* 29 */ }; const struct ioc ptm_ioc[] = { /* 'P'<<8 */ /* ptm/pts driver I_STR ioctls */ { (uint_t)ISPTM, "ISPTM", NULL }, /* 1 */ { (uint_t)UNLKPT, "UNLKPT", NULL }, /* 2 */ { (uint_t)PTSSTTY, "PTSSTTY", NULL }, /* 3 */ { (uint_t)ZONEPT, "ZONEPT", NULL }, /* 4 */ { (uint_t)OWNERPT, "OWNERPT", NULL }, /* 5 */ }; const struct ioc aggr_ioc[] = { /* 0x0A66 << 16 */ /* aggr link aggregation pseudo driver ioctls */ { (uint_t)LAIOC_CREATE, "LAIOC_CREATE", "laioc_create"}, /* 1 */ { (uint_t)LAIOC_DELETE, "LAIOC_DELETE", "laioc_delete"}, /* 2 */ { (uint_t)LAIOC_INFO, "LAIOC_INFO", "laioc_info"}, /* 3 */ { (uint_t)LAIOC_ADD, "LAIOC_ADD", "laioc_add_rem"}, /* 4 */ { (uint_t)LAIOC_REMOVE, "LAIOC_REMOVE", "laioc_add_rem"}, /* 5 */ { (uint_t)LAIOC_MODIFY, "LAIOC_MODIFY", "laioc_modify"}, /* 6 */ }; const struct ioc dld_ioc[] = { /* 0x0D1D << 16 */ /* dld data-link ioctls */ { (uint_t)DLDIOC_ATTR, "DLDIOC_ATTR", "dld_ioc_attr"}, /* 3 */ { (uint_t)DLDIOC_VLAN_ATTR, "DLDIOC_VLAN_ATTR", "dld_ioc_vlan_attr"}, /* 4 */ { (uint_t)DLDIOC_PHYS_ATTR, "DLDIOC_PHYS_ATTR", "dld_ioc_phys_attr"}, /* 5 */ { (uint_t)DLDIOC_SECOBJ_SET, "DLDIOC_SECOBJ_SET", "dld_ioc_secobj_set"}, /* 6 */ { (uint_t)DLDIOC_SECOBJ_GET, "DLDIOC_SECOBJ_GET", "dld_ioc_secobj_get"}, /* 7 */ { (uint_t)DLDIOC_SECOBJ_UNSET, "DLDIOC_SECOBJ_UNSET", "dld_ioc_secobj_unset"}, /* 10 */ { (uint_t)DLDIOC_CREATE_VLAN, "DLDIOC_CREATE_VLAN", "dld_ioc_create_vlan"}, /* 11 */ { (uint_t)DLDIOC_DELETE_VLAN, "DLDIOC_DELETE_VLAN", "dld_ioc_delete_vlan"}, /* 12 */ { (uint_t)DLDIOC_DOORSERVER, "DLDIOC_DOORSERVER", "dld_ioc_door"}, /* 16 */ { (uint_t)DLDIOC_RENAME, "DLDIOC_RENAME", "dld_ioc_rename"}, /* 17 */ { (uint_t)DLDIOC_MACADDRGET, "DLDIOC_MACADDRGET", /* 21 */ "dld_ioc_macaddrget"}, { (uint_t)DLDIOC_ADDFLOW, "DLDIOC_ADDFLOW", "dld_ioc_addflow"}, /* 22 */ { (uint_t)DLDIOC_REMOVEFLOW, "DLDIOC_REMOVEFLOW", "dld_ioc_removeflow"}, /* 23 */ { (uint_t)DLDIOC_MODIFYFLOW, "DLDIOC_MODIFYFLOW", "dld_ioc_modifyflow"}, /* 24 */ { (uint_t)DLDIOC_WALKFLOW, "DLDIOC_WALKFLOW", "dld_ioc_walkflow"}, /* 25 */ { (uint_t)DLDIOC_USAGELOG, "DLDIOC_USAGELOG", "dld_ioc_usagelog"}, /* 26 */ { (uint_t)DLDIOC_SETMACPROP, "DLDIOC_SETMACPROP", "dld_ioc_macprop_s"}, /* 27 */ { (uint_t)DLDIOC_GETMACPROP, "DLDIOC_GETMACPROP", "dld_ioc_macprop_s"}, /* 28 */ { (uint_t)DLDIOC_GETHWGRP, "DLDIOC_GETHWGRP", "dld_ioc_hwgrpget"}, /* 29 */ { (uint_t)DLDIOC_GETTRAN, "DLDIOC_GETTRAN", "dld_ioc_gettran"}, /* 30 */ { (uint_t)DLDIOC_READTRAN, "DLDIOC_READTRAN", "dld_ioc_tranio"}, /* 31 */ }; const struct ioc simnet_ioc[] = { /* 0x5132 << 16 */ /* simnet ioctls */ { (uint_t)SIMNET_IOC_CREATE, "SIMNET_IOC_CREATE", "simnet_ioc_create"}, /* 1 */ { (uint_t)SIMNET_IOC_DELETE, "SIMNET_IOC_DELETE", "simnet_ioc_delete"}, /* 2 */ { (uint_t)SIMNET_IOC_INFO, "SIMNET_IOC_INFO", "simnet_ioc_info"}, /* 3 */ { (uint_t)SIMNET_IOC_MODIFY, "SIMNET_IOC_MODIFY", "simnet_ioc_info"}, /* 4 */ }; const struct ioc vnic_ioc[] = { /* 0x0171 << 16 */ /* vnic ioctls */ { (uint_t)VNIC_IOC_CREATE, "VNIC_IOC_CREATE", "vnic_ioc_create"}, /* 1 */ { (uint_t)VNIC_IOC_DELETE, "VNIC_IOC_DELETE", "vnic_ioc_delete"}, /* 2 */ { (uint_t)VNIC_IOC_INFO, "VNIC_IOC_INFO", "vnic_ioc_info"}, /* 3 */ { (uint_t)VNIC_IOC_MODIFY, "VNIC_IOC_MODIFY", "vnic_ioc_modify"}, /* 4 */ }; const struct ioc zfs_ioc[] = { /* 'Z' << 8 */ /* 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_SPACE_SNAPS, "ZFS_IOC_SPACE_SNAPS", "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_REMAP, "ZFS_IOC_REMAP", "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" }, { (uint_t)ZFS_IOC_POOL_SYNC, "ZFS_IOC_POOL_SYNC", "zfs_cmd_t" }, { (uint_t)ZFS_IOC_CHANNEL_PROGRAM, "ZFS_IOC_CHANNEL_PROGRAM", "zfs_cmd_t" }, { (uint_t)ZFS_IOC_LOAD_KEY, "ZFS_IOC_LOAD_KEY", "zfs_cmd_t" }, { (uint_t)ZFS_IOC_UNLOAD_KEY, "ZFS_IOC_UNLOAD_KEY", "zfs_cmd_t" }, { (uint_t)ZFS_IOC_CHANGE_KEY, "ZFS_IOC_CHANGE_KEY", "zfs_cmd_t" }, { (uint_t)ZFS_IOC_REMAP, "ZFS_IOC_REMAP", "zfs_cmd_t" }, { (uint_t)ZFS_IOC_POOL_CHECKPOINT, "ZFS_IOC_POOL_CHECKPOINT", "zfs_cmd_t" }, { (uint_t)ZFS_IOC_POOL_DISCARD_CHECKPOINT, "ZFS_IOC_POOL_DISCARD_CHECKPOINT", "zfs_cmd_t" }, { (uint_t)ZFS_IOC_POOL_INITIALIZE, "ZFS_IOC_POOL_INITIALIZE", "zfs_cmd_t" }, { (uint_t)ZFS_IOC_POOL_TRIM, "ZFS_IOC_POOL_TRIM", "zfs_cmd_t" }, { (uint_t)ZFS_IOC_REDACT, "ZFS_IOC_REDACT", "zfs_cmd_t" }, { (uint_t)ZFS_IOC_GET_BOOKMARK_PROPS, "ZFS_IOC_GET_BOOKMARK_PROPS", "zfs_cmd_t" }, { (uint_t)ZFS_IOC_EVENTS_NEXT, "ZFS_IOC_EVENTS_NEXT", "zfs_cmd_t" }, { (uint_t)ZFS_IOC_EVENTS_CLEAR, "ZFS_IOC_EVENTS_CLEAR", "zfs_cmd_t" }, { (uint_t)ZFS_IOC_EVENTS_SEEK, "ZFS_IOC_EVENTS_SEEK", "zfs_cmd_t" }, { (uint_t)ZFS_IOC_NEXTBOOT, "ZFS_IOC_NEXTBOOT", "zfs_cmd_t" }, { (uint_t)ZFS_IOC_JAIL, "ZFS_IOC_JAIL", "zfs_cmd_t" }, { (uint_t)ZFS_IOC_UNJAIL, "ZFS_IOC_UNJAIL", "zfs_cmd_t" }, { (uint_t)ZFS_IOC_SET_BOOTENV, "ZFS_IOC_SET_BOOTENV", "zfs_cmd_t" }, { (uint_t)ZFS_IOC_GET_BOOTENV, "ZFS_IOC_GET_BOOTENV", "zfs_cmd_t" }, }; const struct ioc dkio_ioc[] = { /* 0x4 << 8 */ /* disk ioctls - (0x04 << 8) - dkio.h */ { (uint_t)DKIOCGGEOM, "DKIOCGGEOM", "dk_geom"}, /* 1 */ { (uint_t)DKIOCSGEOM, "DKIOCSGEOM", "dk_geom"}, /* 2 */ { (uint_t)DKIOCINFO, "DKIOCINFO", "dk_info"}, /* 3 */ { (uint_t)DKIOCSAPART, "DKIOCSAPART", "dk_allmap"}, /* 4 */ { (uint_t)DKIOCGAPART, "DKIOCGAPART", "dk_allmap"}, /* 5 */ { (uint_t)DKIOCEJECT, "DKIOCEJECT", NULL}, /* 6 */ { (uint_t)DKIOCLOCK, "DKIOCLOCK", NULL}, /* 7 */ { (uint_t)DKIOCUNLOCK, "DKIOCUNLOCK", NULL}, /* 8 */ { (uint_t)DKIOCPARTITION, "DKIOCPARTITION", "partition64"}, /* 9 */ { (uint_t)DKIOCGVTOC, "DKIOCGVTOC", "vtoc"}, /* 11 */ { (uint_t)DKIOCSVTOC, "DKIOCSVTOC", "vtoc"}, /* 12 */ { (uint_t)DKIOCSTATE, "DKIOCSTATE", NULL}, /* 13 */ { (uint_t)DKIOCREMOVABLE, "DKIOCREMOVABLE", NULL}, /* 16 */ { (uint_t)DKIOCSETEFI, "DKIOCSETEFI", "dk_efi"}, /* 17 */ { (uint_t)DKIOCGETEFI, "DKIOCGETEFI", "dk_efi"}, /* 18 */ { (uint_t)DKIOCEXTPARTINFO, "DKIOCEXTPARTINFO", "extpart_info"}, /* 19 */ { (uint_t)DKIOCADDBAD, "DKIOCADDBAD", NULL}, /* 20 */ { (uint_t)DKIOCGETDEF, "DKIOCGETDEF", NULL}, /* 21 */ { (uint_t)DKIOCPARTINFO, "DKIOCPARTINFO", "part_info"}, /* 22 */ { (uint_t)DKIOCGEXTVTOC, "DKIOCGEXTVTOC", "extvtoc"}, /* 23 */ { (uint_t)DKIOCSEXTVTOC, "DKIOCSEXTVTOC", "extvtoc"}, /* 24 */ { (uint_t)DKIOCGETVOLCAP, "DKIOCGETVOLCAP", "volcap_t"}, /* 25 */ { (uint_t)DKIOCSETVOLCAP, "DKIOCSETVOLCAP", "volcap_t"}, /* 26 */ { (uint_t)DKIOCDMR, "DKIOCDMR", "vol_directed_rd"}, /* 27 */ { (uint_t)DKIOCDUMPINIT, "DKIOCDUMPINIT", NULL}, /* 28 */ { (uint_t)DKIOCDUMPFINI, "DKIOCDUMPFINI", NULL}, /* 29 */ { (uint_t)DKIOCG_PHYGEOM, "DKIOCG_PHYGEOM", "dk_geom"}, /* 32 */ { (uint_t)DKIOCG_VIRTGEOM, "DKIOCG_VIRTGEOM", "dk_geom"}, /* 33 */ { (uint_t)DKIOCFLUSHWRITECACHE, "DKIOCFLUSHWRITECACHE", NULL}, /* 34 */ { (uint_t)DKIOCHOTPLUGGABLE, "DKIOCHOTPLUGGABLE", NULL}, /* 35 */ { (uint_t)DKIOCGETWCE, "DKIOCGETWCE", NULL}, /* 36 */ { (uint_t)DKIOCSETWCE, "DKIOCSETWCE", NULL}, /* 37 */ { (uint_t)DKIOCSOLIDSTATE, "DKIOCSOLIDSTATE", NULL}, /* 38 */ { (uint_t)DKIOCGMEDIAINFO, "DKIOCGMEDIAINFO", "dk_minfo"}, /* 42 */ { (uint_t)DKIOCGMBOOT, "DKIOCGMBOOT", NULL}, /* 43 */ { (uint_t)DKIOCSMBOOT, "DKIOCSMBOOT", NULL}, /* 44 */ { (uint_t)DKIOCGTEMPERATURE, "DKIOCGTEMPERATURE", "dk_temperature"}, /* 45 */ { (uint_t)DKIOCSETEXTPART, "DKIOCSETEXTPART", NULL}, /* 46 */ { (uint_t)DKIOC_GETDISKID, "DKIOC_GETDISKID", "dk_disk_id"}, /* 46 - bug? */ { (uint_t)DKIOC_UPDATEFW, "DKIOC_UPDATEFW", "dk_updatefw"}, /* 47 */ { (uint_t)DKIOCGMEDIAINFOEXT, "DKIOCGMEDIAINFOEXT", "dk_minfo_ext"}, /* 48 */ { (uint_t)DKIOCREADONLY, "DKIOCREADONLY", NULL}, /* 49 */ { (uint_t)DKIOCFREE, "DKIOCFREE", "dkioc_free_list_s"}, /* 50 */ { (uint_t)DKIOC_CANFREE, "DKIOC_CANFREE", NULL}, /* 60 */ /* disk ioctls - (0x04 << 8) - fdio.h */ { (uint_t)FDIOGCHAR, "FDIOGCHAR", "fd_char"}, /* 51 */ { (uint_t)FDIOSCHAR, "FDIOSCHAR", "fd_char"}, /* 52 */ { (uint_t)FDEJECT, "FDEJECT", NULL}, /* 53 */ { (uint_t)FDGETCHANGE, "FDGETCHANGE", NULL}, /* 54 */ { (uint_t)FDGETDRIVECHAR, "FDGETDRIVECHAR", "fd_drive"}, /* 55 */ { (uint_t)FDSETDRIVECHAR, "FDSETDRIVECHAR", "fd_drive"}, /* 56 */ { (uint_t)FDGETSEARCH, "FDGETSEARCH", NULL}, /* 57 */ { (uint_t)FDSETSEARCH, "FDSETSEARCH", NULL}, /* 58 */ { (uint_t)FDIOCMD, "FDIOCMD", "fd_cmd"}, /* 59 */ { (uint_t)FDRAW, "FDRAW", "fd_raw"}, /* 70 */ { (uint_t)FDDEFGEOCHAR, "FDDEFGEOCHAR", NULL}, /* 86 */ /* disk ioctls - (0x04 << 8) - cdio.h */ { (uint_t)CDROMPAUSE, "CDROMPAUSE", NULL}, /* 151 */ { (uint_t)CDROMRESUME, "CDROMRESUME", NULL}, /* 152 */ { (uint_t)CDROMPLAYMSF, "CDROMPLAYMSF", "cdrom_msf"}, /* 153 */ { (uint_t)CDROMPLAYTRKIND, "CDROMPLAYTRKIND", "cdrom_ti"}, /* 154 */ { (uint_t)CDROMREADTOCHDR, "CDROMREADTOCHDR", "cdrom_tochdr"}, /* 155 */ { (uint_t)CDROMREADTOCENTRY, "CDROMREADTOCENTRY", "cdrom_tocentry"}, /* 156 */ { (uint_t)CDROMSTOP, "CDROMSTOP", NULL}, /* 157 */ { (uint_t)CDROMSTART, "CDROMSTART", NULL}, /* 158 */ { (uint_t)CDROMEJECT, "CDROMEJECT", NULL}, /* 159 */ { (uint_t)CDROMVOLCTRL, "CDROMVOLCTRL", "cdrom_volctrl"}, /* 160 */ { (uint_t)CDROMSUBCHNL, "CDROMSUBCHNL", "cdrom_subchnl"}, /* 161 */ { (uint_t)CDROMREADMODE2, "CDROMREADMODE2", "cdrom_read"}, /* 162 */ { (uint_t)CDROMREADMODE1, "CDROMREADMODE1", "cdrom_read"}, /* 163 */ { (uint_t)CDROMREADOFFSET, "CDROMREADOFFSET", NULL}, /* 164 */ { (uint_t)CDROMGBLKMODE, "CDROMGBLKMODE", NULL}, /* 165 */ { (uint_t)CDROMSBLKMODE, "CDROMSBLKMODE", NULL}, /* 166 */ { (uint_t)CDROMCDDA, "CDROMCDDA", "cdrom_cdda"}, /* 167 */ { (uint_t)CDROMCDXA, "CDROMCDXA", "cdrom_cdxa"}, /* 168 */ { (uint_t)CDROMSUBCODE, "CDROMSUBCODE", "cdrom_subcode"}, /* 169 */ { (uint_t)CDROMGDRVSPEED, "CDROMGDRVSPEED", NULL}, /* 170 */ { (uint_t)CDROMSDRVSPEED, "CDROMSDRVSPEED", NULL}, /* 171 */ { (uint_t)CDROMCLOSETRAY, "CDROMCLOSETRAY", NULL}, /* 172 */ /* disk ioctls - (0x04 << 8) - uscsi.h */ { (uint_t)USCSICMD, "USCSICMD", "uscsi_cmd"}, /* 201 */ { (uint_t)USCSIMAXXFER, "USCSIMAXXFER", NULL}, /* 202 */ }; const struct ioc dumpadm_ioc[] = { /* 0xdd << 8 */ /* dumpadm ioctls - (0xdd << 8) */ { (uint_t)DIOCGETDUMPSIZE, "DIOCGETDEV", NULL}, /* 0x10 */ { (uint_t)DIOCGETCONF, "DIOCGETCONF", NULL}, /* 0x11 */ { (uint_t)DIOCSETCONF, "DIOCSETCONF", NULL}, /* 0x12 */ { (uint_t)DIOCGETDEV, "DIOCGETDEV", NULL}, /* 0x13 */ { (uint_t)DIOCSETDEV, "DIOCSETDEV", NULL}, /* 0x14 */ { (uint_t)DIOCTRYDEV, "DIOCTRYDEV", NULL}, /* 0x15 */ { (uint_t)DIOCDUMP, "DIOCDUMP", NULL}, /* 0x16 */ { (uint_t)DIOCSETUUID, "DIOCSETUUID", NULL}, /* 0x17 */ { (uint_t)DIOCGETUUID, "DIOCGETUUID", NULL}, /* 0x18 */ { (uint_t)DIOCRMDEV, "DIOCRMDEV", NULL}, /* 0x19 */ }; const struct ioc mnt_ioc[] = { /* 'm' << 8 */ /* mntio ioctls - ('m' << 8) */ { (uint_t)MNTIOC_NMNTS, "MNTIOC_NMNTS", NULL }, /* 1 */ { (uint_t)MNTIOC_GETDEVLIST, "MNTIOC_GETDEVLIST", NULL }, /* 2 */ { (uint_t)MNTIOC_SETTAG, "MNTIOC_SETTAG", "mnttagdesc" }, /* 3 */ { (uint_t)MNTIOC_CLRTAG, "MNTIOC_CLRTAG", "mnttagdesc" }, /* 4 */ { (uint_t)MNTIOC_SHOWHIDDEN, "MNTIOC_SHOWHIDDEN", NULL }, /* 6 */ { (uint_t)MNTIOC_GETMNTENT, "MNTIOC_GETMNTENT", "mnttab" }, /* 7 */ { (uint_t)MNTIOC_GETEXTMNTENT, "MNTIOC_GETEXTMNTENT", "extmnttab" }, /* 8 */ { (uint_t)MNTIOC_GETMNTANY, "MNTIOC_GETMNTANY", "mnttab" }, /* 9 */ }; const struct ioc devinfo_ioc[] = { /* 0xdf << 8 */ /* devinfo ioctls - ('df' << 8) - devinfo_impl.h */ { (uint_t)DINFOUSRLD, "DINFOUSRLD", NULL}, /* 80 */ { (uint_t)DINFOLODRV, "DINFOLODRV", NULL}, /* 81 */ { (uint_t)DINFOIDENT, "DINFOIDENT", NULL}, /* 82 */ }; const struct ioc iptun_ioc[] = { /* 0x454A << 16 */ { (uint_t)IPTUN_CREATE, "IPTUN_CREATE", "iptun_kparams_t"}, /* 1 */ { (uint_t)IPTUN_DELETE, "IPTUN_DELETE", "datalink_id_t"}, /* 2 */ { (uint_t)IPTUN_MODIFY, "IPTUN_MODIFY", "iptun_kparams_t"}, /* 3 */ { (uint_t)IPTUN_INFO, "IPTUN_INFO", NULL}, /* 4 */ { (uint_t)IPTUN_SET_6TO4RELAY, "IPTUN_SET_6TO4RELAY", NULL}, /* 9 */ { (uint_t)IPTUN_GET_6TO4RELAY, "IPTUN_GET_6TO4RELAY", NULL}, /* 10 */ }; const struct ioc zcons_ioc[] = { /* (('Z' << 24) | ('o' << 16) | ('n' << 8)) */ /* zcons ioctls */ { (uint_t)ZC_HOLDSUBSID, "ZC_HOLDSUBSID", NULL }, /* 0 */ { (uint_t)ZC_RELEASESUBSID, "ZC_RELEASESUBSID", NULL }, /* 1 */ }; const struct ioc hid_ioc[] = { /* 'h' << 8 */ /* hid ioctls - ('h' << 8) - hid.h */ { (uint_t)HIDIOCKMGDIRECT, "HIDIOCKMGDIRECT", NULL }, /* 0 */ { (uint_t)HIDIOCKMSDIRECT, "HIDIOCKMSDIRECT", NULL }, /* 1 */ }; const struct ioc pm_ioc[] = { /* 0 */ /* 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 */ }; const struct ioc cpuid_ioc[] = { /* (('c'<<24)|('i'<<16)|('d'<<8)) */ /* cpuid ioctls */ { (uint_t)CPUID_GET_HWCAP, "CPUID_GET_HWCAP", NULL }, /* 0 */ { (uint_t)CPUID_RDMSR, "CPUID_RDMSR", NULL }, /* 1 */ }; /* * Because some IOC codes do overlap, and we are performing linear * lookup with first match returned, care must be taken about the order * of the array elements. */ const struct iocs iocs[] = { /* GLDv3 module ioc lists */ { .nitems = ARRAY_SIZE(aggr_ioc), .data = aggr_ioc}, { .nitems = ARRAY_SIZE(dld_ioc), .data = dld_ioc}, { .nitems = ARRAY_SIZE(simnet_ioc), .data = simnet_ioc}, { .nitems = ARRAY_SIZE(vnic_ioc), .data = vnic_ioc}, { .nitems = ARRAY_SIZE(iptun_ioc), .data = iptun_ioc}, { .nitems = ARRAY_SIZE(Tioc), .data = Tioc}, { .nitems = ARRAY_SIZE(tioc), .data = tioc}, { .nitems = ARRAY_SIZE(pty_ioc), .data = pty_ioc}, { .nitems = ARRAY_SIZE(dlpi_ioc), .data = dlpi_ioc}, { .nitems = ARRAY_SIZE(ldioc_ioc), .data = ldioc_ioc}, { .nitems = ARRAY_SIZE(xioc_ioc), .data = xioc_ioc}, { .nitems = ARRAY_SIZE(fio_ioc), .data = fio_ioc}, { .nitems = ARRAY_SIZE(fil_ioc), .data = fil_ioc}, { .nitems = ARRAY_SIZE(dioc_ioc), .data = dioc_ioc}, { .nitems = ARRAY_SIZE(lioc_ioc), .data = lioc_ioc}, { .nitems = ARRAY_SIZE(jerq_ioc), .data = jerq_ioc}, { .nitems = ARRAY_SIZE(kstat_ioc), .data = kstat_ioc}, { .nitems = ARRAY_SIZE(stream_ioc), .data = stream_ioc}, { .nitems = ARRAY_SIZE(str_ioc), .data = str_ioc}, { .nitems = ARRAY_SIZE(audio_ioc), .data = audio_ioc}, { .nitems = ARRAY_SIZE(audiom_ioc), .data = audiom_ioc}, { .nitems = ARRAY_SIZE(ossx_ioc), .data = ossx_ioc}, { .nitems = ARRAY_SIZE(ossy_ioc), .data = ossy_ioc}, { .nitems = ARRAY_SIZE(ossp_ioc), .data = ossp_ioc}, { .nitems = ARRAY_SIZE(ossm_ioc), .data = ossm_ioc}, { .nitems = ARRAY_SIZE(strredir_ioc), .data = strredir_ioc}, { .nitems = ARRAY_SIZE(cpc_ioc), .data = cpc_ioc}, { .nitems = ARRAY_SIZE(dp_ioc), .data = dp_ioc}, { .nitems = ARRAY_SIZE(p_ioc), .data = p_ioc}, { .nitems = ARRAY_SIZE(socket_ioc), .data = socket_ioc}, { .nitems = ARRAY_SIZE(routing_ioc), .data = routing_ioc}, { .nitems = ARRAY_SIZE(sockio_ioc), .data = sockio_ioc}, { .nitems = ARRAY_SIZE(des_ioc), .data = des_ioc}, { .nitems = ARRAY_SIZE(prn_ioc), .data = prn_ioc}, { .nitems = ARRAY_SIZE(dtrace_ioc), .data = dtrace_ioc}, { .nitems = ARRAY_SIZE(dtraceh_ioc), .data = dtraceh_ioc}, { .nitems = ARRAY_SIZE(crypto_ioc), .data = crypto_ioc}, { .nitems = ARRAY_SIZE(kbd_ioc), .data = kbd_ioc}, { .nitems = ARRAY_SIZE(ptm_ioc), .data = ptm_ioc}, { .nitems = ARRAY_SIZE(zfs_ioc), .data = zfs_ioc}, { .nitems = ARRAY_SIZE(dkio_ioc), .data = dkio_ioc}, { .nitems = ARRAY_SIZE(dumpadm_ioc), .data = dumpadm_ioc}, { .nitems = ARRAY_SIZE(mnt_ioc), .data = mnt_ioc}, { .nitems = ARRAY_SIZE(devinfo_ioc), .data = devinfo_ioc}, { .nitems = ARRAY_SIZE(zcons_ioc), .data = zcons_ioc}, { .nitems = ARRAY_SIZE(hid_ioc), .data = hid_ioc}, { .nitems = ARRAY_SIZE(cpuid_ioc), .data = cpuid_ioc}, { .nitems = ARRAY_SIZE(pm_ioc), .data = pm_ioc}, { .nitems = 0, .data = 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); } static const struct ioc * find_ioc(const struct iocs *iocs, uint_t code) { const struct iocs *ptr; const struct ioc *ip; for (ptr = &iocs[0]; ptr->nitems > 0; ptr++) { /* search for "close enough" table */ if ((ptr->data->code & 0xffff0000) != (code & 0xffff0000) && (ptr->data->code & 0xffff00) != (code & 0xffff00) && (ptr->data->code & IOCTYPE) != (code & IOCTYPE)) { continue; } ip = ptr->data; for (uint_t i = 0; i < ptr->nitems; i++) { /* Do exact match there */ if (code == ip[i].code) return (&ip[i]); } } return (NULL); } const char * ioctlname(private_t *pri, uint_t code) { const struct ioc *ip; const char *str = NULL; ip = find_ioc(vmm_iocs, code); if (ip == NULL) ip = find_ioc(iocs, code); if (ip != NULL) str = ip->name; /* * 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; ip = find_ioc(vmm_iocs, code); if (ip == NULL) ip = find_ioc(iocs, code); if (ip != NULL) str = ip->datastruct; 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(__x86) 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 /* __x86 */ 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|O_DIRECTORY|O_DIRECT|O_CLOFORK|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 & O_DIRECTORY) (void) strlcat(str, "|O_DIRECTORY", sizeof (pri->code_buf)); if (arg & O_DIRECT) (void) strlcat(str, "|O_DIRECT", sizeof (pri->code_buf)); if (arg & O_CLOFORK) (void) strlcat(str, "|O_CLOFORK", 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); } } /* * This file and its contents are supplied under the terms of the * Common Development and Distribution License ("CDDL"), version 1.0. * You may only use this file in accordance with the terms of version * 1.0 of the CDDL. * * A full copy of the text of the CDDL should have accompanied this * source. A copy of the CDDL is also available via the Internet at * http://www.illumos.org/license/CDDL. */ /* * Copyright 2023 Toomas Soome */ #ifndef _CODES_H #define _CODES_H #ifdef __cplusplus extern "C" { #endif struct ioc { uint_t code; const char *name; const char *datastruct; }; struct iocs { uint_t nitems; const struct ioc *data; }; extern const struct iocs vmm_iocs[]; #ifdef __cplusplus } #endif #endif /* _CODES_H */ /* * This file and its contents are supplied under the terms of the * Common Development and Distribution License ("CDDL"), version 1.0. * You may only use this file in accordance with the terms of version * 1.0 of the CDDL. * * A full copy of the text of the CDDL should have accompanied this * source. A copy of the CDDL is also available via the Internet at * http://www.illumos.org/license/CDDL. */ /* * Copyright 2023 Toomas Soome */ #include #include #include "codes.h" #if defined(__x86) /* vmm_dev.h is expecting to have the types below. */ typedef uint64_t vm_paddr_t; typedef int64_t vm_ooffset_t; #include /* VMM ioctls */ const struct ioc vmmctl_ioc[] = { { (uint_t)VMM_CREATE_VM, "VMM_CREATE_VM", NULL }, { (uint_t)VMM_DESTROY_VM, "VMM_DESTROY_VM", NULL }, { (uint_t)VMM_VM_SUPPORTED, "VMM_VM_SUPPORTED", NULL }, { (uint_t)VMM_RESV_QUERY, "VMM_RESV_QUERY", NULL }, { (uint_t)VMM_RESV_SET_TARGET, "VMM_RESV_SET_TARGET", NULL } }; const struct ioc vmm_cpu_ioc[] = { { (uint_t)VM_RUN, "VM_RUN", NULL }, { (uint_t)VM_SET_REGISTER, "VM_SET_REGISTER", NULL }, { (uint_t)VM_GET_REGISTER, "VM_GET_REGISTER", NULL }, { (uint_t)VM_SET_SEGMENT_DESCRIPTOR, "VM_SET_SEGMENT_DESCRIPTOR", NULL }, { (uint_t)VM_GET_SEGMENT_DESCRIPTOR, "VM_GET_SEGMENT_DESCRIPTOR", NULL }, { (uint_t)VM_SET_REGISTER_SET, "VM_SET_REGISTER_SET", NULL }, { (uint_t)VM_GET_REGISTER_SET, "VM_GET_REGISTER_SET", NULL }, { (uint_t)VM_INJECT_EXCEPTION, "VM_INJECT_EXCEPTION", NULL }, { (uint_t)VM_SET_CAPABILITY, "VM_SET_CAPABILITY", NULL }, { (uint_t)VM_GET_CAPABILITY, "VM_GET_CAPABILITY", NULL }, { (uint_t)VM_PPTDEV_MSI, "VM_PPTDEV_MSI", NULL }, { (uint_t)VM_PPTDEV_MSIX, "VM_PPTDEV_MSIX", NULL }, { (uint_t)VM_SET_X2APIC_STATE, "VM_SET_X2APIC_STATE", NULL }, { (uint_t)VM_GLA2GPA, "VM_GLA2GPA", NULL }, { (uint_t)VM_GLA2GPA_NOFAULT, "VM_GLA2GPA_NOFAULT", NULL }, { (uint_t)VM_ACTIVATE_CPU, "VM_ACTIVATE_CPU", NULL }, { (uint_t)VM_SET_INTINFO, "VM_SET_INTINFO", NULL }, { (uint_t)VM_GET_INTINFO, "VM_GET_INTINFO", NULL }, { (uint_t)VM_RESTART_INSTRUCTION, "VM_RESTART_INSTRUCTION", NULL }, { (uint_t)VM_SET_KERNEMU_DEV, "VM_SET_KERNEMU_DEV", NULL }, { (uint_t)VM_GET_KERNEMU_DEV, "VM_GET_KERNEMU_DEV", NULL }, { (uint_t)VM_RESET_CPU, "VM_RESET_CPU", NULL }, { (uint_t)VM_GET_RUN_STATE, "VM_GET_RUN_STATE", NULL }, { (uint_t)VM_SET_RUN_STATE, "VM_SET_RUN_STATE", NULL }, { (uint_t)VM_GET_FPU, "VM_GET_FPU", NULL }, { (uint_t)VM_SET_FPU, "VM_SET_FPU", NULL }, { (uint_t)VM_GET_CPUID, "VM_GET_CPUID", NULL }, { (uint_t)VM_SET_CPUID, "VM_SET_CPUID", NULL }, { (uint_t)VM_LEGACY_CPUID, "VM_LEGACY_CPUID", NULL } }; const struct ioc vmm_lock_ioc[] = { { (uint_t)VM_REINIT, "VM_REINIT", NULL }, { (uint_t)VM_BIND_PPTDEV, "VM_BIND_PPTDEV", NULL }, { (uint_t)VM_UNBIND_PPTDEV, "VM_UNBIND_PPTDEV", NULL }, { (uint_t)VM_MAP_PPTDEV_MMIO, "VM_MAP_PPTDEV_MMIO", NULL }, { (uint_t)VM_ALLOC_MEMSEG, "VM_ALLOC_MEMSEG", NULL }, { (uint_t)VM_MMAP_MEMSEG, "VM_MMAP_MEMSEG", NULL }, { (uint_t)VM_PMTMR_LOCATE, "VM_PMTMR_LOCATE", NULL }, { (uint_t)VM_MUNMAP_MEMSEG, "VM_MUNMAP_MEMSEG", NULL }, { (uint_t)VM_UNMAP_PPTDEV_MMIO, "VM_UNMAP_PPTDEV_MMIO", NULL }, { (uint_t)VM_PAUSE, "VM_PAUSE", NULL }, { (uint_t)VM_RESUME, "VM_RESUME", NULL }, { (uint_t)VM_WRLOCK_CYCLE, "VM_WRLOCK_CYCLE", NULL } }; const struct ioc vmm_ioc[] = { { (uint_t)VM_GET_GPA_PMAP, "VM_GET_GPA_PMAP", NULL }, { (uint_t)VM_GET_MEMSEG, "VM_GET_MEMSEG", NULL }, { (uint_t)VM_MMAP_GETNEXT, "VM_MMAP_GETNEXT", NULL }, { (uint_t)VM_LAPIC_IRQ, "VM_LAPIC_IRQ", NULL }, { (uint_t)VM_LAPIC_LOCAL_IRQ, "VM_LAPIC_LOCAL_IRQ", NULL }, { (uint_t)VM_LAPIC_MSI, "VM_LAPIC_MSI", NULL }, { (uint_t)VM_IOAPIC_ASSERT_IRQ, "VM_IOAPIC_ASSERT_IRQ", NULL }, { (uint_t)VM_IOAPIC_DEASSERT_IRQ, "VM_IOAPIC_DEASSERT_IRQ", NULL }, { (uint_t)VM_IOAPIC_PULSE_IRQ, "VM_IOAPIC_PULSE_IRQ", NULL }, { (uint_t)VM_ISA_ASSERT_IRQ, "VM_ISA_ASSERT_IRQ", NULL }, { (uint_t)VM_ISA_DEASSERT_IRQ, "VM_ISA_DEASSERT_IRQ", NULL }, { (uint_t)VM_ISA_PULSE_IRQ, "VM_ISA_PULSE_IRQ", NULL }, { (uint_t)VM_ISA_SET_IRQ_TRIGGER, "VM_ISA_SET_IRQ_TRIGGER", NULL }, { (uint_t)VM_RTC_WRITE, "VM_RTC_WRITE", NULL }, { (uint_t)VM_RTC_READ, "VM_RTC_READ", NULL }, { (uint_t)VM_RTC_SETTIME, "VM_RTC_SETTIME", NULL }, { (uint_t)VM_RTC_GETTIME, "VM_RTC_GETTIME", NULL }, { (uint_t)VM_SUSPEND, "VM_SUSPEND", NULL }, { (uint_t)VM_IOAPIC_PINCOUNT, "VM_IOAPIC_PINCOUNT", NULL }, { (uint_t)VM_GET_PPTDEV_LIMITS, "VM_GET_PPTDEV_LIMITS", NULL }, { (uint_t)VM_GET_HPET_CAPABILITIES, "VM_GET_HPET_CAPABILITIES", NULL }, { (uint_t)VM_STATS_IOC, "VM_STATS_IOC", NULL }, { (uint_t)VM_STAT_DESC, "VM_STAT_DESC", NULL }, { (uint_t)VM_INJECT_NMI, "VM_INJECT_NMI", NULL }, { (uint_t)VM_GET_X2APIC_STATE, "VM_GET_X2APIC_STATE", NULL }, { (uint_t)VM_SET_TOPOLOGY, "VM_SET_TOPOLOGY", NULL }, { (uint_t)VM_GET_TOPOLOGY, "VM_GET_TOPOLOGY", NULL }, { (uint_t)VM_GET_CPUS, "VM_GET_CPUS", NULL }, { (uint_t)VM_SUSPEND_CPU, "VM_SUSPEND_CPU", NULL }, { (uint_t)VM_RESUME_CPU, "VM_RESUME_CPU", NULL }, { (uint_t)VM_PPTDEV_DISABLE_MSIX, "VM_PPTDEV_DISABLE_MSIX", NULL }, { (uint_t)VM_TRACK_DIRTY_PAGES, "VM_TRACK_DIRTY_PAGES", NULL }, { (uint_t)VM_DESC_FPU_AREA, "VM_DESC_FPU_AREA", NULL }, { (uint_t)VM_DATA_READ, "VM_DATA_READ", NULL }, { (uint_t)VM_DATA_WRITE, "VM_DATA_WRITE", NULL }, { (uint_t)VM_SET_AUTODESTRUCT, "VM_SET_AUTODESTRUCT", NULL }, { (uint_t)VM_DESTROY_SELF, "VM_DESTROY_SELF", NULL }, { (uint_t)VM_DESTROY_PENDING, "VM_DESTROY_PENDING", NULL }, { (uint_t)VM_VCPU_BARRIER, "VM_VCPU_BARRIER", NULL }, { (uint_t)VM_DEVMEM_GETOFFSET, "VM_DEVMEM_GETOFFSET", NULL } }; const struct iocs vmm_iocs[] = { { .nitems = ARRAY_SIZE(vmmctl_ioc), .data = vmmctl_ioc }, { .nitems = ARRAY_SIZE(vmm_cpu_ioc), .data = vmm_cpu_ioc }, { .nitems = ARRAY_SIZE(vmm_lock_ioc), .data = vmm_lock_ioc }, { .nitems = ARRAY_SIZE(vmm_ioc), .data = vmm_ioc }, { .nitems = 0, .data = NULL } }; #else const struct iocs vmm_iocs[] = { { .nitems = 0, .data = NULL } }; #endif /* __x86 */ /* * 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) 2012, 2014 by Delphix. All rights reserved. * Copyright 2015 Joyent, Inc. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ #define _SYSCALL32 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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]) == 0) 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, ×truc, sizeof (timestruc), offset) != sizeof (timestruc)) return; } else { timestruc32_t timestruc32; if (Pread(Proc, ×truc32, sizeof (timestruc32), offset) != sizeof (timestruc32)) return; TIMESPEC32_TO_TIMESPEC(×truc, ×truc32); } (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]) == 0) 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 ). */ struct { char sysname[9]; char nodename[9]; char release[9]; char version[9]; char machine[9]; } ubuf; if (offset != 0 && 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 != 0 && 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); } } void show_ustat32(private_t *pri, long offset) { struct ustat32 ubuf; if (offset != 0 && 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); } } 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; } } } 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; } } } 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, <chars, sizeof (ltchars), offset) == sizeof (ltchars)) { (void) printf("%s\t cc: ", pri->pname); for (p = (char *)<chars, 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; } } 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; } } 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); } } 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 == 0 || 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); } } /* 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)); } } 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)); } } 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); } } 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); } } 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); } } } 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); } } } 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 */ 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: if (lp64) show_strioctl(pri, offset); else show_strioctl32(pri, offset); break; case I_PEEK: if (lp64) show_strpeek(pri, offset); else show_strpeek32(pri, offset); break; case I_FDINSERT: if (lp64) show_strfdinsert(pri, offset); else show_strfdinsert32(pri, offset); break; case I_RECVFD: if (err) break; show_strrecvfd(pri, offset); break; case I_LIST: if (err) break; if (lp64) show_strlist(pri, offset); else show_strlist32(pri, offset); 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]) != 0 && 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); } } void show_statvfs32(private_t *pri) { long offset; struct statvfs32 statvfs; char *cp; if (pri->sys_nargs > 1 && (offset = pri->sys_args[1]) != 0 && 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); } } void show_statvfs64(private_t *pri) { long offset; struct statvfs64_32 statvfs; char *cp; if (pri->sys_nargs > 1 && (offset = pri->sys_args[1]) != 0 && 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]) != 0 && 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); } } void show_statfs32(private_t *pri) { long offset; struct statfs32 statfs; if (pri->sys_nargs >= 2 && (offset = pri->sys_args[1]) != 0 && 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); } } 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); } void show_ffd(private_t *pri) { (void) putchar('\t'); (void) putchar('\t'); prt_ffd(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 >= 2 && pri->sys_args[1] == F_GETFD) { show_ffd(pri); return; } if (pri->sys_nargs < 3 || (offset = pri->sys_args[2]) == 0) return; switch (pri->sys_args[1]) { case F_GETLK: case F_SETLK: case F_SETLKW: case F_FREESP: case F_ALLOCSP: case F_SETLK_NBMAND: case F_OFD_GETLK: case F_OFD_SETLK: case F_OFD_SETLKW: case F_FLOCK: case F_FLOCKW: 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 */ case 50: /* F_OFD_GETLK64 */ case 51: /* F_OFD_SETLK64 */ case 52: /* F_OFD_SETLKW64 */ case 55: /* F_FLOCK64 */ case 56: /* F_FLOCKW64 */ show_flock64(pri, offset); break; 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); } 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); } 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(); if (pri->sys_nargs >= 2 && (offset = pri->sys_args[1]) != 0) { 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]) != 0) { if (data_model == PR_MODEL_LP64) show_strbuf(pri, offset, "dat", dump); else show_strbuf32(pri, offset, "dat", dump); } /* 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 != 0 && nfds > 32) { Eserialize(); serial = 1; } if (offset != 0 && 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); } 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); } static void show_msgctl64(private_t *pri, long offset) { struct msqid_ds64 msgq; if (offset != 0 && 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 != 0 && 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); } } void show_msgctl32(private_t *pri, long offset) { struct msqid_ds32 msgq; if (offset != 0 && 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); } } void show_msgbuf(private_t *pri, long offset, long msgsz) { struct msgbuf msgb; if (offset != 0 && 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(); } } void show_msgbuf32(private_t *pri, long offset, long msgsz) { struct ipcmsgbuf32 msgb; if (offset != 0 && 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(); } } 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; } } static void show_semctl64(private_t *pri, long offset) { struct semid_ds64 semds; if (offset != 0 && 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 != 0 && 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); } } void show_semctl32(private_t *pri, long offset) { struct semid_ds32 semds; if (offset != 0 && 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); } } 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: if (data_model == PR_MODEL_LP64) show_semctl(pri, (long)pri->sys_args[4]); else show_semctl32(pri, (long)pri->sys_args[4]); 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 != 0 && 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 != 0 && 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); } } void show_shmctl32(private_t *pri, long offset) { struct shmid_ds32 shmds; if (offset != 0 && 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); } } 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: if (data_model == PR_MODEL_LP64) show_shmctl(pri, (long)pri->sys_args[3]); else show_shmctl32(pri, (long)pri->sys_args[3]); 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 != 0 && 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 != 0 && Pread(Proc, &sigset, sizeof (sigset), offset) == sizeof (sigset)) { (void) printf("%s\t%s =%s\n", pri->pname, name, sigset_string(pri, &sigset)); } } void show_sigaltstack32(private_t *pri, long offset, const char *name) { struct sigaltstack32 altstack; if (offset != 0 && 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); } } void show_sigaltstack(private_t *pri, long offset, const char *name) { struct sigaltstack altstack; if (data_model != PR_MODEL_LP64) { show_sigaltstack32(pri, offset, name); return; } if (offset != 0 && 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); } } void show_sigaction32(private_t *pri, long offset, const char *name, long odisp) { struct sigaction32 sigaction; if (offset != 0 && Pread(Proc, &sigaction, sizeof (sigaction), offset) == sizeof (sigaction)) { /* This is stupid, we shouldn't have to do this */ if (odisp != 0) 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); } } void show_sigaction(private_t *pri, long offset, const char *name, long odisp) { struct sigaction sigaction; if (data_model != PR_MODEL_LP64) { show_sigaction32(pri, offset, name, odisp); return; } if (offset != 0 && Pread(Proc, &sigaction, sizeof (sigaction), offset) == sizeof (sigaction)) { /* This is stupid, we shouldn't have to do this */ if (odisp != 0) 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); } } 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); } 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); } void show_siginfo32(private_t *pri, long offset) { struct siginfo32 siginfo; if (offset != 0 && Pread(Proc, &siginfo, sizeof (siginfo), offset) == sizeof (siginfo)) print_siginfo32(pri, &siginfo); } void show_siginfo(private_t *pri, long offset) { struct siginfo siginfo; if (data_model != PR_MODEL_LP64) { show_siginfo32(pri, offset); return; } if (offset != 0 && 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(); } 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 != 0 && 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(); } } 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); if (data_model != PR_MODEL_LP64) { show_iovec32(pri, offset, niov, showbuf, count); return; } if (niov > 16) /* is this the real limit? */ niov = 16; if (offset != 0 && 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 != 0 && 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 != 0 && 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 != 0 && 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] = 0; (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); } 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 != 0 && 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); } 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); } } 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); } } static void show_doors(private_t *pri) { switch (pri->sys_args[5]) { case DOOR_CALL: if (data_model == PR_MODEL_LP64) show_doorargs(pri, (long)pri->sys_args[1]); else show_doorargs32(pri, (long)pri->sys_args[1]); 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) { if (data_model == PR_MODEL_LP64) show_doorparam(pri, (long)pri->sys_args[2]); else show_doorparam32(pri, (long)pri->sys_args[2]); } 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); } } 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); } } static void show_ports(private_t *pri) { switch (pri->sys_args[0]) { case PORT_GET: if (data_model == PR_MODEL_LP64) show_portargs(pri, (long)pri->sys_args[2]); else show_portargs32(pri, (long)pri->sys_args[2]); break; } } #define MAX_SNDFL_PRD 16 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(); } /*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; if (data_model != PR_MODEL_LP64) { show_ksendfilevec32(pri, fd, (ksendfilevec32_t *)sndvec, sfvcnt); return; } 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; if (data_model != PR_MODEL_LP64) { show_ksendfilevec64(pri, fd, (ksendfilevec64_t *)sndvec, sfvcnt); return; } 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(); } 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); } } 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); } } static void show_memcntl(private_t *pri) { if ((int)pri->sys_args[2] != MC_HAT_ADVISE) return; 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]); } 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]) == 0) 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]) == 0) 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: %ld\n", r.ru_maxrss); (void) printf("\t shared data: %ld\n", r.ru_ixrss); (void) printf("\t unshared data: %ld\n", r.ru_idrss); (void) printf("\t unshared stack: %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); } 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: %d\n", r.ru_maxrss); (void) printf("\t shared data: %d\n", r.ru_ixrss); (void) printf("\t unshared data: %d\n", r.ru_idrss); (void) printf("\t unshared stack: %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); } /* * 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); } } 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); } } static void show_zones(private_t *pri) { switch (pri->sys_args[0]) { case ZONE_CREATE: 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]); 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); } (void) printf("%s\t\t Recipient PID: %d\n", pri->pname, rctlblk_get_recipient_pid(blk)); (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] != 0) { 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] != 0) { 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; } } 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\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); } } } 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\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: 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]); 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.drr_u.drr_begin; (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 */ /* 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; if (lp64) show_utssys(pri, r0); else show_utssys32(pri, r0); 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; if (!lp64) { show_statvfs32(pri); break; } 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; if (lp64) show_statfs(pri); else show_statfs32(pri); 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; if (!lp64) { show_dents32(pri, (long)pri->sys_args[1], r0); break; } /* FALLTHROUGH */ 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", 0); 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; if (lp64) show_rlimit64(pri, (long)pri->sys_args[1]); else show_rlimit32(pri, (long)pri->sys_args[1]); 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; if (lp64) show_msghdr(pri, pri->sys_args[1]); else show_msghdr32(pri, pri->sys_args[1]); 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) { if (!lp64) show_getrusage32(pri->sys_args[1]); else 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; } } /* * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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, ¬ify) == 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, ¬ify) == RD_OK && (Bp = create_bkpt(notify.u.bptaddr, 0, 1)) != NULL) Bp->flags |= BPT_PREINIT; if (rd_event_addr(Rdb_agent, RD_POSTINIT, ¬ify) == RD_OK && (Bp = create_bkpt(notify.u.bptaddr, 0, 1)) != NULL) Bp->flags |= BPT_POSTINIT; if (rd_event_addr(Rdb_agent, RD_DLACTIVITY, ¬ify) == 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) if (data_model == PR_MODEL_LP64) minsize = 2 * sizeof (uintptr_t); /* fp + pc */ else minsize = 2 * sizeof (uint32_t); #else if (data_model != PR_MODEL_LP64) minsize = SA32(MINFRAME32); else minsize = SA64(MINFRAME64); #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; if (data_model != PR_MODEL_LP64) { sp = (uint32_t)sp; rpc = (uint32_t)rpc; } /* * 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; if (data_model != PR_MODEL_LP64) { sp = (uint32_t)sp; fp = (uint32_t)fp; } 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; 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; 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; } 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) { 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 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) { 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 return (get_arguments32(argp)); } #endif /* __amd64 || __i386 */ /* * 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. */ #include #include #include #include #include #include #include #include #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); } /* * 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 #ifdef __cplusplus extern "C" { #endif #include 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 */ /* * 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 #include #include #include #include #include #include #include #include #include #include #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); } /* * 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 #include #include #include #include #include #include #include #include #include "ramdata.h" #include "systable.h" #include "proto.h" /* XXX A bug in the 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); } /* * 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 2015, Joyent, Inc. * Copyright 2023 Oxide Computer Company */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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); praddset(&traceeven, SYS_upanic); /* 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) Psysentry(Proc, SYS_upanic, TRUE); (void) Psysexit(Proc, SYS_exit, FALSE); (void) Psysexit(Proc, SYS_lwp_exit, FALSE); (void) Psysexit(Proc, SYS_upanic, 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_upanic: /* upanic() */ 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 && Lsp->pr_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(8). */ 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) proc_free_priv(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); } } /* * 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 2020 Joyent, Inc. * Copyright 2022 Garrett D'Amore * Copyright 2024 Oxide Computer Company */ /* 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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: if (data_model == PR_MODEL_ILP32) prt_stg(pri, raw, val + offsetof(kstat32_t, ks_name[0])); else 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 */ { int first = 1; long flags = ~(O_CLOEXEC | O_CLOFORK | O_NONBLOCK); if (raw != 0 || val == 0 || (val & flags) != 0) { prt_dex(pri, 0, val); return; } if (val & O_CLOEXEC) { outstring(pri, "|O_CLOEXEC" + first); first = 0; } if (val & O_CLOFORK) { outstring(pri, "|O_CLOFORK" + first); first = 0; } if (val & O_NONBLOCK) { outstring(pri, "|O_NONBLOCK" + first); } } 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; case MADV_PURGE: s = "MADV_PURGE"; 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 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] == 0) { 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); } void prt_psflags(private_t *pri, secflagset_t val) { size_t len; char *ptr; char str[1024]; if (val == 0) { outstring(pri, "0x0"); return; } *str = '\0'; if (secflag_isset(val, PROC_SEC_ASLR)) { (void) strlcat(str, "|PROC_SEC_ASLR", sizeof (str)); secflag_clear(&val, PROC_SEC_ASLR); } if (secflag_isset(val, PROC_SEC_FORBIDNULLMAP)) { (void) strlcat(str, "|PROC_SEC_FORBIDNULLMAP", sizeof (str)); secflag_clear(&val, PROC_SEC_FORBIDNULLMAP); } if (secflag_isset(val, PROC_SEC_NOEXECSTACK)) { (void) strlcat(str, "|PROC_SEC_NOEXECSTACK", sizeof (str)); secflag_clear(&val, PROC_SEC_NOEXECSTACK); } if (val != 0) { len = strlen(str); ptr = str + len; (void) snprintf(ptr, sizeof (str) - len, "|%#x", val); } outstring(pri, str + 1); } /* * Print a psecflags(2) delta */ void prt_psdelta(private_t *pri, int raw, long value) { secflagdelta_t psd; if ((raw != 0) || (Pread(Proc, &psd, sizeof (psd), value) != sizeof (psd))) { prt_hex(pri, 0, value); return; } outstring(pri, "{ "); prt_psflags(pri, psd.psd_add); outstring(pri, ", "); prt_psflags(pri, psd.psd_rem); outstring(pri, ", "); prt_psflags(pri, psd.psd_assign); outstring(pri, ", "); outstring(pri, psd.psd_ass_active ? "B_TRUE" : "B_FALSE"); outstring(pri, " }"); } /* * Print a psecflagswhich_t */ void prt_psfw(private_t *pri, int raw, long value) { psecflagwhich_t which = (psecflagwhich_t)value; char *s; if (raw != 0) { prt_dec(pri, 0, value); return; } switch (which) { case PSF_EFFECTIVE: s = "PSF_EFFECTIVE"; break; case PSF_INHERIT: s = "PSF_INHERIT"; break; case PSF_LOWER: s = "PSF_LOWER"; break; case PSF_UPPER: s = "PSF_UPPER"; break; } if (s == NULL) prt_dec(pri, 0, value); else outstring(pri, s); } /* * 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; 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; } 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"); } if ((val & SOCK_CLOFORK) != 0) { outstring(pri, "|SOCK_CLOFORK"); } if ((val & SOCK_NDELAY) != 0) { outstring(pri, "|SOCK_NDELAY"); } if ((val & SOCK_NONBLOCK) != 0) { outstring(pri, "|SOCK_NONBLOCK"); } } 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: 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|SOCK_CLOFORK))) { prt_dex(pri, 0, val); return; } if (val & SOCK_CLOEXEC) { outstring(pri, "|SOCK_CLOEXEC" + first); first = 0; } if (val & SOCK_CLOFORK) { outstring(pri, "|SOCK_CLOFORK" + 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"); case TCP_KEEPIDLE: return ("TCP_KEEPIDLE"); case TCP_KEEPCNT: return ("TCP_KEEPCNT"); case TCP_KEEPINTVL: return ("TCP_KEEPINTVL"); case TCP_CONGESTION: return ("TCP_CONGESTION"); case TCP_QUICKACK: return ("TCP_QUICKACK"); case TCP_MD5SIG: return ("TCP_MD5SIG"); 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"); case UDP_SRCPORT_HASH: return ("UDP_SRCPORT_HASH"); default: (void) snprintf(pri->code_buf, sizeof (pri->code_buf), "0x%lx", val); return (pri->code_buf); } } const char * ip_optname(private_t *pri, long val) { switch (val) { case IP_OPTIONS: return ("IP_OPTIONS"); case IP_HDRINCL: return ("IP_HDRINCL"); case IP_TOS: return ("IP_TOS"); case IP_TTL: return ("IP_TTL"); case IP_RECVOPTS: return ("IP_RECVOPTS"); case IP_RECVRETOPTS: return ("IP_RECVRETOPTS"); case IP_RECVDSTADDR: return ("IP_RECVDSTADDR"); case IP_RETOPTS: return ("IP_RETOPTS"); case IP_RECVIF: return ("IP_RECVIF"); case IP_RECVSLLA: return ("IP_RECVSLLA"); case IP_RECVTTL: return ("IP_RECVTTL"); case IP_RECVTOS: return ("IP_RECVTOS"); case IP_MULTICAST_IF: return ("IP_MULTICAST_IF"); case IP_MULTICAST_TTL: return ("IP_MULTICAST_TTL"); case IP_MULTICAST_LOOP: return ("IP_MULTICAST_LOOP"); case IP_ADD_MEMBERSHIP: return ("IP_ADD_MEMBERSHIP"); case IP_DROP_MEMBERSHIP: return ("IP_DROP_MEMBERSHIP"); case IP_BLOCK_SOURCE: return ("IP_BLOCK_SOURCE"); case IP_UNBLOCK_SOURCE: return ("IP_UNBLOCK_SOURCE"); case IP_ADD_SOURCE_MEMBERSHIP: return ("IP_ADD_SOURCE_MEMBERSHIP"); case IP_DROP_SOURCE_MEMBERSHIP: return ("IP_DROP_SOURCE_MEMBERSHIP"); case IP_NEXTHOP: return ("IP_NEXTHOP"); /* IP_PKTINFO and IP_RECVPKTINFO share the same code */ case IP_PKTINFO: return ("IP_PKTINFO/IP_RECVPKTINFO"); case IP_DONTFRAG: return ("IP_DONTFRAG"); case IP_MINTTL: return ("IP_MINTTL"); case IP_SEC_OPT: return ("IP_SEC_OPT"); case MCAST_JOIN_GROUP: return ("MCAST_JOIN_GROUP"); case MCAST_LEAVE_GROUP: return ("MCAST_LEAVE_GROUP"); case MCAST_BLOCK_SOURCE: return ("MCAST_BLOCK_SOURCE"); case MCAST_UNBLOCK_SOURCE: return ("MCAST_UNBLOCK_SOURCE"); case MCAST_JOIN_SOURCE_GROUP: return ("MCAST_JOIN_SOURCE_GROUP"); case MCAST_LEAVE_SOURCE_GROUP: return ("MCAST_LEAVE_SOURCE_GROUP"); case MRT_INIT: return ("MRT_INIT"); case MRT_DONE: return ("MRT_DONE"); case MRT_ADD_VIF: return ("MRT_ADD_VIF"); case MRT_DEL_VIF: return ("MRT_DEL_VIF"); case MRT_ADD_MFC: return ("MRT_ADD_MFC"); case MRT_DEL_MFC: return ("MRT_DEL_MFC"); case MRT_VERSION: return ("MRT_VERSION"); case MRT_ASSERT: return ("MRT_ASSERT"); case IP_BOUND_IF: return ("IP_BOUND_IF"); case IP_UNSPEC_SRC: return ("IP_UNSPEC_SRC"); case IP_BROADCAST_TTL: return ("IP_BROADCAST_TTL"); case IP_DHCPINIT_IF: return ("IP_DHCPINIT_IF"); case IP_REUSEADDR: return ("IP_REUSEADDR"); case IP_DONTROUTE: return ("IP_DONTROUTE"); case IP_BROADCAST: return ("IP_BROADCAST"); default: (void) snprintf(pri->code_buf, sizeof (pri->code_buf), "0x%lx", val); return (pri->code_buf); } } const char * ipv6_optname(private_t *pri, long val) { switch (val) { case IPV6_UNICAST_HOPS: return ("IPV6_UNICAST_HOPS"); case IPV6_MULTICAST_IF: return ("IPV6_MULTICAST_IF"); case IPV6_MULTICAST_HOPS: return ("IPV6_MULTICAST_HOPS"); case IPV6_MULTICAST_LOOP: return ("IPV6_MULTICAST_LOOP"); case IPV6_JOIN_GROUP: return ("IPV6_JOIN_GROUP"); case IPV6_LEAVE_GROUP: return ("IPV6_LEAVE_GROUP"); case IPV6_PKTINFO: return ("IPV6_PKTINFO"); case IPV6_HOPLIMIT: return ("IPV6_HOPLIMIT"); case IPV6_NEXTHOP: return ("IPV6_NEXTHOP"); case IPV6_HOPOPTS: return ("IPV6_HOPOPTS"); case IPV6_DSTOPTS: return ("IPV6_DSTOPTS"); case IPV6_RTHDR: return ("IPV6_RTHDR"); case IPV6_RTHDRDSTOPTS: return ("IPV6_RTHDRDSTOPTS"); case IPV6_RECVPKTINFO: return ("IPV6_RECVPKTINFO"); case IPV6_RECVHOPLIMIT: return ("IPV6_RECVHOPLIMIT"); case IPV6_RECVHOPOPTS: return ("IPV6_RECVHOPOPTS"); case _OLD_IPV6_RECVDSTOPTS: return ("_OLD_IPV6_RECVDSTOPTS"); case IPV6_RECVRTHDR: return ("IPV6_RECVRTHDR"); case IPV6_RECVRTHDRDSTOPTS: return ("IPV6_RECVRTHDRDSTOPTS"); case IPV6_CHECKSUM: return ("IPV6_CHECKSUM"); case IPV6_RECVTCLASS: return ("IPV6_RECVTCLASS"); case IPV6_USE_MIN_MTU: return ("IPV6_USE_MIN_MTU"); case IPV6_DONTFRAG: return ("IPV6_DONTFRAG"); case IPV6_SEC_OPT: return ("IPV6_SEC_OPT"); case IPV6_SRC_PREFERENCES: return ("IPV6_SRC_PREFERENCES"); case IPV6_RECVPATHMTU: return ("IPV6_RECVPATHMTU"); case IPV6_PATHMTU: return ("IPV6_PATHMTU"); case IPV6_TCLASS: return ("IPV6_TCLASS"); case IPV6_V6ONLY: return ("IPV6_V6ONLY"); case IPV6_RECVDSTOPTS: return ("IPV6_RECVDSTOPTS"); case MCAST_JOIN_GROUP: return ("MCAST_JOIN_GROUP"); case MCAST_LEAVE_GROUP: return ("MCAST_LEAVE_GROUP"); case MCAST_BLOCK_SOURCE: return ("MCAST_BLOCK_SOURCE"); case MCAST_UNBLOCK_SOURCE: return ("MCAST_UNBLOCK_SOURCE"); case MCAST_JOIN_SOURCE_GROUP: return ("MCAST_JOIN_SOURCE_GROUP"); case MCAST_LEAVE_SOURCE_GROUP: return ("MCAST_LEAVE_SOURCE_GROUP"); case IPV6_MINHOPCOUNT: return ("IPV6_MINHOPCOUNT"); default: (void) snprintf(pri->code_buf, sizeof (pri->code_buf), "0x%lx", val); return (pri->code_buf); } } const char * icmpv6_optname(private_t *pri, long val) { switch (val) { case ICMP6_FILTER: return ("ICMP6_FILTER"); 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_IP: outstring(pri, ip_optname(pri, val)); break; case IPPROTO_IPV6: outstring(pri, ipv6_optname(pri, val)); break; case IPPROTO_ICMPV6: outstring(pri, icmpv6_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; if (raw) { (void) snprintf(s, CBSIZE, "0x%lx", val); outstring(pri, s); return; } if (val == 0) { outstring(pri, "(no flags)"); return; } *s = '\0'; for (size_t i = 0; i < ARRAY_SIZE(fcntl_flags); i++) { struct fcntl_flags *fp = &fcntl_flags[i]; 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 } /* * Print fcntl() F_GETFD/F_SETFD values */ static struct fcntl_fdflags { long val; const char *name; } fcntl_fdflags[] = { { FD_CLOEXEC, "|FD_CLOEXEC" }, { FD_CLOFORK, "|FD_CLOFORK" } }; void prt_ffd(private_t *pri, int raw, long val) { #define CBSIZE sizeof (pri->code_buf) char *s = pri->code_buf; size_t used = 1; if (raw) { (void) snprintf(s, CBSIZE, "0x%lx", val); outstring(pri, s); return; } if (val == 0) { outstring(pri, "(no flags)"); return; } *s = '\0'; for (size_t i = 0; i < ARRAY_SIZE(fcntl_fdflags); i++) { struct fcntl_fdflags *fp = &fcntl_fdflags[i]; 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); } void prt_grf(private_t *pri, int raw, long val) { int first = 1; if (raw != 0 || val == 0 || (val & ~(GRND_NONBLOCK | GRND_RANDOM)) != 0) { outstring(pri, "0"); return; } if (val & GRND_NONBLOCK) { outstring(pri, "|GRND_NONBLOCK" + first); first = 0; } if (val & GRND_RANDOM) { outstring(pri, "|GRND_RANDOM" + first); first = 0; } } void prt_exc(private_t *pri, int raw, long val) { #define CBSIZE sizeof (pri->code_buf) char *str = pri->code_buf; size_t used = 0; if (raw) { prt_hex(pri, 0, val); return; } if (val == 0) { outstring(pri, "0"); return; } *str = '\0'; if (val & EXEC_DESCRIPTOR) { used = strlcat(str, "|EXEC_DESCRIPTOR", CBSIZE); val &= ~EXEC_DESCRIPTOR; } if (val != 0 && used <= CBSIZE) used += snprintf(str + used, CBSIZE - used, "|0x%lx", val); if (used >= CBSIZE) (void) snprintf(str + 1, CBSIZE - 1, "0x%lx", val); outstring(pri, str + 1); #undef CBSIZE } /* * Print recv*(), send*() flags. This includes all the msg_flags data as well as * they're the same namespace. */ static struct sendrecv_flags { long val; const char *name; } sendrecv_flags[] = { { MSG_OOB, "|MSG_OOB" }, { MSG_PEEK, "|MSG_PEEK" }, { MSG_DONTROUTE, "|MSG_DONTROUTE" }, { MSG_CTRUNC, "|MSG_CTRUNC" }, { MSG_TRUNC, "|MSG_TRUNC" }, { MSG_WAITALL, "|MSG_WAITALL" }, { MSG_DONTWAIT, "|MSG_DONTWAIT" }, { MSG_NOTIFICATION, "|MSG_NOTIFICATION" }, { MSG_NOSIGNAL, "|MSG_NOSIGNAL" }, { MSG_DUPCTRL, "|MSG_DUPCTRL" }, { MSG_CMSG_CLOEXEC, "|MSG_CMSG_CLOEXEC" }, { MSG_CMSG_CLOFORK, "|MSG_CMSG_CLOFORK" }, { MSG_XPG4_2, "|MSG_XPG4_2" } }; void prt_srf(private_t *pri, int raw, long val) { #define CBSIZE sizeof (pri->code_buf) char *s = pri->code_buf; size_t used = 1; if (raw) { (void) snprintf(s, CBSIZE, "0x%lx", val); outstring(pri, s); return; } if (val == 0) { outstring(pri, "(no flags)"); return; } *s = '\0'; for (size_t i = 0; i < ARRAY_SIZE(sendrecv_flags); i++) { struct sendrecv_flags *fp = &sendrecv_flags[i]; 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 } /* * Print fdsync() internal argument. */ void prt_fds(private_t *pri, int raw, long val) { if (raw) { prt_hex(pri, 0, val); return; } switch (val) { case FDSYNC_FS: outstring(pri, "FDSYNC_FS"); break; case FDSYNC_FILE: outstring(pri, "FDSYNC_FILE"); break; case FDSYNC_DATA: outstring(pri, "FDSYNC_DATA"); break; default: prt_hex(pri, 0, val); break; } } /* * 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_grf, /* GRF -- print getrandom flags */ prt_psdelta, /* PSDLT -- print psecflags(2) delta */ prt_psfw, /* PSFW -- print psecflags(2) set */ prt_exc, /* EXC -- print execvex() flags */ prt_ffd, /* FFD -- print fcntl() F_SETFD flags */ prt_srf, /* SRF -- print send*()/recv*() flags */ prt_fds, /* FDS -- print fdsync() flags */ prt_dec, /* HID -- hidden argument, make this the last one */ }; /* * 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) 2015, Joyent, Inc. * Copyright 2024 Oxide Computer Company */ /* 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 GRF 101 /* getrandom flags */ #define PSDLT 102 /* secflagsdelta_t */ #define PSFW 103 /* psecflagswhich_t */ #define EXC 104 /* execx flags */ #define FFD 105 /* fcntl F_SETFD flags */ #define SRF 106 /* send*(), recv() flags */ #define FDS 107 /* fdsync flags */ #define HID 108 /* 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 */ /* * 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 */ #include #include #include #include #include #include #include #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)); } /* * 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 #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 prt_ffd(private_t *, int, long); extern void escape_string(private_t *, const char *); #ifdef __cplusplus } #endif #endif /* _PROTO_H */ /* * 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 #include #include #include #include #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 */ /* * 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 #include #include #include #include #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 */ /* * 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 #include #include #include #include #include #include #include #include #include "ramdata.h" #include "proto.h" void show_stat32(private_t *, long); void show_stat64(private_t *, long); void show_stat(private_t *pri, long offset) { if (data_model == PR_MODEL_LP64) show_stat64(pri, offset); else show_stat32(pri, offset); } void show_stat32(private_t *pri, long offset) { struct stat32 statb; timestruc_t ts; if (offset != 0 && 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 != 0 && 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); } } void show_stat64(private_t *pri, long offset) { struct stat64 statb; if (offset != 0 && 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); } } /* * 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) 2015, Joyent, Inc. All rights reserved. * Copyright 2024 Oxide Computer Company */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ /* Copyright (c) 2013, OmniTI Computer Consulting, Inc. All rights reserved. */ #include #include #include #include #include #include #include #include #include #include #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 */ {"psecflags", 3, DEC, NOV, HEX, PSFW, PSDLT}, /* 2 */ {"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, FDS}, /* 58 */ {"execvex", 4, DEC, NOV, STG, HEX, HEX, EXC}, /* 59 */ {"umask", 1, OCT, NOV, OCT}, /* 60 */ {"chroot", 1, DEC, NOV, STG}, /* 61 */ {"fcntl", 4, DEC, NOV, DEC, FCN, HEX, 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 */ {"preadv", 4, DEC, NOV, DEC, HEX, DEC, DEC}, /* 123 */ {"pwritev", 4, DEC, NOV, DEC, HEX, DEC, DEC}, /* 124 */ {"upanic", 2, DEC, NOV, HEX, DEC}, /* 125 */ {"getrandom", 3, DEC, NOV, IOB, UNS, GRF}, /* 126 */ {"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, SRF}, /* 237 */ {"recvfrom", 6, DEC, NOV, DEC, IOB, DEC, SRF, HEX, HEX}, /* 238 */ {"recvmsg", 3, DEC, NOV, DEC, HEX, SRF}, /* 239 */ {"send", 4, DEC, NOV, DEC, IOB, DEC, SRF}, /* 240 */ {"sendmsg", 3, DEC, NOV, DEC, HEX, SRF}, /* 241 */ {"sendto", 6, DEC, NOV, DEC, IOB, DEC, SRF, 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 */ {"fcntl", 3, DEC, NOV, DEC, FCN, FFD}, /* 3: F_SETFD */ {"fcntl", 4, DEC, NOV, DEC, FCN, DEC, FFD}, /* 4: F_DUP3FD */ }; #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 */ {"getcontext_extd", 2, DEC, NOV, HID, HEX}, /* 4 */ }; #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 }, { "execve", SYS_execve }, { "execvp", SYS_execve }, { "fexecve", 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] == 0) { 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] == 0) { 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] == 0) { 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; case F_SETFD: subcode = 3; break; case F_DUP3FD: subcode = 4; 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 /* * 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 #include #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 */