eBPF 验证器中的 func_info 是什么?

what's func_info in eBPF verifier?

我正在开发 XDP 程序,但在尝试将其安装到 NIC 驱动程序时遇到此错误:

libbpf: failed to guess program type based on ELF section name '.text'
libbpf: supported section(type) names are: socket kprobe/ uprobe/ kretprobe/ uretprobe/ classifier action tracepoint/ tp/ raw_tracepoint/ raw_tp/ tp_btf/ xdp perf_event lwt_in lwt_out lwt_xmit lwt_seg6local cgroup_skb/ingress cgroup_skb/egress cgroup/skb cgroup/sock cgroup/post_bind4 cgroup/post_bind6 cgroup/dev sockops sk_skb/stream_parser sk_skb/stream_verdict sk_skb sk_msg lirc_mode2 flow_dissector cgroup/bind4 cgroup/bind6 cgroup/connect4 cgroup/connect6 cgroup/sendmsg4 cgroup/sendmsg6 cgroup/recvmsg4 cgroup/recvmsg6 cgroup/sysctl cgroup/getsockopt cgroup/setsockopt
libbpf: load bpf program failed: Invalid argument
libbpf: -- BEGIN DUMP LOG ---
libbpf: 
number of funcs in func_info doesn't match number of subprogs
processed 0 insns (limit 1000000) max_states_per_insn 0 total_states 0 peak_states 0 mark_read 0
libbpf: -- END LOG --
libbpf: failed to load program '.text'

我搜索并发现当 eBPF 验证器尝试比较 attr->func_info_cntenv->subprog_cnt 时出现错误,但我不明白这两个值在验证器处理之前是如何设置的。我有一个 XDP 程序,其中包含一个部分和 6 个函数作为助手,我不确定此信息是否有帮助,但如果需要,我可以提供有关程序结构的更多信息。

您是否忘记将您的程序放在专门的 ELF 部分?类似于:

SEC("xdp")
int my_prog(struct xdp_md *ctx)
{
        ...
}

(其中SEC()是libbpf的bpf_helpers.hheader中定义的宏。)

如果您没有指定任何 ELF 部分名称,clang/LLVM 默认为 .text,如您的错误消息所示。当您尝试使用 libbpf 加载程序时,库通常会根据程序所在的 ELF 部分的名称来猜测程序类型。如果您不使用专用的节名称,并且不以其他方式指定程序类型(例如,在 libbpf 中使用 bpf_program__set_type()),则 libbpf 无法为您的程序选择相关类型。

这可能会导致您的某些程序无法加载。从上面的错误消息来看,您似乎在程序中使用了函数调用(而不是声明,例如,您的函数为 static inline)。当您的主程序通过验证器时,某些部分将丢失:“功能”可能未加载,因此验证器抱怨从主程序(env->subprog_cnt)推断出的 functions/subprograms 的预期数量是不同于加载程序应用程序 (attr->func_info_cnt) 收集的函数数量,并在使用 bpf() 系统调用加载程序时传递给内核。

如果是这种情况,您可以通过将您的代码放在专用的 ELF 函数中,或者将您的函数声明为 static inline 如果您不需要在生成的字节码中调用函数。