summaryrefslogtreecommitdiffstats
path: root/usr.bin/kdump
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/kdump')
-rw-r--r--usr.bin/kdump/Makefile40
-rw-r--r--usr.bin/kdump/kdump.1183
-rw-r--r--usr.bin/kdump/kdump.c1736
-rw-r--r--usr.bin/kdump/linux_syscalls.conf11
-rw-r--r--usr.bin/kdump/mkioctls113
-rw-r--r--usr.bin/kdump/mksubr504
6 files changed, 2587 insertions, 0 deletions
diff --git a/usr.bin/kdump/Makefile b/usr.bin/kdump/Makefile
new file mode 100644
index 0000000..f19bd16
--- /dev/null
+++ b/usr.bin/kdump/Makefile
@@ -0,0 +1,40 @@
+# @(#)Makefile 8.1 (Berkeley) 6/6/93
+# $FreeBSD$
+
+.if (${MACHINE_ARCH} == "amd64")
+SFX= 32
+.endif
+
+.PATH: ${.CURDIR}/../ktrace
+
+PROG= kdump
+SRCS= kdump_subr.c kdump.c ioctl.c subr.c
+DPSRCS= kdump_subr.h
+CFLAGS+= -I${.CURDIR}/../ktrace -I${.CURDIR} -I${.CURDIR}/../.. -I.
+
+.if ${MACHINE_ARCH} == "amd64" || ${MACHINE_ARCH} == "i386"
+SRCS+= linux_syscalls.c
+.endif
+
+NO_WERROR?= YES
+
+CLEANFILES= ioctl.c kdump_subr.c kdump_subr.h linux_syscalls.c
+
+ioctl.c: mkioctls
+ env MACHINE=${MACHINE} CPP="${CPP}" \
+ sh ${.CURDIR}/mkioctls print ${DESTDIR}/usr/include > ${.TARGET}
+
+kdump_subr.h: mksubr
+ sh ${.CURDIR}/mksubr ${DESTDIR}/usr/include | \
+ sed -n 's/^\([a-z].*)\)$$/void \1;/p' >${.TARGET}
+
+kdump_subr.c: mksubr kdump_subr.h
+ sh ${.CURDIR}/mksubr ${DESTDIR}/usr/include >${.TARGET}
+
+linux_syscalls.c:
+ /bin/sh ${.CURDIR}/../../sys/kern/makesyscalls.sh \
+ ${.CURDIR}/../../sys/${MACHINE_ARCH}/linux${SFX}/syscalls.master ${.CURDIR}/linux_syscalls.conf
+ echo "int nlinux_syscalls = sizeof(linux_syscallnames) / sizeof(linux_syscallnames[0]);" \
+ >> linux_syscalls.c
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/kdump/kdump.1 b/usr.bin/kdump/kdump.1
new file mode 100644
index 0000000..c03985e
--- /dev/null
+++ b/usr.bin/kdump/kdump.1
@@ -0,0 +1,183 @@
+.\" Copyright (c) 1990, 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.
+.\"
+.\" @(#)kdump.1 8.1 (Berkeley) 6/6/93
+.\" $FreeBSD$
+.\"
+.Dd April 5, 2012
+.Dt KDUMP 1
+.Os
+.Sh NAME
+.Nm kdump
+.Nd display kernel trace data
+.Sh SYNOPSIS
+.Nm
+.Op Fl dEnlHRsTA
+.Op Fl f Ar trfile
+.Op Fl m Ar maxdata
+.Op Fl p Ar pid
+.Op Fl t Ar trstr
+.Sh DESCRIPTION
+The
+.Nm
+command displays the kernel trace files produced with
+.Xr ktrace 1
+in human readable format.
+By default, the file
+.Pa ktrace.out
+in the current directory is displayed.
+.Pp
+The options are as follows:
+.Bl -tag -width Fl
+.It Fl d
+Display all numbers in decimal.
+.It Fl E
+Display elapsed timestamps (time since beginning of trace).
+.It Fl f Ar trfile
+Display the specified file instead of
+.Pa ktrace.out .
+.It Fl H
+List the thread ID (tid) of the thread with each trace record, if available.
+If no thread ID is available, 0 will be printed.
+.It Fl l
+Loop reading the trace file, once the end-of-file is reached, waiting for
+more data.
+.It Fl m Ar maxdata
+Display at most
+.Ar maxdata
+bytes when decoding
+.Tn I/O .
+.It Fl n
+Suppress ad hoc translations.
+Normally
+.Nm
+tries to decode many system calls into a more human readable format.
+For example,
+.Xr ioctl 2
+values are replaced with the macro name and
+.Va errno
+values are replaced with the
+.Xr strerror 3
+string.
+Suppressing this feature yields a more consistent output format and is
+easily amenable to further processing.
+.It Fl p Ar pid
+Display only trace events that correspond to the process
+.Ar pid .
+This may be useful when there are multiple processes recorded in the
+same trace file.
+.It Fl R
+Display relative timestamps (time since previous entry).
+.It Fl r
+When decoding STRU records, display structure members such as UIDs,
+GIDs, dates etc. symbolically instead of numerically.
+.It Fl s
+Suppress display of I/O data.
+.It Fl T
+Display absolute timestamps for each entry (seconds since epoch).
+.It Fl A
+Display description of the ABI of traced process.
+.It Fl t Ar trstr
+See the
+.Fl t
+option of
+.Xr ktrace 1 .
+.El
+.Pp
+The output format of
+.Nm
+is line oriented with several fields.
+The example below shows a section of a kdump generated by the following
+commands:
+.Bd -literal -offset indent
+?> ktrace echo "ktrace"
+
+?> kdump
+
+ 85045 echo CALL writev(0x1,0x804b030,0x2)
+ 85045 echo GIO fd 1 wrote 7 bytes
+ "ktrace
+ "
+ 85045 echo RET writev 7
+.Ed
+.Pp
+The first field is the PID of the process being traced.
+The second field is the name of the program being traced.
+The third field is the operation that the kernel performed
+on behalf of the process.
+If thread IDs are being printed, then an additional thread ID column will be
+added to the output between the PID field and program name field.
+.Pp
+In the first line above, the kernel executes the
+.Xr writev 2
+system call on behalf of the process so this is a
+.Li CALL
+operation.
+The fourth field shows the system call that was executed,
+including its arguments.
+The
+.Xr writev 2
+system call takes a file descriptor, in this case 1, or standard
+output, then a pointer to the iovector to write, and the number of
+iovectors that are to be written.
+In the second line we see the operation was
+.Li GIO ,
+for general I/O, and that file descriptor 1 had
+seven bytes written to it.
+This is followed by the seven bytes that were written, the string
+.Qq Li ktrace
+with a carriage return and line feed.
+The last line is the
+.Li RET
+operation, showing a return from the kernel, what system call we are
+returning from, and the return value that the process received.
+Seven bytes were written by the
+.Xr writev 2
+system call, so 7 is the return value.
+.Pp
+The possible operations are:
+.Bl -column -offset indent ".Li CALL" ".No data from user process"
+.It Sy Name Ta Sy Operation Ta Sy Fourth field
+.It Li CALL Ta enter syscall Ta syscall name and arguments
+.It Li RET Ta return from syscall Ta syscall name and return value
+.It Li NAMI Ta file name lookup Ta path to file
+.It Li GIO Ta general I/O Ta fd, read/write, number of bytes
+.It Li PSIG Ta signal Ta signal name, handler, mask, code
+.It Li CSW Ta context switch Ta stop/resume user/kernel
+.It Li USER Ta data from user process Ta the data
+.It Li STRU Ta various syscalls Ta structure
+.It Li SCTL Ta Xr sysctl 3 requests Ta MIB name
+.It Li PFLT Ta enter page fault Ta fault address and type
+.It Li PRET Ta return from page fault Ta fault result
+.El
+.Sh SEE ALSO
+.Xr ktrace 1
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.4 .
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);
+}
diff --git a/usr.bin/kdump/linux_syscalls.conf b/usr.bin/kdump/linux_syscalls.conf
new file mode 100644
index 0000000..82adb56
--- /dev/null
+++ b/usr.bin/kdump/linux_syscalls.conf
@@ -0,0 +1,11 @@
+# $FreeBSD$
+sysnames="linux_syscalls.c"
+sysproto="/dev/null"
+sysproto_h=_LINUX_SYSPROTO_H_
+syshdr="/dev/null"
+syssw="/dev/null"
+sysmk="/dev/null"
+syscallprefix="LINUX_SYS_"
+switchname="/dev/null"
+namesname="linux_syscallnames"
+systrace="/dev/null"
diff --git a/usr.bin/kdump/mkioctls b/usr.bin/kdump/mkioctls
new file mode 100644
index 0000000..eefe14c
--- /dev/null
+++ b/usr.bin/kdump/mkioctls
@@ -0,0 +1,113 @@
+#!/bin/sh
+#
+# $FreeBSD$
+#
+# When editing this script, keep in mind that truss also uses it.
+#
+
+set -e
+
+if [ $# -ne 2 -o \( $1 != "print" -a $1 != "return" \) ]; then
+ echo "usage: sh $0 print|return include-dir"
+ exit 1
+fi
+
+style="$1"
+includedir="$2"
+
+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' | grep -v '.*disk.*\.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 <sys/diskpc98.h>\\n"
+ ;;
+*)
+ ioctl_includes="$ioctl_includes#include <sys/diskmbr.h>\\n"
+ ;;
+esac
+
+awk -v x="$ioctl_includes" 'BEGIN {print x}' |
+ $CPP -I$1 -dM -DCOMPAT_43TTY - |
+ awk -v ioctl_includes="$ioctl_includes" -v style="$style" '
+BEGIN {
+ print "/* XXX obnoxious prerequisites. */"
+ print "#define COMPAT_43"
+ print "#define COMPAT_43TTY"
+ print "#include <sys/param.h>"
+ print "#include <sys/devicestat.h>"
+ print "#include <sys/disklabel.h>"
+ print "#include <sys/socket.h>"
+ print "#include <sys/time.h>"
+ print "#include <sys/tty.h>"
+ print "#include <bsm/audit.h>"
+ print "#include <net/ethernet.h>"
+ print "#include <net/if.h>"
+ print "#include <net/if_var.h>"
+ print "#include <net/pfvar.h>"
+ print "#include <net/route.h>"
+ print "#include <netinet/in.h>"
+ print "#include <netinet/ip_mroute.h>"
+ print "#include <netinet6/in6_var.h>"
+ print "#include <netinet6/nd6.h>"
+ print "#include <netinet6/ip6_mroute.h>"
+ print "#include <stdio.h>"
+ print "#include <cam/cam.h>"
+ print ""
+ print ioctl_includes
+ print ""
+ if (style == "print") {
+ print "void ioctlname(unsigned long val, int decimal);"
+ print ""
+ print "void"
+ print "ioctlname(unsigned long val, int decimal)"
+ } else {
+ print "const char *ioctlname(unsigned long val);"
+ print ""
+ print "const char *"
+ print "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 ""
+ if (style == "print") {
+ print "\tif (str != NULL)"
+ print "\t\tprintf(\"%s\", str);"
+ print "\telse if (decimal)"
+ print "\t\tprintf(\"%lu\", val);"
+ print "\telse"
+ print "\t\tprintf(\"%#lx\", val);"
+ } else {
+ print "\treturn (str);"
+ }
+ print "}"
+}
+'
diff --git a/usr.bin/kdump/mksubr b/usr.bin/kdump/mksubr
new file mode 100644
index 0000000..bc466d5
--- /dev/null
+++ b/usr.bin/kdump/mksubr
@@ -0,0 +1,504 @@
+#!/bin/sh
+#
+# Copyright (c) 2006 "David Kirchner" <dpk@dpk.net>. 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("<invalid>%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("<invalid=%jd>", 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("<invalid=%jd>", arg);
+}
+
+_EOF_
+}
+
+# C start
+
+cat <<_EOF_
+#include <stdint.h>
+#include <stdio.h>
+#include <sys/fcntl.h>
+#include <sys/stat.h>
+#include <sys/unistd.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+#define _KERNEL
+#include <sys/socket.h>
+#undef _KERNEL
+#include <netinet/in.h>
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/ptrace.h>
+#include <sys/resource.h>
+#include <sys/reboot.h>
+#include <sched.h>
+#include <sys/linker.h>
+#define _KERNEL
+#include <sys/thr.h>
+#undef _KERNEL
+#include <sys/extattr.h>
+#include <sys/acl.h>
+#include <aio.h>
+#include <sys/sem.h>
+#include <sys/ipc.h>
+#include <sys/rtprio.h>
+#include <sys/shm.h>
+#include <nfsserver/nfs.h>
+#include <ufs/ufs/quota.h>
+#include <sys/capability.h>
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+
+#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 */
+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("<invalid=%d>", 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("<invalid=%d>", 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("<unused>%d", mode);
+ } else {
+ printf("<unused>%#x", (unsigned int)mode);
+ }
+ }
+}
+
+/*
+ * 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);
+}
+_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 "capname" "CAP_[A-Z]+[[:space:]]+0x[01248]{16}ULL" "sys/capability.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 "mmapflagsname" "MAP_[A-Z]+[[:space:]]+0x[0-9A-Fa-f]+" "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-Z]+[[:space:]]+0x[0-9]+" "nfsserver/nfs.h"
+auto_switch_type "prioname" "PRIO_[A-Z]+[[:space:]]+[0-9]" "sys/resource.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 "sigprocmaskhowname" "SIG_[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 "vmresultname" "KERN_[A-Z]+[[:space:]]+[0-9]+" "vm/vm_param.h"
+auto_or_type "wait4optname" "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-Z]+[[: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("<invalid=%d>", 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("<invalid>%d", arg);
+ else
+ printf("<invalid>%#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 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("<invalid=%d>", 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(">");
+}
+
+_EOF_
OpenPOWER on IntegriCloud