tracepoint.go (2120B)
1 package link 2 3 import ( 4 "fmt" 5 6 "github.com/cilium/ebpf" 7 ) 8 9 // TracepointOptions defines additional parameters that will be used 10 // when loading Tracepoints. 11 type TracepointOptions struct { 12 // Arbitrary value that can be fetched from an eBPF program 13 // via `bpf_get_attach_cookie()`. 14 // 15 // Needs kernel 5.15+. 16 Cookie uint64 17 } 18 19 // Tracepoint attaches the given eBPF program to the tracepoint with the given 20 // group and name. See /sys/kernel/debug/tracing/events to find available 21 // tracepoints. The top-level directory is the group, the event's subdirectory 22 // is the name. Example: 23 // 24 // tp, err := Tracepoint("syscalls", "sys_enter_fork", prog, nil) 25 // 26 // Losing the reference to the resulting Link (tp) will close the Tracepoint 27 // and prevent further execution of prog. The Link must be Closed during 28 // program shutdown to avoid leaking system resources. 29 // 30 // Note that attaching eBPF programs to syscalls (sys_enter_*/sys_exit_*) is 31 // only possible as of kernel 4.14 (commit cf5f5ce). 32 func Tracepoint(group, name string, prog *ebpf.Program, opts *TracepointOptions) (Link, error) { 33 if group == "" || name == "" { 34 return nil, fmt.Errorf("group and name cannot be empty: %w", errInvalidInput) 35 } 36 if prog == nil { 37 return nil, fmt.Errorf("prog cannot be nil: %w", errInvalidInput) 38 } 39 if !isValidTraceID(group) || !isValidTraceID(name) { 40 return nil, fmt.Errorf("group and name '%s/%s' must be alphanumeric or underscore: %w", group, name, errInvalidInput) 41 } 42 if prog.Type() != ebpf.TracePoint { 43 return nil, fmt.Errorf("eBPF program type %s is not a Tracepoint: %w", prog.Type(), errInvalidInput) 44 } 45 46 tid, err := getTraceEventID(group, name) 47 if err != nil { 48 return nil, err 49 } 50 51 fd, err := openTracepointPerfEvent(tid, perfAllThreads) 52 if err != nil { 53 return nil, err 54 } 55 56 var cookie uint64 57 if opts != nil { 58 cookie = opts.Cookie 59 } 60 61 pe := &perfEvent{ 62 typ: tracepointEvent, 63 group: group, 64 name: name, 65 tracefsID: tid, 66 cookie: cookie, 67 fd: fd, 68 } 69 70 lnk, err := attachPerfEvent(pe, prog) 71 if err != nil { 72 pe.Close() 73 return nil, err 74 } 75 76 return lnk, nil 77 }