Index: lib/libsysdecode/Makefile =================================================================== --- lib/libsysdecode/Makefile +++ lib/libsysdecode/Makefile @@ -17,6 +17,7 @@ sysdecode_cap_rights.3 \ sysdecode_enum.3 \ sysdecode_fcntl_arg.3 \ + sysdecode_kevent.3 \ sysdecode_ioctlname.3 \ sysdecode_mask.3 \ sysdecode_quotactl_cmd.3 \ @@ -69,6 +70,9 @@ sysdecode_enum.3 sysdecode_vmresult.3 \ sysdecode_enum.3 sysdecode_whence.3 MLINKS+=sysdecode_fcntl_arg.3 sysdecode_fcntl_arg_p.3 +MLINKS+=sysdecode_kevent.3 sysdecode_kevent_fflags.3 \ + sysdecode_kevent.3 sysdecode_kevent_filter.3 \ + sysdecode_kevent.3 sysdecode_kevent_flags.3 MLINKS+=sysdecode_mask.3 sysdecode_accessmode.3 \ sysdecode_mask.3 sysdecode_atflags.3 \ sysdecode_mask.3 sysdecode_capfcntlrights.3 \ Index: lib/libsysdecode/flags.c =================================================================== --- lib/libsysdecode/flags.c +++ lib/libsysdecode/flags.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -501,6 +502,116 @@ return (lookup_value(rusage, who)); } +static struct name_table kevent_user_ffctrl[] = { + X(NOTE_FFNOP) X(NOTE_FFAND) X(NOTE_FFOR) X(NOTE_FFCOPY) + XEND +}; + +static struct name_table kevent_rdwr_fflags[] = { + X(NOTE_LOWAT) X(NOTE_FILE_POLL) XEND +}; + +static struct name_table kevent_vnode_fflags[] = { + X(NOTE_DELETE) X(NOTE_WRITE) X(NOTE_EXTEND) X(NOTE_ATTRIB) + X(NOTE_LINK) X(NOTE_RENAME) X(NOTE_REVOKE) X(NOTE_OPEN) X(NOTE_CLOSE) + X(NOTE_CLOSE_WRITE) X(NOTE_READ) XEND +}; + +static struct name_table kevent_proc_fflags[] = { + X(NOTE_EXIT) X(NOTE_FORK) X(NOTE_EXEC) X(NOTE_TRACK) X(NOTE_TRACKERR) + X(NOTE_CHILD) XEND +}; + +static struct name_table kevent_timer_fflags[] = { + X(NOTE_SECONDS) X(NOTE_MSECONDS) X(NOTE_USECONDS) X(NOTE_NSECONDS) + X(NOTE_ABSTIME) XEND +}; + +void +sysdecode_kevent_fflags(FILE *fp, short filter, int fflags, int base) +{ + int rem; + + if (fflags == 0) { + fputs("0", fp); + return; + } + + switch (filter) { + case EVFILT_READ: + case EVFILT_WRITE: + if (!print_mask_int(fp, kevent_rdwr_fflags, fflags, &rem)) + fprintf(fp, "%#x", rem); + else if (rem != 0) + fprintf(fp, "|%#x", rem); + break; + case EVFILT_VNODE: + if (!print_mask_int(fp, kevent_vnode_fflags, fflags, &rem)) + fprintf(fp, "%#x", rem); + else if (rem != 0) + fprintf(fp, "|%#x", rem); + break; + case EVFILT_PROC: + case EVFILT_PROCDESC: + if (!print_mask_int(fp, kevent_proc_fflags, fflags, &rem)) + fprintf(fp, "%#x", rem); + else if (rem != 0) + fprintf(fp, "|%#x", rem); + break; + case EVFILT_TIMER: + if (!print_mask_int(fp, kevent_timer_fflags, fflags, &rem)) + fprintf(fp, "%#x", rem); + else if (rem != 0) + fprintf(fp, "|%#x", rem); + break; + case EVFILT_USER: { + unsigned int ctrl, data; + + ctrl = fflags & NOTE_FFCTRLMASK; + data = fflags & NOTE_FFLAGSMASK; + + if (fflags & NOTE_TRIGGER) { + fputs("NOTE_TRIGGER", fp); + if (fflags == NOTE_TRIGGER) + return; + fputc('|', fp); + } + + /* + * An event with 'ctrl' == NOTE_FFNOP is either a reported + * (output) event for which only 'data' should be output + * or a pointless input event. Assume that pointless + * input events don't occur in practice. An event with + * NOTE_TRIGGER is always an input event. + */ + if (ctrl != NOTE_FFNOP || fflags & NOTE_TRIGGER) { + fputs(lookup_value(kevent_user_ffctrl, ctrl), fp); + fprintf(fp, "|%#x", data); + } else { + print_integer(fp, data, base); + } + break; + } + default: + print_integer(fp, fflags, base); + break; + } +} + +bool +sysdecode_kevent_flags(FILE *fp, int flags, int *rem) +{ + + return (print_mask_int(fp, keventflags, flags, rem)); +} + +const char * +sysdecode_kevent_filter(int filter) +{ + + return (lookup_value(keventfilters, filter)); +} + const char * sysdecode_kldsym_cmd(int cmd) { Index: lib/libsysdecode/mktables =================================================================== --- lib/libsysdecode/mktables +++ lib/libsysdecode/mktables @@ -107,6 +107,8 @@ gen_table "ngbtsolevel" "SOL_[A-Z0-9]+[[:space:]]+0x[0-9A-Fa-f]+" "netgraph/bluetooth/include/ng_btsocket.h" gen_table "fileflags" "[SU]F_[A-Z]+[[:space:]]+0x[0-9A-Fa-f]+" "sys/stat.h" "UF_COMPRESSED|UF_TRACKED|UF_SETTABLE|SF_SETTABLE" gen_table "filemode" "S_[A-Z]+[[:space:]]+[0-6]{7}" "sys/stat.h" +gen_table "keventflags" "EV_[A-Z]+[[:space:]]+0x[0-9]+" "sys/event.h" "EV_SYSFLAGS|EV_DROP|EV_FLAG[12]" +gen_table "keventfilters" "EVFILT_[A-Z]+[[:space:]]+\(-[0-9]+\)" "sys/event.h" gen_table "mountflags" "MNT_[A-Z]+[[:space:]]+0x[0-9]+" "sys/mount.h" gen_table "msyncflags" "MS_[A-Z]+[[:space:]]+0x[0-9]+" "sys/mman.h" gen_table "nfssvcflags" "NFSSVC_[A-Z0-9]+[[:space:]]+0x[0-9]+" "nfs/nfssvc.h" Index: lib/libsysdecode/sysdecode.h =================================================================== --- lib/libsysdecode/sysdecode.h +++ lib/libsysdecode/sysdecode.h @@ -60,6 +60,10 @@ const char *sysdecode_idtype(int _idtype); const char *sysdecode_ioctlname(unsigned long _val); const char *sysdecode_ipproto(int _protocol); +void sysdecode_kevent_fflags(FILE *_fp, short _filter, int _fflags, + int _base); +const char *sysdecode_kevent_filter(int _filter); +bool sysdecode_kevent_flags(FILE *_fp, int _flags, int *_rem); const char *sysdecode_kldsym_cmd(int _cmd); const char *sysdecode_kldunload_flags(int _flags); const char *sysdecode_lio_listio_mode(int _mode); Index: lib/libsysdecode/sysdecode.3 =================================================================== --- lib/libsysdecode/sysdecode.3 +++ lib/libsysdecode/sysdecode.3 @@ -73,6 +73,7 @@ .Xr sysdecode_enum 3 , .Xr sysdecode_fcntl_arg 3 , .Xr sysdecode_ioctlname 3 , +.Xr sysdecode_kevent 3 , .Xr sysdecode_mask 3 , .Xr sysdecode_quotactl_cmd 3 , .Xr sysdecode_sigcode 3 , Index: lib/libsysdecode/sysdecode_kevent.3 =================================================================== --- /dev/null +++ lib/libsysdecode/sysdecode_kevent.3 @@ -0,0 +1,125 @@ +.\" +.\" Copyright (c) 2017 John Baldwin +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd September 10, 2017 +.Dt sysdecode_kevent 3 +.Os +.Sh NAME +.Nm sysdecode_kevent , +.Nm sysdecode_kevent_fflags , +.Nm sysdecode_kevent_filter , +.Nm sysdecode_kevent_flags +.Nd output description of kevent structure fields +.Sh LIBRARY +.Lb libsysdecode +.Sh SYNOPSIS +.In sys/types.h +.In stdbool.h +.In sysdecode.h +.Ft void +.Fn sysdecode_kevent_fflags "FILE *fp" "short filter" "int fflags" "int base" +.Ft bool +.Fn sysdecode_kevent_flags "FILE *fp" "int flags" "int *rem" +.Ft const char * +.Fn sysdecode_kevent_filter "int filter" +.Sh DESCRIPTION +These functions provide text descriptions of +.Vt struct kevent +fields. +.Pp +The +.Fn sysdecode_kevent_fflags +function outputs a text description of the +.Fa fflags +member of a +.Vt struct kevent +to the stream +.Fa fp . +For the +.Dv EVFILT_READ , +.Dv EVFILT_WRITE , +.Dv EVFILT_VNODE , +.Dv EVFILT_PROC , +.Dv EVFILT_PROCDESC , +.Dv EVFILT_TIMER , +and +.Dv EVFILT_USER +filters, +.Fn sysdecode_kevent_fflags +outputs a bitmask of filter-specific +.Dv NOTE_* +flags as documented in +.Xr kevent 2 . +For other values of +.Fa filter , +the value of +.Fa fflags +is output in the indicated +.Fa base +.Pq one of 8, 10, or 16 . +.Pp +The +.Fn sysdecode_kevent_filter +function returns a text description of the +.Fa filter +member of a +.Vt struct kevent . +.Dv NULL +is returned if the +.Fa filter +value is unknown. +.Pp +The +.Fn sysdecode_kevent_flags +function outputs a text description of the +.Fa flags +member of a +.Vt struct kevent +to the stream +.Fa fp . +This function uses the same calling convention and formatting as the other +functions described in +.Xr sysdecode_mask 3 . +.Sh RETURN VALUES +The +.Nm sysdecode_kevent_filter +function returns the name of a filter or +.Dv NULL if the filter value is unknown. +.Pp +The +.Nm sysdecode_kevent_flags +function returns +.Dv true +if any flags in the +.Fa flags +field were decoded and +.Dv false +if no flags were decoded. +.Sh SEE ALSO +.Xr sysdecode 3 , +.Xr sysdecode_enum 3 , +.Xr sysdecode_mask 3 Index: sys/kern/kern_event.c =================================================================== --- sys/kern/kern_event.c +++ sys/kern/kern_event.c @@ -33,6 +33,10 @@ #include "opt_ktrace.h" #include "opt_kqueue.h" +#ifdef COMPAT_FREEBSD11 +#define _WANT_KEVENT11 +#endif + #include #include #include @@ -905,17 +909,6 @@ return (0); } -#ifdef KTRACE -static size_t -kev_iovlen(int n, u_int kgio, size_t kevent_size) -{ - - if (n < 0 || n >= kgio / kevent_size) - return (kgio); - return (n * kevent_size); -} -#endif - struct g_kevent_args { int fd; void *changelist; @@ -952,13 +945,6 @@ { struct timespec ts, *tsp; int error; -#ifdef KTRACE - struct uio ktruio; - struct iovec ktriov; - struct uio *ktruioin = NULL; - struct uio *ktruioout = NULL; - u_int kgio; -#endif if (uap->timeout != NULL) { error = copyin(uap->timeout, &ts, sizeof(ts)); @@ -969,35 +955,18 @@ tsp = NULL; #ifdef KTRACE - if (KTRPOINT(td, KTR_GENIO)) { - kgio = ktr_geniosize; - ktriov.iov_base = uap->changelist; - ktriov.iov_len = kev_iovlen(uap->nchanges, kgio, - k_ops->kevent_size); - ktruio = (struct uio){ .uio_iov = &ktriov, .uio_iovcnt = 1, - .uio_segflg = UIO_USERSPACE, .uio_rw = UIO_READ, - .uio_td = td }; - ktruioin = cloneuio(&ktruio); - ktriov.iov_base = uap->eventlist; - ktriov.iov_len = kev_iovlen(uap->nevents, kgio, - k_ops->kevent_size); - ktriov.iov_len = uap->nevents * k_ops->kevent_size; - ktruioout = cloneuio(&ktruio); - } + if (KTRPOINT(td, KTR_STRUCT_ARRAY)) + ktrstructarray("kevent", UIO_USERSPACE, uap->changelist, + uap->nchanges, k_ops->kevent_size); #endif error = kern_kevent(td, uap->fd, uap->nchanges, uap->nevents, k_ops, tsp); #ifdef KTRACE - if (ktruioin != NULL) { - ktruioin->uio_resid = kev_iovlen(uap->nchanges, kgio, - k_ops->kevent_size); - ktrgenio(uap->fd, UIO_WRITE, ktruioin, 0); - ktruioout->uio_resid = kev_iovlen(td->td_retval[0], kgio, - k_ops->kevent_size); - ktrgenio(uap->fd, UIO_READ, ktruioout, error); - } + if (error == 0 && KTRPOINT(td, KTR_STRUCT_ARRAY)) + ktrstructarray("kevent", UIO_USERSPACE, uap->eventlist, + td->td_retval[0], k_ops->kevent_size); #endif return (error); @@ -1040,15 +1009,6 @@ } #ifdef COMPAT_FREEBSD11 -struct kevent_freebsd11 { - __uintptr_t ident; /* identifier for this event */ - short filter; /* filter for event */ - unsigned short flags; - unsigned int fflags; - __intptr_t data; - void *udata; /* opaque user data identifier */ -}; - static int kevent11_copyout(void *arg, struct kevent *kevp, int count) { Index: sys/kern/kern_ktrace.c =================================================================== --- sys/kern/kern_ktrace.c +++ sys/kern/kern_ktrace.c @@ -106,6 +106,7 @@ struct ktr_csw ktr_csw; struct ktr_fault ktr_fault; struct ktr_faultend ktr_faultend; + struct ktr_struct_array ktr_struct_array; } ktr_data; STAILQ_ENTRY(ktr_request) ktr_list; }; @@ -125,6 +126,7 @@ [KTR_CAPFAIL] = sizeof(struct ktr_cap_fail), [KTR_FAULT] = sizeof(struct ktr_fault), [KTR_FAULTEND] = sizeof(struct ktr_faultend), + [KTR_STRUCT_ARRAY] = sizeof(struct ktr_struct_array), }; static STAILQ_HEAD(, ktr_request) ktr_free; @@ -765,6 +767,52 @@ } void +ktrstructarray(const char *name, enum uio_seg seg, void *data, + int num_items, size_t struct_size) +{ + struct ktr_request *req; + struct ktr_struct_array *ksa; + char *buf; + size_t buflen, datalen, namelen; + int max_items; + + /* Trim array length to genio size. */ + max_items = ktr_geniosize / struct_size; + if (num_items > max_items) { + if (max_items == 0) + num_items = 1; + else + num_items = max_items; + } + datalen = num_items * struct_size; + + if (data == NULL) + datalen = 0; + + namelen = strlen(name) + 1; + buflen = namelen + datalen; + buf = malloc(buflen, M_KTRACE, M_WAITOK); + strcpy(buf, name); + if (seg == UIO_SYSSPACE) + bcopy(data, buf + namelen, datalen); + else { + if (copyin(data, buf + namelen, datalen) != 0) { + free(buf, M_KTRACE); + return; + } + } + if ((req = ktr_getrequest(KTR_STRUCT_ARRAY)) == NULL) { + free(buf, M_KTRACE); + return; + } + ksa = &req->ktr_data.ktr_struct_array; + ksa->struct_size = struct_size; + req->ktr_buffer = buf; + req->ktr_header.ktr_len = buflen; + ktr_submitrequest(curthread, req); +} + +void ktrcapfail(enum ktr_cap_fail_type type, const cap_rights_t *needed, const cap_rights_t *held) { Index: sys/sys/event.h =================================================================== --- sys/sys/event.h +++ sys/sys/event.h @@ -71,6 +71,18 @@ __uint64_t ext[4]; }; +#if defined(_WANT_KEVENT11) +/* Older structure used in FreeBSD 11.x and older. */ +struct kevent_freebsd11 { + __uintptr_t ident; /* identifier for this event */ + short filter; /* filter for event */ + unsigned short flags; + unsigned int fflags; + __intptr_t data; + void *udata; /* opaque user data identifier */ +}; +#endif + /* actions */ #define EV_ADD 0x0001 /* add event to kq (implies enable) */ #define EV_DELETE 0x0002 /* delete event from kq */ Index: sys/sys/ktrace.h =================================================================== --- sys/sys/ktrace.h +++ sys/sys/ktrace.h @@ -221,6 +221,18 @@ }; /* + * KTR_STRUCT_ARRAY - array of misc. structs + */ +#define KTR_STRUCT_ARRAY 15 +struct ktr_struct_array { + size_t struct_size; + /* + * Followed by null-terminated structure name and then payload + * contents. + */ +}; + +/* * KTR_DROP - If this bit is set in ktr_type, then at least one event * between the previous record and this record was dropped. */ @@ -244,6 +256,7 @@ #define KTRFAC_CAPFAIL (1< #include #include #include #include +#include #include #include #include @@ -111,6 +113,8 @@ 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 usage(void); #define TIMESTAMP_NONE 0x0 @@ -546,6 +550,9 @@ 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; @@ -680,6 +687,7 @@ type = "USER"; break; case KTR_STRUCT: + case KTR_STRUCT_ARRAY: type = "STRU"; break; case KTR_SYSCTL: @@ -2072,6 +2080,98 @@ } 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: + case EVFILT_EMPTY: + 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 (!isalpha(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) { + switch (ksa->struct_size) { + case sizeof(struct kevent_freebsd11): + memset(&kev, 0, sizeof(struct kevent)); + memcpy(&kev, data, + sizeof(struct kevent_freebsd11)); + break; + case sizeof(struct kevent): + memcpy(&kev, data, sizeof(struct kevent)); + break; + default: + goto bad_size; + } + ktrkevent(&kev); + } else { + printf(" }\n"); + return; + } + } + printf(" }\n"); + return; +invalid: + printf("invalid record\n"); + return; +bad_size: + printf(" }\n"); + return; +} + +void usage(void) { fprintf(stderr, "usage: kdump [-dEnlHRrSsTA] [-f trfile] " Index: usr.bin/ktrace/ktrace.h =================================================================== --- usr.bin/ktrace/ktrace.h +++ usr.bin/ktrace/ktrace.h @@ -34,7 +34,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) Index: usr.bin/truss/syscalls.c =================================================================== --- usr.bin/truss/syscalls.c +++ usr.bin/truss/syscalls.c @@ -650,43 +650,6 @@ #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) @@ -1137,7 +1100,7 @@ } static void -print_kevent(FILE *fp, struct kevent *ke, int input) +print_kevent(FILE *fp, struct kevent *ke) { switch (ke->filter) { @@ -1147,6 +1110,7 @@ case EVFILT_PROC: case EVFILT_TIMER: case EVFILT_PROCDESC: + case EVFILT_EMPTY: fprintf(fp, "%ju", (uintmax_t)ke->ident); break; case EVFILT_SIGNAL: @@ -1155,42 +1119,12 @@ 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, ",%#jx,%p", (uintmax_t)ke->data, ke->udata); } @@ -1795,7 +1729,7 @@ 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 {