summaryrefslogtreecommitdiff
path: root/internal/generate
diff options
context:
space:
mode:
Diffstat (limited to 'internal/generate')
-rw-r--r--internal/generate/bpfhandler.go26
-rw-r--r--internal/generate/classify.go18
-rw-r--r--internal/generate/classify_test.go64
-rw-r--r--internal/generate/codegen_test.go36
-rw-r--r--internal/generate/kindregistry.go2
-rw-r--r--internal/generate/testdata.go114
6 files changed, 259 insertions, 1 deletions
diff --git a/internal/generate/bpfhandler.go b/internal/generate/bpfhandler.go
index bada317..1a6b210 100644
--- a/internal/generate/bpfhandler.go
+++ b/internal/generate/bpfhandler.go
@@ -79,6 +79,10 @@ func generateExtra(tp GeneratedTracepoint, isEnter bool) string {
return generateExtraSocketpair(isEnter)
case KindAccept:
return generateExtraAccept(isEnter)
+ case KindPipe:
+ return generateExtraPipe(f, isEnter)
+ case KindEventfd:
+ return generateExtraEventfd(f, isEnter)
case KindOpen:
return generateExtraOpen(f)
case KindPathname:
@@ -173,6 +177,28 @@ func generateExtraAccept(isEnter bool) string {
return " ev->fd = -1;\n ev->ret = ctx->ret;\n"
}
+func generateExtraPipe(f *Format, isEnter bool) string {
+ if isEnter {
+ flagsExpr := "0"
+ if f.Name == "sys_enter_pipe2" {
+ flagsExpr = "(__s32)ctx->args[1]"
+ }
+ return " struct pipe_ctx pending;\n pending.upipefd = ctx->args[0];\n pending.flags = " + flagsExpr + ";\n bpf_map_update_elem(&pipe_ctx_map, &tid, &pending, BPF_ANY);\n ev->flags = pending.flags;\n ev->fd0 = -1;\n ev->fd1 = -1;\n ev->ret = 0;\n"
+ }
+ return " __s32 flags = 0;\n __s32 fd0 = -1;\n __s32 fd1 = -1;\n struct pipe_ctx *pending = bpf_map_lookup_elem(&pipe_ctx_map, &tid);\n if (pending) {\n flags = pending->flags;\n if (ctx->ret == 0 && pending->upipefd != 0) {\n int pipefd[2];\n if (bpf_probe_read_user(&pipefd, sizeof(pipefd), (void *)pending->upipefd) == 0) {\n fd0 = (__s32)pipefd[0];\n fd1 = (__s32)pipefd[1];\n }\n }\n bpf_map_delete_elem(&pipe_ctx_map, &tid);\n }\n ev->flags = flags;\n ev->fd0 = fd0;\n ev->fd1 = fd1;\n ev->ret = ctx->ret;\n"
+}
+
+func generateExtraEventfd(f *Format, isEnter bool) string {
+ if isEnter {
+ flagsExpr := "0"
+ if f.Name == "sys_enter_eventfd2" {
+ flagsExpr = "(__s32)ctx->args[1]"
+ }
+ return " __s32 flags = " + flagsExpr + ";\n bpf_map_update_elem(&eventfd_flags_map, &tid, &flags, BPF_ANY);\n ev->flags = flags;\n ev->ret = -1;\n"
+ }
+ return " __s32 flags = 0;\n __s32 *pending = bpf_map_lookup_elem(&eventfd_flags_map, &tid);\n if (pending) {\n flags = *pending;\n bpf_map_delete_elem(&eventfd_flags_map, &tid);\n }\n ev->flags = flags;\n ev->ret = ctx->ret;\n"
+}
+
// eventStructName returns the C struct name for a TracepointKind. The mapping
// is driven by kindRegistry so adding a new kind only requires a registry entry.
func eventStructName(kind TracepointKind) string {
diff --git a/internal/generate/classify.go b/internal/generate/classify.go
index 4f6d14c..0bc00b3 100644
--- a/internal/generate/classify.go
+++ b/internal/generate/classify.go
@@ -18,6 +18,8 @@ const (
KindSocket
KindSocketpair
KindAccept
+ KindPipe
+ KindEventfd
)
type RetClassification string
@@ -96,6 +98,22 @@ func classifyNameOnly(name string) (ClassificationResult, bool) {
return ClassificationResult{Kind: KindAccept}, true
case "sys_exit_accept4":
return ClassificationResult{Kind: KindAccept}, true
+ case "sys_enter_pipe":
+ return ClassificationResult{Kind: KindPipe}, true
+ case "sys_exit_pipe":
+ return ClassificationResult{Kind: KindPipe}, true
+ case "sys_enter_pipe2":
+ return ClassificationResult{Kind: KindPipe}, true
+ case "sys_exit_pipe2":
+ return ClassificationResult{Kind: KindPipe}, true
+ case "sys_enter_eventfd":
+ return ClassificationResult{Kind: KindEventfd}, true
+ case "sys_exit_eventfd":
+ return ClassificationResult{Kind: KindEventfd}, true
+ case "sys_enter_eventfd2":
+ return ClassificationResult{Kind: KindEventfd}, true
+ case "sys_exit_eventfd2":
+ return ClassificationResult{Kind: KindEventfd}, true
case "sys_enter_bind":
return ClassificationResult{Kind: KindFd}, true
case "sys_enter_connect":
diff --git a/internal/generate/classify_test.go b/internal/generate/classify_test.go
index 5c7111f..09989b8 100644
--- a/internal/generate/classify_test.go
+++ b/internal/generate/classify_test.go
@@ -313,6 +313,62 @@ func TestClassifyExitSocketpair(t *testing.T) {
}
}
+func TestClassifyPipe(t *testing.T) {
+ r := classifyFromData(t, FormatPipe)
+ if r.Kind != KindPipe {
+ t.Errorf("pipe: got kind %d, want KindPipe", r.Kind)
+ }
+}
+
+func TestClassifyPipe2(t *testing.T) {
+ r := classifyFromData(t, FormatPipe2)
+ if r.Kind != KindPipe {
+ t.Errorf("pipe2: got kind %d, want KindPipe", r.Kind)
+ }
+}
+
+func TestClassifyExitPipe(t *testing.T) {
+ r := classifyFromData(t, FormatExitPipe)
+ if r.Kind != KindPipe {
+ t.Errorf("exit_pipe: got kind %d, want KindPipe", r.Kind)
+ }
+}
+
+func TestClassifyExitPipe2(t *testing.T) {
+ r := classifyFromData(t, FormatExitPipe2)
+ if r.Kind != KindPipe {
+ t.Errorf("exit_pipe2: got kind %d, want KindPipe", r.Kind)
+ }
+}
+
+func TestClassifyEventfd(t *testing.T) {
+ r := classifyFromData(t, FormatEventfd)
+ if r.Kind != KindEventfd {
+ t.Errorf("eventfd: got kind %d, want KindEventfd", r.Kind)
+ }
+}
+
+func TestClassifyEventfd2(t *testing.T) {
+ r := classifyFromData(t, FormatEventfd2)
+ if r.Kind != KindEventfd {
+ t.Errorf("eventfd2: got kind %d, want KindEventfd", r.Kind)
+ }
+}
+
+func TestClassifyExitEventfd(t *testing.T) {
+ r := classifyFromData(t, FormatExitEventfd)
+ if r.Kind != KindEventfd {
+ t.Errorf("exit_eventfd: got kind %d, want KindEventfd", r.Kind)
+ }
+}
+
+func TestClassifyExitEventfd2(t *testing.T) {
+ r := classifyFromData(t, FormatExitEventfd2)
+ if r.Kind != KindEventfd {
+ t.Errorf("exit_eventfd2: got kind %d, want KindEventfd", r.Kind)
+ }
+}
+
func TestClassifyKillRequiresGenerationFallback(t *testing.T) {
r := classifyFromData(t, FormatKill)
if r.Kind != KindNone {
@@ -353,6 +409,10 @@ func TestClassifySyscallPairAccepted(t *testing.T) {
{"accept4", FormatAccept4, FormatExitAccept4, KindAccept},
{"socket", FormatSocket, FormatExitSocket, KindSocket},
{"socketpair", FormatSocketpair, FormatExitSocketpair, KindSocketpair},
+ {"pipe", FormatPipe, FormatExitPipe, KindPipe},
+ {"pipe2", FormatPipe2, FormatExitPipe2, KindPipe},
+ {"eventfd", FormatEventfd, FormatExitEventfd, KindEventfd},
+ {"eventfd2", FormatEventfd2, FormatExitEventfd2, KindEventfd},
{"kill", FormatKill, FormatExitKill, KindNull},
}
@@ -380,6 +440,10 @@ func TestClassifySyscallPairEmitsAllFamilies(t *testing.T) {
{"accept4", FormatAccept4, FormatExitAccept4, FamilyNetwork},
{"socket", FormatSocket, FormatExitSocket, FamilyNetwork},
{"socketpair", FormatSocketpair, FormatExitSocketpair, FamilyNetwork},
+ {"pipe", FormatPipe, FormatExitPipe, FamilyIPC},
+ {"pipe2", FormatPipe2, FormatExitPipe2, FamilyIPC},
+ {"eventfd", FormatEventfd, FormatExitEventfd, FamilyIPC},
+ {"eventfd2", FormatEventfd2, FormatExitEventfd2, FamilyIPC},
{"kill", FormatKill, FormatExitKill, FamilySignals},
}
diff --git a/internal/generate/codegen_test.go b/internal/generate/codegen_test.go
index d8130c8..1c99314 100644
--- a/internal/generate/codegen_test.go
+++ b/internal/generate/codegen_test.go
@@ -225,6 +225,36 @@ func TestGenerateAcceptHandler(t *testing.T) {
requireContains(t, output, "ev->ret = ctx->ret;")
}
+func TestGeneratePipeHandler(t *testing.T) {
+ output := generateFromPair(t, FormatPipe2, FormatExitPipe2)
+
+ requireContains(t, output, "struct pipe_event *ev")
+ requireContains(t, output, "ev->event_type = ENTER_PIPE_EVENT;")
+ requireContains(t, output, "struct pipe_ctx pending;")
+ requireContains(t, output, "pending.upipefd = ctx->args[0];")
+ requireContains(t, output, "pending.flags = (__s32)ctx->args[1];")
+ requireContains(t, output, "bpf_map_update_elem(&pipe_ctx_map, &tid, &pending, BPF_ANY);")
+ requireContains(t, output, "ev->fd0 = -1;")
+ requireContains(t, output, "ev->fd1 = -1;")
+ requireContains(t, output, "SEC(\"tracepoint/syscalls/sys_exit_pipe2\")")
+ requireContains(t, output, "ev->event_type = EXIT_PIPE_EVENT;")
+ requireContains(t, output, "struct pipe_ctx *pending = bpf_map_lookup_elem(&pipe_ctx_map, &tid);")
+ requireContains(t, output, "ev->ret = ctx->ret;")
+}
+
+func TestGenerateEventfdHandler(t *testing.T) {
+ output := generateFromPair(t, FormatEventfd2, FormatExitEventfd2)
+
+ requireContains(t, output, "struct eventfd_event *ev")
+ requireContains(t, output, "ev->event_type = ENTER_EVENTFD_EVENT;")
+ requireContains(t, output, "bpf_map_update_elem(&eventfd_flags_map, &tid, &flags, BPF_ANY);")
+ requireContains(t, output, "ev->flags = flags;")
+ requireContains(t, output, "ev->ret = -1;")
+ requireContains(t, output, "SEC(\"tracepoint/syscalls/sys_exit_eventfd2\")")
+ requireContains(t, output, "ev->event_type = EXIT_EVENTFD_EVENT;")
+ requireContains(t, output, "ev->ret = ctx->ret;")
+}
+
func TestGenerateNameToHandleAtHandler(t *testing.T) {
output := generateFromPair(t, FormatNameToHandleAt, FormatExitNameToHandleAt)
@@ -335,6 +365,8 @@ func TestGenerateAllEventTypes(t *testing.T) {
{KindSocket, "ENTER_SOCKET_EVENT", "EXIT_SOCKET_EVENT"},
{KindSocketpair, "ENTER_SOCKETPAIR_EVENT", "EXIT_SOCKETPAIR_EVENT"},
{KindAccept, "ENTER_ACCEPT_EVENT", "EXIT_ACCEPT_EVENT"},
+ {KindPipe, "ENTER_PIPE_EVENT", "EXIT_PIPE_EVENT"},
+ {KindEventfd, "ENTER_EVENTFD_EVENT", "EXIT_EVENTFD_EVENT"},
}
for _, tt := range tests {
@@ -364,6 +396,8 @@ func TestEventStructNames(t *testing.T) {
{KindSocket, "socket_event"},
{KindSocketpair, "socketpair_event"},
{KindAccept, "accept_event"},
+ {KindPipe, "pipe_event"},
+ {KindEventfd, "eventfd_event"},
}
for _, tt := range tests {
@@ -382,7 +416,7 @@ func TestEnterReject(t *testing.T) {
t.Error("KindNone should be enter-rejected")
}
- accepted := []TracepointKind{KindFd, KindOpen, KindPathname, KindName, KindFcntl, KindNull, KindDup3, KindOpenByHandleAt, KindSocket, KindSocketpair, KindAccept}
+ accepted := []TracepointKind{KindFd, KindOpen, KindPathname, KindName, KindFcntl, KindNull, KindDup3, KindOpenByHandleAt, KindSocket, KindSocketpair, KindAccept, KindPipe, KindEventfd}
for _, k := range accepted {
if isEnterRejected(k) {
t.Errorf("kind %d should NOT be enter-rejected", k)
diff --git a/internal/generate/kindregistry.go b/internal/generate/kindregistry.go
index 186dbbc..17f7542 100644
--- a/internal/generate/kindregistry.go
+++ b/internal/generate/kindregistry.go
@@ -28,6 +28,8 @@ var kindRegistry = map[TracepointKind]kindMeta{
KindSocket: {structName: "socket_event", enterAccepted: true},
KindSocketpair: {structName: "socketpair_event", enterAccepted: true},
KindAccept: {structName: "accept_event", enterAccepted: true},
+ KindPipe: {structName: "pipe_event", enterAccepted: true},
+ KindEventfd: {structName: "eventfd_event", enterAccepted: true},
// KindNone is intentionally absent: it represents "unclassified" and is
// never enter-accepted. lookupKind returns the zero kindMeta (enterAccepted=false)
// for any unregistered kind, so KindNone is implicitly rejected.
diff --git a/internal/generate/testdata.go b/internal/generate/testdata.go
index 090619b..b34f98d 100644
--- a/internal/generate/testdata.go
+++ b/internal/generate/testdata.go
@@ -885,6 +885,120 @@ format:
print fmt: "0x%lx", REC->ret
`
+const FormatPipe = `name: sys_enter_pipe
+ID: 873
+format:
+ field:unsigned short common_type; offset:0; size:2; signed:0;
+ field:unsigned char common_flags; offset:2; size:1; signed:0;
+ field:unsigned char common_preempt_count; offset:3; size:1; signed:0;
+ field:int common_pid; offset:4; size:4; signed:1;
+
+ field:int __syscall_nr; offset:8; size:4; signed:1;
+ field:int * fildes; offset:16; size:8; signed:0;
+
+print fmt: "fildes: 0x%08lx", ((unsigned long)(REC->fildes))
+`
+
+const FormatExitPipe = `name: sys_exit_pipe
+ID: 872
+format:
+ field:unsigned short common_type; offset:0; size:2; signed:0;
+ field:unsigned char common_flags; offset:2; size:1; signed:0;
+ field:unsigned char common_preempt_count; offset:3; size:1; signed:0;
+ field:int common_pid; offset:4; size:4; signed:1;
+
+ field:int __syscall_nr; offset:8; size:4; signed:1;
+ field:long ret; offset:16; size:8; signed:1;
+
+print fmt: "0x%lx", REC->ret
+`
+
+const FormatPipe2 = `name: sys_enter_pipe2
+ID: 875
+format:
+ field:unsigned short common_type; offset:0; size:2; signed:0;
+ field:unsigned char common_flags; offset:2; size:1; signed:0;
+ field:unsigned char common_preempt_count; offset:3; size:1; signed:0;
+ field:int common_pid; offset:4; size:4; signed:1;
+
+ field:int __syscall_nr; offset:8; size:4; signed:1;
+ field:int * fildes; offset:16; size:8; signed:0;
+ field:int flags; offset:24; size:8; signed:0;
+
+print fmt: "fildes: 0x%08lx, flags: 0x%08lx", ((unsigned long)(REC->fildes)), ((unsigned long)(REC->flags))
+`
+
+const FormatExitPipe2 = `name: sys_exit_pipe2
+ID: 874
+format:
+ field:unsigned short common_type; offset:0; size:2; signed:0;
+ field:unsigned char common_flags; offset:2; size:1; signed:0;
+ field:unsigned char common_preempt_count; offset:3; size:1; signed:0;
+ field:int common_pid; offset:4; size:4; signed:1;
+
+ field:int __syscall_nr; offset:8; size:4; signed:1;
+ field:long ret; offset:16; size:8; signed:1;
+
+print fmt: "0x%lx", REC->ret
+`
+
+const FormatEventfd = `name: sys_enter_eventfd
+ID: 1095
+format:
+ field:unsigned short common_type; offset:0; size:2; signed:0;
+ field:unsigned char common_flags; offset:2; size:1; signed:0;
+ field:unsigned char common_preempt_count; offset:3; size:1; signed:0;
+ field:int common_pid; offset:4; size:4; signed:1;
+
+ field:int __syscall_nr; offset:8; size:4; signed:1;
+ field:unsigned int count; offset:16; size:8; signed:0;
+
+print fmt: "count: 0x%08lx", ((unsigned long)(REC->count))
+`
+
+const FormatExitEventfd = `name: sys_exit_eventfd
+ID: 1094
+format:
+ field:unsigned short common_type; offset:0; size:2; signed:0;
+ field:unsigned char common_flags; offset:2; size:1; signed:0;
+ field:unsigned char common_preempt_count; offset:3; size:1; signed:0;
+ field:int common_pid; offset:4; size:4; signed:1;
+
+ field:int __syscall_nr; offset:8; size:4; signed:1;
+ field:long ret; offset:16; size:8; signed:1;
+
+print fmt: "0x%lx", REC->ret
+`
+
+const FormatEventfd2 = `name: sys_enter_eventfd2
+ID: 1097
+format:
+ field:unsigned short common_type; offset:0; size:2; signed:0;
+ field:unsigned char common_flags; offset:2; size:1; signed:0;
+ field:unsigned char common_preempt_count; offset:3; size:1; signed:0;
+ field:int common_pid; offset:4; size:4; signed:1;
+
+ field:int __syscall_nr; offset:8; size:4; signed:1;
+ field:unsigned int count; offset:16; size:8; signed:0;
+ field:int flags; offset:24; size:8; signed:0;
+
+print fmt: "count: 0x%08lx, flags: 0x%08lx", ((unsigned long)(REC->count)), ((unsigned long)(REC->flags))
+`
+
+const FormatExitEventfd2 = `name: sys_exit_eventfd2
+ID: 1096
+format:
+ field:unsigned short common_type; offset:0; size:2; signed:0;
+ field:unsigned char common_flags; offset:2; size:1; signed:0;
+ field:unsigned char common_preempt_count; offset:3; size:1; signed:0;
+ field:int common_pid; offset:4; size:4; signed:1;
+
+ field:int __syscall_nr; offset:8; size:4; signed:1;
+ field:long ret; offset:16; size:8; signed:1;
+
+print fmt: "0x%lx", REC->ret
+`
+
const FormatPread64 = `name: sys_enter_pread64
ID: 840
format: