eBPF from Go; First Steps
So I had this itch that I wanted to make a Go program compile to eBPF and be able to load that
program in the Linux kernel by use of bpftool
.
As I say in github.com/miekg/ebpf
eBPF in C? What am I, a farmer?
After much reading about eBPF and thinking about how that would work from Go, I figured that would involve writing a Go compiler.
So I could:
-
hack the official Go compiler and (try to) add a eBPF target (which would probably never be added as an official target because of all the constraints eBPF has).
-
create a complete stand-alone and new compiler that parses Go code and emits eBPF binary in an ELF object.
-
find something else that already does (2) and works with constraint backends.
I thought a while about doing (2), but that just seemed A LOT OF WORK.
While searching I found TinyGo which seems to do everything I want it to do, except of course output eBPF bytecode.
So TinyGo it is! For now at least, (2) is still an option – although a distant one.
First Steps⌗
After forking and building TinyGo I need it to recognize (e)BPF (going to drop the ’e’ going forward) as a valid target.
Turns out this is relative easy: just create a target/bpf.json
file with the “correct” values,
recompile tinygo (make
), and voila:
% ./build/tinygo targets | grep bpf
bpf
The top of target/bpf.json
now looks as:
{
"llvm-target": "bpf",
"cpu": "generic",
"features": "+bulk-memory,+mutable-globals,+nontrapping-fptoint,+sign-ext",
"build-tags": ["tinygo.bpf"],
"goos": "linux",
...
The llvm-target
might actually be correct, the rest is still BS (well GOOS
might be OK too). But
my main goal here is to make TinyGo output (via llvm) BPF bytecode and take it from there.