diff --git a/bpf/lbr.c b/bpf/lbr.c index 3862c31..ea115db 100644 --- a/bpf/lbr.c +++ b/bpf/lbr.c @@ -20,8 +20,8 @@ struct event { struct event lbr_events[1] SEC(".data.lbrs"); -SEC("fexit") -int BPF_PROG(fexit_fn) +static __always_inline int +emit_lbr_event(void *ctx) { struct event *event; __u64 retval; @@ -40,4 +40,16 @@ int BPF_PROG(fexit_fn) return BPF_OK; } +SEC("fexit") +int BPF_PROG(fexit_fn) +{ + return emit_lbr_event(ctx); +} + +SEC("fentry") +int BPF_PROG(fentry_fn) +{ + return emit_lbr_event(ctx); +} + char __license[] SEC("license") = "GPL"; diff --git a/internal/bpflbr/bpf_tracing.go b/internal/bpflbr/bpf_tracing.go index 56e786a..d5db824 100644 --- a/internal/bpflbr/bpf_tracing.go +++ b/internal/bpflbr/bpf_tracing.go @@ -13,12 +13,6 @@ import ( "golang.org/x/sync/errgroup" ) -const ( - // tracingFuncName is the name of the BPF function that is used for - // tracing. - tracingFuncName = "fexit_fn" -) - type bpfTracing struct { llock sync.Mutex progs []*ebpf.Program @@ -81,9 +75,14 @@ func (t *bpfTracing) Close() { _ = errg.Wait() } +func TracingProgName(mode string) string { + return fmt.Sprintf("f%s_fn", mode) +} + func (t *bpfTracing) traceProg(spec *ebpf.CollectionSpec, reusedMaps map[string]*ebpf.Map, info bpfTracingInfo) error { spec = spec.Copy() + tracingFuncName := TracingProgName(mode) progSpec := spec.Programs[tracingFuncName] progSpec.AttachTarget = info.prog progSpec.AttachTo = info.funcName @@ -124,6 +123,7 @@ func (t *bpfTracing) traceProg(spec *ebpf.CollectionSpec, reusedMaps map[string] func (t *bpfTracing) traceFunc(spec *ebpf.CollectionSpec, reusedMaps map[string]*ebpf.Map, fn string) error { spec = spec.Copy() + tracingFuncName := TracingProgName(mode) progSpec := spec.Programs[tracingFuncName] progSpec.AttachTo = fn progSpec.AttachType = ebpf.AttachTraceFExit diff --git a/internal/bpflbr/flags.go b/internal/bpflbr/flags.go index 576de9e..f64ee0c 100644 --- a/internal/bpflbr/flags.go +++ b/internal/bpflbr/flags.go @@ -20,9 +20,15 @@ const ( progFlagDescriptorName = "name" ) +const ( + TracingModeEntry = "entry" + TracingModeExit = "exit" +) + var ( verbose bool disasmIntelSyntax bool + mode string ) type ProgFlag struct { @@ -121,6 +127,7 @@ func ParseFlags() (*Flags, error) { f.UintVarP(&flags.disasmBytes, "disasm-bytes", "B", 0, "disasm bytes of kernel function, must not 0") f.BoolVar(&disasmIntelSyntax, "disasm-intel-syntax", false, "use Intel asm syntax for disasm, ATT asm syntax by default") f.BoolVarP(&verbose, "verbose", "v", false, "output verbose log") + f.StringVarP(&mode, "mode", "m", TracingModeExit, "mode of lbr tracing, exit or entry") return &flags, f.Parse(os.Args) } @@ -144,3 +151,15 @@ func (f *Flags) DumpProg() bool { func (f *Flags) Disasm() bool { return f.disasm } + +func (f *Flags) Mode() string { + return mode +} + +func (f *Flags) OtherMode() string { + if mode == TracingModeExit { + return TracingModeEntry + } + + return TracingModeExit +} diff --git a/main.go b/main.go index 786685c..f0ce06e 100644 --- a/main.go +++ b/main.go @@ -9,6 +9,7 @@ import ( "log" "os" "os/signal" + "slices" "syscall" "unsafe" @@ -34,6 +35,9 @@ func main() { return } + mode := flags.Mode() + assert.True(slices.Contains([]string{bpflbr.TracingModeEntry, bpflbr.TracingModeExit}, mode), "Mode must be exit or entry") + progs, err := flags.ParseProgs() assert.NoErr(err, "Failed to parse bpf prog infos: %v") @@ -76,6 +80,7 @@ func main() { bpfSpec, err := loadLbr() assert.NoErr(err, "Failed to load bpf spec: %v") + delete(bpfSpec.Programs, bpflbr.TracingProgName(flags.OtherMode())) numCPU, err := ebpf.PossibleCPU() assert.NoErr(err, "Failed to get possible cpu: %v")