libbpf 开发指南:获取bpf_object 关联的 BTF(BPF Type Format)信息与文件描述符

文章详细介绍了如何通过libbpf库获取BPF_object的BTF信息,包括BTF类型数量和文件描述符。提供了函数原型、代码示例以及Makefile和CMakeLists.txt配置,展示了如何在C程序中加载BPF对象并利用bpf_object__btf和bpf_object__btf_fd函数获取BTF数据。BTF对于理解和调试eBPF程序至关重要,因为它提供了类型和数据结构的信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

获取给定的 bpf_object 关联的 BTF(BPF Type Format)信息

函数原型与解释

代码demo

makefile

cmake

期望输出

获取给定的 bpf_object 关联的 BTF 文件描述符

函数原型与解释

代码demo

makefile

cmake

期望输出


获取给定的 bpf_object 关联的 BTF(BPF Type Format)信息

函数原型与解释

LIBBPF_API struct btf *bpf_object__btf(const struct bpf_object *obj);

参数解释:

  • obj:要获取其关联 BTF 信息的 bpf_object 实例。

返回值:

  • 返回一个指向 btf 结构的指针,该结构包含了与 bpf_object 关联的 BTF 信息。如果没有可用的 BTF 信息,返回 NULL。

代码demo

#include <bpf/bpf_helpers.h>
#include <linux/bpf.h>

struct data {
    int key;
    int value;
};

SEC("maps")
struct bpf_map_def data_map = {
    .type = BPF_MAP_TYPE_HASH,
    .key_size = sizeof(int),
    .value_size = sizeof(struct data),
    .max_entries = 128,
};

SEC("kprobe/__x64_sys_getpid")
int bpf_prog1(struct pt_regs *ctx) {
    return 0;
}

char _license[] SEC("license") = "GPL";
#include <stdio.h>
#include <stdlib.h>
#include <bpf/libbpf.h>
#include <bpf/btf.h>

int main() {
    struct bpf_object *bpf_obj;
    struct btf *btf_info;

    // 加载 BPF 程序
    bpf_obj = bpf_object__open("prog.o");
    if (libbpf_get_error(bpf_obj)) {
        fprintf(stderr, "Error opening BPF object: %d\n", libbpf_get_error(bpf_obj));
        return 1;
    }

    // 获取 BPF 对象的 BTF 信息
    btf_info = bpf_object__btf(bpf_obj);
    if (!btf_info) {
        fprintf(stderr, "No BTF info available for the BPF object\n");
        bpf_object__close(bpf_obj);
        return 1;
    }

    // 获取 BTF 类型数量
    int type_count = btf__get_nr_types(btf_info);
    printf("Number of BTF types: %d\n", type_count);

    // 关闭 BPF 对象
    bpf_object__close(bpf_obj);

    return 0;
}

makefile

CC = gcc
CLANG = clang
CFLAGS = -Wall -I/usr/include/bpf
LDFLAGS = -lbpf

BPF_TARGET = prog.o
BPF_SRC = prog.c

BTF_TARGET = get_btf
BTF_SRC = get_btf.c

all: $(BPF_TARGET) $(BTF_TARGET)

$(BPF_TARGET): $(BPF_SRC)
	$(CLANG) -O2 -target bpf -g -c $(BPF_SRC) -o $(BPF_TARGET)

$(BTF_TARGET): $(BTF_SRC)
	$(CC) $(CFLAGS) $(BTF_SRC) -o $(BTF_TARGET) $(LDFLAGS)

clean:
	rm -f $(BPF_TARGET) $(BTF_TARGET)

.PHONY: all clean

cmake

cmake_minimum_required(VERSION 3.10)
project(bpf_btf_example)

set(CMAKE_C_STANDARD 99)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")

find_library(LIBBPF libbpf.so REQUIRED)

add_custom_command(
    OUTPUT prog.o
    COMMAND clang -O2 -target bpf -g -c ${CMAKE_CURRENT_SOURCE_DIR}/prog.c -o prog.o
    DEPENDS prog.c
    VERBATIM
)

add_custom_target(
    prog_bpf
    DEPENDS prog.o
)

