显然,编译器将所有内容连接在同一节中(我简化了
bpf_main
进行编译和测试)。
$ readelf -x sockops bpf_prog.o
Hex dump of section 'sockops':
0x00000000 b7000000 01000000 95000000 00000000 ................
0x00000010 b7000000 01000000 95000000 00000000 ................
0x00000020 b7000000 01000000 95000000 00000000 ................
0x00000030 b7000000 00000000 95000000 00000000 ...............
从这里,我看不出您以后打算如何检索各个程序以正确加载它们。通常,用户空间工具从一个节中获取一个程序,并尝试通过将指令通过
bpf()
系统调用;在这里,您使用的任何程序都可能试图同时加载连接的四个程序。
您希望所有程序在节中使用相同的名称,有什么特别的原因吗?
我不知道LLVM对这种事情的警告。我想不是:人们可能有理由在一个部分中放不同的东西。这里的例子是针对BPF的,我认为人们通常不会试图将几个程序放在同一个部分中。但这只是猜测,我可能错了。
关于您的更新:
我不认为在不同的对象文件中使用类似的节名称是一个问题。只要您的用户空间工具能够从对象文件中检索程序并执行重新定位,它就应该可以正常工作。内核无论如何看不到任何节名。从
attr
参数是一组指令:
struct { /* anonymous struct used by BPF_PROG_LOAD command */
__u32 prog_type; /* one of enum bpf_prog_type */
__u32 insn_cnt;
__aligned_u64 insns;
__aligned_u64 license;
__u32 log_level; /* verbosity level of verifier */
__u32 log_size; /* size of user buffer */
__aligned_u64 log_buf; /* user supplied buffer */
__u32 kern_version; /* checked when prog_type=kprobe */
__u32 prog_flags;
char prog_name[BPF_OBJ_NAME_LEN];
__u32 prog_ifindex; /* ifindex of netdev to prep for */
};
(来自
include/uapi/linux/bpf.h
,请注意
insns
属性)。对于tail调用,您的用户空间代码还需要创建特定的映射,这些映射包含要跳转到的程序(更多
bpf()
电话)。但是,从ELF文件中提取信息完全是用户空间的责任。我认为Libbpf应该能够正确处理它,但我还没有尝试过。
需要补充说明的是:我不知道您的用例到底是什么,但由于您正试图在不同的对象文件中编译代码并使用调用,您可能有兴趣了解eBPF现在支持函数调用,即您可以定义几个(非内联)函数,可能在几个ELF文件中,并在程序中调用它们。更多信息
in the cover letter
. 再一次,到目前为止,我还没有时间进行实验。