libbpf: 加载 ELF section .BTF 时出错:0

4

当我尝试执行sudo ./mineonlyret时,我的ubuntu 19.04系统出现了以下错误信息。这个程序是用户空间程序,用于加载一个ebpf程序,下面将进行描述。在ubuntu 18.04上,我尝试了相同的配置,没有出现错误。哪些原因可能导致此错误?如果需要更多细节,请告知。

libbpf: Error loading ELF section .BTF: 0.

mineonlyret_user.c

// SPDX-License-Identifier: GPL-2.0
#include <stdio.h>
#include <assert.h>
#include <linux/bpf.h>
#include "libbpf.h"
#include <unistd.h>
#include <arpa/inet.h>
#include <linux/if_ether.h>

int main(int ac, char **argv)
{
    int sock, prog_fd;
    struct bpf_object *obj;
    char filename[256];

    if (bpf_prog_load("mineonlyret_kern.o", BPF_PROG_TYPE_SOCKET_FILTER,
              &obj, &prog_fd))
        return 1;

    /* open up a packet socket */
    sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));  
    if(sock < 0){
        printf("socket");
        return -1;
    }

    /* attach the filter */
    assert(setsockopt(sock, SOL_SOCKET, SO_ATTACH_BPF, &prog_fd,
              sizeof(prog_fd)) == 0);

    int i;
        char buf[65535];
    for (i = 0; i < 5; i++) {
        printf("ci\n");
            int res = recvfrom(sock, buf, sizeof(buf), 0, NULL, 0);
            printf("res=%d\n", res);

        sleep(5);
    }

    return 0;
}

mineonlyret_kern.c

#include <linux/bpf.h>
#include <linux/if_ether.h>
#include <linux/if_packet.h>
#include <linux/ip.h>
#include <linux/udp.h>
#include <linux/in.h>
#include "bpf_helpers.h"
#include <stddef.h>
SEC("socket")
int bpf_sk_prog(struct __sk_buff *skb)
{

        return 0;

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

我使用以下命令编译_kern.c:

clang -S -I. -O2 -emit-llvm -c mineonlyret_kern.c -o - | llc -march=bpf -filetype=obj -o mineonlyret_kern.o

和 _user.c 一起使用

gcc  -o mineonlyret mineonlyret_user.c -I../libbpf/src/  ../libbpf/src/libbpf.a -lelf

此外,我还有另一个疑问:为什么如果我使用库的共享版本,它就无法工作?我的意思是如果我执行...
gcc  -o mineonlyret mineonlyret_user.c -I../libbpf/src/  -L../libbpf/src/ -lbpf

目录树

.
├── libbpf
│   ├── include
│   ├── src
│   │   ├── libbpf.so
│   │   └── libbpf.a
└── libbpfebpf
    |── mineonlyret_user.c
    |── mineonlyret_kern.c

2
这可能是由于您的两台机器之间clang版本的差异引起的,也许?您使用哪些版本?关于共享库,您遇到了什么错误?还有您使用的libbpf版本是什么? - Qeole
UBUNTU: 18.04 clang版本6.0.0-1ubuntu2(tags/RELEASE_600/final) libbpf我认为是0.0.3(我在十月之前克隆了存储库) UBUNTU: 19.04 clang版本8.0.0-3(tags/RELEASE_800/final) libbpf我认为是0.0.5(我昨天克隆了存储库)当我执行gcc -o mineonlyret mineonlyret_user.c -I../libbpf/src -L ../libbpf/src/ -lbpf时,似乎编译正常。但是当我执行程序./mineonlyret时,出现错误:error while loading shared libraries: libbpf.so.0: cannot open shared object file: No such file or directory(如果使用.a编译,则不会显示错误)。 - Maicake
1
对于共享库的问题:看起来您的系统无法找到共享库。您是否已经编译了 libbpf.so 并将其安装在系统上?如果是,那么它是否位于二进制文件所期望的位置 (ldd mineonlyret)? 是否在 ldconfig 缓存中 (ldconfig -p)? - Qeole
1
不确定您的libbpf ELF/BTF错误。这可能是clang和libbpf版本之间的兼容性问题,因为它会在库解析对象文件时触发,而在数据实际发送到内核之前(因此与内核或Ubuntu版本无关)。但除此之外,我不确定。我的建议是尝试使用旧版libbpf或更新的clang。 - Qeole
1
如果libbpf可以继续,那么您很可能可以忽略该错误,BTF是用于调试的。请参见示例。如果要使用BTF,请在编译时使用clang(v8+)的-g标志。另外,您尝试过删除-S标志吗?这会改变什么吗?如果有可能,我建议您尝试使用更新版本的clang(请参见LLVM APT repo)。 - Qeole
显示剩余2条评论
1个回答

5

您需要指定-g以请求Clang生成.BTF(它也将生成DWARF调试信息,但您可以忽略或剥离它,因为libbpf不使用它)。虽然.BTF最初是用于更好的调试和BPF汇编转储的可选额外信息,但它变成了现代BPF应用程序(至少是那些使用libbpf的应用程序)的一个几乎必需的部分,因此请确保您始终指定'-g'。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接