summaryrefslogtreecommitdiffstats
path: root/usr.bin
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2018-01-26 23:49:31 +0000
committerjhb <jhb@FreeBSD.org>2018-01-26 23:49:31 +0000
commit8c4c4ccc2b840390c594ca9d75fba22f186c1b21 (patch)
treef13552e5a0d27a5c87ee875497eb1c0eb47ac759 /usr.bin
parent12d37c182ec56a128cf55cf1cd15ed8d194b0cfd (diff)
downloadFreeBSD-src-8c4c4ccc2b840390c594ca9d75fba22f186c1b21.zip
FreeBSD-src-8c4c4ccc2b840390c594ca9d75fba22f186c1b21.tar.gz
MFC 326184: Decode kevent structures logged via ktrace(2) in kdump.
- Add a new KTR_STRUCT_ARRAY ktrace record type which dumps an array of structures. The structure name in the record payload is preceded by a size_t containing the size of the individual structures. Use this to replace the previous code that dumped the kevent arrays dumped for kevent(). kdump is now able to decode the kevent structures rather than dumping their contents via a hexdump. One change from before is that the 'changes' and 'events' arrays are not marked with separate 'read' and 'write' annotations in kdump output. Instead, the first array is the 'changes' array, and the second array (only present if kevent doesn't fail with an error) is the 'events' array. For kevent(), empty arrays are denoted by an entry with an array containing zero entries rather than no record. - Move kevent decoding tables from truss to libsysdecode. This adds three new functions to decode members of struct kevent: sysdecode_kevent_filter, sysdecode_kevent_flags, and sysdecode_kevent_fflags. kdump uses these helper functions to pretty-print kevent fields. - Move structure definitions for freebsd11 and freebsd32 kevent structures to <sys/event.h> so that they can be shared with userland. The 32-bit structures are only exposed if _WANT_KEVENT32 is defined. The freebsd11 structures are only exposed if _WANT_FREEBSD11_KEVENT is defined. The 32-bit freebsd11 structure requires both. - Decode freebsd11 kevent structures in truss for the compat11.kevent() system call. - Log 32-bit kevent structures via ktrace for 32-bit compat kevent() system calls. - While here, constify the 'void *data' argument to ktrstruct(). Note that this version of the change for 11.x does not include freebsd11 kevent structures or _WANT_FREEBSD11_KEVENT. It also does not include the change to decode the compat11.kevent system call in truss.
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/kdump/kdump.c108
-rw-r--r--usr.bin/ktrace/ktrace.h3
-rw-r--r--usr.bin/truss/syscall.h2
-rw-r--r--usr.bin/truss/syscalls.c83
4 files changed, 119 insertions, 77 deletions
diff --git a/usr.bin/kdump/kdump.c b/usr.bin/kdump/kdump.c
index d849d94..7db1a8b 100644
--- a/usr.bin/kdump/kdump.c
+++ b/usr.bin/kdump/kdump.c
@@ -42,11 +42,15 @@ static char sccsid[] = "@(#)kdump.c 8.1 (Berkeley) 6/6/93";
__FBSDID("$FreeBSD$");
#define _WANT_KERNEL_ERRNO
+#ifdef __LP64__
+#define _WANT_KEVENT32
+#endif
#include <sys/param.h>
#include <sys/capsicum.h>
#include <sys/errno.h>
#include <sys/time.h>
#include <sys/uio.h>
+#include <sys/event.h>
#include <sys/ktrace.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
@@ -109,6 +113,8 @@ void ktrstruct(char *, size_t);
void ktrcapfail(struct ktr_cap_fail *);
void ktrfault(struct ktr_fault *);
void ktrfaultend(struct ktr_faultend *);
+void ktrkevent(struct kevent *);
+void ktrstructarray(struct ktr_struct_array *, size_t);
void limitfd(int fd);
void usage(void);
@@ -546,6 +552,9 @@ main(int argc, char *argv[])
case KTR_FAULTEND:
ktrfaultend((struct ktr_faultend *)m);
break;
+ case KTR_STRUCT_ARRAY:
+ ktrstructarray((struct ktr_struct_array *)m, ktrlen);
+ break;
default:
printf("\n");
break;
@@ -714,6 +723,7 @@ dumpheader(struct ktr_header *kth)
type = "USER";
break;
case KTR_STRUCT:
+ case KTR_STRUCT_ARRAY:
type = "STRU";
break;
case KTR_SYSCTL:
@@ -2109,6 +2119,104 @@ ktrfaultend(struct ktr_faultend *ktr)
}
void
+ktrkevent(struct kevent *kev)
+{
+
+ printf("{ ident=");
+ switch (kev->filter) {
+ case EVFILT_READ:
+ case EVFILT_WRITE:
+ case EVFILT_VNODE:
+ case EVFILT_PROC:
+ case EVFILT_TIMER:
+ case EVFILT_PROCDESC:
+ printf("%ju", (uintmax_t)kev->ident);
+ break;
+ case EVFILT_SIGNAL:
+ print_signal(kev->ident);
+ break;
+ default:
+ printf("%p", (void *)kev->ident);
+ }
+ printf(", filter=");
+ print_integer_arg(sysdecode_kevent_filter, kev->filter);
+ printf(", flags=");
+ print_mask_arg0(sysdecode_kevent_flags, kev->flags);
+ printf(", fflags=");
+ sysdecode_kevent_fflags(stdout, kev->filter, kev->fflags,
+ decimal ? 10 : 16);
+ printf(", data=%#jx, udata=%p }", (uintmax_t)kev->data, kev->udata);
+}
+
+void
+ktrstructarray(struct ktr_struct_array *ksa, size_t buflen)
+{
+ struct kevent kev;
+ char *name, *data;
+ size_t namelen, datalen;
+ int i;
+ bool first;
+
+ buflen -= sizeof(*ksa);
+ for (name = (char *)(ksa + 1), namelen = 0;
+ namelen < buflen && name[namelen] != '\0';
+ ++namelen)
+ /* nothing */;
+ if (namelen == buflen)
+ goto invalid;
+ if (name[namelen] != '\0')
+ goto invalid;
+ /* sanity check */
+ for (i = 0; i < (int)namelen; ++i)
+ if (!isalnum(name[i]) && name[i] != '_')
+ goto invalid;
+ data = name + namelen + 1;
+ datalen = buflen - namelen - 1;
+ printf("struct %s[] = { ", name);
+ first = true;
+ for (; datalen >= ksa->struct_size;
+ data += ksa->struct_size, datalen -= ksa->struct_size) {
+ if (!first)
+ printf("\n ");
+ else
+ first = false;
+ if (strcmp(name, "kevent") == 0) {
+ if (ksa->struct_size != sizeof(kev))
+ goto bad_size;
+ memcpy(&kev, data, sizeof(kev));
+ ktrkevent(&kev);
+#ifdef _WANT_KEVENT32
+ } else if (strcmp(name, "kevent32") == 0) {
+ struct kevent32 kev32;
+
+ if (ksa->struct_size != sizeof(kev32))
+ goto bad_size;
+ memcpy(&kev32, data, sizeof(kev32));
+ memset(&kev, 0, sizeof(kev));
+ kev.ident = kev32.ident;
+ kev.filter = kev32.filter;
+ kev.flags = kev32.flags;
+ kev.fflags = kev32.fflags;
+ kev.data = kev32.data;
+ kev.udata = (void *)(uintptr_t)kev32.udata;
+ ktrkevent(&kev);
+#endif
+ } else {
+ printf("<unknown structure> }\n");
+ return;
+ }
+ }
+ printf(" }\n");
+ return;
+invalid:
+ printf("invalid record\n");
+ return;
+bad_size:
+ printf("<bad size> }\n");
+ return;
+}
+
+void
usage(void)
{
fprintf(stderr, "usage: kdump [-dEnlHRrSsTA] [-f trfile] "
diff --git a/usr.bin/ktrace/ktrace.h b/usr.bin/ktrace/ktrace.h
index 26ac1143..f016516 100644
--- a/usr.bin/ktrace/ktrace.h
+++ b/usr.bin/ktrace/ktrace.h
@@ -32,7 +32,8 @@
#define DEF_POINTS (KTRFAC_SYSCALL | KTRFAC_SYSRET | KTRFAC_NAMEI | \
KTRFAC_GENIO | KTRFAC_PSIG | KTRFAC_USER | \
- KTRFAC_STRUCT | KTRFAC_SYSCTL | KTRFAC_CAPFAIL)
+ KTRFAC_STRUCT | KTRFAC_SYSCTL | KTRFAC_CAPFAIL | \
+ KTRFAC_STRUCT_ARRAY)
#define PROC_ABI_POINTS (KTRFAC_PROCCTOR | KTRFAC_PROCDTOR)
diff --git a/usr.bin/truss/syscall.h b/usr.bin/truss/syscall.h
index 9a5bdec..54e5ddb 100644
--- a/usr.bin/truss/syscall.h
+++ b/usr.bin/truss/syscall.h
@@ -51,7 +51,7 @@ enum Argtype { None = 1, Hex, Octal, Int, UInt, LongHex, Name, Ptr, Stat, Ioctl,
Sockoptname, Msgflags, CapRights, PUInt, PQuadHex, Acltype,
Extattrnamespace, Minherit, Mlockall, Mountflags, Msync, Priowhich,
Ptraceop, Quotactlcmd, Reboothowto, Rtpriofunc, Schedpolicy, Schedparam,
- PSig, Siginfo,
+ PSig, Siginfo, Kevent11,
CloudABIAdvice, CloudABIClockID, ClouduABIFDSFlags,
CloudABIFDStat, CloudABIFileStat, CloudABIFileType,
diff --git a/usr.bin/truss/syscalls.c b/usr.bin/truss/syscalls.c
index c717db1..e5f858f 100644
--- a/usr.bin/truss/syscalls.c
+++ b/usr.bin/truss/syscalls.c
@@ -638,43 +638,6 @@ struct xlat {
#define X(a) { a, #a },
#define XEND { 0, NULL }
-static struct xlat kevent_filters[] = {
- X(EVFILT_READ) X(EVFILT_WRITE) X(EVFILT_AIO) X(EVFILT_VNODE)
- X(EVFILT_PROC) X(EVFILT_SIGNAL) X(EVFILT_TIMER)
- X(EVFILT_PROCDESC) X(EVFILT_FS) X(EVFILT_LIO) X(EVFILT_USER)
- X(EVFILT_SENDFILE) XEND
-};
-
-static struct xlat kevent_flags[] = {
- X(EV_ADD) X(EV_DELETE) X(EV_ENABLE) X(EV_DISABLE) X(EV_ONESHOT)
- X(EV_CLEAR) X(EV_RECEIPT) X(EV_DISPATCH) X(EV_FORCEONESHOT)
- X(EV_DROP) X(EV_FLAG1) X(EV_ERROR) X(EV_EOF) XEND
-};
-
-static struct xlat kevent_user_ffctrl[] = {
- X(NOTE_FFNOP) X(NOTE_FFAND) X(NOTE_FFOR) X(NOTE_FFCOPY)
- XEND
-};
-
-static struct xlat kevent_rdwr_fflags[] = {
- X(NOTE_LOWAT) X(NOTE_FILE_POLL) XEND
-};
-
-static struct xlat kevent_vnode_fflags[] = {
- X(NOTE_DELETE) X(NOTE_WRITE) X(NOTE_EXTEND) X(NOTE_ATTRIB)
- X(NOTE_LINK) X(NOTE_RENAME) X(NOTE_REVOKE) XEND
-};
-
-static struct xlat kevent_proc_fflags[] = {
- X(NOTE_EXIT) X(NOTE_FORK) X(NOTE_EXEC) X(NOTE_TRACK) X(NOTE_TRACKERR)
- X(NOTE_CHILD) XEND
-};
-
-static struct xlat kevent_timer_fflags[] = {
- X(NOTE_SECONDS) X(NOTE_MSECONDS) X(NOTE_USECONDS) X(NOTE_NSECONDS)
- XEND
-};
-
static struct xlat poll_flags[] = {
X(POLLSTANDARD) X(POLLIN) X(POLLPRI) X(POLLOUT) X(POLLERR)
X(POLLHUP) X(POLLNVAL) X(POLLRDNORM) X(POLLRDBAND)
@@ -1125,7 +1088,7 @@ strsig2(int sig)
}
static void
-print_kevent(FILE *fp, struct kevent *ke, int input)
+print_kevent(FILE *fp, struct kevent *ke)
{
switch (ke->filter) {
@@ -1143,42 +1106,12 @@ print_kevent(FILE *fp, struct kevent *ke, int input)
default:
fprintf(fp, "%p", (void *)ke->ident);
}
- fprintf(fp, ",%s,%s,", xlookup(kevent_filters, ke->filter),
- xlookup_bits(kevent_flags, ke->flags));
- switch (ke->filter) {
- case EVFILT_READ:
- case EVFILT_WRITE:
- fputs(xlookup_bits(kevent_rdwr_fflags, ke->fflags), fp);
- break;
- case EVFILT_VNODE:
- fputs(xlookup_bits(kevent_vnode_fflags, ke->fflags), fp);
- break;
- case EVFILT_PROC:
- case EVFILT_PROCDESC:
- fputs(xlookup_bits(kevent_proc_fflags, ke->fflags), fp);
- break;
- case EVFILT_TIMER:
- fputs(xlookup_bits(kevent_timer_fflags, ke->fflags), fp);
- break;
- case EVFILT_USER: {
- int ctrl, data;
-
- ctrl = ke->fflags & NOTE_FFCTRLMASK;
- data = ke->fflags & NOTE_FFLAGSMASK;
- if (input) {
- fputs(xlookup(kevent_user_ffctrl, ctrl), fp);
- if (ke->fflags & NOTE_TRIGGER)
- fputs("|NOTE_TRIGGER", fp);
- if (data != 0)
- fprintf(fp, "|%#x", data);
- } else {
- fprintf(fp, "%#x", data);
- }
- break;
- }
- default:
- fprintf(fp, "%#x", ke->fflags);
- }
+ fprintf(fp, ",");
+ print_integer_arg(sysdecode_kevent_filter, fp, ke->filter);
+ fprintf(fp, ",");
+ print_mask_arg(sysdecode_kevent_flags, fp, ke->flags);
+ fprintf(fp, ",");
+ sysdecode_kevent_fflags(fp, ke->filter, ke->fflags, 16);
fprintf(fp, ",%p,%p", (void *)ke->data, (void *)ke->udata);
}
@@ -1783,7 +1716,7 @@ print_arg(struct syscall_args *sc, unsigned long *args, long *retval,
fputc('{', fp);
for (i = 0; i < numevents; i++) {
fputc(' ', fp);
- print_kevent(fp, &ke[i], sc->offset == 1);
+ print_kevent(fp, &ke[i]);
}
fputs(" }", fp);
} else {
OpenPOWER on IntegriCloud