summaryrefslogtreecommitdiff
path: root/internal/generate
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-05-19 10:12:32 +0300
committerPaul Buetow <paul@buetow.org>2026-05-19 10:12:32 +0300
commit127516b4bf63dc922df222825a9a6a1d7eacc214 (patch)
tree3839a2f6a7f4f1bc713690678fc003d4e2be8a8c /internal/generate
parent32a19cf9fb1344c9b1a61054d7cf2c90edc3708a (diff)
u6: add socket/socketpair kind scaffolding and wiring
Diffstat (limited to 'internal/generate')
-rw-r--r--internal/generate/bpfhandler.go12
-rw-r--r--internal/generate/classify.go6
-rw-r--r--internal/generate/classify_test.go17
-rw-r--r--internal/generate/codegen_test.go28
-rw-r--r--internal/generate/kindregistry.go2
-rw-r--r--internal/generate/testdata.go31
6 files changed, 91 insertions, 5 deletions
diff --git a/internal/generate/bpfhandler.go b/internal/generate/bpfhandler.go
index 549e80b..6c9c314 100644
--- a/internal/generate/bpfhandler.go
+++ b/internal/generate/bpfhandler.go
@@ -73,6 +73,10 @@ func generateExtra(tp GeneratedTracepoint, isEnter bool) string {
return " ev->fd = (__s32)ctx->args[0];\n ev->flags = (__s32)ctx->args[2];\n"
case KindOpenByHandleAt:
return " ev->flags = (__s32)ctx->args[2];\n"
+ case KindSocket:
+ return generateExtraSocket()
+ case KindSocketpair:
+ return generateExtraSocketpair()
case KindOpen:
return generateExtraOpen(f)
case KindPathname:
@@ -149,6 +153,14 @@ func generateExtraFcntl(f *Format) string {
)
}
+func generateExtraSocket() string {
+ return " ev->family = (__s32)ctx->args[0];\n ev->type = (__s32)ctx->args[1];\n ev->protocol = (__s32)ctx->args[2];\n"
+}
+
+func generateExtraSocketpair() string {
+ return " int sv[2];\n __builtin_memset(&sv, 0xff, sizeof(sv));\n if (ctx->args[3] != 0) {\n bpf_probe_read_user(&sv, sizeof(sv), (void *)ctx->args[3]);\n }\n ev->family = (__s32)ctx->args[0];\n ev->type = (__s32)ctx->args[1];\n ev->protocol = (__s32)ctx->args[2];\n ev->sv0 = (__s32)sv[0];\n ev->sv1 = (__s32)sv[1];\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 7768ea7..68cd722 100644
--- a/internal/generate/classify.go
+++ b/internal/generate/classify.go
@@ -15,6 +15,8 @@ const (
KindNull
KindDup3
KindOpenByHandleAt
+ KindSocket
+ KindSocketpair
)
type RetClassification string
@@ -79,6 +81,10 @@ func classifyNameOnly(name string) (ClassificationResult, bool) {
return ClassificationResult{Kind: KindNull}, true
case "sys_enter_getcwd":
return ClassificationResult{Kind: KindNull}, true
+ case "sys_enter_socket":
+ return ClassificationResult{Kind: KindSocket}, true
+ case "sys_enter_socketpair":
+ return ClassificationResult{Kind: KindSocketpair}, true
}
if strings.HasPrefix(name, "sys_enter_io_") {
return ClassificationResult{Kind: KindNull}, true
diff --git a/internal/generate/classify_test.go b/internal/generate/classify_test.go
index ea7d662..ce6eff1 100644
--- a/internal/generate/classify_test.go
+++ b/internal/generate/classify_test.go
@@ -244,10 +244,17 @@ func TestClassifyFdAccept(t *testing.T) {
}
}
-func TestClassifySocketRequiresGenerationFallback(t *testing.T) {
+func TestClassifySocket(t *testing.T) {
r := classifyFromData(t, FormatSocket)
- if r.Kind != KindNone {
- t.Errorf("socket: got kind %d, want KindNone before generation fallback", r.Kind)
+ if r.Kind != KindSocket {
+ t.Errorf("socket: got kind %d, want KindSocket", r.Kind)
+ }
+}
+
+func TestClassifySocketpair(t *testing.T) {
+ r := classifyFromData(t, FormatSocketpair)
+ if r.Kind != KindSocketpair {
+ t.Errorf("socketpair: got kind %d, want KindSocketpair", r.Kind)
}
}
@@ -288,7 +295,8 @@ func TestClassifySyscallPairAccepted(t *testing.T) {
{"mknod", FormatMknod, FormatExitMknod, KindPathname},
{"execve", FormatExecve, FormatExitExecve, KindPathname},
{"accept", FormatAccept, FormatExitAccept, KindFd},
- {"socket", FormatSocket, FormatExitSocket, KindNull},
+ {"socket", FormatSocket, FormatExitSocket, KindSocket},
+ {"socketpair", FormatSocketpair, FormatExitSocketpair, KindSocketpair},
{"kill", FormatKill, FormatExitKill, KindNull},
}
@@ -314,6 +322,7 @@ func TestClassifySyscallPairEmitsAllFamilies(t *testing.T) {
{"execve", FormatExecve, FormatExitExecve, FamilyProcess},
{"accept", FormatAccept, FormatExitAccept, FamilyNetwork},
{"socket", FormatSocket, FormatExitSocket, FamilyNetwork},
+ {"socketpair", FormatSocketpair, FormatExitSocketpair, FamilyNetwork},
{"kill", FormatKill, FormatExitKill, FamilySignals},
}
diff --git a/internal/generate/codegen_test.go b/internal/generate/codegen_test.go
index a448162..f87a6dc 100644
--- a/internal/generate/codegen_test.go
+++ b/internal/generate/codegen_test.go
@@ -185,6 +185,28 @@ func TestGenerateOpenByHandleAtHandler(t *testing.T) {
requireContains(t, output, "ev->flags = (__s32)ctx->args[2];")
}
+func TestGenerateSocketHandler(t *testing.T) {
+ output := generateFromPair(t, FormatSocket, FormatExitSocket)
+
+ requireContains(t, output, "struct socket_event *ev")
+ requireContains(t, output, "ev->event_type = ENTER_SOCKET_EVENT;")
+ requireContains(t, output, "ev->family = (__s32)ctx->args[0];")
+ requireContains(t, output, "ev->type = (__s32)ctx->args[1];")
+ requireContains(t, output, "ev->protocol = (__s32)ctx->args[2];")
+}
+
+func TestGenerateSocketpairHandler(t *testing.T) {
+ output := generateFromPair(t, FormatSocketpair, FormatExitSocketpair)
+
+ requireContains(t, output, "struct socketpair_event *ev")
+ requireContains(t, output, "ev->event_type = ENTER_SOCKETPAIR_EVENT;")
+ requireContains(t, output, "int sv[2];")
+ requireContains(t, output, "bpf_probe_read_user(&sv, sizeof(sv), (void *)ctx->args[3]);")
+ requireContains(t, output, "ev->family = (__s32)ctx->args[0];")
+ requireContains(t, output, "ev->sv0 = (__s32)sv[0];")
+ requireContains(t, output, "ev->sv1 = (__s32)sv[1];")
+}
+
func TestGenerateNameToHandleAtHandler(t *testing.T) {
output := generateFromPair(t, FormatNameToHandleAt, FormatExitNameToHandleAt)
@@ -292,6 +314,8 @@ func TestGenerateAllEventTypes(t *testing.T) {
{KindNull, "ENTER_NULL_EVENT", "EXIT_NULL_EVENT"},
{KindDup3, "ENTER_DUP3_EVENT", "EXIT_DUP3_EVENT"},
{KindOpenByHandleAt, "ENTER_OPEN_BY_HANDLE_AT_EVENT", "EXIT_OPEN_BY_HANDLE_AT_EVENT"},
+ {KindSocket, "ENTER_SOCKET_EVENT", "EXIT_SOCKET_EVENT"},
+ {KindSocketpair, "ENTER_SOCKETPAIR_EVENT", "EXIT_SOCKETPAIR_EVENT"},
}
for _, tt := range tests {
@@ -318,6 +342,8 @@ func TestEventStructNames(t *testing.T) {
{KindNull, "null_event"},
{KindDup3, "dup3_event"},
{KindOpenByHandleAt, "open_by_handle_at_event"},
+ {KindSocket, "socket_event"},
+ {KindSocketpair, "socketpair_event"},
}
for _, tt := range tests {
@@ -336,7 +362,7 @@ func TestEnterReject(t *testing.T) {
t.Error("KindNone should be enter-rejected")
}
- accepted := []TracepointKind{KindFd, KindOpen, KindPathname, KindName, KindFcntl, KindNull, KindDup3, KindOpenByHandleAt}
+ accepted := []TracepointKind{KindFd, KindOpen, KindPathname, KindName, KindFcntl, KindNull, KindDup3, KindOpenByHandleAt, KindSocket, KindSocketpair}
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 86b77aa..f716489 100644
--- a/internal/generate/kindregistry.go
+++ b/internal/generate/kindregistry.go
@@ -25,6 +25,8 @@ var kindRegistry = map[TracepointKind]kindMeta{
KindNull: {structName: "null_event", enterAccepted: true},
KindDup3: {structName: "dup3_event", enterAccepted: true},
KindOpenByHandleAt: {structName: "open_by_handle_at_event", enterAccepted: true},
+ KindSocket: {structName: "socket_event", enterAccepted: true},
+ KindSocketpair: {structName: "socketpair_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 a9bedc6..e363a68 100644
--- a/internal/generate/testdata.go
+++ b/internal/generate/testdata.go
@@ -823,6 +823,37 @@ format:
print fmt: "0x%lx", REC->ret
`
+const FormatSocketpair = `name: sys_enter_socketpair
+ID: 1816
+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 family; offset:16; size:8; signed:0;
+ field:int type; offset:24; size:8; signed:0;
+ field:int protocol; offset:32; size:8; signed:0;
+ field:int * usockvec; offset:40; size:8; signed:0;
+
+print fmt: "family: 0x%08lx, type: 0x%08lx, protocol: 0x%08lx, usockvec: 0x%08lx", ((unsigned long)(REC->family)), ((unsigned long)(REC->type)), ((unsigned long)(REC->protocol)), ((unsigned long)(REC->usockvec))
+`
+
+const FormatExitSocketpair = `name: sys_exit_socketpair
+ID: 1815
+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: