Index: head/lib/libsysdecode/Makefile =================================================================== --- head/lib/libsysdecode/Makefile (revision 307537) +++ head/lib/libsysdecode/Makefile (revision 307538) @@ -1,45 +1,122 @@ # $FreeBSD$ .include PACKAGE=lib${LIB} LIB= sysdecode -SRCS= errno.c ioctl.c syscallnames.c utrace.c +SRCS= errno.c flags.c ioctl.c signal.c syscallnames.c utrace.c INCS= sysdecode.h +CFLAGS+= -I${.OBJDIR} CFLAGS+= -I${.CURDIR}/../../sys CFLAGS+= -I${.CURDIR}/../../libexec/rtld-elf -MAN+= sysdecode.3 \ +MAN= sysdecode.3 \ sysdecode_abi_to_freebsd_errno.3 \ + sysdecode_cap_rights.3 \ + sysdecode_enum.3 \ + sysdecode_fcntl_arg.3 \ sysdecode_ioctlname.3 \ + sysdecode_mask.3 \ + sysdecode_quotactl_cmd.3 \ + sysdecode_sigcode.3 \ + sysdecode_sockopt_name.3 \ sysdecode_syscallnames.3 \ sysdecode_utrace.3 -MLINKS+= sysdecode_abi_to_freebsd_errno.3 sysdecode_freebsd_to_abi_errno.3 +MLINKS= sysdecode_abi_to_freebsd_errno.3 sysdecode_freebsd_to_abi_errno.3 +MLINKS+=sysdecode_enum.3 sysdecode_acltype.3 \ + sysdecode_enum.3 sysdecode_atfd.3 \ + sysdecode_enum.3 sysdecode_extattrnamespace.3 \ + sysdecode_enum.3 sysdecode_fadvice.3 \ + sysdecode_enum.3 sysdecode_fcntl_cmd.3 \ + sysdecode_enum.3 sysdecode_idtype.3 \ + sysdecode_enum.3 sysdecode_ipproto.3 \ + sysdecode_enum.3 sysdecode_kldsym_cmd.3 \ + sysdecode_enum.3 sysdecode_kldunload_flags.3 \ + sysdecode_enum.3 sysdecode_lio_listio_mode.3 \ + sysdecode_enum.3 sysdecode_madvice.3 \ + sysdecode_enum.3 sysdecode_minherit_flags.3 \ + sysdecode_enum.3 sysdecode_msgctl_cmd.3 \ + sysdecode_enum.3 sysdecode_nfssvc_flags.3 \ + sysdecode_enum.3 sysdecode_prio_which.3 \ + sysdecode_enum.3 sysdecode_procctl_cmd.3 \ + sysdecode_enum.3 sysdecode_ptrace_request.3 \ + sysdecode_enum.3 sysdecode_rlimit.3 \ + sysdecode_enum.3 sysdecode_rtprio_function.3 \ + sysdecode_enum.3 sysdecode_scheduler_policy.3 \ + sysdecode_enum.3 sysdecode_semctl_cmd.3 \ + sysdecode_enum.3 sysdecode_shmctl_cmd.3 \ + sysdecode_enum.3 sysdecode_shutdown_how.3 \ + sysdecode_enum.3 sysdecode_sigbus_code.3 \ + sysdecode_enum.3 sysdecode_sigchld_code.3 \ + sysdecode_enum.3 sysdecode_sigfpe_code.3 \ + sysdecode_enum.3 sysdecode_sigill_code.3 \ + sysdecode_enum.3 sysdecode_signal.3 \ + sysdecode_enum.3 sysdecode_sigprocmask_how.3 \ + sysdecode_enum.3 sysdecode_sigsegv_code.3 \ + sysdecode_enum.3 sysdecode_sigtrap_code.3 \ + sysdecode_enum.3 sysdecode_sockaddr_family.3 \ + sysdecode_enum.3 sysdecode_socketdomain.3 \ + sysdecode_enum.3 sysdecode_sockettype.3 \ + sysdecode_enum.3 sysdecode_sockopt_level.3 \ + sysdecode_enum.3 sysdecode_umtx_op.3 \ + sysdecode_enum.3 sysdecode_vmresult.3 \ + sysdecode_enum.3 sysdecode_whence.3 +MLINKS+=sysdecode_fcntl_arg.3 sysdecode_fcntl_arg_p.3 +MLINKS+=sysdecode_mask.3 sysdecode_accessmode.3 \ + sysdecode_mask.3 sysdecode_capfcntlrights.3 \ + sysdecode_mask.3 sysdecode_fcntl_fileflags.3 \ + sysdecode_mask.3 sysdecode_fileflags.3 \ + sysdecode_mask.3 sysdecode_filemode.3 \ + sysdecode_mask.3 sysdecode_flock_operation.3 \ + sysdecode_mask.3 sysdecode_getfsstat_flags.3 \ + sysdecode_mask.3 sysdecode_mlockall_flags.3 \ + sysdecode_mask.3 sysdecode_mmap_flags.3 \ + sysdecode_mask.3 sysdecode_mmap_prot.3 \ + sysdecode_mask.3 sysdecode_mount_flags.3 \ + sysdecode_mask.3 sysdecode_msg_flags.3 \ + sysdecode_mask.3 sysdecode_msync_flags.3 \ + sysdecode_mask.3 sysdecode_open_flags.3 \ + sysdecode_mask.3 sysdecode_pipe2_flags.3 \ + sysdecode_mask.3 sysdecode_reboot_howto.3 \ + sysdecode_mask.3 sysdecode_rfork_flags.3 \ + sysdecode_mask.3 sysdecode_semget_flags.3 \ + sysdecode_mask.3 sysdecode_sendfile_flags.3 \ + sysdecode_mask.3 sysdecode_shmat_flags.3 \ + sysdecode_mask.3 sysdecode_socket_type.3 \ + sysdecode_mask.3 sysdecode_thr_create_flags.3 \ + sysdecode_mask.3 sysdecode_umtx_cvwait_flags.3 \ + sysdecode_mask.3 sysdecode_umtx_rwlock_flags.3 \ + sysdecode_mask.3 sysdecode_vmprot.3 \ + sysdecode_mask.3 sysdecode_wait4_options.3 \ + sysdecode_mask.3 sysdecode_wait6_options.3 -CLEANFILES= ioctl.c +CLEANFILES= ioctl.c tables.h .if defined(COMPAT_32BIT) CPP+= -m32 .endif .if ${MK_PF} != "no" CFLAGS+=-DPF .endif # Workaround duplicate declarations in CFLAGS.gcc.ioctl.c+= -Wno-redundant-decls # Workaround warning for unused ssi_cables[] in CFLAGS.gcc.ioctl.c+= -Wno-unused CFLAGS.gcc+= ${CFLAGS.gcc.${.IMPSRC}} +tables.h: mktables + sh ${.CURDIR}/mktables ${DESTDIR}${INCLUDEDIR} > ${.TARGET} + ioctl.c: mkioctls env MACHINE=${MACHINE} CPP="${CPP}" \ /bin/sh ${.CURDIR}/mkioctls ${DESTDIR}${INCLUDEDIR} > ${.TARGET} -beforedepend: ioctl.c +beforedepend: ioctl.c tables.h .include Index: head/lib/libsysdecode/errno.c =================================================================== --- head/lib/libsysdecode/errno.c (revision 307537) +++ head/lib/libsysdecode/errno.c (revision 307538) @@ -1,209 +1,212 @@ /*- * Copyright (c) 2015 John H. Baldwin * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include +#include +#include #include #include +#include #include #include #if defined(__i386__) || defined(__amd64__) /* * Linux syscalls return negative errno's, we do positive and map them * Reference: * FreeBSD: src/sys/sys/errno.h * Linux: linux-2.6.17.8/include/asm-generic/errno-base.h * linux-2.6.17.8/include/asm-generic/errno.h */ static int bsd_to_linux_errno[ELAST + 1] = { -0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -35, -12, -13, -14, -15, -16, -17, -18, -19, -20, -21, -22, -23, -24, -25, -26, -27, -28, -29, -30, -31, -32, -33, -34, -11,-115,-114, -88, -89, -90, -91, -92, -93, -94, -95, -96, -97, -98, -99, -100,-101,-102,-103,-104,-105,-106,-107,-108,-109, -110,-111, -40, -36,-112,-113, -39, -11, -87,-122, -116, -66, -6, -6, -6, -6, -6, -37, -38, -9, -6, -6, -43, -42, -75,-125, -84, -95, -16, -74, -72, -67, -71 }; #endif #if defined(__aarch64__) || defined(__amd64__) #include static const int cloudabi_errno_table[] = { [CLOUDABI_E2BIG] = E2BIG, [CLOUDABI_EACCES] = EACCES, [CLOUDABI_EADDRINUSE] = EADDRINUSE, [CLOUDABI_EADDRNOTAVAIL] = EADDRNOTAVAIL, [CLOUDABI_EAFNOSUPPORT] = EAFNOSUPPORT, [CLOUDABI_EAGAIN] = EAGAIN, [CLOUDABI_EALREADY] = EALREADY, [CLOUDABI_EBADF] = EBADF, [CLOUDABI_EBADMSG] = EBADMSG, [CLOUDABI_EBUSY] = EBUSY, [CLOUDABI_ECANCELED] = ECANCELED, [CLOUDABI_ECHILD] = ECHILD, [CLOUDABI_ECONNABORTED] = ECONNABORTED, [CLOUDABI_ECONNREFUSED] = ECONNREFUSED, [CLOUDABI_ECONNRESET] = ECONNRESET, [CLOUDABI_EDEADLK] = EDEADLK, [CLOUDABI_EDESTADDRREQ] = EDESTADDRREQ, [CLOUDABI_EDOM] = EDOM, [CLOUDABI_EDQUOT] = EDQUOT, [CLOUDABI_EEXIST] = EEXIST, [CLOUDABI_EFAULT] = EFAULT, [CLOUDABI_EFBIG] = EFBIG, [CLOUDABI_EHOSTUNREACH] = EHOSTUNREACH, [CLOUDABI_EIDRM] = EIDRM, [CLOUDABI_EILSEQ] = EILSEQ, [CLOUDABI_EINPROGRESS] = EINPROGRESS, [CLOUDABI_EINTR] = EINTR, [CLOUDABI_EINVAL] = EINVAL, [CLOUDABI_EIO] = EIO, [CLOUDABI_EISCONN] = EISCONN, [CLOUDABI_EISDIR] = EISDIR, [CLOUDABI_ELOOP] = ELOOP, [CLOUDABI_EMFILE] = EMFILE, [CLOUDABI_EMLINK] = EMLINK, [CLOUDABI_EMSGSIZE] = EMSGSIZE, [CLOUDABI_EMULTIHOP] = EMULTIHOP, [CLOUDABI_ENAMETOOLONG] = ENAMETOOLONG, [CLOUDABI_ENETDOWN] = ENETDOWN, [CLOUDABI_ENETRESET] = ENETRESET, [CLOUDABI_ENETUNREACH] = ENETUNREACH, [CLOUDABI_ENFILE] = ENFILE, [CLOUDABI_ENOBUFS] = ENOBUFS, [CLOUDABI_ENODEV] = ENODEV, [CLOUDABI_ENOENT] = ENOENT, [CLOUDABI_ENOEXEC] = ENOEXEC, [CLOUDABI_ENOLCK] = ENOLCK, [CLOUDABI_ENOLINK] = ENOLINK, [CLOUDABI_ENOMEM] = ENOMEM, [CLOUDABI_ENOMSG] = ENOMSG, [CLOUDABI_ENOPROTOOPT] = ENOPROTOOPT, [CLOUDABI_ENOSPC] = ENOSPC, [CLOUDABI_ENOSYS] = ENOSYS, [CLOUDABI_ENOTCONN] = ENOTCONN, [CLOUDABI_ENOTDIR] = ENOTDIR, [CLOUDABI_ENOTEMPTY] = ENOTEMPTY, [CLOUDABI_ENOTRECOVERABLE] = ENOTRECOVERABLE, [CLOUDABI_ENOTSOCK] = ENOTSOCK, [CLOUDABI_ENOTSUP] = ENOTSUP, [CLOUDABI_ENOTTY] = ENOTTY, [CLOUDABI_ENXIO] = ENXIO, [CLOUDABI_EOVERFLOW] = EOVERFLOW, [CLOUDABI_EOWNERDEAD] = EOWNERDEAD, [CLOUDABI_EPERM] = EPERM, [CLOUDABI_EPIPE] = EPIPE, [CLOUDABI_EPROTO] = EPROTO, [CLOUDABI_EPROTONOSUPPORT] = EPROTONOSUPPORT, [CLOUDABI_EPROTOTYPE] = EPROTOTYPE, [CLOUDABI_ERANGE] = ERANGE, [CLOUDABI_EROFS] = EROFS, [CLOUDABI_ESPIPE] = ESPIPE, [CLOUDABI_ESRCH] = ESRCH, [CLOUDABI_ESTALE] = ESTALE, [CLOUDABI_ETIMEDOUT] = ETIMEDOUT, [CLOUDABI_ETXTBSY] = ETXTBSY, [CLOUDABI_EXDEV] = EXDEV, [CLOUDABI_ENOTCAPABLE] = ENOTCAPABLE, }; #endif int sysdecode_abi_to_freebsd_errno(enum sysdecode_abi abi, int error) { switch (abi) { case SYSDECODE_ABI_FREEBSD: case SYSDECODE_ABI_FREEBSD32: return (error); #if defined(__i386__) || defined(__amd64__) case SYSDECODE_ABI_LINUX: case SYSDECODE_ABI_LINUX32: { unsigned int i; /* * This is imprecise since it returns the first * matching errno. */ for (i = 0; i < nitems(bsd_to_linux_errno); i++) { if (error == bsd_to_linux_errno[i]) return (i); } break; } #endif #if defined(__aarch64__) || defined(__amd64__) case SYSDECODE_ABI_CLOUDABI64: if (error >= 0 && (unsigned int)error < nitems(cloudabi_errno_table)) return (cloudabi_errno_table[error]); break; #endif default: break; } return (INT_MAX); } int sysdecode_freebsd_to_abi_errno(enum sysdecode_abi abi, int error) { switch (abi) { case SYSDECODE_ABI_FREEBSD: case SYSDECODE_ABI_FREEBSD32: return (error); #if defined(__i386__) || defined(__amd64__) case SYSDECODE_ABI_LINUX: case SYSDECODE_ABI_LINUX32: if (error >= 0 && error <= ELAST) return (bsd_to_linux_errno[error]); break; #endif #if defined(__aarch64__) || defined(__amd64__) case SYSDECODE_ABI_CLOUDABI64: { unsigned int i; for (i = 0; i < nitems(cloudabi_errno_table); i++) { if (error == cloudabi_errno_table[i]) return (i); } break; } #endif default: break; } return (INT_MAX); } Index: head/lib/libsysdecode/flags.c =================================================================== --- head/lib/libsysdecode/flags.c (nonexistent) +++ head/lib/libsysdecode/flags.c (revision 307538) @@ -0,0 +1,982 @@ +/* + * Copyright (c) 2006 "David Kirchner" . All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#define L2CAP_SOCKET_CHECKED + +#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 + +/* + * This is taken from the xlat tables originally in truss which were + * in turn taken from strace. + */ +struct name_table { + uintmax_t val; + const char *str; +}; + +#define X(a) { a, #a }, +#define XEND { 0, NULL } + +#define TABLE_START(n) static struct name_table n[] = { +#define TABLE_ENTRY X +#define TABLE_END XEND }; + +#include "tables.h" + +#undef TABLE_START +#undef TABLE_ENTRY +#undef TABLE_END + +/* + * These are simple support macros. print_or utilizes a variable + * defined in the calling function to track whether or not it should + * print a logical-OR character ('|') before a string. if_print_or + * simply handles the necessary "if" statement used in many lines + * of this file. + */ +#define print_or(fp,str,orflag) do { \ + if (orflag) fputc(fp, '|'); else orflag = true; \ + fprintf(fp, str); } \ + while (0) +#define if_print_or(fp,i,flag,orflag) do { \ + if ((i & flag) == flag) \ + print_or(fp,#flag,orflag); } \ + while (0) + +static const char * +lookup_value(struct name_table *table, uintmax_t val) +{ + + for (; table->str != NULL; table++) + if (table->val == val) + return (table->str); + return (NULL); +} + +/* + * Used when the value maps to a bitmask of #definition values in the + * table. This is a helper routine which outputs a symbolic mask of + * matched masks. Multiple masks are separated by a pipe ('|'). + * The value is modified on return to only hold unmatched bits. + */ +static void +print_mask_part(FILE *fp, struct name_table *table, uintmax_t *valp, + bool *printed) +{ + uintmax_t rem; + + rem = *valp; + for (; table->str != NULL; table++) { + if ((table->val & rem) == table->val) { + /* + * Only print a zero mask if the raw value is + * zero. + */ + if (table->val == 0 && *valp != 0) + continue; + fprintf(fp, "%s%s", *printed ? "|" : "", table->str); + *printed = true; + rem &= ~table->val; + } + } + + *valp = rem; +} + +/* + * Used when the value maps to a bitmask of #definition values in the + * table. The return value is true if something was printed. If + * rem is not NULL, *rem holds any bits not decoded if something was + * printed. If nothing was printed and rem is not NULL, *rem holds + * the original value. + */ +static bool +print_mask_int(FILE *fp, struct name_table *table, int ival, int *rem) +{ + uintmax_t val; + bool printed; + + printed = false; + val = (unsigned)ival; + print_mask_part(fp, table, &val, &printed); + if (rem != NULL) + *rem = val; + return (printed); +} + +/* + * Used for a mask of optional flags where a value of 0 is valid. + */ +static bool +print_mask_0(FILE *fp, struct name_table *table, int val, int *rem) +{ + + if (val == 0) { + fputs("0", fp); + if (rem != NULL) + *rem = 0; + return (true); + } + return (print_mask_int(fp, table, val, rem)); +} + +/* + * Like print_mask_0 but for a unsigned long instead of an int. + */ +static bool +print_mask_0ul(FILE *fp, struct name_table *table, u_long lval, u_long *rem) +{ + uintmax_t val; + bool printed; + + if (lval == 0) { + fputs("0", fp); + if (rem != NULL) + *rem = 0; + return (true); + } + + printed = false; + val = lval; + print_mask_part(fp, table, &val, &printed); + if (rem != NULL) + *rem = val; + return (printed); +} + +static void +print_integer(FILE *fp, int val, int base) +{ + + switch (base) { + case 8: + fprintf(fp, "0%o", val); + break; + case 10: + fprintf(fp, "%d", val); + break; + case 16: + fprintf(fp, "0x%x", val); + break; + default: + abort2("bad base", 0, NULL); + break; + } +} + +static bool +print_value(FILE *fp, struct name_table *table, uintmax_t val) +{ + const char *str; + + str = lookup_value(table, val); + if (str != NULL) { + fputs(str, fp); + return (true); + } + return (false); +} + +const char * +sysdecode_atfd(int fd) +{ + + if (fd == AT_FDCWD) + return ("AT_FDCWD"); + return (NULL); +} + +static struct name_table semctlops[] = { + X(GETNCNT) X(GETPID) X(GETVAL) X(GETALL) X(GETZCNT) X(SETVAL) X(SETALL) + X(IPC_RMID) X(IPC_SET) X(IPC_STAT) XEND +}; + +const char * +sysdecode_semctl_cmd(int cmd) +{ + + return (lookup_value(semctlops, cmd)); +} + +static struct name_table shmctlops[] = { + X(IPC_RMID) X(IPC_SET) X(IPC_STAT) XEND +}; + +const char * +sysdecode_shmctl_cmd(int cmd) +{ + + return (lookup_value(shmctlops, cmd)); +} + +const char * +sysdecode_msgctl_cmd(int cmd) +{ + + return (sysdecode_shmctl_cmd(cmd)); +} + +static struct name_table semgetflags[] = { + X(IPC_CREAT) X(IPC_EXCL) X(SEM_R) X(SEM_A) X((SEM_R>>3)) X((SEM_A>>3)) + X((SEM_R>>6)) X((SEM_A>>6)) XEND +}; + +bool +sysdecode_semget_flags(FILE *fp, int flag, int *rem) +{ + + return (print_mask_int(fp, semgetflags, flag, rem)); +} + +static struct name_table idtypes[] = { + X(P_PID) X(P_PPID) X(P_PGID) X(P_SID) X(P_CID) X(P_UID) X(P_GID) + X(P_ALL) X(P_LWPID) X(P_TASKID) X(P_PROJID) X(P_POOLID) X(P_JAILID) + X(P_CTID) X(P_CPUID) X(P_PSETID) XEND +}; + +/* XXX: idtype is really an idtype_t */ +const char * +sysdecode_idtype(int idtype) +{ + + return (lookup_value(idtypes, idtype)); +} + +/* + * [g|s]etsockopt's level argument can either be SOL_SOCKET or a + * protocol-specific value. + */ +const char * +sysdecode_sockopt_level(int level) +{ + const char *str; + + if (level == SOL_SOCKET) + return ("SOL_SOCKET"); + + /* SOL_* constants for Bluetooth sockets. */ + str = lookup_value(ngbtsolevel, level); + if (str != NULL) + return (str); + + /* + * IP and Infiniband sockets use IP protocols as levels. Not all + * protocols are valid but it is simpler to just allow all of them. + * + * XXX: IPPROTO_IP == 0, but UNIX domain sockets use a level of 0 + * for private options. + */ + str = sysdecode_ipproto(level); + if (str != NULL) + return (str); + + return (NULL); +} + +bool +sysdecode_vmprot(FILE *fp, int type, int *rem) +{ + + return (print_mask_int(fp, vmprot, type, rem)); +} + +static struct name_table sockflags[] = { + X(SOCK_CLOEXEC) X(SOCK_NONBLOCK) XEND +}; + +bool +sysdecode_socket_type(FILE *fp, int type, int *rem) +{ + const char *str; + uintmax_t val; + bool printed; + + str = lookup_value(socktype, type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)); + if (str != NULL) { + fputs(str, fp); + *rem = 0; + printed = true; + } else { + *rem = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK); + printed = false; + } + val = type & (SOCK_CLOEXEC | SOCK_NONBLOCK); + print_mask_part(fp, sockflags, &val, &printed); + return (printed); +} + +bool +sysdecode_access_mode(FILE *fp, int mode, int *rem) +{ + + return (print_mask_int(fp, accessmode, mode, rem)); +} + +/* XXX: 'type' is really an acl_type_t. */ +const char * +sysdecode_acltype(int type) +{ + + return (lookup_value(acltype, type)); +} + +bool +sysdecode_cap_fcntlrights(FILE *fp, uint32_t rights, uint32_t *rem) +{ + + return (print_mask_int(fp, capfcntl, rights, rem)); +} + +const char * +sysdecode_extattrnamespace(int namespace) +{ + + return (lookup_value(extattrns, namespace)); +} + +const char * +sysdecode_fadvice(int advice) +{ + + return (lookup_value(fadvisebehav, advice)); +} + +bool +sysdecode_open_flags(FILE *fp, int flags, int *rem) +{ + bool printed; + int mode; + uintmax_t val; + + mode = flags & O_ACCMODE; + flags &= ~O_ACCMODE; + switch (mode) { + case O_RDONLY: + if (flags & O_EXEC) { + flags &= ~O_EXEC; + fputs("O_EXEC", fp); + } else + fputs("O_RDONLY", fp); + printed = true; + mode = 0; + break; + case O_WRONLY: + fputs("O_WRONLY", fp); + printed = true; + mode = 0; + break; + case O_RDWR: + fputs("O_RDWR", fp); + printed = true; + mode = 0; + break; + default: + printed = false; + } + val = (unsigned)flags; + print_mask_part(fp, openflags, &val, &printed); + if (rem != NULL) + *rem = val | mode; + return (printed); +} + +bool +sysdecode_fcntl_fileflags(FILE *fp, int flags, int *rem) +{ + bool printed; + int oflags; + + /* + * The file flags used with F_GETFL/F_SETFL mostly match the + * flags passed to open(2). However, a few open-only flag + * bits have been repurposed for fcntl-only flags. + */ + oflags = flags & ~(O_NOFOLLOW | FRDAHEAD); + printed = sysdecode_open_flags(fp, oflags, rem); + if (flags & O_NOFOLLOW) { + fprintf(fp, "%sFPOIXSHM", printed ? "|" : ""); + printed = true; + } + if (flags & FRDAHEAD) { + fprintf(fp, "%sFRDAHEAD", printed ? "|" : ""); + printed = true; + } + return (printed); +} + +bool +sysdecode_flock_operation(FILE *fp, int operation, int *rem) +{ + + return (print_mask_int(fp, flockops, operation, rem)); +} + +bool +sysdecode_getfsstat_flags(FILE *fp, int flags, int *rem) +{ + + return (print_mask_int(fp, getfsstatflags, flags, rem)); +} + +const char * +sysdecode_kldsym_cmd(int cmd) +{ + + return (lookup_value(kldsymcmd, cmd)); +} + +const char * +sysdecode_kldunload_flags(int flags) +{ + + return (lookup_value(kldunloadfflags, flags)); +} + +const char * +sysdecode_lio_listio_mode(int mode) +{ + + return (lookup_value(lio_listiomodes, mode)); +} + +const char * +sysdecode_madvice(int advice) +{ + + return (lookup_value(madvisebehav, advice)); +} + +const char * +sysdecode_minherit_inherit(int inherit) +{ + + return (lookup_value(minheritflags, inherit)); +} + +bool +sysdecode_mlockall_flags(FILE *fp, int flags, int *rem) +{ + + return (print_mask_int(fp, mlockallflags, flags, rem)); +} + +bool +sysdecode_mmap_prot(FILE *fp, int prot, int *rem) +{ + + return (print_mask_int(fp, mmapprot, prot, rem)); +} + +bool +sysdecode_fileflags(FILE *fp, fflags_t flags, fflags_t *rem) +{ + + return (print_mask_0(fp, fileflags, flags, rem)); +} + +bool +sysdecode_filemode(FILE *fp, int mode, int *rem) +{ + + return (print_mask_0(fp, filemode, mode, rem)); +} + +bool +sysdecode_mount_flags(FILE *fp, int flags, int *rem) +{ + + return (print_mask_int(fp, mountflags, flags, rem)); +} + +bool +sysdecode_msync_flags(FILE *fp, int flags, int *rem) +{ + + return (print_mask_int(fp, msyncflags, flags, rem)); +} + +const char * +sysdecode_nfssvc_flags(int flags) +{ + + return (lookup_value(nfssvcflags, flags)); +} + +static struct name_table pipe2flags[] = { + X(O_CLOEXEC) X(O_NONBLOCK) XEND +}; + +bool +sysdecode_pipe2_flags(FILE *fp, int flags, int *rem) +{ + + return (print_mask_0(fp, pipe2flags, flags, rem)); +} + +const char * +sysdecode_prio_which(int which) +{ + + return (lookup_value(prio, which)); +} + +const char * +sysdecode_procctl_cmd(int cmd) +{ + + return (lookup_value(procctlcmd, cmd)); +} + +const char * +sysdecode_ptrace_request(int request) +{ + + return (lookup_value(ptraceop, request)); +} + +static struct name_table quotatypes[] = { + X(GRPQUOTA) X(USRQUOTA) XEND +}; + +bool +sysdecode_quotactl_cmd(FILE *fp, int cmd) +{ + const char *primary, *type; + + primary = lookup_value(quotactlcmds, cmd >> SUBCMDSHIFT); + if (primary == NULL) + return (false); + fprintf(fp, "QCMD(%s,", primary); + type = lookup_value(quotatypes, cmd & SUBCMDMASK); + if (type != NULL) + fprintf(fp, "%s", type); + else + fprintf(fp, "%#x", cmd & SUBCMDMASK); + fprintf(fp, ")"); + return (true); +} + +bool +sysdecode_reboot_howto(FILE *fp, int howto, int *rem) +{ + + return (print_mask_int(fp, rebootopt, howto, rem)); +} + +bool +sysdecode_rfork_flags(FILE *fp, int flags, int *rem) +{ + + return (print_mask_int(fp, rforkflags, flags, rem)); +} + +const char * +sysdecode_rlimit(int resource) +{ + + return (lookup_value(rlimit, resource)); +} + +const char * +sysdecode_scheduler_policy(int policy) +{ + + return (lookup_value(schedpolicy, policy)); +} + +bool +sysdecode_sendfile_flags(FILE *fp, int flags, int *rem) +{ + + return (print_mask_int(fp, sendfileflags, flags, rem)); +} + +bool +sysdecode_shmat_flags(FILE *fp, int flags, int *rem) +{ + + return (print_mask_int(fp, shmatflags, flags, rem)); +} + +const char * +sysdecode_shutdown_how(int how) +{ + + return (lookup_value(shutdownhow, how)); +} + +const char * +sysdecode_sigbus_code(int si_code) +{ + + return (lookup_value(sigbuscode, si_code)); +} + +const char * +sysdecode_sigchld_code(int si_code) +{ + + return (lookup_value(sigchldcode, si_code)); +} + +const char * +sysdecode_sigfpe_code(int si_code) +{ + + return (lookup_value(sigfpecode, si_code)); +} + +const char * +sysdecode_sigill_code(int si_code) +{ + + return (lookup_value(sigillcode, si_code)); +} + +const char * +sysdecode_sigsegv_code(int si_code) +{ + + return (lookup_value(sigsegvcode, si_code)); +} + +const char * +sysdecode_sigtrap_code(int si_code) +{ + + return (lookup_value(sigtrapcode, si_code)); +} + +const char * +sysdecode_sigprocmask_how(int how) +{ + + return (lookup_value(sigprocmaskhow, how)); +} + +const char * +sysdecode_socketdomain(int domain) +{ + + return (lookup_value(sockdomain, domain)); +} + +const char * +sysdecode_sockaddr_family(int sa_family) +{ + + return (lookup_value(sockfamily, sa_family)); +} + +const char * +sysdecode_ipproto(int protocol) +{ + + return (lookup_value(sockipproto, protocol)); +} + +const char * +sysdecode_sockopt_name(int level, int optname) +{ + + if (level == SOL_SOCKET) + return (lookup_value(sockopt, optname)); + if (level == IPPROTO_IP) + /* XXX: UNIX domain socket options use a level of 0 also. */ + return (lookup_value(sockoptip, optname)); + if (level == IPPROTO_TCP) + return (lookup_value(sockopttcp, optname)); + if (level == IPPROTO_UDP) + return (lookup_value(sockoptudp, optname)); + return (NULL); +} + +bool +sysdecode_thr_create_flags(FILE *fp, int flags, int *rem) +{ + + return (print_mask_int(fp, thrcreateflags, flags, rem)); +} + +const char * +sysdecode_umtx_op(int op) +{ + + return (lookup_value(umtxop, op)); +} + +const char * +sysdecode_vmresult(int result) +{ + + return (lookup_value(vmresult, result)); +} + +bool +sysdecode_wait4_options(FILE *fp, int options, int *rem) +{ + bool printed; + int opt6; + + /* A flags value of 0 is normal. */ + if (options == 0) { + fputs("0", fp); + if (rem != NULL) + *rem = 0; + return (true); + } + + /* + * These flags are implicit and aren't valid flags for wait4() + * directly (though they don't fail with EINVAL). + */ + opt6 = options & (WEXITED | WTRAPPED); + options &= ~opt6; + printed = print_mask_int(fp, wait6opt, options, rem); + if (rem != NULL) + *rem |= opt6; + return (printed); +} + +bool +sysdecode_wait6_options(FILE *fp, int options, int *rem) +{ + + return (print_mask_int(fp, wait6opt, options, rem)); +} + +const char * +sysdecode_whence(int whence) +{ + + return (lookup_value(seekwhence, whence)); +} + +const char * +sysdecode_fcntl_cmd(int cmd) +{ + + return (lookup_value(fcntlcmd, cmd)); +} + +static struct name_table fcntl_fd_arg[] = { + X(FD_CLOEXEC) X(0) XEND +}; + +bool +sysdecode_fcntl_arg_p(int cmd) +{ + + switch (cmd) { + case F_GETFD: + case F_GETFL: + case F_GETOWN: + return (false); + default: + return (true); + } +} + +void +sysdecode_fcntl_arg(FILE *fp, int cmd, uintptr_t arg, int base) +{ + int rem; + + switch (cmd) { + case F_SETFD: + if (!print_value(fp, fcntl_fd_arg, arg)) + print_integer(fp, arg, base); + break; + case F_SETFL: + if (!sysdecode_fcntl_fileflags(fp, arg, &rem)) + fprintf(fp, "%#x", rem); + else if (rem != 0) + fprintf(fp, "|%#x", rem); + break; + case F_GETLK: + case F_SETLK: + case F_SETLKW: + fprintf(fp, "%p", (void *)arg); + break; + default: + print_integer(fp, arg, base); + break; + } +} + +bool +sysdecode_mmap_flags(FILE *fp, int flags, int *rem) +{ + uintmax_t val; + bool printed; + int align; + + /* + * MAP_ALIGNED can't be handled directly by print_mask_int(). + * MAP_32BIT is also problematic since it isn't defined for + * all platforms. + */ + printed = false; + align = flags & MAP_ALIGNMENT_MASK; + val = (unsigned)flags & ~MAP_ALIGNMENT_MASK; + print_mask_part(fp, mmapflags, &val, &printed); +#ifdef MAP_32BIT + if (val & MAP_32BIT) { + fprintf(fp, "%sMAP_32BIT", printed ? "|" : ""); + printed = true; + val &= ~MAP_32BIT; + } +#endif + if (align != 0) { + if (printed) + fputc('|', fp); + if (align == MAP_ALIGNED_SUPER) + fputs("MAP_ALIGNED_SUPER", fp); + else + fprintf(fp, "MAP_ALIGNED(%d)", + align >> MAP_ALIGNMENT_SHIFT); + printed = true; + } + if (rem != NULL) + *rem = val; + return (printed); +} + +const char * +sysdecode_rtprio_function(int function) +{ + + return (lookup_value(rtpriofuncs, function)); +} + +bool +sysdecode_msg_flags(FILE *fp, int flags, int *rem) +{ + + return (print_mask_0(fp, msgflags, flags, rem)); +} + +const char * +sysdecode_sigcode(int sig, int si_code) +{ + const char *str; + + str = lookup_value(sigcode, si_code); + if (str != NULL) + return (str); + + switch (sig) { + case SIGILL: + return (sysdecode_sigill_code(si_code)); + case SIGBUS: + return (sysdecode_sigbus_code(si_code)); + case SIGSEGV: + return (sysdecode_sigsegv_code(si_code)); + case SIGFPE: + return (sysdecode_sigfpe_code(si_code)); + case SIGTRAP: + return (sysdecode_sigtrap_code(si_code)); + case SIGCHLD: + return (sysdecode_sigchld_code(si_code)); + default: + return (NULL); + } +} + +bool +sysdecode_umtx_cvwait_flags(FILE *fp, u_long flags, u_long *rem) +{ + + return (print_mask_0ul(fp, umtxcvwaitflags, flags, rem)); +} + +bool +sysdecode_umtx_rwlock_flags(FILE *fp, u_long flags, u_long *rem) +{ + + return (print_mask_0ul(fp, umtxrwlockflags, flags, rem)); +} + +/* XXX: This should be in */ +#define CAPMASK(right) ((right) && (((uint64_t)1 << 57) - 1)) + +void +sysdecode_cap_rights(FILE *fp, cap_rights_t *rightsp) +{ + struct name_table *t; + int idx; + bool comma; + + comma = false; + for (t = caprights; t->str != NULL; t++) { + idx = ffs(CAPIDXBIT(t->val)) - 1; + if (CAPARSIZE(rightsp) < idx) + continue; + if ((rightsp->cr_rights[CAPIDXBIT(t->val)] & CAPMASK(t->val)) == + CAPMASK(t->val)) { + fprintf(fp, "%s%s", comma ? "," : "", t->str); + comma = true; + } + } +} Property changes on: head/lib/libsysdecode/flags.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/lib/libsysdecode/mkioctls =================================================================== --- head/lib/libsysdecode/mkioctls (revision 307537) +++ head/lib/libsysdecode/mkioctls (revision 307538) @@ -1,97 +1,98 @@ #!/bin/sh # # $FreeBSD$ set -e if [ $# -ne 1 ]; then echo "usage: sh $0 include-dir" exit 1 fi includedir="$1" LC_ALL=C; export LC_ALL # Build a list of headers that have ioctls in them. # XXX should we use an ANSI cpp? ioctl_includes=$( cd $includedir find -H -s * -name '*.h' | \ egrep -v '(.*disk.*|net/pfvar|net/if_pfsync)\.h' | \ xargs egrep -l \ '^#[ ]*define[ ]+[A-Za-z_][A-Za-z0-9_]*[ ]+_IO[^a-z0-9_]' | awk '{printf("#include <%s>\\n", $1)}' ) : ${MACHINE=$(uname -m)} case "${MACHINE}" in *pc98*) ioctl_includes="$ioctl_includes#include \\n" ;; *) ioctl_includes="$ioctl_includes#include \\n" ;; esac awk -v x="$ioctl_includes" 'BEGIN {print x}' | $CPP -nostdinc -I$includedir -dM -DCOMPAT_43TTY - | awk -v ioctl_includes="$ioctl_includes" ' BEGIN { print "/* XXX obnoxious prerequisites. */" print "#define COMPAT_43" print "#define COMPAT_43TTY" print "#include " print "#include " print "#include " print "#include " print "#include " print "#include " print "#include " print "#include " print "#include " print "#ifdef PF" print "#include " print "#include " print "#endif" print "#include " print "#include " print "#include " print "#include " print "#include " print "#include " print "#include " print "#include " + print "#include " print "#include " print "#include " print "#include " print "" print ioctl_includes print "" print "const char *" print "sysdecode_ioctlname(unsigned long val)" print "{" print "\tconst char *str = NULL;" print "" } /^#[ ]*define[ ]+[A-Za-z_][A-Za-z0-9_]*[ ]+_IO/ { # find where the name starts for (i = 1; i <= NF; i++) if ($i ~ /define/) break; ++i; # printf("\t"); if (n++ > 0) printf("else "); printf("if (val == %s)\n", $i); printf("\t\tstr = \"%s\";\n", $i); } END { print "" print "\treturn (str);" print "}" } ' Index: head/lib/libsysdecode/mktables =================================================================== --- head/lib/libsysdecode/mktables (nonexistent) +++ head/lib/libsysdecode/mktables (revision 307538) @@ -0,0 +1,144 @@ +#!/bin/sh +# +# Copyright (c) 2006 "David Kirchner" . All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $FreeBSD$ +# +# Generates tables.h +# +# Originally this script was 'mksubr' for kdump which generated a complete +# C file along with function definitions. Now this script generates tables +# of constants and names extracted from header files. + +set -e + +LC_ALL=C; export LC_ALL + +if [ -z "$1" ] +then + echo "usage: sh $0 include-dir" + exit 1 +fi +include_dir=$1 + +# +# Generate a table C #definitions. The including file can define the +# TABLE_NAME(n), TABLE_ENTRY(x), and TABLE_END macros to define what +# the tables map to. +# +gen_table() +{ + local name grep file excl filter + name=$1 + grep=$2 + file=$3 + excl=$4 + + if [ -z "$excl" ]; then + filter="cat" + else + filter="egrep -v" + fi + cat <<_EOF_ +TABLE_START(${name}) +_EOF_ + egrep "^#[[:space:]]*define[[:space:]]+"${grep}"[[:space:]]*" \ + $include_dir/$file | ${filter} ${excl} | \ + awk '{ for (i = 1; i <= NF; i++) \ + if ($i ~ /define/) \ + break; \ + ++i; \ + printf "TABLE_ENTRY(%s)\n", $i }' +cat <<_EOF_ +TABLE_END + +_EOF_ +} + +cat <<_EOF_ +/* This file is auto-generated. */ + +_EOF_ + +gen_table "accessmode" "[A-Z]_OK[[:space:]]+0?x?[0-9A-Fa-f]+" "sys/unistd.h" +gen_table "acltype" "ACL_TYPE_[A-Z4_]+[[:space:]]+0x[0-9]+" "sys/acl.h" +gen_table "capfcntl" "CAP_FCNTL_[A-Z]+[[:space:]]+\(1" "sys/capsicum.h" +gen_table "extattrns" "EXTATTR_NAMESPACE_[A-Z]+[[:space:]]+0x[0-9]+" "sys/extattr.h" +gen_table "fadvisebehav" "POSIX_FADV_[A-Z]+[[:space:]]+[0-9]+" "sys/fcntl.h" +gen_table "openflags" "O_[A-Z]+[[:space:]]+0x[0-9A-Fa-f]+" "sys/fcntl.h" "O_RDONLY|O_RDWR|O_WRONLY" +gen_table "flockops" "LOCK_[A-Z]+[[:space:]]+0x[0-9]+" "sys/fcntl.h" +gen_table "getfsstatflags" "MNT_[A-Z]+[[:space:]]+[1-9][0-9]*" "sys/mount.h" +gen_table "kldsymcmd" "KLDSYM_[A-Z]+[[:space:]]+[0-9]+" "sys/linker.h" +gen_table "kldunloadfflags" "LINKER_UNLOAD_[A-Z]+[[:space:]]+[0-9]+" "sys/linker.h" +gen_table "lio_listiomodes" "LIO_(NO)?WAIT[[:space:]]+[0-9]+" "aio.h" +gen_table "madvisebehav" "_?MADV_[A-Z]+[[:space:]]+[0-9]+" "sys/mman.h" +gen_table "minheritflags" "INHERIT_[A-Z]+[[:space:]]+[0-9]+" "sys/mman.h" +gen_table "mlockallflags" "MCL_[A-Z]+[[:space:]]+0x[0-9]+" "sys/mman.h" +gen_table "mmapprot" "PROT_[A-Z]+[[:space:]]+0x[0-9A-Fa-f]+" "sys/mman.h" +gen_table "ngbtsolevel" "SOL_[A-Z0-9]+[[:space:]]+0x[0-9A-Fa-f]+" "netgraph/bluetooth/include/ng_btsocket.h" +gen_table "fileflags" "[SU]F_[A-Z]+[[:space:]]+0x[0-9A-Fa-f]+" "sys/stat.h" "UF_COMPRESSED|UF_TRACKED|UF_SETTABLE|SF_SETTABLE" +gen_table "filemode" "S_[A-Z]+[[:space:]]+[0-6]{7}" "sys/stat.h" +gen_table "mountflags" "MNT_[A-Z]+[[:space:]]+0x[0-9]+" "sys/mount.h" +gen_table "msyncflags" "MS_[A-Z]+[[:space:]]+0x[0-9]+" "sys/mman.h" +gen_table "nfssvcflags" "NFSSVC_[A-Z0-9]+[[:space:]]+0x[0-9]+" "nfs/nfssvc.h" +gen_table "prio" "PRIO_[A-Z]+[[:space:]]+[0-9]" "sys/resource.h" +gen_table "procctlcmd" "PROC_[A-Z_]+[[:space:]]+[0-9]" "sys/procctl.h" "PROC_TRACE_CTL_" +gen_table "ptraceop" "PT_[[:alnum:]_]+[[:space:]]+[0-9]+" "sys/ptrace.h" +gen_table "quotactlcmds" "Q_[A-Z]+[[:space:]]+0x[0-9]+" "ufs/ufs/quota.h" +gen_table "rebootopt" "RB_[A-Z]+[[:space:]]+0x[0-9]+" "sys/reboot.h" +gen_table "rforkflags" "RF[A-Z]+[[:space:]]+\([0-9]+<<[0-9]+\)" "sys/unistd.h" +gen_table "rlimit" "RLIMIT_[A-Z]+[[:space:]]+[0-9]+" "sys/resource.h" +gen_table "schedpolicy" "SCHED_[A-Z]+[[:space:]]+[0-9]+" "sched.h" +gen_table "sendfileflags" "SF_[A-Z]+[[:space:]]+[0-9]+" "sys/socket.h" +gen_table "shmatflags" "SHM_[A-Z]+[[:space:]]+[0-9]{6}+" "sys/shm.h" +gen_table "shutdownhow" "SHUT_[A-Z]+[[:space:]]+[0-9]+" "sys/socket.h" +gen_table "sigbuscode" "BUS_[A-Z]+[[:space:]]+[0-9]+" "sys/signal.h" +gen_table "sigchldcode" "CLD_[A-Z]+[[:space:]]+[0-9]+" "sys/signal.h" +gen_table "sigfpecode" "FPE_[A-Z]+[[:space:]]+[0-9]+" "sys/signal.h" +gen_table "sigprocmaskhow" "SIG_[A-Z]+[[:space:]]+[0-9]+" "sys/signal.h" +gen_table "sigillcode" "ILL_[A-Z]+[[:space:]]+[0-9]+" "sys/signal.h" +gen_table "sigsegvcode" "SEGV_[A-Z]+[[:space:]]+[0-9]+" "sys/signal.h" +gen_table "sigtrapcode" "TRAP_[A-Z]+[[:space:]]+[0-9]+" "sys/signal.h" +gen_table "sockdomain" "PF_[[:alnum:]]+[[:space:]]+" "sys/socket.h" +gen_table "sockfamily" "AF_[[:alnum:]]+[[:space:]]+" "sys/socket.h" +gen_table "sockipproto" "IPPROTO_[[:alnum:]]+[[:space:]]+" "netinet/in.h" +gen_table "sockopt" "SO_[A-Z]+[[:space:]]+0x[0-9]+" "sys/socket.h" +gen_table "sockoptip" "(IP_[[:alnum:]_]+|MCAST_[[:alnum:]_]+_GROUP)[[:space:]]+" "netinet/in.h" "IP_DEFAULT|IP_MIN|IP_MAX|IP_PORTRANGE" +gen_table "sockopttcp" "TCP_[[:alnum:]_]+[[:space:]]+[0-9]+" "netinet/tcp.h" "TCP_MIN|TCP_MAX[^S]|TCP_MSS|TCP_[[:alnum:]_]+_MAX" +gen_table "sockoptudp" "UDP_[[:alnum:]]+[[:space:]]+[0-9]+" "netinet/udp.h" "UDP_ENCAP_" +gen_table "socktype" "SOCK_[A-Z]+[[:space:]]+[1-9]+[0-9]*" "sys/socket.h" +gen_table "thrcreateflags" "THR_[A-Z]+[[:space:]]+0x[0-9]+" "sys/thr.h" +gen_table "umtxop" "UMTX_OP_[[:alnum:]_]+[[:space:]]+[0-9]+" "sys/umtx.h" +gen_table "vmprot" "VM_PROT_[A-Z]+[[:space:]]+\(\(vm_prot_t\)\)" "vm/vm.h" +gen_table "vmresult" "KERN_[A-Z]+[[:space:]]+[0-9]+" "vm/vm_param.h" +gen_table "wait6opt" "W[A-Z]+[[:space:]]+[0-9]+" "sys/wait.h" +gen_table "seekwhence" "SEEK_[A-Z]+[[:space:]]+[0-9]+" "sys/unistd.h" +gen_table "fcntlcmd" "F_[A-Z0-9_]+[[:space:]]+[0-9]+[[:space:]]+" "sys/fcntl.h" "F_CANCEL|F_..LCK" +gen_table "mmapflags" "MAP_[A-Z_]+[[:space:]]+0x[0-9A-Fa-f]+" "sys/mman.h" +gen_table "rtpriofuncs" "RTP_[A-Z]+[[:space:]]+[0-9]+" "sys/rtprio.h" +gen_table "msgflags" "MSG_[A-Z]+[[:space:]]+0x[0-9]+" "sys/socket.h" "MSG_SOCALLBCK" +gen_table "sigcode" "SI_[A-Z]+[[:space:]]+0(x[0-9abcdef]+)?" "sys/signal.h" +gen_table "umtxcvwaitflags" "CVWAIT_[A-Z_]+[[:space:]]+0x[0-9]+" "sys/umtx.h" +gen_table "umtxrwlockflags" "URWLOCK_PREFER_READER[[:space:]]+0x[0-9]+" "sys/umtx.h" +gen_table "caprights" "CAP_[A-Z_]+[[:space:]]+CAPRIGHT\([0-9],[[:space:]]+0x[0-9]{16}ULL\)" "sys/capsicum.h" Property changes on: head/lib/libsysdecode/mktables ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/lib/libsysdecode/signal.c =================================================================== --- head/lib/libsysdecode/signal.c (nonexistent) +++ head/lib/libsysdecode/signal.c (revision 307538) @@ -0,0 +1,143 @@ +/*- + * Copyright (c) 2016 John H. Baldwin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include + +static const char *signames[] = { + [SIGHUP] = "SIGHUP", + [SIGINT] = "SIGINT", + [SIGQUIT] = "SIGQUIT", + [SIGILL] = "SIGILL", + [SIGTRAP] = "SIGTRAP", + [SIGABRT] = "SIGABRT", + [SIGEMT] = "SIGEMT", + [SIGFPE] = "SIGFPE", + [SIGKILL] = "SIGKILL", + [SIGBUS] = "SIGBUS", + [SIGSEGV] = "SIGSEGV", + [SIGSYS] = "SIGSYS", + [SIGPIPE] = "SIGPIPE", + [SIGALRM] = "SIGALRM", + [SIGTERM] = "SIGTERM", + [SIGURG] = "SIGURG", + [SIGSTOP] = "SIGSTOP", + [SIGTSTP] = "SIGTSTP", + [SIGCONT] = "SIGCONT", + [SIGCHLD] = "SIGCHLD", + [SIGTTIN] = "SIGTTIN", + [SIGTTOU] = "SIGTTOU", + [SIGIO] = "SIGIO", + [SIGXCPU] = "SIGXCPU", + [SIGXFSZ] = "SIGXFSZ", + [SIGVTALRM] = "SIGVTALRM", + [SIGPROF] = "SIGPROF", + [SIGWINCH] = "SIGWINCH", + [SIGINFO] = "SIGINFO", + [SIGUSR1] = "SIGUSR1", + [SIGUSR2] = "SIGUSR2", + [SIGTHR] = "SIGTHR", + [SIGLIBRT] = "SIGLIBRT", + + /* XXX: Solaris uses SIGRTMIN, SIGRTMIN+...SIGRTMAX-, SIGRTMAX */ + [SIGRTMIN] = "SIGRT0", + [SIGRTMIN + 1] = "SIGRT1", + [SIGRTMIN + 2] = "SIGRT2", + [SIGRTMIN + 3] = "SIGRT3", + [SIGRTMIN + 4] = "SIGRT4", + [SIGRTMIN + 5] = "SIGRT5", + [SIGRTMIN + 6] = "SIGRT6", + [SIGRTMIN + 7] = "SIGRT7", + [SIGRTMIN + 8] = "SIGRT8", + [SIGRTMIN + 9] = "SIGRT9", + [SIGRTMIN + 10] = "SIGRT10", + [SIGRTMIN + 11] = "SIGRT11", + [SIGRTMIN + 12] = "SIGRT12", + [SIGRTMIN + 13] = "SIGRT13", + [SIGRTMIN + 14] = "SIGRT14", + [SIGRTMIN + 15] = "SIGRT15", + [SIGRTMIN + 16] = "SIGRT16", + [SIGRTMIN + 17] = "SIGRT17", + [SIGRTMIN + 18] = "SIGRT18", + [SIGRTMIN + 19] = "SIGRT19", + [SIGRTMIN + 20] = "SIGRT20", + [SIGRTMIN + 21] = "SIGRT21", + [SIGRTMIN + 22] = "SIGRT22", + [SIGRTMIN + 23] = "SIGRT23", + [SIGRTMIN + 24] = "SIGRT24", + [SIGRTMIN + 25] = "SIGRT25", + [SIGRTMIN + 26] = "SIGRT26", + [SIGRTMIN + 27] = "SIGRT27", + [SIGRTMIN + 28] = "SIGRT28", + [SIGRTMIN + 29] = "SIGRT29", + [SIGRTMIN + 30] = "SIGRT30", + [SIGRTMIN + 31] = "SIGRT31", + [SIGRTMIN + 32] = "SIGRT32", + [SIGRTMIN + 33] = "SIGRT33", + [SIGRTMIN + 34] = "SIGRT34", + [SIGRTMIN + 35] = "SIGRT35", + [SIGRTMIN + 36] = "SIGRT36", + [SIGRTMIN + 37] = "SIGRT37", + [SIGRTMIN + 38] = "SIGRT38", + [SIGRTMIN + 39] = "SIGRT39", + [SIGRTMIN + 40] = "SIGRT40", + [SIGRTMIN + 41] = "SIGRT41", + [SIGRTMIN + 42] = "SIGRT42", + [SIGRTMIN + 43] = "SIGRT43", + [SIGRTMIN + 44] = "SIGRT44", + [SIGRTMIN + 45] = "SIGRT45", + [SIGRTMIN + 46] = "SIGRT46", + [SIGRTMIN + 47] = "SIGRT47", + [SIGRTMIN + 48] = "SIGRT48", + [SIGRTMIN + 49] = "SIGRT49", + [SIGRTMIN + 50] = "SIGRT50", + [SIGRTMIN + 51] = "SIGRT51", + [SIGRTMIN + 52] = "SIGRT52", + [SIGRTMIN + 53] = "SIGRT53", + [SIGRTMIN + 54] = "SIGRT54", + [SIGRTMIN + 55] = "SIGRT55", + [SIGRTMIN + 56] = "SIGRT56", + [SIGRTMIN + 57] = "SIGRT57", + [SIGRTMIN + 58] = "SIGRT58", + [SIGRTMIN + 59] = "SIGRT59", + [SIGRTMIN + 60] = "SIGRT60", + [SIGRTMIN + 61] = "SIGRT61", +}; + +const char * +sysdecode_signal(int sig) +{ + + if ((unsigned)sig < nitems(signames)) + return (signames[sig]); + return (NULL); +} Property changes on: head/lib/libsysdecode/signal.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/lib/libsysdecode/syscallnames.c =================================================================== --- head/lib/libsysdecode/syscallnames.c (revision 307537) +++ head/lib/libsysdecode/syscallnames.c (revision 307538) @@ -1,105 +1,108 @@ /*- * Copyright (c) 2015 John H. Baldwin * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * Map system call codes to names for the supported ABIs on each * platform. Rather than regnerating system call name tables locally * during the build, use the generated tables in the kernel source * tree. */ #include +#include +#include +#include #include #include static #include #if defined(__amd64__) || defined(__powerpc64__) static #include #endif #if defined(__amd64__) || defined(__i386__) static #ifdef __amd64__ #include #else #include #endif #endif #ifdef __amd64__ static #include #endif #if defined(__amd64__) || defined(__aarch64__) static #include #endif const char * sysdecode_syscallname(enum sysdecode_abi abi, unsigned int code) { switch (abi) { case SYSDECODE_ABI_FREEBSD: if (code < nitems(syscallnames)) return (syscallnames[code]); break; #if defined(__amd64__) || defined(__powerpc64__) case SYSDECODE_ABI_FREEBSD32: if (code < nitems(freebsd32_syscallnames)) return (freebsd32_syscallnames[code]); break; #endif #if defined(__amd64__) || defined(__i386__) case SYSDECODE_ABI_LINUX: if (code < nitems(linux_syscallnames)) return (linux_syscallnames[code]); break; #endif #ifdef __amd64__ case SYSDECODE_ABI_LINUX32: if (code < nitems(linux32_syscallnames)) return (linux32_syscallnames[code]); break; #endif #if defined(__amd64__) || defined(__aarch64__) case SYSDECODE_ABI_CLOUDABI64: if (code < nitems(cloudabi64_syscallnames)) return (cloudabi64_syscallnames[code]); break; #endif default: break; } return (NULL); } Index: head/lib/libsysdecode/sysdecode.3 =================================================================== --- head/lib/libsysdecode/sysdecode.3 (revision 307537) +++ head/lib/libsysdecode/sysdecode.3 (revision 307538) @@ -1,75 +1,86 @@ .\" .\" Copyright (c) 2015 John Baldwin .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" $FreeBSD$ .\" -.Dd January 29, 2016 +.Dd October 17, 2016 .Dt SYSDECODE 3 .Os .Sh NAME .Nm sysdecode .Nd system argument decoding library .Sh LIBRARY .Lb libsysdecode +.Sh SYNOPSIS +.In sys/types.h +.In stdbool.h +.In sysdecode.h .Sh DESCRIPTION The .Nm library includes several functions that provide descriptive names of values associated with system calls. .Ss Supported ABIs Some functions in this library provide ABI-specific descriptions. The supported ABIs are named by the .Vt enum sysdecode_abi enumeration. .Pp .Bl -tag -width "Li SYSDECODE_ABI_CLOUDABI64" -compact .It Li SYSDECODE_ABI_FREEBSD Native FreeBSD binaries. Supported on all platforms. .It Li SYSDECODE_ABI_FREEBSD32 32-bit FreeBSD binaries. Supported on amd64 and powerpc64. .It Li SYSDECODE_ABI_LINUX Linux binaries of the same platform. Supported on amd64 and i386. .It Li SYSDECODE_ABI_LINUX32 32-bit Linux binaries. Supported on amd64. .It Li SYSDECODE_ABI_CLOUDABI64 64-bit CloudABI binaries. Supported on aarch64 and amd64. .It Li SYSDECODE_ABI_UNKNOWN A placeholder for use when the ABI is not known. .El .Sh SEE ALSO .Xr sysdecode_abi_to_freebsd_errno 3 , +.Xr sysdecode_cap_rights 3 , +.Xr sysdecode_enum 3 , +.Xr sysdecode_fcntl_arg 3 , .Xr sysdecode_ioctlname 3 , +.Xr sysdecode_mask 3 , +.Xr sysdecode_quotactl_cmd 3 , +.Xr sysdecode_sigcode 3 , +.Xr sysdecode_sockopt_name 3 , .Xr sysdecode_syscallnames 3 , .Xr sysdecode_utrace 3 .Sh HISTORY The .Nm library first appeared in .Fx 11.0 . Index: head/lib/libsysdecode/sysdecode.h =================================================================== --- head/lib/libsysdecode/sysdecode.h (revision 307537) +++ head/lib/libsysdecode/sysdecode.h (revision 307538) @@ -1,47 +1,117 @@ /*- * Copyright (c) 2015 John H. Baldwin * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef __SYSDECODE_H__ #define __SYSDECODE_H__ enum sysdecode_abi { SYSDECODE_ABI_UNKNOWN = 0, SYSDECODE_ABI_FREEBSD, SYSDECODE_ABI_FREEBSD32, SYSDECODE_ABI_LINUX, SYSDECODE_ABI_LINUX32, SYSDECODE_ABI_CLOUDABI64 }; int sysdecode_abi_to_freebsd_errno(enum sysdecode_abi _abi, int _error); +bool sysdecode_access_mode(FILE *_fp, int _mode, int *_rem); +const char *sysdecode_acltype(int _type); +const char *sysdecode_atfd(int _fd); +bool sysdecode_cap_fcntlrights(FILE *_fp, uint32_t _rights, uint32_t *_rem); +void sysdecode_cap_rights(FILE *_fp, cap_rights_t *_rightsp); +const char *sysdecode_extattrnamespace(int _namespace); +const char *sysdecode_fadvice(int _advice); +void sysdecode_fcntl_arg(FILE *_fp, int _cmd, uintptr_t _arg, int _base); +bool sysdecode_fcntl_arg_p(int _cmd); +const char *sysdecode_fcntl_cmd(int _cmd); +bool sysdecode_fcntl_fileflags(FILE *_fp, int _flags, int *_rem); +bool sysdecode_fileflags(FILE *_fp, fflags_t _flags, fflags_t *_rem); +bool sysdecode_filemode(FILE *_fp, int _mode, int *_rem); +bool sysdecode_flock_operation(FILE *_fp, int _operation, int *_rem); int sysdecode_freebsd_to_abi_errno(enum sysdecode_abi _abi, int _error); +bool sysdecode_getfsstat_flags(FILE *_fp, int _flags, int *_rem); +const char *sysdecode_idtype(int _idtype); const char *sysdecode_ioctlname(unsigned long _val); +const char *sysdecode_ipproto(int _protocol); +const char *sysdecode_kldsym_cmd(int _cmd); +const char *sysdecode_kldunload_flags(int _flags); +const char *sysdecode_lio_listio_mode(int _mode); +const char *sysdecode_madvice(int _advice); +const char *sysdecode_minherit_inherit(int _inherit); +const char *sysdecode_msgctl_cmd(int _cmd); +bool sysdecode_mlockall_flags(FILE *_fp, int _flags, int *_rem); +bool sysdecode_mmap_flags(FILE *_fp, int _flags, int *_rem); +bool sysdecode_mmap_prot(FILE *_fp, int _prot, int *_rem); +bool sysdecode_mount_flags(FILE *_fp, int _flags, int *_rem); +bool sysdecode_msg_flags(FILE *_fp, int _flags, int *_rem); +bool sysdecode_msync_flags(FILE *_fp, int _flags, int *_rem); +const char *sysdecode_nfssvc_flags(int _flags); +bool sysdecode_open_flags(FILE *_fp, int _flags, int *_rem); +bool sysdecode_pipe2_flags(FILE *_fp, int _flags, int *_rem); +const char *sysdecode_prio_which(int _which); +const char *sysdecode_procctl_cmd(int _cmd); +const char *sysdecode_ptrace_request(int _request); +bool sysdecode_quotactl_cmd(FILE *_fp, int _cmd); +bool sysdecode_reboot_howto(FILE *_fp, int _howto, int *_rem); +bool sysdecode_rfork_flags(FILE *_fp, int _flags, int *_rem); +const char *sysdecode_rlimit(int _resource); +const char *sysdecode_rtprio_function(int _function); +const char *sysdecode_scheduler_policy(int _policy); +const char *sysdecode_semctl_cmd(int _cmd); +bool sysdecode_semget_flags(FILE *_fp, int _flag, int *_rem); +bool sysdecode_sendfile_flags(FILE *_fp, int _flags, int *_rem); +bool sysdecode_shmat_flags(FILE *_fp, int _flags, int *_rem); +const char *sysdecode_shmctl_cmd(int _cmd); +const char *sysdecode_shutdown_how(int _how); +const char *sysdecode_sigbus_code(int _si_code); +const char *sysdecode_sigchld_code(int _si_code); +const char *sysdecode_sigcode(int _sig, int _si_code); +const char *sysdecode_sigfpe_code(int _si_code); +const char *sysdecode_sigill_code(int _si_code); +const char *sysdecode_signal(int _sig); +const char *sysdecode_sigprocmask_how(int _how); +const char *sysdecode_sigsegv_code(int _si_code); +const char *sysdecode_sigtrap_code(int _si_code); +const char *sysdecode_sockaddr_family(int _sa_family); +const char *sysdecode_socketdomain(int _domain); +bool sysdecode_socket_type(FILE *_fp, int _type, int *_rem); +const char *sysdecode_sockopt_level(int _level); +const char *sysdecode_sockopt_name(int _level, int _optname); const char *sysdecode_syscallname(enum sysdecode_abi _abi, unsigned int _code); +bool sysdecode_thr_create_flags(FILE *_fp, int _flags, int *_rem); +bool sysdecode_umtx_cvwait_flags(FILE *_fp, u_long _flags, u_long *_rem); +const char *sysdecode_umtx_op(int _op); +bool sysdecode_umtx_rwlock_flags(FILE *_fp, u_long _flags, u_long *_rem); int sysdecode_utrace(FILE *_fp, void *_buf, size_t _len); +bool sysdecode_vmprot(FILE *_fp, int _type, int *_rem); +const char *sysdecode_vmresult(int _result); +bool sysdecode_wait4_options(FILE *_fp, int _options, int *_rem); +bool sysdecode_wait6_options(FILE *_fp, int _options, int *_rem); +const char *sysdecode_whence(int _whence); #endif /* !__SYSDECODE_H__ */ Index: head/lib/libsysdecode/sysdecode_abi_to_freebsd_errno.3 =================================================================== --- head/lib/libsysdecode/sysdecode_abi_to_freebsd_errno.3 (revision 307537) +++ head/lib/libsysdecode/sysdecode_abi_to_freebsd_errno.3 (revision 307538) @@ -1,94 +1,97 @@ .\" .\" Copyright (c) 2016 John Baldwin .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" $FreeBSD$ .\" -.Dd February 23, 2016 +.Dd October 17, 2016 .Dt sysdecode_abi_to_freebsd_errno 3 .Os .Sh NAME .Nm sysdecode_abi_to_freebsd_errno , .Nm sysdecode_freebsd_to_abi_errno .Nd translate error numbers between process ABIs .Sh LIBRARY .Lb libsysdecode .Sh SYNOPSIS +.In sys/types.h +.In stdbool.h +.In sysdecode.h .Ft int .Fn sysdecode_abi_to_freebsd_errno "enum sysdecode_abi abi" "int error" .Ft int .Fn sysdecode_freebsd_to_abi_errno "enum sysdecode_abi abi" "int error" .Sh DESCRIPTION The .Fn sysdecode_abi_to_freebsd_errno function returns the native .Xr errno 2 value that corresponds to the error indicated by .Fa error for the process ABI .Fa abi . If .Fa error does not identify a valid error for .Fa abi , .Dv INT_MAX is returned. .Pp The .Fn sysdecode_freebsd_to_abi_errno function the error value for the process ABI .Fa abi that corresponds to the native .Xr errno 2 value .Fa error . If .Fa error does not identify a valid .Xr errno 2 error, .Dv INT_MAX is returned. .Pp Note that the mappings between native .Xr errno 2 values and errors for other ABIs are not exhaustive. If a mapping does not exist, these functions return .Dv INT_MAX . In addition, multiple error values in one ABI may map to a single error in another ABI. .Sh RETURN VALUES These functions return an error value on success or .Dv INT_MAX if .Fa error is not valid. .Pp For the list of supported ABIs, see .Xr sysdecode 3 . .Sh SEE ALSO .Xr sysdecode 3 , .Xr sysdecode_syscallnames 3 Index: head/lib/libsysdecode/sysdecode_cap_rights.3 =================================================================== --- head/lib/libsysdecode/sysdecode_cap_rights.3 (nonexistent) +++ head/lib/libsysdecode/sysdecode_cap_rights.3 (revision 307538) @@ -0,0 +1,50 @@ +.\" +.\" Copyright (c) 2016 John Baldwin +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd October 17, 2016 +.Dt sysdecode_cap_rights 3 +.Os +.Sh NAME +.Nm sysdecode_cap_rights +.Nd output list of capability rights +.Sh LIBRARY +.Lb libsysdecode +.Sh SYNOPSIS +.In sys/types.h +.In stdbool.h +.In sysdecode.h +.Ft void +.Fn sysdecode_cap_rights "FILE *fp" "cap_rights_t *rightsp" +.Sh DESCRIPTION +The +.Fn sysdecode_cap_rights +function outputs a comma-separated list of capability rights at +.Fa rightsp +to the stream +.Fa fp . +.Sh SEE ALSO +.Xr sysdecode 3 Property changes on: head/lib/libsysdecode/sysdecode_cap_rights.3 ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/lib/libsysdecode/sysdecode_enum.3 =================================================================== --- head/lib/libsysdecode/sysdecode_enum.3 (nonexistent) +++ head/lib/libsysdecode/sysdecode_enum.3 (revision 307538) @@ -0,0 +1,235 @@ +.\" +.\" Copyright (c) 2016 John Baldwin +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd October 17, 2016 +.Dt sysdecode_enum 3 +.Os +.Sh NAME +.Nm sysdecode_enum , +.Nm sysdecode_acltype , +.Nm sysdecode_atfd , +.Nm sysdecode_extattrnamespace , +.Nm sysdecode_fadvice , +.Nm sysdecode_fcntl_cmd , +.Nm sysdecode_idtype , +.Nm sysdecode_ipproto , +.Nm sysdecode_kldsym_cmd , +.Nm sysdecode_kldunload_flags , +.Nm sysdecode_lio_listio_mode , +.Nm sysdecode_madvice , +.Nm sysdecode_minherit_flags , +.Nm sysdecode_msgctl_cmd , +.Nm sysdecode_nfssvc_flags , +.Nm sysdecode_prio_which , +.Nm sysdecode_procctl_cmd , +.Nm sysdecode_ptrace_request , +.Nm sysdecode_rlimit , +.Nm sysdecode_rtprio_function , +.Nm sysdecode_scheduler_policy , +.Nm sysdecode_semctl_cmd , +.Nm sysdecode_shmctl_cmd , +.Nm sysdecode_shutdown_how , +.Nm sysdecode_sigbus_code , +.Nm sysdecode_sigchld_code , +.Nm sysdecode_sigfpe_code , +.Nm sysdecode_sigill_code , +.Nm sysdecode_signal , +.Nm sysdecode_sigprocmask_how , +.Nm sysdecode_sigsegv_code , +.Nm sysdecode_sigtrap_code , +.Nm sysdecode_sockaddr_family , +.Nm sysdecode_socketdomain , +.Nm sysdecode_sockettype , +.Nm sysdecode_sockopt_level , +.Nm sysdecode_umtx_op , +.Nm sysdecode_vmresult , +.Nm sysdecode_whence +.Nd lookup name of various enumerated values +.Sh LIBRARY +.Lb libsysdecode +.Sh SYNOPSIS +.In sys/types.h +.In stdbool.h +.In sysdecode.h +.Ft const char * +.Fn sysdecode_acltype "int type" +.Ft const char * +.Fn sysdecode_atfd "int fd" +.Ft const char * +.Fn sysdecode_extattrnamespace "int namespace" +.Ft const char * +.Fn sysdecode_fadvice "int advice" +.Ft const char * +.Fn sysdecode_fcntl_cmd "int cmd" +.Ft const char * +.Fn sysdecode_idtype "int idtype" +.Ft const char * +.Fn sysdecode_ipproto "int protocol" +.Ft const char * +.Fn sysdecode_kldsym_cmd "int cmd" +.Ft const char * +.Fn sysdecode_kldunload_flags "int flags" +.Ft const char * +.Fn sysdecode_lio_listio_mode "int mode" +.Ft const char * +.Fn sysdecode_madvice "int advice" +.Ft const char * +.Fn sysdecode_minherit_flags "int inherit" +.Ft const char * +.Fn sysdecode_msgctl_cmd "int cmd" +.Ft const char * +.Fn sysdecode_nfssvc_flags "int flags" +.Ft const char * +.Fn sysdecode_prio_which "int which" +.Ft const char * +.Fn sysdecode_procctl_cmd "int cmd" +.Ft const char * +.Fn sysdecode_ptrace_request "int request" +.Ft const char * +.Fn sysdecode_rlimit "int resource" +.Ft const char * +.Fn sysdecode_rtprio_function "int function" +.Ft const char * +.Fn sysdecode_scheduler_policy "int policy" +.Ft const char * +.Fn sysdecode_semctl_cmd "int cmd" +.Ft const char * +.Fn sysdecode_shmctl_cmd "int cmd" +.Ft const char * +.Fn sysdecode_shutdown_how "int how" +.Ft const char * +.Fn sysdecode_sigbus_code "int si_code" +.Ft const char * +.Fn sysdecode_sigchld_code "int si_code" +.Ft const char * +.Fn sysdecode_sigfpe_code "int si_code" +.Ft const char * +.Fn sysdecode_sigill_code "int si_code" +.Ft const char * +.Fn sysdecode_signal "int sig" +.Ft const char * +.Fn sysdecode_sigprocmask_how "int how" +.Ft const char * +.Fn sysdecode_sigsegv_code "int si_code" +.Ft const char * +.Fn sysdecode_sigtrap_code "int si_code" +.Ft const char * +.Fn sysdecode_sockaddr_family "int sa_family" +.Ft const char * +.Fn sysdecode_socketdomain "int domain" +.Ft const char * +.Fn sysdecode_sockettype "int type" +.Ft const char * +.Fn sysdecode_sockopt_level "int level" +.Ft const char * +.Fn sysdecode_umtx_op "int op" +.Ft const char * +.Fn sysdecode_vmresult "int result" +.Ft const char * +.Fn sysdecode_whence "int whence" +.Sh DESCRIPTION +The +.Nm +functions return a text description of an integer value. +The text description matches the name of a C macro with the same value as the +sole function argument. +.Dv NULL +is returned if there is no matching C macro name. +.Pp +Most of these functions decode an argument passed to a system call: +.Bl -column "Fn sysdecode_extattrnamespace" "Xr sched_setscheduler 2" +.It Sy Function Ta Sy System Call Ta Sy Argument +.It Fn sysdecode_acltype Ta Xr acl_get_file 3 Ta Fa type +.It Fn sysdecode_atfd Ta Xr openat 2 Ta Fa fd +.It Fn sysdecode_extattrnamespace Ta Xr extattr_get_fd 2 Ta Fa attrnamespace +.It Fn sysdecode_fadvice Ta Xr posix_fadvise 2 Ta Fa advice +.It Fn sysdecode_fcntl_cmd Ta Xr fcntl 2 Ta Fa cmd +.It Fn sysdecode_idtype Ta +.Xr procctl 2 , +.Xr waitid 2 +.Ta Fa idtype +.It Fn sysdecode_kldsym_cmd Ta Xr kldsym 2 Ta Fa cmd +.It Fn sysdecode_kldunload_flags Ta Xr kldunloadf 2 Ta Fa flags +.It Fn sysdecode_lio_listio_mode Ta Xr lio_listio 2 Ta Fa mode +.It Fn sysdecode_madvice Ta Xr madvise 2 Ta Fa advice +.It Fn sysdecode_minherit_inherit Ta Xr minherit 2 Ta Fa inherit +.It Fn sysdecode_msgctl_cmd Ta Xr msgctl 2 Ta Fa cmd +.It Fn sysdecode_nfssvc_flags Ta Xr nfssvc 2 Ta Fa flags +.It Fn sysdecode_prio_which Ta Xr getpriority 2 Ta Fa which +.It Fn sysdecode_procctl_cmd Ta Xr procctl 2 Ta Fa cmd +.It Fn sysdecode_ptrace_request Ta Xr ptrace 2 Ta Fa request +.It Fn sysdecode_rlimit Ta Xr getrlimit 2 Ta Fa resource +.It Fn sysdecode_rtprio_function Ta Xr rtprio 2 Ta Fa function +.It Fn sysdecode_scheduler_policy Ta Xr sched_setscheduler 2 Ta Fa policy +.It Fn sysdecode_semctl_cmd Ta Xr semctl 2 Ta Fa cmd +.It Fn sysdecode_shmctl_cmd Ta Xr shmctl 2 Ta Fa cmd +.It Fn sysdecode_shutdown_how Ta Xr shutdown 2 Ta Fa how +.It Fn sysdecode_sigprocmask_how Ta Xr sigprocmask 2 Ta Fa how +.It Fn sysdecode_sockopt_level Ta Xr getsockopt 2 Ta Fa level +.It Fn sysdecode_umtx_op Ta Xr _umtx_op 2 Ta Fa op +.It Fn sysdecode_whence Ta Xr lseek 2 Ta Fa whence +.El +.Pp +These functions decode signal-specific signal codes stored in the +.Fa si_code +field of the +.Vt siginfo_t +object associated with an instance of signal: +.Bl -column "Fn sysdecode_sigchld_code" +.It Sy Function Ta Sy Signal +.It Fn sysdecode_sigbus_code Ta Dv SIGBUS +.It Fn sysdecode_sigchld_code Ta Dv SIGCHLD +.It Fn sysdecode_sigfpe_code Ta Dv SIGFPE +.It Fn sysdecode_sigill_code Ta Dv SIGILL +.It Fn sysdecode_sigsegv_code Ta Dv SIGSEGV +.It Fn sysdecode_sigtrap_code Ta Dv SIGBTRAP +.El +.Pp +Other functions decode the values described below: +.Bl -tag -width "Fn sysdecode_sockaddr_family" +.It Fn sysdecode_ipproto +An IP protocol. +.It Fn sysdecode_signal +A process signal. +.It Fn sysdecode_sockaddr_family +A socket address family. +.It Fn sysdecode_socketdomain +A socket domain. +.It Fn sysdecode_vmresult +The return value of a function in the virtual memory subsystem of the kernel +indicating the status of the associated request. +.El +.Sh RETURN VALUES +The +.Nm +functions return the name of a matching C macro or +.Dv NULL +if no matching C macro was found. +.Sh SEE ALSO +.Xr sysdecode 3 , +.Xr sysdecode_mask 3 , +.Xr sysdecode_sigcode 3 Property changes on: head/lib/libsysdecode/sysdecode_enum.3 ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/lib/libsysdecode/sysdecode_fcntl_arg.3 =================================================================== --- head/lib/libsysdecode/sysdecode_fcntl_arg.3 (nonexistent) +++ head/lib/libsysdecode/sysdecode_fcntl_arg.3 (revision 307538) @@ -0,0 +1,121 @@ +.\" +.\" Copyright (c) 2016 John Baldwin +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd October 17, 2016 +.Dt sysdecode_fcntl_arg 3 +.Os +.Sh NAME +.Nm sysdecode_fcntl_arg , +.Nm sysdecode_fcntl_arg_p +.Nd output description of fcntl argument +.Sh LIBRARY +.Lb libsysdecode +.Sh SYNOPSIS +.In sys/types.h +.In stdbool.h +.In sysdecode.h +.Ft void +.Fn sysdecode_fcntl_arg "FILE *fp" "int cmd" "uintptr_t arg" "int base" +.Ft bool +.Fn sysdecode_fcntl_arg_p "int cmd" +.Sh DESCRIPTION +The +.Fn sysdecode_fcntl_arg +function outputs a text description of the optional +.Fa arg +argument to +.Xr fcntl 2 +to the stream +.Fa fp . +The type and format of +.Fa arg +are determined by +.Fa cmd : +.Bl -column ".Dv F_SETLKW" "Vt struct flock *" +.It Sy Command Ta Fa arg Sy Type Ta Sy Output Format +.It +.It Dv F_SETFD Ta Vt int Ta +.Dq FD_CLOEXEC +or the value of +.Fa arg +in the indicated +.Fa base +.Pq one of 8, 10, or 16 . +.It +.It Dv F_SETFL Ta Vt int Ta +File flags as output by +.Xr sysdecode_fcntl_fileflags 3 +with any unknown or remaining bits output in hexadecimal. +.It +.It Dv F_GETLK Ta Vt struct flock * Ta +.It Dv F_SETLK Ta Vt struct flock * Ta +.It Dv F_SETLKW Ta Vt struct flock * Ta +The value of +.Fa arg +using the +.Dq %p +conversion specification. +.It +.It Others Ta Vt int Ta +The value of +.Fa arg +in the indicated +.Fa base +.Pq one of 8, 10, or 16 . +.El +.Pp +The +.Fn sysdecode_fcntl_arg_p +function can be used to determine if a +.Xr fcntl 2 +command uses the optional third argument to +.Xr fcntl 2 . +The function returns +.Dv true +if +.Fa cmd +accepts a third argument to +.Xr fcntl 2 +and +.Dv false +if it does not. +.Sh RETURN VALUES +The +.Nm sysdecode_fcntl_arg_p +function returns +.Dv true +if +.Fa cmd +accepts a third argument to +.Xr fcntl 2 +and +.Dv false +if it does not. +.Sh SEE ALSO +.Xr sysdecode 3 , +.Xr sysdecode_fcntl_cmd 3 , +.Xr sysdecode_fcntl_fileflags 3 Property changes on: head/lib/libsysdecode/sysdecode_fcntl_arg.3 ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/lib/libsysdecode/sysdecode_ioctlname.3 =================================================================== --- head/lib/libsysdecode/sysdecode_ioctlname.3 (revision 307537) +++ head/lib/libsysdecode/sysdecode_ioctlname.3 (revision 307538) @@ -1,57 +1,60 @@ .\" .\" Copyright (c) 2015 John Baldwin .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" $FreeBSD$ .\" -.Dd December 12, 2015 +.Dd October 17, 2016 .Dt sysdecode_ioctlname 3 .Os .Sh NAME .Nm sysdecode_ioctlname .Nd lookup name of device control command .Sh LIBRARY .Lb libsysdecode .Sh SYNOPSIS +.In sys/types.h +.In stdbool.h +.In sysdecode.h .Ft conts char * .Fn sysdecode_ioctlname "unsigned long request" .Sh DESCRIPTION The .Fn sysdecode_ioctlname function returns the name of a device control request identified by .Fa request . A table of names is generated during the build of the .Nm sysdecode library from system headers that maps device control request values to the name of the corresponding C macro. .Sh RETURN VALUES The .Fn sysdecode_ioctlname function returns the name of a device control request if .Fa request is a known value; otherwise .Dv NULL . .Sh SEE ALSO .Xr sysdecode 3 Index: head/lib/libsysdecode/sysdecode_mask.3 =================================================================== --- head/lib/libsysdecode/sysdecode_mask.3 (nonexistent) +++ head/lib/libsysdecode/sysdecode_mask.3 (revision 307538) @@ -0,0 +1,216 @@ +.\" +.\" Copyright (c) 2016 John Baldwin +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd October 17, 2016 +.Dt sysdecode_mask 3 +.Os +.Sh NAME +.Nm sysdecode_mask , +.Nm sysdecode_accessmode , +.Nm sysdecode_capfcntlrights , +.Nm sysdecode_fcntl_fileflags , +.Nm sysdecode_fileflags , +.Nm sysdecode_filemode , +.Nm sysdecode_flock_operation , +.Nm sysdecode_getfsstat_flags , +.Nm sysdecode_mlockall_flags , +.Nm sysdecode_mmap_flags , +.Nm sysdecode_mmap_prot , +.Nm sysdecode_mount_flags , +.Nm sysdecode_msg_flags , +.Nm sysdecode_msync_flags , +.Nm sysdecode_open_flags , +.Nm sysdecode_pipe2_flags , +.Nm sysdecode_reboot_howto , +.Nm sysdecode_rfork_flags , +.Nm sysdecode_semget_flags , +.Nm sysdecode_sendfile_flags , +.Nm sysdecode_shmat_flags , +.Nm sysdecode_socket_type , +.Nm sysdecode_thr_create_flags , +.Nm sysdecode_umtx_cvwait_flags , +.Nm sysdecode_umtx_rwlock_flags , +.Nm sysdecode_vmprot , +.Nm sysdecode_wait4_options , +.Nm sysdecode_wait6_options +.Nd print name of various bitmask values +.Sh LIBRARY +.Lb libsysdecode +.Sh SYNOPSIS +.In sys/types.h +.In stdbool.h +.In sysdecode.h +.Ft bool +.Fn sysdecode_access_mode "FILE *fp" "int mode" "int *rem" +.Ft bool +.Fn sysdecode_cap_fcntlrights "FILE *fp" "uint32_t rights" "uint32_t *rem" +.Ft bool +.Fn sysdecode_fcntl_fileflags "FILE *fp" "int flags" "int *rem" +.Ft bool +.Fn sysdecode_fileflags "FILE *fp" "fflags_t flags" "fflags_t *rem" +.Ft bool +.Fn sysdecode_filemode "FILE *fp" "int mode" "int *rem" +.Ft bool +.Fn sysdecode_flock_operation "FILE *fp" "int operation" "int *rem" +.Ft bool +.Fn sysdecode_mlockall_flags "FILE *fp" "int flags" "int *rem" +.Ft bool +.Fn sysdecode_mmap_flags "FILE *fp" "int flags" "int *rem" +.Ft bool +.Fn sysdecode_mmap_prot "FILE *fp" "int prot" "int *rem" +.Ft bool +.Fn sysdecode_mount_flags "FILE *fp" "int flags" "int *rem" +.Ft bool +.Fn sysdecode_msg_flags "FILE *fp" "int flags" "int *rem" +.Ft bool +.Fn sysdecode_msync_flags "FILE *fp" "int flags" "int *rem" +.Ft bool +.Fn sysdecode_open_flags "FILE *fp" "int flags" "int *rem" +.Ft bool +.Fn sysdecode_pipe2_flags "FILE *fp" "int flags" "int *rem" +.Ft bool +.Fn sysdecode_reboot_howto "FILE *fp" "int howto" "int *rem" +.Ft bool +.Fn sysdecode_rfork_flags "FILE *fp" "int flags" "int *rem" +.Ft bool +.Fn sysdecode_semget_flags "FILE *fp" "int flags" "int *rem" +.Ft bool +.Fn sysdecode_sendfile_flags "FILE *fp" "int flags" "int *rem" +.Ft bool +.Fn sysdecode_shmat_flags "FILE *fp" "int flags" "int *rem" +.Ft bool +.Fn sysdecode_socket_type "FILE *fp" "int type" "int *rem" +.Ft bool +.Fn sysdecode_thr_create_flags "FILE *fp" "int flags" "int *rem" +.Ft bool +.Fn sysdecode_umtx_cvwait_flags "FILE *fp" "u_long flags" "u_long *rem" +.Ft bool +.Fn sysdecode_umtx_rwlock_flags "FILE *fp" "u_long flags" "u_long *rem" +.Ft bool +.Fn sysdecode_vmprot "FILE *fp" "int type" "int *rem" +.Ft bool +.Fn sysdecode_wait4_options "FILE *fp" "int options" "int *rem" +.Ft bool +.Fn sysdecode_wait6_options "FILE *fp" "int options" "int *rem" +.Sh DESCRIPTION +The +.Nm +functions are used to generate a text description of an integer value +built from a mask of bitfields. +The text description lists the C macros for field values joined by pipe +.Sq | +characters matching the format used in C source code. +Most of the values decoded by these functions are passed as arguments to +system calls, +though some of these values are used internally in the kernel. +.Pp +Each function writes the text description to +.Fa fp . +The second argument should contain the integer value to be decoded. +The +.Fa rem +argument is set to the value of any bits that were not decoded +.Pq bit fields that do not have a corresponding C macro . +.Fa rem +may be set to +.Dv NULL +if the caller does not need this value. +Each function returns +.Dv true +if any bit fields in the value were decoded and +.Dv false +if no bit fields were decoded. +.Pp +Most of these functions decode an argument passed to a system call: +.Bl -column "Fn sysdecode_flock_operation" "Xr cap_fcntls_limit 2" +.It Sy Function Ta Sy System Call Ta Sy Argument +.It Fn sysdecode_access_mode Ta Xr access 2 Ta Fa mode +.It Fn sysdecode_cap_fcntlrights Ta Xr cap_fcntls_limit 2 Ta Fa fcntlrights +.It Fn sysdecode_fileflags Ta Xr chflags 2 Ta Fa flags +.It Fn sysdecode_filemode Ta Xr chmod 2 , Xr open 2 Ta mode +.It Fn sysdecode_flock_operation Ta Xr flock 2 Ta Fa operation +.It Fn sysdecode_getfsstat_flags Ta Xr getfsstatflags 2 Ta Fa flags +.It Fn sysdecode_mlockall_flags Ta Xr mlockall 2 Ta Fa flags +.It Fn sysdecode_mmap_flags Ta Xr mmap 2 Ta Fa flags +.It Fn sysdecode_mmap_prot Ta Xr mmap 2 Ta Fa prot +.It Fn sysdecode_mount_flags Ta Xr mount 2 Ta Fa flags +.It Fn sysdecode_msg_flags Ta Xr recv 2 , Xr send 2 Ta Fa flags +.It Fn sysdecode_msync_flags Ta Xr msync 2 Ta Fa flags +.It Fn sysdecode_open_flags Ta Xr open 2 Ta Fa flags +.It Fn sysdecode_pipe2_flags Ta Xr pipe2 Ta Fa flags +.It Fn sysdecode_reboot_howto Ta Xr reboot 2 Ta Fa howto +.It Fn sysdecode_rfork_flags Ta Xr rfork 2 Ta Fa flags +.It Fn sysdecode_semget_flags Ta Xr semget 2 Ta Fa flags +.It Fn sysdecode_sendfile_flags Ta Xr sendfile 2 Ta Fa flags +.It Fn sysdecode_shmat_flags Ta Xr shmat 2 Ta Fa flags +.It Fn sysdecode_socket_type Ta Xr socket 2 Ta Fa type +.It Fn sysdecode_thr_create_flags Ta Xr thr_create 2 Ta Fa flags +.It Fn sysdecode_wait4_options Ta Xr wait4 2 Ta Fa options +.It Fn sysdecode_wait6_options Ta Xr wait6 2 Ta Fa options +.El +.Pp +Other functions decode the values described below: +.Bl -tag -width ".Fn sysdecode_umtx_cvwait_flags" +.It Fn sysdecode_fcntl_fileflags +The file flags used with the +.Dv F_GETFL +and +.Dv F_SETFL +.Xr fcntl 2 +commands. +.It Fn sysdecode_umtx_cvwait_flags +The +.Fa val +argument to +.Xr _umtx_op 2 +for +.Dv UMTX_OP_CV_WAIT +operations. +.It Fn sysdecode_umtx_rwlock_flags +The +.Fa val +argument to +.Xr _umtx_op 2 +for +.Dv UMTX_OP_RW_RDLOCK +operations. +.It Fn sysdecode_vmprot +The memory protection flags stored in +.Vt vm_prot_t +variables. +.El +.Sh RETURN VALUES +The +.Nm +functions return +.Dv true +if any bit fields in the value were decoded and +.Dv false +if no bit fields were decoded. +.Sh SEE ALSO +.Xr sysdecode 3 , +.Xr sysdecode_enum 3 Property changes on: head/lib/libsysdecode/sysdecode_mask.3 ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/lib/libsysdecode/sysdecode_quotactl_cmd.3 =================================================================== --- head/lib/libsysdecode/sysdecode_quotactl_cmd.3 (nonexistent) +++ head/lib/libsysdecode/sysdecode_quotactl_cmd.3 (revision 307538) @@ -0,0 +1,93 @@ +.\" +.\" Copyright (c) 2016 John Baldwin +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd October 17, 2016 +.Dt sysdecode_quotactl_cmd 3 +.Os +.Sh NAME +.Nm sysdecode_quotactl_cmd +.Nd output name of quotactl command +.Sh LIBRARY +.Lb libsysdecode +.Sh SYNOPSIS +.In sys/types.h +.In stdbool.h +.In sysdecode.h +.Ft bool +.Fn sysdecode_quotactl_cmd "FILE *fp" "int cmd" +.Sh DESCRIPTION +The +.Fn sysdecode_quotactl_cmd +function outputs a text description of the +.Fa cmd +argument to +.Xr quotactl 2 +to the stream +.Fa fp . +The description is formatted as an invocation of the +.Dv QCMD +macro defined in the +.In ufs/ufs/quota.h +header. +.Pp +The function first computes the primary and secondary values used by +.Dv QCMD +to construct +.Fa cmd . +If the primary command value does not represent a known constant, +.Fn sysdecode_quotactl_cmd +does not generate any output and returns +.Dv false . +Otherwise, +.Fn sysdecode_quotactl_cmd +outputs text depicting an invocation of +.Dv QCMD +with the associated constants for the primary and secondary command values +and returns +.Dv true . +If the secondary command values does not represent a known constant, +its value is output as a hexadecimal integer. +.Sh RETURN VALUES +The +.Nm sysdecode_quotactl_cmd +function returns +.Dv true +if it outputs a description of +.Fa cmd +and +.Dv false +if it does not. +.Sh EXAMPLES +The statement +.Pp +.Dl sysdecode_quotatcl_cmd(stdout, QCMD(Q_GETQUOTA, USRQUOTA); +.Pp +outputs the text +.Dq QCMD(Q_GETQUOTA, USRQUOTA) +to standard output. +.Sh SEE ALSO +.Xr sysdecode 3 Property changes on: head/lib/libsysdecode/sysdecode_quotactl_cmd.3 ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/lib/libsysdecode/sysdecode_sigcode.3 =================================================================== --- head/lib/libsysdecode/sysdecode_sigcode.3 (nonexistent) +++ head/lib/libsysdecode/sysdecode_sigcode.3 (revision 307538) @@ -0,0 +1,83 @@ +.\" +.\" Copyright (c) 2016 John Baldwin +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd October 17, 2016 +.Dt sysdecode_sigcode 3 +.Os +.Sh NAME +.Nm sysdecode_sigcode +.Nd lookup name of signal code +.Sh LIBRARY +.Lb libsysdecode +.Sh SYNOPSIS +.In sys/types.h +.In stdbool.h +.In sysdecode.h +.Ft const char * +.Fn sysdecode_sigcode "int signal" "int si_code" +.Sh DESCRIPTION +The +.Fn sysdecode_sigcode +function returns a text description of the +.Fa si_code +field of the +.Vt siginfo_t +object associated with an instance of signal +.Fa sig . +The text description contains the name of the C macro whose value matches +.Fa si_code . +General purpose signal codes such as +.Dv SI_USER +are handled as well as signal-specific codes for +.Dv SIGBUS , +.Dv SIGCHLD , +.Dv SIGFPE , +.Dv SIGILL , +.Dv SIGSEGV +and +.Dv SIGTRAP . +If +.Fa si_code +does not represent a known signal code, +.Fn sysdecode_sigcode +returns +.Dv NULL . +.Sh RETURN VALUES +The +.Fn sysdecode_sigcode +function returns a pointer to a signal code description or +.Dv NULL +if +.Fa si_code +is not a known signal code. +.Sh SEE ALSO +.Xr sysdecode_sigbus_code 3 , +.Xr sysdecode_sigchld_code 3 , +.Xr sysdecode_sigfpe_code 3 , +.Xr sysdecode_sigill_code 3 , +.Xr sysdecode_sigsegv_code 3 , +.Xr sysdecode_sigtrap_code 3 Property changes on: head/lib/libsysdecode/sysdecode_sigcode.3 ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/lib/libsysdecode/sysdecode_sockopt_name.3 =================================================================== --- head/lib/libsysdecode/sysdecode_sockopt_name.3 (nonexistent) +++ head/lib/libsysdecode/sysdecode_sockopt_name.3 (revision 307538) @@ -0,0 +1,61 @@ +.\" +.\" Copyright (c) 2016 John Baldwin +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd October 17, 2016 +.Dt sysdecode_sockopt_name 3 +.Os +.Sh NAME +.Nm sysdecode_sockopt_name +.Nd lookup name of socket option +.Sh LIBRARY +.Lb libsysdecode +.Sh SYNOPSIS +.In sys/types.h +.In stdbool.h +.In sysdecode.h +.Ft const char * +.Fn sysdecode_sockopt_name "int level" "int optname" +.Sh DESCRIPTION +The +.Fn sysdecode_sockopt_name +function returns a text description of the socket option name passed in the +.Fa optname +argument to +.Xr getsockopt 2 . +.Fn sysdecode_sockopt_name +takes the socket option +.Fa level +as well as the option name to uniquely identify the option. +.Sh SEE ALSO +.Xr sysdecode_sockopt_level 3 +.Sh BUGS +Socket option levels and names are protocol-specific. +Both +.Fn sysdecode_sockopt_level +and +.Fn sysdecode_sockopt_name +should possibly accept the protocol family as an additional argument. Property changes on: head/lib/libsysdecode/sysdecode_sockopt_name.3 ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/lib/libsysdecode/sysdecode_syscallnames.3 =================================================================== --- head/lib/libsysdecode/sysdecode_syscallnames.3 (revision 307537) +++ head/lib/libsysdecode/sysdecode_syscallnames.3 (revision 307538) @@ -1,68 +1,71 @@ .\" .\" Copyright (c) 2016 John Baldwin .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" $FreeBSD$ .\" -.Dd January 30, 2016 +.Dd October 17, 2016 .Dt sysdecode_syscallnames 3 .Os .Sh NAME .Nm sysdecode_syscallnames .Nd lookup name of system calls .Sh LIBRARY .Lb libsysdecode .Sh SYNOPSIS +.In sys/types.h +.In stdbool.h +.In sysdecode.h .Ft const char * .Fn sysdecode_syscallnames "enum sysdecode_abi abi" "unsigned int code" .Sh DESCRIPTION This function returns a pointer to the name of a system call identified by .Fa code for the process ABI .Fa abi . If .Fa code specifies an unknown system call or .Fa abi is an unsupported ABI, .Nm returns .Dv NULL . .Pp For the list of supported ABIs, see .Xr sysdecode 3 . .Sh RETURN VALUES The .Nm function returns a pointer to a string on success or .Dv NULL if either .Fa code or .Fa ABI is invalid . .Sh SEE ALSO .Xr sysdecode 3 , .Xr sysdecode_abi_to_freebsd_errno 3 Index: head/lib/libsysdecode/sysdecode_utrace.3 =================================================================== --- head/lib/libsysdecode/sysdecode_utrace.3 (revision 307537) +++ head/lib/libsysdecode/sysdecode_utrace.3 (revision 307538) @@ -1,73 +1,76 @@ .\" .\" Copyright (c) 2015 John Baldwin .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" $FreeBSD$ .\" -.Dd December 11, 2015 +.Dd October 17, 2016 .Dt sysdecode_utrace 3 .Os .Sh NAME .Nm sysdecode_utrace .Nd produce text description of a utrace record .Sh LIBRARY .Lb libsysdecode .Sh SYNOPSIS +.In sys/types.h +.In stdbool.h +.In sysdecode.h .Ft int .Fn sysdecode_utrace "FILE *fp" "void *buf" "size_t len" "int decimal" .Sh DESCRIPTION The .Fn sysdecode_utrace function outputs a textual representation of a .Xr utrace 2 record identified by .Fa buf and .Fa len to the output stream .Fa fp . .Pp The function only outputs a representation for certain types of records. If a record is recognized, the function outputs the description and returns a non-zero value. If the record is not recognized, the function does not output anything and returns zero. The .Fn sysdecode_utrace function currently recognizes .Xr utrace 2 records generated by .Xr malloc 3 and .Xr rtld 1 . .Sh RETURN VALUES The .Fn sysdecode_utrace function returns a non-zero value if it recognizes a .Xr utrace 2 record; otherwise it returns zero. .Sh SEE ALSO .Xr utrace 2 , .Xr sysdecode 3 Index: head/lib/libsysdecode/utrace.c =================================================================== --- head/lib/libsysdecode/utrace.c (revision 307537) +++ head/lib/libsysdecode/utrace.c (revision 307538) @@ -1,209 +1,210 @@ /*- * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include #include "rtld_utrace.h" #ifdef __LP64__ struct utrace_rtld32 { char sig[4]; int event; uint32_t handle; uint32_t mapbase; uint32_t mapsize; int refcnt; char name[MAXPATHLEN]; }; #endif static int print_utrace_rtld(FILE *fp, void *p) { struct utrace_rtld *ut = p; void *parent; int mode; switch (ut->event) { case UTRACE_DLOPEN_START: mode = ut->refcnt; fprintf(fp, "dlopen(%s, ", ut->name); switch (mode & RTLD_MODEMASK) { case RTLD_NOW: fprintf(fp, "RTLD_NOW"); break; case RTLD_LAZY: fprintf(fp, "RTLD_LAZY"); break; default: fprintf(fp, "%#x", mode & RTLD_MODEMASK); } if (mode & RTLD_GLOBAL) fprintf(fp, " | RTLD_GLOBAL"); if (mode & RTLD_TRACE) fprintf(fp, " | RTLD_TRACE"); if (mode & ~(RTLD_MODEMASK | RTLD_GLOBAL | RTLD_TRACE)) fprintf(fp, " | %#x", mode & ~(RTLD_MODEMASK | RTLD_GLOBAL | RTLD_TRACE)); fprintf(fp, ")"); break; case UTRACE_DLOPEN_STOP: fprintf(fp, "%p = dlopen(%s) ref %d", ut->handle, ut->name, ut->refcnt); break; case UTRACE_DLCLOSE_START: fprintf(fp, "dlclose(%p) (%s, %d)", ut->handle, ut->name, ut->refcnt); break; case UTRACE_DLCLOSE_STOP: fprintf(fp, "dlclose(%p) finished", ut->handle); break; case UTRACE_LOAD_OBJECT: fprintf(fp, "RTLD: loaded %p @ %p - %p (%s)", ut->handle, ut->mapbase, (char *)ut->mapbase + ut->mapsize - 1, ut->name); break; case UTRACE_UNLOAD_OBJECT: fprintf(fp, "RTLD: unloaded %p @ %p - %p (%s)", ut->handle, ut->mapbase, (char *)ut->mapbase + ut->mapsize - 1, ut->name); break; case UTRACE_ADD_RUNDEP: parent = ut->mapbase; fprintf(fp, "RTLD: %p now depends on %p (%s, %d)", parent, ut->handle, ut->name, ut->refcnt); break; case UTRACE_PRELOAD_FINISHED: fprintf(fp, "RTLD: LD_PRELOAD finished"); break; case UTRACE_INIT_CALL: fprintf(fp, "RTLD: init %p for %p (%s)", ut->mapbase, ut->handle, ut->name); break; case UTRACE_FINI_CALL: fprintf(fp, "RTLD: fini %p for %p (%s)", ut->mapbase, ut->handle, ut->name); break; case UTRACE_DLSYM_START: fprintf(fp, "RTLD: dlsym(%p, %s)", ut->handle, ut->name); break; case UTRACE_DLSYM_STOP: fprintf(fp, "RTLD: %p = dlsym(%p, %s)", ut->mapbase, ut->handle, ut->name); break; default: return (0); } return (1); } struct utrace_malloc { void *p; size_t s; void *r; }; #ifdef __LP64__ struct utrace_malloc32 { uint32_t p; uint32_t s; uint32_t r; }; #endif static void print_utrace_malloc(FILE *fp, void *p) { struct utrace_malloc *ut = p; if (ut->p == (void *)(intptr_t)(-1)) fprintf(fp, "malloc_init()"); else if (ut->s == 0) fprintf(fp, "free(%p)", ut->p); else if (ut->p == NULL) fprintf(fp, "%p = malloc(%zu)", ut->r, ut->s); else fprintf(fp, "%p = realloc(%p, %zu)", ut->r, ut->p, ut->s); } int sysdecode_utrace(FILE *fp, void *p, size_t len) { #ifdef __LP64__ struct utrace_rtld ur; struct utrace_rtld32 *pr; struct utrace_malloc um; struct utrace_malloc32 *pm; #endif static const char rtld_utrace_sig[RTLD_UTRACE_SIG_SZ] = RTLD_UTRACE_SIG; if (len == sizeof(struct utrace_rtld) && bcmp(p, rtld_utrace_sig, sizeof(rtld_utrace_sig)) == 0) return (print_utrace_rtld(fp, p)); if (len == sizeof(struct utrace_malloc)) { print_utrace_malloc(fp, p); return (1); } #ifdef __LP64__ if (len == sizeof(struct utrace_rtld32) && bcmp(p, rtld_utrace_sig, sizeof(rtld_utrace_sig)) == 0) { pr = p; memset(&ur, 0, sizeof(ur)); memcpy(ur.sig, pr->sig, sizeof(ur.sig)); ur.event = pr->event; ur.handle = (void *)(uintptr_t)pr->handle; ur.mapbase = (void *)(uintptr_t)pr->mapbase; ur.mapsize = pr->mapsize; ur.refcnt = pr->refcnt; memcpy(ur.name, pr->name, sizeof(ur.name)); return (print_utrace_rtld(fp, &ur)); } if (len == sizeof(struct utrace_malloc32)) { pm = p; memset(&um, 0, sizeof(um)); um.p = pm->p == (uint32_t)-1 ? (void *)(intptr_t)-1 : (void *)(uintptr_t)pm->p; um.s = pm->s; um.r = (void *)(uintptr_t)pm->r; print_utrace_malloc(fp, &um); return (1); } #endif return (0); } Index: head/usr.bin/kdump/mksubr =================================================================== --- head/usr.bin/kdump/mksubr (revision 307537) +++ head/usr.bin/kdump/mksubr (nonexistent) @@ -1,759 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2006 "David Kirchner" . All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. -# -# $FreeBSD$ -# -# Generates kdump_subr.c -# mkioctls is a special-purpose script, and works fine as it is -# now, so it remains independent. The idea behind how it generates -# its list was heavily borrowed here. -# -# Some functions here are automatically generated. This can mean -# the user will see unusual kdump output or errors while building -# if the underlying .h files are changed significantly. -# -# Key: -# AUTO: Completely auto-generated with either the "or" or the "switch" -# method. -# AUTO - Special: Generated automatically, but with some extra commands -# that the auto_*_type() functions are inappropriate for. -# MANUAL: Manually entered and must therefore be manually updated. - -set -e - -LC_ALL=C; export LC_ALL - -if [ -z "$1" ] -then - echo "usage: sh $0 include-dir" - exit 1 -fi -include_dir=$1 - -# -# Automatically generates a C function that will print out the -# numeric input as a pipe-delimited string of the appropriate -# #define keys. ex: -# S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH -# The XOR is necessary to prevent including the "0"-value in every -# line. -# -auto_or_type () { - local name grep file - name=$1 - grep=$2 - file=$3 - - cat <<_EOF_ -/* AUTO */ -void -$name(intmax_t arg) -{ - int or = 0; - printf("%#jx<", (uintmax_t)arg); -_EOF_ - egrep "^#[[:space:]]*define[[:space:]]+"${grep}"[[:space:]]*" \ - $include_dir/$file | \ - awk '{ for (i = 1; i <= NF; i++) \ - if ($i ~ /define/) \ - break; \ - ++i; \ - printf "\tif (!((arg > 0) ^ ((%s) > 0)))\n\t\tif_print_or(arg, %s, or);\n", $i, $i }' -cat <<_EOF_ - printf(">"); - if (or == 0) - printf("%jd", arg); -} - -_EOF_ -} - -# -# Automatically generates a C function used when the argument -# maps to a single, specific #definition -# -auto_switch_type () { - local name grep file - name=$1 - grep=$2 - file=$3 - - cat <<_EOF_ -/* AUTO */ -void -$name(intmax_t arg) -{ - switch (arg) { -_EOF_ - egrep "^#[[:space:]]*define[[:space:]]+"${grep}"[[:space:]]*" \ - $include_dir/$file | \ - awk '{ for (i = 1; i <= NF; i++) \ - if ($i ~ /define/) \ - break; \ - ++i; \ - printf "\tcase %s:\n\t\tprintf(\"%s\");\n\t\tbreak;\n", $i, $i }' -cat <<_EOF_ - default: /* Should not reach */ - printf("", arg); - } -} - -_EOF_ -} - -# -# Automatically generates a C function used when the argument -# maps to a #definition -# -auto_if_type () { - local name grep file - name=$1 - grep=$2 - file=$3 - - cat <<_EOF_ -/* AUTO */ -void -$name(intmax_t arg) -{ -_EOF_ - egrep "^#[[:space:]]*define[[:space:]]+"${grep}"[[:space:]]*" \ - $include_dir/$file | \ - awk '{ printf "\t"; \ - if (NR > 1) \ - printf "else " ; \ - printf "if (arg == %s) \n\t\tprintf(\"%s\");\n", $2, $2 }' -cat <<_EOF_ - else /* Should not reach */ - printf("", arg); -} - -_EOF_ -} - -# C start - -cat <<_EOF_ -#include -#include -#include -#include -#include -#include -#include -#define _KERNEL -#include -#undef _KERNEL -#include -#include -#include -#include -#include -#include -#include -#include -#include -#define _KERNEL -#include -#undef _KERNEL -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "kdump_subr.h" - -/* - * These are simple support macros. print_or utilizes a variable - * defined in the calling function to track whether or not it should - * print a logical-OR character ('|') before a string. if_print_or - * simply handles the necessary "if" statement used in many lines - * of this file. - */ -#define print_or(str,orflag) do { \\ - if (orflag) putchar('|'); else orflag = 1; \\ - printf (str); } \\ - while (0) -#define if_print_or(i,flag,orflag) do { \\ - if ((i & flag) == flag) \\ - print_or(#flag,orflag); } \\ - while (0) - -/* MANUAL */ -void -atfdname(int fd, int decimal) -{ - if (fd == AT_FDCWD) - printf("AT_FDCWD"); - else if (decimal) - printf("%d", fd); - else - printf("%#x", fd); -} - -/* MANUAL */ -extern char *signames[]; /* from kdump.c */ -void -signame(int sig) -{ - if (sig > 0 && sig < NSIG) - printf("SIG%s",signames[sig]); - else - printf("SIG %d", sig); -} - -/* MANUAL */ -void -semctlname(int cmd) -{ - switch (cmd) { - case GETNCNT: - printf("GETNCNT"); - break; - case GETPID: - printf("GETPID"); - break; - case GETVAL: - printf("GETVAL"); - break; - case GETALL: - printf("GETALL"); - break; - case GETZCNT: - printf("GETZCNT"); - break; - case SETVAL: - printf("SETVAL"); - break; - case SETALL: - printf("SETALL"); - break; - case IPC_RMID: - printf("IPC_RMID"); - break; - case IPC_SET: - printf("IPC_SET"); - break; - case IPC_STAT: - printf("IPC_STAT"); - break; - default: /* Should not reach */ - printf("", cmd); - } -} - -/* MANUAL */ -void -shmctlname(int cmd) -{ - switch (cmd) { - case IPC_RMID: - printf("IPC_RMID"); - break; - case IPC_SET: - printf("IPC_SET"); - break; - case IPC_STAT: - printf("IPC_STAT"); - break; - default: /* Should not reach */ - printf("", cmd); - } -} - -/* MANUAL */ -void -semgetname(int flag) -{ - int or = 0; - if_print_or(flag, IPC_CREAT, or); - if_print_or(flag, IPC_EXCL, or); - if_print_or(flag, SEM_R, or); - if_print_or(flag, SEM_A, or); - if_print_or(flag, (SEM_R>>3), or); - if_print_or(flag, (SEM_A>>3), or); - if_print_or(flag, (SEM_R>>6), or); - if_print_or(flag, (SEM_A>>6), or); -} - -/* - * MANUAL - * - * Only used by SYS_open. Unless O_CREAT is set in flags, the - * mode argument is unused (and often bogus and misleading). - */ -void -flagsandmodename(int flags, int mode, int decimal) -{ - flagsname(flags); - putchar(','); - if ((flags & O_CREAT) == O_CREAT) { - modename (mode); - } else { - if (decimal) { - printf("%d", mode); - } else { - printf("%#x", (unsigned int)mode); - } - } -} - -/* MANUAL */ -void -idtypename(idtype_t idtype, int decimal) -{ - switch(idtype) { - case P_PID: - printf("P_PID"); - break; - case P_PPID: - printf("P_PPID"); - break; - case P_PGID: - printf("P_PGID"); - break; - case P_SID: - printf("P_SID"); - break; - case P_CID: - printf("P_CID"); - break; - case P_UID: - printf("P_UID"); - break; - case P_GID: - printf("P_GID"); - break; - case P_ALL: - printf("P_ALL"); - break; - case P_LWPID: - printf("P_LWPID"); - break; - case P_TASKID: - printf("P_TASKID"); - break; - case P_PROJID: - printf("P_PROJID"); - break; - case P_POOLID: - printf("P_POOLID"); - break; - case P_JAILID: - printf("P_JAILID"); - break; - case P_CTID: - printf("P_CTID"); - break; - case P_CPUID: - printf("P_CPUID"); - break; - case P_PSETID: - printf("P_PSETID"); - break; - default: - if (decimal) { - printf("%d", idtype); - } else { - printf("%#x", idtype); - } - } -} - -/* - * MANUAL - * - * [g|s]etsockopt's level argument can either be SOL_SOCKET or a value - * referring to a line in /etc/protocols . It might be appropriate - * to use getprotoent(3) here. - */ -void -sockoptlevelname(int level, int decimal) -{ - if (level == SOL_SOCKET) { - printf("SOL_SOCKET"); - } else { - if (decimal) { - printf("%d", level); - } else { - printf("%#x", (unsigned int)level); - } - } -} - -/* - * MANUAL - * - * Used for page fault type. Cannot use auto_or_type since the macro - * values contain a cast. Also, VM_PROT_NONE has to be handled specially. - */ -void -vmprotname (int type) -{ - int or = 0; - - if (type == VM_PROT_NONE) { - (void)printf("VM_PROT_NONE"); - return; - } - if_print_or(type, VM_PROT_READ, or); - if_print_or(type, VM_PROT_WRITE, or); - if_print_or(type, VM_PROT_EXECUTE, or); - if_print_or(type, VM_PROT_COPY, or); -} - -/* - * MANUAL - */ -void -socktypenamewithflags(int type) -{ - if (type & SOCK_CLOEXEC) - printf("SOCK_CLOEXEC|"), type &= ~SOCK_CLOEXEC; - if (type & SOCK_NONBLOCK) - printf("SOCK_NONBLOCK|"), type &= ~SOCK_NONBLOCK; - socktypename(type); -} -_EOF_ - -auto_or_type "accessmodename" "[A-Z]_OK[[:space:]]+0?x?[0-9A-Fa-f]+" "sys/unistd.h" -auto_switch_type "acltypename" "ACL_TYPE_[A-Z4_]+[[:space:]]+0x[0-9]+" "sys/acl.h" -auto_or_type "capfcntlname" "CAP_FCNTL_[A-Z]+[[:space:]]+\(1" "sys/capsicum.h" -auto_switch_type "extattrctlname" "EXTATTR_NAMESPACE_[A-Z]+[[:space:]]+0x[0-9]+" "sys/extattr.h" -auto_switch_type "fadvisebehavname" "POSIX_FADV_[A-Z]+[[:space:]]+[0-9]+" "sys/fcntl.h" -auto_or_type "flagsname" "O_[A-Z]+[[:space:]]+0x[0-9A-Fa-f]+" "sys/fcntl.h" -auto_or_type "flockname" "LOCK_[A-Z]+[[:space:]]+0x[0-9]+" "sys/fcntl.h" -auto_or_type "getfsstatflagsname" "MNT_[A-Z]+[[:space:]]+[1-9][0-9]*" "sys/mount.h" -auto_switch_type "kldsymcmdname" "KLDSYM_[A-Z]+[[:space:]]+[0-9]+" "sys/linker.h" -auto_switch_type "kldunloadfflagsname" "LINKER_UNLOAD_[A-Z]+[[:space:]]+[0-9]+" "sys/linker.h" -auto_switch_type "lio_listioname" "LIO_(NO)?WAIT[[:space:]]+[0-9]+" "aio.h" -auto_switch_type "madvisebehavname" "_?MADV_[A-Z]+[[:space:]]+[0-9]+" "sys/mman.h" -auto_switch_type "minheritname" "INHERIT_[A-Z]+[[:space:]]+[0-9]+" "sys/mman.h" -auto_or_type "mlockallname" "MCL_[A-Z]+[[:space:]]+0x[0-9]+" "sys/mman.h" -auto_or_type "mmapprotname" "PROT_[A-Z]+[[:space:]]+0x[0-9A-Fa-f]+" "sys/mman.h" -auto_or_type "modename" "S_[A-Z]+[[:space:]]+[0-6]{7}" "sys/stat.h" -auto_or_type "mountflagsname" "MNT_[A-Z]+[[:space:]]+0x[0-9]+" "sys/mount.h" -auto_switch_type "msyncflagsname" "MS_[A-Z]+[[:space:]]+0x[0-9]+" "sys/mman.h" -auto_or_type "nfssvcname" "NFSSVC_[A-Z0-9]+[[:space:]]+0x[0-9]+" "nfs/nfssvc.h" -auto_switch_type "prioname" "PRIO_[A-Z]+[[:space:]]+[0-9]" "sys/resource.h" -auto_switch_type "procctlcmdname" "PROC_[A-Z]+[[:space:]]+[0-9]" "sys/procctl.h" -auto_switch_type "ptraceopname" "PT_[[:alnum:]_]+[[:space:]]+[0-9]+" "sys/ptrace.h" -auto_switch_type "quotactlname" "Q_[A-Z]+[[:space:]]+0x[0-9]+" "ufs/ufs/quota.h" -auto_or_type "rebootoptname" "RB_[A-Z]+[[:space:]]+0x[0-9]+" "sys/reboot.h" -auto_or_type "rforkname" "RF[A-Z]+[[:space:]]+\([0-9]+<<[0-9]+\)" "sys/unistd.h" -auto_switch_type "rlimitname" "RLIMIT_[A-Z]+[[:space:]]+[0-9]+" "sys/resource.h" -auto_switch_type "schedpolicyname" "SCHED_[A-Z]+[[:space:]]+[0-9]+" "sched.h" -auto_switch_type "sendfileflagsname" "SF_[A-Z]+[[:space:]]+[0-9]+" "sys/socket.h" -auto_or_type "shmatname" "SHM_[A-Z]+[[:space:]]+[0-9]{6}+" "sys/shm.h" -auto_switch_type "shutdownhowname" "SHUT_[A-Z]+[[:space:]]+[0-9]+" "sys/socket.h" -auto_switch_type "sigbuscodename" "BUS_[A-Z]+[[:space:]]+[0-9]+" "sys/signal.h" -auto_switch_type "sigchldcodename" "CLD_[A-Z]+[[:space:]]+[0-9]+" "sys/signal.h" -auto_switch_type "sigfpecodename" "FPE_[A-Z]+[[:space:]]+[0-9]+" "sys/signal.h" -auto_switch_type "sigprocmaskhowname" "SIG_[A-Z]+[[:space:]]+[0-9]+" "sys/signal.h" -auto_switch_type "sigillcodename" "ILL_[A-Z]+[[:space:]]+[0-9]+" "sys/signal.h" -auto_switch_type "sigsegvcodename" "SEGV_[A-Z]+[[:space:]]+[0-9]+" "sys/signal.h" -auto_switch_type "sigtrapcodename" "TRAP_[A-Z]+[[:space:]]+[0-9]+" "sys/signal.h" -auto_if_type "sockdomainname" "PF_[[:alnum:]]+[[:space:]]+" "sys/socket.h" -auto_if_type "sockfamilyname" "AF_[[:alnum:]]+[[:space:]]+" "sys/socket.h" -auto_if_type "sockipprotoname" "IPPROTO_[[:alnum:]]+[[:space:]]+" "netinet/in.h" -auto_switch_type "sockoptname" "SO_[A-Z]+[[:space:]]+0x[0-9]+" "sys/socket.h" -auto_switch_type "socktypename" "SOCK_[A-Z]+[[:space:]]+[1-9]+[0-9]*" "sys/socket.h" -auto_or_type "thrcreateflagsname" "THR_[A-Z]+[[:space:]]+0x[0-9]+" "sys/thr.h" -auto_switch_type "umtxopname" "UMTX_OP_[[:alnum:]_]+[[:space:]]+[0-9]+" "sys/umtx.h" -auto_switch_type "vmresultname" "KERN_[A-Z]+[[:space:]]+[0-9]+" "vm/vm_param.h" -auto_or_type "wait6optname" "W[A-Z]+[[:space:]]+[0-9]+" "sys/wait.h" -auto_switch_type "whencename" "SEEK_[A-Z]+[[:space:]]+[0-9]+" "sys/unistd.h" - -cat <<_EOF_ -/* - * AUTO - Special - * F_ is used to specify fcntl commands as well as arguments. Both sets are - * grouped in fcntl.h, and this awk script grabs the first group. - */ -void -fcntlcmdname(int cmd, int arg, int decimal) -{ - switch (cmd) { -_EOF_ -egrep "^#[[:space:]]*define[[:space:]]+F_[A-Z0-9_]+[[:space:]]+[0-9]+[[:space:]]*" \ - $include_dir/sys/fcntl.h | \ - awk 'BEGIN { o=0 } { for (i = 1; i <= NF; i++) \ - if ($i ~ /define/) \ - break; \ - ++i; \ - if (o <= $(i+1)) \ - printf "\tcase %s:\n\t\tprintf(\"%s\");\n\t\tbreak;\n", $i, $i; \ - else \ - exit; \ - o = $(i+1) }' -cat <<_EOF_ - default: /* Should not reach */ - printf("", cmd); - } - putchar(','); - if (cmd == F_GETFD || cmd == F_SETFD) { - if (arg == FD_CLOEXEC) - printf("FD_CLOEXEC"); - else if (arg == 0) - printf("0"); - else { - if (decimal) - printf("%d", arg); - else - printf("%#x", (unsigned int)arg); - } - } else if (cmd == F_SETFL) { - flagsname(arg); - } else { - if (decimal) - printf("%d", arg); - else - printf("%#x", (unsigned int)arg); - } -} - -/* - * AUTO - Special - * - * The MAP_ALIGNED flag requires special handling. - */ -void -mmapflagsname(int flags) -{ - int align; - int or = 0; - printf("%#x<", flags); -_EOF_ -egrep "^#[[:space:]]*define[[:space:]]+MAP_[A-Z_]+[[:space:]]+0x[0-9A-Fa-f]+[[:space:]]*" \ - $include_dir/sys/mman.h | grep -v MAP_ALIGNED | \ - awk '{ for (i = 1; i <= NF; i++) \ - if ($i ~ /define/) \ - break; \ - ++i; \ - printf "\tif (!((flags > 0) ^ ((%s) > 0)))\n\t\tif_print_or(flags, %s, or);\n", $i, $i }' -cat <<_EOF_ -#ifdef MAP_32BIT - if (!((flags > 0) ^ ((MAP_32BIT) > 0))) - if_print_or(flags, MAP_32BIT, or); -#endif - align = flags & MAP_ALIGNMENT_MASK; - if (align != 0) { - if (align == MAP_ALIGNED_SUPER) - print_or("MAP_ALIGNED_SUPER", or); - else { - print_or("MAP_ALIGNED", or); - printf("(%d)", align >> MAP_ALIGNMENT_SHIFT); - } - } - printf(">"); - if (or == 0) - printf("%d", flags); -} - -/* - * AUTO - Special - * - * The only reason this is not fully automated is due to the - * grep -v RTP_PRIO statement. A better egrep line should - * make this capable of being a auto_switch_type() function. - */ -void -rtprioname(int func) -{ - switch (func) { -_EOF_ -egrep "^#[[:space:]]*define[[:space:]]+RTP_[A-Z]+[[:space:]]+0x[0-9]+[[:space:]]*" \ - $include_dir/sys/rtprio.h | grep -v RTP_PRIO | \ - awk '{ for (i = 1; i <= NF; i++) \ - if ($i ~ /define/) \ - break; \ - ++i; \ - printf "\tcase %s:\n\t\tprintf(\"%s\");\n\t\tbreak;\n", $i, $i }' -cat <<_EOF_ - default: /* Should not reach */ - printf("", func); - } -} - -/* - * AUTO - Special - * - * The send and recv functions have a flags argument which can be - * set to 0. There is no corresponding #define. The auto_ functions - * detect this as "invalid", which is incorrect here. - */ -void -sendrecvflagsname(int flags) -{ - int or = 0; - - if (flags == 0) { - printf("0"); - return; - } - - printf("%#x<", flags); -_EOF_ -egrep "^#[[:space:]]*define[[:space:]]+MSG_[A-Z]+[[:space:]]+0x[0-9]+[[:space:]]*" $include_dir/sys/socket.h | \ - awk '{ for (i = 1; i <= NF; i++) \ - if ($i ~ /define/) \ - break; \ - ++i; \ - printf "\tif(!((flags>0)^((%s)>0)))\n\t\tif_print_or(flags, %s, or);\n", $i, $i }' -cat <<_EOF_ - printf(">"); -} - -/* - * AUTO - Special - * - * Check general codes first, then defer to signal-specific codes. - */ -void -sigcodename(int sig, int code) -{ - switch (code) { -_EOF_ -egrep "^#[[:space:]]*define[[:space:]]+SI_[A-Z]+[[:space:]]+0(x[0-9abcdef]+)?[[:space:]]*" \ - $include_dir/sys/signal.h | grep -v SI_UNDEFINED | \ - awk '{ for (i = 1; i <= NF; i++) \ - if ($i ~ /define/) \ - break; \ - ++i; \ - printf "\tcase %s:\n\t\tprintf(\"%s\");\n\t\tbreak;\n", $i, $i }' -cat <<_EOF_ - default: - switch (sig) { - case SIGILL: - sigillcodename(code); - break; - case SIGBUS: - sigbuscodename(code); - break; - case SIGSEGV: - sigsegvcodename(code); - break; - case SIGFPE: - sigfpecodename(code); - break; - case SIGTRAP: - sigtrapcodename(code); - break; - case SIGCHLD: - sigchldcodename(code); - break; - default: - printf("", code); - } - } -} - -/* - * AUTO - Special - * - * Just print 0 as 0. - */ -void -umtxcvwaitflags(intmax_t arg) -{ - int or = 0; - if (arg == 0) { - printf("0"); - return; - } - printf("%#jx<", (uintmax_t)arg); -_EOF_ - egrep "^#[[:space:]]*define[[:space:]]+CVWAIT_[A-Z_]+[[:space:]]+0x[0-9]+[[:space:]]*" \ - $include_dir/sys/umtx.h | \ - awk '{ for (i = 1; i <= NF; i++) \ - if ($i ~ /define/) \ - break; \ - ++i; \ - printf "\tif (!((arg > 0) ^ ((%s) > 0)))\n\t\tif_print_or(arg, %s, or);\n", $i, $i }' -cat <<_EOF_ - printf(">"); - if (or == 0) - printf("%jd", arg); -} - - -/* - * AUTO - Special - * - * Just print 0 as 0. - */ -void -umtxrwlockflags(intmax_t arg) -{ - int or = 0; - if (arg == 0) { - printf("0"); - return; - } - printf("%#jx<", (uintmax_t)arg); -_EOF_ - egrep "^#[[:space:]]*define[[:space:]]+URWLOCK_PREFER_READER[[:space:]]+0x[0-9]+[[:space:]]*" \ - $include_dir/sys/umtx.h | \ - awk '{ for (i = 1; i <= NF; i++) \ - if ($i ~ /define/) \ - break; \ - ++i; \ - printf "\tif (!((arg > 0) ^ ((%s) > 0)))\n\t\tif_print_or(arg, %s, or);\n", $i, $i }' -cat <<_EOF_ - printf(">"); - if (or == 0) - printf("%jd", arg); -} -_EOF_ -egrep '#define[[:space:]]+CAP_[A-Z_]+[[:space:]]+CAPRIGHT\([0-9],[[:space:]]+0x[0-9]{16}ULL\)' \ - $include_dir/sys/capsicum.h | \ - sed -E 's/[ ]+/ /g' | \ - awk -F '[ \(,\)]' ' - BEGIN { - printf "void\n" - printf "capname(const cap_rights_t *rightsp)\n" - printf "{\n" - printf "\tint comma = 0;\n\n" - printf "\tprintf(\"<\");\n" - } - { - printf "\tif ((rightsp->cr_rights[%s] & %s) == %s) {\n", $4, $2, $2 - printf "\t\tif (comma) printf(\",\"); else comma = 1;\n" - printf "\t\tprintf(\"%s\");\n", $2 - printf "\t}\n" - } - END { - printf "\tprintf(\">\");\n" - printf "}\n" - }' Property changes on: head/usr.bin/kdump/mksubr ___________________________________________________________________ Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Index: head/usr.bin/kdump/Makefile =================================================================== --- head/usr.bin/kdump/Makefile (revision 307537) +++ head/usr.bin/kdump/Makefile (revision 307538) @@ -1,31 +1,22 @@ # @(#)Makefile 8.1 (Berkeley) 6/6/93 # $FreeBSD$ .include .PATH: ${.CURDIR}/../ktrace PROG= kdump -SRCS= kdump_subr.c kdump_subr.h kdump.c subr.c -CFLAGS+= -I${.CURDIR}/../ktrace -I${.CURDIR} -I${.CURDIR}/../.. -I. +SRCS= kdump.c subr.c +CFLAGS+= -I${.CURDIR}/../ktrace #-I${.CURDIR}/../... LIBADD= sysdecode .if ${MK_CASPER} != "no" LIBADD+= casper LIBADD+= cap_grp LIBADD+= cap_pwd CFLAGS+=-DHAVE_LIBCASPER .endif -NO_WERROR?= YES - -CLEANFILES= kdump_subr.c kdump_subr.h - -kdump_subr.h: mksubr - sh ${.CURDIR}/mksubr ${DESTDIR}${INCLUDEDIR} | \ - sed -n 's/^\([a-z].*)\)$$/void \1;/p' >${.TARGET} - -kdump_subr.c: mksubr kdump_subr.h - sh ${.CURDIR}/mksubr ${DESTDIR}${INCLUDEDIR} >${.TARGET} +#NO_WERROR?= YES .include Index: head/usr.bin/kdump/kdump.c =================================================================== --- head/usr.bin/kdump/kdump.c (revision 307537) +++ head/usr.bin/kdump/kdump.c (revision 307538) @@ -1,1858 +1,2026 @@ /*- * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1988, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint #if 0 static char sccsid[] = "@(#)kdump.c 8.1 (Berkeley) 6/6/93"; #endif #endif /* not lint */ #include __FBSDID("$FreeBSD$"); #define _WANT_KERNEL_ERRNO #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_LIBCASPER #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ktrace.h" -#include "kdump_subr.h" #ifdef HAVE_LIBCASPER #include #include #include #endif u_int abidump(struct ktr_header *); int fetchprocinfo(struct ktr_header *, u_int *); int fread_tail(void *, int, int); void dumpheader(struct ktr_header *); void ktrsyscall(struct ktr_syscall *, u_int); void ktrsysret(struct ktr_sysret *, u_int); void ktrnamei(char *, int); void hexdump(char *, int, int); void visdump(char *, int, int); void ktrgenio(struct ktr_genio *, int); void ktrpsig(struct ktr_psig *); void ktrcsw(struct ktr_csw *); void ktrcsw_old(struct ktr_csw_old *); void ktruser(int, void *); void ktrcaprights(cap_rights_t *); void ktritimerval(struct itimerval *it); void ktrsockaddr(struct sockaddr *); void ktrstat(struct stat *); void ktrstruct(char *, size_t); void ktrcapfail(struct ktr_cap_fail *); void ktrfault(struct ktr_fault *); void ktrfaultend(struct ktr_faultend *); void usage(void); #define TIMESTAMP_NONE 0x0 #define TIMESTAMP_ABSOLUTE 0x1 #define TIMESTAMP_ELAPSED 0x2 #define TIMESTAMP_RELATIVE 0x4 -extern const char *signames[]; - static int timestamp, decimal, fancy = 1, suppressdata, tail, threads, maxdata, resolv = 0, abiflag = 0, syscallno = 0; static const char *tracefile = DEF_TRACEFILE; static struct ktr_header ktr_header; #define TIME_FORMAT "%b %e %T %Y" #define eqs(s1, s2) (strcmp((s1), (s2)) == 0) #define print_number64(first,i,n,c) do { \ uint64_t __v; \ \ if (quad_align && (((ptrdiff_t)((i) - (first))) & 1) == 1) { \ (i)++; \ (n)--; \ } \ if (quad_slots == 2) \ __v = (uint64_t)(uint32_t)(i)[0] | \ ((uint64_t)(uint32_t)(i)[1]) << 32; \ else \ __v = (uint64_t)*(i); \ if (decimal) \ printf("%c%jd", (c), (intmax_t)__v); \ else \ printf("%c%#jx", (c), (uintmax_t)__v); \ (i) += quad_slots; \ (n) -= quad_slots; \ (c) = ','; \ } while (0) #define print_number(i,n,c) do { \ if (decimal) \ printf("%c%jd", c, (intmax_t)*i); \ else \ printf("%c%#jx", c, (uintmax_t)(u_register_t)*i); \ i++; \ n--; \ c = ','; \ } while (0) struct proc_info { TAILQ_ENTRY(proc_info) info; u_int sv_flags; pid_t pid; }; static TAILQ_HEAD(trace_procs, proc_info) trace_procs; #ifdef HAVE_LIBCASPER static cap_channel_t *cappwd, *capgrp; #endif static void strerror_init(void) { /* * Cache NLS data before entering capability mode. * XXXPJD: There should be strerror_init() and strsignal_init() in libc. */ (void)catopen("libc", NL_CAT_LOCALE); } static void localtime_init(void) { time_t ltime; /* * Allow localtime(3) to cache /etc/localtime content before entering * capability mode. * XXXPJD: There should be localtime_init() in libc. */ (void)time(<ime); (void)localtime(<ime); } #ifdef HAVE_LIBCASPER static int cappwdgrp_setup(cap_channel_t **cappwdp, cap_channel_t **capgrpp) { cap_channel_t *capcas, *cappwdloc, *capgrploc; const char *cmds[1], *fields[1]; capcas = cap_init(); if (capcas == NULL) { err(1, "unable to create casper process"); exit(1); } cappwdloc = cap_service_open(capcas, "system.pwd"); capgrploc = cap_service_open(capcas, "system.grp"); /* Casper capability no longer needed. */ cap_close(capcas); if (cappwdloc == NULL || capgrploc == NULL) { if (cappwdloc == NULL) warn("unable to open system.pwd service"); if (capgrploc == NULL) warn("unable to open system.grp service"); exit(1); } /* Limit system.pwd to only getpwuid() function and pw_name field. */ cmds[0] = "getpwuid"; if (cap_pwd_limit_cmds(cappwdloc, cmds, 1) < 0) err(1, "unable to limit system.pwd service"); fields[0] = "pw_name"; if (cap_pwd_limit_fields(cappwdloc, fields, 1) < 0) err(1, "unable to limit system.pwd service"); /* Limit system.grp to only getgrgid() function and gr_name field. */ cmds[0] = "getgrgid"; if (cap_grp_limit_cmds(capgrploc, cmds, 1) < 0) err(1, "unable to limit system.grp service"); fields[0] = "gr_name"; if (cap_grp_limit_fields(capgrploc, fields, 1) < 0) err(1, "unable to limit system.grp service"); *cappwdp = cappwdloc; *capgrpp = capgrploc; return (0); } #endif /* HAVE_LIBCASPER */ +static void +print_integer_arg(const char *(*decoder)(int), int value) +{ + const char *str; + + str = decoder(value); + if (str != NULL) + printf("%s", str); + else { + if (decimal) + printf("", value); + else + printf("", value); + } +} + +/* Like print_integer_arg but unknown values are treated as valid. */ +static void +print_integer_arg_valid(const char *(*decoder)(int), int value) +{ + const char *str; + + str = decoder(value); + if (str != NULL) + printf("%s", str); + else { + if (decimal) + printf("%d", value); + else + printf("%#x", value); + } +} + +static void +print_mask_arg(bool (*decoder)(FILE *, int, int *), int value) +{ + bool invalid; + int rem; + + printf("%#x<", value); + invalid = !decoder(stdout, value, &rem); + printf(">"); + if (invalid) + printf("%u", rem); +} + +static void +print_mask_arg0(bool (*decoder)(FILE *, int, int *), int value) +{ + bool invalid; + int rem; + + if (value == 0) { + printf("0"); + return; + } + printf("%#x<", value); + invalid = !decoder(stdout, value, &rem); + printf(">"); + if (invalid) + printf("%u", rem); +} + +static void +decode_fileflags(fflags_t value) +{ + bool invalid; + fflags_t rem; + + if (value == 0) { + printf("0"); + return; + } + printf("%#x<", value); + invalid = !sysdecode_fileflags(stdout, value, &rem); + printf(">"); + if (invalid) + printf("%u", rem); +} + +static void +decode_filemode(int value) +{ + bool invalid; + int rem; + + if (value == 0) { + printf("0"); + return; + } + printf("%#o<", value); + invalid = !sysdecode_filemode(stdout, value, &rem); + printf(">"); + if (invalid) + printf("%u", rem); +} + +static void +print_mask_arg32(bool (*decoder)(FILE *, uint32_t, uint32_t *), uint32_t value) +{ + bool invalid; + uint32_t rem; + + printf("%#x<", value); + invalid = !decoder(stdout, value, &rem); + printf(">"); + if (invalid) + printf("%u", rem); +} + +static void +print_mask_argul(bool (*decoder)(FILE *, u_long, u_long *), u_long value) +{ + bool invalid; + u_long rem; + + if (value == 0) { + printf("0"); + return; + } + printf("%#lx<", value); + invalid = !decoder(stdout, value, &rem); + printf(">"); + if (invalid) + printf("%lu", rem); +} + int main(int argc, char *argv[]) { int ch, ktrlen, size; void *m; int trpoints = ALL_POINTS; int drop_logged; pid_t pid = 0; u_int sv_flags; setlocale(LC_CTYPE, ""); timestamp = TIMESTAMP_NONE; while ((ch = getopt(argc,argv,"f:dElm:np:AHRrSsTt:")) != -1) switch (ch) { case 'A': abiflag = 1; break; case 'f': tracefile = optarg; break; case 'd': decimal = 1; break; case 'l': tail = 1; break; case 'm': maxdata = atoi(optarg); break; case 'n': fancy = 0; break; case 'p': pid = atoi(optarg); break; case 'r': resolv = 1; break; case 'S': syscallno = 1; break; case 's': suppressdata = 1; break; case 'E': timestamp |= TIMESTAMP_ELAPSED; break; case 'H': threads = 1; break; case 'R': timestamp |= TIMESTAMP_RELATIVE; break; case 'T': timestamp |= TIMESTAMP_ABSOLUTE; break; case 't': trpoints = getpoints(optarg); if (trpoints < 0) errx(1, "unknown trace point in %s", optarg); break; default: usage(); } if (argc > optind) usage(); m = malloc(size = 1025); if (m == NULL) errx(1, "%s", strerror(ENOMEM)); if (strcmp(tracefile, "-") != 0) if (!freopen(tracefile, "r", stdin)) err(1, "%s", tracefile); strerror_init(); localtime_init(); #ifdef HAVE_LIBCASPER if (resolv != 0) { if (cappwdgrp_setup(&cappwd, &capgrp) < 0) { cappwd = NULL; capgrp = NULL; } } if (resolv == 0 || (cappwd != NULL && capgrp != NULL)) { if (cap_enter() < 0 && errno != ENOSYS) err(1, "unable to enter capability mode"); } #else if (resolv == 0) { if (cap_enter() < 0 && errno != ENOSYS) err(1, "unable to enter capability mode"); } #endif if (caph_limit_stdio() == -1) err(1, "unable to limit stdio"); TAILQ_INIT(&trace_procs); drop_logged = 0; while (fread_tail(&ktr_header, sizeof(struct ktr_header), 1)) { if (ktr_header.ktr_type & KTR_DROP) { ktr_header.ktr_type &= ~KTR_DROP; if (!drop_logged && threads) { printf( "%6jd %6jd %-8.*s Events dropped.\n", (intmax_t)ktr_header.ktr_pid, ktr_header.ktr_tid > 0 ? (intmax_t)ktr_header.ktr_tid : 0, MAXCOMLEN, ktr_header.ktr_comm); drop_logged = 1; } else if (!drop_logged) { printf("%6jd %-8.*s Events dropped.\n", (intmax_t)ktr_header.ktr_pid, MAXCOMLEN, ktr_header.ktr_comm); drop_logged = 1; } } if (trpoints & (1< size) { m = realloc(m, ktrlen+1); if (m == NULL) errx(1, "%s", strerror(ENOMEM)); size = ktrlen; } if (ktrlen && fread_tail(m, ktrlen, 1) == 0) errx(1, "data too short"); if (fetchprocinfo(&ktr_header, (u_int *)m) != 0) continue; sv_flags = abidump(&ktr_header); if (pid && ktr_header.ktr_pid != pid && ktr_header.ktr_tid != pid) continue; if ((trpoints & (1<ktr_type) { case KTR_PROCCTOR: TAILQ_FOREACH(pi, &trace_procs, info) { if (pi->pid == kth->ktr_pid) { TAILQ_REMOVE(&trace_procs, pi, info); break; } } pi = malloc(sizeof(struct proc_info)); if (pi == NULL) errx(1, "%s", strerror(ENOMEM)); pi->sv_flags = *flags; pi->pid = kth->ktr_pid; TAILQ_INSERT_TAIL(&trace_procs, pi, info); return (1); case KTR_PROCDTOR: TAILQ_FOREACH(pi, &trace_procs, info) { if (pi->pid == kth->ktr_pid) { TAILQ_REMOVE(&trace_procs, pi, info); free(pi); break; } } return (1); } return (0); } u_int abidump(struct ktr_header *kth) { struct proc_info *pi; const char *abi; const char *arch; u_int flags = 0; TAILQ_FOREACH(pi, &trace_procs, info) { if (pi->pid == kth->ktr_pid) { flags = pi->sv_flags; break; } } if (abiflag == 0) return (flags); switch (flags & SV_ABI_MASK) { case SV_ABI_LINUX: abi = "L"; break; case SV_ABI_FREEBSD: abi = "F"; break; case SV_ABI_CLOUDABI: abi = "C"; break; default: abi = "U"; break; } if (flags & SV_LP64) arch = "64"; else if (flags & SV_ILP32) arch = "32"; else arch = "00"; printf("%s%s ", abi, arch); return (flags); } void dumpheader(struct ktr_header *kth) { static char unknown[64]; static struct timeval prevtime, prevtime_e; struct timeval temp; const char *type; const char *sign; switch (kth->ktr_type) { case KTR_SYSCALL: type = "CALL"; break; case KTR_SYSRET: type = "RET "; break; case KTR_NAMEI: type = "NAMI"; break; case KTR_GENIO: type = "GIO "; break; case KTR_PSIG: type = "PSIG"; break; case KTR_CSW: type = "CSW "; break; case KTR_USER: type = "USER"; break; case KTR_STRUCT: type = "STRU"; break; case KTR_SYSCTL: type = "SCTL"; break; case KTR_PROCCTOR: /* FALLTHROUGH */ case KTR_PROCDTOR: return; case KTR_CAPFAIL: type = "CAP "; break; case KTR_FAULT: type = "PFLT"; break; case KTR_FAULTEND: type = "PRET"; break; default: sprintf(unknown, "UNKNOWN(%d)", kth->ktr_type); type = unknown; } /* * The ktr_tid field was previously the ktr_buffer field, which held * the kernel pointer value for the buffer associated with data * following the record header. It now holds a threadid, but only * for trace files after the change. Older trace files still contain * kernel pointers. Detect this and suppress the results by printing * negative tid's as 0. */ if (threads) printf("%6jd %6jd %-8.*s ", (intmax_t)kth->ktr_pid, kth->ktr_tid > 0 ? (intmax_t)kth->ktr_tid : 0, MAXCOMLEN, kth->ktr_comm); else printf("%6jd %-8.*s ", (intmax_t)kth->ktr_pid, MAXCOMLEN, kth->ktr_comm); if (timestamp) { if (timestamp & TIMESTAMP_ABSOLUTE) { printf("%jd.%06ld ", (intmax_t)kth->ktr_time.tv_sec, kth->ktr_time.tv_usec); } if (timestamp & TIMESTAMP_ELAPSED) { if (prevtime_e.tv_sec == 0) prevtime_e = kth->ktr_time; timersub(&kth->ktr_time, &prevtime_e, &temp); printf("%jd.%06ld ", (intmax_t)temp.tv_sec, temp.tv_usec); } if (timestamp & TIMESTAMP_RELATIVE) { if (prevtime.tv_sec == 0) prevtime = kth->ktr_time; if (timercmp(&kth->ktr_time, &prevtime, <)) { timersub(&prevtime, &kth->ktr_time, &temp); sign = "-"; } else { timersub(&kth->ktr_time, &prevtime, &temp); sign = ""; } prevtime = kth->ktr_time; printf("%s%jd.%06ld ", sign, (intmax_t)temp.tv_sec, temp.tv_usec); } } printf("%s ", type); } #include static void ioctlname(unsigned long val) { const char *str; str = sysdecode_ioctlname(val); if (str != NULL) printf("%s", str); else if (decimal) printf("%lu", val); else printf("%#lx", val); } static enum sysdecode_abi syscallabi(u_int sv_flags) { if (sv_flags == 0) return (SYSDECODE_ABI_FREEBSD); switch (sv_flags & SV_ABI_MASK) { case SV_ABI_FREEBSD: return (SYSDECODE_ABI_FREEBSD); #if defined(__amd64__) || defined(__i386__) case SV_ABI_LINUX: #ifdef __amd64__ if (sv_flags & SV_ILP32) return (SYSDECODE_ABI_LINUX32); #endif return (SYSDECODE_ABI_LINUX); #endif #if defined(__aarch64__) || defined(__amd64__) case SV_ABI_CLOUDABI: return (SYSDECODE_ABI_CLOUDABI64); #endif default: return (SYSDECODE_ABI_UNKNOWN); } } static void syscallname(u_int code, u_int sv_flags) { const char *name; name = sysdecode_syscallname(syscallabi(sv_flags), code); if (name == NULL) printf("[%d]", code); else { printf("%s", name); if (syscallno) printf("[%d]", code); } } +static void +print_signal(int signo) +{ + const char *signame; + + signame = sysdecode_signal(signo); + if (signame != NULL) + printf("%s", signame); + else + printf("SIG %d", signo); +} + void ktrsyscall(struct ktr_syscall *ktr, u_int sv_flags) { int narg = ktr->ktr_narg; register_t *ip, *first; intmax_t arg; int quad_align, quad_slots; syscallname(ktr->ktr_code, sv_flags); ip = first = &ktr->ktr_args[0]; if (narg) { char c = '('; if (fancy && (sv_flags == 0 || (sv_flags & SV_ABI_MASK) == SV_ABI_FREEBSD)) { quad_align = 0; if (sv_flags & SV_ILP32) { #ifdef __powerpc__ quad_align = 1; #endif quad_slots = 2; } else quad_slots = 1; switch (ktr->ktr_code) { case SYS_bindat: case SYS_connectat: case SYS_faccessat: case SYS_fchmodat: case SYS_fchownat: case SYS_fstatat: case SYS_futimesat: case SYS_linkat: case SYS_mkdirat: case SYS_mkfifoat: case SYS_mknodat: case SYS_openat: case SYS_readlinkat: case SYS_renameat: case SYS_unlinkat: case SYS_utimensat: putchar('('); - atfdname(*ip, decimal); + print_integer_arg_valid(sysdecode_atfd, *ip); c = ','; ip++; narg--; break; } switch (ktr->ktr_code) { case SYS_ioctl: { print_number(ip, narg, c); putchar(c); ioctlname(*ip); c = ','; ip++; narg--; break; } case SYS_ptrace: putchar('('); - ptraceopname(*ip); + print_integer_arg(sysdecode_ptrace_request, *ip); c = ','; ip++; narg--; break; case SYS_access: case SYS_eaccess: case SYS_faccessat: print_number(ip, narg, c); putchar(','); - accessmodename(*ip); + print_mask_arg(sysdecode_access_mode, *ip); ip++; narg--; break; case SYS_open: case SYS_openat: print_number(ip, narg, c); putchar(','); - flagsandmodename(ip[0], ip[1], decimal); + print_mask_arg(sysdecode_open_flags, ip[0]); + if ((ip[0] & O_CREAT) == O_CREAT) { + putchar(','); + decode_filemode(ip[1]); + } ip += 2; narg -= 2; break; case SYS_wait4: print_number(ip, narg, c); print_number(ip, narg, c); - /* - * A flags value of zero is valid for - * wait4() but not for wait6(), so - * handle zero special here. - */ - if (*ip == 0) { - print_number(ip, narg, c); - } else { - putchar(','); - wait6optname(*ip); - ip++; - narg--; - } + putchar(','); + print_mask_arg0(sysdecode_wait4_options, *ip); + ip++; + narg--; break; case SYS_wait6: putchar('('); - idtypename(*ip, decimal); + print_integer_arg(sysdecode_idtype, *ip); c = ','; ip++; narg--; print_number64(first, ip, narg, c); print_number(ip, narg, c); putchar(','); - wait6optname(*ip); + print_mask_arg(sysdecode_wait6_options, *ip); ip++; narg--; break; case SYS_chmod: case SYS_fchmod: case SYS_lchmod: case SYS_fchmodat: print_number(ip, narg, c); putchar(','); - modename(*ip); + decode_filemode(*ip); ip++; narg--; break; case SYS_mknod: case SYS_mknodat: print_number(ip, narg, c); putchar(','); - modename(*ip); + decode_filemode(*ip); ip++; narg--; break; case SYS_getfsstat: print_number(ip, narg, c); print_number(ip, narg, c); putchar(','); - getfsstatflagsname(*ip); + print_mask_arg(sysdecode_getfsstat_flags, *ip); ip++; narg--; break; case SYS_mount: print_number(ip, narg, c); print_number(ip, narg, c); putchar(','); - mountflagsname(*ip); + print_mask_arg(sysdecode_mount_flags, *ip); ip++; narg--; break; case SYS_unmount: print_number(ip, narg, c); putchar(','); - mountflagsname(*ip); + print_mask_arg(sysdecode_mount_flags, *ip); ip++; narg--; break; case SYS_recvmsg: case SYS_sendmsg: print_number(ip, narg, c); print_number(ip, narg, c); putchar(','); - sendrecvflagsname(*ip); + print_mask_arg0(sysdecode_msg_flags, *ip); ip++; narg--; break; case SYS_recvfrom: case SYS_sendto: print_number(ip, narg, c); print_number(ip, narg, c); print_number(ip, narg, c); putchar(','); - sendrecvflagsname(*ip); + print_mask_arg0(sysdecode_msg_flags, *ip); ip++; narg--; break; case SYS_chflags: case SYS_fchflags: case SYS_lchflags: print_number(ip, narg, c); putchar(','); - modename(*ip); + decode_fileflags(*ip); ip++; narg--; break; case SYS_kill: print_number(ip, narg, c); putchar(','); - signame(*ip); + print_signal(*ip); ip++; narg--; break; case SYS_reboot: putchar('('); - rebootoptname(*ip); + print_mask_arg(sysdecode_reboot_howto, *ip); ip++; narg--; break; case SYS_umask: putchar('('); - modename(*ip); + decode_filemode(*ip); ip++; narg--; break; case SYS_msync: print_number(ip, narg, c); print_number(ip, narg, c); putchar(','); - msyncflagsname(*ip); + print_mask_arg(sysdecode_msync_flags, *ip); ip++; narg--; break; #ifdef SYS_freebsd6_mmap case SYS_freebsd6_mmap: print_number(ip, narg, c); print_number(ip, narg, c); putchar(','); - mmapprotname(*ip); + print_mask_arg(sysdecode_mmap_prot, *ip); putchar(','); ip++; narg--; - mmapflagsname(*ip); + print_mask_arg(sysdecode_mmap_flags, *ip); ip++; narg--; break; #endif case SYS_mmap: print_number(ip, narg, c); print_number(ip, narg, c); putchar(','); - mmapprotname(*ip); + print_mask_arg(sysdecode_mmap_prot, *ip); putchar(','); ip++; narg--; - mmapflagsname(*ip); + print_mask_arg(sysdecode_mmap_flags, *ip); ip++; narg--; break; case SYS_mprotect: print_number(ip, narg, c); print_number(ip, narg, c); putchar(','); - mmapprotname(*ip); + print_mask_arg(sysdecode_mmap_prot, *ip); ip++; narg--; break; case SYS_madvise: print_number(ip, narg, c); print_number(ip, narg, c); putchar(','); - madvisebehavname(*ip); + print_integer_arg(sysdecode_madvice, *ip); ip++; narg--; break; case SYS_setpriority: print_number(ip, narg, c); print_number(ip, narg, c); putchar(','); - prioname(*ip); + print_integer_arg(sysdecode_prio_which, *ip); ip++; narg--; break; case SYS_fcntl: print_number(ip, narg, c); putchar(','); - fcntlcmdname(ip[0], ip[1], decimal); + print_integer_arg(sysdecode_fcntl_cmd, ip[0]); + if (sysdecode_fcntl_arg_p(ip[0])) { + putchar(','); + if (ip[0] == F_SETFL) + print_mask_arg( + sysdecode_fcntl_fileflags, + ip[1]); + else + sysdecode_fcntl_arg(stdout, + ip[0], ip[1], + decimal ? 10 : 16); + } ip += 2; narg -= 2; break; case SYS_socket: { int sockdomain; putchar('('); sockdomain = *ip; - sockdomainname(sockdomain); + print_integer_arg(sysdecode_socketdomain, + sockdomain); ip++; narg--; putchar(','); - socktypenamewithflags(*ip); + print_mask_arg(sysdecode_socket_type, *ip); ip++; narg--; if (sockdomain == PF_INET || sockdomain == PF_INET6) { putchar(','); - sockipprotoname(*ip); + print_integer_arg(sysdecode_ipproto, + *ip); ip++; narg--; } c = ','; break; } case SYS_setsockopt: - case SYS_getsockopt: + case SYS_getsockopt: { + const char *str; + print_number(ip, narg, c); putchar(','); - sockoptlevelname(*ip, decimal); - if (*ip == SOL_SOCKET) { + print_integer_arg_valid(sysdecode_sockopt_level, + *ip); + str = sysdecode_sockopt_name(ip[0], ip[1]); + if (str != NULL) { + printf(",%s", str); ip++; narg--; - putchar(','); - sockoptname(*ip); } ip++; narg--; break; + } #ifdef SYS_freebsd6_lseek case SYS_freebsd6_lseek: print_number(ip, narg, c); /* Hidden 'pad' argument, not in lseek(2) */ print_number(ip, narg, c); print_number64(first, ip, narg, c); putchar(','); - whencename(*ip); + print_integer_arg(sysdecode_whence, *ip); ip++; narg--; break; #endif case SYS_lseek: print_number(ip, narg, c); print_number64(first, ip, narg, c); putchar(','); - whencename(*ip); + print_integer_arg(sysdecode_whence, *ip); ip++; narg--; break; case SYS_flock: print_number(ip, narg, c); putchar(','); - flockname(*ip); + print_mask_arg(sysdecode_flock_operation, *ip); ip++; narg--; break; case SYS_mkfifo: case SYS_mkfifoat: case SYS_mkdir: case SYS_mkdirat: print_number(ip, narg, c); putchar(','); - modename(*ip); + decode_filemode(*ip); ip++; narg--; break; case SYS_shutdown: print_number(ip, narg, c); putchar(','); - shutdownhowname(*ip); + print_integer_arg(sysdecode_shutdown_how, *ip); ip++; narg--; break; case SYS_socketpair: putchar('('); - sockdomainname(*ip); + print_integer_arg(sysdecode_socketdomain, *ip); ip++; narg--; putchar(','); - socktypenamewithflags(*ip); + print_mask_arg(sysdecode_socket_type, *ip); ip++; narg--; c = ','; break; case SYS_getrlimit: case SYS_setrlimit: putchar('('); - rlimitname(*ip); + print_integer_arg(sysdecode_rlimit, *ip); ip++; narg--; c = ','; break; case SYS_quotactl: print_number(ip, narg, c); putchar(','); - quotactlname(*ip); + if (!sysdecode_quotactl_cmd(stdout, *ip)) { + if (decimal) + printf("", (int)*ip); + else + printf("", + (int)*ip); + } ip++; narg--; c = ','; break; case SYS_nfssvc: putchar('('); - nfssvcname(*ip); + print_integer_arg(sysdecode_nfssvc_flags, *ip); ip++; narg--; c = ','; break; case SYS_rtprio: putchar('('); - rtprioname(*ip); + print_integer_arg(sysdecode_rtprio_function, + *ip); ip++; narg--; c = ','; break; case SYS___semctl: print_number(ip, narg, c); print_number(ip, narg, c); putchar(','); - semctlname(*ip); + print_integer_arg(sysdecode_semctl_cmd, *ip); ip++; narg--; break; case SYS_semget: print_number(ip, narg, c); print_number(ip, narg, c); putchar(','); - semgetname(*ip); + print_mask_arg(sysdecode_semget_flags, *ip); ip++; narg--; break; case SYS_msgctl: print_number(ip, narg, c); putchar(','); - shmctlname(*ip); + print_integer_arg(sysdecode_msgctl_cmd, *ip); ip++; narg--; break; case SYS_shmat: print_number(ip, narg, c); print_number(ip, narg, c); putchar(','); - shmatname(*ip); + print_mask_arg(sysdecode_shmat_flags, *ip); ip++; narg--; break; case SYS_shmctl: print_number(ip, narg, c); putchar(','); - shmctlname(*ip); + print_integer_arg(sysdecode_shmctl_cmd, *ip); ip++; narg--; break; case SYS_shm_open: print_number(ip, narg, c); putchar(','); - flagsname(ip[0]); - printf(",0%o", (unsigned int)ip[1]); - ip += 3; - narg -= 3; + print_mask_arg(sysdecode_open_flags, ip[0]); + putchar(','); + decode_filemode(ip[1]); + ip += 2; + narg -= 2; break; case SYS_minherit: print_number(ip, narg, c); print_number(ip, narg, c); putchar(','); - minheritname(*ip); + print_integer_arg(sysdecode_minherit_inherit, + *ip); ip++; narg--; break; case SYS_rfork: putchar('('); - rforkname(*ip); + print_mask_arg(sysdecode_rfork_flags, *ip); ip++; narg--; c = ','; break; case SYS_lio_listio: putchar('('); - lio_listioname(*ip); + print_integer_arg(sysdecode_lio_listio_mode, + *ip); ip++; narg--; c = ','; break; case SYS_mlockall: putchar('('); - mlockallname(*ip); + print_mask_arg(sysdecode_mlockall_flags, *ip); ip++; narg--; break; case SYS_sched_setscheduler: print_number(ip, narg, c); putchar(','); - schedpolicyname(*ip); + print_integer_arg(sysdecode_scheduler_policy, + *ip); ip++; narg--; break; case SYS_sched_get_priority_max: case SYS_sched_get_priority_min: putchar('('); - schedpolicyname(*ip); + print_integer_arg(sysdecode_scheduler_policy, + *ip); ip++; narg--; break; case SYS_sendfile: print_number(ip, narg, c); print_number(ip, narg, c); print_number(ip, narg, c); print_number(ip, narg, c); print_number(ip, narg, c); print_number(ip, narg, c); putchar(','); - sendfileflagsname(*(int *)ip); + print_mask_arg(sysdecode_sendfile_flags, *ip); ip++; narg--; break; case SYS_kldsym: print_number(ip, narg, c); putchar(','); - kldsymcmdname(*ip); + print_integer_arg(sysdecode_kldsym_cmd, *ip); ip++; narg--; break; case SYS_sigprocmask: putchar('('); - sigprocmaskhowname(*ip); + print_integer_arg(sysdecode_sigprocmask_how, + *ip); ip++; narg--; c = ','; break; case SYS___acl_get_file: case SYS___acl_set_file: case SYS___acl_get_fd: case SYS___acl_set_fd: case SYS___acl_delete_file: case SYS___acl_delete_fd: case SYS___acl_aclcheck_file: case SYS___acl_aclcheck_fd: case SYS___acl_get_link: case SYS___acl_set_link: case SYS___acl_delete_link: case SYS___acl_aclcheck_link: print_number(ip, narg, c); putchar(','); - acltypename(*ip); + print_integer_arg(sysdecode_acltype, *ip); ip++; narg--; break; case SYS_sigaction: putchar('('); - signame(*ip); + print_signal(*ip); ip++; narg--; c = ','; break; case SYS_extattrctl: print_number(ip, narg, c); putchar(','); - extattrctlname(*ip); + print_integer_arg(sysdecode_extattrnamespace, + *ip); ip++; narg--; break; case SYS_nmount: print_number(ip, narg, c); print_number(ip, narg, c); putchar(','); - mountflagsname(*ip); + print_mask_arg(sysdecode_mount_flags, *ip); ip++; narg--; break; case SYS_thr_create: print_number(ip, narg, c); print_number(ip, narg, c); putchar(','); - thrcreateflagsname(*ip); + print_mask_arg(sysdecode_thr_create_flags, *ip); ip++; narg--; break; case SYS_thr_kill: print_number(ip, narg, c); putchar(','); - signame(*ip); + print_signal(*ip); ip++; narg--; break; case SYS_kldunloadf: print_number(ip, narg, c); putchar(','); - kldunloadfflagsname(*ip); + print_integer_arg(sysdecode_kldunload_flags, + *ip); ip++; narg--; break; case SYS_linkat: case SYS_renameat: case SYS_symlinkat: print_number(ip, narg, c); putchar(','); - atfdname(*ip, decimal); + print_integer_arg_valid(sysdecode_atfd, *ip); ip++; narg--; break; case SYS_cap_fcntls_limit: print_number(ip, narg, c); putchar(','); arg = *ip; ip++; narg--; - capfcntlname(arg); + print_mask_arg32(sysdecode_cap_fcntlrights, arg); break; case SYS_posix_fadvise: print_number(ip, narg, c); print_number(ip, narg, c); print_number(ip, narg, c); (void)putchar(','); - fadvisebehavname((int)*ip); + print_integer_arg(sysdecode_fadvice, *ip); ip++; narg--; break; case SYS_procctl: putchar('('); - idtypename(*ip, decimal); + print_integer_arg(sysdecode_idtype, *ip); c = ','; ip++; narg--; print_number64(first, ip, narg, c); putchar(','); - procctlcmdname(*ip); + print_integer_arg(sysdecode_procctl_cmd, *ip); ip++; narg--; break; case SYS__umtx_op: print_number(ip, narg, c); putchar(','); - umtxopname(*ip); + print_integer_arg(sysdecode_umtx_op, *ip); switch (*ip) { case UMTX_OP_CV_WAIT: ip++; narg--; putchar(','); - umtxcvwaitflags(*ip); + print_mask_argul( + sysdecode_umtx_cvwait_flags, *ip); break; case UMTX_OP_RW_RDLOCK: ip++; narg--; putchar(','); - umtxrwlockflags(*ip); + print_mask_argul( + sysdecode_umtx_rwlock_flags, *ip); break; } ip++; narg--; break; case SYS_ftruncate: case SYS_truncate: print_number(ip, narg, c); print_number64(first, ip, narg, c); break; } } while (narg > 0) { print_number(ip, narg, c); } putchar(')'); } putchar('\n'); } void ktrsysret(struct ktr_sysret *ktr, u_int sv_flags) { register_t ret = ktr->ktr_retval; int error = ktr->ktr_error; syscallname(ktr->ktr_code, sv_flags); printf(" "); if (error == 0) { if (fancy) { printf("%ld", (long)ret); if (ret < 0 || ret > 9) printf("/%#lx", (unsigned long)ret); } else { if (decimal) printf("%ld", (long)ret); else printf("%#lx", (unsigned long)ret); } } else if (error == ERESTART) printf("RESTART"); else if (error == EJUSTRETURN) printf("JUSTRETURN"); else { printf("-1 errno %d", sysdecode_freebsd_to_abi_errno( syscallabi(sv_flags), error)); if (fancy) printf(" %s", strerror(ktr->ktr_error)); } putchar('\n'); } void ktrnamei(char *cp, int len) { printf("\"%.*s\"\n", len, cp); } void hexdump(char *p, int len, int screenwidth) { int n, i; int width; width = 0; do { width += 2; i = 13; /* base offset */ i += (width / 2) + 1; /* spaces every second byte */ i += (width * 2); /* width of bytes */ i += 3; /* " |" */ i += width; /* each byte */ i += 1; /* "|" */ } while (i < screenwidth); width -= 2; for (n = 0; n < len; n += width) { for (i = n; i < n + width; i++) { if ((i % width) == 0) { /* beginning of line */ printf(" 0x%04x", i); } if ((i % 2) == 0) { printf(" "); } if (i < len) printf("%02x", p[i] & 0xff); else printf(" "); } printf(" |"); for (i = n; i < n + width; i++) { if (i >= len) break; if (p[i] >= ' ' && p[i] <= '~') printf("%c", p[i]); else printf("."); } printf("|\n"); } if ((i % width) != 0) printf("\n"); } void visdump(char *dp, int datalen, int screenwidth) { int col = 0; char *cp; int width; char visbuf[5]; printf(" \""); col = 8; for (;datalen > 0; datalen--, dp++) { vis(visbuf, *dp, VIS_CSTYLE, *(dp+1)); cp = visbuf; /* * Keep track of printables and * space chars (like fold(1)). */ if (col == 0) { putchar('\t'); col = 8; } switch(*cp) { case '\n': col = 0; putchar('\n'); continue; case '\t': width = 8 - (col&07); break; default: width = strlen(cp); } if (col + width > (screenwidth-2)) { printf("\\\n\t"); col = 8; } col += width; do { putchar(*cp++); } while (*cp); } if (col == 0) printf(" "); printf("\"\n"); } void ktrgenio(struct ktr_genio *ktr, int len) { int datalen = len - sizeof (struct ktr_genio); char *dp = (char *)ktr + sizeof (struct ktr_genio); static int screenwidth = 0; int i, binary; printf("fd %d %s %d byte%s\n", ktr->ktr_fd, ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen, datalen == 1 ? "" : "s"); if (suppressdata) return; if (screenwidth == 0) { struct winsize ws; if (fancy && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 && ws.ws_col > 8) screenwidth = ws.ws_col; else screenwidth = 80; } if (maxdata && datalen > maxdata) datalen = maxdata; for (i = 0, binary = 0; i < datalen && binary == 0; i++) { if (dp[i] >= 32 && dp[i] < 127) continue; if (dp[i] == 10 || dp[i] == 13 || dp[i] == 0 || dp[i] == 9) continue; binary = 1; } if (binary) hexdump(dp, datalen, screenwidth); else visdump(dp, datalen, screenwidth); } -const char *signames[] = { - "NULL", "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT", /* 1 - 6 */ - "EMT", "FPE", "KILL", "BUS", "SEGV", "SYS", /* 7 - 12 */ - "PIPE", "ALRM", "TERM", "URG", "STOP", "TSTP", /* 13 - 18 */ - "CONT", "CHLD", "TTIN", "TTOU", "IO", "XCPU", /* 19 - 24 */ - "XFSZ", "VTALRM", "PROF", "WINCH", "29", "USR1", /* 25 - 30 */ - "USR2", NULL, /* 31 - 32 */ -}; - void ktrpsig(struct ktr_psig *psig) { - if (psig->signo > 0 && psig->signo < NSIG) - printf("SIG%s ", signames[psig->signo]); - else - printf("SIG %d ", psig->signo); + const char *str; + + print_signal(psig->signo); if (psig->action == SIG_DFL) { - printf("SIG_DFL code="); - sigcodename(psig->signo, psig->code); - putchar('\n'); + printf(" SIG_DFL"); } else { - printf("caught handler=0x%lx mask=0x%x code=", + printf(" caught handler=0x%lx mask=0x%x", (u_long)psig->action, psig->mask.__bits[0]); - sigcodename(psig->signo, psig->code); - putchar('\n'); } + printf(" code="); + str = sysdecode_sigcode(psig->signo, psig->code); + if (str != NULL) + printf("%s", str); + else + printf("", psig->code); + putchar('\n'); } void ktrcsw_old(struct ktr_csw_old *cs) { printf("%s %s\n", cs->out ? "stop" : "resume", cs->user ? "user" : "kernel"); } void ktrcsw(struct ktr_csw *cs) { printf("%s %s \"%s\"\n", cs->out ? "stop" : "resume", cs->user ? "user" : "kernel", cs->wmesg); } void ktruser(int len, void *p) { unsigned char *cp; if (sysdecode_utrace(stdout, p, len)) { printf("\n"); return; } printf("%d ", len); cp = p; while (len--) if (decimal) printf(" %d", *cp++); else printf(" %02x", *cp++); printf("\n"); } void ktrcaprights(cap_rights_t *rightsp) { printf("cap_rights_t "); - capname(rightsp); + sysdecode_cap_rights(stdout, rightsp); printf("\n"); } static void ktrtimeval(struct timeval *tv) { printf("{%ld, %ld}", (long)tv->tv_sec, tv->tv_usec); } void ktritimerval(struct itimerval *it) { printf("itimerval { .interval = "); ktrtimeval(&it->it_interval); printf(", .value = "); ktrtimeval(&it->it_value); printf(" }\n"); } void ktrsockaddr(struct sockaddr *sa) { /* TODO: Support additional address families #include struct sockaddr_natm *natm; #include struct sockaddr_nb *nb; */ + const char *str; char addr[64]; /* * note: ktrstruct() has already verified that sa points to a * buffer at least sizeof(struct sockaddr) bytes long and exactly * sa->sa_len bytes long. */ printf("struct sockaddr { "); - sockfamilyname(sa->sa_family); + str = sysdecode_sockaddr_family(sa->sa_family); + if (str != NULL) + printf("%s", str); + else + printf("", sa->sa_family); printf(", "); #define check_sockaddr_len(n) \ if (sa_##n.s##n##_len < sizeof(struct sockaddr_##n)) { \ printf("invalid"); \ break; \ } switch(sa->sa_family) { case AF_INET: { struct sockaddr_in sa_in; memset(&sa_in, 0, sizeof(sa_in)); memcpy(&sa_in, sa, sa->sa_len); check_sockaddr_len(in); inet_ntop(AF_INET, &sa_in.sin_addr, addr, sizeof addr); printf("%s:%u", addr, ntohs(sa_in.sin_port)); break; } case AF_INET6: { struct sockaddr_in6 sa_in6; memset(&sa_in6, 0, sizeof(sa_in6)); memcpy(&sa_in6, sa, sa->sa_len); check_sockaddr_len(in6); getnameinfo((struct sockaddr *)&sa_in6, sizeof(sa_in6), addr, sizeof(addr), NULL, 0, NI_NUMERICHOST); printf("[%s]:%u", addr, htons(sa_in6.sin6_port)); break; } case AF_UNIX: { struct sockaddr_un sa_un; memset(&sa_un, 0, sizeof(sa_un)); memcpy(&sa_un, sa, sa->sa_len); printf("%.*s", (int)sizeof(sa_un.sun_path), sa_un.sun_path); break; } default: printf("unknown address family"); } printf(" }\n"); } void ktrstat(struct stat *statp) { char mode[12], timestr[PATH_MAX + 4]; struct passwd *pwd; struct group *grp; struct tm *tm; /* * note: ktrstruct() has already verified that statp points to a * buffer exactly sizeof(struct stat) bytes long. */ printf("struct stat {"); printf("dev=%ju, ino=%ju, ", (uintmax_t)statp->st_dev, (uintmax_t)statp->st_ino); if (resolv == 0) printf("mode=0%jo, ", (uintmax_t)statp->st_mode); else { strmode(statp->st_mode, mode); printf("mode=%s, ", mode); } printf("nlink=%ju, ", (uintmax_t)statp->st_nlink); if (resolv == 0) { pwd = NULL; } else { #ifdef HAVE_LIBCASPER if (cappwd != NULL) pwd = cap_getpwuid(cappwd, statp->st_uid); else #endif pwd = getpwuid(statp->st_uid); } if (pwd == NULL) printf("uid=%ju, ", (uintmax_t)statp->st_uid); else printf("uid=\"%s\", ", pwd->pw_name); if (resolv == 0) { grp = NULL; } else { #ifdef HAVE_LIBCASPER if (capgrp != NULL) grp = cap_getgrgid(capgrp, statp->st_gid); else #endif grp = getgrgid(statp->st_gid); } if (grp == NULL) printf("gid=%ju, ", (uintmax_t)statp->st_gid); else printf("gid=\"%s\", ", grp->gr_name); printf("rdev=%ju, ", (uintmax_t)statp->st_rdev); printf("atime="); if (resolv == 0) printf("%jd", (intmax_t)statp->st_atim.tv_sec); else { tm = localtime(&statp->st_atim.tv_sec); strftime(timestr, sizeof(timestr), TIME_FORMAT, tm); printf("\"%s\"", timestr); } if (statp->st_atim.tv_nsec != 0) printf(".%09ld, ", statp->st_atim.tv_nsec); else printf(", "); printf("mtime="); if (resolv == 0) printf("%jd", (intmax_t)statp->st_mtim.tv_sec); else { tm = localtime(&statp->st_mtim.tv_sec); strftime(timestr, sizeof(timestr), TIME_FORMAT, tm); printf("\"%s\"", timestr); } if (statp->st_mtim.tv_nsec != 0) printf(".%09ld, ", statp->st_mtim.tv_nsec); else printf(", "); printf("ctime="); if (resolv == 0) printf("%jd", (intmax_t)statp->st_ctim.tv_sec); else { tm = localtime(&statp->st_ctim.tv_sec); strftime(timestr, sizeof(timestr), TIME_FORMAT, tm); printf("\"%s\"", timestr); } if (statp->st_ctim.tv_nsec != 0) printf(".%09ld, ", statp->st_ctim.tv_nsec); else printf(", "); printf("birthtime="); if (resolv == 0) printf("%jd", (intmax_t)statp->st_birthtim.tv_sec); else { tm = localtime(&statp->st_birthtim.tv_sec); strftime(timestr, sizeof(timestr), TIME_FORMAT, tm); printf("\"%s\"", timestr); } if (statp->st_birthtim.tv_nsec != 0) printf(".%09ld, ", statp->st_birthtim.tv_nsec); else printf(", "); printf("size=%jd, blksize=%ju, blocks=%jd, flags=0x%x", (uintmax_t)statp->st_size, (uintmax_t)statp->st_blksize, (intmax_t)statp->st_blocks, statp->st_flags); printf(" }\n"); } void ktrstruct(char *buf, size_t buflen) { char *name, *data; size_t namelen, datalen; int i; cap_rights_t rights; struct itimerval it; struct stat sb; struct sockaddr_storage ss; for (name = buf, namelen = 0; namelen < buflen && name[namelen] != '\0'; ++namelen) /* nothing */; if (namelen == buflen) goto invalid; if (name[namelen] != '\0') goto invalid; data = buf + namelen + 1; datalen = buflen - namelen - 1; if (datalen == 0) goto invalid; /* sanity check */ for (i = 0; i < (int)namelen; ++i) if (!isalpha(name[i])) goto invalid; if (strcmp(name, "caprights") == 0) { if (datalen != sizeof(cap_rights_t)) goto invalid; memcpy(&rights, data, datalen); ktrcaprights(&rights); } else if (strcmp(name, "itimerval") == 0) { if (datalen != sizeof(struct itimerval)) goto invalid; memcpy(&it, data, datalen); ktritimerval(&it); } else if (strcmp(name, "stat") == 0) { if (datalen != sizeof(struct stat)) goto invalid; memcpy(&sb, data, datalen); ktrstat(&sb); } else if (strcmp(name, "sockaddr") == 0) { if (datalen > sizeof(ss)) goto invalid; memcpy(&ss, data, datalen); if (datalen != ss.ss_len) goto invalid; ktrsockaddr((struct sockaddr *)&ss); } else { printf("unknown structure\n"); } return; invalid: printf("invalid record\n"); } void ktrcapfail(struct ktr_cap_fail *ktr) { switch (ktr->cap_type) { case CAPFAIL_NOTCAPABLE: /* operation on fd with insufficient capabilities */ printf("operation requires "); - capname(&ktr->cap_needed); + sysdecode_cap_rights(stdout, &ktr->cap_needed); printf(", descriptor holds "); - capname(&ktr->cap_held); + sysdecode_cap_rights(stdout, &ktr->cap_held); break; case CAPFAIL_INCREASE: /* requested more capabilities than fd already has */ printf("attempt to increase capabilities from "); - capname(&ktr->cap_held); + sysdecode_cap_rights(stdout, &ktr->cap_held); printf(" to "); - capname(&ktr->cap_needed); + sysdecode_cap_rights(stdout, &ktr->cap_needed); break; case CAPFAIL_SYSCALL: /* called restricted syscall */ printf("disallowed system call"); break; case CAPFAIL_LOOKUP: /* used ".." in strict-relative mode */ printf("restricted VFS lookup"); break; default: printf("unknown capability failure: "); - capname(&ktr->cap_needed); + sysdecode_cap_rights(stdout, &ktr->cap_needed); printf(" "); - capname(&ktr->cap_held); + sysdecode_cap_rights(stdout, &ktr->cap_held); break; } printf("\n"); } void ktrfault(struct ktr_fault *ktr) { printf("0x%jx ", (uintmax_t)ktr->vaddr); - vmprotname(ktr->type); + print_mask_arg(sysdecode_vmprot, ktr->type); printf("\n"); } void ktrfaultend(struct ktr_faultend *ktr) { + const char *str; - vmresultname(ktr->result); + str = sysdecode_vmresult(ktr->result); + if (str != NULL) + printf("%s", str); + else + printf("", ktr->result); printf("\n"); } void usage(void) { fprintf(stderr, "usage: kdump [-dEnlHRrSsTA] [-f trfile] " "[-m maxdata] [-p pid] [-t trstr]\n"); exit(1); } Index: head/usr.bin/truss/Makefile =================================================================== --- head/usr.bin/truss/Makefile (revision 307537) +++ head/usr.bin/truss/Makefile (revision 307538) @@ -1,42 +1,43 @@ # $FreeBSD$ -NO_WERROR= +#NO_WERROR= PROG= truss SRCS= main.c setup.c syscalls.c LIBADD= sysdecode -CFLAGS+= -I${.CURDIR} -I. -I${.CURDIR}/../../sys +#CFLAGS+= -I${.CURDIR} -I. -I${.CURDIR}/../../sys +CFLAGS+= -I${.CURDIR}/../../sys ABIS+= freebsd # Each ABI is expected to have an ABI.c, MACHINE_ARCH-ABI.c or # MACHINE_CPUARCH-ABI.c file that will be used to map the syscall arguments. .if ${MACHINE_ARCH} == "aarch64" ABIS+= cloudabi64 .endif .if ${MACHINE_CPUARCH} == "i386" ABIS+= i386-linux .endif .if ${MACHINE_CPUARCH} == "amd64" ABIS+= amd64-linux ABIS+= amd64-linux32 ABIS+= freebsd32 ABIS+= cloudabi64 .endif .if ${MACHINE_ARCH} == "powerpc64" ABIS+= freebsd32 .endif .for abi in ${ABIS} # Find the right file to handle this ABI. abi_src= ABI_SRCS= ${abi}.c ${MACHINE_ARCH}-${abi}.c ${MACHINE_CPUARCH}-${abi}.c .for f in ${ABI_SRCS} .if exists(${.CURDIR}/${f}) && empty(abi_src) abi_src= ${f} .endif .endfor SRCS:= ${SRCS} ${abi_src} .endfor .include Index: head/usr.bin/truss/aarch64-cloudabi64.c =================================================================== --- head/usr.bin/truss/aarch64-cloudabi64.c (revision 307537) +++ head/usr.bin/truss/aarch64-cloudabi64.c (revision 307538) @@ -1,85 +1,86 @@ /*- * Copyright (c) 2015 Nuxi, https://nuxi.nl/ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include "truss.h" static int aarch64_cloudabi64_fetch_args(struct trussinfo *trussinfo, unsigned int narg) { struct current_syscall *cs; struct reg regs; lwpid_t tid; unsigned int i; tid = trussinfo->curthread->tid; if (ptrace(PT_GETREGS, tid, (caddr_t)®s, 0) == -1) { fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); return (-1); } cs = &trussinfo->curthread->cs; for (i = 0; i < narg && i < 8; i++) cs->args[i] = regs.x[i]; return (0); } static int aarch64_cloudabi64_fetch_retval(struct trussinfo *trussinfo, long *retval, int *errorp) { struct reg regs; lwpid_t tid; tid = trussinfo->curthread->tid; if (ptrace(PT_GETREGS, tid, (caddr_t)®s, 0) == -1) { fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); return (-1); } retval[0] = regs.x[0]; retval[1] = regs.x[1]; *errorp = (regs.spsr & PSR_C) != 0; return (0); } static struct procabi aarch64_cloudabi64 = { "CloudABI ELF64", SYSDECODE_ABI_CLOUDABI64, aarch64_cloudabi64_fetch_args, aarch64_cloudabi64_fetch_retval }; PROCABI(aarch64_cloudabi64); Index: head/usr.bin/truss/aarch64-freebsd.c =================================================================== --- head/usr.bin/truss/aarch64-freebsd.c (revision 307537) +++ head/usr.bin/truss/aarch64-freebsd.c (revision 307538) @@ -1,107 +1,108 @@ /* * Copyright (c) 2015 The FreeBSD Foundation * * Portions of this software were developed by Konstantin Belousov * under sponsorship from the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* FreeBSD/arm64-specific system call handling. */ #include #include #include #include #include +#include #include #include #include "truss.h" static int aarch64_fetch_args(struct trussinfo *trussinfo, u_int narg) { struct reg regs; struct current_syscall *cs; lwpid_t tid; u_int i, reg, syscall_num; tid = trussinfo->curthread->tid; cs = &trussinfo->curthread->cs; if (ptrace(PT_GETREGS, tid, (caddr_t)®s, 0) < 0) { fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); return (-1); } /* * FreeBSD has two special kinds of system call redirections -- * SYS_syscall, and SYS___syscall. The former is the old syscall() * routine, basically; the latter is for quad-aligned arguments. * * The system call argument count and code from ptrace() already * account for these, but we need to skip over the first argument. */ syscall_num = regs.x[8]; if (syscall_num == SYS_syscall || syscall_num == SYS___syscall) { reg = 1; syscall_num = regs.x[0]; } else { reg = 0; } for (i = 0; i < narg && reg < 8; i++, reg++) cs->args[i] = regs.x[reg]; return (0); } static int aarch64_fetch_retval(struct trussinfo *trussinfo, long *retval, int *errorp) { struct reg regs; lwpid_t tid; tid = trussinfo->curthread->tid; if (ptrace(PT_GETREGS, tid, (caddr_t)®s, 0) < 0) { fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); return (-1); } retval[0] = regs.x[0]; retval[1] = regs.x[1]; *errorp = !!(regs.spsr & PSR_C); return (0); } static struct procabi aarch64_freebsd = { "FreeBSD ELF64", SYSDECODE_ABI_FREEBSD, aarch64_fetch_args, aarch64_fetch_retval }; PROCABI(aarch64_freebsd); Index: head/usr.bin/truss/amd64-cloudabi64.c =================================================================== --- head/usr.bin/truss/amd64-cloudabi64.c (revision 307537) +++ head/usr.bin/truss/amd64-cloudabi64.c (revision 307538) @@ -1,94 +1,95 @@ /*- * Copyright (c) 2015 Nuxi, https://nuxi.nl/ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include "truss.h" static int amd64_cloudabi64_fetch_args(struct trussinfo *trussinfo, unsigned int narg) { struct current_syscall *cs; struct reg regs; lwpid_t tid; tid = trussinfo->curthread->tid; if (ptrace(PT_GETREGS, tid, (caddr_t)®s, 0) == -1) { fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); return (-1); } cs = &trussinfo->curthread->cs; if (narg >= 1) cs->args[0] = regs.r_rdi; if (narg >= 2) cs->args[1] = regs.r_rsi; if (narg >= 3) cs->args[2] = regs.r_rdx; if (narg >= 4) cs->args[3] = regs.r_rcx; if (narg >= 5) cs->args[4] = regs.r_r8; if (narg >= 6) cs->args[5] = regs.r_r9; return (0); } static int amd64_cloudabi64_fetch_retval(struct trussinfo *trussinfo, long *retval, int *errorp) { struct reg regs; lwpid_t tid; tid = trussinfo->curthread->tid; if (ptrace(PT_GETREGS, tid, (caddr_t)®s, 0) == -1) { fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); return (-1); } retval[0] = regs.r_rax; retval[1] = regs.r_rdx; *errorp = (regs.r_rflags & PSL_C) != 0; return (0); } static struct procabi amd64_cloudabi64 = { "CloudABI ELF64", SYSDECODE_ABI_CLOUDABI64, amd64_cloudabi64_fetch_args, amd64_cloudabi64_fetch_retval }; PROCABI(amd64_cloudabi64); Index: head/usr.bin/truss/amd64-freebsd.c =================================================================== --- head/usr.bin/truss/amd64-freebsd.c (revision 307537) +++ head/usr.bin/truss/amd64-freebsd.c (revision 307538) @@ -1,129 +1,130 @@ /* * Copyright 1997 Sean Eric Fagan * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Sean Eric Fagan * 4. Neither the name of the author may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* FreeBSD/amd64-specific system call handling. */ #include #include #include #include +#include #include #include #include "truss.h" static int amd64_fetch_args(struct trussinfo *trussinfo, u_int narg) { struct ptrace_io_desc iorequest; struct reg regs; struct current_syscall *cs; lwpid_t tid; u_int i, reg; tid = trussinfo->curthread->tid; cs = &trussinfo->curthread->cs; if (ptrace(PT_GETREGS, tid, (caddr_t)®s, 0) < 0) { fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); return (-1); } /* * FreeBSD has two special kinds of system call redirections -- * SYS_syscall, and SYS___syscall. The former is the old syscall() * routine, basically; the latter is for quad-aligned arguments. * * The system call argument count and code from ptrace() already * account for these, but we need to skip over %rax if it contains * either of these values. */ reg = 0; switch (regs.r_rax) { case SYS_syscall: case SYS___syscall: reg++; break; } for (i = 0; i < narg && reg < 6; i++, reg++) { switch (reg) { case 0: cs->args[i] = regs.r_rdi; break; case 1: cs->args[i] = regs.r_rsi; break; case 2: cs->args[i] = regs.r_rdx; break; case 3: cs->args[i] = regs.r_rcx; break; case 4: cs->args[i] = regs.r_r8; break; case 5: cs->args[i] = regs.r_r9; break; } } if (narg > i) { iorequest.piod_op = PIOD_READ_D; iorequest.piod_offs = (void *)(regs.r_rsp + sizeof(register_t)); iorequest.piod_addr = &cs->args[i]; iorequest.piod_len = (narg - i) * sizeof(register_t); ptrace(PT_IO, tid, (caddr_t)&iorequest, 0); if (iorequest.piod_len == 0) return (-1); } return (0); } static int amd64_fetch_retval(struct trussinfo *trussinfo, long *retval, int *errorp) { struct reg regs; lwpid_t tid; tid = trussinfo->curthread->tid; if (ptrace(PT_GETREGS, tid, (caddr_t)®s, 0) < 0) { fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); return (-1); } retval[0] = regs.r_rax; retval[1] = regs.r_rdx; *errorp = !!(regs.r_rflags & PSL_C); return (0); } static struct procabi amd64_freebsd = { "FreeBSD ELF64", SYSDECODE_ABI_FREEBSD, amd64_fetch_args, amd64_fetch_retval }; PROCABI(amd64_freebsd); Index: head/usr.bin/truss/amd64-freebsd32.c =================================================================== --- head/usr.bin/truss/amd64-freebsd32.c (revision 307537) +++ head/usr.bin/truss/amd64-freebsd32.c (revision 307538) @@ -1,134 +1,135 @@ /* * Copyright 1997 Sean Eric Fagan * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Sean Eric Fagan * 4. Neither the name of the author may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* FreeBSD/amd64-freebsd32-specific system call handling. */ #include #include #include #include +#include #include #include #include #include "truss.h" static int amd64_freebsd32_fetch_args(struct trussinfo *trussinfo, u_int narg) { struct ptrace_io_desc iorequest; struct reg regs; struct current_syscall *cs; unsigned int args32[narg]; unsigned long parm_offset; lwpid_t tid; u_int i; tid = trussinfo->curthread->tid; cs = &trussinfo->curthread->cs; if (ptrace(PT_GETREGS, tid, (caddr_t)®s, 0) < 0) { fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); return (-1); } parm_offset = regs.r_rsp + sizeof(int); /* * FreeBSD has two special kinds of system call redirections -- * SYS_syscall, and SYS___syscall. The former is the old syscall() * routine, basically; the latter is for quad-aligned arguments. * * The system call argument count and code from ptrace() already * account for these, but we need to skip over the first argument. */ switch (regs.r_rax) { case SYS_syscall: parm_offset += sizeof(int); break; case SYS___syscall: parm_offset += sizeof(quad_t); break; } iorequest.piod_op = PIOD_READ_D; iorequest.piod_offs = (void *)parm_offset; iorequest.piod_addr = args32; iorequest.piod_len = sizeof(args32); ptrace(PT_IO, tid, (caddr_t)&iorequest, 0); if (iorequest.piod_len == 0) { return (-1); } for (i = 0; i < narg; i++) cs->args[i] = args32[i]; return (0); } static int amd64_freebsd32_fetch_retval(struct trussinfo *trussinfo, long *retval, int *errorp) { struct reg regs; lwpid_t tid; tid = trussinfo->curthread->tid; if (ptrace(PT_GETREGS, tid, (caddr_t)®s, 0) < 0) { fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); return (-1); } retval[0] = regs.r_rax & 0xffffffff; retval[1] = regs.r_rdx & 0xffffffff; *errorp = !!(regs.r_rflags & PSL_C); return (0); } static struct procabi amd64_freebsd32 = { "FreeBSD ELF32", SYSDECODE_ABI_FREEBSD32, amd64_freebsd32_fetch_args, amd64_freebsd32_fetch_retval }; PROCABI(amd64_freebsd32); static struct procabi amd64_freebsd32_aout = { "FreeBSD a.out", SYSDECODE_ABI_FREEBSD32, amd64_freebsd32_fetch_args, amd64_freebsd32_fetch_retval }; PROCABI(amd64_freebsd32_aout); Index: head/usr.bin/truss/amd64-linux.c =================================================================== --- head/usr.bin/truss/amd64-linux.c (revision 307537) +++ head/usr.bin/truss/amd64-linux.c (revision 307538) @@ -1,104 +1,105 @@ /* * Copyright 1997 Sean Eric Fagan * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Sean Eric Fagan * 4. Neither the name of the author may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* Linux/x86_64-specific system call handling. */ #include #include #include +#include #include #include #include "truss.h" static int amd64_linux_fetch_args(struct trussinfo *trussinfo, u_int narg) { struct reg regs; struct current_syscall *cs; lwpid_t tid; tid = trussinfo->curthread->tid; cs = &trussinfo->curthread->cs; if (ptrace(PT_GETREGS, tid, (caddr_t)®s, 0) < 0) { fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); return (-1); } switch (narg) { default: cs->args[5] = regs.r_r9; case 5: cs->args[4] = regs.r_r8; case 4: cs->args[3] = regs.r_rcx; case 3: cs->args[2] = regs.r_rdx; case 2: cs->args[1] = regs.r_rsi; case 1: cs->args[0] = regs.r_rdi; } return (0); } static int amd64_linux_fetch_retval(struct trussinfo *trussinfo, long *retval, int *errorp) { struct reg regs; lwpid_t tid; tid = trussinfo->curthread->tid; if (ptrace(PT_GETREGS, tid, (caddr_t)®s, 0) < 0) { fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); return (-1); } retval[0] = regs.r_rax; retval[1] = regs.r_rdx; *errorp = !!(regs.r_rflags & PSL_C); return (0); } static struct procabi amd64_linux = { "Linux ELF64", SYSDECODE_ABI_LINUX, amd64_linux_fetch_args, amd64_linux_fetch_retval }; PROCABI(amd64_linux); Index: head/usr.bin/truss/amd64-linux32.c =================================================================== --- head/usr.bin/truss/amd64-linux32.c (revision 307537) +++ head/usr.bin/truss/amd64-linux32.c (revision 307538) @@ -1,114 +1,115 @@ /* * Copyright 1997 Sean Eric Fagan * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Sean Eric Fagan * 4. Neither the name of the author may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* Linux/i386-specific system call handling. */ #include #include #include +#include #include #include #include "truss.h" static int amd64_linux32_fetch_args(struct trussinfo *trussinfo, u_int narg) { struct reg regs; struct current_syscall *cs; lwpid_t tid; tid = trussinfo->curthread->tid; cs = &trussinfo->curthread->cs; if (ptrace(PT_GETREGS, tid, (caddr_t)®s, 0) < 0) { fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); return (-1); } /* * Linux passes syscall arguments in registers, not * on the stack. Fortunately, we've got access to the * register set. Note that we don't bother checking the * number of arguments. And what does linux do for syscalls * that have more than five arguments? */ switch (narg) { default: cs->args[5] = regs.r_rbp; /* Unconfirmed */ case 5: cs->args[4] = regs.r_rdi; case 4: cs->args[3] = regs.r_rsi; case 3: cs->args[2] = regs.r_rdx; case 2: cs->args[1] = regs.r_rcx; case 1: cs->args[0] = regs.r_rbx; } return (0); } static int amd64_linux32_fetch_retval(struct trussinfo *trussinfo, long *retval, int *errorp) { struct reg regs; lwpid_t tid; tid = trussinfo->curthread->tid; if (ptrace(PT_GETREGS, tid, (caddr_t)®s, 0) < 0) { fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); return (-1); } retval[0] = regs.r_rax & 0xffffffff; retval[1] = regs.r_rdx & 0xffffffff; *errorp = !!(regs.r_rflags & PSL_C); if (*errorp) retval[0] = (int)retval[0]; return (0); } static struct procabi amd64_linux32 = { "Linux ELF32", SYSDECODE_ABI_LINUX32, amd64_linux32_fetch_args, amd64_linux32_fetch_retval }; PROCABI(amd64_linux32); Index: head/usr.bin/truss/arm-freebsd.c =================================================================== --- head/usr.bin/truss/arm-freebsd.c (revision 307537) +++ head/usr.bin/truss/arm-freebsd.c (revision 307538) @@ -1,136 +1,137 @@ /* * Copyright 1997 Sean Eric Fagan * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Sean Eric Fagan * 4. Neither the name of the author may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* FreeBSD/arm-specific system call handling. */ #include #include #include #include #include +#include #include #include #include "truss.h" static int arm_fetch_args(struct trussinfo *trussinfo, u_int narg) { struct ptrace_io_desc iorequest; struct reg regs; struct current_syscall *cs; lwpid_t tid; u_int i, reg, syscall_num; tid = trussinfo->curthread->tid; cs = &trussinfo->curthread->cs; if (ptrace(PT_GETREGS, tid, (caddr_t)®s, 0) < 0) { fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); return (-1); } /* * FreeBSD has two special kinds of system call redirections -- * SYS_syscall, and SYS___syscall. The former is the old syscall() * routine, basically; the latter is for quad-aligned arguments. * * The system call argument count and code from ptrace() already * account for these, but we need to skip over the first argument. */ #ifdef __ARM_EABI__ syscall_num = regs.r[7]; #else if ((syscall_num = ptrace(PT_READ_I, tid, (caddr_t)(regs.r[_REG_PC] - INSN_SIZE), 0)) == -1) { fprintf(trussinfo->outfile, "-- CANNOT READ PC --\n"); return (-1); } syscall_num = syscall_num & 0x000fffff; #endif reg = 0; switch (syscall_num) { case SYS_syscall: reg = 1; break; case SYS___syscall: reg = 2; break; } for (i = 0; i < narg && reg < 4; i++, reg++) cs->args[i] = regs.r[reg]; if (narg > i) { iorequest.piod_op = PIOD_READ_D; iorequest.piod_offs = (void *)(regs.r_sp + 4 * sizeof(uint32_t)); iorequest.piod_addr = &cs->args[i]; iorequest.piod_len = (narg - i) * sizeof(cs->args[0]); ptrace(PT_IO, tid, (caddr_t)&iorequest, 0); if (iorequest.piod_len == 0) return (-1); } return (0); } static int arm_fetch_retval(struct trussinfo *trussinfo, long *retval, int *errorp) { struct reg regs; lwpid_t tid; tid = trussinfo->curthread->tid; if (ptrace(PT_GETREGS, tid, (caddr_t)®s, 0) < 0) { fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); return (-1); } /* XXX: Does not have the __ARMEB__ handling for __syscall(). */ retval[0] = regs.r[0]; retval[1] = regs.r[1]; *errorp = !!(regs.r_cpsr & PSR_C); return (0); } static struct procabi arm_freebsd = { "FreeBSD ELF32", SYSDECODE_ABI_FREEBSD, arm_fetch_args, arm_fetch_retval }; PROCABI(arm_freebsd); Index: head/usr.bin/truss/extern.h =================================================================== --- head/usr.bin/truss/extern.h (revision 307537) +++ head/usr.bin/truss/extern.h (revision 307538) @@ -1,40 +1,39 @@ /* * Copyright 1997 Sean Eric Fagan * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Sean Eric Fagan * 4. Neither the name of the author may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ extern int print_line_prefix(struct trussinfo *); extern void setup_and_wait(struct trussinfo *, char **); extern void start_tracing(struct trussinfo *, pid_t); extern void restore_proc(int); extern void eventloop(struct trussinfo *); extern const char *ioctlname(unsigned long val); -extern char *strsig(int sig); Index: head/usr.bin/truss/i386-freebsd.c =================================================================== --- head/usr.bin/truss/i386-freebsd.c (revision 307537) +++ head/usr.bin/truss/i386-freebsd.c (revision 307538) @@ -1,128 +1,129 @@ /* * Copyright 1997 Sean Eric Fagan * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Sean Eric Fagan * 4. Neither the name of the author may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* FreeBSD/i386-specific system call handling. */ #include #include #include #include +#include #include #include #include "truss.h" static int i386_fetch_args(struct trussinfo *trussinfo, u_int narg) { struct ptrace_io_desc iorequest; struct reg regs; struct current_syscall *cs; lwpid_t tid; unsigned int parm_offset; tid = trussinfo->curthread->tid; cs = &trussinfo->curthread->cs; if (ptrace(PT_GETREGS, tid, (caddr_t)®s, 0) < 0) { fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); return (-1); } parm_offset = regs.r_esp + sizeof(int); /* * FreeBSD has two special kinds of system call redirections -- * SYS_syscall, and SYS___syscall. The former is the old syscall() * routine, basically; the latter is for quad-aligned arguments. * * The system call argument count and code from ptrace() already * account for these, but we need to skip over the first argument. */ switch (regs.r_eax) { case SYS_syscall: parm_offset += sizeof(int); break; case SYS___syscall: parm_offset += sizeof(quad_t); break; } iorequest.piod_op = PIOD_READ_D; iorequest.piod_offs = (void *)parm_offset; iorequest.piod_addr = cs->args; iorequest.piod_len = narg * sizeof(unsigned long); ptrace(PT_IO, tid, (caddr_t)&iorequest, 0); if (iorequest.piod_len == 0) return (-1); return (0); } static int i386_fetch_retval(struct trussinfo *trussinfo, long *retval, int *errorp) { struct reg regs; lwpid_t tid; tid = trussinfo->curthread->tid; if (ptrace(PT_GETREGS, tid, (caddr_t)®s, 0) < 0) { fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); return (-1); } retval[0] = regs.r_eax; retval[1] = regs.r_edx; *errorp = !!(regs.r_eflags & PSL_C); return (0); } static struct procabi i386_freebsd = { "FreeBSD ELF32", SYSDECODE_ABI_FREEBSD, i386_fetch_args, i386_fetch_retval }; PROCABI(i386_freebsd); static struct procabi i386_freebsd_aout = { "FreeBSD a.out", SYSDECODE_ABI_FREEBSD, i386_fetch_args, i386_fetch_retval }; PROCABI(i386_freebsd_aout); Index: head/usr.bin/truss/i386-linux.c =================================================================== --- head/usr.bin/truss/i386-linux.c (revision 307537) +++ head/usr.bin/truss/i386-linux.c (revision 307538) @@ -1,111 +1,112 @@ /* * Copyright 1997 Sean Eric Fagan * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Sean Eric Fagan * 4. Neither the name of the author may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* Linux/i386-specific system call handling. */ #include #include #include +#include #include #include #include "truss.h" static int i386_linux_fetch_args(struct trussinfo *trussinfo, u_int narg) { struct reg regs; struct current_syscall *cs; lwpid_t tid; tid = trussinfo->curthread->tid; cs = &trussinfo->curthread->cs; if (ptrace(PT_GETREGS, tid, (caddr_t)®s, 0) < 0) { fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); return (-1); } /* * Linux passes syscall arguments in registers, not * on the stack. Fortunately, we've got access to the * register set. Note that we don't bother checking the * number of arguments. And what does linux do for syscalls * that have more than five arguments? */ switch (narg) { default: cs->args[5] = regs.r_ebp; /* Unconfirmed */ case 5: cs->args[4] = regs.r_edi; case 4: cs->args[3] = regs.r_esi; case 3: cs->args[2] = regs.r_edx; case 2: cs->args[1] = regs.r_ecx; case 1: cs->args[0] = regs.r_ebx; } return (0); } static int i386_linux_fetch_retval(struct trussinfo *trussinfo, long *retval, int *errorp) { struct reg regs; lwpid_t tid; tid = trussinfo->curthread->tid; if (ptrace(PT_GETREGS, tid, (caddr_t)®s, 0) < 0) { fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); return (-1); } retval[0] = regs.r_eax; retval[1] = regs.r_edx; *errorp = !!(regs.r_eflags & PSL_C); return (0); } static struct procabi i386_linux = { "Linux ELF", SYSDECODE_ABI_LINUX, i386_linux_fetch_args, i386_linux_fetch_retval }; PROCABI(i386_linux); Index: head/usr.bin/truss/main.c =================================================================== --- head/usr.bin/truss/main.c (revision 307537) +++ head/usr.bin/truss/main.c (revision 307538) @@ -1,215 +1,204 @@ /*- * Copyright 1997 Sean Eric Fagan * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Sean Eric Fagan * 4. Neither the name of the author may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * The main module for truss. Surprisingly simple, but, then, the other * files handle the bulk of the work. And, of course, the kernel has to * do a lot of the work :). */ #include #include #include +#include #include #include #include #include #include #include "truss.h" #include "extern.h" #include "syscall.h" static void usage(void) { fprintf(stderr, "%s\n%s\n", "usage: truss [-cfaedDS] [-o file] [-s strsize] -p pid", " truss [-cfaedDS] [-o file] [-s strsize] command [args]"); exit(1); -} - -char * -strsig(int sig) -{ - static char tmp[64]; - - if (sig > 0 && sig < NSIG) { - snprintf(tmp, sizeof(tmp), "SIG%s", sys_signame[sig]); - return (tmp); - } - return (NULL); } int main(int ac, char **av) { struct sigaction sa; struct trussinfo *trussinfo; char *fname; char **command; pid_t pid; int c; fname = NULL; /* Initialize the trussinfo struct */ trussinfo = (struct trussinfo *)calloc(1, sizeof(struct trussinfo)); if (trussinfo == NULL) errx(1, "calloc() failed"); pid = 0; trussinfo->outfile = stderr; trussinfo->strsize = 32; trussinfo->curthread = NULL; LIST_INIT(&trussinfo->proclist); init_syscalls(); while ((c = getopt(ac, av, "p:o:facedDs:SH")) != -1) { switch (c) { case 'p': /* specified pid */ pid = atoi(optarg); /* make sure i don't trace me */ if (pid == getpid()) { errx(2, "attempt to grab self."); } break; case 'f': /* Follow fork()'s */ trussinfo->flags |= FOLLOWFORKS; break; case 'a': /* Print execve() argument strings. */ trussinfo->flags |= EXECVEARGS; break; case 'c': /* Count number of system calls and time. */ trussinfo->flags |= (COUNTONLY | NOSIGS); break; case 'e': /* Print execve() environment strings. */ trussinfo->flags |= EXECVEENVS; break; case 'd': /* Absolute timestamps */ trussinfo->flags |= ABSOLUTETIMESTAMPS; break; case 'D': /* Relative timestamps */ trussinfo->flags |= RELATIVETIMESTAMPS; break; case 'o': /* Specified output file */ fname = optarg; break; case 's': /* Specified string size */ trussinfo->strsize = atoi(optarg); break; case 'S': /* Don't trace signals */ trussinfo->flags |= NOSIGS; break; case 'H': trussinfo->flags |= DISPLAYTIDS; break; default: usage(); } } ac -= optind; av += optind; if ((pid == 0 && ac == 0) || (pid != 0 && ac != 0)) usage(); if (fname != NULL) { /* Use output file */ /* * Set close-on-exec ('e'), so that the output file is not * shared with the traced process. */ if ((trussinfo->outfile = fopen(fname, "we")) == NULL) err(1, "cannot open %s", fname); } /* * If truss starts the process itself, it will ignore some signals -- * they should be passed off to the process, which may or may not * exit. If, however, we are examining an already-running process, * then we restore the event mask on these same signals. */ if (pid == 0) { /* Start a command ourselves */ command = av; setup_and_wait(trussinfo, command); signal(SIGINT, SIG_IGN); signal(SIGTERM, SIG_IGN); signal(SIGQUIT, SIG_IGN); } else { sa.sa_handler = restore_proc; sa.sa_flags = 0; sigemptyset(&sa.sa_mask); sigaction(SIGINT, &sa, NULL); sigaction(SIGQUIT, &sa, NULL); sigaction(SIGTERM, &sa, NULL); start_tracing(trussinfo, pid); } /* * At this point, if we started the process, it is stopped waiting to * be woken up, either in exit() or in execve(). */ if (LIST_FIRST(&trussinfo->proclist)->abi == NULL) { /* * If we are not able to handle this ABI, detach from the * process and exit. If we just created a new process to * run a command, kill the new process rather than letting * it run untraced. */ if (pid == 0) kill(LIST_FIRST(&trussinfo->proclist)->pid, SIGKILL); ptrace(PT_DETACH, LIST_FIRST(&trussinfo->proclist)->pid, NULL, 0); return (1); } ptrace(PT_SYSCALL, LIST_FIRST(&trussinfo->proclist)->pid, (caddr_t)1, 0); /* * At this point, it's a simple loop, waiting for the process to * stop, finding out why, printing out why, and then continuing it. * All of the grunt work is done in the support routines. */ clock_gettime(CLOCK_REALTIME, &trussinfo->start_time); eventloop(trussinfo); if (trussinfo->flags & COUNTONLY) print_summary(trussinfo); fflush(trussinfo->outfile); return (0); } Index: head/usr.bin/truss/mips-freebsd.c =================================================================== --- head/usr.bin/truss/mips-freebsd.c (revision 307537) +++ head/usr.bin/truss/mips-freebsd.c (revision 307538) @@ -1,139 +1,140 @@ /* * Copyright 1998 Sean Eric Fagan * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Sean Eric Fagan * 4. Neither the name of the author may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* FreeBSD/mips-specific system call handling. */ #include #include #include #include +#include #include #include #include "truss.h" static int mips_fetch_args(struct trussinfo *trussinfo, u_int narg) { struct ptrace_io_desc iorequest; struct reg regs; struct current_syscall *cs; lwpid_t tid; u_int i, reg; tid = trussinfo->curthread->tid; cs = &trussinfo->curthread->cs; if (ptrace(PT_GETREGS, tid, (caddr_t)®s, 0) < 0) { fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); return (-1); } /* * FreeBSD has two special kinds of system call redirections -- * SYS_syscall, and SYS___syscall. The former is the old syscall() * routine, basically; the latter is for quad-aligned arguments. * * The system call argument count and code from ptrace() already * account for these, but we need to skip over the first argument. */ reg = A0; switch (regs.r_regs[V0]) { case SYS_syscall: reg = A1; break; case SYS___syscall: #if defined(__mips_n32) || defined(__mips_n64) reg = A1; #else reg = A2; #endif break; } #if defined(__mips_n32) || defined(__mips_n64) #define MAXREG A7 #else #define MAXREG A3 #endif for (i = 0; i < narg && reg <= MAXREG; i++, reg++) cs->args[i] = regs.r_regs[reg]; if (narg > i) { iorequest.piod_op = PIOD_READ_D; iorequest.piod_offs = (void *)((uintptr_t)regs.r_regs[SP] + 4 * sizeof(cs->args[0])); iorequest.piod_addr = &cs->args[i]; iorequest.piod_len = (narg - i) * sizeof(cs->args[0]); ptrace(PT_IO, tid, (caddr_t)&iorequest, 0); if (iorequest.piod_len == 0) return (-1); } return (0); } static int mips_fetch_retval(struct trussinfo *trussinfo, long *retval, int *errorp) { struct reg regs; lwpid_t tid; tid = trussinfo->curthread->tid; if (ptrace(PT_GETREGS, tid, (caddr_t)®s, 0) < 0) { fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); return (-1); } /* XXX: Does not have special handling for __syscall(). */ retval[0] = regs.r_regs[V0]; retval[1] = regs.r_regs[V1]; *errorp = !!regs.r_regs[A3]; return (0); } static struct procabi mips_freebsd = { #ifdef __mips_n64 "FreeBSD ELF64", #else "FreeBSD ELF32", #endif SYSDECODE_ABI_FREEBSD, mips_fetch_args, mips_fetch_retval }; PROCABI(mips_freebsd); Index: head/usr.bin/truss/powerpc-freebsd.c =================================================================== --- head/usr.bin/truss/powerpc-freebsd.c (revision 307537) +++ head/usr.bin/truss/powerpc-freebsd.c (revision 307538) @@ -1,120 +1,121 @@ /* * Copyright 2006 Peter Grehan * Copyright 2005 Orlando Bassotto * Copyright 1998 Sean Eric Fagan * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* FreeBSD/powerpc-specific system call handling. */ #include #include #include #include +#include #include #include #include "truss.h" static int powerpc_fetch_args(struct trussinfo *trussinfo, u_int narg) { struct ptrace_io_desc iorequest; struct reg regs; struct current_syscall *cs; lwpid_t tid; u_int i, reg; tid = trussinfo->curthread->tid; cs = &trussinfo->curthread->cs; if (ptrace(PT_GETREGS, tid, (caddr_t)®s, 0) < 0) { fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); return (-1); } /* * FreeBSD has two special kinds of system call redirections -- * SYS_syscall, and SYS___syscall. The former is the old syscall() * routine, basically; the latter is for quad-aligned arguments. * * The system call argument count and code from ptrace() already * account for these, but we need to skip over the first argument. */ reg = 0; switch (regs.fixreg[0]) { case SYS_syscall: reg += 1; break; case SYS___syscall: reg += 2; break; } for (i = 0; i < narg && reg < NARGREG; i++, reg++) { cs->args[i] = regs.fixreg[FIRSTARG + reg]; } if (narg > i) { iorequest.piod_op = PIOD_READ_D; iorequest.piod_offs = (void *)(regs.fixreg[1] + 8); iorequest.piod_addr = &cs->args[i]; iorequest.piod_len = (narg - i) * sizeof(cs->args[0]); ptrace(PT_IO, tid, (caddr_t)&iorequest, 0); if (iorequest.piod_len == 0) return (-1); } return (0); } static int powerpc_fetch_retval(struct trussinfo *trussinfo, long *retval, int *errorp) { struct reg regs; lwpid_t tid; tid = trussinfo->curthread->tid; if (ptrace(PT_GETREGS, tid, (caddr_t)®s, 0) < 0) { fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); return (-1); } /* XXX: Does not have fixup for __syscall(). */ retval[0] = regs.fixreg[3]; retval[1] = regs.fixreg[4]; *errorp = !!(regs.cr & 0x10000000); return (0); } static struct procabi powerpc_freebsd = { "FreeBSD ELF32", SYSDECODE_ABI_FREEBSD, powerpc_fetch_args, powerpc_fetch_retval }; PROCABI(powerpc_freebsd); Index: head/usr.bin/truss/powerpc64-freebsd.c =================================================================== --- head/usr.bin/truss/powerpc64-freebsd.c (revision 307537) +++ head/usr.bin/truss/powerpc64-freebsd.c (revision 307538) @@ -1,116 +1,117 @@ /* * Copyright 2006 Peter Grehan * Copyright 2005 Orlando Bassotto * Copyright 1998 Sean Eric Fagan * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* FreeBSD/powerpc64-specific system call handling. */ #include #include #include #include +#include #include #include #include "truss.h" static int powerpc64_fetch_args(struct trussinfo *trussinfo, u_int narg) { struct ptrace_io_desc iorequest; struct reg regs; struct current_syscall *cs; lwpid_t tid; u_int i, reg; tid = trussinfo->curthread->tid; cs = &trussinfo->curthread->cs; if (ptrace(PT_GETREGS, tid, (caddr_t)®s, 0) < 0) { fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); return (-1); } /* * FreeBSD has two special kinds of system call redirections -- * SYS_syscall, and SYS___syscall. The former is the old syscall() * routine, basically; the latter is for quad-aligned arguments. * * The system call argument count and code from ptrace() already * account for these, but we need to skip over the first argument. */ reg = 0; switch (regs.fixreg[0]) { case SYS_syscall: case SYS___syscall: reg += 1; break; } for (i = 0; i < narg && reg < NARGREG; i++, reg++) cs->args[i] = regs.fixreg[FIRSTARG + reg]; if (narg > i) { iorequest.piod_op = PIOD_READ_D; iorequest.piod_offs = (void *)(regs.fixreg[1] + 48); iorequest.piod_addr = &cs->args[i]; iorequest.piod_len = (narg - i) * sizeof(cs->args[0]); ptrace(PT_IO, tid, (caddr_t)&iorequest, 0); if (iorequest.piod_len == 0) return (-1); } return (0); } static int powerpc64_fetch_retval(struct trussinfo *trussinfo, long *retval, int *errorp) { struct reg regs; lwpid_t tid; tid = trussinfo->curthread->tid; if (ptrace(PT_GETREGS, tid, (caddr_t)®s, 0) < 0) { fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); return (-1); } retval[0] = regs.fixreg[3]; retval[1] = regs.fixreg[4]; *errorp = !!(regs.cr & 0x10000000); return (0); } static struct procabi powerpc64_freebsd = { "FreeBSD ELF64", SYSDECODE_ABI_FREEBSD, powerpc64_fetch_args, powerpc64_fetch_retval }; PROCABI(powerpc64_freebsd); Index: head/usr.bin/truss/powerpc64-freebsd32.c =================================================================== --- head/usr.bin/truss/powerpc64-freebsd32.c (revision 307537) +++ head/usr.bin/truss/powerpc64-freebsd32.c (revision 307538) @@ -1,125 +1,126 @@ /* * Copyright 2006 Peter Grehan * Copyright 2005 Orlando Bassotto * Copyright 1998 Sean Eric Fagan * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* FreeBSD/powerpc64-freebsd32-specific system call handling. */ #include #include #include #include +#include #include #include #include "truss.h" static int powerpc64_freebsd32_fetch_args(struct trussinfo *trussinfo, u_int narg) { struct ptrace_io_desc iorequest; struct reg regs; struct current_syscall *cs; lwpid_t tid; u_int i, reg; tid = trussinfo->curthread->tid; cs = &trussinfo->curthread->cs; if (ptrace(PT_GETREGS, tid, (caddr_t)®s, 0) < 0) { fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); return (-1); } /* * FreeBSD has two special kinds of system call redirections -- * SYS_syscall, and SYS___syscall. The former is the old syscall() * routine, basically; the latter is for quad-aligned arguments. * * The system call argument count and code from ptrace() already * account for these, but we need to skip over the first argument. */ reg = 0; switch (regs.fixreg[0]) { case SYS_syscall: reg += 1; break; case SYS___syscall: reg += 2; break; } for (i = 0; i < narg && reg < NARGREG; i++, reg++) { cs->args[i] = regs.fixreg[FIRSTARG + reg] & 0xffffffff; } if (narg > i) { uint32_t args32[narg - i]; u_int j; iorequest.piod_op = PIOD_READ_D; iorequest.piod_offs = (void *)(regs.fixreg[1] + 8); iorequest.piod_addr = args32; iorequest.piod_len = sizeof(args32); ptrace(PT_IO, tid, (caddr_t)&iorequest, 0); if (iorequest.piod_len == 0) return (-1); for (j = 0; j < narg - i; j++) cs->args[i + j] = args32[j]; } return (0); } static int powerpc64_freebsd32_fetch_retval(struct trussinfo *trussinfo, long *retval, int *errorp) { struct reg regs; lwpid_t tid; tid = trussinfo->curthread->tid; if (ptrace(PT_GETREGS, tid, (caddr_t)®s, 0) < 0) { fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); return (-1); } /* XXX: Does not have fixup for __syscall(). */ retval[0] = regs.fixreg[3] & 0xffffffff; retval[1] = regs.fixreg[4] & 0xffffffff; *errorp = !!(regs.cr & 0x10000000); return (0); } static struct procabi powerpc64_freebsd32 = { "FreeBSD ELF32", SYSDECODE_ABI_FREEBSD32, powerpc64_freebsd32_fetch_args, powerpc64_freebsd32_fetch_retval }; PROCABI(powerpc64_freebsd32); Index: head/usr.bin/truss/setup.c =================================================================== --- head/usr.bin/truss/setup.c (revision 307537) +++ head/usr.bin/truss/setup.c (revision 307538) @@ -1,690 +1,692 @@ /*- * Copyright 1997 Sean Eric Fagan * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Sean Eric Fagan * 4. Neither the name of the author may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * Various setup functions for truss. Not the cleanest-written code, * I'm afraid. */ #include #include #include #include #include #include #include +#include #include #include #include #include #include #include #include #include "truss.h" #include "syscall.h" #include "extern.h" SET_DECLARE(procabi, struct procabi); static sig_atomic_t detaching; static void enter_syscall(struct trussinfo *, struct threadinfo *, struct ptrace_lwpinfo *); static void new_proc(struct trussinfo *, pid_t, lwpid_t); /* * setup_and_wait() is called to start a process. All it really does * is fork(), enable tracing in the child, and then exec the given * command. At that point, the child process stops, and the parent * can wake up and deal with it. */ void setup_and_wait(struct trussinfo *info, char *command[]) { pid_t pid; pid = vfork(); if (pid == -1) err(1, "fork failed"); if (pid == 0) { /* Child */ ptrace(PT_TRACE_ME, 0, 0, 0); execvp(command[0], command); err(1, "execvp %s", command[0]); } /* Only in the parent here */ if (waitpid(pid, NULL, 0) < 0) err(1, "unexpect stop in waitpid"); new_proc(info, pid, 0); } /* * start_tracing is called to attach to an existing process. */ void start_tracing(struct trussinfo *info, pid_t pid) { int ret, retry; retry = 10; do { ret = ptrace(PT_ATTACH, pid, NULL, 0); usleep(200); } while (ret && retry-- > 0); if (ret) err(1, "can not attach to target process"); if (waitpid(pid, NULL, 0) < 0) err(1, "Unexpect stop in waitpid"); new_proc(info, pid, 0); } /* * Restore a process back to it's pre-truss state. * Called for SIGINT, SIGTERM, SIGQUIT. This only * applies if truss was told to monitor an already-existing * process. */ void restore_proc(int signo __unused) { detaching = 1; } static void detach_proc(pid_t pid) { /* stop the child so that we can detach */ kill(pid, SIGSTOP); if (waitpid(pid, NULL, 0) < 0) err(1, "Unexpected stop in waitpid"); if (ptrace(PT_DETACH, pid, (caddr_t)1, 0) < 0) err(1, "Can not detach the process"); kill(pid, SIGCONT); } /* * Determine the ABI. This is called after every exec, and when * a process is first monitored. */ static struct procabi * find_abi(pid_t pid) { struct procabi **pabi; size_t len; int error; int mib[4]; char progt[32]; len = sizeof(progt); mib[0] = CTL_KERN; mib[1] = KERN_PROC; mib[2] = KERN_PROC_SV_NAME; mib[3] = pid; error = sysctl(mib, 4, progt, &len, NULL, 0); if (error != 0) err(2, "can not get sysvec name"); SET_FOREACH(pabi, procabi) { if (strcmp((*pabi)->type, progt) == 0) return (*pabi); } warnx("ABI %s for pid %ld is not supported", progt, (long)pid); return (NULL); } static struct threadinfo * new_thread(struct procinfo *p, lwpid_t lwpid) { struct threadinfo *nt; /* * If this happens it means there is a bug in truss. Unfortunately * this will kill any processes truss is attached to. */ LIST_FOREACH(nt, &p->threadlist, entries) { if (nt->tid == lwpid) errx(1, "Duplicate thread for LWP %ld", (long)lwpid); } nt = calloc(1, sizeof(struct threadinfo)); if (nt == NULL) err(1, "calloc() failed"); nt->proc = p; nt->tid = lwpid; LIST_INSERT_HEAD(&p->threadlist, nt, entries); return (nt); } static void free_thread(struct threadinfo *t) { LIST_REMOVE(t, entries); free(t); } static void add_threads(struct trussinfo *info, struct procinfo *p) { struct ptrace_lwpinfo pl; struct threadinfo *t; lwpid_t *lwps; int i, nlwps; nlwps = ptrace(PT_GETNUMLWPS, p->pid, NULL, 0); if (nlwps == -1) err(1, "Unable to fetch number of LWPs"); assert(nlwps > 0); lwps = calloc(nlwps, sizeof(*lwps)); nlwps = ptrace(PT_GETLWPLIST, p->pid, (caddr_t)lwps, nlwps); if (nlwps == -1) err(1, "Unable to fetch LWP list"); for (i = 0; i < nlwps; i++) { t = new_thread(p, lwps[i]); if (ptrace(PT_LWPINFO, lwps[i], (caddr_t)&pl, sizeof(pl)) == -1) err(1, "ptrace(PT_LWPINFO)"); if (pl.pl_flags & PL_FLAG_SCE) { info->curthread = t; enter_syscall(info, t, &pl); } } free(lwps); } static void new_proc(struct trussinfo *info, pid_t pid, lwpid_t lwpid) { struct procinfo *np; /* * If this happens it means there is a bug in truss. Unfortunately * this will kill any processes truss is attached to. */ LIST_FOREACH(np, &info->proclist, entries) { if (np->pid == pid) errx(1, "Duplicate process for pid %ld", (long)pid); } if (info->flags & FOLLOWFORKS) if (ptrace(PT_FOLLOW_FORK, pid, NULL, 1) == -1) err(1, "Unable to follow forks for pid %ld", (long)pid); if (ptrace(PT_LWP_EVENTS, pid, NULL, 1) == -1) err(1, "Unable to enable LWP events for pid %ld", (long)pid); np = calloc(1, sizeof(struct procinfo)); np->pid = pid; np->abi = find_abi(pid); LIST_INIT(&np->threadlist); LIST_INSERT_HEAD(&info->proclist, np, entries); if (lwpid != 0) new_thread(np, lwpid); else add_threads(info, np); } static void free_proc(struct procinfo *p) { struct threadinfo *t, *t2; LIST_FOREACH_SAFE(t, &p->threadlist, entries, t2) { free(t); } LIST_REMOVE(p, entries); free(p); } static void detach_all_procs(struct trussinfo *info) { struct procinfo *p, *p2; LIST_FOREACH_SAFE(p, &info->proclist, entries, p2) { detach_proc(p->pid); free_proc(p); } } static struct procinfo * find_proc(struct trussinfo *info, pid_t pid) { struct procinfo *np; LIST_FOREACH(np, &info->proclist, entries) { if (np->pid == pid) return (np); } return (NULL); } /* * Change curthread member based on (pid, lwpid). */ static void find_thread(struct trussinfo *info, pid_t pid, lwpid_t lwpid) { struct procinfo *np; struct threadinfo *nt; np = find_proc(info, pid); assert(np != NULL); LIST_FOREACH(nt, &np->threadlist, entries) { if (nt->tid == lwpid) { info->curthread = nt; return; } } errx(1, "could not find thread"); } /* * When a process exits, it should have exactly one thread left. * All of the other threads should have reported thread exit events. */ static void find_exit_thread(struct trussinfo *info, pid_t pid) { struct procinfo *p; p = find_proc(info, pid); assert(p != NULL); info->curthread = LIST_FIRST(&p->threadlist); assert(info->curthread != NULL); assert(LIST_NEXT(info->curthread, entries) == NULL); } static void alloc_syscall(struct threadinfo *t, struct ptrace_lwpinfo *pl) { u_int i; assert(t->in_syscall == 0); assert(t->cs.number == 0); assert(t->cs.name == NULL); assert(t->cs.nargs == 0); for (i = 0; i < nitems(t->cs.s_args); i++) assert(t->cs.s_args[i] == NULL); memset(t->cs.args, 0, sizeof(t->cs.args)); t->cs.number = pl->pl_syscall_code; t->in_syscall = 1; } static void free_syscall(struct threadinfo *t) { u_int i; for (i = 0; i < t->cs.nargs; i++) free(t->cs.s_args[i]); memset(&t->cs, 0, sizeof(t->cs)); t->in_syscall = 0; } static void enter_syscall(struct trussinfo *info, struct threadinfo *t, struct ptrace_lwpinfo *pl) { struct syscall *sc; u_int i, narg; alloc_syscall(t, pl); narg = MIN(pl->pl_syscall_narg, nitems(t->cs.args)); if (narg != 0 && t->proc->abi->fetch_args(info, narg) != 0) { free_syscall(t); return; } t->cs.name = sysdecode_syscallname(t->proc->abi->abi, t->cs.number); if (t->cs.name == NULL) fprintf(info->outfile, "-- UNKNOWN %s SYSCALL %d --\n", t->proc->abi->type, t->cs.number); sc = get_syscall(t->cs.name, narg); t->cs.nargs = sc->nargs; assert(sc->nargs <= nitems(t->cs.s_args)); t->cs.sc = sc; /* * At this point, we set up the system call arguments. * We ignore any OUT ones, however -- those are arguments that * are set by the system call, and so are probably meaningless * now. This doesn't currently support arguments that are * passed in *and* out, however. */ if (t->cs.name != NULL) { #if DEBUG fprintf(stderr, "syscall %s(", t->cs.name); #endif for (i = 0; i < t->cs.nargs; i++) { #if DEBUG fprintf(stderr, "0x%lx%s", sc ? t->cs.args[sc->args[i].offset] : t->cs.args[i], i < (t->cs.nargs - 1) ? "," : ""); #endif if (!(sc->args[i].type & OUT)) { t->cs.s_args[i] = print_arg(&sc->args[i], t->cs.args, 0, info); } } #if DEBUG fprintf(stderr, ")\n"); #endif } clock_gettime(CLOCK_REALTIME, &t->before); } /* * When a thread exits voluntarily (including when a thread calls * exit() to trigger a process exit), the thread's internal state * holds the arguments passed to the exit system call. When the * thread's exit is reported, log that system call without a return * value. */ static void thread_exit_syscall(struct trussinfo *info) { struct threadinfo *t; t = info->curthread; if (!t->in_syscall) return; clock_gettime(CLOCK_REALTIME, &t->after); print_syscall_ret(info, 0, NULL); free_syscall(t); } static void exit_syscall(struct trussinfo *info, struct ptrace_lwpinfo *pl) { struct threadinfo *t; struct procinfo *p; struct syscall *sc; long retval[2]; u_int i; int errorp; t = info->curthread; if (!t->in_syscall) return; clock_gettime(CLOCK_REALTIME, &t->after); p = t->proc; if (p->abi->fetch_retval(info, retval, &errorp) < 0) { free_syscall(t); return; } sc = t->cs.sc; /* * Here, we only look for arguments that have OUT masked in -- * otherwise, they were handled in enter_syscall(). */ for (i = 0; i < sc->nargs; i++) { char *temp; if (sc->args[i].type & OUT) { /* * If an error occurred, then don't bother * getting the data; it may not be valid. */ if (errorp) { asprintf(&temp, "0x%lx", t->cs.args[sc->args[i].offset]); } else { temp = print_arg(&sc->args[i], t->cs.args, retval, info); } t->cs.s_args[i] = temp; } } print_syscall_ret(info, errorp, retval); free_syscall(t); /* * If the process executed a new image, check the ABI. If the * new ABI isn't supported, stop tracing this process. */ if (pl->pl_flags & PL_FLAG_EXEC) { assert(LIST_NEXT(LIST_FIRST(&p->threadlist), entries) == NULL); p->abi = find_abi(p->pid); if (p->abi == NULL) { if (ptrace(PT_DETACH, p->pid, (caddr_t)1, 0) < 0) err(1, "Can not detach the process"); free_proc(p); } } } int print_line_prefix(struct trussinfo *info) { struct timespec timediff; struct threadinfo *t; int len; len = 0; t = info->curthread; if (info->flags & (FOLLOWFORKS | DISPLAYTIDS)) { if (info->flags & FOLLOWFORKS) len += fprintf(info->outfile, "%5d", t->proc->pid); if ((info->flags & (FOLLOWFORKS | DISPLAYTIDS)) == (FOLLOWFORKS | DISPLAYTIDS)) len += fprintf(info->outfile, " "); if (info->flags & DISPLAYTIDS) len += fprintf(info->outfile, "%6d", t->tid); len += fprintf(info->outfile, ": "); } if (info->flags & ABSOLUTETIMESTAMPS) { timespecsubt(&t->after, &info->start_time, &timediff); len += fprintf(info->outfile, "%jd.%09ld ", (intmax_t)timediff.tv_sec, timediff.tv_nsec); } if (info->flags & RELATIVETIMESTAMPS) { timespecsubt(&t->after, &t->before, &timediff); len += fprintf(info->outfile, "%jd.%09ld ", (intmax_t)timediff.tv_sec, timediff.tv_nsec); } return (len); } static void report_thread_death(struct trussinfo *info) { struct threadinfo *t; t = info->curthread; clock_gettime(CLOCK_REALTIME, &t->after); print_line_prefix(info); fprintf(info->outfile, "\n", (long)t->tid); } static void report_thread_birth(struct trussinfo *info) { struct threadinfo *t; t = info->curthread; clock_gettime(CLOCK_REALTIME, &t->after); t->before = t->after; print_line_prefix(info); fprintf(info->outfile, "\n", (long)t->tid); } static void report_exit(struct trussinfo *info, siginfo_t *si) { struct threadinfo *t; t = info->curthread; clock_gettime(CLOCK_REALTIME, &t->after); print_line_prefix(info); if (si->si_code == CLD_EXITED) fprintf(info->outfile, "process exit, rval = %u\n", si->si_status); else fprintf(info->outfile, "process killed, signal = %u%s\n", si->si_status, si->si_code == CLD_DUMPED ? " (core dumped)" : ""); } static void report_new_child(struct trussinfo *info) { struct threadinfo *t; t = info->curthread; clock_gettime(CLOCK_REALTIME, &t->after); t->before = t->after; print_line_prefix(info); fprintf(info->outfile, "\n"); } static void report_signal(struct trussinfo *info, siginfo_t *si) { struct threadinfo *t; - char *signame; + const char *signame; t = info->curthread; clock_gettime(CLOCK_REALTIME, &t->after); print_line_prefix(info); - signame = strsig(si->si_status); - fprintf(info->outfile, "SIGNAL %u (%s)\n", si->si_status, - signame == NULL ? "?" : signame); + signame = sysdecode_signal(si->si_status); + if (signame == NULL) + signame = "?"; + fprintf(info->outfile, "SIGNAL %u (%s)\n", si->si_status, signame); } /* * Wait for events until all the processes have exited or truss has been * asked to stop. */ void eventloop(struct trussinfo *info) { struct ptrace_lwpinfo pl; siginfo_t si; int pending_signal; while (!LIST_EMPTY(&info->proclist)) { if (detaching) { detach_all_procs(info); return; } if (waitid(P_ALL, 0, &si, WTRAPPED | WEXITED) == -1) { if (errno == EINTR) continue; err(1, "Unexpected error from waitid"); } assert(si.si_signo == SIGCHLD); switch (si.si_code) { case CLD_EXITED: case CLD_KILLED: case CLD_DUMPED: find_exit_thread(info, si.si_pid); if ((info->flags & COUNTONLY) == 0) { if (si.si_code == CLD_EXITED) thread_exit_syscall(info); report_exit(info, &si); } free_proc(info->curthread->proc); info->curthread = NULL; break; case CLD_TRAPPED: if (ptrace(PT_LWPINFO, si.si_pid, (caddr_t)&pl, sizeof(pl)) == -1) err(1, "ptrace(PT_LWPINFO)"); if (pl.pl_flags & PL_FLAG_CHILD) { new_proc(info, si.si_pid, pl.pl_lwpid); assert(LIST_FIRST(&info->proclist)->abi != NULL); } else if (pl.pl_flags & PL_FLAG_BORN) new_thread(find_proc(info, si.si_pid), pl.pl_lwpid); find_thread(info, si.si_pid, pl.pl_lwpid); if (si.si_status == SIGTRAP && (pl.pl_flags & (PL_FLAG_BORN|PL_FLAG_EXITED| PL_FLAG_SCE|PL_FLAG_SCX)) != 0) { if (pl.pl_flags & PL_FLAG_BORN) { if ((info->flags & COUNTONLY) == 0) report_thread_birth(info); } else if (pl.pl_flags & PL_FLAG_EXITED) { if ((info->flags & COUNTONLY) == 0) report_thread_death(info); free_thread(info->curthread); info->curthread = NULL; } else if (pl.pl_flags & PL_FLAG_SCE) enter_syscall(info, info->curthread, &pl); else if (pl.pl_flags & PL_FLAG_SCX) exit_syscall(info, &pl); pending_signal = 0; } else if (pl.pl_flags & PL_FLAG_CHILD) { if ((info->flags & COUNTONLY) == 0) report_new_child(info); pending_signal = 0; } else { if ((info->flags & NOSIGS) == 0) report_signal(info, &si); pending_signal = si.si_status; } ptrace(PT_SYSCALL, si.si_pid, (caddr_t)1, pending_signal); break; case CLD_STOPPED: errx(1, "waitid reported CLD_STOPPED"); case CLD_CONTINUED: break; } } } Index: head/usr.bin/truss/sparc64-freebsd.c =================================================================== --- head/usr.bin/truss/sparc64-freebsd.c (revision 307537) +++ head/usr.bin/truss/sparc64-freebsd.c (revision 307538) @@ -1,123 +1,124 @@ /* * Copyright 1998 Sean Eric Fagan * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Sean Eric Fagan * 4. Neither the name of the author may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* FreeBSD/sparc64-specific system call handling. */ #include #include #include #include #include +#include #include #include #include #include "truss.h" static int sparc64_fetch_args(struct trussinfo *trussinfo, u_int narg) { struct ptrace_io_desc iorequest; struct reg regs; struct current_syscall *cs; lwpid_t tid; u_int i, reg; tid = trussinfo->curthread->tid; cs = &trussinfo->curthread->cs; if (ptrace(PT_GETREGS, tid, (caddr_t)®s, 0) < 0) { fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); return (-1); } /* * FreeBSD has two special kinds of system call redirections -- * SYS_syscall, and SYS___syscall. The former is the old syscall() * routine, basically; the latter is for quad-aligned arguments. * * The system call argument count and code from ptrace() already * account for these, but we need to skip over the first argument. */ reg = 0; switch (regs.r_global[1]) { case SYS_syscall: case SYS___syscall: reg = 1; break; } for (i = 0; i < narg && reg < 6; i++, reg++) cs->args[i] = regs.r_out[reg]; if (narg > i) { iorequest.piod_op = PIOD_READ_D; iorequest.piod_offs = (void *)(regs.r_out[6] + SPOFF + offsetof(struct frame, fr_pad[6])); iorequest.piod_addr = &cs->args[i]; iorequest.piod_len = (narg - i) * sizeof(cs->args[0]); ptrace(PT_IO, tid, (caddr_t)&iorequest, 0); if (iorequest.piod_len == 0) return (-1); } return (0); } static int sparc64_fetch_retval(struct trussinfo *trussinfo, long *retval, int *errorp) { struct reg regs; lwpid_t tid; tid = trussinfo->curthread->tid; if (ptrace(PT_GETREGS, tid, (caddr_t)®s, 0) < 0) { fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); return (-1); } retval[0] = regs.r_out[0]; retval[1] = regs.r_out[1]; *errorp = !!(regs.r_tstate & TSTATE_XCC_C); return (0); } static struct procabi sparc64_freebsd = { "FreeBSD ELF64", SYSDECODE_ABI_FREEBSD, sparc64_fetch_args, sparc64_fetch_retval }; PROCABI(sparc64_freebsd); Index: head/usr.bin/truss/syscall.h =================================================================== --- head/usr.bin/truss/syscall.h (revision 307537) +++ head/usr.bin/truss/syscall.h (revision 307538) @@ -1,123 +1,123 @@ /* * See i386-fbsd.c for copyright and license terms. * * System call arguments come in several flavours: * Hex -- values that should be printed in hex (addresses) * Octal -- Same as above, but octal * Int -- normal integer values (file descriptors, for example) * LongHex -- long value that should be printed in hex * Name -- pointer to a NULL-terminated string. * BinString -- pointer to an array of chars, printed via strvisx(). * Ptr -- pointer to some unspecified structure. Just print as hex for now. * Stat -- a pointer to a stat buffer. Prints a couple fields. * StatFs -- a pointer to a statfs buffer. Prints a few fields. * Ioctl -- an ioctl command. Woefully limited. * Quad -- a double-word value. e.g., lseek(int, offset_t, int) * Signal -- a signal number. Prints the signal name (SIGxxx) * Sockaddr -- a pointer to a struct sockaddr. Prints symbolic AF, and IP:Port * StringArray -- a pointer to an array of string pointers. * Timespec -- a pointer to a struct timespec. Prints both elements. * Timeval -- a pointer to a struct timeval. Prints both elements. * Timeval2 -- a pointer to two struct timevals. Prints both elements of both. * Itimerval -- a pointer to a struct itimerval. Prints all elements. * Pollfd -- a pointer to an array of struct pollfd. Prints .fd and .events. * Fd_set -- a pointer to an array of fd_set. Prints the fds that are set. * Sigaction -- a pointer to a struct sigaction. Prints all elements. * Sigset -- a pointer to a sigset_t. Prints the signals that are set. * Sigprocmask -- the first argument to sigprocmask(). Prints the name. * Kevent -- a pointer to an array of struct kevents. Prints all elements. * Pathconf -- the 2nd argument of pathconf(). * Utrace -- utrace(2) buffer. * * In addition, the pointer types (String, Ptr) may have OUT masked in -- * this means that the data is set on *return* from the system call -- or * IN (meaning that the data is passed *into* the system call). */ /* * $FreeBSD$ */ enum Argtype { None = 1, Hex, Octal, Int, UInt, LongHex, Name, Ptr, Stat, Ioctl, Quad, Signal, Sockaddr, StringArray, Timespec, Timeval, Itimerval, Pollfd, Fd_set, Sigaction, Fcntl, Mprot, Mmapflags, Whence, Readlinkres, Sigset, Sigprocmask, StatFs, Kevent, Sockdomain, Socktype, Open, Fcntlflag, Rusage, BinString, Shutdown, Resource, Rlimit, Timeval2, Pathconf, Rforkflags, ExitStatus, Waitoptions, Idtype, Procctl, LinuxSockArgs, Umtxop, Atfd, Atflags, Timespec2, Accessmode, Long, - Sysarch, ExecArgs, ExecEnv, PipeFds, QuadHex, Utrace, IntArray, + Sysarch, ExecArgs, ExecEnv, PipeFds, QuadHex, Utrace, IntArray, Pipe2, CloudABIAdvice, CloudABIClockID, ClouduABIFDSFlags, CloudABIFDStat, CloudABIFileStat, CloudABIFileType, CloudABIFSFlags, CloudABILookup, CloudABIMFlags, CloudABIMProt, CloudABIMSFlags, CloudABIOFlags, CloudABISDFlags, CloudABISignal, CloudABISockStat, CloudABISSFlags, CloudABITimestamp, CloudABIULFlags, CloudABIWhence }; #define ARG_MASK 0xff #define OUT 0x100 #define IN /*0x20*/0 struct syscall_args { enum Argtype type; int offset; }; struct syscall { STAILQ_ENTRY(syscall) entries; const char *name; u_int ret_type; /* 0, 1, or 2 return values */ u_int nargs; /* actual number of meaningful arguments */ /* Hopefully, no syscalls with > 10 args */ struct syscall_args args[10]; struct timespec time; /* Time spent for this call */ int ncalls; /* Number of calls */ int nerror; /* Number of calls that returned with error */ }; struct syscall *get_syscall(const char *, int nargs); char *print_arg(struct syscall_args *, unsigned long*, long *, struct trussinfo *); /* * Linux Socket defines */ #define LINUX_SOCKET 1 #define LINUX_BIND 2 #define LINUX_CONNECT 3 #define LINUX_LISTEN 4 #define LINUX_ACCEPT 5 #define LINUX_GETSOCKNAME 6 #define LINUX_GETPEERNAME 7 #define LINUX_SOCKETPAIR 8 #define LINUX_SEND 9 #define LINUX_RECV 10 #define LINUX_SENDTO 11 #define LINUX_RECVFROM 12 #define LINUX_SHUTDOWN 13 #define LINUX_SETSOCKOPT 14 #define LINUX_GETSOCKOPT 15 #define LINUX_SENDMSG 16 #define LINUX_RECVMSG 17 #define PAD_(t) (sizeof(register_t) <= sizeof(t) ? \ 0 : sizeof(register_t) - sizeof(t)) #if BYTE_ORDER == LITTLE_ENDIAN #define PADL_(t) 0 #define PADR_(t) PAD_(t) #else #define PADL_(t) PAD_(t) #define PADR_(t) 0 #endif typedef int l_int; typedef uint32_t l_ulong; struct linux_socketcall_args { char what_l_[PADL_(l_int)]; l_int what; char what_r_[PADR_(l_int)]; char args_l_[PADL_(l_ulong)]; l_ulong args; char args_r_[PADR_(l_ulong)]; }; void init_syscalls(void); void print_syscall(struct trussinfo *); void print_syscall_ret(struct trussinfo *, int, long *); void print_summary(struct trussinfo *trussinfo); Index: head/usr.bin/truss/syscalls.c =================================================================== --- head/usr.bin/truss/syscalls.c (revision 307537) +++ head/usr.bin/truss/syscalls.c (revision 307538) @@ -1,2114 +1,1968 @@ /* * Copyright 1997 Sean Eric Fagan * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Sean Eric Fagan * 4. Neither the name of the author may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * This file has routines used to print out system calls and their * arguments. */ #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 "truss.h" #include "extern.h" #include "syscall.h" /* 64-bit alignment on 32-bit platforms. */ #if !defined(__LP64__) && defined(__powerpc__) #define QUAD_ALIGN 1 #else #define QUAD_ALIGN 0 #endif /* Number of slots needed for a 64-bit argument. */ #ifdef __LP64__ #define QUAD_SLOTS 1 #else #define QUAD_SLOTS 2 #endif /* * This should probably be in its own file, sorted alphabetically. */ static struct syscall decoded_syscalls[] = { /* Native ABI */ { .name = "__getcwd", .ret_type = 1, .nargs = 2, .args = { { Name | OUT, 0 }, { Int, 1 } } }, { .name = "_umtx_op", .ret_type = 1, .nargs = 5, .args = { { Ptr, 0 }, { Umtxop, 1 }, { LongHex, 2 }, { Ptr, 3 }, { Ptr, 4 } } }, { .name = "accept", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } }, { .name = "access", .ret_type = 1, .nargs = 2, .args = { { Name | IN, 0 }, { Accessmode, 1 } } }, { .name = "bind", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { Sockaddr | IN, 1 }, { Int, 2 } } }, { .name = "bindat", .ret_type = 1, .nargs = 4, .args = { { Atfd, 0 }, { Int, 1 }, { Sockaddr | IN, 2 }, { Int, 3 } } }, { .name = "break", .ret_type = 1, .nargs = 1, .args = { { Ptr, 0 } } }, { .name = "chdir", .ret_type = 1, .nargs = 1, .args = { { Name, 0 } } }, { .name = "chflags", .ret_type = 1, .nargs = 2, .args = { { Name | IN, 0 }, { Hex, 1 } } }, { .name = "chmod", .ret_type = 1, .nargs = 2, .args = { { Name, 0 }, { Octal, 1 } } }, { .name = "chown", .ret_type = 1, .nargs = 3, .args = { { Name, 0 }, { Int, 1 }, { Int, 2 } } }, { .name = "chroot", .ret_type = 1, .nargs = 1, .args = { { Name, 0 } } }, { .name = "clock_gettime", .ret_type = 1, .nargs = 2, .args = { { Int, 0 }, { Timespec | OUT, 1 } } }, { .name = "close", .ret_type = 1, .nargs = 1, .args = { { Int, 0 } } }, { .name = "connect", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { Sockaddr | IN, 1 }, { Int, 2 } } }, { .name = "connectat", .ret_type = 1, .nargs = 4, .args = { { Atfd, 0 }, { Int, 1 }, { Sockaddr | IN, 2 }, { Int, 3 } } }, { .name = "eaccess", .ret_type = 1, .nargs = 2, .args = { { Name | IN, 0 }, { Accessmode, 1 } } }, { .name = "execve", .ret_type = 1, .nargs = 3, .args = { { Name | IN, 0 }, { ExecArgs | IN, 1 }, { ExecEnv | IN, 2 } } }, { .name = "exit", .ret_type = 0, .nargs = 1, .args = { { Hex, 0 } } }, { .name = "faccessat", .ret_type = 1, .nargs = 4, .args = { { Atfd, 0 }, { Name | IN, 1 }, { Accessmode, 2 }, { Atflags, 3 } } }, { .name = "fchmod", .ret_type = 1, .nargs = 2, .args = { { Int, 0 }, { Octal, 1 } } }, { .name = "fchmodat", .ret_type = 1, .nargs = 4, .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Atflags, 3 } } }, { .name = "fchown", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { Int, 1 }, { Int, 2 } } }, { .name = "fchownat", .ret_type = 1, .nargs = 5, .args = { { Atfd, 0 }, { Name, 1 }, { Int, 2 }, { Int, 3 }, { Atflags, 4 } } }, { .name = "fcntl", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { Fcntl, 1 }, { Fcntlflag, 2 } } }, { .name = "fstat", .ret_type = 1, .nargs = 2, .args = { { Int, 0 }, { Stat | OUT, 1 } } }, { .name = "fstatat", .ret_type = 1, .nargs = 4, .args = { { Atfd, 0 }, { Name | IN, 1 }, { Stat | OUT, 2 }, { Atflags, 3 } } }, { .name = "fstatfs", .ret_type = 1, .nargs = 2, .args = { { Int, 0 }, { StatFs | OUT, 1 } } }, { .name = "ftruncate", .ret_type = 1, .nargs = 2, .args = { { Int | IN, 0 }, { QuadHex | IN, 1 + QUAD_ALIGN } } }, { .name = "futimens", .ret_type = 1, .nargs = 2, .args = { { Int, 0 }, { Timespec2 | IN, 1 } } }, { .name = "futimes", .ret_type = 1, .nargs = 2, .args = { { Int, 0 }, { Timeval2 | IN, 1 } } }, { .name = "futimesat", .ret_type = 1, .nargs = 3, .args = { { Atfd, 0 }, { Name | IN, 1 }, { Timeval2 | IN, 2 } } }, { .name = "getitimer", .ret_type = 1, .nargs = 2, .args = { { Int, 0 }, { Itimerval | OUT, 2 } } }, { .name = "getpeername", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } }, { .name = "getpgid", .ret_type = 1, .nargs = 1, .args = { { Int, 0 } } }, { .name = "getrlimit", .ret_type = 1, .nargs = 2, .args = { { Resource, 0 }, { Rlimit | OUT, 1 } } }, { .name = "getrusage", .ret_type = 1, .nargs = 2, .args = { { Int, 0 }, { Rusage | OUT, 1 } } }, { .name = "getsid", .ret_type = 1, .nargs = 1, .args = { { Int, 0 } } }, { .name = "getsockname", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } }, { .name = "gettimeofday", .ret_type = 1, .nargs = 2, .args = { { Timeval | OUT, 0 }, { Ptr, 1 } } }, { .name = "ioctl", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { Ioctl, 1 }, { Hex, 2 } } }, { .name = "kevent", .ret_type = 1, .nargs = 6, .args = { { Int, 0 }, { Kevent, 1 }, { Int, 2 }, { Kevent | OUT, 3 }, { Int, 4 }, { Timespec, 5 } } }, { .name = "kill", .ret_type = 1, .nargs = 2, .args = { { Int | IN, 0 }, { Signal | IN, 1 } } }, { .name = "kldfind", .ret_type = 1, .nargs = 1, .args = { { Name | IN, 0 } } }, { .name = "kldfirstmod", .ret_type = 1, .nargs = 1, .args = { { Int, 0 } } }, { .name = "kldload", .ret_type = 1, .nargs = 1, .args = { { Name | IN, 0 } } }, { .name = "kldnext", .ret_type = 1, .nargs = 1, .args = { { Int, 0 } } }, { .name = "kldstat", .ret_type = 1, .nargs = 2, .args = { { Int, 0 }, { Ptr, 1 } } }, { .name = "kldunload", .ret_type = 1, .nargs = 1, .args = { { Int, 0 } } }, { .name = "kse_release", .ret_type = 0, .nargs = 1, .args = { { Timespec, 0 } } }, { .name = "lchflags", .ret_type = 1, .nargs = 2, .args = { { Name | IN, 0 }, { Hex, 1 } } }, { .name = "lchmod", .ret_type = 1, .nargs = 2, .args = { { Name, 0 }, { Octal, 1 } } }, { .name = "lchown", .ret_type = 1, .nargs = 3, .args = { { Name, 0 }, { Int, 1 }, { Int, 2 } } }, { .name = "link", .ret_type = 1, .nargs = 2, .args = { { Name, 0 }, { Name, 1 } } }, { .name = "linkat", .ret_type = 1, .nargs = 5, .args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 }, { Atflags, 4 } } }, { .name = "lseek", .ret_type = 2, .nargs = 3, .args = { { Int, 0 }, { QuadHex, 1 + QUAD_ALIGN }, { Whence, 1 + QUAD_SLOTS + QUAD_ALIGN } } }, { .name = "lstat", .ret_type = 1, .nargs = 2, .args = { { Name | IN, 0 }, { Stat | OUT, 1 } } }, { .name = "lutimes", .ret_type = 1, .nargs = 2, .args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } }, { .name = "mkdir", .ret_type = 1, .nargs = 2, .args = { { Name, 0 }, { Octal, 1 } } }, { .name = "mkdirat", .ret_type = 1, .nargs = 3, .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 } } }, { .name = "mkfifo", .ret_type = 1, .nargs = 2, .args = { { Name, 0 }, { Octal, 1 } } }, { .name = "mkfifoat", .ret_type = 1, .nargs = 3, .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 } } }, { .name = "mknod", .ret_type = 1, .nargs = 3, .args = { { Name, 0 }, { Octal, 1 }, { Int, 2 } } }, { .name = "mknodat", .ret_type = 1, .nargs = 4, .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Int, 3 } } }, { .name = "mmap", .ret_type = 1, .nargs = 6, .args = { { Ptr, 0 }, { Int, 1 }, { Mprot, 2 }, { Mmapflags, 3 }, { Int, 4 }, { QuadHex, 5 + QUAD_ALIGN } } }, { .name = "modfind", .ret_type = 1, .nargs = 1, .args = { { Name | IN, 0 } } }, { .name = "mount", .ret_type = 1, .nargs = 4, .args = { { Name, 0 }, { Name, 1 }, { Int, 2 }, { Ptr, 3 } } }, { .name = "mprotect", .ret_type = 1, .nargs = 3, .args = { { Ptr, 0 }, { Int, 1 }, { Mprot, 2 } } }, { .name = "munmap", .ret_type = 1, .nargs = 2, .args = { { Ptr, 0 }, { Int, 1 } } }, { .name = "nanosleep", .ret_type = 1, .nargs = 1, .args = { { Timespec, 0 } } }, { .name = "open", .ret_type = 1, .nargs = 3, .args = { { Name | IN, 0 }, { Open, 1 }, { Octal, 2 } } }, { .name = "openat", .ret_type = 1, .nargs = 4, .args = { { Atfd, 0 }, { Name | IN, 1 }, { Open, 2 }, { Octal, 3 } } }, { .name = "pathconf", .ret_type = 1, .nargs = 2, .args = { { Name | IN, 0 }, { Pathconf, 1 } } }, { .name = "pipe", .ret_type = 1, .nargs = 1, .args = { { PipeFds | OUT, 0 } } }, { .name = "pipe2", .ret_type = 1, .nargs = 2, - .args = { { Ptr, 0 }, { Open, 1 } } }, + .args = { { Ptr, 0 }, { Pipe2, 1 } } }, { .name = "poll", .ret_type = 1, .nargs = 3, .args = { { Pollfd, 0 }, { Int, 1 }, { Int, 2 } } }, { .name = "posix_openpt", .ret_type = 1, .nargs = 1, .args = { { Open, 0 } } }, { .name = "procctl", .ret_type = 1, .nargs = 4, .args = { { Idtype, 0 }, { Quad, 1 + QUAD_ALIGN }, { Procctl, 1 + QUAD_ALIGN + QUAD_SLOTS }, { Ptr, 2 + QUAD_ALIGN + QUAD_SLOTS } } }, { .name = "read", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 } } }, { .name = "readlink", .ret_type = 1, .nargs = 3, .args = { { Name, 0 }, { Readlinkres | OUT, 1 }, { Int, 2 } } }, { .name = "readlinkat", .ret_type = 1, .nargs = 4, .args = { { Atfd, 0 }, { Name, 1 }, { Readlinkres | OUT, 2 }, { Int, 3 } } }, { .name = "recvfrom", .ret_type = 1, .nargs = 6, .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 }, { Hex, 3 }, { Sockaddr | OUT, 4 }, { Ptr | OUT, 5 } } }, { .name = "rename", .ret_type = 1, .nargs = 2, .args = { { Name, 0 }, { Name, 1 } } }, { .name = "renameat", .ret_type = 1, .nargs = 4, .args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 } } }, { .name = "rfork", .ret_type = 1, .nargs = 1, .args = { { Rforkflags, 0 } } }, { .name = "rmdir", .ret_type = 1, .nargs = 1, .args = { { Name, 0 } } }, { .name = "select", .ret_type = 1, .nargs = 5, .args = { { Int, 0 }, { Fd_set, 1 }, { Fd_set, 2 }, { Fd_set, 3 }, { Timeval, 4 } } }, { .name = "sendto", .ret_type = 1, .nargs = 6, .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 }, { Hex, 3 }, { Sockaddr | IN, 4 }, { Ptr | IN, 5 } } }, { .name = "setitimer", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { Itimerval, 1 }, { Itimerval | OUT, 2 } } }, { .name = "setrlimit", .ret_type = 1, .nargs = 2, .args = { { Resource, 0 }, { Rlimit | IN, 1 } } }, { .name = "shutdown", .ret_type = 1, .nargs = 2, .args = { { Int, 0 }, { Shutdown, 1 } } }, { .name = "sigaction", .ret_type = 1, .nargs = 3, .args = { { Signal, 0 }, { Sigaction | IN, 1 }, { Sigaction | OUT, 2 } } }, { .name = "sigpending", .ret_type = 1, .nargs = 1, .args = { { Sigset | OUT, 0 } } }, { .name = "sigprocmask", .ret_type = 1, .nargs = 3, .args = { { Sigprocmask, 0 }, { Sigset, 1 }, { Sigset | OUT, 2 } } }, { .name = "sigqueue", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { Signal, 1 }, { LongHex, 2 } } }, { .name = "sigreturn", .ret_type = 1, .nargs = 1, .args = { { Ptr, 0 } } }, { .name = "sigsuspend", .ret_type = 1, .nargs = 1, .args = { { Sigset | IN, 0 } } }, { .name = "sigtimedwait", .ret_type = 1, .nargs = 3, .args = { { Sigset | IN, 0 }, { Ptr, 1 }, { Timespec | IN, 2 } } }, { .name = "sigwait", .ret_type = 1, .nargs = 2, .args = { { Sigset | IN, 0 }, { Ptr, 1 } } }, { .name = "sigwaitinfo", .ret_type = 1, .nargs = 2, .args = { { Sigset | IN, 0 }, { Ptr, 1 } } }, { .name = "socket", .ret_type = 1, .nargs = 3, .args = { { Sockdomain, 0 }, { Socktype, 1 }, { Int, 2 } } }, { .name = "stat", .ret_type = 1, .nargs = 2, .args = { { Name | IN, 0 }, { Stat | OUT, 1 } } }, { .name = "statfs", .ret_type = 1, .nargs = 2, .args = { { Name | IN, 0 }, { StatFs | OUT, 1 } } }, { .name = "symlink", .ret_type = 1, .nargs = 2, .args = { { Name, 0 }, { Name, 1 } } }, { .name = "symlinkat", .ret_type = 1, .nargs = 3, .args = { { Name, 0 }, { Atfd, 1 }, { Name, 2 } } }, { .name = "sysarch", .ret_type = 1, .nargs = 2, .args = { { Sysarch, 0 }, { Ptr, 1 } } }, { .name = "thr_kill", .ret_type = 1, .nargs = 2, .args = { { Long, 0 }, { Signal, 1 } } }, { .name = "thr_self", .ret_type = 1, .nargs = 1, .args = { { Ptr, 0 } } }, { .name = "truncate", .ret_type = 1, .nargs = 2, .args = { { Name | IN, 0 }, { QuadHex | IN, 1 + QUAD_ALIGN } } }, #if 0 /* Does not exist */ { .name = "umount", .ret_type = 1, .nargs = 2, .args = { { Name, 0 }, { Int, 2 } } }, #endif { .name = "unlink", .ret_type = 1, .nargs = 1, .args = { { Name, 0 } } }, { .name = "unlinkat", .ret_type = 1, .nargs = 3, .args = { { Atfd, 0 }, { Name, 1 }, { Atflags, 2 } } }, { .name = "unmount", .ret_type = 1, .nargs = 2, .args = { { Name, 0 }, { Int, 1 } } }, { .name = "utimensat", .ret_type = 1, .nargs = 4, .args = { { Atfd, 0 }, { Name | IN, 1 }, { Timespec2 | IN, 2 }, { Atflags, 3 } } }, { .name = "utimes", .ret_type = 1, .nargs = 2, .args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } }, { .name = "utrace", .ret_type = 1, .nargs = 1, .args = { { Utrace, 0 } } }, { .name = "wait4", .ret_type = 1, .nargs = 4, .args = { { Int, 0 }, { ExitStatus | OUT, 1 }, { Waitoptions, 2 }, { Rusage | OUT, 3 } } }, { .name = "wait6", .ret_type = 1, .nargs = 6, .args = { { Idtype, 0 }, { Quad, 1 + QUAD_ALIGN }, { ExitStatus | OUT, 1 + QUAD_ALIGN + QUAD_SLOTS }, { Waitoptions, 2 + QUAD_ALIGN + QUAD_SLOTS }, { Rusage | OUT, 3 + QUAD_ALIGN + QUAD_SLOTS }, { Ptr, 4 + QUAD_ALIGN + QUAD_SLOTS } } }, { .name = "write", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 } } }, /* Linux ABI */ { .name = "linux_access", .ret_type = 1, .nargs = 2, .args = { { Name, 0 }, { Accessmode, 1 } } }, { .name = "linux_execve", .ret_type = 1, .nargs = 3, .args = { { Name | IN, 0 }, { ExecArgs | IN, 1 }, { ExecEnv | IN, 2 } } }, { .name = "linux_lseek", .ret_type = 2, .nargs = 3, .args = { { Int, 0 }, { Int, 1 }, { Whence, 2 } } }, { .name = "linux_mkdir", .ret_type = 1, .nargs = 2, .args = { { Name | IN, 0 }, { Int, 1 } } }, { .name = "linux_newfstat", .ret_type = 1, .nargs = 2, .args = { { Int, 0 }, { Ptr | OUT, 1 } } }, { .name = "linux_newstat", .ret_type = 1, .nargs = 2, .args = { { Name | IN, 0 }, { Ptr | OUT, 1 } } }, { .name = "linux_open", .ret_type = 1, .nargs = 3, .args = { { Name, 0 }, { Hex, 1 }, { Octal, 2 } } }, { .name = "linux_readlink", .ret_type = 1, .nargs = 3, .args = { { Name, 0 }, { Name | OUT, 1 }, { Int, 2 } } }, { .name = "linux_socketcall", .ret_type = 1, .nargs = 2, .args = { { Int, 0 }, { LinuxSockArgs, 1 } } }, { .name = "linux_stat64", .ret_type = 1, .nargs = 3, .args = { { Name | IN, 0 }, { Ptr | OUT, 1 }, { Ptr | IN, 1 } } }, /* CloudABI system calls. */ { .name = "cloudabi_sys_clock_res_get", .ret_type = 1, .nargs = 1, .args = { { CloudABIClockID, 0 } } }, { .name = "cloudabi_sys_clock_time_get", .ret_type = 1, .nargs = 2, .args = { { CloudABIClockID, 0 }, { CloudABITimestamp, 1 } } }, { .name = "cloudabi_sys_condvar_signal", .ret_type = 1, .nargs = 3, .args = { { Ptr, 0 }, { CloudABIMFlags, 1 }, { UInt, 2 } } }, { .name = "cloudabi_sys_fd_close", .ret_type = 1, .nargs = 1, .args = { { Int, 0 } } }, { .name = "cloudabi_sys_fd_create1", .ret_type = 1, .nargs = 1, .args = { { CloudABIFileType, 0 } } }, { .name = "cloudabi_sys_fd_create2", .ret_type = 1, .nargs = 2, .args = { { CloudABIFileType, 0 }, { PipeFds | OUT, 0 } } }, { .name = "cloudabi_sys_fd_datasync", .ret_type = 1, .nargs = 1, .args = { { Int, 0 } } }, { .name = "cloudabi_sys_fd_dup", .ret_type = 1, .nargs = 1, .args = { { Int, 0 } } }, { .name = "cloudabi_sys_fd_replace", .ret_type = 1, .nargs = 2, .args = { { Int, 0 }, { Int, 1 } } }, { .name = "cloudabi_sys_fd_seek", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { Int, 1 }, { CloudABIWhence, 2 } } }, { .name = "cloudabi_sys_fd_stat_get", .ret_type = 1, .nargs = 2, .args = { { Int, 0 }, { CloudABIFDStat | OUT, 1 } } }, { .name = "cloudabi_sys_fd_stat_put", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { CloudABIFDStat | IN, 1 }, { ClouduABIFDSFlags, 2 } } }, { .name = "cloudabi_sys_fd_sync", .ret_type = 1, .nargs = 1, .args = { { Int, 0 } } }, { .name = "cloudabi_sys_file_advise", .ret_type = 1, .nargs = 4, .args = { { Int, 0 }, { Int, 1 }, { Int, 2 }, { CloudABIAdvice, 3 } } }, { .name = "cloudabi_sys_file_allocate", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { Int, 1 }, { Int, 2 } } }, { .name = "cloudabi_sys_file_create", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { BinString | IN, 1 }, { CloudABIFileType, 3 } } }, { .name = "cloudabi_sys_file_link", .ret_type = 1, .nargs = 4, .args = { { CloudABILookup, 0 }, { BinString | IN, 1 }, { Int, 3 }, { BinString | IN, 4 } } }, { .name = "cloudabi_sys_file_open", .ret_type = 1, .nargs = 4, .args = { { Int, 0 }, { BinString | IN, 1 }, { CloudABIOFlags, 3 }, { CloudABIFDStat | IN, 4 } } }, { .name = "cloudabi_sys_file_readdir", .ret_type = 1, .nargs = 4, .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 }, { Int, 3 } } }, { .name = "cloudabi_sys_file_readlink", .ret_type = 1, .nargs = 4, .args = { { Int, 0 }, { BinString | IN, 1 }, { BinString | OUT, 3 }, { Int, 4 } } }, { .name = "cloudabi_sys_file_rename", .ret_type = 1, .nargs = 4, .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 3 }, { BinString | IN, 4 } } }, { .name = "cloudabi_sys_file_stat_fget", .ret_type = 1, .nargs = 2, .args = { { Int, 0 }, { CloudABIFileStat | OUT, 1 } } }, { .name = "cloudabi_sys_file_stat_fput", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { CloudABIFileStat | IN, 1 }, { CloudABIFSFlags, 2 } } }, { .name = "cloudabi_sys_file_stat_get", .ret_type = 1, .nargs = 3, .args = { { CloudABILookup, 0 }, { BinString | IN, 1 }, { CloudABIFileStat | OUT, 3 } } }, { .name = "cloudabi_sys_file_stat_put", .ret_type = 1, .nargs = 4, .args = { { CloudABILookup, 0 }, { BinString | IN, 1 }, { CloudABIFileStat | IN, 3 }, { CloudABIFSFlags, 4 } } }, { .name = "cloudabi_sys_file_symlink", .ret_type = 1, .nargs = 3, .args = { { BinString | IN, 0 }, { Int, 2 }, { BinString | IN, 3 } } }, { .name = "cloudabi_sys_file_unlink", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { BinString | IN, 1 }, { CloudABIULFlags, 3 } } }, { .name = "cloudabi_sys_lock_unlock", .ret_type = 1, .nargs = 2, .args = { { Ptr, 0 }, { CloudABIMFlags, 1 } } }, { .name = "cloudabi_sys_mem_advise", .ret_type = 1, .nargs = 3, .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIAdvice, 2 } } }, { .name = "cloudabi_sys_mem_lock", .ret_type = 1, .nargs = 2, .args = { { Ptr, 0 }, { Int, 1 } } }, { .name = "cloudabi_sys_mem_map", .ret_type = 1, .nargs = 6, .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMProt, 2 }, { CloudABIMFlags, 3 }, { Int, 4 }, { Int, 5 } } }, { .name = "cloudabi_sys_mem_protect", .ret_type = 1, .nargs = 3, .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMProt, 2 } } }, { .name = "cloudabi_sys_mem_sync", .ret_type = 1, .nargs = 3, .args = { { Ptr, 0 }, { Int, 1 }, { CloudABIMSFlags, 2 } } }, { .name = "cloudabi_sys_mem_unlock", .ret_type = 1, .nargs = 2, .args = { { Ptr, 0 }, { Int, 1 } } }, { .name = "cloudabi_sys_mem_unmap", .ret_type = 1, .nargs = 2, .args = { { Ptr, 0 }, { Int, 1 } } }, { .name = "cloudabi_sys_proc_exec", .ret_type = 1, .nargs = 5, .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 }, { IntArray, 3 }, { Int, 4 } } }, { .name = "cloudabi_sys_proc_exit", .ret_type = 1, .nargs = 1, .args = { { Int, 0 } } }, { .name = "cloudabi_sys_proc_fork", .ret_type = 1, .nargs = 0 }, { .name = "cloudabi_sys_proc_raise", .ret_type = 1, .nargs = 1, .args = { { CloudABISignal, 0 } } }, { .name = "cloudabi_sys_random_get", .ret_type = 1, .nargs = 2, .args = { { BinString | OUT, 0 }, { Int, 1 } } }, { .name = "cloudabi_sys_sock_accept", .ret_type = 1, .nargs = 2, .args = { { Int, 0 }, { CloudABISockStat | OUT, 1 } } }, { .name = "cloudabi_sys_sock_bind", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { Int, 1 }, { BinString | IN, 2 } } }, { .name = "cloudabi_sys_sock_connect", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { Int, 1 }, { BinString | IN, 2 } } }, { .name = "cloudabi_sys_sock_listen", .ret_type = 1, .nargs = 2, .args = { { Int, 0 }, { Int, 1 } } }, { .name = "cloudabi_sys_sock_shutdown", .ret_type = 1, .nargs = 2, .args = { { Int, 0 }, { CloudABISDFlags, 1 } } }, { .name = "cloudabi_sys_sock_stat_get", .ret_type = 1, .nargs = 3, .args = { { Int, 0 }, { CloudABISockStat | OUT, 1 }, { CloudABISSFlags, 2 } } }, { .name = "cloudabi_sys_thread_exit", .ret_type = 1, .nargs = 2, .args = { { Ptr, 0 }, { CloudABIMFlags, 1 } } }, { .name = "cloudabi_sys_thread_yield", .ret_type = 1, .nargs = 0 }, { .name = 0 }, }; static STAILQ_HEAD(, syscall) syscalls; /* Xlat idea taken from strace */ struct xlat { int val; const char *str; }; #define X(a) { a, #a }, #define XEND { 0, NULL } static struct xlat kevent_filters[] = { X(EVFILT_READ) X(EVFILT_WRITE) X(EVFILT_AIO) X(EVFILT_VNODE) X(EVFILT_PROC) X(EVFILT_SIGNAL) X(EVFILT_TIMER) X(EVFILT_PROCDESC) X(EVFILT_FS) X(EVFILT_LIO) X(EVFILT_USER) X(EVFILT_SENDFILE) XEND }; static struct xlat kevent_flags[] = { X(EV_ADD) X(EV_DELETE) X(EV_ENABLE) X(EV_DISABLE) X(EV_ONESHOT) X(EV_CLEAR) X(EV_RECEIPT) X(EV_DISPATCH) X(EV_FORCEONESHOT) X(EV_DROP) X(EV_FLAG1) X(EV_ERROR) X(EV_EOF) XEND }; static struct xlat kevent_user_ffctrl[] = { X(NOTE_FFNOP) X(NOTE_FFAND) X(NOTE_FFOR) X(NOTE_FFCOPY) XEND }; static struct xlat kevent_rdwr_fflags[] = { X(NOTE_LOWAT) X(NOTE_FILE_POLL) XEND }; static struct xlat kevent_vnode_fflags[] = { X(NOTE_DELETE) X(NOTE_WRITE) X(NOTE_EXTEND) X(NOTE_ATTRIB) X(NOTE_LINK) X(NOTE_RENAME) X(NOTE_REVOKE) XEND }; static struct xlat kevent_proc_fflags[] = { X(NOTE_EXIT) X(NOTE_FORK) X(NOTE_EXEC) X(NOTE_TRACK) X(NOTE_TRACKERR) X(NOTE_CHILD) XEND }; static struct xlat kevent_timer_fflags[] = { X(NOTE_SECONDS) X(NOTE_MSECONDS) X(NOTE_USECONDS) X(NOTE_NSECONDS) XEND }; static struct xlat poll_flags[] = { X(POLLSTANDARD) X(POLLIN) X(POLLPRI) X(POLLOUT) X(POLLERR) X(POLLHUP) X(POLLNVAL) X(POLLRDNORM) X(POLLRDBAND) X(POLLWRBAND) X(POLLINIGNEOF) XEND }; -static struct xlat mmap_flags[] = { - X(MAP_SHARED) X(MAP_PRIVATE) X(MAP_FIXED) X(MAP_RESERVED0020) - X(MAP_RESERVED0040) X(MAP_RESERVED0080) X(MAP_RESERVED0100) - X(MAP_HASSEMAPHORE) X(MAP_STACK) X(MAP_NOSYNC) X(MAP_ANON) - X(MAP_EXCL) X(MAP_NOCORE) X(MAP_PREFAULT_READ) -#ifdef MAP_32BIT - X(MAP_32BIT) -#endif - XEND -}; - -static struct xlat mprot_flags[] = { - X(PROT_NONE) X(PROT_READ) X(PROT_WRITE) X(PROT_EXEC) XEND -}; - -static struct xlat whence_arg[] = { - X(SEEK_SET) X(SEEK_CUR) X(SEEK_END) X(SEEK_DATA) X(SEEK_HOLE) XEND -}; - static struct xlat sigaction_flags[] = { X(SA_ONSTACK) X(SA_RESTART) X(SA_RESETHAND) X(SA_NOCLDSTOP) X(SA_NODEFER) X(SA_NOCLDWAIT) X(SA_SIGINFO) XEND }; -static struct xlat fcntl_arg[] = { - X(F_DUPFD) X(F_GETFD) X(F_SETFD) X(F_GETFL) X(F_SETFL) - X(F_GETOWN) X(F_SETOWN) X(F_OGETLK) X(F_OSETLK) X(F_OSETLKW) - X(F_DUP2FD) X(F_GETLK) X(F_SETLK) X(F_SETLKW) X(F_SETLK_REMOTE) - X(F_READAHEAD) X(F_RDAHEAD) X(F_DUPFD_CLOEXEC) X(F_DUP2FD_CLOEXEC) - XEND -}; - -static struct xlat fcntlfd_arg[] = { - X(FD_CLOEXEC) XEND -}; - -static struct xlat fcntlfl_arg[] = { - X(O_APPEND) X(O_ASYNC) X(O_FSYNC) X(O_NONBLOCK) X(O_NOFOLLOW) - X(FRDAHEAD) X(O_DIRECT) XEND -}; - -static struct xlat sockdomain_arg[] = { - X(PF_UNSPEC) X(PF_LOCAL) X(PF_UNIX) X(PF_INET) X(PF_IMPLINK) - X(PF_PUP) X(PF_CHAOS) X(PF_NETBIOS) X(PF_ISO) X(PF_OSI) - X(PF_ECMA) X(PF_DATAKIT) X(PF_CCITT) X(PF_SNA) X(PF_DECnet) - X(PF_DLI) X(PF_LAT) X(PF_HYLINK) X(PF_APPLETALK) X(PF_ROUTE) - X(PF_LINK) X(PF_XTP) X(PF_COIP) X(PF_CNT) X(PF_SIP) X(PF_IPX) - X(PF_RTIP) X(PF_PIP) X(PF_ISDN) X(PF_KEY) X(PF_INET6) - X(PF_NATM) X(PF_ATM) X(PF_NETGRAPH) X(PF_SLOW) X(PF_SCLUSTER) - X(PF_ARP) X(PF_BLUETOOTH) X(PF_IEEE80211) X(PF_INET_SDP) - X(PF_INET6_SDP) XEND -}; - -static struct xlat socktype_arg[] = { - X(SOCK_STREAM) X(SOCK_DGRAM) X(SOCK_RAW) X(SOCK_RDM) - X(SOCK_SEQPACKET) XEND -}; - -static struct xlat open_flags[] = { - X(O_RDONLY) X(O_WRONLY) X(O_RDWR) X(O_ACCMODE) X(O_NONBLOCK) - X(O_APPEND) X(O_SHLOCK) X(O_EXLOCK) X(O_ASYNC) X(O_FSYNC) - X(O_NOFOLLOW) X(O_CREAT) X(O_TRUNC) X(O_EXCL) X(O_NOCTTY) - X(O_DIRECT) X(O_DIRECTORY) X(O_EXEC) X(O_TTY_INIT) X(O_CLOEXEC) - X(O_VERIFY) XEND -}; - -static struct xlat shutdown_arg[] = { - X(SHUT_RD) X(SHUT_WR) X(SHUT_RDWR) XEND -}; - -static struct xlat resource_arg[] = { - X(RLIMIT_CPU) X(RLIMIT_FSIZE) X(RLIMIT_DATA) X(RLIMIT_STACK) - X(RLIMIT_CORE) X(RLIMIT_RSS) X(RLIMIT_MEMLOCK) X(RLIMIT_NPROC) - X(RLIMIT_NOFILE) X(RLIMIT_SBSIZE) X(RLIMIT_VMEM) X(RLIMIT_NPTS) - X(RLIMIT_SWAP) X(RLIMIT_KQUEUES) XEND -}; - static struct xlat pathconf_arg[] = { X(_PC_LINK_MAX) X(_PC_MAX_CANON) X(_PC_MAX_INPUT) X(_PC_NAME_MAX) X(_PC_PATH_MAX) X(_PC_PIPE_BUF) X(_PC_CHOWN_RESTRICTED) X(_PC_NO_TRUNC) X(_PC_VDISABLE) X(_PC_ASYNC_IO) X(_PC_PRIO_IO) X(_PC_SYNC_IO) X(_PC_ALLOC_SIZE_MIN) X(_PC_FILESIZEBITS) X(_PC_REC_INCR_XFER_SIZE) X(_PC_REC_MAX_XFER_SIZE) X(_PC_REC_MIN_XFER_SIZE) X(_PC_REC_XFER_ALIGN) X(_PC_SYMLINK_MAX) X(_PC_ACL_EXTENDED) X(_PC_ACL_PATH_MAX) X(_PC_CAP_PRESENT) X(_PC_INF_PRESENT) X(_PC_MAC_PRESENT) X(_PC_ACL_NFS4) X(_PC_MIN_HOLE_SIZE) XEND }; -static struct xlat rfork_flags[] = { - X(RFFDG) X(RFPROC) X(RFMEM) X(RFNOWAIT) X(RFCFDG) X(RFTHREAD) - X(RFSIGSHARE) X(RFLINUXTHPN) X(RFTSIGZMB) X(RFPPWAIT) XEND -}; - -static struct xlat wait_options[] = { - X(WNOHANG) X(WUNTRACED) X(WCONTINUED) X(WNOWAIT) X(WEXITED) - X(WTRAPPED) XEND -}; - -static struct xlat idtype_arg[] = { - X(P_PID) X(P_PPID) X(P_PGID) X(P_SID) X(P_CID) X(P_UID) X(P_GID) - X(P_ALL) X(P_LWPID) X(P_TASKID) X(P_PROJID) X(P_POOLID) X(P_JAILID) - X(P_CTID) X(P_CPUID) X(P_PSETID) XEND -}; - -static struct xlat procctl_arg[] = { - X(PROC_SPROTECT) X(PROC_REAP_ACQUIRE) X(PROC_REAP_RELEASE) - X(PROC_REAP_STATUS) X(PROC_REAP_GETPIDS) X(PROC_REAP_KILL) - X(PROC_TRACE_CTL) X(PROC_TRACE_STATUS) XEND -}; - -static struct xlat umtx_ops[] = { - X(UMTX_OP_RESERVED0) X(UMTX_OP_RESERVED1) X(UMTX_OP_WAIT) - X(UMTX_OP_WAKE) X(UMTX_OP_MUTEX_TRYLOCK) X(UMTX_OP_MUTEX_LOCK) - X(UMTX_OP_MUTEX_UNLOCK) X(UMTX_OP_SET_CEILING) X(UMTX_OP_CV_WAIT) - X(UMTX_OP_CV_SIGNAL) X(UMTX_OP_CV_BROADCAST) X(UMTX_OP_WAIT_UINT) - X(UMTX_OP_RW_RDLOCK) X(UMTX_OP_RW_WRLOCK) X(UMTX_OP_RW_UNLOCK) - X(UMTX_OP_WAIT_UINT_PRIVATE) X(UMTX_OP_WAKE_PRIVATE) - X(UMTX_OP_MUTEX_WAIT) X(UMTX_OP_MUTEX_WAKE) X(UMTX_OP_SEM_WAIT) - X(UMTX_OP_SEM_WAKE) X(UMTX_OP_NWAKE_PRIVATE) X(UMTX_OP_MUTEX_WAKE2) - X(UMTX_OP_SEM2_WAIT) X(UMTX_OP_SEM2_WAKE) - XEND -}; - static struct xlat at_flags[] = { X(AT_EACCESS) X(AT_SYMLINK_NOFOLLOW) X(AT_SYMLINK_FOLLOW) X(AT_REMOVEDIR) XEND }; -static struct xlat access_modes[] = { - X(R_OK) X(W_OK) X(X_OK) XEND -}; - static struct xlat sysarch_ops[] = { #if defined(__i386__) || defined(__amd64__) X(I386_GET_LDT) X(I386_SET_LDT) X(I386_GET_IOPERM) X(I386_SET_IOPERM) X(I386_VM86) X(I386_GET_FSBASE) X(I386_SET_FSBASE) X(I386_GET_GSBASE) X(I386_SET_GSBASE) X(I386_GET_XFPUSTATE) X(AMD64_GET_FSBASE) X(AMD64_SET_FSBASE) X(AMD64_GET_GSBASE) X(AMD64_SET_GSBASE) X(AMD64_GET_XFPUSTATE) #endif XEND }; static struct xlat linux_socketcall_ops[] = { X(LINUX_SOCKET) X(LINUX_BIND) X(LINUX_CONNECT) X(LINUX_LISTEN) X(LINUX_ACCEPT) X(LINUX_GETSOCKNAME) X(LINUX_GETPEERNAME) X(LINUX_SOCKETPAIR) X(LINUX_SEND) X(LINUX_RECV) X(LINUX_SENDTO) X(LINUX_RECVFROM) X(LINUX_SHUTDOWN) X(LINUX_SETSOCKOPT) X(LINUX_GETSOCKOPT) X(LINUX_SENDMSG) X(LINUX_RECVMSG) XEND }; -static struct xlat sigprocmask_ops[] = { - X(SIG_BLOCK) X(SIG_UNBLOCK) X(SIG_SETMASK) - XEND -}; - #undef X #define X(a) { CLOUDABI_##a, #a }, static struct xlat cloudabi_advice[] = { X(ADVICE_DONTNEED) X(ADVICE_NOREUSE) X(ADVICE_NORMAL) X(ADVICE_RANDOM) X(ADVICE_SEQUENTIAL) X(ADVICE_WILLNEED) XEND }; static struct xlat cloudabi_clockid[] = { X(CLOCK_MONOTONIC) X(CLOCK_PROCESS_CPUTIME_ID) X(CLOCK_REALTIME) X(CLOCK_THREAD_CPUTIME_ID) XEND }; static struct xlat cloudabi_errno[] = { X(E2BIG) X(EACCES) X(EADDRINUSE) X(EADDRNOTAVAIL) X(EAFNOSUPPORT) X(EAGAIN) X(EALREADY) X(EBADF) X(EBADMSG) X(EBUSY) X(ECANCELED) X(ECHILD) X(ECONNABORTED) X(ECONNREFUSED) X(ECONNRESET) X(EDEADLK) X(EDESTADDRREQ) X(EDOM) X(EDQUOT) X(EEXIST) X(EFAULT) X(EFBIG) X(EHOSTUNREACH) X(EIDRM) X(EILSEQ) X(EINPROGRESS) X(EINTR) X(EINVAL) X(EIO) X(EISCONN) X(EISDIR) X(ELOOP) X(EMFILE) X(EMLINK) X(EMSGSIZE) X(EMULTIHOP) X(ENAMETOOLONG) X(ENETDOWN) X(ENETRESET) X(ENETUNREACH) X(ENFILE) X(ENOBUFS) X(ENODEV) X(ENOENT) X(ENOEXEC) X(ENOLCK) X(ENOLINK) X(ENOMEM) X(ENOMSG) X(ENOPROTOOPT) X(ENOSPC) X(ENOSYS) X(ENOTCONN) X(ENOTDIR) X(ENOTEMPTY) X(ENOTRECOVERABLE) X(ENOTSOCK) X(ENOTSUP) X(ENOTTY) X(ENXIO) X(EOVERFLOW) X(EOWNERDEAD) X(EPERM) X(EPIPE) X(EPROTO) X(EPROTONOSUPPORT) X(EPROTOTYPE) X(ERANGE) X(EROFS) X(ESPIPE) X(ESRCH) X(ESTALE) X(ETIMEDOUT) X(ETXTBSY) X(EXDEV) X(ENOTCAPABLE) XEND }; static struct xlat cloudabi_fdflags[] = { X(FDFLAG_APPEND) X(FDFLAG_DSYNC) X(FDFLAG_NONBLOCK) X(FDFLAG_RSYNC) X(FDFLAG_SYNC) XEND }; static struct xlat cloudabi_fdsflags[] = { X(FDSTAT_FLAGS) X(FDSTAT_RIGHTS) XEND }; static struct xlat cloudabi_filetype[] = { X(FILETYPE_UNKNOWN) X(FILETYPE_BLOCK_DEVICE) X(FILETYPE_CHARACTER_DEVICE) X(FILETYPE_DIRECTORY) X(FILETYPE_FIFO) X(FILETYPE_POLL) X(FILETYPE_PROCESS) X(FILETYPE_REGULAR_FILE) X(FILETYPE_SHARED_MEMORY) X(FILETYPE_SOCKET_DGRAM) X(FILETYPE_SOCKET_SEQPACKET) X(FILETYPE_SOCKET_STREAM) X(FILETYPE_SYMBOLIC_LINK) XEND }; static struct xlat cloudabi_fsflags[] = { X(FILESTAT_ATIM) X(FILESTAT_ATIM_NOW) X(FILESTAT_MTIM) X(FILESTAT_MTIM_NOW) X(FILESTAT_SIZE) XEND }; static struct xlat cloudabi_mflags[] = { X(MAP_ANON) X(MAP_FIXED) X(MAP_PRIVATE) X(MAP_SHARED) XEND }; static struct xlat cloudabi_mprot[] = { X(PROT_EXEC) X(PROT_WRITE) X(PROT_READ) XEND }; static struct xlat cloudabi_msflags[] = { X(MS_ASYNC) X(MS_INVALIDATE) X(MS_SYNC) XEND }; static struct xlat cloudabi_oflags[] = { X(O_CREAT) X(O_DIRECTORY) X(O_EXCL) X(O_TRUNC) XEND }; static struct xlat cloudabi_sa_family[] = { X(AF_UNSPEC) X(AF_INET) X(AF_INET6) X(AF_UNIX) XEND }; static struct xlat cloudabi_sdflags[] = { X(SHUT_RD) X(SHUT_WR) XEND }; static struct xlat cloudabi_signal[] = { X(SIGABRT) X(SIGALRM) X(SIGBUS) X(SIGCHLD) X(SIGCONT) X(SIGFPE) X(SIGHUP) X(SIGILL) X(SIGINT) X(SIGKILL) X(SIGPIPE) X(SIGQUIT) X(SIGSEGV) X(SIGSTOP) X(SIGSYS) X(SIGTERM) X(SIGTRAP) X(SIGTSTP) X(SIGTTIN) X(SIGTTOU) X(SIGURG) X(SIGUSR1) X(SIGUSR2) X(SIGVTALRM) X(SIGXCPU) X(SIGXFSZ) XEND }; static struct xlat cloudabi_ssflags[] = { X(SOCKSTAT_CLEAR_ERROR) XEND }; static struct xlat cloudabi_ssstate[] = { X(SOCKSTATE_ACCEPTCONN) XEND }; static struct xlat cloudabi_ulflags[] = { X(UNLINK_REMOVEDIR) XEND }; static struct xlat cloudabi_whence[] = { X(WHENCE_CUR) X(WHENCE_END) X(WHENCE_SET) XEND }; #undef X #undef XEND /* * Searches an xlat array for a value, and returns it if found. Otherwise * return a string representation. */ static const char * lookup(struct xlat *xlat, int val, int base) { static char tmp[16]; for (; xlat->str != NULL; xlat++) if (xlat->val == val) return (xlat->str); switch (base) { case 8: sprintf(tmp, "0%o", val); break; case 16: sprintf(tmp, "0x%x", val); break; case 10: sprintf(tmp, "%u", val); break; default: errx(1,"Unknown lookup base"); break; } return (tmp); } static const char * xlookup(struct xlat *xlat, int val) { return (lookup(xlat, val, 16)); } /* * Searches an xlat array containing bitfield values. Remaining bits * set after removing the known ones are printed at the end: * IN|0x400. */ static char * xlookup_bits(struct xlat *xlat, int val) { int len, rem; static char str[512]; len = 0; rem = val; for (; xlat->str != NULL; xlat++) { if ((xlat->val & rem) == xlat->val) { /* * Don't print the "all-bits-zero" string unless all * bits are really zero. */ if (xlat->val == 0 && val != 0) continue; len += sprintf(str + len, "%s|", xlat->str); rem &= ~(xlat->val); } } /* * If we have leftover bits or didn't match anything, print * the remainder. */ if (rem || len == 0) len += sprintf(str + len, "0x%x", rem); if (len && str[len - 1] == '|') len--; str[len] = 0; return (str); } +static void +print_integer_arg(const char *(*decoder)(int), FILE *fp, int value) +{ + const char *str; + + str = decoder(value); + if (str != NULL) + fputs(str, fp); + else + fprintf(fp, "%d", value); +} + +static void +print_mask_arg(bool (*decoder)(FILE *, int, int *), FILE *fp, int value) +{ + int rem; + + if (!decoder(fp, value, &rem)) + fprintf(fp, "0x%x", rem); + else if (rem != 0) + fprintf(fp, "|0x%x", rem); +} + void init_syscalls(void) { struct syscall *sc; STAILQ_INIT(&syscalls); for (sc = decoded_syscalls; sc->name != NULL; sc++) STAILQ_INSERT_HEAD(&syscalls, sc, entries); } /* * If/when the list gets big, it might be desirable to do it * as a hash table or binary search. */ struct syscall * get_syscall(const char *name, int nargs) { struct syscall *sc; int i; if (name == NULL) return (NULL); STAILQ_FOREACH(sc, &syscalls, entries) if (strcmp(name, sc->name) == 0) return (sc); /* It is unknown. Add it into the list. */ #if DEBUG fprintf(stderr, "unknown syscall %s -- setting args to %d\n", name, nargs); #endif sc = calloc(1, sizeof(struct syscall)); sc->name = strdup(name); sc->ret_type = 1; sc->nargs = nargs; for (i = 0; i < nargs; i++) { sc->args[i].offset = i; /* Treat all unknown arguments as LongHex. */ sc->args[i].type = LongHex; } STAILQ_INSERT_HEAD(&syscalls, sc, entries); return (sc); } /* * Copy a fixed amount of bytes from the process. */ static int get_struct(pid_t pid, void *offset, void *buf, int len) { struct ptrace_io_desc iorequest; iorequest.piod_op = PIOD_READ_D; iorequest.piod_offs = offset; iorequest.piod_addr = buf; iorequest.piod_len = len; if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0) return (-1); return (0); } #define MAXSIZE 4096 /* * Copy a string from the process. Note that it is * expected to be a C string, but if max is set, it will * only get that much. */ static char * get_string(pid_t pid, void *addr, int max) { struct ptrace_io_desc iorequest; char *buf, *nbuf; size_t offset, size, totalsize; offset = 0; if (max) size = max + 1; else { /* Read up to the end of the current page. */ size = PAGE_SIZE - ((uintptr_t)addr % PAGE_SIZE); if (size > MAXSIZE) size = MAXSIZE; } totalsize = size; buf = malloc(totalsize); if (buf == NULL) return (NULL); for (;;) { iorequest.piod_op = PIOD_READ_D; iorequest.piod_offs = (char *)addr + offset; iorequest.piod_addr = buf + offset; iorequest.piod_len = size; if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0) { free(buf); return (NULL); } if (memchr(buf + offset, '\0', size) != NULL) return (buf); offset += size; if (totalsize < MAXSIZE && max == 0) { size = MAXSIZE - totalsize; if (size > PAGE_SIZE) size = PAGE_SIZE; nbuf = realloc(buf, totalsize + size); if (nbuf == NULL) { buf[totalsize - 1] = '\0'; return (buf); } buf = nbuf; totalsize += size; } else { buf[totalsize - 1] = '\0'; return (buf); } } } -static char * +static const char * strsig2(int sig) { - static char tmp[sizeof(int) * 3 + 1]; - char *ret; + static char tmp[32]; + const char *signame; - ret = strsig(sig); - if (ret == NULL) { + signame = sysdecode_signal(sig); + if (signame == NULL) { snprintf(tmp, sizeof(tmp), "%d", sig); - ret = tmp; + signame = tmp; } - return (ret); + return (signame); } static void print_kevent(FILE *fp, struct kevent *ke, int input) { switch (ke->filter) { case EVFILT_READ: case EVFILT_WRITE: case EVFILT_VNODE: case EVFILT_PROC: case EVFILT_TIMER: case EVFILT_PROCDESC: fprintf(fp, "%ju", (uintmax_t)ke->ident); break; case EVFILT_SIGNAL: fputs(strsig2(ke->ident), fp); break; default: fprintf(fp, "%p", (void *)ke->ident); } fprintf(fp, ",%s,%s,", xlookup(kevent_filters, ke->filter), xlookup_bits(kevent_flags, ke->flags)); switch (ke->filter) { case EVFILT_READ: case EVFILT_WRITE: fputs(xlookup_bits(kevent_rdwr_fflags, ke->fflags), fp); break; case EVFILT_VNODE: fputs(xlookup_bits(kevent_vnode_fflags, ke->fflags), fp); break; case EVFILT_PROC: case EVFILT_PROCDESC: fputs(xlookup_bits(kevent_proc_fflags, ke->fflags), fp); break; case EVFILT_TIMER: fputs(xlookup_bits(kevent_timer_fflags, ke->fflags), fp); break; case EVFILT_USER: { int ctrl, data; ctrl = ke->fflags & NOTE_FFCTRLMASK; data = ke->fflags & NOTE_FFLAGSMASK; if (input) { fputs(xlookup(kevent_user_ffctrl, ctrl), fp); if (ke->fflags & NOTE_TRIGGER) fputs("|NOTE_TRIGGER", fp); if (data != 0) fprintf(fp, "|%#x", data); } else { fprintf(fp, "%#x", data); } break; } default: fprintf(fp, "%#x", ke->fflags); } fprintf(fp, ",%p,%p", (void *)ke->data, (void *)ke->udata); } static void print_utrace(FILE *fp, void *utrace_addr, size_t len) { unsigned char *utrace_buffer; fprintf(fp, "{ "); if (sysdecode_utrace(fp, utrace_addr, len)) { fprintf(fp, " }"); return; } utrace_buffer = utrace_addr; fprintf(fp, "%zu:", len); while (len--) fprintf(fp, " %02x", *utrace_buffer++); fprintf(fp, " }"); } /* * Converts a syscall argument into a string. Said string is * allocated via malloc(), so needs to be free()'d. sc is * a pointer to the syscall description (see above); args is * an array of all of the system call arguments. */ char * print_arg(struct syscall_args *sc, unsigned long *args, long *retval, struct trussinfo *trussinfo) { FILE *fp; char *tmp; size_t tmplen; pid_t pid; fp = open_memstream(&tmp, &tmplen); pid = trussinfo->curthread->proc->pid; switch (sc->type & ARG_MASK) { case Hex: fprintf(fp, "0x%x", (int)args[sc->offset]); break; case Octal: fprintf(fp, "0%o", (int)args[sc->offset]); break; case Int: fprintf(fp, "%d", (int)args[sc->offset]); break; case UInt: fprintf(fp, "%u", (unsigned int)args[sc->offset]); break; case LongHex: fprintf(fp, "0x%lx", args[sc->offset]); break; case Long: fprintf(fp, "%ld", args[sc->offset]); break; case Name: { /* NULL-terminated string. */ char *tmp2; tmp2 = get_string(pid, (void*)args[sc->offset], 0); fprintf(fp, "\"%s\"", tmp2); free(tmp2); break; } case BinString: { /* * Binary block of data that might have printable characters. * XXX If type|OUT, assume that the length is the syscall's * return value. Otherwise, assume that the length of the block * is in the next syscall argument. */ int max_string = trussinfo->strsize; char tmp2[max_string + 1], *tmp3; int len; int truncated = 0; if (sc->type & OUT) len = retval[0]; else len = args[sc->offset + 1]; /* * Don't print more than max_string characters, to avoid word * wrap. If we have to truncate put some ... after the string. */ if (len > max_string) { len = max_string; truncated = 1; } if (len && get_struct(pid, (void*)args[sc->offset], &tmp2, len) != -1) { tmp3 = malloc(len * 4 + 1); while (len) { if (strvisx(tmp3, tmp2, len, VIS_CSTYLE|VIS_TAB|VIS_NL) <= max_string) break; len--; truncated = 1; } fprintf(fp, "\"%s\"%s", tmp3, truncated ? "..." : ""); free(tmp3); } else { fprintf(fp, "0x%lx", args[sc->offset]); } break; } case ExecArgs: case ExecEnv: case StringArray: { uintptr_t addr; union { char *strarray[0]; char buf[PAGE_SIZE]; } u; char *string; size_t len; u_int first, i; /* * Only parse argv[] and environment arrays from exec calls * if requested. */ if (((sc->type & ARG_MASK) == ExecArgs && (trussinfo->flags & EXECVEARGS) == 0) || ((sc->type & ARG_MASK) == ExecEnv && (trussinfo->flags & EXECVEENVS) == 0)) { fprintf(fp, "0x%lx", args[sc->offset]); break; } /* * Read a page of pointers at a time. Punt if the top-level * pointer is not aligned. Note that the first read is of * a partial page. */ addr = args[sc->offset]; if (addr % sizeof(char *) != 0) { fprintf(fp, "0x%lx", args[sc->offset]); break; } len = PAGE_SIZE - (addr & PAGE_MASK); if (get_struct(pid, (void *)addr, u.buf, len) == -1) { fprintf(fp, "0x%lx", args[sc->offset]); break; } fputc('[', fp); first = 1; i = 0; while (u.strarray[i] != NULL) { string = get_string(pid, u.strarray[i], 0); fprintf(fp, "%s \"%s\"", first ? "" : ",", string); free(string); first = 0; i++; if (i == len / sizeof(char *)) { addr += len; len = PAGE_SIZE; if (get_struct(pid, (void *)addr, u.buf, len) == -1) { fprintf(fp, ", "); break; } i = 0; } } fputs(" ]", fp); break; } #ifdef __LP64__ case Quad: fprintf(fp, "%ld", args[sc->offset]); break; case QuadHex: fprintf(fp, "0x%lx", args[sc->offset]); break; #else case Quad: case QuadHex: { unsigned long long ll; #if _BYTE_ORDER == _LITTLE_ENDIAN ll = (unsigned long long)args[sc->offset + 1] << 32 | args[sc->offset]; #else ll = (unsigned long long)args[sc->offset] << 32 | args[sc->offset + 1]; #endif if ((sc->type & ARG_MASK) == Quad) fprintf(fp, "%lld", ll); else fprintf(fp, "0x%llx", ll); break; } #endif case Ptr: fprintf(fp, "0x%lx", args[sc->offset]); break; case Readlinkres: { char *tmp2; if (retval[0] == -1) break; tmp2 = get_string(pid, (void*)args[sc->offset], retval[0]); fprintf(fp, "\"%s\"", tmp2); free(tmp2); break; } case Ioctl: { const char *temp; unsigned long cmd; cmd = args[sc->offset]; temp = sysdecode_ioctlname(cmd); if (temp) fputs(temp, fp); else { fprintf(fp, "0x%lx { IO%s%s 0x%lx('%c'), %lu, %lu }", cmd, cmd & IOC_OUT ? "R" : "", cmd & IOC_IN ? "W" : "", IOCGROUP(cmd), isprint(IOCGROUP(cmd)) ? (char)IOCGROUP(cmd) : '?', cmd & 0xFF, IOCPARM_LEN(cmd)); } break; } case Timespec: { struct timespec ts; if (get_struct(pid, (void *)args[sc->offset], &ts, sizeof(ts)) != -1) fprintf(fp, "{ %jd.%09ld }", (intmax_t)ts.tv_sec, ts.tv_nsec); else fprintf(fp, "0x%lx", args[sc->offset]); break; } case Timespec2: { struct timespec ts[2]; const char *sep; unsigned int i; if (get_struct(pid, (void *)args[sc->offset], &ts, sizeof(ts)) != -1) { fputs("{ ", fp); sep = ""; for (i = 0; i < nitems(ts); i++) { fputs(sep, fp); sep = ", "; switch (ts[i].tv_nsec) { case UTIME_NOW: fprintf(fp, "UTIME_NOW"); break; case UTIME_OMIT: fprintf(fp, "UTIME_OMIT"); break; default: fprintf(fp, "%jd.%09ld", (intmax_t)ts[i].tv_sec, ts[i].tv_nsec); break; } } fputs(" }", fp); } else fprintf(fp, "0x%lx", args[sc->offset]); break; } case Timeval: { struct timeval tv; if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv)) != -1) fprintf(fp, "{ %jd.%06ld }", (intmax_t)tv.tv_sec, tv.tv_usec); else fprintf(fp, "0x%lx", args[sc->offset]); break; } case Timeval2: { struct timeval tv[2]; if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv)) != -1) fprintf(fp, "{ %jd.%06ld, %jd.%06ld }", (intmax_t)tv[0].tv_sec, tv[0].tv_usec, (intmax_t)tv[1].tv_sec, tv[1].tv_usec); else fprintf(fp, "0x%lx", args[sc->offset]); break; } case Itimerval: { struct itimerval itv; if (get_struct(pid, (void *)args[sc->offset], &itv, sizeof(itv)) != -1) fprintf(fp, "{ %jd.%06ld, %jd.%06ld }", (intmax_t)itv.it_interval.tv_sec, itv.it_interval.tv_usec, (intmax_t)itv.it_value.tv_sec, itv.it_value.tv_usec); else fprintf(fp, "0x%lx", args[sc->offset]); break; } case LinuxSockArgs: { struct linux_socketcall_args largs; if (get_struct(pid, (void *)args[sc->offset], (void *)&largs, sizeof(largs)) != -1) fprintf(fp, "{ %s, 0x%lx }", lookup(linux_socketcall_ops, largs.what, 10), (long unsigned int)largs.args); else fprintf(fp, "0x%lx", args[sc->offset]); break; } case Pollfd: { /* * XXX: A Pollfd argument expects the /next/ syscall argument * to be the number of fds in the array. This matches the poll * syscall. */ struct pollfd *pfd; int numfds = args[sc->offset + 1]; size_t bytes = sizeof(struct pollfd) * numfds; int i; if ((pfd = malloc(bytes)) == NULL) err(1, "Cannot malloc %zu bytes for pollfd array", bytes); if (get_struct(pid, (void *)args[sc->offset], pfd, bytes) != -1) { fputs("{", fp); for (i = 0; i < numfds; i++) { fprintf(fp, " %d/%s", pfd[i].fd, xlookup_bits(poll_flags, pfd[i].events)); } fputs(" }", fp); } else { fprintf(fp, "0x%lx", args[sc->offset]); } free(pfd); break; } case Fd_set: { /* * XXX: A Fd_set argument expects the /first/ syscall argument * to be the number of fds in the array. This matches the * select syscall. */ fd_set *fds; int numfds = args[0]; size_t bytes = _howmany(numfds, _NFDBITS) * _NFDBITS; int i; if ((fds = malloc(bytes)) == NULL) err(1, "Cannot malloc %zu bytes for fd_set array", bytes); if (get_struct(pid, (void *)args[sc->offset], fds, bytes) != -1) { fputs("{", fp); for (i = 0; i < numfds; i++) { if (FD_ISSET(i, fds)) fprintf(fp, " %d", i); } fputs(" }", fp); } else fprintf(fp, "0x%lx", args[sc->offset]); free(fds); break; } case Signal: fputs(strsig2(args[sc->offset]), fp); break; case Sigset: { long sig; sigset_t ss; int i, first; sig = args[sc->offset]; if (get_struct(pid, (void *)args[sc->offset], (void *)&ss, sizeof(ss)) == -1) { fprintf(fp, "0x%lx", args[sc->offset]); break; } fputs("{ ", fp); first = 1; for (i = 1; i < sys_nsig; i++) { if (sigismember(&ss, i)) { fprintf(fp, "%s%s", !first ? "|" : "", - strsig(i)); + strsig2(i)); first = 0; } } if (!first) fputc(' ', fp); fputc('}', fp); break; } - case Sigprocmask: { - fputs(xlookup(sigprocmask_ops, args[sc->offset]), fp); + case Sigprocmask: + print_integer_arg(sysdecode_sigprocmask_how, fp, + args[sc->offset]); break; - } - case Fcntlflag: { + case Fcntlflag: /* XXX: Output depends on the value of the previous argument. */ - switch (args[sc->offset - 1]) { - case F_SETFD: - fputs(xlookup_bits(fcntlfd_arg, args[sc->offset]), fp); - break; - case F_SETFL: - fputs(xlookup_bits(fcntlfl_arg, args[sc->offset]), fp); - break; - case F_GETFD: - case F_GETFL: - case F_GETOWN: - break; - default: - fprintf(fp, "0x%lx", args[sc->offset]); - break; - } + if (sysdecode_fcntl_arg_p(args[sc->offset - 1])) + sysdecode_fcntl_arg(fp, args[sc->offset - 1], + args[sc->offset], 16); break; - } case Open: - fputs(xlookup_bits(open_flags, args[sc->offset]), fp); + print_mask_arg(sysdecode_open_flags, fp, args[sc->offset]); break; case Fcntl: - fputs(xlookup(fcntl_arg, args[sc->offset]), fp); + print_integer_arg(sysdecode_fcntl_cmd, fp, args[sc->offset]); break; case Mprot: - fputs(xlookup_bits(mprot_flags, args[sc->offset]), fp); + print_mask_arg(sysdecode_mmap_prot, fp, args[sc->offset]); break; - case Mmapflags: { - int align, flags; - - /* - * MAP_ALIGNED can't be handled by xlookup_bits(), so - * generate that string manually and prepend it to the - * string from xlookup_bits(). Have to be careful to - * avoid outputting MAP_ALIGNED|0 if MAP_ALIGNED is - * the only flag. - */ - flags = args[sc->offset] & ~MAP_ALIGNMENT_MASK; - align = args[sc->offset] & MAP_ALIGNMENT_MASK; - if (align != 0) { - if (align == MAP_ALIGNED_SUPER) - fputs("MAP_ALIGNED_SUPER", fp); - else - fprintf(fp, "MAP_ALIGNED(%d)", - align >> MAP_ALIGNMENT_SHIFT); - if (flags == 0) - break; - fputc('|', fp); - } - fputs(xlookup_bits(mmap_flags, flags), fp); + case Mmapflags: + print_mask_arg(sysdecode_mmap_flags, fp, args[sc->offset]); break; - } case Whence: - fputs(xlookup(whence_arg, args[sc->offset]), fp); + print_integer_arg(sysdecode_whence, fp, args[sc->offset]); break; case Sockdomain: - fputs(xlookup(sockdomain_arg, args[sc->offset]), fp); + print_integer_arg(sysdecode_socketdomain, fp, args[sc->offset]); break; - case Socktype: { - int type, flags; - - flags = args[sc->offset] & (SOCK_CLOEXEC | SOCK_NONBLOCK); - type = args[sc->offset] & ~flags; - fputs(xlookup(socktype_arg, type), fp); - if (flags & SOCK_CLOEXEC) - fprintf(fp, "|SOCK_CLOEXEC"); - if (flags & SOCK_NONBLOCK) - fprintf(fp, "|SOCK_NONBLOCK"); + case Socktype: + print_mask_arg(sysdecode_socket_type, fp, args[sc->offset]); break; - } case Shutdown: - fputs(xlookup(shutdown_arg, args[sc->offset]), fp); + print_integer_arg(sysdecode_shutdown_how, fp, args[sc->offset]); break; case Resource: - fputs(xlookup(resource_arg, args[sc->offset]), fp); + print_integer_arg(sysdecode_rlimit, fp, args[sc->offset]); break; case Pathconf: fputs(xlookup(pathconf_arg, args[sc->offset]), fp); break; case Rforkflags: - fputs(xlookup_bits(rfork_flags, args[sc->offset]), fp); + print_mask_arg(sysdecode_rfork_flags, fp, args[sc->offset]); break; case Sockaddr: { char addr[64]; struct sockaddr_in *lsin; struct sockaddr_in6 *lsin6; struct sockaddr_un *sun; struct sockaddr *sa; socklen_t len; u_char *q; if (args[sc->offset] == 0) { fputs("NULL", fp); break; } /* * Extract the address length from the next argument. If * this is an output sockaddr (OUT is set), then the * next argument is a pointer to a socklen_t. Otherwise * the next argument contains a socklen_t by value. */ if (sc->type & OUT) { if (get_struct(pid, (void *)args[sc->offset + 1], &len, sizeof(len)) == -1) { fprintf(fp, "0x%lx", args[sc->offset]); break; } } else len = args[sc->offset + 1]; /* If the length is too small, just bail. */ if (len < sizeof(*sa)) { fprintf(fp, "0x%lx", args[sc->offset]); break; } sa = calloc(1, len); if (get_struct(pid, (void *)args[sc->offset], sa, len) == -1) { free(sa); fprintf(fp, "0x%lx", args[sc->offset]); break; } switch (sa->sa_family) { case AF_INET: if (len < sizeof(*lsin)) goto sockaddr_short; lsin = (struct sockaddr_in *)(void *)sa; inet_ntop(AF_INET, &lsin->sin_addr, addr, sizeof(addr)); fprintf(fp, "{ AF_INET %s:%d }", addr, htons(lsin->sin_port)); break; case AF_INET6: if (len < sizeof(*lsin6)) goto sockaddr_short; lsin6 = (struct sockaddr_in6 *)(void *)sa; inet_ntop(AF_INET6, &lsin6->sin6_addr, addr, sizeof(addr)); fprintf(fp, "{ AF_INET6 [%s]:%d }", addr, htons(lsin6->sin6_port)); break; case AF_UNIX: sun = (struct sockaddr_un *)sa; fprintf(fp, "{ AF_UNIX \"%.*s\" }", (int)(len - offsetof(struct sockaddr_un, sun_path)), sun->sun_path); break; default: sockaddr_short: fprintf(fp, "{ sa_len = %d, sa_family = %d, sa_data = {", (int)sa->sa_len, (int)sa->sa_family); for (q = (u_char *)sa->sa_data; q < (u_char *)sa + len; q++) fprintf(fp, "%s 0x%02x", q == (u_char *)sa->sa_data ? "" : ",", *q); fputs(" } }", fp); } free(sa); break; } case Sigaction: { struct sigaction sa; if (get_struct(pid, (void *)args[sc->offset], &sa, sizeof(sa)) != -1) { fputs("{ ", fp); if (sa.sa_handler == SIG_DFL) fputs("SIG_DFL", fp); else if (sa.sa_handler == SIG_IGN) fputs("SIG_IGN", fp); else fprintf(fp, "%p", sa.sa_handler); fprintf(fp, " %s ss_t }", xlookup_bits(sigaction_flags, sa.sa_flags)); } else fprintf(fp, "0x%lx", args[sc->offset]); break; } case Kevent: { /* * XXX XXX: The size of the array is determined by either the * next syscall argument, or by the syscall return value, * depending on which argument number we are. This matches the * kevent syscall, but luckily that's the only syscall that uses * them. */ struct kevent *ke; int numevents = -1; size_t bytes; int i; if (sc->offset == 1) numevents = args[sc->offset+1]; else if (sc->offset == 3 && retval[0] != -1) numevents = retval[0]; if (numevents >= 0) { bytes = sizeof(struct kevent) * numevents; if ((ke = malloc(bytes)) == NULL) err(1, "Cannot malloc %zu bytes for kevent array", bytes); } else ke = NULL; if (numevents >= 0 && get_struct(pid, (void *)args[sc->offset], ke, bytes) != -1) { fputc('{', fp); for (i = 0; i < numevents; i++) { fputc(' ', fp); print_kevent(fp, &ke[i], sc->offset == 1); } fputs(" }", fp); } else { fprintf(fp, "0x%lx", args[sc->offset]); } free(ke); break; } case Stat: { struct stat st; if (get_struct(pid, (void *)args[sc->offset], &st, sizeof(st)) != -1) { char mode[12]; strmode(st.st_mode, mode); fprintf(fp, "{ mode=%s,inode=%ju,size=%jd,blksize=%ld }", mode, (uintmax_t)st.st_ino, (intmax_t)st.st_size, (long)st.st_blksize); } else { fprintf(fp, "0x%lx", args[sc->offset]); } break; } case StatFs: { unsigned int i; struct statfs buf; if (get_struct(pid, (void *)args[sc->offset], &buf, sizeof(buf)) != -1) { char fsid[17]; bzero(fsid, sizeof(fsid)); if (buf.f_fsid.val[0] != 0 || buf.f_fsid.val[1] != 0) { for (i = 0; i < sizeof(buf.f_fsid); i++) snprintf(&fsid[i*2], sizeof(fsid) - (i*2), "%02x", ((u_char *)&buf.f_fsid)[i]); } fprintf(fp, "{ fstypename=%s,mntonname=%s,mntfromname=%s," "fsid=%s }", buf.f_fstypename, buf.f_mntonname, buf.f_mntfromname, fsid); } else fprintf(fp, "0x%lx", args[sc->offset]); break; } case Rusage: { struct rusage ru; if (get_struct(pid, (void *)args[sc->offset], &ru, sizeof(ru)) != -1) { fprintf(fp, "{ u=%jd.%06ld,s=%jd.%06ld,in=%ld,out=%ld }", (intmax_t)ru.ru_utime.tv_sec, ru.ru_utime.tv_usec, (intmax_t)ru.ru_stime.tv_sec, ru.ru_stime.tv_usec, ru.ru_inblock, ru.ru_oublock); } else fprintf(fp, "0x%lx", args[sc->offset]); break; } case Rlimit: { struct rlimit rl; if (get_struct(pid, (void *)args[sc->offset], &rl, sizeof(rl)) != -1) { fprintf(fp, "{ cur=%ju,max=%ju }", rl.rlim_cur, rl.rlim_max); } else fprintf(fp, "0x%lx", args[sc->offset]); break; } case ExitStatus: { int status; if (get_struct(pid, (void *)args[sc->offset], &status, sizeof(status)) != -1) { fputs("{ ", fp); if (WIFCONTINUED(status)) fputs("CONTINUED", fp); else if (WIFEXITED(status)) fprintf(fp, "EXITED,val=%d", WEXITSTATUS(status)); else if (WIFSIGNALED(status)) fprintf(fp, "SIGNALED,sig=%s%s", strsig2(WTERMSIG(status)), WCOREDUMP(status) ? ",cored" : ""); else fprintf(fp, "STOPPED,sig=%s", strsig2(WTERMSIG(status))); fputs(" }", fp); } else fprintf(fp, "0x%lx", args[sc->offset]); break; } case Waitoptions: - fputs(xlookup_bits(wait_options, args[sc->offset]), fp); + print_mask_arg(sysdecode_wait6_options, fp, args[sc->offset]); break; case Idtype: - fputs(xlookup(idtype_arg, args[sc->offset]), fp); + print_integer_arg(sysdecode_idtype, fp, args[sc->offset]); break; case Procctl: - fputs(xlookup(procctl_arg, args[sc->offset]), fp); + print_integer_arg(sysdecode_procctl_cmd, fp, args[sc->offset]); break; case Umtxop: - fputs(xlookup(umtx_ops, args[sc->offset]), fp); + print_integer_arg(sysdecode_umtx_op, fp, args[sc->offset]); break; case Atfd: - if ((int)args[sc->offset] == AT_FDCWD) - fputs("AT_FDCWD", fp); - else - fprintf(fp, "%d", (int)args[sc->offset]); + print_integer_arg(sysdecode_atfd, fp, args[sc->offset]); break; case Atflags: fputs(xlookup_bits(at_flags, args[sc->offset]), fp); break; case Accessmode: - if (args[sc->offset] == F_OK) - fputs("F_OK", fp); - else - fputs(xlookup_bits(access_modes, args[sc->offset]), fp); + print_mask_arg(sysdecode_access_mode, fp, args[sc->offset]); break; case Sysarch: fputs(xlookup(sysarch_ops, args[sc->offset]), fp); break; case PipeFds: /* * The pipe() system call in the kernel returns its * two file descriptors via return values. However, * the interface exposed by libc is that pipe() * accepts a pointer to an array of descriptors. * Format the output to match the libc API by printing * the returned file descriptors as a fake argument. * * Overwrite the first retval to signal a successful * return as well. */ fprintf(fp, "{ %ld, %ld }", retval[0], retval[1]); retval[0] = 0; break; case Utrace: { size_t len; void *utrace_addr; len = args[sc->offset + 1]; utrace_addr = calloc(1, len); if (get_struct(pid, (void *)args[sc->offset], (void *)utrace_addr, len) != -1) print_utrace(fp, utrace_addr, len); else fprintf(fp, "0x%lx", args[sc->offset]); free(utrace_addr); break; } case IntArray: { int descriptors[16]; unsigned long i, ndescriptors; bool truncated; ndescriptors = args[sc->offset + 1]; truncated = false; if (ndescriptors > nitems(descriptors)) { ndescriptors = nitems(descriptors); truncated = true; } if (get_struct(pid, (void *)args[sc->offset], descriptors, ndescriptors * sizeof(descriptors[0])) != -1) { fprintf(fp, "{"); for (i = 0; i < ndescriptors; i++) fprintf(fp, i == 0 ? " %d" : ", %d", descriptors[i]); fprintf(fp, truncated ? ", ... }" : " }"); } else fprintf(fp, "0x%lx", args[sc->offset]); break; } + case Pipe2: + print_mask_arg(sysdecode_pipe2_flags, fp, args[sc->offset]); + break; case CloudABIAdvice: fputs(xlookup(cloudabi_advice, args[sc->offset]), fp); break; case CloudABIClockID: fputs(xlookup(cloudabi_clockid, args[sc->offset]), fp); break; case ClouduABIFDSFlags: fputs(xlookup_bits(cloudabi_fdsflags, args[sc->offset]), fp); break; case CloudABIFDStat: { cloudabi_fdstat_t fds; if (get_struct(pid, (void *)args[sc->offset], &fds, sizeof(fds)) != -1) { fprintf(fp, "{ %s, ", xlookup(cloudabi_filetype, fds.fs_filetype)); fprintf(fp, "%s, ... }", xlookup_bits(cloudabi_fdflags, fds.fs_flags)); } else fprintf(fp, "0x%lx", args[sc->offset]); break; } case CloudABIFileStat: { cloudabi_filestat_t fsb; if (get_struct(pid, (void *)args[sc->offset], &fsb, sizeof(fsb)) != -1) fprintf(fp, "{ %s, %ju }", xlookup(cloudabi_filetype, fsb.st_filetype), (uintmax_t)fsb.st_size); else fprintf(fp, "0x%lx", args[sc->offset]); break; } case CloudABIFileType: fputs(xlookup(cloudabi_filetype, args[sc->offset]), fp); break; case CloudABIFSFlags: fputs(xlookup_bits(cloudabi_fsflags, args[sc->offset]), fp); break; case CloudABILookup: if ((args[sc->offset] & CLOUDABI_LOOKUP_SYMLINK_FOLLOW) != 0) fprintf(fp, "%d|LOOKUP_SYMLINK_FOLLOW", (int)args[sc->offset]); else fprintf(fp, "%d", (int)args[sc->offset]); break; case CloudABIMFlags: fputs(xlookup_bits(cloudabi_mflags, args[sc->offset]), fp); break; case CloudABIMProt: fputs(xlookup_bits(cloudabi_mprot, args[sc->offset]), fp); break; case CloudABIMSFlags: fputs(xlookup_bits(cloudabi_msflags, args[sc->offset]), fp); break; case CloudABIOFlags: fputs(xlookup_bits(cloudabi_oflags, args[sc->offset]), fp); break; case CloudABISDFlags: fputs(xlookup_bits(cloudabi_sdflags, args[sc->offset]), fp); break; case CloudABISignal: fputs(xlookup(cloudabi_signal, args[sc->offset]), fp); break; case CloudABISockStat: { cloudabi_sockstat_t ss; if (get_struct(pid, (void *)args[sc->offset], &ss, sizeof(ss)) != -1) { fprintf(fp, "{ %s, ", xlookup( cloudabi_sa_family, ss.ss_sockname.sa_family)); fprintf(fp, "%s, ", xlookup( cloudabi_sa_family, ss.ss_peername.sa_family)); fprintf(fp, "%s, ", xlookup( cloudabi_errno, ss.ss_error)); fprintf(fp, "%s }", xlookup_bits( cloudabi_ssstate, ss.ss_state)); } else fprintf(fp, "0x%lx", args[sc->offset]); break; } case CloudABISSFlags: fputs(xlookup_bits(cloudabi_ssflags, args[sc->offset]), fp); break; case CloudABITimestamp: fprintf(fp, "%lu.%09lus", args[sc->offset] / 1000000000, args[sc->offset] % 1000000000); break; case CloudABIULFlags: fputs(xlookup_bits(cloudabi_ulflags, args[sc->offset]), fp); break; case CloudABIWhence: fputs(xlookup(cloudabi_whence, args[sc->offset]), fp); break; default: errx(1, "Invalid argument type %d\n", sc->type & ARG_MASK); } fclose(fp); return (tmp); } /* * Print (to outfile) the system call and its arguments. */ void print_syscall(struct trussinfo *trussinfo) { struct threadinfo *t; const char *name; char **s_args; int i, len, nargs; t = trussinfo->curthread; name = t->cs.name; nargs = t->cs.nargs; s_args = t->cs.s_args; len = print_line_prefix(trussinfo); len += fprintf(trussinfo->outfile, "%s(", name); for (i = 0; i < nargs; i++) { if (s_args[i] != NULL) len += fprintf(trussinfo->outfile, "%s", s_args[i]); else len += fprintf(trussinfo->outfile, ""); len += fprintf(trussinfo->outfile, "%s", i < (nargs - 1) ? "," : ""); } len += fprintf(trussinfo->outfile, ")"); for (i = 0; i < 6 - (len / 8); i++) fprintf(trussinfo->outfile, "\t"); } void print_syscall_ret(struct trussinfo *trussinfo, int errorp, long *retval) { struct timespec timediff; struct threadinfo *t; struct syscall *sc; int error; t = trussinfo->curthread; sc = t->cs.sc; if (trussinfo->flags & COUNTONLY) { timespecsubt(&t->after, &t->before, &timediff); timespecadd(&sc->time, &timediff, &sc->time); sc->ncalls++; if (errorp) sc->nerror++; return; } print_syscall(trussinfo); fflush(trussinfo->outfile); if (retval == NULL) { /* * This system call resulted in the current thread's exit, * so there is no return value or error to display. */ fprintf(trussinfo->outfile, "\n"); return; } if (errorp) { error = sysdecode_abi_to_freebsd_errno(t->proc->abi->abi, retval[0]); fprintf(trussinfo->outfile, " ERR#%ld '%s'\n", retval[0], error == INT_MAX ? "Unknown error" : strerror(error)); } #ifndef __LP64__ else if (sc->ret_type == 2) { off_t off; #if _BYTE_ORDER == _LITTLE_ENDIAN off = (off_t)retval[1] << 32 | retval[0]; #else off = (off_t)retval[0] << 32 | retval[1]; #endif fprintf(trussinfo->outfile, " = %jd (0x%jx)\n", (intmax_t)off, (intmax_t)off); } #endif else fprintf(trussinfo->outfile, " = %ld (0x%lx)\n", retval[0], retval[0]); } void print_summary(struct trussinfo *trussinfo) { struct timespec total = {0, 0}; struct syscall *sc; int ncall, nerror; fprintf(trussinfo->outfile, "%-20s%15s%8s%8s\n", "syscall", "seconds", "calls", "errors"); ncall = nerror = 0; STAILQ_FOREACH(sc, &syscalls, entries) if (sc->ncalls) { fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n", sc->name, (intmax_t)sc->time.tv_sec, sc->time.tv_nsec, sc->ncalls, sc->nerror); timespecadd(&total, &sc->time, &total); ncall += sc->ncalls; nerror += sc->nerror; } fprintf(trussinfo->outfile, "%20s%15s%8s%8s\n", "", "-------------", "-------", "-------"); fprintf(trussinfo->outfile, "%-20s%5jd.%09ld%8d%8d\n", "", (intmax_t)total.tv_sec, total.tv_nsec, ncall, nerror); }