aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2016-12-06 03:14:56 -0500
committerIngo Molnar <mingo@kernel.org>2016-12-06 03:14:56 -0500
commit34c4a42791bbc455e65a15d12dcd0b6b3c52ad13 (patch)
tree207c8a98f29d65fb3e809a84af62294e3e92c07e /tools/perf
parent78987584de42742bb46eaf55517a0475bfd7f032 (diff)
parentbec60e50af83741cde1786ab475d4bf472aed6f9 (diff)
Merge tag 'perf-core-for-mingo-20161205' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo: Fixes: - Do not show a bogus target address in 'perf annotate' for targetless powerpc jump instructions such as 'bctr' (Ravi Bangoria) - Fix tools/build race conditions with the fixdep utility (Jiri Olsa) - Fix building objtool with clang (Peter Foley) Infrastructure changes: - Support linking perf with clang and LLVM libraries, initially statically, but this limitation will be lifted and shared libraries, when available, will be preferred to the static build, that should, as with other features, be enabled explicitly (Wang Nan) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/Makefile.config62
-rw-r--r--tools/perf/Makefile.perf56
-rw-r--r--tools/perf/tests/Build1
-rw-r--r--tools/perf/tests/builtin-test.c9
-rw-r--r--tools/perf/tests/clang.c46
-rw-r--r--tools/perf/tests/llvm.h7
-rw-r--r--tools/perf/tests/make4
-rw-r--r--tools/perf/tests/perf-hooks.c14
-rw-r--r--tools/perf/tests/tests.h3
-rw-r--r--tools/perf/util/Build2
-rw-r--r--tools/perf/util/annotate.c3
-rw-r--r--tools/perf/util/bpf-loader.c19
-rw-r--r--tools/perf/util/c++/Build2
-rw-r--r--tools/perf/util/c++/clang-c.h43
-rw-r--r--tools/perf/util/c++/clang-test.cpp62
-rw-r--r--tools/perf/util/c++/clang.cpp195
-rw-r--r--tools/perf/util/c++/clang.h26
-rw-r--r--tools/perf/util/llvm-utils.c76
-rw-r--r--tools/perf/util/llvm-utils.h6
-rw-r--r--tools/perf/util/perf-hooks.c10
-rw-r--r--tools/perf/util/perf-hooks.h6
-rw-r--r--tools/perf/util/util-cxx.h26
22 files changed, 615 insertions, 63 deletions
diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
index 8a493d46fab9..09c2a9874f2f 100644
--- a/tools/perf/Makefile.config
+++ b/tools/perf/Makefile.config
@@ -136,6 +136,7 @@ endif
136# Treat warnings as errors unless directed not to 136# Treat warnings as errors unless directed not to
137ifneq ($(WERROR),0) 137ifneq ($(WERROR),0)
138 CFLAGS += -Werror 138 CFLAGS += -Werror
139 CXXFLAGS += -Werror
139endif 140endif
140 141
141ifndef DEBUG 142ifndef DEBUG
@@ -182,6 +183,13 @@ CFLAGS += -Wall
182CFLAGS += -Wextra 183CFLAGS += -Wextra
183CFLAGS += -std=gnu99 184CFLAGS += -std=gnu99
184 185
186CXXFLAGS += -std=gnu++11 -fno-exceptions -fno-rtti
187CXXFLAGS += -Wall
188CXXFLAGS += -fno-omit-frame-pointer
189CXXFLAGS += -ggdb3
190CXXFLAGS += -funwind-tables
191CXXFLAGS += -Wno-strict-aliasing
192
185# Enforce a non-executable stack, as we may regress (again) in the future by 193# Enforce a non-executable stack, as we may regress (again) in the future by
186# adding assembler files missing the .GNU-stack linker note. 194# adding assembler files missing the .GNU-stack linker note.
187LDFLAGS += -Wl,-z,noexecstack 195LDFLAGS += -Wl,-z,noexecstack
@@ -204,24 +212,27 @@ ifeq ($(DEBUG),0)
204 endif 212 endif
205endif 213endif
206 214
207CFLAGS += -I$(src-perf)/util/include 215INC_FLAGS += -I$(src-perf)/util/include
208CFLAGS += -I$(src-perf)/arch/$(ARCH)/include 216INC_FLAGS += -I$(src-perf)/arch/$(ARCH)/include
209CFLAGS += -I$(srctree)/tools/include/uapi 217INC_FLAGS += -I$(srctree)/tools/include/uapi
210CFLAGS += -I$(srctree)/tools/include/ 218INC_FLAGS += -I$(srctree)/tools/include/
211CFLAGS += -I$(srctree)/tools/arch/$(ARCH)/include/uapi 219INC_FLAGS += -I$(srctree)/tools/arch/$(ARCH)/include/uapi
212CFLAGS += -I$(srctree)/tools/arch/$(ARCH)/include/ 220INC_FLAGS += -I$(srctree)/tools/arch/$(ARCH)/include/
213CFLAGS += -I$(srctree)/tools/arch/$(ARCH)/ 221INC_FLAGS += -I$(srctree)/tools/arch/$(ARCH)/
214 222
215# $(obj-perf) for generated common-cmds.h 223# $(obj-perf) for generated common-cmds.h
216# $(obj-perf)/util for generated bison/flex headers 224# $(obj-perf)/util for generated bison/flex headers
217ifneq ($(OUTPUT),) 225ifneq ($(OUTPUT),)
218CFLAGS += -I$(obj-perf)/util 226INC_FLAGS += -I$(obj-perf)/util
219CFLAGS += -I$(obj-perf) 227INC_FLAGS += -I$(obj-perf)
220endif 228endif
221 229
222CFLAGS += -I$(src-perf)/util 230INC_FLAGS += -I$(src-perf)/util
223CFLAGS += -I$(src-perf) 231INC_FLAGS += -I$(src-perf)
224CFLAGS += -I$(srctree)/tools/lib/ 232INC_FLAGS += -I$(srctree)/tools/lib/
233
234CFLAGS += $(INC_FLAGS)
235CXXFLAGS += $(INC_FLAGS)
225 236
226CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE 237CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
227 238
@@ -783,6 +794,33 @@ ifndef NO_JVMTI
783 endif 794 endif
784endif 795endif
785 796
797USE_CXX = 0
798USE_CLANGLLVM = 0
799ifdef LIBCLANGLLVM
800 $(call feature_check,cxx)
801 ifneq ($(feature-cxx), 1)
802 msg := $(warning No g++ found, disable clang and llvm support. Please install g++)
803 else
804 $(call feature_check,llvm)
805 ifneq ($(feature-llvm), 1)
806 msg := $(warning No libLLVM found, disable clang and llvm support. Please install llvm-dev)
807 else
808 $(call feature_check,clang)
809 ifneq ($(feature-clang), 1)
810 msg := $(warning No libclang found, disable clang and llvm support. Please install libclang-dev)
811 else
812 CFLAGS += -DHAVE_LIBCLANGLLVM_SUPPORT
813 CXXFLAGS += -DHAVE_LIBCLANGLLVM_SUPPORT -I$(shell $(LLVM_CONFIG) --includedir)
814 $(call detected,CONFIG_CXX)
815 $(call detected,CONFIG_CLANGLLVM)
816 USE_CXX = 1
817 USE_LLVM = 1
818 USE_CLANG = 1
819 endif
820 endif
821 endif
822endif
823
786# Among the variables below, these: 824# Among the variables below, these:
787# perfexecdir 825# perfexecdir
788# template_dir 826# template_dir
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 3cb1df43ad3e..10495c9dbe71 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -88,6 +88,10 @@ include ../scripts/utilities.mak
88# and bypass the feature detection 88# and bypass the feature detection
89# 89#
90# Define NO_JVMTI if you do not want jvmti agent built 90# Define NO_JVMTI if you do not want jvmti agent built
91#
92# Define LIBCLANGLLVM if you DO want builtin clang and llvm support.
93# When selected, pass LLVM_CONFIG=/path/to/llvm-config to `make' if
94# llvm-config is not in $PATH.
91 95
92# As per kernel Makefile, avoid funny character set dependencies 96# As per kernel Makefile, avoid funny character set dependencies
93unexport LC_ALL 97unexport LC_ALL
@@ -143,6 +147,7 @@ endef
143$(call allow-override,CC,$(CROSS_COMPILE)gcc) 147$(call allow-override,CC,$(CROSS_COMPILE)gcc)
144$(call allow-override,AR,$(CROSS_COMPILE)ar) 148$(call allow-override,AR,$(CROSS_COMPILE)ar)
145$(call allow-override,LD,$(CROSS_COMPILE)ld) 149$(call allow-override,LD,$(CROSS_COMPILE)ld)
150$(call allow-override,CXX,$(CROSS_COMPILE)g++)
146 151
147LD += $(EXTRA_LDFLAGS) 152LD += $(EXTRA_LDFLAGS)
148 153
@@ -151,6 +156,7 @@ HOSTLD ?= ld
151HOSTAR ?= ar 156HOSTAR ?= ar
152 157
153PKG_CONFIG = $(CROSS_COMPILE)pkg-config 158PKG_CONFIG = $(CROSS_COMPILE)pkg-config
159LLVM_CONFIG ?= llvm-config
154 160
155RM = rm -f 161RM = rm -f
156LN = ln -f 162LN = ln -f
@@ -171,7 +177,7 @@ SUBCMD_DIR = $(srctree)/tools/lib/subcmd/
171# non-config cases 177# non-config cases
172config := 1 178config := 1
173 179
174NON_CONFIG_TARGETS := clean TAGS tags cscope help install-doc 180NON_CONFIG_TARGETS := clean TAGS tags cscope help install-doc install-man install-html install-info install-pdf doc man html info pdf
175 181
176ifdef MAKECMDGOALS 182ifdef MAKECMDGOALS
177ifeq ($(filter-out $(NON_CONFIG_TARGETS),$(MAKECMDGOALS)),) 183ifeq ($(filter-out $(NON_CONFIG_TARGETS),$(MAKECMDGOALS)),)
@@ -262,17 +268,6 @@ python-clean := $(call QUIET_CLEAN, python) $(RM) -r $(PYTHON_EXTBUILD) $(OUTPUT
262PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources) 268PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources)
263PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBAPI) 269PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBAPI)
264 270
265$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) $(LIBTRACEEVENT_DYNAMIC_LIST)
266 $(QUIET_GEN)LDSHARED="$(CC) -pthread -shared" \
267 CFLAGS='$(CFLAGS)' LDFLAGS='$(LDFLAGS) $(LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS)' \
268 $(PYTHON_WORD) util/setup.py \
269 --quiet build_ext; \
270 mkdir -p $(OUTPUT)python && \
271 cp $(PYTHON_EXTBUILD_LIB)perf.so $(OUTPUT)python/
272#
273# No Perl scripts right now:
274#
275
276SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) 271SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH))
277 272
278PROGRAMS += $(OUTPUT)perf 273PROGRAMS += $(OUTPUT)perf
@@ -325,11 +320,6 @@ endif
325ifndef NO_GTK2 320ifndef NO_GTK2
326 ALL_PROGRAMS += $(OUTPUT)libperf-gtk.so 321 ALL_PROGRAMS += $(OUTPUT)libperf-gtk.so
327 GTK_IN := $(OUTPUT)gtk-in.o 322 GTK_IN := $(OUTPUT)gtk-in.o
328
329install-gtk: $(OUTPUT)libperf-gtk.so
330 $(call QUIET_INSTALL, 'GTK UI') \
331 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(libdir_SQ)'; \
332 $(INSTALL) $(OUTPUT)libperf-gtk.so '$(DESTDIR_SQ)$(libdir_SQ)'
333endif 323endif
334 324
335ifdef ASCIIDOC8 325ifdef ASCIIDOC8
@@ -338,6 +328,21 @@ endif
338 328
339LIBS = -Wl,--whole-archive $(PERFLIBS) -Wl,--no-whole-archive -Wl,--start-group $(EXTLIBS) -Wl,--end-group 329LIBS = -Wl,--whole-archive $(PERFLIBS) -Wl,--no-whole-archive -Wl,--start-group $(EXTLIBS) -Wl,--end-group
340 330
331ifeq ($(USE_CLANG), 1)
332 CLANGLIBS_LIST = AST Basic CodeGen Driver Frontend Lex Tooling Edit Sema Analysis Parse Serialization
333 LIBCLANG = $(foreach l,$(CLANGLIBS_LIST),$(wildcard $(shell $(LLVM_CONFIG) --libdir)/libclang$(l).a))
334 LIBS += -Wl,--start-group $(LIBCLANG) -Wl,--end-group
335endif
336
337ifeq ($(USE_LLVM), 1)
338 LIBLLVM = $(shell $(LLVM_CONFIG) --libs all) $(shell $(LLVM_CONFIG) --system-libs)
339 LIBS += -L$(shell $(LLVM_CONFIG) --libdir) $(LIBLLVM)
340endif
341
342ifeq ($(USE_CXX), 1)
343 LIBS += -lstdc++
344endif
345
341export INSTALL SHELL_PATH 346export INSTALL SHELL_PATH
342 347
343### Build rules 348### Build rules
@@ -346,6 +351,14 @@ SHELL = $(SHELL_PATH)
346 351
347all: shell_compatibility_test $(ALL_PROGRAMS) $(LANG_BINDINGS) $(OTHER_PROGRAMS) 352all: shell_compatibility_test $(ALL_PROGRAMS) $(LANG_BINDINGS) $(OTHER_PROGRAMS)
348 353
354$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) $(LIBTRACEEVENT_DYNAMIC_LIST)
355 $(QUIET_GEN)LDSHARED="$(CC) -pthread -shared" \
356 CFLAGS='$(CFLAGS)' LDFLAGS='$(LDFLAGS) $(LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS)' \
357 $(PYTHON_WORD) util/setup.py \
358 --quiet build_ext; \
359 mkdir -p $(OUTPUT)python && \
360 cp $(PYTHON_EXTBUILD_LIB)perf.so $(OUTPUT)python/
361
349please_set_SHELL_PATH_to_a_more_modern_shell: 362please_set_SHELL_PATH_to_a_more_modern_shell:
350 $(Q)$$(:) 363 $(Q)$$(:)
351 364
@@ -356,7 +369,7 @@ strip: $(PROGRAMS) $(OUTPUT)perf
356 369
357PERF_IN := $(OUTPUT)perf-in.o 370PERF_IN := $(OUTPUT)perf-in.o
358 371
359export srctree OUTPUT RM CC LD AR CFLAGS V BISON FLEX AWK 372export srctree OUTPUT RM CC CXX LD AR CFLAGS CXXFLAGS V BISON FLEX AWK
360export HOSTCC HOSTLD HOSTAR 373export HOSTCC HOSTLD HOSTAR
361include $(srctree)/tools/build/Makefile.include 374include $(srctree)/tools/build/Makefile.include
362 375
@@ -691,7 +704,14 @@ check: $(OUTPUT)common-cmds.h
691 704
692### Installation rules 705### Installation rules
693 706
707ifndef NO_GTK2
708install-gtk: $(OUTPUT)libperf-gtk.so
709 $(call QUIET_INSTALL, 'GTK UI') \
710 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(libdir_SQ)'; \
711 $(INSTALL) $(OUTPUT)libperf-gtk.so '$(DESTDIR_SQ)$(libdir_SQ)'
712else
694install-gtk: 713install-gtk:
714endif
695 715
696install-tools: all install-gtk 716install-tools: all install-gtk
697 $(call QUIET_INSTALL, binaries) \ 717 $(call QUIET_INSTALL, binaries) \
diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index af3ec94869aa..6676c2dd6dcb 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -43,6 +43,7 @@ perf-y += sdt.o
43perf-y += is_printable_array.o 43perf-y += is_printable_array.o
44perf-y += bitmap.o 44perf-y += bitmap.o
45perf-y += perf-hooks.o 45perf-y += perf-hooks.o
46perf-y += clang.o
46 47
47$(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build 48$(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build
48 $(call rule_mkdir) 49 $(call rule_mkdir)
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index d1bec0444be7..23605202d4a1 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -234,6 +234,15 @@ static struct test generic_tests[] = {
234 .func = test__perf_hooks, 234 .func = test__perf_hooks,
235 }, 235 },
236 { 236 {
237 .desc = "builtin clang support",
238 .func = test__clang,
239 .subtest = {
240 .skip_if_fail = true,
241 .get_nr = test__clang_subtest_get_nr,
242 .get_desc = test__clang_subtest_get_desc,
243 }
244 },
245 {
237 .func = NULL, 246 .func = NULL,
238 }, 247 },
239}; 248};
diff --git a/tools/perf/tests/clang.c b/tools/perf/tests/clang.c
new file mode 100644
index 000000000000..f853e242a86c
--- /dev/null
+++ b/tools/perf/tests/clang.c
@@ -0,0 +1,46 @@
1#include "tests.h"
2#include "debug.h"
3#include "util.h"
4#include "c++/clang-c.h"
5
6static struct {
7 int (*func)(void);
8 const char *desc;
9} clang_testcase_table[] = {
10#ifdef HAVE_LIBCLANGLLVM_SUPPORT
11 {
12 .func = test__clang_to_IR,
13 .desc = "builtin clang compile C source to IR",
14 },
15 {
16 .func = test__clang_to_obj,
17 .desc = "builtin clang compile C source to ELF object",
18 },
19#endif
20};
21
22int test__clang_subtest_get_nr(void)
23{
24 return (int)ARRAY_SIZE(clang_testcase_table);
25}
26
27const char *test__clang_subtest_get_desc(int i)
28{
29 if (i < 0 || i >= (int)ARRAY_SIZE(clang_testcase_table))
30 return NULL;
31 return clang_testcase_table[i].desc;
32}
33
34#ifndef HAVE_LIBCLANGLLVM_SUPPORT
35int test__clang(int i __maybe_unused)
36{
37 return TEST_SKIP;
38}
39#else
40int test__clang(int i)
41{
42 if (i < 0 || i >= (int)ARRAY_SIZE(clang_testcase_table))
43 return TEST_FAIL;
44 return clang_testcase_table[i].func();
45}
46#endif
diff --git a/tools/perf/tests/llvm.h b/tools/perf/tests/llvm.h
index 0eaa604be99d..b83571758d83 100644
--- a/tools/perf/tests/llvm.h
+++ b/tools/perf/tests/llvm.h
@@ -1,6 +1,10 @@
1#ifndef PERF_TEST_LLVM_H 1#ifndef PERF_TEST_LLVM_H
2#define PERF_TEST_LLVM_H 2#define PERF_TEST_LLVM_H
3 3
4#ifdef __cplusplus
5extern "C" {
6#endif
7
4#include <stddef.h> /* for size_t */ 8#include <stddef.h> /* for size_t */
5#include <stdbool.h> /* for bool */ 9#include <stdbool.h> /* for bool */
6 10
@@ -20,4 +24,7 @@ enum test_llvm__testcase {
20int test_llvm__fetch_bpf_obj(void **p_obj_buf, size_t *p_obj_buf_sz, 24int test_llvm__fetch_bpf_obj(void **p_obj_buf, size_t *p_obj_buf_sz,
21 enum test_llvm__testcase index, bool force, 25 enum test_llvm__testcase index, bool force,
22 bool *should_load_fail); 26 bool *should_load_fail);
27#ifdef __cplusplus
28}
29#endif
23#endif 30#endif
diff --git a/tools/perf/tests/make b/tools/perf/tests/make
index 08ed7f12cc37..0784748f1670 100644
--- a/tools/perf/tests/make
+++ b/tools/perf/tests/make
@@ -83,6 +83,7 @@ make_no_libbpf := NO_LIBBPF=1
83make_no_libcrypto := NO_LIBCRYPTO=1 83make_no_libcrypto := NO_LIBCRYPTO=1
84make_with_babeltrace:= LIBBABELTRACE=1 84make_with_babeltrace:= LIBBABELTRACE=1
85make_no_sdt := NO_SDT=1 85make_no_sdt := NO_SDT=1
86make_with_clangllvm := LIBCLANGLLVM=1
86make_tags := tags 87make_tags := tags
87make_cscope := cscope 88make_cscope := cscope
88make_help := help 89make_help := help
@@ -139,6 +140,7 @@ run += make_no_libbionic
139run += make_no_auxtrace 140run += make_no_auxtrace
140run += make_no_libbpf 141run += make_no_libbpf
141run += make_with_babeltrace 142run += make_with_babeltrace
143run += make_with_clangllvm
142run += make_help 144run += make_help
143run += make_doc 145run += make_doc
144run += make_perf_o 146run += make_perf_o
@@ -278,7 +280,7 @@ endif
278 280
279MAKEFLAGS := --no-print-directory 281MAKEFLAGS := --no-print-directory
280 282
281clean := @(cd $(PERF); $(MAKE_F) -s $(O_OPT) clean >/dev/null) 283clean := @(cd $(PERF); $(MAKE_F) -s $(O_OPT) clean >/dev/null && $(MAKE) -s $(O_OPT) -C ../build clean >/dev/null)
282 284
283$(run): 285$(run):
284 $(call clean) 286 $(call clean)
diff --git a/tools/perf/tests/perf-hooks.c b/tools/perf/tests/perf-hooks.c
index 9338cb2c25ab..665ecc19671c 100644
--- a/tools/perf/tests/perf-hooks.c
+++ b/tools/perf/tests/perf-hooks.c
@@ -15,13 +15,13 @@ static void sigsegv_handler(int sig __maybe_unused)
15 exit(-1); 15 exit(-1);
16} 16}
17 17
18static int hook_flags;
19 18
20static void the_hook(void) 19static void the_hook(void *_hook_flags)
21{ 20{
21 int *hook_flags = _hook_flags;
22 int *p = NULL; 22 int *p = NULL;
23 23
24 hook_flags = 1234; 24 *hook_flags = 1234;
25 25
26 /* Generate a segfault, test perf_hooks__recover */ 26 /* Generate a segfault, test perf_hooks__recover */
27 *p = 0; 27 *p = 0;
@@ -29,13 +29,17 @@ static void the_hook(void)
29 29
30int test__perf_hooks(int subtest __maybe_unused) 30int test__perf_hooks(int subtest __maybe_unused)
31{ 31{
32 int hook_flags = 0;
33
32 signal(SIGSEGV, sigsegv_handler); 34 signal(SIGSEGV, sigsegv_handler);
33 perf_hooks__set_hook("test", the_hook); 35 perf_hooks__set_hook("test", the_hook, &hook_flags);
34 perf_hooks__invoke_test(); 36 perf_hooks__invoke_test();
35 37
36 /* hook is triggered? */ 38 /* hook is triggered? */
37 if (hook_flags != 1234) 39 if (hook_flags != 1234) {
40 pr_debug("Setting failed: %d (%p)\n", hook_flags, &hook_flags);
38 return TEST_FAIL; 41 return TEST_FAIL;
42 }
39 43
40 /* the buggy hook is removed? */ 44 /* the buggy hook is removed? */
41 if (perf_hooks__get_hook("test")) 45 if (perf_hooks__get_hook("test"))
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 3a1f98f291ba..0d7b251305af 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -92,6 +92,9 @@ int test__sdt_event(int subtest);
92int test__is_printable_array(int subtest); 92int test__is_printable_array(int subtest);
93int test__bitmap_print(int subtest); 93int test__bitmap_print(int subtest);
94int test__perf_hooks(int subtest); 94int test__perf_hooks(int subtest);
95int test__clang(int subtest);
96const char *test__clang_subtest_get_desc(int subtest);
97int test__clang_subtest_get_nr(void);
95 98
96#if defined(__arm__) || defined(__aarch64__) 99#if defined(__arm__) || defined(__aarch64__)
97#ifdef HAVE_DWARF_UNWIND_SUPPORT 100#ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index bdad82a9812d..3840e3a87057 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -126,6 +126,8 @@ endif
126 126
127libperf-y += perf-hooks.o 127libperf-y += perf-hooks.o
128 128
129libperf-$(CONFIG_CXX) += c++/
130
129CFLAGS_config.o += -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))" 131CFLAGS_config.o += -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))"
130# avoid compiler warnings in 32-bit mode 132# avoid compiler warnings in 32-bit mode
131CFLAGS_genelf_debug.o += -Wno-packed 133CFLAGS_genelf_debug.o += -Wno-packed
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 4012b1de2813..ea7e0de4b9c1 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -237,6 +237,9 @@ static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *op
237static int jump__scnprintf(struct ins *ins, char *bf, size_t size, 237static int jump__scnprintf(struct ins *ins, char *bf, size_t size,
238 struct ins_operands *ops) 238 struct ins_operands *ops)
239{ 239{
240 if (!ops->target.addr)
241 return ins__raw_scnprintf(ins, bf, size, ops);
242
240 return scnprintf(bf, size, "%-6.6s %" PRIx64, ins->name, ops->target.offset); 243 return scnprintf(bf, size, "%-6.6s %" PRIx64, ins->name, ops->target.offset);
241} 244}
242 245
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index a5fd275238f7..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,10 +86,21 @@ 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);
100
101 if (!IS_ERR(obj) && llvm_param.dump_obj)
102 llvm__dump_obj(filename, obj_buf, obj_buf_sz);
103
93 free(obj_buf); 104 free(obj_buf);
94 } else 105 } else
95 obj = bpf_object__open(filename); 106 obj = bpf_object__open(filename);
diff --git a/tools/perf/util/c++/Build b/tools/perf/util/c++/Build
new file mode 100644
index 000000000000..988fef1b11d7
--- /dev/null
+++ b/tools/perf/util/c++/Build
@@ -0,0 +1,2 @@
1libperf-$(CONFIG_CLANGLLVM) += clang.o
2libperf-$(CONFIG_CLANGLLVM) += clang-test.o
diff --git a/tools/perf/util/c++/clang-c.h b/tools/perf/util/c++/clang-c.h
new file mode 100644
index 000000000000..0eadd792ab1f
--- /dev/null
+++ b/tools/perf/util/c++/clang-c.h
@@ -0,0 +1,43 @@
1#ifndef PERF_UTIL_CLANG_C_H
2#define PERF_UTIL_CLANG_C_H
3
4#include <stddef.h> /* for size_t */
5#include <util-cxx.h> /* for __maybe_unused */
6
7#ifdef __cplusplus
8extern "C" {
9#endif
10
11#ifdef HAVE_LIBCLANGLLVM_SUPPORT
12extern void perf_clang__init(void);
13extern void perf_clang__cleanup(void);
14
15extern int test__clang_to_IR(void);
16extern int test__clang_to_obj(void);
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
40#ifdef __cplusplus
41}
42#endif
43#endif
diff --git a/tools/perf/util/c++/clang-test.cpp b/tools/perf/util/c++/clang-test.cpp
new file mode 100644
index 000000000000..9b11e8c82798
--- /dev/null
+++ b/tools/perf/util/c++/clang-test.cpp
@@ -0,0 +1,62 @@
1#include "clang.h"
2#include "clang-c.h"
3#include "llvm/IR/Function.h"
4#include "llvm/IR/LLVMContext.h"
5
6#include <util-cxx.h>
7#include <tests/llvm.h>
8#include <string>
9
10class perf_clang_scope {
11public:
12 explicit perf_clang_scope() {perf_clang__init();}
13 ~perf_clang_scope() {perf_clang__cleanup();}
14};
15
16static std::unique_ptr<llvm::Module>
17__test__clang_to_IR(void)
18{
19 unsigned int kernel_version;
20
21 if (fetch_kernel_version(&kernel_version, NULL, 0))
22 return std::unique_ptr<llvm::Module>(nullptr);
23
24 std::string cflag_kver("-DLINUX_VERSION_CODE=" +
25 std::to_string(kernel_version));
26
27 std::unique_ptr<llvm::Module> M =
28 perf::getModuleFromSource({cflag_kver.c_str()},
29 "perf-test.c",
30 test_llvm__bpf_base_prog);
31 return M;
32}
33
34extern "C" {
35int test__clang_to_IR(void)
36{
37 perf_clang_scope _scope;
38
39 auto M = __test__clang_to_IR();
40 if (!M)
41 return -1;
42 for (llvm::Function& F : *M)
43 if (F.getName() == "bpf_func__SyS_epoll_wait")
44 return 0;
45 return -1;
46}
47
48int test__clang_to_obj(void)
49{
50 perf_clang_scope _scope;
51
52 auto M = __test__clang_to_IR();
53 if (!M)
54 return -1;
55
56 auto Buffer = perf::getBPFObjectFromModule(&*M);
57 if (!Buffer)
58 return -1;
59 return 0;
60}
61
62}
diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp
new file mode 100644
index 000000000000..1e974152cac2
--- /dev/null
+++ b/tools/perf/util/c++/clang.cpp
@@ -0,0 +1,195 @@
1/*
2 * llvm C frontend for perf. Support dynamically compile C file
3 *
4 * Inspired by clang example code:
5 * http://llvm.org/svn/llvm-project/cfe/trunk/examples/clang-interpreter/main.cpp
6 *
7 * Copyright (C) 2016 Wang Nan <wangnan0@huawei.com>
8 * Copyright (C) 2016 Huawei Inc.
9 */
10
11#include "clang/CodeGen/CodeGenAction.h"
12#include "clang/Frontend/CompilerInvocation.h"
13#include "clang/Frontend/CompilerInstance.h"
14#include "clang/Frontend/TextDiagnosticPrinter.h"
15#include "clang/Tooling/Tooling.h"
16#include "llvm/IR/LegacyPassManager.h"
17#include "llvm/IR/Module.h"
18#include "llvm/Option/Option.h"
19#include "llvm/Support/FileSystem.h"
20#include "llvm/Support/ManagedStatic.h"
21#include "llvm/Support/TargetRegistry.h"
22#include "llvm/Support/TargetSelect.h"
23#include "llvm/Target/TargetMachine.h"
24#include "llvm/Target/TargetOptions.h"
25#include <memory>
26
27#include "clang.h"
28#include "clang-c.h"
29
30namespace perf {
31
32static std::unique_ptr<llvm::LLVMContext> LLVMCtx;
33
34using namespace clang;
35
36static CompilerInvocation *
37createCompilerInvocation(llvm::opt::ArgStringList CFlags, StringRef& Path,
38 DiagnosticsEngine& Diags)
39{
40 llvm::opt::ArgStringList CCArgs {
41 "-cc1",
42 "-triple", "bpf-pc-linux",
43 "-fsyntax-only",
44 "-ferror-limit", "19",
45 "-fmessage-length", "127",
46 "-O2",
47 "-nostdsysteminc",
48 "-nobuiltininc",
49 "-vectorize-loops",
50 "-vectorize-slp",
51 "-Wno-unused-value",
52 "-Wno-pointer-sign",
53 "-x", "c"};
54
55 CCArgs.append(CFlags.begin(), CFlags.end());
56 CompilerInvocation *CI = tooling::newInvocation(&Diags, CCArgs);
57
58 FrontendOptions& Opts = CI->getFrontendOpts();
59 Opts.Inputs.clear();
60 Opts.Inputs.emplace_back(Path, IK_C);
61 return CI;
62}
63
64static std::unique_ptr<llvm::Module>
65getModuleFromSource(llvm::opt::ArgStringList CFlags,
66 StringRef Path, IntrusiveRefCntPtr<vfs::FileSystem> VFS)
67{
68 CompilerInstance Clang;
69 Clang.createDiagnostics();
70
71 Clang.setVirtualFileSystem(&*VFS);
72
73 IntrusiveRefCntPtr<CompilerInvocation> CI =
74 createCompilerInvocation(std::move(CFlags), Path,
75 Clang.getDiagnostics());
76 Clang.setInvocation(&*CI);
77
78 std::unique_ptr<CodeGenAction> Act(new EmitLLVMOnlyAction(&*LLVMCtx));
79 if (!Clang.ExecuteAction(*Act))
80 return std::unique_ptr<llvm::Module>(nullptr);
81
82 return Act->takeModule();
83}
84
85std::unique_ptr<llvm::Module>
86getModuleFromSource(llvm::opt::ArgStringList CFlags,
87 StringRef Name, StringRef Content)
88{
89 using namespace vfs;
90
91 llvm::IntrusiveRefCntPtr<OverlayFileSystem> OverlayFS(
92 new OverlayFileSystem(getRealFileSystem()));
93 llvm::IntrusiveRefCntPtr<InMemoryFileSystem> MemFS(
94 new InMemoryFileSystem(true));
95
96 /*
97 * pushOverlay helps setting working dir for MemFS. Must call
98 * before addFile.
99 */
100 OverlayFS->pushOverlay(MemFS);
101 MemFS->addFile(Twine(Name), 0, llvm::MemoryBuffer::getMemBuffer(Content));
102
103 return getModuleFromSource(std::move(CFlags), Name, OverlayFS);
104}
105
106std::unique_ptr<llvm::Module>
107getModuleFromSource(llvm::opt::ArgStringList CFlags, StringRef Path)
108{
109 IntrusiveRefCntPtr<vfs::FileSystem> VFS(vfs::getRealFileSystem());
110 return getModuleFromSource(std::move(CFlags), Path, VFS);
111}
112
113std::unique_ptr<llvm::SmallVectorImpl<char>>
114getBPFObjectFromModule(llvm::Module *Module)
115{
116 using namespace llvm;
117
118 std::string TargetTriple("bpf-pc-linux");
119 std::string Error;
120 const Target* Target = TargetRegistry::lookupTarget(TargetTriple, Error);
121 if (!Target) {
122 llvm::errs() << Error;
123 return std::unique_ptr<llvm::SmallVectorImpl<char>>(nullptr);
124 }
125
126 llvm::TargetOptions Opt;
127 TargetMachine *TargetMachine =
128 Target->createTargetMachine(TargetTriple,
129 "generic", "",
130 Opt, Reloc::Static);
131
132 Module->setDataLayout(TargetMachine->createDataLayout());
133 Module->setTargetTriple(TargetTriple);
134
135 std::unique_ptr<SmallVectorImpl<char>> Buffer(new SmallVector<char, 0>());
136 raw_svector_ostream ostream(*Buffer);
137
138 legacy::PassManager PM;
139 if (TargetMachine->addPassesToEmitFile(PM, ostream,
140 TargetMachine::CGFT_ObjectFile)) {
141 llvm::errs() << "TargetMachine can't emit a file of this type\n";
142 return std::unique_ptr<llvm::SmallVectorImpl<char>>(nullptr);;
143 }
144 PM.run(*Module);
145
146 return std::move(Buffer);
147}
148
149}
150
151extern "C" {
152void perf_clang__init(void)
153{
154 perf::LLVMCtx.reset(new llvm::LLVMContext());
155 LLVMInitializeBPFTargetInfo();
156 LLVMInitializeBPFTarget();
157 LLVMInitializeBPFTargetMC();
158 LLVMInitializeBPFAsmPrinter();
159}
160
161void perf_clang__cleanup(void)
162{
163 perf::LLVMCtx.reset(nullptr);
164 llvm::llvm_shutdown();
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}
195}
diff --git a/tools/perf/util/c++/clang.h b/tools/perf/util/c++/clang.h
new file mode 100644
index 000000000000..dd8b0427550d
--- /dev/null
+++ b/tools/perf/util/c++/clang.h
@@ -0,0 +1,26 @@
1#ifndef PERF_UTIL_CLANG_H
2#define PERF_UTIL_CLANG_H
3
4#include "llvm/ADT/StringRef.h"
5#include "llvm/IR/LLVMContext.h"
6#include "llvm/IR/Module.h"
7#include "llvm/Option/Option.h"
8#include <memory>
9
10namespace perf {
11
12using namespace llvm;
13
14std::unique_ptr<Module>
15getModuleFromSource(opt::ArgStringList CFlags,
16 StringRef Name, StringRef Content);
17
18std::unique_ptr<Module>
19getModuleFromSource(opt::ArgStringList CFlags,
20 StringRef Path);
21
22std::unique_ptr<llvm::SmallVectorImpl<char>>
23getBPFObjectFromModule(llvm::Module *Module);
24
25}
26#endif
diff --git a/tools/perf/util/llvm-utils.c b/tools/perf/util/llvm-utils.c
index 27b6f303720a..b23ff44cf214 100644
--- a/tools/perf/util/llvm-utils.c
+++ b/tools/perf/util/llvm-utils.c
@@ -7,6 +7,7 @@
7#include <limits.h> 7#include <limits.h>
8#include <stdio.h> 8#include <stdio.h>
9#include <stdlib.h> 9#include <stdlib.h>
10#include <linux/err.h>
10#include "debug.h" 11#include "debug.h"
11#include "llvm-utils.h" 12#include "llvm-utils.h"
12#include "config.h" 13#include "config.h"
@@ -282,9 +283,10 @@ static const char *kinc_fetch_script =
282"rm -rf $TMPDIR\n" 283"rm -rf $TMPDIR\n"
283"exit $RET\n"; 284"exit $RET\n";
284 285
285static inline void 286void llvm__get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts)
286get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts)
287{ 287{
288 static char *saved_kbuild_dir;
289 static char *saved_kbuild_include_opts;
288 int err; 290 int err;
289 291
290 if (!kbuild_dir || !kbuild_include_opts) 292 if (!kbuild_dir || !kbuild_include_opts)
@@ -293,10 +295,28 @@ get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts)
293 *kbuild_dir = NULL; 295 *kbuild_dir = NULL;
294 *kbuild_include_opts = NULL; 296 *kbuild_include_opts = NULL;
295 297
298 if (saved_kbuild_dir && saved_kbuild_include_opts &&
299 !IS_ERR(saved_kbuild_dir) && !IS_ERR(saved_kbuild_include_opts)) {
300 *kbuild_dir = strdup(saved_kbuild_dir);
301 *kbuild_include_opts = strdup(saved_kbuild_include_opts);
302
303 if (*kbuild_dir && *kbuild_include_opts)
304 return;
305
306 zfree(kbuild_dir);
307 zfree(kbuild_include_opts);
308 /*
309 * Don't fall through: it may breaks saved_kbuild_dir and
310 * saved_kbuild_include_opts if detect them again when
311 * memory is low.
312 */
313 return;
314 }
315
296 if (llvm_param.kbuild_dir && !llvm_param.kbuild_dir[0]) { 316 if (llvm_param.kbuild_dir && !llvm_param.kbuild_dir[0]) {
297 pr_debug("[llvm.kbuild-dir] is set to \"\" deliberately.\n"); 317 pr_debug("[llvm.kbuild-dir] is set to \"\" deliberately.\n");
298 pr_debug("Skip kbuild options detection.\n"); 318 pr_debug("Skip kbuild options detection.\n");
299 return; 319 goto errout;
300 } 320 }
301 321
302 err = detect_kbuild_dir(kbuild_dir); 322 err = detect_kbuild_dir(kbuild_dir);
@@ -306,7 +326,7 @@ get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts)
306"Hint:\tSet correct kbuild directory using 'kbuild-dir' option in [llvm]\n" 326"Hint:\tSet correct kbuild directory using 'kbuild-dir' option in [llvm]\n"
307" \tsection of ~/.perfconfig or set it to \"\" to suppress kbuild\n" 327" \tsection of ~/.perfconfig or set it to \"\" to suppress kbuild\n"
308" \tdetection.\n\n"); 328" \tdetection.\n\n");
309 return; 329 goto errout;
310 } 330 }
311 331
312 pr_debug("Kernel build dir is set to %s\n", *kbuild_dir); 332 pr_debug("Kernel build dir is set to %s\n", *kbuild_dir);
@@ -325,14 +345,43 @@ get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts)
325 345
326 free(*kbuild_dir); 346 free(*kbuild_dir);
327 *kbuild_dir = NULL; 347 *kbuild_dir = NULL;
328 return; 348 goto errout;
329 } 349 }
330 350
331 pr_debug("include option is set to %s\n", *kbuild_include_opts); 351 pr_debug("include option is set to %s\n", *kbuild_include_opts);
352
353 saved_kbuild_dir = strdup(*kbuild_dir);
354 saved_kbuild_include_opts = strdup(*kbuild_include_opts);
355
356 if (!saved_kbuild_dir || !saved_kbuild_include_opts) {
357 zfree(&saved_kbuild_dir);
358 zfree(&saved_kbuild_include_opts);
359 }
360 return;
361errout:
362 saved_kbuild_dir = ERR_PTR(-EINVAL);
363 saved_kbuild_include_opts = ERR_PTR(-EINVAL);
332} 364}
333 365
334static void 366int llvm__get_nr_cpus(void)
335dump_obj(const char *path, void *obj_buf, size_t size) 367{
368 static int nr_cpus_avail = 0;
369 char serr[STRERR_BUFSIZE];
370
371 if (nr_cpus_avail > 0)
372 return nr_cpus_avail;
373
374 nr_cpus_avail = sysconf(_SC_NPROCESSORS_CONF);
375 if (nr_cpus_avail <= 0) {
376 pr_err(
377"WARNING:\tunable to get available CPUs in this system: %s\n"
378" \tUse 128 instead.\n", str_error_r(errno, serr, sizeof(serr)));
379 nr_cpus_avail = 128;
380 }
381 return nr_cpus_avail;
382}
383
384void llvm__dump_obj(const char *path, void *obj_buf, size_t size)
336{ 385{
337 char *obj_path = strdup(path); 386 char *obj_path = strdup(path);
338 FILE *fp; 387 FILE *fp;
@@ -406,15 +455,9 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
406 * This is an optional work. Even it fail we can continue our 455 * This is an optional work. Even it fail we can continue our
407 * work. Needn't to check error return. 456 * work. Needn't to check error return.
408 */ 457 */
409 get_kbuild_opts(&kbuild_dir, &kbuild_include_opts); 458 llvm__get_kbuild_opts(&kbuild_dir, &kbuild_include_opts);
410 459
411 nr_cpus_avail = sysconf(_SC_NPROCESSORS_CONF); 460 nr_cpus_avail = llvm__get_nr_cpus();
412 if (nr_cpus_avail <= 0) {
413 pr_err(
414"WARNING:\tunable to get available CPUs in this system: %s\n"
415" \tUse 128 instead.\n", str_error_r(errno, serr, sizeof(serr)));
416 nr_cpus_avail = 128;
417 }
418 snprintf(nr_cpus_avail_str, sizeof(nr_cpus_avail_str), "%d", 461 snprintf(nr_cpus_avail_str, sizeof(nr_cpus_avail_str), "%d",
419 nr_cpus_avail); 462 nr_cpus_avail);
420 463
@@ -453,9 +496,6 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
453 free(kbuild_dir); 496 free(kbuild_dir);
454 free(kbuild_include_opts); 497 free(kbuild_include_opts);
455 498
456 if (llvm_param.dump_obj)
457 dump_obj(path, obj_buf, obj_buf_sz);
458
459 if (!p_obj_buf) 499 if (!p_obj_buf)
460 free(obj_buf); 500 free(obj_buf);
461 else 501 else
diff --git a/tools/perf/util/llvm-utils.h b/tools/perf/util/llvm-utils.h
index 9f501cef06a1..c87a2a92a88f 100644
--- a/tools/perf/util/llvm-utils.h
+++ b/tools/perf/util/llvm-utils.h
@@ -50,4 +50,10 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf, size_t *p_obj_buf_sz);
50 50
51/* This function is for test__llvm() use only */ 51/* This function is for test__llvm() use only */
52int llvm__search_clang(void); 52int llvm__search_clang(void);
53
54/* Following functions are reused by builtin clang support */
55void llvm__get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts);
56int llvm__get_nr_cpus(void);
57
58void llvm__dump_obj(const char *path, void *obj_buf, size_t size);
53#endif 59#endif
diff --git a/tools/perf/util/perf-hooks.c b/tools/perf/util/perf-hooks.c
index 4ce88e37dd63..cb368306b12b 100644
--- a/tools/perf/util/perf-hooks.c
+++ b/tools/perf/util/perf-hooks.c
@@ -27,7 +27,7 @@ void perf_hooks__invoke(const struct perf_hook_desc *desc)
27 *(current_perf_hook->p_hook_func) = NULL; 27 *(current_perf_hook->p_hook_func) = NULL;
28 } else { 28 } else {
29 current_perf_hook = desc; 29 current_perf_hook = desc;
30 (**desc->p_hook_func)(); 30 (**desc->p_hook_func)(desc->hook_ctx);
31 } 31 }
32 current_perf_hook = NULL; 32 current_perf_hook = NULL;
33} 33}
@@ -41,7 +41,9 @@ void perf_hooks__recover(void)
41#define PERF_HOOK(name) \ 41#define PERF_HOOK(name) \
42perf_hook_func_t __perf_hook_func_##name = NULL; \ 42perf_hook_func_t __perf_hook_func_##name = NULL; \
43struct perf_hook_desc __perf_hook_desc_##name = \ 43struct perf_hook_desc __perf_hook_desc_##name = \
44 {.hook_name = #name, .p_hook_func = &__perf_hook_func_##name}; 44 {.hook_name = #name, \
45 .p_hook_func = &__perf_hook_func_##name, \
46 .hook_ctx = NULL};
45#include "perf-hooks-list.h" 47#include "perf-hooks-list.h"
46#undef PERF_HOOK 48#undef PERF_HOOK
47 49
@@ -54,7 +56,8 @@ static struct perf_hook_desc *perf_hooks[] = {
54#undef PERF_HOOK 56#undef PERF_HOOK
55 57
56int perf_hooks__set_hook(const char *hook_name, 58int perf_hooks__set_hook(const char *hook_name,
57 perf_hook_func_t hook_func) 59 perf_hook_func_t hook_func,
60 void *hook_ctx)
58{ 61{
59 unsigned int i; 62 unsigned int i;
60 63
@@ -65,6 +68,7 @@ int perf_hooks__set_hook(const char *hook_name,
65 if (*(perf_hooks[i]->p_hook_func)) 68 if (*(perf_hooks[i]->p_hook_func))
66 pr_warning("Overwrite existing hook: %s\n", hook_name); 69 pr_warning("Overwrite existing hook: %s\n", hook_name);
67 *(perf_hooks[i]->p_hook_func) = hook_func; 70 *(perf_hooks[i]->p_hook_func) = hook_func;
71 perf_hooks[i]->hook_ctx = hook_ctx;
68 return 0; 72 return 0;
69 } 73 }
70 return -ENOENT; 74 return -ENOENT;
diff --git a/tools/perf/util/perf-hooks.h b/tools/perf/util/perf-hooks.h
index 1d482b26b4b9..838d5797bc1e 100644
--- a/tools/perf/util/perf-hooks.h
+++ b/tools/perf/util/perf-hooks.h
@@ -5,10 +5,11 @@
5extern "C" { 5extern "C" {
6#endif 6#endif
7 7
8typedef void (*perf_hook_func_t)(void); 8typedef void (*perf_hook_func_t)(void *ctx);
9struct perf_hook_desc { 9struct perf_hook_desc {
10 const char * const hook_name; 10 const char * const hook_name;
11 perf_hook_func_t * const p_hook_func; 11 perf_hook_func_t * const p_hook_func;
12 void *hook_ctx;
12}; 13};
13 14
14extern void perf_hooks__invoke(const struct perf_hook_desc *); 15extern void perf_hooks__invoke(const struct perf_hook_desc *);
@@ -26,7 +27,8 @@ static inline void perf_hooks__invoke_##name(void) \
26 27
27extern int 28extern int
28perf_hooks__set_hook(const char *hook_name, 29perf_hooks__set_hook(const char *hook_name,
29 perf_hook_func_t hook_func); 30 perf_hook_func_t hook_func,
31 void *hook_ctx);
30 32
31extern perf_hook_func_t 33extern perf_hook_func_t
32perf_hooks__get_hook(const char *hook_name); 34perf_hooks__get_hook(const char *hook_name);
diff --git a/tools/perf/util/util-cxx.h b/tools/perf/util/util-cxx.h
new file mode 100644
index 000000000000..0e0e019c9f34
--- /dev/null
+++ b/tools/perf/util/util-cxx.h
@@ -0,0 +1,26 @@
1/*
2 * Support C++ source use utilities defined in util.h
3 */
4
5#ifndef PERF_UTIL_UTIL_CXX_H
6#define PERF_UTIL_UTIL_CXX_H
7
8#ifdef __cplusplus
9extern "C" {
10#endif
11
12/*
13 * Now 'new' is the only C++ keyword found in util.h:
14 * in tools/include/linux/rbtree.h
15 *
16 * Other keywords, like class and delete, should be
17 * redefined if necessary.
18 */
19#define new _new
20#include "util.h"
21#undef new
22
23#ifdef __cplusplus
24}
25#endif
26#endif