目录
获取给定的 bpf_object 关联的 BTF(BPF Type Format)信息
获取给定的 bpf_object 关联的 BTF 文件描述符
获取给定的 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 个不同的类型和结构。
这些类型可以包括:
- 基本类型(如 int)
- 结构体(如示例中的 struct data)
- 枚举
- 函数指针等
这个数量是通过分析 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)。