gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

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 }