diff options
author | Wang Nan <wangnan0@huawei.com> | 2015-07-08 06:04:02 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2015-08-07 09:57:24 -0400 |
commit | 9bc898c7019383b6aa2ae6cb2928c4ca926449f0 (patch) | |
tree | 0ba71f573541cf42609230d8d96bc5e4c295536c | |
parent | 0c6d18bfd551622b438e216e4863155f47907b0d (diff) |
perf tests: Add LLVM test for eBPF on-the-fly compiling
Previous patches introduce llvm__compile_bpf() to compile source file to
eBPF object. This patch adds testcase to test it. It also tests libbpf
by opening generated object after applying next patch which introduces
HAVE_LIBBPF_SUPPORT option.
Since llvm__compile_bpf() prints long messages which users who don't
explicitly test llvm doesn't care, this patch set verbose to -1 to
suppress all debug, warning and error message, and hint user use 'perf
test -v' to see the full output.
For the same reason, if clang is not found in PATH and there's no [llvm]
section in .perfconfig, skip this test.
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Acked-by: Alexei Starovoitov <ast@plumgrid.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: David Ahern <dsahern@gmail.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kaixu Xia <xiakaixu@huawei.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/n/1436445342-1402-17-git-send-email-wangnan0@huawei.com
[ Add tools/lib/bpf/ to tools/perf/MANIFEST, so that the tarball targets build ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r-- | tools/perf/MANIFEST | 1 | ||||
-rw-r--r-- | tools/perf/tests/Build | 1 | ||||
-rw-r--r-- | tools/perf/tests/builtin-test.c | 4 | ||||
-rw-r--r-- | tools/perf/tests/llvm.c | 98 | ||||
-rw-r--r-- | tools/perf/tests/tests.h | 1 | ||||
-rw-r--r-- | tools/perf/util/llvm-utils.c | 9 | ||||
-rw-r--r-- | tools/perf/util/llvm-utils.h | 10 |
7 files changed, 124 insertions, 0 deletions
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST index d01a0aad5a01..f31f15a5f873 100644 --- a/tools/perf/MANIFEST +++ b/tools/perf/MANIFEST | |||
@@ -18,6 +18,7 @@ tools/arch/x86/include/asm/atomic.h | |||
18 | tools/arch/x86/include/asm/rmwcc.h | 18 | tools/arch/x86/include/asm/rmwcc.h |
19 | tools/lib/traceevent | 19 | tools/lib/traceevent |
20 | tools/lib/api | 20 | tools/lib/api |
21 | tools/lib/bpf | ||
21 | tools/lib/hweight.c | 22 | tools/lib/hweight.c |
22 | tools/lib/rbtree.c | 23 | tools/lib/rbtree.c |
23 | tools/lib/symbol/kallsyms.c | 24 | tools/lib/symbol/kallsyms.c |
diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build index d20d6e6ab65b..c1518bdd0f1b 100644 --- a/tools/perf/tests/Build +++ b/tools/perf/tests/Build | |||
@@ -32,6 +32,7 @@ perf-y += sample-parsing.o | |||
32 | perf-y += parse-no-sample-id-all.o | 32 | perf-y += parse-no-sample-id-all.o |
33 | perf-y += kmod-path.o | 33 | perf-y += kmod-path.o |
34 | perf-y += thread-map.o | 34 | perf-y += thread-map.o |
35 | perf-y += llvm.o | ||
35 | 36 | ||
36 | perf-$(CONFIG_X86) += perf-time-to-tsc.o | 37 | perf-$(CONFIG_X86) += perf-time-to-tsc.o |
37 | 38 | ||
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index c1dde733c3a6..136cd934be66 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c | |||
@@ -175,6 +175,10 @@ static struct test { | |||
175 | .func = test__thread_map, | 175 | .func = test__thread_map, |
176 | }, | 176 | }, |
177 | { | 177 | { |
178 | .desc = "Test LLVM searching and compiling", | ||
179 | .func = test__llvm, | ||
180 | }, | ||
181 | { | ||
178 | .func = NULL, | 182 | .func = NULL, |
179 | }, | 183 | }, |
180 | }; | 184 | }; |
diff --git a/tools/perf/tests/llvm.c b/tools/perf/tests/llvm.c new file mode 100644 index 000000000000..a337356fd979 --- /dev/null +++ b/tools/perf/tests/llvm.c | |||
@@ -0,0 +1,98 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <bpf/libbpf.h> | ||
3 | #include <util/llvm-utils.h> | ||
4 | #include <util/cache.h> | ||
5 | #include "tests.h" | ||
6 | #include "debug.h" | ||
7 | |||
8 | static int perf_config_cb(const char *var, const char *val, | ||
9 | void *arg __maybe_unused) | ||
10 | { | ||
11 | return perf_default_config(var, val, arg); | ||
12 | } | ||
13 | |||
14 | /* | ||
15 | * Randomly give it a "version" section since we don't really load it | ||
16 | * into kernel | ||
17 | */ | ||
18 | static const char test_bpf_prog[] = | ||
19 | "__attribute__((section(\"do_fork\"), used)) " | ||
20 | "int fork(void *ctx) {return 0;} " | ||
21 | "char _license[] __attribute__((section(\"license\"), used)) = \"GPL\";" | ||
22 | "int _version __attribute__((section(\"version\"), used)) = 0x40100;"; | ||
23 | |||
24 | #ifdef HAVE_LIBBPF_SUPPORT | ||
25 | static int test__bpf_parsing(void *obj_buf, size_t obj_buf_sz) | ||
26 | { | ||
27 | struct bpf_object *obj; | ||
28 | |||
29 | obj = bpf_object__open_buffer(obj_buf, obj_buf_sz); | ||
30 | if (!obj) | ||
31 | return -1; | ||
32 | bpf_object__close(obj); | ||
33 | return 0; | ||
34 | } | ||
35 | #else | ||
36 | static int test__bpf_parsing(void *obj_buf __maybe_unused, | ||
37 | size_t obj_buf_sz __maybe_unused) | ||
38 | { | ||
39 | fprintf(stderr, " (skip bpf parsing)"); | ||
40 | return 0; | ||
41 | } | ||
42 | #endif | ||
43 | |||
44 | int test__llvm(void) | ||
45 | { | ||
46 | char *tmpl_new, *clang_opt_new; | ||
47 | void *obj_buf; | ||
48 | size_t obj_buf_sz; | ||
49 | int err, old_verbose; | ||
50 | |||
51 | perf_config(perf_config_cb, NULL); | ||
52 | |||
53 | /* | ||
54 | * Skip this test if user's .perfconfig doesn't set [llvm] section | ||
55 | * and clang is not found in $PATH, and this is not perf test -v | ||
56 | */ | ||
57 | if (verbose == 0 && !llvm_param.user_set_param && llvm__search_clang()) { | ||
58 | fprintf(stderr, " (no clang, try 'perf test -v LLVM')"); | ||
59 | return TEST_SKIP; | ||
60 | } | ||
61 | |||
62 | old_verbose = verbose; | ||
63 | /* | ||
64 | * llvm is verbosity when error. Suppress all error output if | ||
65 | * not 'perf test -v'. | ||
66 | */ | ||
67 | if (verbose == 0) | ||
68 | verbose = -1; | ||
69 | |||
70 | if (!llvm_param.clang_bpf_cmd_template) | ||
71 | return -1; | ||
72 | |||
73 | if (!llvm_param.clang_opt) | ||
74 | llvm_param.clang_opt = strdup(""); | ||
75 | |||
76 | err = asprintf(&tmpl_new, "echo '%s' | %s", test_bpf_prog, | ||
77 | llvm_param.clang_bpf_cmd_template); | ||
78 | if (err < 0) | ||
79 | return -1; | ||
80 | err = asprintf(&clang_opt_new, "-xc %s", llvm_param.clang_opt); | ||
81 | if (err < 0) | ||
82 | return -1; | ||
83 | |||
84 | llvm_param.clang_bpf_cmd_template = tmpl_new; | ||
85 | llvm_param.clang_opt = clang_opt_new; | ||
86 | err = llvm__compile_bpf("-", &obj_buf, &obj_buf_sz); | ||
87 | |||
88 | verbose = old_verbose; | ||
89 | if (err) { | ||
90 | if (!verbose) | ||
91 | fprintf(stderr, " (use -v to see error message)"); | ||
92 | return -1; | ||
93 | } | ||
94 | |||
95 | err = test__bpf_parsing(obj_buf, obj_buf_sz); | ||
96 | free(obj_buf); | ||
97 | return err; | ||
98 | } | ||
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index ebb47d96bc0b..bf113a247987 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h | |||
@@ -62,6 +62,7 @@ int test__fdarray__filter(void); | |||
62 | int test__fdarray__add(void); | 62 | int test__fdarray__add(void); |
63 | int test__kmod_path__parse(void); | 63 | int test__kmod_path__parse(void); |
64 | int test__thread_map(void); | 64 | int test__thread_map(void); |
65 | int test__llvm(void); | ||
65 | 66 | ||
66 | #if defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__) | 67 | #if defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__) |
67 | #ifdef HAVE_DWARF_UNWIND_SUPPORT | 68 | #ifdef HAVE_DWARF_UNWIND_SUPPORT |
diff --git a/tools/perf/util/llvm-utils.c b/tools/perf/util/llvm-utils.c index 5887bb8c1243..4f6a4780bd5f 100644 --- a/tools/perf/util/llvm-utils.c +++ b/tools/perf/util/llvm-utils.c | |||
@@ -22,6 +22,7 @@ struct llvm_param llvm_param = { | |||
22 | .clang_opt = NULL, | 22 | .clang_opt = NULL, |
23 | .kbuild_dir = NULL, | 23 | .kbuild_dir = NULL, |
24 | .kbuild_opts = NULL, | 24 | .kbuild_opts = NULL, |
25 | .user_set_param = false, | ||
25 | }; | 26 | }; |
26 | 27 | ||
27 | int perf_llvm_config(const char *var, const char *value) | 28 | int perf_llvm_config(const char *var, const char *value) |
@@ -42,6 +43,7 @@ int perf_llvm_config(const char *var, const char *value) | |||
42 | llvm_param.kbuild_opts = strdup(value); | 43 | llvm_param.kbuild_opts = strdup(value); |
43 | else | 44 | else |
44 | return -1; | 45 | return -1; |
46 | llvm_param.user_set_param = true; | ||
45 | return 0; | 47 | return 0; |
46 | } | 48 | } |
47 | 49 | ||
@@ -397,3 +399,10 @@ errout: | |||
397 | *p_obj_buf_sz = 0; | 399 | *p_obj_buf_sz = 0; |
398 | return err; | 400 | return err; |
399 | } | 401 | } |
402 | |||
403 | int llvm__search_clang(void) | ||
404 | { | ||
405 | char clang_path[PATH_MAX]; | ||
406 | |||
407 | return search_program(llvm_param.clang_path, "clang", clang_path); | ||
408 | } | ||
diff --git a/tools/perf/util/llvm-utils.h b/tools/perf/util/llvm-utils.h index d23adbca120b..5b3cf1c229e2 100644 --- a/tools/perf/util/llvm-utils.h +++ b/tools/perf/util/llvm-utils.h | |||
@@ -29,6 +29,13 @@ struct llvm_param { | |||
29 | * compiling. Should not be used for dynamic compiling. | 29 | * compiling. Should not be used for dynamic compiling. |
30 | */ | 30 | */ |
31 | const char *kbuild_opts; | 31 | const char *kbuild_opts; |
32 | /* | ||
33 | * Default is false. If one of the above fields is set by user | ||
34 | * explicitly then user_set_llvm is set to true. This is used | ||
35 | * for perf test. If user doesn't set anything in .perfconfig | ||
36 | * and clang is not found, don't trigger llvm test. | ||
37 | */ | ||
38 | bool user_set_param; | ||
32 | }; | 39 | }; |
33 | 40 | ||
34 | extern struct llvm_param llvm_param; | 41 | extern struct llvm_param llvm_param; |
@@ -36,4 +43,7 @@ extern int perf_llvm_config(const char *var, const char *value); | |||
36 | 43 | ||
37 | extern int llvm__compile_bpf(const char *path, void **p_obj_buf, | 44 | extern int llvm__compile_bpf(const char *path, void **p_obj_buf, |
38 | size_t *p_obj_buf_sz); | 45 | size_t *p_obj_buf_sz); |
46 | |||
47 | /* This function is for test__llvm() use only */ | ||
48 | extern int llvm__search_clang(void); | ||
39 | #endif | 49 | #endif |