github.com/cilium/ebpf@v0.10.0/examples/kprobepin/main.go (about) 1 // This program demonstrates attaching an eBPF program to a kernel symbol. 2 // The eBPF program will be attached to the start of the sys_execve 3 // kernel function and prints out the number of times it has been called 4 // every second. 5 package main 6 7 import ( 8 "log" 9 "os" 10 "path" 11 "time" 12 13 "github.com/cilium/ebpf" 14 "github.com/cilium/ebpf/link" 15 "github.com/cilium/ebpf/rlimit" 16 ) 17 18 // $BPF_CLANG and $BPF_CFLAGS are set by the Makefile. 19 //go:generate go run github.com/cilium/ebpf/cmd/bpf2go -cc $BPF_CLANG -cflags $BPF_CFLAGS bpf kprobe_pin.c -- -I../headers 20 21 const ( 22 mapKey uint32 = 0 23 bpfFSPath = "/sys/fs/bpf" 24 ) 25 26 func main() { 27 28 // Name of the kernel function to trace. 29 fn := "sys_execve" 30 31 // Allow the current process to lock memory for eBPF resources. 32 if err := rlimit.RemoveMemlock(); err != nil { 33 log.Fatal(err) 34 } 35 36 pinPath := path.Join(bpfFSPath, fn) 37 if err := os.MkdirAll(pinPath, os.ModePerm); err != nil { 38 log.Fatalf("failed to create bpf fs subpath: %+v", err) 39 } 40 41 var objs bpfObjects 42 if err := loadBpfObjects(&objs, &ebpf.CollectionOptions{ 43 Maps: ebpf.MapOptions{ 44 // Pin the map to the BPF filesystem and configure the 45 // library to automatically re-write it in the BPF 46 // program so it can be re-used if it already exists or 47 // create it if not 48 PinPath: pinPath, 49 }, 50 }); err != nil { 51 log.Fatalf("loading objects: %v", err) 52 } 53 defer objs.Close() 54 55 // Open a Kprobe at the entry point of the kernel function and attach the 56 // pre-compiled program. Each time the kernel function enters, the program 57 // will increment the execution counter by 1. The read loop below polls this 58 // map value once per second. 59 kp, err := link.Kprobe(fn, objs.KprobeExecve, nil) 60 if err != nil { 61 log.Fatalf("opening kprobe: %s", err) 62 } 63 defer kp.Close() 64 65 // Read loop reporting the total amount of times the kernel 66 // function was entered, once per second. 67 ticker := time.NewTicker(1 * time.Second) 68 defer ticker.Stop() 69 70 log.Println("Waiting for events..") 71 72 for range ticker.C { 73 var value uint64 74 if err := objs.KprobeMap.Lookup(mapKey, &value); err != nil { 75 log.Fatalf("reading map: %v", err) 76 } 77 log.Printf("%s called %d times\n", fn, value) 78 } 79 }