[PATCH v2 16/18] perf clang: Declare BPF functions for BPF scripts automatically

From: Wang Nan
Date: Mon Sep 26 2016 - 03:29:14 EST


Use Clang's OverlayFileSystem, add '-include' options to make builtin
clang define BPF functions. After this patch BPF script writer needn't
define BPF functions by their own.

Test cases are updated to avoid redefine these functions.

Signed-off-by: Wang Nan <wangnan0@xxxxxxxxxx>
Cc: Arnaldo Carvalho de Melo <acme@xxxxxxxxxx>
Cc: Alexei Starovoitov <ast@xxxxxx>
Cc: He Kuang <hekuang@xxxxxxxxxx>
Cc: Jiri Olsa <jolsa@xxxxxxxxxx>
---
tools/perf/tests/bpf-script-example.c | 18 +++++++++------
tools/perf/tests/bpf-script-test-prologue.c | 2 ++
tools/perf/tests/bpf-script-test-relocation.c | 18 +++++++++------
tools/perf/util/c++/clang.cpp | 32 ++++++++++++++++++++++++++-
4 files changed, 55 insertions(+), 15 deletions(-)

diff --git a/tools/perf/tests/bpf-script-example.c b/tools/perf/tests/bpf-script-example.c
index 268e5f8..5fb3e66 100644
--- a/tools/perf/tests/bpf-script-example.c
+++ b/tools/perf/tests/bpf-script-example.c
@@ -8,13 +8,6 @@
#endif
#define BPF_ANY 0
#define BPF_MAP_TYPE_ARRAY 2
-#define BPF_FUNC_map_lookup_elem 1
-#define BPF_FUNC_map_update_elem 2
-
-static void *(*bpf_map_lookup_elem)(void *map, void *key) =
- (void *) BPF_FUNC_map_lookup_elem;
-static void *(*bpf_map_update_elem)(void *map, void *key, void *value, int flags) =
- (void *) BPF_FUNC_map_update_elem;

