eBPF程序加载失败:handle_execveat符号未解析求助
问题原因排查与解决方案
核心原因分析
这个错误本质是eBPF程序编译/加载阶段生成的字节码引用了内核中不存在的handle_execveat符号,触发点是你在read_dentry_strings里混用bpf_probe_read_str与BPF_CORE_READ(curr_dtry, d_name.name)的写法,具体诱因有两点:
CO-RE宏与传统读取函数的冲突
BPF_CORE_READ是CO-RE(一次编译、多版本运行)专用宏,会自动处理内核结构体字段的偏移重定位;而bpf_probe_read_str是老版本的字符串读取辅助函数,二者混用后,编译器可能生成意外的代码路径,错误引入对handle_execveat的依赖——这个符号仅在特定内核版本或tracepoint上下文存在,你的环境内核未导出该符号,导致加载失败。冗余且风险的字符串读取逻辑
读取dentry的d_name.name时,用BPF_CORE_READ获取指针后再传给bpf_probe_read_str是冗余操作,这种写法会让编译器误解为需要调用额外的内核辅助函数(比如handle_execveat)来完成读取,进而引入未定义符号。
修复方案
替换为CO-RE原生的字符串读取宏BPF_CORE_READ_STR,这是专门适配CO-RE场景的安全读取方式,不会引入不必要的符号依赖:
// 替换原有的bpf_probe_read_str调用 BPF_CORE_READ_STR(&buf[i], DEFAULT_SUB_BUF_SIZE, curr_dtry, d_name.name);
如果你的内核版本低于5.15(不支持BPF_CORE_READ_STR),也可以改用内核空间字符串读取函数,直接传入BPF_CORE_READ获取的指针:
char *name_ptr = BPF_CORE_READ(curr_dtry, d_name.name); bpf_probe_read_kernel_str(buf[i], DEFAULT_SUB_BUF_SIZE, name_ptr);
额外验证点
- 检查内核版本:执行
uname -r确认,低于5.8的版本CO-RE支持有限,可能需要调整编译选项或改用非CO-RE写法。 - 更新ebpf2go工具:旧版本工具对CO-RE宏的处理存在bug,可能导致错误引入未定义符号,建议使用最新版。
内容的提问来源于stack exchange,提问作者SPinSO
相关产品推荐
相关产品推荐

