You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义kfunc加载BPF程序失败:找不到foo_bar的BTF符号

问题分析与修复方案

报错原因

libbpf: failed to find BTF for extern 'foo_bar': -3 报错源于两个核心问题:

  • BPF程序未标记kfunc引用:默认情况下libbpf会将extern符号视为普通内核符号,仅在vmlinux的BTF中查找,不会识别为自定义kfunc。
  • kfunc注册的程序类型不匹配:你的BPF程序是uretprobe(属于BPF_PROG_TYPE_UPROBE类型),但内核模块中却将kfunc注册给了BPF_PROG_TYPE_KPROBE类型,导致UPROBE程序无法访问该kfunc。

修复步骤

1. 修改BPF程序(foo_bpf.c)

在extern声明中添加__attribute__((btf_decl_tag("bpf_kfunc"))),明确标记这是一个kfunc,让libbpf知道要从kfunc集合中查找:

#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include <asm/ptrace.h>

// 添加btf_decl_tag标记,指定为kfunc
extern int foo_bar(struct pt_regs *regs) __attribute__((btf_decl_tag("bpf_kfunc")));

SEC("uretprobe//tmp/app:foo")
int foo_bar_call(struct pt_regs *ctx) {
    foo_bar(ctx);
    return 0;
}

char _license[] SEC("license") = "GPL";

2. 修改内核模块(kfoo.c)

将register_btf_kfunc_id_set的第一个参数改为BPF_PROG_TYPE_UPROBE,与你的uretprobe程序类型匹配:

static int __init kfoo_init(void)
{
    int ret;
    // 替换为BPF_PROG_TYPE_UPROBE,对应uretprobe程序类型
    ret = register_btf_kfunc_id_set(BPF_PROG_TYPE_UPROBE, &foo_bar_set);

    pr_err("%s: %d\n", __func__, ret);
    return ret;
}

3. 重新编译加载

执行以下命令完成重新编译与加载:

# 清理并重新编译内核模块
make clean && make
# 卸载旧模块(若已加载)
sudo rmmod kfoo
# 加载新模块
sudo insmod kfoo.ko
# 重新编译BPF程序
clang -Wall -Werror -O2 -target bpf -c foo_bpf.c -o foo_bpf.o
# 加载BPF程序
sudo bpftool prog load foo_bpf.o /sys/fs/bpf/foo_bpf autoattach

验证

加载成功后,运行/tmp/app触发uretprobe,通过dmesg或journalctl -k查看内核日志,应该能看到foo_bar的打印信息。

内容的提问来源于stack exchange,提问作者Sławek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 11:13:16