diff options
| author | Paul Buetow <paul@buetow.org> | 2026-05-13 20:04:48 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-05-13 20:04:48 +0300 |
| commit | 251894cf3375812564ecf28392179b395cdda9c7 (patch) | |
| tree | 83c3609ab591702e29a375923670e7622a33b5c7 /internal/generate | |
| parent | 78ea9e22e596255c5e23ce445d80641870674ca9 (diff) | |
refactor: break down functions exceeding 50 lines into smaller helpers
Split 22 production files across the codebase — event loop, TUI models,
probe manager, dashboard, export, flag parsing, code generation, and
ioworkload scenarios — so that no function body exceeds 50 lines. Each
extracted helper carries its own comment explaining its role.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'internal/generate')
| -rw-r--r-- | internal/generate/bpfhandler.go | 120 | ||||
| -rw-r--r-- | internal/generate/format.go | 84 |
2 files changed, 114 insertions, 90 deletions
diff --git a/internal/generate/bpfhandler.go b/internal/generate/bpfhandler.go index cf9a0c9..549e80b 100644 --- a/internal/generate/bpfhandler.go +++ b/internal/generate/bpfhandler.go @@ -62,77 +62,93 @@ func renderHandler(name, ctxStruct, eventStruct, comment, eventTypeConst, extra return b.String() } +// generateExtra returns the kind-specific C body lines for a tracepoint handler, +// dispatching to a per-kind helper so that each case stays concise. func generateExtra(tp GeneratedTracepoint, isEnter bool) string { f := tp.Format - switch tp.Classification.Kind { case KindFd: - if f.Name == "sys_enter_pidfd_getfd" { - return " ev->fd = (__s32)ctx->args[0];\n" - } - fdIdx := f.FieldNumber("fd") - if fdIdx >= 0 { - return fmt.Sprintf(" ev->fd = (__s32)ctx->args[%d];\n", fdIdx) - } - return " ev->fd = (__s32)ctx->args[0];\n" - + return generateExtraFd(f) case KindDup3: 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 KindOpen: - filenameIdx := f.FieldNumber("filename") - flagsIdx := f.FieldNumber("flags") - var b strings.Builder - b.WriteString(" __builtin_memset(&(ev->filename), 0, sizeof(ev->filename) + sizeof(ev->comm));\n") - fmt.Fprintf(&b, " bpf_probe_read_user_str(ev->filename, sizeof(ev->filename), (void *)ctx->args[%d]);\n", filenameIdx) - b.WriteString(" bpf_get_current_comm(&ev->comm, sizeof(ev->comm));\n") - if flagsIdx > -1 { - fmt.Fprintf(&b, " ev->flags = ctx->args[%d];\n", flagsIdx) - } else { - b.WriteString(" ev->flags = -1; // Probably OK\n") - } - return b.String() - + return generateExtraOpen(f) case KindPathname: - fieldName := tp.Classification.PathnameField - fieldIdx := f.FieldNumber(fieldName) - var b strings.Builder - b.WriteString(" __builtin_memset(&(ev->pathname), 0, sizeof(ev->pathname));\n") - fmt.Fprintf(&b, " bpf_probe_read_user_str(ev->pathname, sizeof(ev->pathname), (void*)ctx->args[%d]);\n", fieldIdx) - return b.String() - + return generateExtraPathname(tp, f) case KindName: - oldIdx := f.FieldNumber("oldname") - newIdx := f.FieldNumber("newname") - var b strings.Builder - b.WriteString(" __builtin_memset(&(ev->oldname), 0, sizeof(ev->oldname) + sizeof(ev->newname));\n") - fmt.Fprintf(&b, " bpf_probe_read_user_str(ev->oldname, sizeof(ev->oldname), (void*)ctx->args[%d]);\n", oldIdx) - fmt.Fprintf(&b, " bpf_probe_read_user_str(ev->newname, sizeof(ev->newname), (void*)ctx->args[%d]);\n", newIdx) - return b.String() - + return generateExtraName(f) case KindFcntl: - fdIdx := f.FieldNumber("fd") - cmdIdx := f.FieldNumber("cmd") - argIdx := f.FieldNumber("arg") - return fmt.Sprintf( - " ev->fd = ctx->args[%d];\n ev->cmd = ctx->args[%d];\n ev->arg = ctx->args[%d];\n", - fdIdx, cmdIdx, argIdx, - ) - + return generateExtraFcntl(f) case KindRet: - classification := ClassifyRet(f.Name) - return fmt.Sprintf(" ev->ret = ctx->ret;\n ev->ret_type = %s;\n", classification) - + return fmt.Sprintf(" ev->ret = ctx->ret;\n ev->ret_type = %s;\n", ClassifyRet(f.Name)) case KindNull: return "" } - return "" } +// generateExtraFd returns the fd-capture lines for fd-family events. +func generateExtraFd(f *Format) string { + if f.Name == "sys_enter_pidfd_getfd" { + return " ev->fd = (__s32)ctx->args[0];\n" + } + fdIdx := f.FieldNumber("fd") + if fdIdx >= 0 { + return fmt.Sprintf(" ev->fd = (__s32)ctx->args[%d];\n", fdIdx) + } + return " ev->fd = (__s32)ctx->args[0];\n" +} + +// generateExtraOpen returns the filename/comm/flags capture lines for open-family events. +func generateExtraOpen(f *Format) string { + filenameIdx := f.FieldNumber("filename") + flagsIdx := f.FieldNumber("flags") + var b strings.Builder + b.WriteString(" __builtin_memset(&(ev->filename), 0, sizeof(ev->filename) + sizeof(ev->comm));\n") + fmt.Fprintf(&b, " bpf_probe_read_user_str(ev->filename, sizeof(ev->filename), (void *)ctx->args[%d]);\n", filenameIdx) + b.WriteString(" bpf_get_current_comm(&ev->comm, sizeof(ev->comm));\n") + if flagsIdx > -1 { + fmt.Fprintf(&b, " ev->flags = ctx->args[%d];\n", flagsIdx) + } else { + b.WriteString(" ev->flags = -1; // Probably OK\n") + } + return b.String() +} + +// generateExtraPathname returns the pathname capture lines for path-family events. +func generateExtraPathname(tp GeneratedTracepoint, f *Format) string { + fieldName := tp.Classification.PathnameField + fieldIdx := f.FieldNumber(fieldName) + var b strings.Builder + b.WriteString(" __builtin_memset(&(ev->pathname), 0, sizeof(ev->pathname));\n") + fmt.Fprintf(&b, " bpf_probe_read_user_str(ev->pathname, sizeof(ev->pathname), (void*)ctx->args[%d]);\n", fieldIdx) + return b.String() +} + +// generateExtraName returns the oldname/newname capture lines for rename/link-family events. +func generateExtraName(f *Format) string { + oldIdx := f.FieldNumber("oldname") + newIdx := f.FieldNumber("newname") + var b strings.Builder + b.WriteString(" __builtin_memset(&(ev->oldname), 0, sizeof(ev->oldname) + sizeof(ev->newname));\n") + fmt.Fprintf(&b, " bpf_probe_read_user_str(ev->oldname, sizeof(ev->oldname), (void*)ctx->args[%d]);\n", oldIdx) + fmt.Fprintf(&b, " bpf_probe_read_user_str(ev->newname, sizeof(ev->newname), (void*)ctx->args[%d]);\n", newIdx) + return b.String() +} + +// generateExtraFcntl returns the fd/cmd/arg capture lines for fcntl events. +func generateExtraFcntl(f *Format) string { + fdIdx := f.FieldNumber("fd") + cmdIdx := f.FieldNumber("cmd") + argIdx := f.FieldNumber("arg") + return fmt.Sprintf( + " ev->fd = ctx->args[%d];\n ev->cmd = ctx->args[%d];\n ev->arg = ctx->args[%d];\n", + fdIdx, cmdIdx, argIdx, + ) +} + // 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/format.go b/internal/generate/format.go index ea579b6..ef51ba8 100644 --- a/internal/generate/format.go +++ b/internal/generate/format.go @@ -44,52 +44,60 @@ func ParseFormats(r io.Reader) ([]Format, error) { isExternal := false for scanner.Scan() { - line := scanner.Text() - trimmed := strings.TrimSpace(line) - - switch { - case strings.HasPrefix(trimmed, "name:"): - f := Format{} - f.Name = strings.TrimSpace(strings.TrimPrefix(trimmed, "name:")) - formats = append(formats, f) - current = &formats[len(formats)-1] - isExternal = false - - case strings.HasPrefix(trimmed, "ID:"): - if current == nil { - return nil, fmt.Errorf("ID without name") - } - id, err := strconv.Atoi(strings.TrimSpace(strings.TrimPrefix(trimmed, "ID:"))) - if err != nil { - return nil, fmt.Errorf("parsing ID: %w", err) - } - current.ID = id - - case strings.HasPrefix(trimmed, "field:"): - if current == nil { - return nil, fmt.Errorf("field without name") - } - field, err := parseField(trimmed) - if err != nil { - return nil, fmt.Errorf("parsing field in %s: %w", current.Name, err) - } - if field.Name == "__syscall_nr" { - isExternal = true - } - if isExternal { - current.ExternalFields = append(current.ExternalFields, field) - } else { - current.InternalFields = append(current.InternalFields, field) - } + var err error + current, isExternal, err = applyFormatLine(scanner.Text(), formats, current, isExternal, &formats) + if err != nil { + return nil, err } } - if err := scanner.Err(); err != nil { return nil, fmt.Errorf("scanning input: %w", err) } return formats, nil } +// applyFormatLine processes one line from the format file, updating the +// running parse state (current format, isExternal flag, and formats slice). +func applyFormatLine(line string, _ []Format, current *Format, isExternal bool, formats *[]Format) (*Format, bool, error) { + trimmed := strings.TrimSpace(line) + switch { + case strings.HasPrefix(trimmed, "name:"): + f := Format{} + f.Name = strings.TrimSpace(strings.TrimPrefix(trimmed, "name:")) + *formats = append(*formats, f) + current = &(*formats)[len(*formats)-1] + isExternal = false + + case strings.HasPrefix(trimmed, "ID:"): + if current == nil { + return nil, false, fmt.Errorf("ID without name") + } + id, err := strconv.Atoi(strings.TrimSpace(strings.TrimPrefix(trimmed, "ID:"))) + if err != nil { + return nil, false, fmt.Errorf("parsing ID: %w", err) + } + current.ID = id + + case strings.HasPrefix(trimmed, "field:"): + if current == nil { + return nil, false, fmt.Errorf("field without name") + } + field, err := parseField(trimmed) + if err != nil { + return nil, false, fmt.Errorf("parsing field in %s: %w", current.Name, err) + } + if field.Name == "__syscall_nr" { + isExternal = true + } + if isExternal { + current.ExternalFields = append(current.ExternalFields, field) + } else { + current.InternalFields = append(current.InternalFields, field) + } + } + return current, isExternal, nil +} + func parseField(line string) (Field, error) { // Format: "field:TYPE NAME; offset:N; size:N; signed:N;" line = strings.TrimPrefix(line, "field:") |
