After this patch, perf utilizes builtin cflags 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: Arnaldo Carvalho de Melo <a...@redhat.com> Cc: Alexei Starovoitov <a...@fb.com> Cc: He Kuang <heku...@huawei.com> Cc: Jiri Olsa <jo...@kernel.org> --- 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 2b2c9b8..a5ddb8e 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_debug("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); free(obj_buf); } else 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 38dcc14..010b91e 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; +} } -- 1.8.3.4