tinybpf

module
v0.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 23, 2026 License: MIT

README

tinybpf

tinybpf

Write eBPF programs in Go. Compile with TinyGo. Run in the Linux kernel.

CI Go Report Card License


Overview

eBPF lets sandboxed programs run inside the Linux kernel. Today those programs must be written in C or Rust. tinybpf lets you write them in Go instead.

graph LR
    A["Go source"] --> B["TinyGo"]
    B --> C["LLVM IR"]
    C --> D["tinybpf"]
    D --> E["bpf.o"]

The output is a standard BPF ELF object compatible with cilium/ebpf, libbpf, and bpftool.

Why TinyGo?

Standard Go compiles to native machine code via its own backend — there is no LLVM IR to retarget to BPF, and its runtime (GC, goroutines, channels) cannot run in the kernel. TinyGo compiles through LLVM and supports bare-metal mode (-gc=none -scheduler=none -panic=trap) with no runtime, producing IR that tinybpf transforms into verifier-friendly BPF bytecode.

How it works

tinybpf sits between TinyGo's LLVM IR output and the final BPF ELF. It retargets the IR to BPF, strips the TinyGo runtime, rewrites helper calls to kernel form, and injects the metadata that loaders expect. See Architecture for the full pipeline.

Quick start

Install

go install github.com/kyleseneker/tinybpf/cmd/tinybpf@latest

Prerequisites

Dependency Version Required
Go 1.24+ Yes
TinyGo 0.40+ Yes
LLVM (llvm-link, opt, llc) 20+ (>= TinyGo's bundled LLVM) Yes
llvm-ar, llvm-objcopy 20+ For .a / .o inputs
pahole For BTF injection
make setup    # install everything
make doctor   # verify toolchain

Example

A tracepoint probe that captures outbound TCP connections, written entirely in Go:

//go:extern bpf_get_current_pid_tgid
func bpfGetCurrentPidTgid() uint64

//go:extern bpf_probe_read_user
func bpfProbeReadUser(dst unsafe.Pointer, size uint32, src unsafe.Pointer) int64

//go:extern bpf_ringbuf_output
func bpfRingbufOutput(mapPtr unsafe.Pointer, data unsafe.Pointer, size uint64, flags uint64) int64

//export handle_connect
func handle_connect(ctx unsafe.Pointer) int32 {
    args := (*tpConnectArgs)(ctx)
    var sa sockaddrIn
    bpfProbeReadUser(unsafe.Pointer(&sa), uint32(unsafe.Sizeof(sa)), unsafe.Pointer(uintptr(args.Uservaddr)))
    if sa.Family != afINET {
        return 0
    }
    pid := uint32(bpfGetCurrentPidTgid() >> 32)
    ev := connectEvent{PID: pid, DstAddrBE: sa.AddrBE, DstPortBE: sa.PortBE, Proto: ipProtoTCP}
    bpfRingbufOutput(unsafe.Pointer(&events), unsafe.Pointer(&ev), uint64(unsafe.Sizeof(ev)), 0)
    return 0
}

Build:

tinybpf build --output program.o \
  --section handle_connect=tracepoint/syscalls/sys_enter_connect \
  ./bpf

Examples

Scaffold a new project

tinybpf init xdp_filter

Generates a BPF source file, stub file for IDE compatibility, and a Makefile.

CLI reference

Run tinybpf --help or tinybpf <command> --help.

Subcommands

Subcommand Description
build [flags] <package> Compile Go source to BPF ELF in one step
link --input <file> [flags] Link pre-compiled LLVM IR into a BPF ELF
init <name> Scaffold a new BPF project
doctor Check toolchain installation
version Print version
Flag Default Description
--output, -o bpf.o Output ELF path
--program (auto-detect) Program function to keep (repeatable)
--section Program-to-section mapping name=section (repeatable)
--cpu v3 BPF CPU version for llc -mcpu
--opt-profile default conservative, default, aggressive, or verifier-safe
--pass-pipeline Explicit opt pass pipeline (overrides profile)
--btf false Inject BTF via pahole
--verbose, -v false Print each pipeline stage
--timeout 30s Per-stage timeout
--dump-ir false Write intermediate IR after each transform stage
--program-type Validate sections match a BPF program type (e.g. kprobe, xdp)
--keep-temp false Preserve intermediate files
--tmpdir Directory for intermediate files

build-only flags

Flag Default Description
--tinygo (PATH) Path to tinygo binary
Flag Default Description
--input (required) Input file .ll, .bc, .o, .a (repeatable)
--config Path to linker-config.json for custom passes
--jobs, -j 1 Parallel input normalization workers

Tool path overrides

Flag Description
--llvm-link Override llvm-link
--opt Override opt
--llc Override llc
--llvm-ar Override llvm-ar
--llvm-objcopy Override llvm-objcopy
--pahole Override pahole

Documentation

Document Description
Writing Go for eBPF Language constraints, BPF concepts, helpers, patterns, and FAQ
Architecture Pipeline design and the 15-step IR transformation
Support Matrix Tested toolchain versions and platforms
Troubleshooting Setup issues, pipeline errors, and verifier debugging
Contributing Development setup, testing, and PR process
Project Relationship
cilium/ebpf Go library for loading eBPF programs; loads tinybpf output
bpf2go Compiles C eBPF and generates Go bindings; replaced when the program is Go
libbpf C loader library; compatible with tinybpf output
TinyGo Go compiler targeting LLVM; provides the IR that tinybpf transforms
Aya eBPF in Rust; similar goal, different language
miekg/bpf Prior effort to add BPF to TinyGo's LLVM; archived

License

MIT

Directories

Path Synopsis
cmd
tinybpf command
internal
cli
Package cli implements the tinybpf command-line interface.
Package cli implements the tinybpf command-line interface.
diag
Package diag provides structured, stage-attributed error types for the tinybpf pipeline.
Package diag provides structured, stage-attributed error types for the tinybpf pipeline.
doctor
Package doctor implements the `tinybpf doctor` subcommand, which discovers and version-checks all LLVM toolchain binaries.
Package doctor implements the `tinybpf doctor` subcommand, which discovers and version-checks all LLVM toolchain binaries.
elfcheck
Package elfcheck validates that an output file is a well-formed eBPF ELF object.
Package elfcheck validates that an output file is a well-formed eBPF ELF object.
llvm
Package llvm provides typed wrappers for discovering and executing LLVM toolchain binaries (llvm-link, opt, llc, and optional helpers).
Package llvm provides typed wrappers for discovering and executing LLVM toolchain binaries (llvm-link, opt, llc, and optional helpers).
pipeline
Package pipeline orchestrates the LLVM tool stages that transform input IR/bitcode into a valid eBPF ELF object.
Package pipeline orchestrates the LLVM tool stages that transform input IR/bitcode into a valid eBPF ELF object.
scaffold
Package scaffold generates the file structure for a new tinybpf project.
Package scaffold generates the file structure for a new tinybpf project.
transform
Package transform converts TinyGo-emitted host-targeted LLVM IR into BPF-compatible IR suitable for llc -march=bpf.
Package transform converts TinyGo-emitted host-targeted LLVM IR into BPF-compatible IR suitable for llc -march=bpf.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL