本文为翻译文章,译者水平有限,如果错误欢迎指正。
原文地址:https://kinvolk.io/blog/2022/03/btfgen-one-step-closer-to-truly-portable-ebpf-programs/
eBPF 是一项广为人知的技术,已经在可观测、网络和安全领域领域得到广泛应用。Linux 操作系统提供了虚拟机,可用于安全和高效的方式运行 eBPF 程序【译者注:如果是 JIT 模式则会直接翻译成本地 CPU 指令,则不需要虚拟机】。eBPF 程序挂载在操作系统提供的钩子上,使其能够在内核中发生特定事件时过滤和提取感兴趣的信息。
在本文中,我们将介绍助力 eBPF 程序移植的工具 BTFGen,以及其如何被集成到其他项目中,主要的内容如下:
eBPF 程序需要访问内核结构来获取需要的数据,因此依赖于内核结构的布局。为特定内核版本编译的 eBPF 程序通常不能在另一个内核版本上工作,这是因为相关的内核数据结构布局可能会发生了变化:比如字段添加、删除,或类型被改变,甚至内核编译配置的改变也会改变整个结构布局。例如,禁用 CONFIG_THREAD_INFO_IN_TASK
会改变 task_struct[1] 的所有成员变量的偏移:
struct task_struct {
#ifdef CONFIG_THREAD_INFO_IN_TASK
/*
* For reasons of header soup (see current_thread_info()), this
* must be the first element of task_struct.
*/
struct thread_info thread_info;
#endif
unsigned int __state;
#ifdef CONFIG_PREEMPT_RT
/* saved state for "spinlock sleepers" */
unsigned int saved_state;
#endif
...
该问题的解决通常是在目标机器使用内核头文件编译 eBPF 程序并进行加载,BCC[2] 项目所使用的正是这种方式。但该方法存在以下问题:
CO-RE 机制正是为解决上述问题提出的方案。在该方案中,eBPF 程序一次编译,然后在运行时进行更新(patched):基于运行的机器的内核结构布局更新运行指令。BPF CO-RE (Compile Once - Run Everywhere)[3] 介绍了该技术背后的所有细节。对于本文,需要理解的是 CO-RE 需要有目标内核的 BTF 信息(BPF Type Format 类型格式)。BTF 信息由内核本身提供的,这需要在内核编译时设置 CONFIG_DEBUG_INFO_BTF=y
选项 。该选项在 Linux 内核 5.2[4] 中引入的,许多流行的 Linux 发行版在其后的部分内核版本才默认启用。这意味着有很多用户运行的内核并没有导出 BTF 信息,因此不能使用基于 CO-RE 的工具。
BTFHub[5] 是 Aqua Security 公司的一个项目,其可为不导出 BTF 信息的流行发行版内核提供 BTF 信息补充。目标内核的 BTF 文件可以在运行时下载,然后与加载库(libbpf、cilium/ebpf 或其他)配合,加载库基于 BTF 文件对程序进行相应的更新(patch)。
尽管 BTFHub 做了很大的改进,但是它仍然面临着一些挑战:每个 BTF 文件有数 MB 大小,因此不可能把所有内核的 BTF 文件和应用程序一起打包,因为这可能需要数 GB 的空间占用。另一种方法是在运行时下载当前内核的所需 BTF,但这也带来了一些问题:延迟 eBPF 程序启动,而且在某些情况下,连接到外部主机下载文件也不可行。
其实,通常我们并不需要提供描述所有内核类型的完整 BTF 文件,因为 eBPF 程序通常只需要访问其中的少数类型。一个 "精简版" 的 BTF 文件,只需要提供程序使用类型的信息就足够了。这就是工具 BTFGen 发挥作用:其可以生成一组 eBPF 程序所需的精简的 BTF ,通过该方式生成的 BTF 文件只有数 KB 大小,将其与应用程序打包交付变成了可能。
BTFGen 并不是单独提供能力的。它需要具有不同 Linux 发行版的所有内核类型的源 BTF 文件(由 BTFHub 提供),并且 CO-RE 机制(在 libbpf、Linux 内核或另一个加载库中)在加载程序时通过打补丁方式更新 eBPF 程序。
使用 BTFGen 的主要流程如下:
BTFGen 在 bpftool 工具中实现,其使用 libbpf CO-RE 逻辑来解决重定位问题。有了这些信息,它就能挑选出重新定位所涉及的类型来生成 "精简版" 的 BTF 文件。这篇文章的目的不是要解释所有的内部实现细节。如果你想知道更多,你可以查看 BTFHub 仓库中的这个[7]文档或实现它的补丁[8]。
本节提供了 BTFGen 工具使用的更多细节。在本例中,我们将使用 BTFGen 来实现内核未启用 CONFIG_DEBUG_INFO_BTF
选项的机器上运行特定的 BCC libbpf-tools[9] 工具。其他 eBPF 应用程序集成的方式也是类似。
为了实现上述的目的,我们需要以下流程:
首先,我们为该演示创建一个临时目录:
$ mkdir /tmp/btfgendemo
BTFGen 刚刚被合入 bpftool。在 BTFGen 未被包含在不同发行版的软件包之前,我们需要从源代码进行编译:
$ cd /tmp/btfgendemo
$ git clone --recurse-submodules https://github.com/libbpf/bpftool.git
$ cd bpftool/src
$ make
$ sudo make install
这里为简洁起见,我们只考虑 Ubuntu Focal 系统中使用的场景,该方式也完全适用于 BTFHub 支持的其他发行版本。
$ cd /tmp/btfgendemo
$ git clone https://github.com/aquasecurity/btfhub-archive
$ cd btfhub-archive/ubuntu/focal/x86_64/
$ for f in *.tar.xz; do tar -xf "$f"; done
$ ls -lhn *.btf | head
-rw-r----- 1 1000 1000 4,5M Sep 29 13:36 5.11.0-1007-azure.btf
-rw-r----- 1 1000 1000 4,8M Aug 10 23:33 5.11.0-1009-aws.btf
-rw-r----- 1 1000 1000 4,8M Jan 22 12:29 5.11.0-1009-gcp.btf
-rw-r----- 1 1000 1000 4,5M Sep 29 13:38 5.11.0-1012-azure.btf
-rw-r----- 1 1000 1000 4,5M Sep 29 13:40 5.11.0-1013-azure.btf
-rw-r----- 1 1000 1000 4,8M Aug 10 23:39 5.11.0-1014-aws.btf
-rw-r----- 1 1000 1000 4,8M Jan 22 12:32 5.11.0-1014-gcp.btf
-rw-r----- 1 1000 1000 4,5M Sep 29 13:43 5.11.0-1015-azure.btf
-rw-r----- 1 1000 1000 4,8M Sep 7 22:52 5.11.0-1016-aws.btf
-rw-r----- 1 1000 1000 4,8M Sep 7 22:57 5.11.0-1017-aws.btf
如上述显示,我们可以看到每个内核对应的 BTF 文件的大小约为 4MB。
$ find . -name "*.btf" | xargs du -ch | tail -n 1
944M total
但是汇总起来看,仅 Ubuntu Focal 就有~944MB 的大小,将其与应用程序一起打包显然不太可行。
我们从 BCC v0.24.0 标签上克隆仓库代码:
$ cd /tmp/btfgendemo
$ git clone https://github.com/iovisor/bcc -b v0.24.0 --recursive
默认情况下,不同的 BCC 工具会尝试从约定目录中[10]加载 BTF 信息。正常情况下,我们不能直接覆盖对应的文件,因为它们极有可能也会被其他工具所依赖。相反,我们可以修改 BCC 工具源码,让其从一个自定义的路径加载 BTF 文件。我们可以使用 LIBBPF_OPTS()
来声明一个 bpf_object_open_opts
结构,将其中的 btf_custom_path
字段设置为自定义 BTF 所在的路径,并将其传递给 TOOL_bpf__open_opts()
函数。我们尝试使用如下的补丁来修改 opennoop、execsnoop 和 bindsnoop 工具。
译者注,约定的加载 BTF 目录如下:{ "/sys/kernel/btf/vmlinux", true /_ raw BTF _/ },
{ "/boot/vmlinux-%1$s" },
{ "/lib/modules/%1$s/vmlinux-%1$s" },
{ "/lib/modules/%1$s/build/vmlinux" },
{ "/usr/lib/modules/%1$s/kernel/vmlinux" },
{ "/usr/lib/debug/boot/vmlinux-%1$s" },
{ "/usr/lib/debug/boot/vmlinux-%1$s.debug" },
{ "/usr/lib/debug/lib/modules/%1$s/vmlinux" },
# /tmp/btfgendemo/bcc.patch
diff --git a/libbpf-tools/bindsnoop.c b/libbpf-tools/bindsnoop.c
index 5d87d484..a336747e 100644
--- a/libbpf-tools/bindsnoop.c
+++ b/libbpf-tools/bindsnoop.c
@@ -187,7 +187,8 @@ int main(int argc, char **argv)
libbpf_set_strict_mode(LIBBPF_STRICT_ALL);
libbpf_set_print(libbpf_print_fn);
- obj = bindsnoop_bpf__open();
+ LIBBPF_OPTS(bpf_object_open_opts, opts, .btf_custom_path = "/tmp/vmlinux.btf");
+ obj = bindsnoop_bpf__open_opts(&opts);
if (!obj) {
warn("failed to open BPF object\n");
return 1;
diff --git a/libbpf-tools/execsnoop.c b/libbpf-tools/execsnoop.c
index 38294816..9bd0d077 100644
--- a/libbpf-tools/execsnoop.c
+++ b/libbpf-tools/execsnoop.c
@@ -274,7 +274,8 @@ int main(int argc, char **argv)
libbpf_set_strict_mode(LIBBPF_STRICT_ALL);
libbpf_set_print(libbpf_print_fn);
- obj = execsnoop_bpf__open();
+ LIBBPF_OPTS(bpf_object_open_opts, opts, .btf_custom_path = "/tmp/vmlinux.btf");
+ obj = execsnoop_bpf__open_opts(&opts);
if (!obj) {
fprintf(stderr, "failed to open BPF object\n");
return 1;
diff --git a/libbpf-tools/opensnoop.c b/libbpf-tools/opensnoop.c
index 557a63cd..cf2c5db6 100644
--- a/libbpf-tools/opensnoop.c
+++ b/libbpf-tools/opensnoop.c
@@ -231,7 +231,8 @@ int main(int argc, char **argv)
libbpf_set_strict_mode(LIBBPF_STRICT_ALL);
libbpf_set_print(libbpf_print_fn);
- obj = opensnoop_bpf__open();
+ LIBBPF_OPTS(bpf_object_open_opts, opts, .btf_custom_path = "/tmp/vmlinux.btf");
+ obj = opensnoop_bpf__open_opts(&opts);
if (!obj) {
fprintf(stderr, "failed to open BPF object\n");
return 1;
$ cd bcc
$ git apply /tmp/btfgendemo/bcc.patch
$ cd libbpf-tools/
$ make -j$(nproc)
这里,我们将使用 bpftool gen min_core_btf
命令为 BCC 工具中的 bindsnoop、execsnoop 和 opensnoop 同时生成精简的 BTF 文件。下述的命令对目录中存在的每个 BTF 文件逐次调用 bpftool 工具进行精简。
$ OBJ1=/tmp/btfgendemo/bcc/libbpf-tools/.output/bindsnoop.bpf.o
$ OBJ2=/tmp/btfgendemo/bcc/libbpf-tools/.output/execsnoop.bpf.o
$ OBJ3=/tmp/btfgendemo/bcc/libbpf-tools/.output/opensnoop.bpf.o
$ mkdir -p /tmp/btfgendemo/btfs
$ cd /tmp/btfgendemo/btfhub-archive/ubuntu/focal/x86_64/
$ for f in *.btf; do bpftool gen min_core_btf "$f" \
/tmp/btfgendemo/btfs/$(basename "$f") $OBJ1 $OBJ2 $OBJ3; \
done
$ ls -lhn /tmp/btfgendemo/btfs | head
total 864K
-rw-r--r-- 1 1000 1000 1,1K Feb 8 14:46 5.11.0-1007-azure.btf
-rw-r--r-- 1 1000 1000 1,1K Feb 8 14:46 5.11.0-1009-aws.btf
-rw-r--r-- 1 1000 1000 1,1K Feb 8 14:46 5.11.0-1009-gcp.btf
-rw-r--r-- 1 1000 1000 1,1K Feb 8 14:46 5.11.0-1012-azure.btf
-rw-r--r-- 1 1000 1000 1,1K Feb 8 14:46 5.11.0-1013-azure.btf
-rw-r--r-- 1 1000 1000 1,1K Feb 8 14:46 5.11.0-1014-aws.btf
-rw-r--r-- 1 1000 1000 1,1K Feb 8 14:46 5.11.0-1014-gcp.btf
-rw-r--r-- 1 1000 1000 1,1K Feb 8 14:46 5.11.0-1015-azure.btf
-rw-r--r-- 1 1000 1000 1,1K Feb 8 14:46 5.11.0-1016-aws.btf
精简后生成的 BTF 文件大约为 1.1KB,Ubuntu Focal 对应的所有文件的大小为 864KB,将其与程序一起打包完全可行。
如果我们对生成的文件进一步进行压缩,其大小还可以大幅缩减:
$ cd /tmp/btfgendemo/btfs
$ tar cvfJ compressed.tar.xz *.btf
$ ls -lhn compressed.tar.xz
-rw-r--r-- 1 1000 1000 2,5K Feb 17 15:19 compressed.tar.xz
压缩率如此之高是因为许多生成的文件相同,我们将在下文中进一步讨论。
为了验证,我们需要运行一台装有 Ubuntu Focal 的机器。这里提供的 Vagrant 文件可以用来创建对应的虚拟机。请注意,Ubuntu Focal 从内核 5.4.0-92-generic 版本开始启用 BTF 支持,所以我们需要运行其早期的版本进行验证。我们使用 bento/ubuntu-20.04
Vagrant 虚拟机中的 202012.21.0
版本,内核为 5.4.0-58-generic。
本文使用 sshfs
在主机和虚拟机之间共享文件,需要我们确保已经安装了 vagrant-sshfs
[11] 插件。
译者注:
$ sudo vagrant plugin install vagrant-sshfs
# /tmp/btfgendemo/Vagrantfile
Vagrant.configure("2") do | config |
config.vm.box = "bento/ubuntu-20.04"
config.vm.box_version = "= 202012.21.0"
config.vm.synced_folder "/tmp/btfgendemo", "/btfgendemo", type: "sshfs"
config.vm.provider "virtualbox" do | vb |
vb.gui = false
vb.cpus = 4
vb.memory = "4096"
end
end
启动虚拟机并使用 ssh 登录:
$ vagrant up
$ vagrant ssh
后续的命令必须在虚拟机内执行。检查内核版本:
$ uname -a
Linux vagrant 5.4.0-58-generic #64-Ubuntu SMP Wed Dec 9 08:16:25 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
让我们检查一下内核是否启用了CONFIG_DEBUG_INFO_BTF
:
$ cat /boot/config-$(uname -r) | grep CONFIG_DEBUG_INFO_BTF
CONFIG_DEBUG_INFO_BTF is not set
在把 BTF 文件复制到正确路径之前,我们尝试运行以下这些工具:
$ sudo /btfgendemo/bcc/libbpf-tools/execsnoop
libbpf: failed to parse target BTF: -2
libbpf: failed to perform CO-RE relocations: -2
libbpf: failed to load object 'execsnoop_bpf'
libbpf: failed to load BPF skeleton 'execsnoop_bpf': -2
failed to load BPF object: -2
正如预期,我们运行工具失败,因为工具不能找到执行 CO-RE 重定位所需的 BTF 信息。
接着,我们将该内核版本的 BTF 文件复制到对应目录:
$ cp /btfgendemo/btfs/$(uname -r).btf /tmp/vmlinux.btf
将复制 BTF 到指定目录后,工具运行正常:
$ sudo /btfgendemo/bcc/libbpf-tools/execsnoop
PCOMM PID PPID RET ARGS
^C
$ sudo /btfgendemo/bcc/libbpf-tools/bindsnoop
PID COMM RET PROTO OPTS IF PORT ADDR
^C
$ sudo /btfgendemo/bcc/libbpf-tools/opensnoop
PID COMM FD ERR PATH
^C
当然这只是为了演示工具工作流程的样例。真正的集成需要负责基于主机的内核版本自动提供对应的 BTF 文件。下面的部分通过两个例子展示了对应的集成。
在本节中,我们将介绍 Inspektor Gadget 和 Tracee 项目是如何使用 BTFGen。
Inspektor Gadget[12] 是一个用于调试/检查 Kubernetes 资源和应用程序的工具集。由于 Inspektor Gadget 是以容器镜像的形式发布的,我们选择在其中为不同的 Linux 发行版搭载 BTF 文件。我们在 Docker 文件中添加了一个步骤[13],使其可以在构建容器镜像时生成 BTF 文件:
RUN set -ex; \
if [ "$ENABLE_BTFGEN" = true ]; then \
cd /btf-tools && \
LIBBPFTOOLS=/objs BTFHUB=/tmp/btfhub INSPEKTOR_GADGET=/gadget ./btfgen.sh; \
fi
辅助脚本 btfgen.sh[14] 调用 bpftool 为 BTFHub 支持的所有内核生成 BTF 文件。
我们修改 entrypoint[15] 脚本,在容器文件系统上安装正确的 BTF 文件,使对应的工具都能运行。Inspektor 工具被设计成总是在容器中运行,因此我们可以将 BTF 文件安装在系统路径(/boot/vmlinux-$(uname -r)
),而不影响主机。通过这样做,我们还可以避免修改不同的 BCC 工具的源代码(就像我们在上面的例子中做的那样):
echo "Kernel provided BTF is not available: Trying shipped BTF files"
SOURCE_BTF=/btfs/$ID/$VERSION_ID/$ARCH/$KERNEL.btf
if [-f $SOURCE_BTF]; then
objcopy --input binary --output elf64-little --rename-section .data=.BTF $SOURCE_BTF /boot/vmlinux-$KERNEL
echo "shipped BTF available. Installed at /boot/vmlinux-$KERNEL"
else
...
PR 完整实现参见 inspektor-gadget/pull/387[16] 。
Tracee[17] 是用于 Linux 的运行时安全和取证工具。这里,生成的 BTF 文件可被嵌入到应用程序的二进制文件中。Makefile 有一个 btfhub[18] 目标,然后调用 btfhub.sh[19]。脚本克隆 BTFHub 仓库,并调用[20] btfgen.sh 来生成 BTF 文件。这些文件被移到 ./dist/btfhub
目录中。
# generate tailored BTFs
[ ! -f ./tools/btfgen.sh ] && die "could not find btfgen.sh"
./tools/btfgen.sh -a ${ARCH} -o $TRACEE_BPF_CORE
# move tailored BTFs to dist
[ ! -d ${BASEDIR}/dist ] && die "could not find dist directory"
[ ! -d ${BASEDIR}/dist/btfhub ] && mkdir ${BASEDIR}/dist/btfhub
rm -rf ${BASEDIR}/dist/btfhub/*
mv ./custom-archive/* ${BASEDIR}/dist/btfhub
然后,使用 go:embed
[21]指令[22]将 BTF 文件嵌入到 Go 二进制中。
//go:build ebpf
// +build ebpf
package tracee
import (
"embed"
)
//go:embed "dist/tracee.bpf.core.o"
//go:embed "dist/btfhub/*"
var BPFBundleInjected embed.FS
在运行时,当前内核的对应的 BTF 文件被解压[23],其路径传递[24]给 libbpf-go,用于 CO-RE 重定位。
内核中的 BTF 支持不仅仅是关于导出 BTF 类型。部分 eBPF 程序如 fentry/fexit 和 LSM 钩子需要内核导出 BTF 信息。这些程序将不能使用 BTFGen,唯一的选择是启用 CONFIG_DEBUG_INFO_BTF
的内核。
当然,我们知道 BTFGen 是一个临时的解决方案,直到大多数系统更新到默认导出 BTF 信息的内核版本。然而,我们认为这需要几年的时间,在这期间,BTFGen 可以帮助填补这一空白。
以下是我们可以近期考虑的一些改进。
部分项目如 BCC 及其基于 libbpf 的工具都可以与 BTFGen 整合获益。我们提交了一个 PR[25],通过使用 BTFGen 使上述工具可以在更多的 Linux 发行版中使用。
eBPF 程序通常访问很少的内核类型,因此,两个不同的内核版本生成的文件很有可能是相同的,这对于同一 Linux 发行版的小版本内核来说尤其如此。对 BTFGen 的进一步改进是基于此,通过使用符号链接或类似的方法来避免创建重复的文件。
这也可以直接在 BTFHub 上进行,因为有些源 BTF 文件是重复的,就像这个[26]问题中所指出的那样,但即使在这种情况下,出现重复文件的机会还是较低。
BTFHub 仓库体积很大,而且由于新内核的发布,它的规模还在不断增加。Seekret 创建了一个 API[27],使用 BTFGen 和 BTFHub 为用户提供的 eBPF 对象按需生成 "精简版" BTF 文件。
如果你想了解更多关于 eBPF、BTF、CO-RE、BTFHub 和 BTFGen 的信息,以下资料无疑是优秀的参考:
功能从已经存在的项目中获得了灵感,并由不同的公司联合实现。
首先,我们要感谢 Aqua Security 团队在 BTFHub 上所做的出色工作,这是我们的基础项目。
其次,我们要感谢在这个功能的开发过程中做出贡献的人员。Aqua Security 的 Rafael David Tinoco 和 Elastic 的 Lorenzo Fontana 和 Leonardo Di Donato。
最后,libbpf 的维护者 Andrii Nakryiko 和 Alexei Starovoitov 以及 bpftool 的维护者 Quentin Monnet,他们为实现该功能提供了大量宝贵的反馈和指导。
原文地址: https://kinvolk.io/blog/2022/03/btfgen-one-step-closer-to-truly-portable-ebpf-programs/
[1]task_struct: https://github.com/torvalds/linux/blob/v5.16/include/linux/sched.h#L723
[2]BCC: https://github.com/iovisor/bcc/
[3]BPF CO-RE (Compile Once - Run Everywhere): https://nakryiko.com/posts/bpf-portability-and-co-re
[4]在 Linux 内核 5.2: https://github.com/torvalds/linux/commit/e83b9f55448afce3fe1abcd1d10db9584f8042a6
[5]BTFHub: https://github.com/aquasecurity/btfhub
[6]基于 CO-RE: https://nakryiko.com/posts/bpf-core-reference-guide/
[7]这个: https://github.com/aquasecurity/btfhub/blob/main/docs/btfgen-internals.md
[8]补丁: https://lore.kernel.org/bpf/164503621150.2935.6634904664671748900.git-patchwork-notify@kernel.org/T/#mdd100ccbc95947c8fe6be74db66002e273a29abd
[9]BCC libbpf-tools: https://github.com/iovisor/bcc/tree/v0.24.0/libbpf-tools
[10]约定目录中: https://github.com/libbpf/libbpf/blob/22411acc4b2c846868fd570b2d9f3b016d2af2cb/src/btf.c#L4631-L4639
[11]vagrant-sshfs
: https://github.com/dustymabe/vagrant-sshfs
[12]Inspektor Gadget: https://github.com/kinvolk/inspektor-gadget
[13]步骤: https://github.com/kinvolk/inspektor-gadget/blob/v0.4.2/gadget.Dockerfile#L42-L46
[14]btfgen.sh: https://github.com/kinvolk/inspektor-gadget/blob/v0.4.2/tools/btfgen.sh
[15]entrypoint: https://github.com/kinvolk/inspektor-gadget/blob/v0.4.2/gadget-container/entrypoint.sh#L149-L154
[16]inspektor-gadget/pull/387: https://github.com/kinvolk/inspektor-gadget/pull/387
[17]Tracee: https://github.com/aquasecurity/tracee
[18]btfhub: https://github.com/aquasecurity/tracee/blob/add1efa7934dcf46be67ea2be54ac0d139a94804/Makefile.one#L507
[19]btfhub.sh: https://github.com/aquasecurity/tracee/blob/add1efa7934dcf46be67ea2be54ac0d139a94804/3rdparty/btfhub.sh#L1
[20]调用: https://github.com/aquasecurity/tracee/blob/add1efa7934dcf46be67ea2be54ac0d139a94804/3rdparty/btfhub.sh#L112
[21]go:embed
: https://pkg.go.dev/embed
[22]指令: https://github.com/aquasecurity/tracee/blob/add1efa7934dcf46be67ea2be54ac0d139a94804/embedded-ebpf.go#L11
[23]解压: https://github.com/aquasecurity/tracee/blob/add1efa7934dcf46be67ea2be54ac0d139a94804/cmd/tracee-ebpf/main.go#L367
[24]传递: https://github.com/aquasecurity/tracee/blob/add1efa7934dcf46be67ea2be54ac0d139a94804/cmd/tracee-ebpf/main.go#L373
[25]PR: https://github.com/iovisor/bcc/pull/3889
[26]这个: https://github.com/aquasecurity/btfhub/issues/17
[27]API: https://github.com/seek-ret/btfhub-online
[28]BPF CO-RE 参考指南: https://nakryiko.com/posts/bpf-core-reference-guide/
[29]BPF CO-RE (Compile Once - Run Everywhere): https://nakryiko.com/posts/bpf-portability-and-co-re/
[30]eBPF BTF 生成器:通往真正的可移植 CO-RE eBPF 程序之路: https://github.com/aquasecurity/btfhub/blob/main/docs/btfgen-internals.md
[31]BPF 类型格式(BTF): https://www.kernel.org/doc/html/latest/bpf/btf.html
Copyright© 2013-2020
All Rights Reserved 京ICP备2023019179号-8