From b4eccd408fde876761541bc0704f35fa18357032 Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Thu, 29 Feb 2024 10:58:32 +0200 Subject: a more generic enter/exit event handler --- internal/event.go | 41 +++++++++ internal/eventloop.go | 77 ++++++---------- internal/generated/nqc.raku | 25 +++++- internal/generated/types/types.go | 183 ++++++++++++++++++++++++++++++++++++-- 4 files changed, 268 insertions(+), 58 deletions(-) create mode 100644 internal/event.go diff --git a/internal/event.go b/internal/event.go new file mode 100644 index 0000000..7de9307 --- /dev/null +++ b/internal/event.go @@ -0,0 +1,41 @@ +package internal + +import ( + "fmt" + . "ioriotng/internal/generated/types" + "strings" +) + +type event interface { + String() string + GetSyscallId() SyscallId + GetPid() uint32 + GetTid() uint32 + GetTime() uint32 + Recycle() +} + +type enterExitEvent struct { + enterEv, exitEv event +} + +func (e enterExitEvent) String() string { + var sb strings.Builder + + duration := e.exitEv.GetTime() - e.enterEv.GetTime() + sb.WriteString(fmt.Sprintf("%08d µs", duration)) + + sb.WriteString(" ") + sb.WriteString(e.enterEv.GetSyscallId().Name()) + + return sb.String() +} + +func (e enterExitEvent) dump() string { + return fmt.Sprintf("%v with enterEv(%v) and exitEv(%v)", e, e.enterEv, e.exitEv) +} + +func (e enterExitEvent) recycle() { + e.enterEv.Recycle() + e.exitEv.Recycle() +} diff --git a/internal/eventloop.go b/internal/eventloop.go index d15c221..1d161dd 100644 --- a/internal/eventloop.go +++ b/internal/eventloop.go @@ -19,69 +19,50 @@ func (o openFile) String() string { return fmt.Sprintf("(%d) %s", o.fd, o.path) } -type Event interface { - String() string - TID() uint32 - Timestamp() uint32 - Recycle() -} - -type Syscall struct { - enterEv, exitEv Event -} +func eventLoop(bpfModule *bpf.Module, ch <-chan []byte) { + enterEvs := make(map[uint32]enterExitEvent) + evCh := make(chan enterExitEvent) -func (s Syscall) String() string { - return "" -} + enter := func(enterEv event) { + enterEvs[enterEv.GetTid()] = enterExitEvent{ + enterEv: enterEv, + } + } -func human(enterEv, exitEv Event) string { - return fmt.Sprintf("%08d µs %s %s", - exitEv.Timestamp()-enterEv.Timestamp(), enterEv, exitEv) -} + exit := func(exitEv event) { + ev, ok := enterEvs[exitEv.GetTid()] + if !ok { + exitEv.Recycle() + return + } + delete(enterEvs, exitEv.GetTid()) + ev.exitEv = exitEv + evCh <- ev + } -func eventLoop(bpfModule *bpf.Module, ch <-chan []byte) { - enterEvs := make(map[uint32]Event) + go func() { + for ev := range evCh { + fmt.Println(ev.dump()) + } + }() for raw := range ch { - var exitEv Event - switch EventType(raw[0]) { case ENTER_OPEN_EVENT: - ev := NewOpenEnterEvent(raw) - enterEvs[ev.Tid] = ev + enter(NewOpenEnterEvent(raw)) case EXIT_OPEN_EVENT: - ev := NewFdEvent(raw) - if enterEv, ok := enterEvs[ev.Tid]; ok { - fmt.Println(human(enterEv, ev)) - delete(enterEvs, ev.Tid) - enterEv.Recycle() - } - ev.Recycle() - + exit(NewFdEvent(raw)) case ENTER_FD_EVENT: - ev := NewFdEvent(raw) - enterEvs[ev.Tid] = ev + enter(NewFdEvent(raw)) case EXIT_FD_EVENT: - exitEv = NewFdEvent(raw) + exit(NewFdEvent(raw)) case EXIT_NULL_EVENT: - exitEv = NewNullEvent(raw) + exit(NewNullEvent(raw)) case EXIT_RET_EVENT: - exitEv = NewRetEvent(raw) + exit(NewRetEvent(raw)) default: panic(fmt.Sprintf("Unknown event type %s", EventType(raw[0]))) } - - if exitEv == nil { - continue - } - - if enterEv, ok := enterEvs[exitEv.TID()]; ok { - fmt.Println(human(enterEv, exitEv)) - delete(enterEvs, exitEv.TID()) - enterEv.Recycle() - } - - exitEv.Recycle() } fmt.Println("Good bye") diff --git a/internal/generated/nqc.raku b/internal/generated/nqc.raku index 835365f..f53f34e 100644 --- a/internal/generated/nqc.raku +++ b/internal/generated/nqc.raku @@ -64,6 +64,15 @@ class NQCToGoActions { default: panic(fmt.Sprintf("Unknown SyscallId: %d", s)) \} \} + + func (s SyscallId) Name() string \{ + switch (s) \{ + {@!const-names.grep(/^SYS_/).map({ + "case $_: return \"{$_.subst(/'SYS_ENTER_'|'SYS_EXIT_'/, '').lc}\"" + }).join('; ')} + default: panic(fmt.Sprintf("Unknown SyscallId: %d", s)) + \} + \} END } @@ -94,11 +103,23 @@ class NQCToGoActions { return fmt.Sprintf("{@format.join(' ')}", {@args.join(', ')}) \} - func ($self-ref *{$.made}) TID() uint32 \{ + func ($self-ref *{$.made}) GetEventType() EventType \{ + return $self-ref.EventType + \} + + func ($self-ref *{$.made}) GetSyscallId() SyscallId \{ + return $self-ref.SyscallId + \} + + func ($self-ref *{$.made}) GetPid() uint32 \{ + return $self-ref.Pid + \} + + func ($self-ref *{$.made}) GetTid() uint32 \{ return $self-ref.Tid \} - func ($self-ref *{$.made}) Timestamp() uint32 \{ + func ($self-ref *{$.made}) GetTime() uint32 \{ return $self-ref.Time \} END diff --git a/internal/generated/types/types.go b/internal/generated/types/types.go index 7f0bebe..6f520e5 100644 --- a/internal/generated/types/types.go +++ b/internal/generated/types/types.go @@ -130,6 +130,125 @@ func (s SyscallId) String() string { } } +func (s SyscallId) Name() string { + switch s { + case SYS_EXIT_CACHESTAT: + return "cachestat" + case SYS_ENTER_CACHESTAT: + return "cachestat" + case SYS_EXIT_CLOSE_RANGE: + return "close_range" + case SYS_ENTER_CLOSE_RANGE: + return "close_range" + case SYS_EXIT_CLOSE: + return "close" + case SYS_ENTER_CLOSE: + return "close" + case SYS_EXIT_FCHOWN: + return "fchown" + case SYS_ENTER_FCHOWN: + return "fchown" + case SYS_EXIT_FCHMOD: + return "fchmod" + case SYS_ENTER_FCHMOD: + return "fchmod" + case SYS_EXIT_FCHDIR: + return "fchdir" + case SYS_ENTER_FCHDIR: + return "fchdir" + case SYS_EXIT_FTRUNCATE: + return "ftruncate" + case SYS_ENTER_FTRUNCATE: + return "ftruncate" + case SYS_EXIT_COPY_FILE_RANGE: + return "copy_file_range" + case SYS_ENTER_COPY_FILE_RANGE: + return "copy_file_range" + case SYS_EXIT_PWRITE64: + return "pwrite64" + case SYS_ENTER_PWRITE64: + return "pwrite64" + case SYS_EXIT_PREAD64: + return "pread64" + case SYS_ENTER_PREAD64: + return "pread64" + case SYS_EXIT_WRITE: + return "write" + case SYS_ENTER_WRITE: + return "write" + case SYS_EXIT_READ: + return "read" + case SYS_ENTER_READ: + return "read" + case SYS_EXIT_LSEEK: + return "lseek" + case SYS_ENTER_LSEEK: + return "lseek" + case SYS_EXIT_NEWFSTAT: + return "newfstat" + case SYS_ENTER_NEWFSTAT: + return "newfstat" + case SYS_EXIT_FCNTL: + return "fcntl" + case SYS_ENTER_FCNTL: + return "fcntl" + case SYS_EXIT_IOCTL: + return "ioctl" + case SYS_ENTER_IOCTL: + return "ioctl" + case SYS_EXIT_GETDENTS64: + return "getdents64" + case SYS_ENTER_GETDENTS64: + return "getdents64" + case SYS_EXIT_GETDENTS: + return "getdents" + case SYS_ENTER_GETDENTS: + return "getdents" + case SYS_EXIT_SYNC_FILE_RANGE: + return "sync_file_range" + case SYS_ENTER_SYNC_FILE_RANGE: + return "sync_file_range" + case SYS_EXIT_FDATASYNC: + return "fdatasync" + case SYS_ENTER_FDATASYNC: + return "fdatasync" + case SYS_EXIT_FSYNC: + return "fsync" + case SYS_ENTER_FSYNC: + return "fsync" + case SYS_EXIT_FSTATFS: + return "fstatfs" + case SYS_ENTER_FSTATFS: + return "fstatfs" + case SYS_EXIT_FLOCK: + return "flock" + case SYS_ENTER_FLOCK: + return "flock" + case SYS_EXIT_QUOTACTL_FD: + return "quotactl_fd" + case SYS_ENTER_QUOTACTL_FD: + return "quotactl_fd" + case SYS_EXIT_IO_URING_REGISTER: + return "io_uring_register" + case SYS_ENTER_IO_URING_REGISTER: + return "io_uring_register" + case SYS_EXIT_IO_URING_ENTER: + return "io_uring_enter" + case SYS_ENTER_IO_URING_ENTER: + return "io_uring_enter" + case SYS_ENTER_OPEN: + return "open" + case SYS_EXIT_OPEN: + return "open" + case SYS_ENTER_OPENAT: + return "openat" + case SYS_EXIT_OPENAT: + return "openat" + default: + panic(fmt.Sprintf("Unknown SyscallId: %d", s)) + } +} + const MAX_FILENAME_LENGTH = 256 const MAX_PROGNAME_LENGTH = 16 const ENTER_OPEN_EVENT = 1 @@ -155,11 +274,23 @@ func (o OpenEnterEvent) String() string { return fmt.Sprintf("EventType:%v SyscallId:%v Pid:%v Tid:%v Time:%v Filename:%v Comm:%v", o.EventType, o.SyscallId, o.Pid, o.Tid, o.Time, string(o.Filename[:]), string(o.Comm[:])) } -func (o *OpenEnterEvent) TID() uint32 { +func (o *OpenEnterEvent) GetEventType() EventType { + return o.EventType +} + +func (o *OpenEnterEvent) GetSyscallId() SyscallId { + return o.SyscallId +} + +func (o *OpenEnterEvent) GetPid() uint32 { + return o.Pid +} + +func (o *OpenEnterEvent) GetTid() uint32 { return o.Tid } -func (o *OpenEnterEvent) Timestamp() uint32 { +func (o *OpenEnterEvent) GetTime() uint32 { return o.Time } @@ -192,11 +323,23 @@ func (n NullEvent) String() string { return fmt.Sprintf("EventType:%v SyscallId:%v Pid:%v Tid:%v Time:%v", n.EventType, n.SyscallId, n.Pid, n.Tid, n.Time) } -func (n *NullEvent) TID() uint32 { +func (n *NullEvent) GetEventType() EventType { + return n.EventType +} + +func (n *NullEvent) GetSyscallId() SyscallId { + return n.SyscallId +} + +func (n *NullEvent) GetPid() uint32 { + return n.Pid +} + +func (n *NullEvent) GetTid() uint32 { return n.Tid } -func (n *NullEvent) Timestamp() uint32 { +func (n *NullEvent) GetTime() uint32 { return n.Time } @@ -230,11 +373,23 @@ func (f FdEvent) String() string { return fmt.Sprintf("EventType:%v SyscallId:%v Pid:%v Tid:%v Time:%v Fd:%v", f.EventType, f.SyscallId, f.Pid, f.Tid, f.Time, f.Fd) } -func (f *FdEvent) TID() uint32 { +func (f *FdEvent) GetEventType() EventType { + return f.EventType +} + +func (f *FdEvent) GetSyscallId() SyscallId { + return f.SyscallId +} + +func (f *FdEvent) GetPid() uint32 { + return f.Pid +} + +func (f *FdEvent) GetTid() uint32 { return f.Tid } -func (f *FdEvent) Timestamp() uint32 { +func (f *FdEvent) GetTime() uint32 { return f.Time } @@ -268,11 +423,23 @@ func (r RetEvent) String() string { return fmt.Sprintf("EventType:%v SyscallId:%v Pid:%v Tid:%v Ret:%v Time:%v", r.EventType, r.SyscallId, r.Pid, r.Tid, r.Ret, r.Time) } -func (r *RetEvent) TID() uint32 { +func (r *RetEvent) GetEventType() EventType { + return r.EventType +} + +func (r *RetEvent) GetSyscallId() SyscallId { + return r.SyscallId +} + +func (r *RetEvent) GetPid() uint32 { + return r.Pid +} + +func (r *RetEvent) GetTid() uint32 { return r.Tid } -func (r *RetEvent) Timestamp() uint32 { +func (r *RetEvent) GetTime() uint32 { return r.Time } -- cgit v1.2.3