12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061 |
- // This program demonstrates attaching an eBPF program to a kernel symbol.
- // The eBPF program will be attached to the start of the sys_execve
- // kernel function and prints out the number of times it has been called
- // every second.
- package main
- import (
- "log"
- "time"
- "github.com/cilium/ebpf/link"
- "github.com/cilium/ebpf/rlimit"
- )
- // $BPF_CLANG and $BPF_CFLAGS are set by the Makefile.
- //go:generate go run github.com/cilium/ebpf/cmd/bpf2go -cc $BPF_CLANG -cflags $BPF_CFLAGS bpf kprobe.c -- -I../headers
- const mapKey uint32 = 0
- func main() {
- // Name of the kernel function to trace.
- fn := "sys_execve"
- // Allow the current process to lock memory for eBPF resources.
- if err := rlimit.RemoveMemlock(); err != nil {
- log.Fatal(err)
- }
- // Load pre-compiled programs and maps into the kernel.
- objs := bpfObjects{}
- if err := loadBpfObjects(&objs, nil); err != nil {
- log.Fatalf("loading objects: %v", err)
- }
- defer objs.Close()
- // Open a Kprobe at the entry point of the kernel function and attach the
- // pre-compiled program. Each time the kernel function enters, the program
- // will increment the execution counter by 1. The read loop below polls this
- // map value once per second.
- kp, err := link.Kprobe(fn, objs.KprobeExecve, nil)
- if err != nil {
- log.Fatalf("opening kprobe: %s", err)
- }
- defer kp.Close()
- // Read loop reporting the total amount of times the kernel
- // function was entered, once per second.
- ticker := time.NewTicker(1 * time.Second)
- defer ticker.Stop()
- log.Println("Waiting for events..")
- for range ticker.C {
- var value uint64
- if err := objs.KprobeMap.Lookup(mapKey, &value); err != nil {
- log.Fatalf("reading map: %v", err)
- }
- log.Printf("%s called %d times\n", fn, value)
- }
- }
|