Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S966209AbcKOEN3 (ORCPT ); Mon, 14 Nov 2016 23:13:29 -0500 Received: from szxga03-in.huawei.com ([119.145.14.66]:25296 "EHLO szxga03-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S965886AbcKOEIQ (ORCPT ); Mon, 14 Nov 2016 23:08:16 -0500 From: Wang Nan To: , CC: , , , , Wang Nan , Jiri Olsa Subject: [PATCH 19/34] perf clang: Compile BPF script use builtin clang support Date: Tue, 15 Nov 2016 04:06:02 +0000 Message-ID: <20161115040617.69788-20-wangnan0@huawei.com> X-Mailer: git-send-email 2.10.1 In-Reply-To: <20161115040617.69788-1-wangnan0@huawei.com> References: <20161115040617.69788-1-wangnan0@huawei.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.107.193.248] X-CFilter-Loop: Reflected Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 4437 Lines: 154 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 Cc: Alexei Starovoitov Cc: He Kuang Cc: Jiri Olsa Cc: Zefan Li Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/1474874832-134786-13-git-send-email-wangnan0@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- 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 /* for size_t */ +#include /* 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