从内核树中编译eBPF C代码时出错

时间:2019-07-10 17:33:05

标签: linux clang bpf ebpf

我正在尝试将用C编写的BPF程序构建到加载它所需的bpf字节码中。我使用了这篇文章来尝试让我起步:https://blogs.oracle.com/linux/notes-on-bpf-4

由于库依赖性,我不想使用BCC。我正在使用ubuntu 18.04(Linux bpf-ubuntu 4.15.0-1036-gcp#38-Ubuntu SMP Mon Jun 24 13:49:05 UTC 2019 x86_64 x86_64 x86_64 GNU / Linux)

目前,我的文件非常简单(而且可能不正确),因为我仍在尝试进行编译工作:

#include <linux/version.h>
#include <uapi/linux/bpf.h>
#include "bpf_helpers.h"
#include <net/sock.h>

SEC("kprobe/tcp_connect")
int bpf_prog1(struct pt_regs *ctx) {
        struct sock *sk;
        sk = (struct sock*) PT_REGS_PARM1(ctx);
        bpf_trace_printk("%s\n","Got tcp_connect");
}

char _license[] SEC("license") = "GPL";
u32 _version SEC("version") = LINUX_VERSION_CODE;

用于生成结果的命令是:

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-`uname -r`/include -I/usr/src/linux-headers-`uname -r`/arch/x86/include -I/usr/src/linux-headers-`uname -r`/arch/x86/include/uapi -I/usr/src/linux-headers-`uname -r`/arch/x86/include/generated/uapi -I/usr/src/linux-headers-`uname -r`/include/generated/uapi -I/usr/src/linux-headers-`uname -r`/include/uapi \
                -O2 -emit-llvm -c net_mon_kern.c -o -| llc -march=bpf -filetype=obj -o net_mon_kern.o
In file included from net_mon_kern.c:7:
In file included from /usr/src/linux-headers-4.15.0-1036-gcp/include/net/sock.h:43:
In file included from /usr/src/linux-headers-4.15.0-1036-gcp/include/linux/hardirq.h:5:
In file included from /usr/src/linux-headers-4.15.0-1036-gcp/include/linux/preempt.h:11:
In file included from /usr/src/linux-headers-4.15.0-1036-gcp/include/linux/list.h:9:
In file included from /usr/src/linux-headers-4.15.0-1036-gcp/include/linux/kernel.h:11:
In file included from /usr/src/linux-headers-4.15.0-1036-gcp/include/linux/bitops.h:18:
In file included from /usr/src/linux-headers-4.15.0-1036-gcp/arch/x86/include/asm/bitops.h:514:
/usr/src/linux-headers-4.15.0-1036-gcp/arch/x86/include/asm/arch_hweight.h:55:42: error: expected ')'
        asm (ALTERNATIVE("call __sw_hweight64", POPCNT64, X86_FEATURE_POPCNT)
                                                ^
/usr/src/linux-headers-4.15.0-1036-gcp/arch/x86/include/asm/arch_hweight.h:55:6: note: to match this '('
        asm (ALTERNATIVE("call __sw_hweight64", POPCNT64, X86_FEATURE_POPCNT)
            ^
In file included from net_mon_kern.c:7:
In file included from /usr/src/linux-headers-4.15.0-1036-gcp/include/net/sock.h:43:
In file included from /usr/src/linux-headers-4.15.0-1036-gcp/include/linux/hardirq.h:5:
In file included from /usr/src/linux-headers-4.15.0-1036-gcp/include/linux/preempt.h:81:
In file included from /usr/src/linux-headers-4.15.0-1036-gcp/arch/x86/include/asm/preempt.h:7:
In file included from /usr/src/linux-headers-4.15.0-1036-gcp/include/linux/thread_info.h:38:
In file included from /usr/src/linux-headers-4.15.0-1036-gcp/arch/x86/include/asm/thread_info.h:12:
In file included from /usr/src/linux-headers-4.15.0-1036-gcp/arch/x86/include/asm/page.h:14:
In file included from /usr/src/linux-headers-4.15.0-1036-gcp/arch/x86/include/asm/page_32.h:35:
In file included from /usr/src/linux-headers-4.15.0-1036-gcp/include/linux/string.h:19:
In file included from /usr/src/linux-headers-4.15.0-1036-gcp/arch/x86/include/asm/string.h:5:
In file included from /usr/src/linux-headers-4.15.0-1036-gcp/arch/x86/include/asm/string_64.h:6:
In file included from /usr/src/linux-headers-4.15.0-1036-gcp/include/linux/jump_label.h:188:
In file included from /usr/src/linux-headers-4.15.0-1036-gcp/include/linux/atomic.h:5:
In file included from /usr/src/linux-headers-4.15.0-1036-gcp/arch/x86/include/asm/atomic.h:276:
/usr/src/linux-headers-4.15.0-1036-gcp/arch/x86/include/asm/atomic64_64.h:20:40: error: unknown type name
      'atomic64_t'; did you mean 'atomic_t'?
static inline long atomic64_read(const atomic64_t *v)
                                       ^~~~~~~~~~
                                       atomic_t
/usr/src/linux-headers-4.15.0-1036-gcp/include/linux/types.h:178:3: note: 'atomic_t' declared here
} atomic_t;
  ^

18 more errors relating to atomic64_t...

我不太确定如何解决该问题。我只能假设我包含标头的方式不正确。

1 个答案:

答案 0 :(得分:2)

TL; DR:尝试在包含其他文件之前添加In [20]: (www[:,None] == uniques).all(2) Out[20]: array([[ True, False], [ True, False], [False, True]]) # Respective indices in `counts` array In [21]: np.where((www[:,None] == uniques).all(2))[1] Out[21]: array([0, 0, 1]) In [22]: counts[np.where((www[:,None] == uniques).all(2))[1]] > 1 Out[22]: array([ True, True, False]) In [23]: (counts[np.where((www[:,None] == uniques).all(2))[1]] > 1).astype(int) Out[23]: array([1, 1, 0])

在我看来,您的命令行是受内核示例启发的(在linux/kconfig.h下),但您尝试从树中进行编译,并修剪了不相关的位。

当您尝试编译代码时,发生的事情是clang在使用samples/bpf/选项传递的路径中获取了所有相关的内核头文件。但是,其中许多标头包含条件定义或包含条件,具体取决于要构建的内核所请求的配置。例如,最终通过-I包含的include/linux/types.h具有以下代码:

<net/sock.h>

但是,当您编译时,#ifdef CONFIG_64BIT typedef struct { long counter; } atomic64_t; #endif 从未被定义...我让您了解所获得的错误消息:)。

内核样本实际上包括CONFIG_64BITLINUXINCLUDEUSERINCLUDE,因此我们必须找到一种以某种方式添加它的方法。显然,这足以正确设置配置变量并解决编译问题。

我发现在您的情况下可以包含该文件的以下可能性:

  • kconfig.h添加到文件中,之前,包括其他内核头文件(例如,第一行)。
  • 或者通过您的命令行#include <linux/kconfig.h>添加它,就像内核示例一样(这似乎是最干净的方法)。