summaryrefslogtreecommitdiffstats
path: root/usr.bin/kdump/kdump.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/kdump/kdump.c')
-rw-r--r--usr.bin/kdump/kdump.c1736
1 files changed, 1736 insertions, 0 deletions
diff --git a/usr.bin/kdump/kdump.c b/usr.bin/kdump/kdump.c
new file mode 100644
index 0000000..4d8e109
--- /dev/null
+++ b/usr.bin/kdump/kdump.c
@@ -0,0 +1,1736 @@
+/*-
+ * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#define _KERNEL
+extern int errno;
+#include <sys/errno.h>
+#undef _KERNEL
+#include <sys/param.h>
+#include <sys/errno.h>
+#define _KERNEL
+#include <sys/time.h>
+#undef _KERNEL
+#include <sys/uio.h>
+#include <sys/ktrace.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/sysent.h>
+#include <sys/un.h>
+#include <sys/queue.h>
+#ifdef IPX
+#include <sys/types.h>
+#include <netipx/ipx.h>
+#endif
+#ifdef NETATALK
+#include <netatalk/at.h>
+#endif
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <ctype.h>
+#include <dlfcn.h>
+#include <err.h>
+#include <grp.h>
+#include <inttypes.h>
+#include <locale.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <vis.h>
+#include "ktrace.h"
+#include "kdump_subr.h"
+
+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 ktruser_malloc(unsigned char *);
+void ktruser_rtld(int, unsigned char *);
+void ktruser(int, unsigned char *);
+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);
+void ioctlname(unsigned long, int);
+
+int timestamp, decimal, fancy = 1, suppressdata, tail, threads, maxdata,
+ resolv = 0, abiflag = 0;
+const char *tracefile = DEF_TRACEFILE;
+struct ktr_header ktr_header;
+
+#define TIME_FORMAT "%b %e %T %Y"
+#define eqs(s1, s2) (strcmp((s1), (s2)) == 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)
+
+#if defined(__amd64__) || defined(__i386__)
+
+void linux_ktrsyscall(struct ktr_syscall *);
+void linux_ktrsysret(struct ktr_sysret *);
+extern char *linux_syscallnames[];
+extern int nlinux_syscalls;
+
+/*
+ * from linux.h
+ * Linux syscalls return negative errno's, we do positive and map them
+ */
+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
+
+struct proc_info
+{
+ TAILQ_ENTRY(proc_info) info;
+ u_int sv_flags;
+ pid_t pid;
+};
+
+TAILQ_HEAD(trace_procs, proc_info) trace_procs;
+
+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, "");
+
+ while ((ch = getopt(argc,argv,"f:dElm:np:AHRrsTt:")) != -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':
+ suppressdata = 1;
+ break;
+ case 'E':
+ timestamp = 3; /* elapsed timestamp */
+ break;
+ case 'H':
+ threads = 1;
+ break;
+ case 'R':
+ timestamp = 2; /* relative timestamp */
+ break;
+ case 'T':
+ timestamp = 1;
+ 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 (!freopen(tracefile, "r", stdin))
+ err(1, "%s", tracefile);
+ 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<<ktr_header.ktr_type))
+ if (pid == 0 || ktr_header.ktr_pid == pid)
+ dumpheader(&ktr_header);
+ if ((ktrlen = ktr_header.ktr_len) < 0)
+ errx(1, "bogus length 0x%x", ktrlen);
+ if (ktrlen > 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)
+ continue;
+ if ((trpoints & (1<<ktr_header.ktr_type)) == 0)
+ continue;
+ drop_logged = 0;
+ switch (ktr_header.ktr_type) {
+ case KTR_SYSCALL:
+#if defined(__amd64__) || defined(__i386__)
+ if ((sv_flags & SV_ABI_MASK) == SV_ABI_LINUX)
+ linux_ktrsyscall((struct ktr_syscall *)m);
+ else
+#endif
+ ktrsyscall((struct ktr_syscall *)m, sv_flags);
+ break;
+ case KTR_SYSRET:
+#if defined(__amd64__) || defined(__i386__)
+ if ((sv_flags & SV_ABI_MASK) == SV_ABI_LINUX)
+ linux_ktrsysret((struct ktr_sysret *)m);
+ else
+#endif
+ ktrsysret((struct ktr_sysret *)m, sv_flags);
+ break;
+ case KTR_NAMEI:
+ case KTR_SYSCTL:
+ ktrnamei(m, ktrlen);
+ break;
+ case KTR_GENIO:
+ ktrgenio((struct ktr_genio *)m, ktrlen);
+ break;
+ case KTR_PSIG:
+ ktrpsig((struct ktr_psig *)m);
+ break;
+ case KTR_CSW:
+ ktrcsw((struct ktr_csw *)m);
+ break;
+ case KTR_USER:
+ ktruser(ktrlen, m);
+ break;
+ case KTR_STRUCT:
+ ktrstruct(m, ktrlen);
+ break;
+ case KTR_CAPFAIL:
+ ktrcapfail((struct ktr_cap_fail *)m);
+ break;
+ case KTR_FAULT:
+ ktrfault((struct ktr_fault *)m);
+ break;
+ case KTR_FAULTEND:
+ ktrfaultend((struct ktr_faultend *)m);
+ break;
+ default:
+ printf("\n");
+ break;
+ }
+ if (tail)
+ fflush(stdout);
+ }
+ return 0;
+}
+
+int
+fread_tail(void *buf, int size, int num)
+{
+ int i;
+
+ while ((i = fread(buf, size, num, stdin)) == 0 && tail) {
+ sleep(1);
+ clearerr(stdin);
+ }
+ return (i);
+}
+
+int
+fetchprocinfo(struct ktr_header *kth, u_int *flags)
+{
+ struct proc_info *pi;
+
+ switch (kth->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;
+ default:
+ abi = "U";
+ break;
+ }
+
+ if (flags != 0) {
+ if (flags & SV_LP64)
+ arch = "64";
+ else
+ 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, temp;
+ const char *type;
+
+ 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 == 3) {
+ if (prevtime.tv_sec == 0)
+ prevtime = kth->ktr_time;
+ timevalsub(&kth->ktr_time, &prevtime);
+ }
+ if (timestamp == 2) {
+ temp = kth->ktr_time;
+ timevalsub(&kth->ktr_time, &prevtime);
+ prevtime = temp;
+ }
+ printf("%jd.%06ld ", (intmax_t)kth->ktr_time.tv_sec,
+ kth->ktr_time.tv_usec);
+ }
+ printf("%s ", type);
+}
+
+#include <sys/syscall.h>
+#define KTRACE
+#include <sys/kern/syscalls.c>
+#undef KTRACE
+int nsyscalls = sizeof (syscallnames) / sizeof (syscallnames[0]);
+
+void
+ktrsyscall(struct ktr_syscall *ktr, u_int flags)
+{
+ int narg = ktr->ktr_narg;
+ register_t *ip;
+ intmax_t arg;
+
+ if ((flags != 0 && ((flags & SV_ABI_MASK) != SV_ABI_FREEBSD)) ||
+ (ktr->ktr_code >= nsyscalls || ktr->ktr_code < 0))
+ printf("[%d]", ktr->ktr_code);
+ else
+ printf("%s", syscallnames[ktr->ktr_code]);
+ ip = &ktr->ktr_args[0];
+ if (narg) {
+ char c = '(';
+ if (fancy &&
+ (flags == 0 || (flags & SV_ABI_MASK) == SV_ABI_FREEBSD)) {
+ switch (ktr->ktr_code) {
+ case SYS_ioctl: {
+ print_number(ip, narg, c);
+ putchar(c);
+ ioctlname(*ip, decimal);
+ c = ',';
+ ip++;
+ narg--;
+ break;
+ }
+ case SYS_ptrace:
+ putchar('(');
+ ptraceopname(*ip);
+ c = ',';
+ ip++;
+ narg--;
+ break;
+ case SYS_access:
+ case SYS_eaccess:
+ print_number(ip, narg, c);
+ putchar(',');
+ accessmodename(*ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_open:
+ print_number(ip, narg, c);
+ putchar(',');
+ flagsandmodename(ip[0], ip[1], decimal);
+ ip += 2;
+ narg -= 2;
+ break;
+ case SYS_wait4:
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ putchar(',');
+ wait4optname(*ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_chmod:
+ case SYS_fchmod:
+ case SYS_lchmod:
+ print_number(ip, narg, c);
+ putchar(',');
+ modename(*ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_mknod:
+ print_number(ip, narg, c);
+ putchar(',');
+ modename(*ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_getfsstat:
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ putchar(',');
+ getfsstatflagsname(*ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_mount:
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ putchar(',');
+ mountflagsname(*ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_unmount:
+ print_number(ip, narg, c);
+ putchar(',');
+ mountflagsname(*ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_recvmsg:
+ case SYS_sendmsg:
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ putchar(',');
+ sendrecvflagsname(*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);
+ ip++;
+ narg--;
+ break;
+ case SYS_chflags:
+ case SYS_fchflags:
+ case SYS_lchflags:
+ print_number(ip, narg, c);
+ putchar(',');
+ modename(*ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_kill:
+ print_number(ip, narg, c);
+ putchar(',');
+ signame(*ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_reboot:
+ putchar('(');
+ rebootoptname(*ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_umask:
+ putchar('(');
+ modename(*ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_msync:
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ putchar(',');
+ msyncflagsname(*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);
+ putchar(',');
+ ip++;
+ narg--;
+ mmapflagsname(*ip);
+ ip++;
+ narg--;
+ break;
+#endif
+ case SYS_mmap:
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ putchar(',');
+ mmapprotname(*ip);
+ putchar(',');
+ ip++;
+ narg--;
+ mmapflagsname(*ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_mprotect:
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ putchar(',');
+ mmapprotname(*ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_madvise:
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ putchar(',');
+ madvisebehavname(*ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_setpriority:
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ putchar(',');
+ prioname(*ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_fcntl:
+ print_number(ip, narg, c);
+ putchar(',');
+ fcntlcmdname(ip[0], ip[1], decimal);
+ ip += 2;
+ narg -= 2;
+ break;
+ case SYS_socket: {
+ int sockdomain;
+ putchar('(');
+ sockdomain = *ip;
+ sockdomainname(sockdomain);
+ ip++;
+ narg--;
+ putchar(',');
+ socktypename(*ip);
+ ip++;
+ narg--;
+ if (sockdomain == PF_INET ||
+ sockdomain == PF_INET6) {
+ putchar(',');
+ sockipprotoname(*ip);
+ ip++;
+ narg--;
+ }
+ c = ',';
+ break;
+ }
+ case SYS_setsockopt:
+ case SYS_getsockopt:
+ print_number(ip, narg, c);
+ putchar(',');
+ sockoptlevelname(*ip, decimal);
+ if (*ip == SOL_SOCKET) {
+ 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_number(ip, narg, c);
+ putchar(',');
+ whencename(*ip);
+ ip++;
+ narg--;
+ break;
+#endif
+ case SYS_lseek:
+ print_number(ip, narg, c);
+ /* Hidden 'pad' argument, not in lseek(2) */
+ print_number(ip, narg, c);
+ putchar(',');
+ whencename(*ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_flock:
+ print_number(ip, narg, c);
+ putchar(',');
+ flockname(*ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_mkfifo:
+ case SYS_mkdir:
+ print_number(ip, narg, c);
+ putchar(',');
+ modename(*ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_shutdown:
+ print_number(ip, narg, c);
+ putchar(',');
+ shutdownhowname(*ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_socketpair:
+ putchar('(');
+ sockdomainname(*ip);
+ ip++;
+ narg--;
+ putchar(',');
+ socktypename(*ip);
+ ip++;
+ narg--;
+ c = ',';
+ break;
+ case SYS_getrlimit:
+ case SYS_setrlimit:
+ putchar('(');
+ rlimitname(*ip);
+ ip++;
+ narg--;
+ c = ',';
+ break;
+ case SYS_quotactl:
+ print_number(ip, narg, c);
+ putchar(',');
+ quotactlname(*ip);
+ ip++;
+ narg--;
+ c = ',';
+ break;
+ case SYS_nfssvc:
+ putchar('(');
+ nfssvcname(*ip);
+ ip++;
+ narg--;
+ c = ',';
+ break;
+ case SYS_rtprio:
+ putchar('(');
+ rtprioname(*ip);
+ ip++;
+ narg--;
+ c = ',';
+ break;
+ case SYS___semctl:
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ putchar(',');
+ semctlname(*ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_semget:
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ putchar(',');
+ semgetname(*ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_msgctl:
+ print_number(ip, narg, c);
+ putchar(',');
+ shmctlname(*ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_shmat:
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ putchar(',');
+ shmatname(*ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_shmctl:
+ print_number(ip, narg, c);
+ putchar(',');
+ shmctlname(*ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_minherit:
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ putchar(',');
+ minheritname(*ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_rfork:
+ putchar('(');
+ rforkname(*ip);
+ ip++;
+ narg--;
+ c = ',';
+ break;
+ case SYS_lio_listio:
+ putchar('(');
+ lio_listioname(*ip);
+ ip++;
+ narg--;
+ c = ',';
+ break;
+ case SYS_mlockall:
+ putchar('(');
+ mlockallname(*ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_sched_setscheduler:
+ print_number(ip, narg, c);
+ putchar(',');
+ schedpolicyname(*ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_sched_get_priority_max:
+ case SYS_sched_get_priority_min:
+ putchar('(');
+ schedpolicyname(*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(*ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_kldsym:
+ print_number(ip, narg, c);
+ putchar(',');
+ kldsymcmdname(*ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_sigprocmask:
+ putchar('(');
+ sigprocmaskhowname(*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);
+ ip++;
+ narg--;
+ break;
+ case SYS_sigaction:
+ putchar('(');
+ signame(*ip);
+ ip++;
+ narg--;
+ c = ',';
+ break;
+ case SYS_extattrctl:
+ print_number(ip, narg, c);
+ putchar(',');
+ extattrctlname(*ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_nmount:
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ putchar(',');
+ mountflagsname(*ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_thr_create:
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ putchar(',');
+ thrcreateflagsname(*ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_thr_kill:
+ print_number(ip, narg, c);
+ putchar(',');
+ signame(*ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_kldunloadf:
+ print_number(ip, narg, c);
+ putchar(',');
+ kldunloadfflagsname(*ip);
+ ip++;
+ narg--;
+ break;
+ case SYS_cap_new:
+ print_number(ip, narg, c);
+ putchar(',');
+ arg = *ip;
+ ip++;
+ narg--;
+ /*
+ * Hack: the second argument is a
+ * cap_rights_t, which 64 bits wide, so on
+ * 32-bit systems, it is split between two
+ * registers.
+ *
+ * Since sizeof() is not evaluated by the
+ * preprocessor, we can't use an #ifdef,
+ * but the compiler will probably optimize
+ * the code out anyway.
+ */
+ if (sizeof(cap_rights_t) > sizeof(register_t)) {
+#if _BYTE_ORDER == _LITTLE_ENDIAN
+ arg = ((intmax_t)*ip << 32) + arg;
+#else
+ arg = (arg << 32) + *ip;
+#endif
+ ip++;
+ narg--;
+ }
+ capname(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);
+ ip++;
+ narg--;
+ break;
+ }
+ }
+ while (narg > 0) {
+ print_number(ip, narg, c);
+ }
+ putchar(')');
+ }
+ putchar('\n');
+}
+
+void
+ktrsysret(struct ktr_sysret *ktr, u_int flags)
+{
+ register_t ret = ktr->ktr_retval;
+ int error = ktr->ktr_error;
+ int code = ktr->ktr_code;
+
+ if ((flags != 0 && ((flags & SV_ABI_MASK) != SV_ABI_FREEBSD)) ||
+ (code >= nsyscalls || code < 0))
+ printf("[%d] ", code);
+ else
+ printf("%s ", syscallnames[code]);
+
+ 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", ktr->ktr_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;
+
+ 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;
+ }
+ 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 (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);
+ if (psig->action == SIG_DFL)
+ printf("SIG_DFL code=0x%x\n", psig->code);
+ else {
+ printf("caught handler=0x%lx mask=0x%x code=0x%x\n",
+ (u_long)psig->action, psig->mask.__bits[0], psig->code);
+ }
+}
+
+void
+ktrcsw(struct ktr_csw *cs)
+{
+ printf("%s %s\n", cs->out ? "stop" : "resume",
+ cs->user ? "user" : "kernel");
+}
+
+#define UTRACE_DLOPEN_START 1
+#define UTRACE_DLOPEN_STOP 2
+#define UTRACE_DLCLOSE_START 3
+#define UTRACE_DLCLOSE_STOP 4
+#define UTRACE_LOAD_OBJECT 5
+#define UTRACE_UNLOAD_OBJECT 6
+#define UTRACE_ADD_RUNDEP 7
+#define UTRACE_PRELOAD_FINISHED 8
+#define UTRACE_INIT_CALL 9
+#define UTRACE_FINI_CALL 10
+
+struct utrace_rtld {
+ char sig[4]; /* 'RTLD' */
+ int event;
+ void *handle;
+ void *mapbase;
+ size_t mapsize;
+ int refcnt;
+ char name[MAXPATHLEN];
+};
+
+void
+ktruser_rtld(int len, unsigned char *p)
+{
+ struct utrace_rtld *ut = (struct utrace_rtld *)p;
+ void *parent;
+ int mode;
+
+ switch (ut->event) {
+ case UTRACE_DLOPEN_START:
+ mode = ut->refcnt;
+ printf("dlopen(%s, ", ut->name);
+ switch (mode & RTLD_MODEMASK) {
+ case RTLD_NOW:
+ printf("RTLD_NOW");
+ break;
+ case RTLD_LAZY:
+ printf("RTLD_LAZY");
+ break;
+ default:
+ printf("%#x", mode & RTLD_MODEMASK);
+ }
+ if (mode & RTLD_GLOBAL)
+ printf(" | RTLD_GLOBAL");
+ if (mode & RTLD_TRACE)
+ printf(" | RTLD_TRACE");
+ if (mode & ~(RTLD_MODEMASK | RTLD_GLOBAL | RTLD_TRACE))
+ printf(" | %#x", mode &
+ ~(RTLD_MODEMASK | RTLD_GLOBAL | RTLD_TRACE));
+ printf(")\n");
+ break;
+ case UTRACE_DLOPEN_STOP:
+ printf("%p = dlopen(%s) ref %d\n", ut->handle, ut->name,
+ ut->refcnt);
+ break;
+ case UTRACE_DLCLOSE_START:
+ printf("dlclose(%p) (%s, %d)\n", ut->handle, ut->name,
+ ut->refcnt);
+ break;
+ case UTRACE_DLCLOSE_STOP:
+ printf("dlclose(%p) finished\n", ut->handle);
+ break;
+ case UTRACE_LOAD_OBJECT:
+ printf("RTLD: loaded %p @ %p - %p (%s)\n", ut->handle,
+ ut->mapbase, (char *)ut->mapbase + ut->mapsize - 1,
+ ut->name);
+ break;
+ case UTRACE_UNLOAD_OBJECT:
+ printf("RTLD: unloaded %p @ %p - %p (%s)\n", ut->handle,
+ ut->mapbase, (char *)ut->mapbase + ut->mapsize - 1,
+ ut->name);
+ break;
+ case UTRACE_ADD_RUNDEP:
+ parent = ut->mapbase;
+ printf("RTLD: %p now depends on %p (%s, %d)\n", parent,
+ ut->handle, ut->name, ut->refcnt);
+ break;
+ case UTRACE_PRELOAD_FINISHED:
+ printf("RTLD: LD_PRELOAD finished\n");
+ break;
+ case UTRACE_INIT_CALL:
+ printf("RTLD: init %p for %p (%s)\n", ut->mapbase, ut->handle,
+ ut->name);
+ break;
+ case UTRACE_FINI_CALL:
+ printf("RTLD: fini %p for %p (%s)\n", ut->mapbase, ut->handle,
+ ut->name);
+ break;
+ default:
+ p += 4;
+ len -= 4;
+ printf("RTLD: %d ", len);
+ while (len--)
+ if (decimal)
+ printf(" %d", *p++);
+ else
+ printf(" %02x", *p++);
+ printf("\n");
+ }
+}
+
+struct utrace_malloc {
+ void *p;
+ size_t s;
+ void *r;
+};
+
+void
+ktruser_malloc(unsigned char *p)
+{
+ struct utrace_malloc *ut = (struct utrace_malloc *)p;
+
+ if (ut->p == (void *)(intptr_t)(-1))
+ printf("malloc_init()\n");
+ else if (ut->s == 0)
+ printf("free(%p)\n", ut->p);
+ else if (ut->p == NULL)
+ printf("%p = malloc(%zu)\n", ut->r, ut->s);
+ else
+ printf("%p = realloc(%p, %zu)\n", ut->r, ut->p, ut->s);
+}
+
+void
+ktruser(int len, unsigned char *p)
+{
+
+ if (len >= 8 && bcmp(p, "RTLD", 4) == 0) {
+ ktruser_rtld(len, p);
+ return;
+ }
+
+ if (len == sizeof(struct utrace_malloc)) {
+ ktruser_malloc(p);
+ return;
+ }
+
+ printf("%d ", len);
+ while (len--)
+ if (decimal)
+ printf(" %d", *p++);
+ else
+ printf(" %02x", *p++);
+ printf("\n");
+}
+
+void
+ktrsockaddr(struct sockaddr *sa)
+{
+/*
+ TODO: Support additional address families
+ #include <netnatm/natm.h>
+ struct sockaddr_natm *natm;
+ #include <netsmb/netbios.h>
+ struct sockaddr_nb *nb;
+*/
+ 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);
+ 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, sizeof(sa));
+ 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;
+ }
+#ifdef NETATALK
+ case AF_APPLETALK: {
+ struct sockaddr_at sa_at;
+ struct netrange *nr;
+
+ memset(&sa_at, 0, sizeof(sa_at));
+ memcpy(&sa_at, sa, sizeof(sa));
+ check_sockaddr_len(at);
+ nr = &sa_at.sat_range.r_netrange;
+ printf("%d.%d, %d-%d, %d", ntohs(sa_at.sat_addr.s_net),
+ sa_at.sat_addr.s_node, ntohs(nr->nr_firstnet),
+ ntohs(nr->nr_lastnet), nr->nr_phase);
+ break;
+ }
+#endif
+ case AF_INET6: {
+ struct sockaddr_in6 sa_in6;
+
+ memset(&sa_in6, 0, sizeof(sa_in6));
+ memcpy(&sa_in6, sa, sizeof(sa));
+ check_sockaddr_len(in6);
+ inet_ntop(AF_INET6, &sa_in6.sin6_addr, addr, sizeof addr);
+ printf("[%s]:%u", addr, htons(sa_in6.sin6_port));
+ break;
+ }
+#ifdef IPX
+ case AF_IPX: {
+ struct sockaddr_ipx sa_ipx;
+
+ memset(&sa_ipx, 0, sizeof(sa_ipx));
+ memcpy(&sa_ipx, sa, sizeof(sa));
+ check_sockaddr_len(ipx);
+ /* XXX wish we had ipx_ntop */
+ printf("%s", ipx_ntoa(sa_ipx.sipx_addr));
+ free(sa_ipx);
+ break;
+ }
+#endif
+ case AF_UNIX: {
+ struct sockaddr_un sa_un;
+
+ memset(&sa_un, 0, sizeof(sa_un));
+ memcpy(&sa_un, sa, sizeof(sa));
+ check_sockaddr_len(un);
+ 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 {");
+ strmode(statp->st_mode, mode);
+ printf("dev=%ju, ino=%ju, mode=%s, nlink=%ju, ",
+ (uintmax_t)statp->st_dev, (uintmax_t)statp->st_ino, mode,
+ (uintmax_t)statp->st_nlink);
+ if (resolv == 0 || (pwd = getpwuid(statp->st_uid)) == NULL)
+ printf("uid=%ju, ", (uintmax_t)statp->st_uid);
+ else
+ printf("uid=\"%s\", ", pwd->pw_name);
+ if (resolv == 0 || (grp = getgrgid(statp->st_gid)) == 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("stime=");
+ 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;
+ 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, "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 < sizeof(struct sockaddr) ||
+ 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((intmax_t)ktr->cap_needed);
+ printf(", process holds ");
+ capname((intmax_t)ktr->cap_held);
+ break;
+ case CAPFAIL_INCREASE:
+ /* requested more capabilities than fd already has */
+ printf("attempt to increase capabilities from ");
+ capname((intmax_t)ktr->cap_held);
+ printf(" to ");
+ capname((intmax_t)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((intmax_t)ktr->cap_needed);
+ printf(" ");
+ capname((intmax_t)ktr->cap_held);
+ break;
+ }
+ printf("\n");
+}
+
+void
+ktrfault(struct ktr_fault *ktr)
+{
+
+ printf("0x%jx ", ktr->vaddr);
+ vmprotname(ktr->type);
+ printf("\n");
+}
+
+void
+ktrfaultend(struct ktr_faultend *ktr)
+{
+
+ vmresultname(ktr->result);
+ printf("\n");
+}
+
+#if defined(__amd64__) || defined(__i386__)
+void
+linux_ktrsyscall(struct ktr_syscall *ktr)
+{
+ int narg = ktr->ktr_narg;
+ register_t *ip;
+
+ if (ktr->ktr_code >= nlinux_syscalls || ktr->ktr_code < 0)
+ printf("[%d]", ktr->ktr_code);
+ else
+ printf("%s", linux_syscallnames[ktr->ktr_code]);
+ ip = &ktr->ktr_args[0];
+ if (narg) {
+ char c = '(';
+ while (narg > 0)
+ print_number(ip, narg, c);
+ putchar(')');
+ }
+ putchar('\n');
+}
+
+void
+linux_ktrsysret(struct ktr_sysret *ktr)
+{
+ register_t ret = ktr->ktr_retval;
+ int error = ktr->ktr_error;
+ int code = ktr->ktr_code;
+
+ if (code >= nlinux_syscalls || code < 0)
+ printf("[%d] ", code);
+ else
+ printf("%s ", linux_syscallnames[code]);
+
+ 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 {
+ if (ktr->ktr_error <= ELAST + 1)
+ error = abs(bsd_to_linux_errno[ktr->ktr_error]);
+ else
+ error = 999;
+ printf("-1 errno %d", error);
+ if (fancy)
+ printf(" %s", strerror(ktr->ktr_error));
+ }
+ putchar('\n');
+}
+#endif
+
+void
+usage(void)
+{
+ fprintf(stderr, "usage: kdump [-dEnlHRrsTA] [-f trfile] "
+ "[-m maxdata] [-p pid] [-t trstr]\n");
+ exit(1);
+}
OpenPOWER on IntegriCloud