libbpf: Ошибка загрузки раздела ELF .BTF: 0

Я получил это сообщение об ошибке в Ubuntu 19.04, когда я пытаюсь выполнить sudo ./mineonlyret, которая является программой пользовательского пространства, которая загружает программу 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

person Maicake    schedule 18.11.2019    source источник
comment
Возможно, это связано с разницей версий clang между двумя вашими машинами? Какие версии вы используете? Что касается общей библиотеки, какую ошибку вы получаете? И какую версию libbpf вы используете?   -  person Qeole    schedule 18.11.2019
comment
UBUNTU: 18.04 clang версии 6.0.0-1ubuntu2 (теги/RELEASE_600/final) libbpf Я думаю, 0.0.3 (я git клонировал репозиторий до октября) UBUNTU: 19.04 clang версии 8.0.0-3 (теги/RELEASE_800/final) libbpf Я думаю, что 0.0.5 (вчера я клонировал репозиторий). Когда я запускаю gcc -o mineonlyret mineonlyret_user.c -I../libbpf/src -L ../libbpf/src/ -lbpf, кажется, компилируется нормально. Но когда я запускаю программу ./mineonlyret, я получаю сообщение об ошибке: ошибка при загрузке общих библиотек: libbpf.so.0: невозможно открыть общий объектный файл: нет такого файла или каталога (ошибка не отображается, если я компилирую с .a   -  person Maicake    schedule 18.11.2019
comment
Исправление ошибок: в UBUNTU 18.04 у меня есть libbpf 0.0.4, потому что он содержит определение btf__parse_elf   -  person Maicake    schedule 18.11.2019
comment
Что касается общей библиотеки: похоже, ваша система не может найти общую библиотеку. Вы скомпилировали libbpf.so и установили его в своей системе? Если да, то находится ли он в месте, ожидаемом вашим двоичным файлом (ldd mineonlyret)? Это в вашем кеше ldconfig (ldconfig -p)?   -  person Qeole    schedule 18.11.2019
comment
Не уверен в вашей ошибке libbpf ELF/BTF. Вероятно, это вопрос совместимости между версиями clang и libbpf, потому что он срабатывает, когда библиотека анализирует ваш объектный файл, прежде чем данные будут фактически отправлены в ядро ​​(поэтому оно не зависит от ядра или версии Ubuntu). Но кроме этого я не уверен. Попробуйте старый libbpf или более новый clang, мой совет.   -  person Qeole    schedule 18.11.2019
comment
На ubuntu 19.04 пробовал все комбинации, например clang 8.0.0 и libbpf 0.3, 0.4, 0.5 — всегда одна и та же ошибка. Затем я попытался использовать clang 6.0.0 (как я делал в Ubuntu 18.04) с libbpf 0.3, 0.4, 05. Я всегда получал одну и ту же ошибку. В случае clang 6.0.0 и libbpf 0.3 сообщение немного отличается libbpf: Ошибка загрузки раздела ELF .BTF: -22. Игнорировать и продолжать. Я не понимаю, могу ли я игнорировать эту ошибку, поскольку из определения BTF BTF (формат типа BPF) — это формат метаданных, который кодирует отладочную информацию, связанную с программой/картой BPF.   -  person Maicake    schedule 19.11.2019
comment
Вы, скорее всего, можете игнорировать ошибку, если libbpf может продолжать работу, BTF предназначен для отладки. См. пример. Используйте флаг -g с clang (v8+) при компиляции, если вы хотите BTF. Также вы пытались удалить флаг -S, это что-то меняет? Я думал попробовать более новую версию clang (см. репозиторий LLVM APT), а не более старую, если у вас есть возможность.   -  person Qeole    schedule 20.11.2019


Ответы (1)


Вам нужно указать -g, чтобы запросить у Clang генерацию .BTF (он также будет генерировать отладочную информацию DWARF, но вы можете игнорировать или удалить ее, она не используется libbpf). Хотя .BTF изначально использовался как необязательная дополнительная информация для лучшей отладки и дампов сборки BPF, он превратился в довольно необходимую часть современного приложения BPF (по крайней мере, тех, которые используют libbpf), поэтому убедитесь, что у вас всегда есть '-g' указано.

person Andrii Nakryiko    schedule 28.09.2020