gobee
- title
- gobee
- type
- toolbox
- summary
- Транспайлер Go в BPF C, использующий BPF-бэкенд clang и генерирующий типизированные привязки для cilium/ebpf
- tags
- go, ebpf, bpf, transpiler, kernel, linux
- language
- Go
- license
- MIT
- created
- 2026-05-22
- updated
- 2026-05-22
- lang
- ru
- translation_of
- gobee
- source_updated
- 2026-05-22
- translated
- 2026-09-01
- translator
- lllm/antigravity/gemini-3.7-flash-medium
Транспайлер Go в BPF C от Bora Tanrıkulu. BPF-программа для ядра пишется на строгом подмножестве Go; gobee генерирует BPF C, запускает clang и создаёт типизированные привязки для Go, чтобы драйвер в userspace работал со своими структурами и именами программ, а не со строковыми обращениями вида coll.Programs["..."].
Архитектурное решение здесь самое интересное. Aya (Rust eBPF) решает задачу за счёт добавления нового BPF-бэкенда в rustc - это осуществимо, так как rustc построен на LLVM. Компилятор Go gc устроен иначе, поэтому добавление BPF-бэкенда превратилось бы в многолетний проект разработки компилятора. gobee обходит эту работу: инструмент генерирует C и повторно использует зрелый BPF-бэкенд clang, что даёт готовую поддержку CO-RE, BTF и дружественную к верификатору генерацию кода. Плата за это - clang остаётся в инструментарии пользователя.
Как устроен
Конвейер:
- Проверка типов. Сначала
go/typesпроверяет входные данные, поэтому ошибки использования выявляются сразу с указаниемfile:line:colв Go-коде, а не где-то дальше в потоке ошибок clang'а. - Транспиляция. Команда
gobee translate --bindings-dir ./bpf ./bpf/srcсоздаёт по три артефакта на каждый исходный файл ядра:<stem>.bpf.c, sourcemap<stem>.bpf.c.mapи типизированный<stem>_bindings.go. - Компиляция. Пользователь запускает clang для сборки
<stem>.bpf.o. Тот же шаблон Makefile, что и у bpf2go. - Загрузка. Сгенерированная функция
Load<Stem>обращается кcilium/ebpfи внутри запускает bpfvet. Если ядро хоста слишком старое для какого-либо используемого хелпера, загрузка быстро завершается с ошибкойbpf program needs kernel >= 5.8, host is 5.4вместо неинформативногоEINVAL. Если верификатор отклоняет программу, возвращаемая ошибка*ebpf.VerifierErrorавтоматически аннотируется маркерами вида→ counter.go:18:5, указывающими на исходный Go-код.
Сгенерированный C-код намеренно сделан читаемым: если gobee выдаст что-то странное, это будет видно.
Покрытие возможностей
8 типов программ (XDP, tracepoint, kprobe/kretprobe, uprobe/uretprobe, sock_ops, TC, cgroup_skb, LSM). 19 типов map'ов, включая ringbuf, perf_event_array, sk/task/inode storage, devmap/cpumap/xskmap. Около 200 типизированных Go-заглушек, автоматически сгенерированных из заголовков libbpf v1.5.0: те из них, что задействованы в example/helloworld/ и example/sysmon/, протестированы в CI на реальном ядре, остальные не верифицированы.
Пользовательские вспомогательные функции: функции Go верхнего уровня без директивы //bpf:section генерируются как C-функции с static __always_inline.
CO-RE определяется автоматически: BPF_CORE_READ для полей внутренних структур ядра (task_struct, sock, inode), прямой доступ ctx->field для структур BPF-контекста UAPI (xdp_md, __sk_buff, bpf_sock_ops). Проверено на Linux 6.x (CI на Ubuntu 24.04); более старые ядра пока не включены в матрицу CI. Кросс-архитектурность: Linux arm64 + amd64.
Чего он принципиально не делает
- Не заменяет clang. Повторная реализация BPF-бэкенда clang'а заняла бы годы и ничего бы не дала.
- Не заменяет
cilium/ebpf. Сгенерированные привязки работают поверх него. - Не скрывает BPF. Подмножество Go один к одному сопоставляется с идиомами BPF C. Если вы знаете BPF, gobee - это лишь тонкий синтаксический сахар; если нет, читать документацию всё равно придётся.
- Не запускает clang за вас. Компиляция, внедрение и загрузка остаются под управлением пользователя - по тому же принципу, что и в
bpf2go.
Место в экосистеме
Тот же автор, что и у gecit и bpfvet; gobee использует bpfvet во время загрузки, а gecit демонстрирует тип сетевой BPF-программы в ядре (десинхронизация SNI через sock_ops), разработку которых gobee призван сделать удобнее. О публикациях автора на эту тему см. bora-blog.
О контексте изоляции (песочниц) - уровне, где это важно на практике, - см. ebpf-sock-ops и sandboxing-ai-agents (обсуждение Layer 1 / границы ядра). Инструменты для сравнения: bpf2go (базовый вариант на C+clang) и Aya (Rust через BPF-бэкенд rustc).
Ограничения
- macOS/Windows: сам gobee работает (чистый Go), но для компиляции
.bpf.oнужен clang с поддержкой целевой архитектуры BPF: встроенный clang от Apple её не содержит, поэтому требуетсяbrew install llvmили виртуальная машина с Linux. - Запуск артефакта: Linux на arm64 или amd64.
- Покрытие хелперов за пределами примеров в CI не верифицировано; до расширения матрицы возможны проблемы с редкими хелперами ядра.
Репозиторий
github.com/boratanrikulu/gobee · 25★ на момент ingest'а · MIT · создан 2026-05-01.