升级内核至6.8.0-48-generic后eBPF程序BTF加载失败求助
问题分析与解决思路
核心原因
升级到6.8.0-48-generic内核后出现libbpf: failed to find valid kernel BTF错误,通常和以下几点相关:
- libbpf的BTF查找逻辑:libbpf会优先尝试从
/boot/vmlinux-<内核版本>读取BTF,但Ubuntu默认不把未压缩的vmlinux镜像放到/boot目录,导致查找失败;即使/sys/kernel/btf/vmlinux存在,libbpf的 fallback 逻辑可能因验证问题无法正常使用该文件。 - BTF完整性或兼容性:部分Ubuntu内核包的BTF可能存在缺失,或系统安装的libbpf版本较旧,无法兼容6.8内核的BTF格式。
- 双启动环境的潜在影响:grub2win的启动配置可能间接影响内核BTF的加载(概率较低,因为
/sys/kernel/btf/vmlinux已存在)。
具体解决步骤
1. 强制指定BTF路径给libbpf
修改用户态代码execve_user.c,在加载eBPF对象时手动指定BTF文件路径,绕过libbpf的自动查找逻辑:
#include <bpf/libbpf.h> // 在加载对象前添加以下配置 LIBBPF_OPTS(bpf_object_open_opts, open_opts, .btf_path = "/sys/kernel/btf/vmlinux", // 直接指向系统提供的BTF文件 ); // 替换原有的bpf_object__open_file调用 struct bpf_object *obj = bpf_object__open_file("execve.bpf.o", &open_opts); if (!obj) { fprintf(stderr, "Failed to open BPF object\n"); return 1; }
重新编译运行:
make clean && make sudo ./execve_user
2. 生成完整vmlinux镜像到/boot
如果不想修改代码,可以手动生成未压缩的vmlinux镜像到/boot,满足libbpf的查找需求:
- 安装提取工具:
sudo apt install linux-tools-common
- 从压缩的vmlinuz提取vmlinux:
sudo extract-vmlinux /boot/vmlinuz-$(uname -r) > /boot/vmlinux-$(uname -r) sudo chmod 644 /boot/vmlinux-$(uname -r)
- 重新运行程序,libbpf会自动找到该文件并读取BTF。
3. 验证BTF完整性并更新依赖
- 检查BTF是否正常可用:
sudo bpftool btf dump file /sys/kernel/btf/vmlinux | head -20
如果能正常输出结构体定义,说明BTF本身有效;若报错则重新安装内核包:
sudo apt reinstall linux-image-$(uname -r) linux-headers-$(uname -r)
- 更新pahole和libbpf到最新版本:
sudo apt update && sudo apt install --only-upgrade pahole libbpf-dev
若系统库版本过旧,可从源码编译最新libbpf:
git clone https://github.com/libbpf/libbpf.git cd libbpf/src make && sudo make install sudo ldconfig
之后重新编译你的eBPF项目。
4. 检查内核配置
确认内核开启了BTF支持:
cat /boot/config-$(uname -r) | grep CONFIG_DEBUG_INFO_BTF
输出应为CONFIG_DEBUG_INFO_BTF=y,若为m则需加载对应的模块:
sudo modprobe btf
内容的提问来源于stack exchange,提问作者KnightChaser
相关产品推荐
相关产品推荐

