- asm 包含一个基本的汇编生成器。
- link 允许将附加的 eBPF 程序挂载到各类 hooks 上。
- perf 提供从 PERF_EVENT_ARRAY 读取对应的数据。
- cmd/bpf2go 将 eBPF 程序嵌入到 Go 代码中。
godoc 地址: https://godoc.org/github.com/cilium/ebpf
可以实现将 C 代码编写的 bpf 程序编译成 Go 代码。
test.c
// +build ignore
char __license[] __attribute__((section("license"), used)) = "MIT";
__attribute__((section("socket"), used)) int filter() { return 0; }
将 C 文件编译成 Go 代码
# go build -o bpf2go
# export GOPACKAGE="sock" // 定义生产 go 代码的包名
# ./bpf2go -cc=clang -makebase="" -target=bpf sock test.c
Compiled /root/go/src/github.com/cilium/ebpf/cmd/bpf2go/test_bpf.o
Wrote /root/go/src/github.com/cilium/ebpf/cmd/bpf2go/sock_bpf.go
# 最后会生成 test_bpf.o 和 sock_bpf.go
生成的 sock_bpf.go 完整代码如下:
// Code generated by bpf2go; DO NOT EDIT.
package aa
import (
"bytes"
"fmt"
"io"
"github.com/cilium/ebpf"
)
type sockSpecs struct {
ProgramFilter *ebpf.ProgramSpec `ebpf:"filter"`
}
func newSockSpecs() (*sockSpecs, error) {
reader := bytes.NewReader(_SockBytes)
spec, err := ebpf.LoadCollectionSpecFromReader(reader)
if err != nil {
return nil, fmt.Errorf("can't load sock: %w", err)
}
specs := new(sockSpecs)
if err := spec.Assign(specs); err != nil {
return nil, fmt.Errorf("can't assign sock: %w", err)
}
return specs, nil
}
func (s *sockSpecs) CollectionSpec() *ebpf.CollectionSpec {
return &ebpf.CollectionSpec{
Programs: map[string]*ebpf.ProgramSpec{
"filter": s.ProgramFilter,
},
Maps: map[string]*ebpf.MapSpec{},
}
}
func (s *sockSpecs) Load(opts *ebpf.CollectionOptions) (*sockObjects, error) {
var objs sockObjects
if err := s.CollectionSpec().LoadAndAssign(&objs, opts); err != nil {
return nil, err
}
return &objs, nil
}
func (s *sockSpecs) Copy() *sockSpecs {
return &sockSpecs{
ProgramFilter: s.ProgramFilter.Copy(),
}
}
type sockObjects struct {
ProgramFilter *ebpf.Program `ebpf:"filter"`
}
func (o *sockObjects) Close() error {
for _, closer := range []io.Closer{
o.ProgramFilter,
} {
if err := closer.Close(); err != nil {
return err
}
}
return nil
}
// Do not access this directly.
var _SockBytes = []byte("0x....")