After this patch, perf utilizes builtin clang support to build BPF
script, no longer depend on external clang.

Test:

  $ type clang
  -bash: type: clang: not found
  $ cat ~/.perfconfig
  $ echo '#define LINUX_VERSION_CODE 0x040700' > ./test.c
  $ cat ./tools/perf/tests/bpf-script-example.c >> ./test.c
  $ ./perf record -v --dry-run -e ./test.c 2>&1 | grep builtin
  bpf: builtin compiling successful

Can't pass cflags so unable to include kernel headers now. Will be fixed
by following commits.

Signed-off-by: Wang Nan <wangn...@huawei.com>
Cc: Alexei Starovoitov <a...@fb.com>
Cc: He Kuang <heku...@huawei.com>
Cc: Jiri Olsa <jo...@kernel.org>
Cc: Zefan Li <lize...@huawei.com>
Cc: pi3or...@163.com
Link: 
http://lkml.kernel.org/r/1474874832-134786-13-git-send-email-wangn...@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <a...@redhat.com>
---
 tools/perf/util/bpf-loader.c  | 15 +++++++++++----
 tools/perf/util/c++/clang-c.h | 26 ++++++++++++++++++++++++++
 tools/perf/util/c++/clang.cpp | 29 +++++++++++++++++++++++++++++
 3 files changed, 66 insertions(+), 4 deletions(-)

diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index cf16b941..a0ea334f 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -14,11 +14,11 @@
 #include "debug.h"
 #include "bpf-loader.h"
 #include "bpf-prologue.h"
-#include "llvm-utils.h"
 #include "probe-event.h"
 #include "probe-finder.h" // for MAX_PROBES
 #include "parse-events.h"
 #include "llvm-utils.h"
+#include "c++/clang-c.h"
 
 #define DEFINE_PRINT_FN(name, level) \
 static int libbpf_##name(const char *fmt, ...) \
@@ -86,9 +86,16 @@ struct bpf_object *bpf__prepare_load(const char *filename, 
bool source)
                void *obj_buf;
                size_t obj_buf_sz;
 
-               err = llvm__compile_bpf(filename, &obj_buf, &obj_buf_sz);
-               if (err)
-                       return ERR_PTR(-BPF_LOADER_ERRNO__COMPILE);
+               perf_clang__init();
+               err = perf_clang__compile_bpf(filename, &obj_buf, &obj_buf_sz);
+               perf_clang__cleanup();
+               if (err) {
+                       pr_warning("bpf: builtin compiling failed: %d, try 
external compiler\n", err);
+                       err = llvm__compile_bpf(filename, &obj_buf, 
&obj_buf_sz);
+                       if (err)
+                               return ERR_PTR(-BPF_LOADER_ERRNO__COMPILE);
+               } else
+                       pr_debug("bpf: builtin compiling successful\n");
                obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, filename);
 
                if (!IS_ERR(obj) && llvm_param.dump_obj)
diff --git a/tools/perf/util/c++/clang-c.h b/tools/perf/util/c++/clang-c.h
index 22b3936..0eadd79 100644
--- a/tools/perf/util/c++/clang-c.h
+++ b/tools/perf/util/c++/clang-c.h
@@ -1,16 +1,42 @@
 #ifndef PERF_UTIL_CLANG_C_H
 #define PERF_UTIL_CLANG_C_H
 
+#include <stddef.h>    /* for size_t */
+#include <util-cxx.h>  /* for __maybe_unused */
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+#ifdef HAVE_LIBCLANGLLVM_SUPPORT
 extern void perf_clang__init(void);
 extern void perf_clang__cleanup(void);
 
 extern int test__clang_to_IR(void);
 extern int test__clang_to_obj(void);
 
+extern int perf_clang__compile_bpf(const char *filename,
+                                  void **p_obj_buf,
+                                  size_t *p_obj_buf_sz);
+#else
+
+
+static inline void perf_clang__init(void) { }
+static inline void perf_clang__cleanup(void) { }
+
+static inline int test__clang_to_IR(void) { return -1; }
+static inline int test__clang_to_obj(void) { return -1;}
+
+static inline int
+perf_clang__compile_bpf(const char *filename __maybe_unused,
+                       void **p_obj_buf __maybe_unused,
+                       size_t *p_obj_buf_sz __maybe_unused)
+{
+       return -ENOTSUP;
+}
+
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index 2a1a75d..1e97415 100644
--- a/tools/perf/util/c++/clang.cpp
+++ b/tools/perf/util/c++/clang.cpp
@@ -163,4 +163,33 @@ void perf_clang__cleanup(void)
        perf::LLVMCtx.reset(nullptr);
        llvm::llvm_shutdown();
 }
+
+int perf_clang__compile_bpf(const char *filename,
+                           void **p_obj_buf,
+                           size_t *p_obj_buf_sz)
+{
+       using namespace perf;
+
+       if (!p_obj_buf || !p_obj_buf_sz)
+               return -EINVAL;
+
+       llvm::opt::ArgStringList CFlags;
+       auto M = getModuleFromSource(std::move(CFlags), filename);
+       if (!M)
+               return  -EINVAL;
+       auto O = getBPFObjectFromModule(&*M);
+       if (!O)
+               return -EINVAL;
+
+       size_t size = O->size_in_bytes();
+       void *buffer;
+
+       buffer = malloc(size);
+       if (!buffer)
+               return -ENOMEM;
+       memcpy(buffer, O->data(), size);
+       *p_obj_buf = buffer;
+       *p_obj_buf_sz = size;
+       return 0;
+}
 }
-- 
2.10.1

Reply via email to