struct bpf_map_def {
unsigned int type;
@@ -24,6 +17,17 @@ struct bpf_map_def {
};

#define SEC(NAME) __attribute__((section(NAME), used))
+
+#ifndef BPF_FUNCS_DEFINED
+#define BPF_FUNC_map_lookup_elem 1
+#define BPF_FUNC_map_update_elem 2
+
+static void *(*bpf_map_lookup_elem)(void *map, void *key) =
+ (void *) BPF_FUNC_map_lookup_elem;
+static void *(*bpf_map_update_elem)(void *map, void *key, void *value, int flags) =
+ (void *) BPF_FUNC_map_update_elem;
+#endif
+
struct bpf_map_def SEC("maps") flip_table = {
.type = BPF_MAP_TYPE_ARRAY,
.key_size = sizeof(int),
diff --git a/tools/perf/tests/bpf-script-test-prologue.c b/tools/perf/tests/bpf-script-test-prologue.c
index 7230e62..e8dba36 100644
--- a/tools/perf/tests/bpf-script-test-prologue.c
+++ b/tools/perf/tests/bpf-script-test-prologue.c
@@ -13,8 +13,10 @@
#define FMODE_READ 0x1
#define FMODE_WRITE 0x2

+#ifndef BPF_FUNCS_DEFINED
static void (*bpf_trace_printk)(const char *fmt, int fmt_size, ...) =
(void *) 6;
+#endif

SEC("func=null_lseek file->f_mode offset orig")
int bpf_func__null_lseek(void *ctx, int err, unsigned long f_mode,
diff --git a/tools/perf/tests/bpf-script-test-relocation.c b/tools/perf/tests/bpf-script-test-relocation.c
index 93af774..a9638eb7 100644
--- a/tools/perf/tests/bpf-script-test-relocation.c
+++ b/tools/perf/tests/bpf-script-test-relocation.c
@@ -8,13 +8,6 @@
#endif
#define BPF_ANY 0
#define BPF_MAP_TYPE_ARRAY 2
-#define BPF_FUNC_map_lookup_elem 1
-#define BPF_FUNC_map_update_elem 2
-
-static void *(*bpf_map_lookup_elem)(void *map, void *key) =
- (void *) BPF_FUNC_map_lookup_elem;
-static void *(*bpf_map_update_elem)(void *map, void *key, void *value, int flags) =
- (void *) BPF_FUNC_map_update_elem;

struct bpf_map_def {
unsigned int type;
@@ -24,6 +17,17 @@ struct bpf_map_def {
};

#define SEC(NAME) __attribute__((section(NAME), used))
+
+#ifndef BPF_FUNCS_DEFINED
+#define BPF_FUNC_map_lookup_elem 1
+#define BPF_FUNC_map_update_elem 2
+
+static void *(*bpf_map_lookup_elem)(void *map, void *key) =
+ (void *) BPF_FUNC_map_lookup_elem;
+static void *(*bpf_map_update_elem)(void *map, void *key, void *value, int flags) =
+ (void *) BPF_FUNC_map_update_elem;
+#endif
+
struct bpf_map_def SEC("maps") my_table = {
.type = BPF_MAP_TYPE_ARRAY,
.key_size = sizeof(int),
diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index c1660ab..1016d5d 100644
--- a/tools/perf/util/c++/clang.cpp
+++ b/tools/perf/util/c++/clang.cpp
@@ -27,11 +27,19 @@

#include "clang.h"
#include "clang-c.h"
+#include "clang-bpf-includes.h"
#include "llvm-utils-cxx.h"
#include "util-cxx.h"

namespace perf {

+static struct BPFHeader {
+ llvm::StringRef Path;
+ llvm::StringRef Content;
+} BPFHeaders[] = {
+ {"/virtual/bpf-funcs.h", clang_builtin_bpf_funcs_str},
+};
+
static std::unique_ptr<llvm::LLVMContext> LLVMCtx;

using namespace clang;
@@ -56,6 +64,11 @@ createCompilerInvocation(llvm::opt::ArgStringList CFlags, StringRef& Path,
"-x", "c"};

CCArgs.append(CFlags.begin(), CFlags.end());
+ for (BPFHeader &h : BPFHeaders) {
+ CCArgs.append(1, "-include");
+ CCArgs.append(1, h.Path.begin());
+ }
+
CompilerInvocation *CI = tooling::newInvocation(&Diags, CCArgs);

FrontendOptions& Opts = CI->getFrontendOpts();
@@ -64,6 +77,22 @@ createCompilerInvocation(llvm::opt::ArgStringList CFlags, StringRef& Path,
return CI;
}

+static IntrusiveRefCntPtr<vfs::FileSystem>
+addBPFHeaders(IntrusiveRefCntPtr<vfs::FileSystem> VFS)
+{
+ using namespace vfs;
+
+ llvm::IntrusiveRefCntPtr<OverlayFileSystem> OverlayFS(
+ new OverlayFileSystem(VFS));
+ llvm::IntrusiveRefCntPtr<InMemoryFileSystem> MemFS(
+ new InMemoryFileSystem(true));
+ OverlayFS->pushOverlay(MemFS);
+
+ for (BPFHeader &h : BPFHeaders)
+ MemFS->addFile(h.Path, 0, llvm::MemoryBuffer::getMemBuffer(h.Content));
+ return OverlayFS;
+}
+
static std::unique_ptr<llvm::Module>
getModuleFromSource(llvm::opt::ArgStringList CFlags,
StringRef Path, IntrusiveRefCntPtr<vfs::FileSystem> VFS)
@@ -71,7 +100,8 @@ getModuleFromSource(llvm::opt::ArgStringList CFlags,
CompilerInstance Clang;
Clang.createDiagnostics();

- Clang.setVirtualFileSystem(&*VFS);
+ IntrusiveRefCntPtr<vfs::FileSystem> OverlayVFS = addBPFHeaders(VFS);
+ Clang.setVirtualFileSystem(&*OverlayVFS);

IntrusiveRefCntPtr<CompilerInvocation> CI =
createCompilerInvocation(std::move(CFlags), Path,
--
1.8.3.4