https://github.com/v420v/ego
Go compiler for eBPF
https://github.com/v420v/ego
compiler ebpf go
Last synced: 22 days ago
JSON representation
Go compiler for eBPF
- Host: GitHub
- URL: https://github.com/v420v/ego
- Owner: v420v
- Created: 2026-05-11T00:39:55.000Z (about 1 month ago)
- Default Branch: main
- Last Pushed: 2026-05-25T05:47:51.000Z (29 days ago)
- Last Synced: 2026-05-25T07:25:09.833Z (29 days ago)
- Topics: compiler, ebpf, go
- Language: Go
- Homepage:
- Size: 221 KB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.md
Awesome Lists containing this project
README
# eGo - eBPF in Pure Go
**Write eBPF programs in Go. Get a regular `.bpf.o` that any BPF loader can load.**
eGo is a Go-to-eBPF compiler. You write a subset of Go; it emits a
`clang -target bpf`-compatible ELF object — BTF, CO-RE relocations, and
all. The BPF backend, BTF encoder, and CO-RE relocator are all pure Go.
```
your_program.go ← //go:build ego
│ ego build
▼
your_program.bpf.o ← standard BPF ELF + BTF + CO-RE relocs
│ any BPF loader: libbpf (C), libbpf-rs / aya (Rust),
│ cilium/ebpf (Go), libbpf-python / bcc (Python), bpftool, …
▼
kernel: verifier → JIT → run
```
eGo owns ELF emission. The output is a normal BPF ELF, so any existing loader in any language works. The examples in this repo use `cilium/ebpf`
because the project is Go-leaning, but nothing about eGo's output is Go-specific.
## Install
```sh
go install github.com/v420v/ego/cmd/ego@latest
```
Or from source:
```sh
make build # → bin/ego
make examples # build every example to .bpf.o
```
## Hello, XDP
```go
//go:build ego
package bpf
import (
"github.com/v420v/ego/stdlib/maps"
"github.com/v420v/ego/stdlib/xdp"
)
var PacketCount = maps.PerCPUArray[uint64]{MaxEntries: 1}
//ego:program type=xdp
func Count(ctx *xdp.Context) xdp.Action {
var key uint32 = 0
if v := PacketCount.Lookup(&key); v != nil {
*v = *v + 1
}
return xdp.Pass
}
```
Build:
```sh
ego build -o counter.bpf.o ./path/to/pkg
```
Load with whatever BPF loader you already use. Examples:
```go
// Go — github.com/cilium/ebpf
spec, _ := ebpf.LoadCollectionSpec("counter.bpf.o")
coll, _ := ebpf.NewCollection(spec)
defer coll.Close()
l, _ := link.AttachXDP(link.XDPOptions{
Program: coll.Programs["Count"], Interface: ifaceIdx,
})
defer l.Close()
```
```c
// C — libbpf
struct bpf_object *obj = bpf_object__open_file("counter.bpf.o", NULL);
bpf_object__load(obj);
struct bpf_program *prog = bpf_object__find_program_by_name(obj, "Count");
bpf_program__attach_xdp(prog, ifindex);
```
```sh
# Shell — bpftool, no userspace code at all
bpftool prog loadall counter.bpf.o /sys/fs/bpf/counter
bpftool net attach xdp pinned /sys/fs/bpf/counter/Count dev eth0
```
The `.bpf.o` is the same standard ELF in every case.
## License
MIT.