EnglishРусский Map

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 остаётся в инструментарии пользователя.

Как устроен

Конвейер:

  1. Проверка типов. Сначала go/types проверяет входные данные, поэтому ошибки использования выявляются сразу с указанием file:line:col в Go-коде, а не где-то дальше в потоке ошибок clang'а.
  2. Транспиляция. Команда gobee translate --bindings-dir ./bpf ./bpf/src создаёт по три артефакта на каждый исходный файл ядра: <stem>.bpf.c, sourcemap <stem>.bpf.c.map и типизированный <stem>_bindings.go.
  3. Компиляция. Пользователь запускает clang для сборки <stem>.bpf.o. Тот же шаблон Makefile, что и у bpf2go.
  4. Загрузка. Сгенерированная функция 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.