Skip to content

Commit

Permalink
example: demonstrate tracepoint usage
Browse files Browse the repository at this point in the history
Signed-off-by: Florian Lehner <dev@der-flo.net>
  • Loading branch information
florianl committed Feb 24, 2021
1 parent da367ec commit 5d66b59
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 129 deletions.
9 changes: 9 additions & 0 deletions _example/tracepoint/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module github.com/cilium/ebpf/_example/tracepoint

go 1.15

require (
github.com/cilium/ebpf v0.3.0
github.com/elastic/go-perf v0.0.0-20191212140718-9c656876f595
golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9
)
8 changes: 8 additions & 0 deletions _example/tracepoint/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
github.com/cilium/ebpf v0.3.0 h1:LI3lsl5GmTh+OFYamrj8sp+R0yam38zHG6NTDhSlNmQ=
github.com/cilium/ebpf v0.3.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs=
github.com/elastic/go-perf v0.0.0-20191212140718-9c656876f595 h1:q8n4QjcLa4q39Q3fqHRknTBXBtegjriHFrB42YKgXGI=
github.com/elastic/go-perf v0.0.0-20191212140718-9c656876f595/go.mod h1:s09U1b4P1ZxnKx2OsqY7KlHdCesqZWIhyq0Gs/QC/Us=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9 h1:1/DFK4b7JH8DmkqhUk48onnSfrPzImPoVxuomtbT2nk=
golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
133 changes: 133 additions & 0 deletions _example/tracepoint/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
// +build linux

package main

import (
"context"
"fmt"
"os"
"runtime"
"time"

"github.com/cilium/ebpf"
"github.com/cilium/ebpf/asm"
ringbuffer "github.com/cilium/ebpf/perf"
"golang.org/x/sys/unix"

"github.com/elastic/go-perf"
)

// This program demonstrates how to attach an eBPF program to a tracepoint.
// The program will be attached to the sys_enter_open syscall and print out the integer
// 123 everytime the sycall is used.
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

var originalLimit unix.Rlimit
// Get the original rlimit values so we can restore them laster.
if err := unix.Getrlimit(unix.RLIMIT_MEMLOCK, &originalLimit); err != nil {
panic(fmt.Errorf("failed to get rlimit: %v", err))
}

// Increase rlimit so the eBPF map and program can be loaded.
if err := unix.Setrlimit(unix.RLIMIT_MEMLOCK, &unix.Rlimit{
Cur: unix.RLIM_INFINITY,
Max: unix.RLIM_INFINITY,
}); err != nil {
panic(fmt.Errorf("failed to set temporary rlimit: %v", err))
}

events, err := ebpf.NewMap(&ebpf.MapSpec{
Type: ebpf.PerfEventArray,
Name: "pureGo",
})
if err != nil {
panic(fmt.Errorf("could not create event map: %v", err))
}
defer events.Close()

rd, err := ringbuffer.NewReader(events, os.Getpagesize())
if err != nil {
panic(fmt.Errorf("could not create event reader: %v", err))
}
defer rd.Close()

go func() {
for {
select {
case <-ctx.Done():
return
default:
}
record, err := rd.Read()
if err != nil {
if ringbuffer.IsClosed(err) {
return
}
panic(fmt.Errorf("could not read from reader: %v", err))
}
fmt.Println(record)
}
}()

ins := asm.Instructions{
// store the integer 123 at FP[-8]
asm.Mov.Imm(asm.R2, 123),
asm.StoreMem(asm.RFP, -8, asm.R2, asm.Word),

// load registers with arguments for call of FnPerfEventOutput
asm.LoadMapPtr(asm.R2, events.FD()),
asm.LoadImm(asm.R3, 0xffffffff, asm.DWord),
asm.Mov.Reg(asm.R4, asm.RFP),
asm.Add.Imm(asm.R4, -8),
asm.Mov.Imm(asm.R5, 4),

// call FnPerfEventOutput
asm.FnPerfEventOutput.Call(),

// set exit code to 0
asm.Mov.Imm(asm.R0, 0),
asm.Return(),
}

prog, err := ebpf.NewProgram(&ebpf.ProgramSpec{
Name: "trace_open",
Type: ebpf.TracePoint,
License: "GPL",
Instructions: ins,
})
if err != nil {
panic(fmt.Errorf("could not create new ebpf program: %v", err))
}
defer prog.Close()

ga := new(perf.Attr)
gtp := perf.Tracepoint("syscalls", "sys_enter_open")
if err := gtp.Configure(ga); err != nil {
panic(fmt.Errorf("failed to configure tracepoint: %v", err))
}

// Restore original rlimit values.
if err := unix.Setrlimit(unix.RLIMIT_MEMLOCK, &originalLimit); err != nil {
panic(fmt.Errorf("failed to restore original rlimit: %v", err))
}

runtime.LockOSThread()
defer runtime.UnlockOSThread()

openTracepoint, err := perf.Open(ga, perf.AllThreads, 0, nil)
if err != nil {
panic(fmt.Errorf("failed to open perf event on tracepoint: %v", err))
}
defer openTracepoint.Close()

if err := openTracepoint.SetBPF(uint32(prog.FD())); err != nil {
panic(fmt.Errorf("failed to attach eBPF to tracepoint: %v", err))
}
if err := openTracepoint.Enable(); err != nil {
panic(fmt.Errorf("failed to enable eBPF to tracepoint: %v", err))
}

<-ctx.Done()
}
129 changes: 0 additions & 129 deletions example_program_test.go

This file was deleted.

0 comments on commit 5d66b59

Please sign in to comment.