c - 无法在内核树之外编译 bindsnoop eBPF c 代码
问题描述
我正在尝试将用 C 编写的 BPF 程序构建到 bpf 字节码中。程序 C 代码取自https://github.com/iovisor/bcc/blob/master/tools/bindsnoop.py(我使用了来自 bpf_text 的 C 代码并进行了一些自定义)。我不想使用 bcc python 工具,我的目的是用 C 编写内核和用户空间代码,我想在内核树之外构建一个内核程序。
我使用 Ubuntu 20.10,这里是 uname -a 输出:Linux bb-VirtualBox 5.8.0-63-generic #71-Ubuntu SMP Tue Jul 13 15:59:12 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
Linux 头文件已安装,但由于某种原因,我有两个目录包含 5.8.0-63 的 linux 头文件:/usr/src/linux-headers-5.8.0-63 和 /usr/src/linux-headers-5.8.0 -63-通用
我使用这篇文章为我的程序创建了一个生成文件:https ://blogs.oracle.com/linux/post/bpf-in-depth-building-bpf-programs 所以生成文件如下所示:
OBJS = kprobe_bindsnoop_kern.o
LLC ?= llc
CLANG ?= clang
INC_FLAGS = -nostdinc -isystem `$(CLANG) -print-file-name=include`
EXTRA_CFLAGS ?= -O2 -emit-llvm
linuxhdrsgen ?= /usr/src/linux-headers-5.8.0-63-generic
LINUXINCLUDE = -I$(linuxhdrsgen)/arch/x86/include \
-I$(linuxhdrsgen)/arch/x86/include/generated/uapi \
-I$(linuxhdrsgen)/arch/x86/include/generated \
-I$(linuxhdrsgen)/arch/x86/include/uapi \
-I$(linuxhdrsgen)/arch/x86/include/generated/uapi \
-I$(linuxhdrsgen)/include/uapi \
-I$(linuxhdrsgen)/include/generated/uapi \
-I$(linuxhdrsgen)/include \
-include ${linuxhdrsgen}/include/linux/kconfig.h
all: $(OBJS)
.PHONY: clean
clean:
rm -f $(OBJS)
INC_FLAGS = -nostdinc -isystem `$(CLANG) -print-file-name=include`
$(OBJS): %.o:%.c
$(CLANG) $(INC_FLAGS) \
-D__KERNEL__ -D__ASM_SYSREG_H \
-Wno-unused-value -Wno-pointer-sign \
-Wno-compare-distinct-pointer-types \
-Wno-gnu-variable-sized-type-not-at-end \
-Wno-address-of-packed-member -Wno-tautological-compare \
-Wno-unknown-warning-option \
-I../include $(LINUXINCLUDE) \
$(EXTRA_CFLAGS) -c $< -o -| $(LLC) -march=bpf -filetype=obj -o $@
而 kprobe_bindsnoop_kern.c 从以下一组包含文件开始:
#include <uapi/linux/ptrace.h>
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wtautological-compare"
#include <net/sock.h>
#pragma clang diagnostic pop
#include <net/inet_sock.h>
#include <net/net_namespace.h>
#include <bcc/proto.h>
下面你可以看到编译输出:
clang -nostdinc -isystem `clang -print-file-name=include` \
-D__KERNEL__ -D__ASM_SYSREG_H \
-Wno-unused-value -Wno-pointer-sign \
-Wno-compare-distinct-pointer-types \
-Wno-gnu-variable-sized-type-not-at-end \
-Wno-address-of-packed-member -Wno-tautological-compare \
-Wno-unknown-warning-option \
-I../include -I/usr/src/linux-headers-5.8.0-63-generic/arch/x86/include/ -I/usr/src/linux-headers-5.8.0-63-generic/arch/x86/include/generated/uapi -I/usr/src/linux-headers-5.8.0-63-generic/arch/x86/include/generated/ -I/usr/src/linux-headers-5.8.0-63-generic/arch/x86/include/uapi -I/usr/src/linux-headers-5.8.0-63-generic/arch/x86/include/generated/uapi -I/usr/src/linux-headers-5.8.0-63-generic/include/uapi -I/usr/src/linux-headers-5.8.0-63-generic/include/generated/uapi -I/usr/src/linux-headers-5.8.0-63-generic/include -include /usr/src/linux-headers-5.8.0-63-generic/include/linux/kconfig.h \
-O2 -emit-llvm -c kprobe_bindsnoop_kern.c -o -| llc -march=bpf -filetype=obj -o kprobe_bindsnoop_kern.o
In file included from kprobe_bindsnoop_kern.c:22:
In file included from /usr/src/linux-headers-5.8.0-63-generic/include/uapi/linux/ptrace.h:143:
In file included from /usr/src/linux-headers-5.8.0-63-generic/arch/x86/include/asm/ptrace.h:5:
In file included from /usr/src/linux-headers-5.8.0-63-generic/arch/x86/include/asm/segment.h:6:
/usr/src/linux-headers-5.8.0-63-generic/arch/x86/include/asm/alternative.h:59:2: error: unknown type name 's32'
s32 instr_offset; /* original instruction */
^
/usr/src/linux-headers-5.8.0-63-generic/arch/x86/include/asm/alternative.h:60:2: error: unknown type name 's32'
s32 repl_offset; /* offset to replacement instruction */
^
/usr/src/linux-headers-5.8.0-63-generic/arch/x86/include/asm/alternative.h:61:2: error: unknown type name 'u16'
u16 cpuid; /* cpuid bit set for replacement */
^
/usr/src/linux-headers-5.8.0-63-generic/arch/x86/include/asm/alternative.h:62:2: error: unknown type name 'u8'
u8 instrlen; /* length of original instruction */
^
/usr/src/linux-headers-5.8.0-63-generic/arch/x86/include/asm/alternative.h:63:2: error: unknown type name 'u8'
u8 replacementlen; /* length of new instruction */
^
/usr/src/linux-headers-5.8.0-63-generic/arch/x86/include/asm/alternative.h:64:2: error: unknown type name 'u8'
u8 padlen; /* length of build-time padding */
^
/usr/src/linux-headers-5.8.0-63-generic/arch/x86/include/asm/alternative.h:85:8: error: unknown type name 'bool'
extern bool skip_smp_alternatives;
^
In file included from kprobe_bindsnoop_kern.c:22:
In file included from /usr/src/linux-headers-5.8.0-63-generic/include/uapi/linux/ptrace.h:143:
In file included from /usr/src/linux-headers-5.8.0-63-generic/arch/x86/include/asm/ptrace.h:5:
In file included from /usr/src/linux-headers-5.8.0-63-generic/arch/x86/include/asm/segment.h:169:
In file included from /usr/src/linux-headers-5.8.0-63-generic/arch/x86/include/asm/cache.h:5:
In file included from /usr/src/linux-headers-5.8.0-63-generic/include/linux/linkage.h:7:
In file included from /usr/src/linux-headers-5.8.0-63-generic/include/linux/export.h:43:
In file included from /usr/src/linux-headers-5.8.0-63-generic/include/linux/compiler.h:266:
/usr/src/linux-headers-5.8.0-63-generic/include/linux/kasan-checks.h:16:15: error: unknown type name 'bool'
static inline bool __kasan_check_read(const volatile void *p, unsigned int size)
^
/usr/src/linux-headers-5.8.0-63-generic/include/linux/kasan-checks.h:18:9: error: use of undeclared identifier 'true'
return true;
^
/usr/src/linux-headers-5.8.0-63-generic/include/linux/kasan-checks.h:20:15: error: unknown type name 'bool'
static inline bool __kasan_check_write(const volatile void *p, unsigned int size)
^
/usr/src/linux-headers-5.8.0-63-generic/include/linux/kasan-checks.h:22:9: error: use of undeclared identifier 'true'
return true;
^
/usr/src/linux-headers-5.8.0-63-generic/include/linux/kasan-checks.h:34:15: error: unknown type name 'bool'
static inline bool kasan_check_read(const volatile void *p, unsigned int size)
^
/usr/src/linux-headers-5.8.0-63-generic/include/linux/kasan-checks.h:36:9: error: use of undeclared identifier 'true'
return true;
^
/usr/src/linux-headers-5.8.0-63-generic/include/linux/kasan-checks.h:38:15: error: unknown type name 'bool'
static inline bool kasan_check_write(const volatile void *p, unsigned int size)
^
/usr/src/linux-headers-5.8.0-63-generic/include/linux/kasan-checks.h:40:9: error: use of undeclared identifier 'true'
return true;
^
In file included from kprobe_bindsnoop_kern.c:22:
In file included from /usr/src/linux-headers-5.8.0-63-generic/include/uapi/linux/ptrace.h:143:
In file included from /usr/src/linux-headers-5.8.0-63-generic/arch/x86/include/asm/ptrace.h:5:
In file included from /usr/src/linux-headers-5.8.0-63-generic/arch/x86/include/asm/segment.h:169:
In file included from /usr/src/linux-headers-5.8.0-63-generic/arch/x86/include/asm/cache.h:5:
In file included from /usr/src/linux-headers-5.8.0-63-generic/include/linux/linkage.h:7:
In file included from /usr/src/linux-headers-5.8.0-63-generic/include/linux/export.h:43:
In file included from /usr/src/linux-headers-5.8.0-63-generic/include/linux/compiler.h:267:
/usr/src/linux-headers-5.8.0-63-generic/include/linux/kcsan-checks.h:148:67: error: unknown type name 'size_t'
static inline void __kcsan_check_access(const volatile void *ptr, size_t size,
^
/usr/src/linux-headers-5.8.0-63-generic/include/linux/kcsan-checks.h:164:53: error: unknown type name 'size_t'
kcsan_begin_scoped_access(const volatile void *ptr, size_t size, int type,
^
/usr/src/linux-headers-5.8.0-63-generic/include/linux/kcsan-checks.h:184:65: error: unknown type name 'size_t'
static inline void kcsan_check_access(const volatile void *ptr, size_t size,
^
In file included from kprobe_bindsnoop_kern.c:22:
In file included from /usr/src/linux-headers-5.8.0-63-generic/include/uapi/linux/ptrace.h:143:
In file included from /usr/src/linux-headers-5.8.0-63-generic/arch/x86/include/asm/ptrace.h:6:
In file included from /usr/src/linux-headers-5.8.0-63-generic/arch/x86/include/asm/page_types.h:7:
In file included from /usr/src/linux-headers-5.8.0-63-generic/include/linux/mem_encrypt.h:17:
In file included from /usr/src/linux-headers-5.8.0-63-generic/arch/x86/include/asm/mem_encrypt.h:15:
/usr/src/linux-headers-5.8.0-63-generic/include/linux/init.h:155:8: error: unknown type name 'bool'
extern bool rodata_enabled;
^
fatal error: too many errors emitted, stopping now [-ferror-limit=]
20 errors generated.
我试图添加 #include <linux/types.h> 或 #include <asm/types.h> 但它没有帮助。我检查了很多帖子,比如这个 Error compiling eBPF C code out of kernel tree 和 this how to build BPF program out of the kernel tree 但仍然没有得到答案。我错过了什么?任何帮助将不胜感激 ))
解决方案
感谢所有试图帮助我的人!最后,问题非常简单——只需要更改 makefile 中指定的包含目录的顺序。
刚刚将“-I$(linuxhdrsgen)/include”移到列表中的第一个,它解决了这个问题。意思是,现在包含目录的列表如下所示:
LINUXINCLUDE = -I$(linuxhdrsgen)/include
-I$(linuxhdrsgen)/arch/x86/include
-I$(linuxhdrsgen)/arch/x86/include/generated/uapi
-I$(linuxhdrsgen)/arch/x86/include /generated
-I$(linuxhdrsgen)/arch/x86/include/uapi
-I$(linuxhdrsgen)/arch/x86/include/generated/uapi
-I$(linuxhdrsgen)/include/uapi
-I$(linuxhdrsgen)/include /生成/uapi
-include ${linuxhdrsgen}/include/linux/kconfig.h
推荐阅读
- java - 当活动/片段处于前台时如何连续检查互联网连接并解析数据
- python - Docker Container 中的 Gunicorn Flask 应用程序未暴露
- ios - 如何在 react-native 中获取绝对图像路径?
- django - 如何在 django 中为一个用户只选择一行?
- java - 如何在 Spring Data 中的另一个实体更新后更新一个实体?
- python - 如何根据第一个元素对嵌套列表进行分组?
- python - Tensorflow 2.0 - SparseCategoricalCrossentropy 的数据形状不正确
- mysql - 有人可以向我解释一下我在哪里可以获得从谷歌云连接到 sql 数据库的属性?
- ruby-on-rails - 在保存嵌套对象时无法检测到错误
- javascript - 制作自定义 CLI 以安装 npm 依赖项