add_executable(get_btf get_btf.c)
target_link_libraries(get_btf ${LIBBPF})
target_include_directories(get_btf PUBLIC /usr/include/bpf)

期望输出

在上述示例中,get_object_name 程序加载 BPF 对象(prog.o),然后使用 bpf_object__name 函数获取其名称。输出为以下内容:

Number of BTF types: 7

BTF(BPF Type Format)是一种类型和数据格式,用于在 eBPF 程序之间共享类型和数据结构信息。BTF 类型数量表示 BPF 程序中的不同数据类型和结构的数量。在我们的示例中,Number of BTF types: 7 表示 BPF 程序中有 7 个不同的类型和结构。

这些类型可以包括:

  1. 基本类型(如 int)
  2. 结构体(如示例中的 struct data)
  3. 枚举
  4. 函数指针等

这个数量是通过分析 BPF 程序中的类型和数据结构计算出来的。BTF 类型数量有助于了解 BPF 程序中的类型复杂性。请注意,这个数字可能因不同的 BPF 程序和环境而变化。

在我们的示例中,打印的 BTF 类型数量 7 是根据示例 BPF 程序中的数据类型和结构得出的。这个数字对于演示如何使用 bpf_object__btf 函数从 BPF 对象获取 BTF 信息来说是次要的,关键是理解如何使用这个 API 函数。

获取给定的 bpf_object 关联的 BTF 文件描述符

函数原型与解释

LIBBPF_API int bpf_object__btf_fd(const struct bpf_object *obj);

参数解释:

  • obj:要获取其关联 BTF 文件描述符的 bpf_object 实例。

返回值:

  • 返回一个正整数,表示与 bpf_object 关联的 BTF 文件描述符。如果没有可用的 BTF 文件描述符,返回 -1。

代码demo

#include <bpf/bpf_helpers.h>
#include <linux/bpf.h>

struct data {
    int key;
    int value;
};

SEC("maps")
struct bpf_map_def data_map = {
    .type = BPF_MAP_TYPE_HASH,
    .key_size = sizeof(int),
    .value_size = sizeof(struct data),
    .max_entries = 128,
};

SEC("kprobe/__x64_sys_getpid")
int bpf_prog1(struct pt_regs *ctx) {
    return 0;
}

char _license[] SEC("license") = "GPL";
#include <stdio.h>
#include <stdlib.h>
#include <bpf/libbpf.h>
#include <bpf/btf.h>

int main() {
    struct bpf_object *bpf_obj;
    int btf_fd;

    // 加载 BPF 程序
    bpf_obj = bpf_object__open("prog.o");
    if (libbpf_get_error(bpf_obj)) {
        fprintf(stderr, "Error opening BPF object: %d\n", libbpf_get_error(bpf_obj));
        return 1;
    }

    // 获取 BPF 对象的 BTF 文件描述符
    btf_fd = bpf_object__btf_fd(bpf_obj);
    if (btf_fd < 0) {
        fprintf(stderr, "No BTF file descriptor available for the BPF object\n");
        bpf_object__close(bpf_obj);
        return 1;
    }

    printf("BTF file descriptor: %d\n", btf_fd);

    // 关闭 BPF 对象
    bpf_object__close(bpf_obj);

    return 0;
}

makefile

CC = gcc
CLANG = clang
CFLAGS = -Wall -I/usr/include/bpf
LDFLAGS = -lbpf

BPF_TARGET = prog.o
BPF_SRC = prog.c

BTF_FD_TARGET = get_btf_fd
BTF_FD_SRC = get_btf_fd.c

all: $(BPF_TARGET) $(BTF_FD_TARGET)

$(BPF_TARGET): $(BPF_SRC)
	$(CLANG) -O2 -target bpf -g -c $(BPF_SRC) -o $(BPF_TARGET)

$(BTF_FD_TARGET): $(BTF_FD_SRC)
	$(CC) $(CFLAGS) $(BTF_FD_SRC) -o $(BTF_FD_TARGET) $(LDFLAGS)

clean:
	rm -f $(BPF_TARGET) $(BTF_FD_TARGET)

.PHONY: all clean

cmake

