aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWang Nan <wangnan0@huawei.com>2016-11-26 02:03:39 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2016-12-05 13:51:45 -0500
commitedd695b032ba3a90c3bb07d934500b2c390a61ff (patch)
treed54f227be186c8c268dc17e339d10606a818a4a0
parent5e08a76525b8f5e9aeb8b27d0466614abec070a9 (diff)
perf clang: Compile BPF script using builtin clang support
After this patch, perf utilizes builtin clang support to build BPF script, no longer depend on external clang, but fallbacking to it if for some reason the builtin compiling framework fails. 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: successfull builtin compilation $ Can't pass cflags so unable to include kernel headers now. Will be fixed by following commits. Committer notes: Make sure '-v' comes before the '-e ./test.c' in the command line otherwise the 'verbose' variable will not be set when the bpf event is parsed and thus the pr_debug indicating a 'successfull builtin compilation' will not be output, as the debug level (1) will be less than what 'verbose' has at that point (0). Signed-off-by: Wang Nan <wangnan0@huawei.com> Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Alexei Starovoitov <ast@fb.com> Cc: He Kuang <hekuang@huawei.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Joe Stringer <joe@ovn.org> Cc: Zefan Li <lizefan@huawei.com> Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/20161126070354.141764-16-wangnan0@huawei.com [ Spell check/reflow successfull pr_debug string ] Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r--tools/perf/util/bpf-loader.c15
-rw-r--r--tools/perf/util/c++/clang-c.h26
-rw-r--r--tools/perf/util/c++/clang.cpp29
3 files changed, 66 insertions, 4 deletions
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index cf16b94115b5..36c861103291 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -14,11 +14,11 @@
14#include "debug.h" 14#include "debug.h"
15#include "bpf-loader.h" 15#include "bpf-loader.h"
16#include "bpf-prologue.h" 16#include "bpf-prologue.h"
17#include "llvm-utils.h"
18#include "probe-event.h" 17#include "probe-event.h"
19#include "probe-finder.h" // for MAX_PROBES 18#include "probe-finder.h" // for MAX_PROBES
20#include "parse-events.h" 19#include "parse-events.h"
21#include "llvm-utils.h" 20#include "llvm-utils.h"
21#include "c++/clang-c.h"
22 22
23#define DEFINE_PRINT_FN(name, level) \ 23#define DEFINE_PRINT_FN(name, level) \
24static int libbpf_##name(const char *fmt, ...) \ 24static int libbpf_##name(const char *fmt, ...) \
@@ -86,9 +86,16 @@ struct bpf_object *bpf__prepare_load(const char *filename, bool source)
86 void *obj_buf; 86 void *obj_buf;
87 size_t obj_buf_sz; 87 size_t obj_buf_sz;
88 88
89 err = llvm__compile_bpf(filename, &obj_buf, &obj_buf_sz); 89 perf_clang__init();
90 if (err) 90 err = perf_clang__compile_bpf(filename, &obj_buf, &obj_buf_sz);
91 return ERR_PTR(-BPF_LOADER_ERRNO__COMPILE); 91 perf_clang__cleanup();
92 if (err) {
93 pr_warning("bpf: builtin compilation failed: %d, try external compiler\n", err);
94 err = llvm__compile_bpf(filename, &obj_buf, &obj_buf_sz);
95 if (err)
96 return ERR_PTR(-BPF_LOADER_ERRNO__COMPILE);
97 } else
98 pr_debug("bpf: successfull builtin compilation\n");
92 obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, filename); 99 obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, filename);
93 100
94 if (!IS_ERR(obj) && llvm_param.dump_obj) 101 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 22b3936d1f09..0eadd792ab1f 100644
--- a/tools/perf/util/c++/clang-c.h
+++ b/tools/perf/util/c++/clang-c.h
@@ -1,16 +1,42 @@
1#ifndef PERF_UTIL_CLANG_C_H 1#ifndef PERF_UTIL_CLANG_C_H
2#define PERF_UTIL_CLANG_C_H 2#define PERF_UTIL_CLANG_C_H
3 3
4#include <stddef.h> /* for size_t */
5#include <util-cxx.h> /* for __maybe_unused */
6
4#ifdef __cplusplus 7#ifdef __cplusplus
5extern "C" { 8extern "C" {
6#endif 9#endif
7 10
11#ifdef HAVE_LIBCLANGLLVM_SUPPORT
8extern void perf_clang__init(void); 12extern void perf_clang__init(void);
9extern void perf_clang__cleanup(void); 13extern void perf_clang__cleanup(void);
10 14
11extern int test__clang_to_IR(void); 15extern int test__clang_to_IR(void);
12extern int test__clang_to_obj(void); 16extern int test__clang_to_obj(void);
13 17
18extern int perf_clang__compile_bpf(const char *filename,
19 void **p_obj_buf,
20 size_t *p_obj_buf_sz);
21#else
22
23
24static inline void perf_clang__init(void) { }
25static inline void perf_clang__cleanup(void) { }
26
27static inline int test__clang_to_IR(void) { return -1; }
28static inline int test__clang_to_obj(void) { return -1;}
29
30static inline int
31perf_clang__compile_bpf(const char *filename __maybe_unused,
32 void **p_obj_buf __maybe_unused,
33 size_t *p_obj_buf_sz __maybe_unused)
34{
35 return -ENOTSUP;
36}
37
38#endif
39
14#ifdef __cplusplus 40#ifdef __cplusplus
15} 41}
16#endif 42#endif
diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
index 2a1a75df204f..1e974152cac2 100644
--- a/tools/perf/util/c++/clang.cpp
+++ b/tools/perf/util/c++/clang.cpp
@@ -163,4 +163,33 @@ void perf_clang__cleanup(void)
163 perf::LLVMCtx.reset(nullptr); 163 perf::LLVMCtx.reset(nullptr);
164 llvm::llvm_shutdown(); 164 llvm::llvm_shutdown();
165} 165}
166
167int perf_clang__compile_bpf(const char *filename,
168 void **p_obj_buf,
169 size_t *p_obj_buf_sz)
170{
171 using namespace perf;
172
173 if (!p_obj_buf || !p_obj_buf_sz)
174 return -EINVAL;
175
176 llvm::opt::ArgStringList CFlags;
177 auto M = getModuleFromSource(std::move(CFlags), filename);
178 if (!M)
179 return -EINVAL;
180 auto O = getBPFObjectFromModule(&*M);
181 if (!O)
182 return -EINVAL;
183
184 size_t size = O->size_in_bytes();
185 void *buffer;
186
187 buffer = malloc(size);
188 if (!buffer)
189 return -ENOMEM;
190 memcpy(buffer, O->data(), size);
191 *p_obj_buf = buffer;
192 *p_obj_buf_sz = size;
193 return 0;
194}
166} 195}