cmake_minimum_required(VERSION 3.10)
project(bpf_btf_fd_example)

set(CMAKE_C_STANDARD 99)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")

find_library(LIBBPF libbpf.so REQUIRED)

add_custom_command(
    OUTPUT prog.o
    COMMAND clang -O2 -target bpf -g -c ${CMAKE_CURRENT_SOURCE_DIR}/prog.c -o prog.o
    DEPENDS prog.c
    VERBATIM
)

add_custom_target(
    prog_bpf
    DEPENDS prog.o
)

add_executable(get_btf_fd get_btf_fd.c)
target_link_libraries(get_btf_fd ${LIBBPF})
target_include_directories(get_btf_fd PUBLIC /usr/include/bpf)

期望输出

在上述示例中,get_object_name 程序加载 BPF 对象(prog.o),然后使用 bpf_object__name 函数获取其名称。输出为以下内容:

BTF file descriptor: 3

BTF 文件描述符可以用于与 Linux 内核进行通信,以便获取或设置 BTF 信息。例如,通过使用 BTF 文件描述符,您可以查询 BTF 类型信息、加载 BTF 类型信息到内核中,或者使用 BTF 信息来实现更高级的 eBPF 功能,如 CO-RE(Compile Once - Run Everywhere)。

使用上面代码编译出现以下问题:make -C ../../ /root/bpf/linux-4.19.90/samples/bpf/ BPF_SAMPLES_PATH=/root/bpf/linux-4.19.90/samples/bpf make[1]: Entering directory '/root/bpf/linux-4.19.90' CALL scripts/checksyscalls.sh DESCEND objtool make -C /root/bpf/linux-4.19.90/samples/bpf/../../tools/lib/bpf/ RM='rm -rf' LDFLAGS= srctree=/root/bpf/linux-4.19.90/samples/bpf/../../ O= Warning: Kernel ABI header at 'tools/include/uapi/linux/bpf.h' differs from latest version at 'include/uapi/linux/bpf.h' HOSTCC /root/bpf/linux-4.19.90/samples/bpf/xdp_whitelist_user.o /root/bpf/linux-4.19.90/samples/bpf/xdp_whitelist_user.c: In function ‘print_violation’: /root/bpf/linux-4.19.90/samples/bpf/xdp_whitelist_user.c:53:26: warning: implicit declaration of function ‘localtime’; did you mean ‘st_atime’? [-Wimplicit-function-declaration] struct tm *tm_info = localtime(&ts); ^~~~~~~~~ st_atime /root/bpf/linux-4.19.90/samples/bpf/xdp_whitelist_user.c:53:26: warning: initialization makes pointer from integer without a cast [-Wint-conversion] /root/bpf/linux-4.19.90/samples/bpf/xdp_whitelist_user.c:55:5: warning: implicit declaration of function ‘strftime’ [-Wimplicit-function-declaration] strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S", tm_info); ^~~~~~~~ /root/bpf/linux-4.19.90/samples/bpf/xdp_whitelist_user.c:55:5: warning: incompatible implicit declaration of built-in function ‘strftime’ /root/bpf/linux-4.19.90/samples/bpf/xdp_whitelist_user.c:55:5: note: include ‘<time.h>’ or provide a declaration of ‘strftime’ /root/bpf/linux-4.19.90/samples/bpf/xdp_whitelist_user.c: At top level: /root/bpf/linux-4.19.90/samples/bpf/xdp_whitelist_user.c:69:13: warning: function declaration isn’t a prototype [-Wstrict-prototypes] static void read_violations() { ^~~~~~~~~~~~~~~ /root/bpf/linux-4.19.90/samples/bpf/xdp_whitelist_user.c: In function ‘read_violations’: /root/bpf/linux-4.19.90/samples/bpf/xdp_whitelist_user.c:77:12: error: variable ‘attr’ has initializer but incomplete type struct perf_event_attr attr = { ^~~~~~~~~~~~~~~ /root/bpf/linux-4.19.90/samples/bpf/xdp_whitelist_user.c:78:10: error: ‘struct perf_event_attr’ has no member named ‘sample_type’ .sample_type = PERF_SAMPLE_RAW, ^~~~~~~~~~~ /root/bpf/linux-4.19.90/samples/bpf/xdp_whitelist_user.c:78:24: error: ‘PERF_SAMPLE_RAW’ undeclared (first use in this function) .sample_type = PERF_SAMPLE_RAW, ^~~~~~~~~~~~~~~ /root/bpf/linux-4.19.90/samples/bpf/xdp_whitelist_user.c:78:24: note: each undeclared identifier is reported only once for each function it appears in /root/bpf/linux-4.19.90/samples/bpf/xdp_whitelist_user.c:78:24: warning: excess elements in struct initializer /root/bpf/linux-4.19.90/samples/bpf/xdp_whitelist_user.c:78:24: note: (near initialization for ‘attr’) /root/bpf/linux-4.19.90/samples/bpf/xdp_whitelist_user.c:79:10: error: ‘struct perf_event_attr’ has no member named ‘type’ .type = PERF_TYPE_SOFTWARE, ^~~~ /root/bpf/linux-4.19.90/samples/bpf/xdp_whitelist_user.c:79:17: error: ‘PERF_TYPE_SOFTWARE’ undeclared (first use in this function) .type = PERF_TYPE_SOFTWARE, ^~~~~~~~~~~~~~~~~~ /root/bpf/linux-4.19.90/samples/bpf/xdp_whitelist_user.c:79:17: warning: excess elements in struct initializer /root/bpf/linux-4.19.90/samples/bpf/xdp_whitelist_user.c:79:17: note: (near initialization for ‘attr’) /root/bpf/linux-4.19.90/samples/bpf/xdp_whitelist_user.c:80:10: error: ‘struct perf_event_attr’ has no member named ‘config’ .config = PERF_COUNT_SW_BPF_OUTPUT, ^~~~~~ /root/bpf/linux-4.19.90/samples/bpf/xdp_whitelist_user.c:80:19: error: ‘PERF_COUNT_SW_BPF_OUTPUT’ undeclared (first use in this function) .config = PERF_COUNT_SW_BPF_OUTPUT, ^~~~~~~~~~~~~~~~~~~~~~~~ /root/bpf/linux-4.19.90/samples/bpf/xdp_whitelist_user.c:80:19: warning: excess elements in struct initializer /root/bpf/linux-4.19.90/samples/bpf/xdp_whitelist_user.c:80:19: note: (near initialization for ‘attr’) /root/bpf/linux-4.19.90/samples/bpf/xdp_whitelist_user.c:81:10: error: ‘struct perf_event_attr’ has no member named ‘size’ .size = sizeof(attr), ^~~~ /root/bpf/linux-4.19.90/samples/bpf/xdp_whitelist_user.c:81:23: error: invalid application of ‘sizeof’ to incomplete type ‘struct perf_event_attr’ .size = sizeof(attr), ^ /root/bpf/linux-4.19.90/samples/bpf/xdp_whitelist_user.c:81:17: warning: excess elements in struct initializer .size = sizeof(attr), ^~~~~~ /root/bpf/linux-4.19.90/samples/bpf/xdp_whitelist_user.c:81:17: note: (near initialization for ‘attr’) /root/bpf/linux-4.19.90/samples/bpf/xdp_whitelist_user.c:82:10: error: ‘struct perf_event_attr’ has no member named ‘wakeup_events’ .wakeup_events = 1, ^~~~~~~~~~~~~ /root/bpf/linux-4.19.90/samples/bpf/xdp_whitelist_user.c:82:26: warning: excess elements in struct initializer .wakeup_events = 1, ^ /root/bpf/linux-4.19.90/samples/bpf/xdp_whitelist_user.c:82:26: note: (near initialization for ‘attr’) /root/bpf/linux-4.19.90/samples/bpf/xdp_whitelist_user.c:77:28: error: storage size of ‘attr’ isn’t known struct perf_event_attr attr = { ^~~~ /root/bpf/linux-4.19.90/samples/bpf/xdp_whitelist_user.c:85:23: error: ‘__NR_perf_event_open’ undeclared (first use in this function); did you mean ‘bpf_perf_event_ret’? perf_fd = syscall(__NR_perf_event_open, &attr, -1, 0, -1, 0); ^~~~~~~~~~~~~~~~~~~~ bpf_perf_event_ret /root/bpf/linux-4.19.90/samples/bpf/xdp_whitelist_user.c:100:11: warning: implicit declaration of function ‘mmap’ [-Wimplicit-function-declaration] buf = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, perf_fd, 0); ^~~~ /root/bpf/linux-4.19.90/samples/bpf/xdp_whitelist_user.c:100:33: error: ‘PROT_READ’ undeclared (first use in this function); did you mean ‘IPPROTO_RAW’? buf = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, perf_fd, 0); ^~~~~~~~~ IPPROTO_RAW /root/bpf/linux-4.19.90/samples/bpf/xdp_whitelist_user.c:100:45: error: ‘PROT_WRITE’ undeclared (first use in this function); did you mean ‘PROT_READ’? buf = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, perf_fd, 0); ^~~~~~~~~~ PROT_READ /root/bpf/linux-4.19.90/samples/bpf/xdp_whitelist_user.c:100:57: error: ‘MAP_SHARED’ undeclared (first use in this function) buf = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, perf_fd, 0); ^~~~~~~~~~ /root/bpf/linux-4.19.90/samples/bpf/xdp_whitelist_user.c:101:16: error: ‘MAP_FAILED’ undeclared (first use in this function); did you mean ‘MAP_SHARED’? if (buf == MAP_FAILED) { ^~~~~~~~~~ MAP_SHARED /root/bpf/linux-4.19.90/samples/bpf/xdp_whitelist_user.c:113:55: error: dereferencing pointer to incomplete type ‘struct perf_event_mmap_page’ __u64 data_head = __sync_fetch_and_add(&header->data_head, 0); ^~ /root/bpf/linux-4.19.90/samples/bpf/xdp_whitelist_user.c:131:5: warning: implicit declaration of function ‘munmap’ [-Wimplicit-function-declaration] munmap(buf, mmap_size); ^~~~~~ /root/bpf/linux-4.19.90/samples/bpf/xdp_whitelist_user.c: In function ‘load_xdp’: /root/bpf/linux-4.19.90/samples/bpf/xdp_whitelist_user.c:194:15: warning: implicit declaration of function ‘if_nametoindex’ [-Wimplicit-function-declaration] ifindex = if_nametoindex(iface); ^~~~~~~~~~~~~~ /root/bpf/linux-4.19.90/samples/bpf/xdp_whitelist_user.c:214:31: warning: implicit declaration of function ‘bpf_object__find_program_by_name’; did you mean ‘bpf_object__find_program_by_title’? [-Wimplicit-function-declaration] prog_fd = bpf_program__fd(bpf_object__find_program_by_name(obj, "xdp_whitelist")); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ bpf_object__find_program_by_title /root/bpf/linux-4.19.90/samples/bpf/xdp_whitelist_user.c:214:31: warning: passing argument 1 of ‘bpf_program__fd’ makes pointer from integer without a cast [-Wint-conversion] In file included from /root/bpf/linux-4.19.90/samples/bpf/xdp_whitelist_user.c:11:0: ./tools/lib/bpf/libbpf.h:128:5: note: expected ‘struct bpf_program *’ but argument is of type ‘int’ int bpf_program__fd(struct bpf_program *prog); ^~~~~~~~~~~~~~~ /root/bpf/linux-4.19.90/samples/bpf/xdp_whitelist_user.c: At top level: /root/bpf/linux-4.19.90/samples/bpf/xdp_whitelist_user.c:238:13: warning: function declaration isn’t a prototype [-Wstrict-prototypes] static void unload_xdp() { ^~~~~~~~~~ make[2]: *** [scripts/Makefile.host:107: /root/bpf/linux-4.19.90/samples/bpf/xdp_whitelist_user.o] Error 1 make[1]: *** [Makefile:1695: /root/bpf/linux-4.19.90/samples/bpf/] Error 2 make[1]: Leaving directory '/root/bpf/linux-4.19.90' make: *** [Makefile:224: all] Error 2
07-22
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ym影子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值