From 1cd6472e3f8d3fdee0fd19f7088807b284d3080f Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 1 Dec 2016 14:00:25 +0100 Subject: [PATCH 01/20] tools build: Make fixdep parsing wait for last target The fixdep tool, among other things, replaces the target of the object in the gcc generated dependency output file. The parsing code assumes there's only single target in the rule but this is not always the case as described in here: https://gcc.gnu.org/ml/gcc-help/2016-11/msg00099.html Make the fixdep code smart enough to skip all the possible targets. Signed-off-by: Jiri Olsa Tested-by: Arnaldo Carvalho de Melo Acked-by: Peter Foley Cc: Wang Nan Link: http://lkml.kernel.org/r/20161201130025.GA16430@krava Signed-off-by: Arnaldo Carvalho de Melo --- tools/build/fixdep.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/build/fixdep.c b/tools/build/fixdep.c index 1521d36cef0d..734d1547cbae 100644 --- a/tools/build/fixdep.c +++ b/tools/build/fixdep.c @@ -49,7 +49,7 @@ static void parse_dep_file(void *map, size_t len) char *end = m + len; char *p; char s[PATH_MAX]; - int is_target; + int is_target, has_target = 0; int saw_any_target = 0; int is_first_dep = 0; @@ -67,7 +67,8 @@ static void parse_dep_file(void *map, size_t len) if (is_target) { /* The /next/ file is the first dependency */ is_first_dep = 1; - } else { + has_target = 1; + } else if (has_target) { /* Save this token/filename */ memcpy(s, m, p-m); s[p - m] = 0; From baa1973ebcf6a7bd15522a5b6a35a8fefd6cb232 Mon Sep 17 00:00:00 2001 From: Peter Foley Date: Sun, 27 Nov 2016 21:43:46 -0500 Subject: [PATCH 02/20] tools build: Fix objtool build with clang Clang doesn't support multiple arguments being passed to -Wp, so split them. Fixes this error: HOSTCC tools/objtool/fixdep.o cat: tools/objtool/.fixdep.o.d: No such file or directory Signed-off-by: Peter Foley Tested-by: Arnaldo Carvalho de Melo Acked-by: Jiri Olsa Cc: Wang Nan Link: http://lkml.kernel.org/r/20161128024346.17371-1-pefoley2@pefoley.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/build/Build.include | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/build/Build.include b/tools/build/Build.include index c4ae12a5d0a5..62dcf0c7aac2 100644 --- a/tools/build/Build.include +++ b/tools/build/Build.include @@ -89,12 +89,12 @@ if_changed = $(if $(strip $(any-prereq) $(arg-check)), \ # - per target C flags # - per object C flags # - BUILD_STR macro to allow '-D"$(variable)"' constructs -c_flags_1 = -Wp,-MD,$(depfile),-MT,$@ $(CFLAGS) -D"BUILD_STR(s)=\#s" $(CFLAGS_$(basetarget).o) $(CFLAGS_$(obj)) +c_flags_1 = -Wp,-MD,$(depfile) -Wp,-MT,$@ $(CFLAGS) -D"BUILD_STR(s)=\#s" $(CFLAGS_$(basetarget).o) $(CFLAGS_$(obj)) c_flags_2 = $(filter-out $(CFLAGS_REMOVE_$(basetarget).o), $(c_flags_1)) c_flags = $(filter-out $(CFLAGS_REMOVE_$(obj)), $(c_flags_2)) -cxx_flags = -Wp,-MD,$(depfile),-MT,$@ $(CXXFLAGS) -D"BUILD_STR(s)=\#s" $(CXXFLAGS_$(basetarget).o) $(CXXFLAGS_$(obj)) +cxx_flags = -Wp,-MD,$(depfile) -Wp,-MT,$@ $(CXXFLAGS) -D"BUILD_STR(s)=\#s" $(CXXFLAGS_$(basetarget).o) $(CXXFLAGS_$(obj)) ### ## HOSTCC C flags -host_c_flags = -Wp,-MD,$(depfile),-MT,$@ $(CHOSTFLAGS) -D"BUILD_STR(s)=\#s" $(CHOSTFLAGS_$(basetarget).o) $(CHOSTFLAGS_$(obj)) +host_c_flags = -Wp,-MD,$(depfile) -Wp,-MT,$@ $(CHOSTFLAGS) -D"BUILD_STR(s)=\#s" $(CHOSTFLAGS_$(basetarget).o) $(CHOSTFLAGS_$(obj)) From 8ad85e9e6fdaf996bf3ff60303ea00e696bcdd36 Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Sat, 26 Nov 2016 07:03:29 +0000 Subject: [PATCH 03/20] perf tools: Pass context to perf hook functions Pass a pointer to perf hook functions so they receive context information during setup. Signed-off-by: Wang Nan Cc: Alexei Starovoitov Cc: He Kuang Cc: Jiri Olsa Cc: Joe Stringer Cc: Zefan Li Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/20161126070354.141764-6-wangnan0@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/perf-hooks.c | 14 +++++++++----- tools/perf/util/perf-hooks.c | 10 +++++++--- tools/perf/util/perf-hooks.h | 6 ++++-- 3 files changed, 20 insertions(+), 10 deletions(-) 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) exit(-1); } -static int hook_flags; -static void the_hook(void) +static void the_hook(void *_hook_flags) { + int *hook_flags = _hook_flags; int *p = NULL; - hook_flags = 1234; + *hook_flags = 1234; /* Generate a segfault, test perf_hooks__recover */ *p = 0; @@ -29,13 +29,17 @@ static void the_hook(void) int test__perf_hooks(int subtest __maybe_unused) { + int hook_flags = 0; + signal(SIGSEGV, sigsegv_handler); - perf_hooks__set_hook("test", the_hook); + perf_hooks__set_hook("test", the_hook, &hook_flags); perf_hooks__invoke_test(); /* hook is triggered? */ - if (hook_flags != 1234) + if (hook_flags != 1234) { + pr_debug("Setting failed: %d (%p)\n", hook_flags, &hook_flags); return TEST_FAIL; + } /* the buggy hook is removed? */ if (perf_hooks__get_hook("test")) 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) *(current_perf_hook->p_hook_func) = NULL; } else { current_perf_hook = desc; - (**desc->p_hook_func)(); + (**desc->p_hook_func)(desc->hook_ctx); } current_perf_hook = NULL; } @@ -41,7 +41,9 @@ void perf_hooks__recover(void) #define PERF_HOOK(name) \ perf_hook_func_t __perf_hook_func_##name = NULL; \ struct perf_hook_desc __perf_hook_desc_##name = \ - {.hook_name = #name, .p_hook_func = &__perf_hook_func_##name}; + {.hook_name = #name, \ + .p_hook_func = &__perf_hook_func_##name, \ + .hook_ctx = NULL}; #include "perf-hooks-list.h" #undef PERF_HOOK @@ -54,7 +56,8 @@ static struct perf_hook_desc *perf_hooks[] = { #undef PERF_HOOK int perf_hooks__set_hook(const char *hook_name, - perf_hook_func_t hook_func) + perf_hook_func_t hook_func, + void *hook_ctx) { unsigned int i; @@ -65,6 +68,7 @@ int perf_hooks__set_hook(const char *hook_name, if (*(perf_hooks[i]->p_hook_func)) pr_warning("Overwrite existing hook: %s\n", hook_name); *(perf_hooks[i]->p_hook_func) = hook_func; + perf_hooks[i]->hook_ctx = hook_ctx; return 0; } 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 @@ extern "C" { #endif -typedef void (*perf_hook_func_t)(void); +typedef void (*perf_hook_func_t)(void *ctx); struct perf_hook_desc { const char * const hook_name; perf_hook_func_t * const p_hook_func; + void *hook_ctx; }; extern void perf_hooks__invoke(const struct perf_hook_desc *); @@ -26,7 +27,8 @@ static inline void perf_hooks__invoke_##name(void) \ extern int perf_hooks__set_hook(const char *hook_name, - perf_hook_func_t hook_func); + perf_hook_func_t hook_func, + void *hook_ctx); extern perf_hook_func_t perf_hooks__get_hook(const char *hook_name); From 2bd42de0e196f89994cbae1990d2c7c5a9b6a529 Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Sat, 26 Nov 2016 07:03:30 +0000 Subject: [PATCH 04/20] perf llvm: Extract helpers in llvm-utils.c The following commits will use builtin clang to compile BPF scripts. llvm__get_kbuild_opts() and llvm__get_nr_cpus() are extracted to help building '-DKERNEL_VERSION_CODE' and '-D__NR_CPUS__' macros. Doing object dumping in bpf loader, so further builtin clang compiling needn't consider it. Signed-off-by: Wang Nan Cc: Alexei Starovoitov Cc: He Kuang Cc: Jiri Olsa Cc: Joe Stringer Cc: Zefan Li Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/20161126070354.141764-7-wangnan0@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/bpf-loader.c | 4 ++ tools/perf/util/llvm-utils.c | 76 +++++++++++++++++++++++++++--------- tools/perf/util/llvm-utils.h | 6 +++ 3 files changed, 68 insertions(+), 18 deletions(-) diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c index a5fd275238f7..cf16b94115b5 100644 --- a/tools/perf/util/bpf-loader.c +++ b/tools/perf/util/bpf-loader.c @@ -90,6 +90,10 @@ struct bpf_object *bpf__prepare_load(const char *filename, bool source) if (err) return ERR_PTR(-BPF_LOADER_ERRNO__COMPILE); obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, filename); + + if (!IS_ERR(obj) && llvm_param.dump_obj) + llvm__dump_obj(filename, obj_buf, obj_buf_sz); + free(obj_buf); } else obj = bpf_object__open(filename); 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 @@ #include #include #include +#include #include "debug.h" #include "llvm-utils.h" #include "config.h" @@ -282,9 +283,10 @@ static const char *kinc_fetch_script = "rm -rf $TMPDIR\n" "exit $RET\n"; -static inline void -get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts) +void llvm__get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts) { + static char *saved_kbuild_dir; + static char *saved_kbuild_include_opts; int err; if (!kbuild_dir || !kbuild_include_opts) @@ -293,10 +295,28 @@ get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts) *kbuild_dir = NULL; *kbuild_include_opts = NULL; + if (saved_kbuild_dir && saved_kbuild_include_opts && + !IS_ERR(saved_kbuild_dir) && !IS_ERR(saved_kbuild_include_opts)) { + *kbuild_dir = strdup(saved_kbuild_dir); + *kbuild_include_opts = strdup(saved_kbuild_include_opts); + + if (*kbuild_dir && *kbuild_include_opts) + return; + + zfree(kbuild_dir); + zfree(kbuild_include_opts); + /* + * Don't fall through: it may breaks saved_kbuild_dir and + * saved_kbuild_include_opts if detect them again when + * memory is low. + */ + return; + } + if (llvm_param.kbuild_dir && !llvm_param.kbuild_dir[0]) { pr_debug("[llvm.kbuild-dir] is set to \"\" deliberately.\n"); pr_debug("Skip kbuild options detection.\n"); - return; + goto errout; } err = detect_kbuild_dir(kbuild_dir); @@ -306,7 +326,7 @@ get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts) "Hint:\tSet correct kbuild directory using 'kbuild-dir' option in [llvm]\n" " \tsection of ~/.perfconfig or set it to \"\" to suppress kbuild\n" " \tdetection.\n\n"); - return; + goto errout; } 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) free(*kbuild_dir); *kbuild_dir = NULL; - return; + goto errout; } pr_debug("include option is set to %s\n", *kbuild_include_opts); + + saved_kbuild_dir = strdup(*kbuild_dir); + saved_kbuild_include_opts = strdup(*kbuild_include_opts); + + if (!saved_kbuild_dir || !saved_kbuild_include_opts) { + zfree(&saved_kbuild_dir); + zfree(&saved_kbuild_include_opts); + } + return; +errout: + saved_kbuild_dir = ERR_PTR(-EINVAL); + saved_kbuild_include_opts = ERR_PTR(-EINVAL); } -static void -dump_obj(const char *path, void *obj_buf, size_t size) +int llvm__get_nr_cpus(void) +{ + static int nr_cpus_avail = 0; + char serr[STRERR_BUFSIZE]; + + if (nr_cpus_avail > 0) + return nr_cpus_avail; + + nr_cpus_avail = sysconf(_SC_NPROCESSORS_CONF); + if (nr_cpus_avail <= 0) { + pr_err( +"WARNING:\tunable to get available CPUs in this system: %s\n" +" \tUse 128 instead.\n", str_error_r(errno, serr, sizeof(serr))); + nr_cpus_avail = 128; + } + return nr_cpus_avail; +} + +void llvm__dump_obj(const char *path, void *obj_buf, size_t size) { char *obj_path = strdup(path); FILE *fp; @@ -406,15 +455,9 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf, * This is an optional work. Even it fail we can continue our * work. Needn't to check error return. */ - get_kbuild_opts(&kbuild_dir, &kbuild_include_opts); + llvm__get_kbuild_opts(&kbuild_dir, &kbuild_include_opts); - nr_cpus_avail = sysconf(_SC_NPROCESSORS_CONF); - if (nr_cpus_avail <= 0) { - pr_err( -"WARNING:\tunable to get available CPUs in this system: %s\n" -" \tUse 128 instead.\n", str_error_r(errno, serr, sizeof(serr))); - nr_cpus_avail = 128; - } + nr_cpus_avail = llvm__get_nr_cpus(); snprintf(nr_cpus_avail_str, sizeof(nr_cpus_avail_str), "%d", nr_cpus_avail); @@ -453,9 +496,6 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf, free(kbuild_dir); free(kbuild_include_opts); - if (llvm_param.dump_obj) - dump_obj(path, obj_buf, obj_buf_sz); - if (!p_obj_buf) free(obj_buf); 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); /* This function is for test__llvm() use only */ int llvm__search_clang(void); + +/* Following functions are reused by builtin clang support */ +void llvm__get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts); +int llvm__get_nr_cpus(void); + +void llvm__dump_obj(const char *path, void *obj_buf, size_t size); #endif From cb40d55b595cd117ef7c1880247605875b2115e8 Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Sat, 26 Nov 2016 07:03:31 +0000 Subject: [PATCH 05/20] tools build: Add feature detection for LLVM Check if basic LLVM compiling environment is ready. Use llvm-config to detect include and library directories. Avoid using 'llvm-config --cxxflags' because its result contain some unwanted flags like --sysroot (if LLVM is built by yocto). Use '?=' to set LLVM_CONFIG, so explicitly passing LLVM_CONFIG to make would override it. Use 'llvm-config --libs BPF' to check if BPF backend is compiled in. Since now BPF bytecode is the only required backend, no need to waste time linking llvm and clang if BPF backend is missing. This also introduce an implicit requirement that LLVM should be new enough. Old LLVM doesn't support BPF backend. Signed-off-by: Wang Nan Cc: Alexei Starovoitov Cc: He Kuang Cc: Jiri Olsa Cc: Joe Stringer Cc: Zefan Li Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/20161126070354.141764-8-wangnan0@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/build/feature/Makefile | 8 ++++++++ tools/build/feature/test-llvm.cpp | 8 ++++++++ 2 files changed, 16 insertions(+) create mode 100644 tools/build/feature/test-llvm.cpp diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile index 8f668bce8996..c09de59affc9 100644 --- a/tools/build/feature/Makefile +++ b/tools/build/feature/Makefile @@ -55,6 +55,7 @@ FILES := $(addprefix $(OUTPUT),$(FILES)) CC := $(CROSS_COMPILE)gcc -MD CXX := $(CROSS_COMPILE)g++ -MD PKG_CONFIG := $(CROSS_COMPILE)pkg-config +LLVM_CONFIG ?= llvm-config all: $(FILES) @@ -229,6 +230,13 @@ $(OUTPUT)test-cxx.bin: $(OUTPUT)test-jvmti.bin: $(BUILD) +$(OUTPUT)test-llvm.bin: + $(BUILDXX) -std=gnu++11 \ + -I$(shell $(LLVM_CONFIG) --includedir) \ + -L$(shell $(LLVM_CONFIG) --libdir) \ + $(shell $(LLVM_CONFIG) --libs Core BPF) \ + $(shell $(LLVM_CONFIG) --system-libs) + -include $(OUTPUT)*.d ############################### diff --git a/tools/build/feature/test-llvm.cpp b/tools/build/feature/test-llvm.cpp new file mode 100644 index 000000000000..d8d2cee35345 --- /dev/null +++ b/tools/build/feature/test-llvm.cpp @@ -0,0 +1,8 @@ +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/raw_ostream.h" +int main() +{ + llvm::errs() << "Hello World!\n"; + llvm::llvm_shutdown(); + return 0; +} From c7fb4f62e2a97bd25d555263ef501fe053edcbb6 Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Sat, 26 Nov 2016 07:03:32 +0000 Subject: [PATCH 06/20] tools build: Add feature detection for clang Check if basic clang compiling environment is ready. Doesn't like 'llvm-config --libs' which can returns llvm libraries in right order and duplicates some libraries if necessary, there's no correspondence for clang libraries (-lclangxxx). to avoid extra complexity and to avoid new clang breaking libraries ordering, use --start-group and --end-group. In this test case, manually identify required clang libs and hope it to be stable. Putting all clang libraries here is possible (use make's wildcard), but then feature checking becomes very slow. Signed-off-by: Wang Nan Cc: Alexei Starovoitov Cc: He Kuang Cc: Jiri Olsa Cc: Joe Stringer Cc: Zefan Li Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/20161126070354.141764-9-wangnan0@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/build/feature/Makefile | 10 ++++++++++ tools/build/feature/test-clang.cpp | 21 +++++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 tools/build/feature/test-clang.cpp diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile index c09de59affc9..871d5536951d 100644 --- a/tools/build/feature/Makefile +++ b/tools/build/feature/Makefile @@ -237,6 +237,16 @@ $(OUTPUT)test-llvm.bin: $(shell $(LLVM_CONFIG) --libs Core BPF) \ $(shell $(LLVM_CONFIG) --system-libs) +$(OUTPUT)test-clang.bin: + $(BUILDXX) -std=gnu++11 \ + -I$(shell $(LLVM_CONFIG) --includedir) \ + -L$(shell $(LLVM_CONFIG) --libdir) \ + -Wl,--start-group -lclangBasic -lclangDriver \ + -lclangFrontend -lclangEdit -lclangLex \ + -lclangAST -Wl,--end-group \ + $(shell $(LLVM_CONFIG) --libs Core option) \ + $(shell $(LLVM_CONFIG) --system-libs) + -include $(OUTPUT)*.d ############################### diff --git a/tools/build/feature/test-clang.cpp b/tools/build/feature/test-clang.cpp new file mode 100644 index 000000000000..e23c1b1f1b91 --- /dev/null +++ b/tools/build/feature/test-clang.cpp @@ -0,0 +1,21 @@ +#include "clang/Basic/VirtualFileSystem.h" +#include "clang/Driver/Driver.h" +#include "clang/Frontend/TextDiagnosticPrinter.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/raw_ostream.h" + +using namespace clang; +using namespace clang::driver; + +int main() +{ + IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); + IntrusiveRefCntPtr DiagOpts = new DiagnosticOptions(); + + DiagnosticsEngine Diags(DiagID, &*DiagOpts); + Driver TheDriver("test", "bpf-pc-linux", Diags); + + llvm::llvm_shutdown(); + return 0; +} From d58ac0bf8d1e6ffbfcb0a77e459cf4737b131b75 Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Sat, 26 Nov 2016 07:03:33 +0000 Subject: [PATCH 07/20] perf build: Add clang and llvm compile and linking support Add necessary c++ flags and link libraries to support builtin clang and LLVM. Add all llvm and clang libraries, so don't need to worry about clang changes its libraries setting. However, linking perf would take much longer than usual. Signed-off-by: Wang Nan Cc: Alexei Starovoitov Cc: He Kuang Cc: Jiri Olsa Cc: Joe Stringer Cc: Zefan Li Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/20161126070354.141764-10-wangnan0@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile.config | 35 +++++++++++++++++++++++++++++++++++ tools/perf/Makefile.perf | 23 ++++++++++++++++++++++- tools/perf/tests/make | 2 ++ 3 files changed, 59 insertions(+), 1 deletion(-) diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config index 8a493d46fab9..b7c9c8051a33 100644 --- a/tools/perf/Makefile.config +++ b/tools/perf/Makefile.config @@ -136,6 +136,7 @@ endif # Treat warnings as errors unless directed not to ifneq ($(WERROR),0) CFLAGS += -Werror + CXXFLAGS += -Werror endif ifndef DEBUG @@ -182,6 +183,13 @@ CFLAGS += -Wall CFLAGS += -Wextra CFLAGS += -std=gnu99 +CXXFLAGS += -std=gnu++11 -fno-exceptions -fno-rtti +CXXFLAGS += -Wall +CXXFLAGS += -fno-omit-frame-pointer +CXXFLAGS += -ggdb3 +CXXFLAGS += -funwind-tables +CXXFLAGS += -Wno-strict-aliasing + # Enforce a non-executable stack, as we may regress (again) in the future by # adding assembler files missing the .GNU-stack linker note. LDFLAGS += -Wl,-z,noexecstack @@ -783,6 +791,33 @@ ifndef NO_JVMTI endif endif +USE_CXX = 0 +USE_CLANGLLVM = 0 +ifdef LIBCLANGLLVM + $(call feature_check,cxx) + ifneq ($(feature-cxx), 1) + msg := $(warning No g++ found, disable clang and llvm support. Please install g++) + else + $(call feature_check,llvm) + ifneq ($(feature-llvm), 1) + msg := $(warning No libLLVM found, disable clang and llvm support. Please install llvm-dev) + else + $(call feature_check,clang) + ifneq ($(feature-clang), 1) + msg := $(warning No libclang found, disable clang and llvm support. Please install libclang-dev) + else + CFLAGS += -DHAVE_LIBCLANGLLVM_SUPPORT + CXXFLAGS += -DHAVE_LIBCLANGLLVM_SUPPORT -I$(shell $(LLVM_CONFIG) --includedir) + $(call detected,CONFIG_CXX) + $(call detected,CONFIG_CLANGLLVM) + USE_CXX = 1 + USE_LLVM = 1 + USE_CLANG = 1 + endif + endif + endif +endif + # Among the variables below, these: # perfexecdir # template_dir diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index 3cb1df43ad3e..dfb20dd31865 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -88,6 +88,10 @@ include ../scripts/utilities.mak # and bypass the feature detection # # Define NO_JVMTI if you do not want jvmti agent built +# +# Define LIBCLANGLLVM if you DO want builtin clang and llvm support. +# When selected, pass LLVM_CONFIG=/path/to/llvm-config to `make' if +# llvm-config is not in $PATH. # As per kernel Makefile, avoid funny character set dependencies unexport LC_ALL @@ -143,6 +147,7 @@ endef $(call allow-override,CC,$(CROSS_COMPILE)gcc) $(call allow-override,AR,$(CROSS_COMPILE)ar) $(call allow-override,LD,$(CROSS_COMPILE)ld) +$(call allow-override,CXX,$(CROSS_COMPILE)g++) LD += $(EXTRA_LDFLAGS) @@ -151,6 +156,7 @@ HOSTLD ?= ld HOSTAR ?= ar PKG_CONFIG = $(CROSS_COMPILE)pkg-config +LLVM_CONFIG ?= llvm-config RM = rm -f LN = ln -f @@ -338,6 +344,21 @@ endif LIBS = -Wl,--whole-archive $(PERFLIBS) -Wl,--no-whole-archive -Wl,--start-group $(EXTLIBS) -Wl,--end-group +ifeq ($(USE_CLANG), 1) + CLANGLIBS_LIST = AST Basic CodeGen Driver Frontend Lex Tooling Edit Sema Analysis Parse Serialization + LIBCLANG = $(foreach l,$(CLANGLIBS_LIST),$(wildcard $(shell $(LLVM_CONFIG) --libdir)/libclang$(l).a)) + LIBS += -Wl,--start-group $(LIBCLANG) -Wl,--end-group +endif + +ifeq ($(USE_LLVM), 1) + LIBLLVM = $(shell $(LLVM_CONFIG) --libs all) $(shell $(LLVM_CONFIG) --system-libs) + LIBS += -L$(shell $(LLVM_CONFIG) --libdir) $(LIBLLVM) +endif + +ifeq ($(USE_CXX), 1) + LIBS += -lstdc++ +endif + export INSTALL SHELL_PATH ### Build rules @@ -356,7 +377,7 @@ strip: $(PROGRAMS) $(OUTPUT)perf PERF_IN := $(OUTPUT)perf-in.o -export srctree OUTPUT RM CC LD AR CFLAGS V BISON FLEX AWK +export srctree OUTPUT RM CC CXX LD AR CFLAGS CXXFLAGS V BISON FLEX AWK export HOSTCC HOSTLD HOSTAR include $(srctree)/tools/build/Makefile.include diff --git a/tools/perf/tests/make b/tools/perf/tests/make index 08ed7f12cc37..aa49b6600d1f 100644 --- a/tools/perf/tests/make +++ b/tools/perf/tests/make @@ -83,6 +83,7 @@ make_no_libbpf := NO_LIBBPF=1 make_no_libcrypto := NO_LIBCRYPTO=1 make_with_babeltrace:= LIBBABELTRACE=1 make_no_sdt := NO_SDT=1 +make_with_clangllvm := LIBCLANGLLVM=1 make_tags := tags make_cscope := cscope make_help := help @@ -139,6 +140,7 @@ run += make_no_libbionic run += make_no_auxtrace run += make_no_libbpf run += make_with_babeltrace +run += make_with_clangllvm run += make_help run += make_doc run += make_perf_o From 00b86691c77c6576861b82a3cfe4d609800758fe Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Sat, 26 Nov 2016 07:03:34 +0000 Subject: [PATCH 08/20] perf clang: Add builtin clang support ant test case Add basic clang support in clang.cpp and test__clang() testcase. The first testcase checks if builtin clang is able to generate LLVM IR. tests/clang.c is a proxy. Real testcase resides in utils/c++/clang-test.cpp in c++ and exports C interface to perf test subsystem. Test result: $ perf test -v clang 51: builtin clang support : 51.1: Test builtin clang compile C source to IR : --- start --- test child forked, pid 13215 test child finished with 0 ---- end ---- Test builtin clang support subtest 0: Ok Committer note: Make sure you've enabled CLANG and LLVM builtin support by setting the LIBCLANGLLVM variable on the make command line, e.g.: make LIBCLANGLLVM=1 O=/tmp/build/perf -C tools/perf install-bin Otherwise you'll get this when trying to do the 'perf test' call above: # perf test clang 51: builtin clang support : Skip (not compiled in) # Signed-off-by: Wang Nan Tested-by: Arnaldo Carvalho de Melo Cc: Alexei Starovoitov Cc: He Kuang Cc: Jiri Olsa Cc: Joe Stringer Cc: Zefan Li Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/20161126070354.141764-11-wangnan0@huawei.com [ Removed "Test" from descriptions, redundant and already removed from all the other entries ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/Build | 1 + tools/perf/tests/builtin-test.c | 9 +++ tools/perf/tests/clang.c | 42 +++++++++++++ tools/perf/tests/tests.h | 3 + tools/perf/util/Build | 2 + tools/perf/util/c++/Build | 2 + tools/perf/util/c++/clang-c.h | 16 +++++ tools/perf/util/c++/clang-test.cpp | 31 ++++++++++ tools/perf/util/c++/clang.cpp | 96 ++++++++++++++++++++++++++++++ tools/perf/util/c++/clang.h | 16 +++++ 10 files changed, 218 insertions(+) create mode 100644 tools/perf/tests/clang.c create mode 100644 tools/perf/util/c++/Build create mode 100644 tools/perf/util/c++/clang-c.h create mode 100644 tools/perf/util/c++/clang-test.cpp create mode 100644 tools/perf/util/c++/clang.cpp create mode 100644 tools/perf/util/c++/clang.h 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 perf-y += is_printable_array.o perf-y += bitmap.o perf-y += perf-hooks.o +perf-y += clang.o $(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build $(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 @@ -233,6 +233,15 @@ static struct test generic_tests[] = { .desc = "perf hooks", .func = test__perf_hooks, }, + { + .desc = "builtin clang support", + .func = test__clang, + .subtest = { + .skip_if_fail = true, + .get_nr = test__clang_subtest_get_nr, + .get_desc = test__clang_subtest_get_desc, + } + }, { .func = NULL, }, diff --git a/tools/perf/tests/clang.c b/tools/perf/tests/clang.c new file mode 100644 index 000000000000..636d6d0e9037 --- /dev/null +++ b/tools/perf/tests/clang.c @@ -0,0 +1,42 @@ +#include "tests.h" +#include "debug.h" +#include "util.h" +#include "c++/clang-c.h" + +static struct { + int (*func)(void); + const char *desc; +} clang_testcase_table[] = { +#ifdef HAVE_LIBCLANGLLVM_SUPPORT + { + .func = test__clang_to_IR, + .desc = "builtin clang compile C source to IR", + }, +#endif +}; + +int test__clang_subtest_get_nr(void) +{ + return (int)ARRAY_SIZE(clang_testcase_table); +} + +const char *test__clang_subtest_get_desc(int i) +{ + if (i < 0 || i >= (int)ARRAY_SIZE(clang_testcase_table)) + return NULL; + return clang_testcase_table[i].desc; +} + +#ifndef HAVE_LIBCLANGLLVM_SUPPORT +int test__clang(int i __maybe_unused) +{ + return TEST_SKIP; +} +#else +int test__clang(int i __maybe_unused) +{ + if (i < 0 || i >= (int)ARRAY_SIZE(clang_testcase_table)) + return TEST_FAIL; + return clang_testcase_table[i].func(); +} +#endif 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); int test__is_printable_array(int subtest); int test__bitmap_print(int subtest); int test__perf_hooks(int subtest); +int test__clang(int subtest); +const char *test__clang_subtest_get_desc(int subtest); +int test__clang_subtest_get_nr(void); #if defined(__arm__) || defined(__aarch64__) #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 libperf-y += perf-hooks.o +libperf-$(CONFIG_CXX) += c++/ + CFLAGS_config.o += -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))" # avoid compiler warnings in 32-bit mode CFLAGS_genelf_debug.o += -Wno-packed 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 @@ +libperf-$(CONFIG_CLANGLLVM) += clang.o +libperf-$(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..dcde4b564f3b --- /dev/null +++ b/tools/perf/util/c++/clang-c.h @@ -0,0 +1,16 @@ +#ifndef PERF_UTIL_CLANG_C_H +#define PERF_UTIL_CLANG_C_H + +#ifdef __cplusplus +extern "C" { +#endif + +extern void perf_clang__init(void); +extern void perf_clang__cleanup(void); + +extern int test__clang_to_IR(void); + +#ifdef __cplusplus +} +#endif +#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..3da6bfa4bc54 --- /dev/null +++ b/tools/perf/util/c++/clang-test.cpp @@ -0,0 +1,31 @@ +#include "clang.h" +#include "clang-c.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/LLVMContext.h" + +class perf_clang_scope { +public: + explicit perf_clang_scope() {perf_clang__init();} + ~perf_clang_scope() {perf_clang__cleanup();} +}; + +extern "C" { + +int test__clang_to_IR(void) +{ + perf_clang_scope _scope; + + std::unique_ptr M = + perf::getModuleFromSource("perf-test.c", + "int myfunc(void) {return 1;}"); + + if (!M) + return -1; + + for (llvm::Function& F : *M) + if (F.getName() == "myfunc") + return 0; + return -1; +} + +} diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp new file mode 100644 index 000000000000..c17b1176e25d --- /dev/null +++ b/tools/perf/util/c++/clang.cpp @@ -0,0 +1,96 @@ +/* + * llvm C frontend for perf. Support dynamically compile C file + * + * Inspired by clang example code: + * http://llvm.org/svn/llvm-project/cfe/trunk/examples/clang-interpreter/main.cpp + * + * Copyright (C) 2016 Wang Nan + * Copyright (C) 2016 Huawei Inc. + */ + +#include "clang/CodeGen/CodeGenAction.h" +#include "clang/Frontend/CompilerInvocation.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/TextDiagnosticPrinter.h" +#include "clang/Tooling/Tooling.h" +#include "llvm/IR/Module.h" +#include "llvm/Option/Option.h" +#include "llvm/Support/ManagedStatic.h" +#include + +#include "clang.h" +#include "clang-c.h" + +namespace perf { + +static std::unique_ptr LLVMCtx; + +using namespace clang; + +static vfs::InMemoryFileSystem * +buildVFS(StringRef& Name, StringRef& Content) +{ + vfs::InMemoryFileSystem *VFS = new vfs::InMemoryFileSystem(true); + VFS->addFile(Twine(Name), 0, llvm::MemoryBuffer::getMemBuffer(Content)); + return VFS; +} + +static CompilerInvocation * +createCompilerInvocation(StringRef& Path, DiagnosticsEngine& Diags) +{ + llvm::opt::ArgStringList CCArgs { + "-cc1", + "-triple", "bpf-pc-linux", + "-fsyntax-only", + "-ferror-limit", "19", + "-fmessage-length", "127", + "-O2", + "-nostdsysteminc", + "-nobuiltininc", + "-vectorize-loops", + "-vectorize-slp", + "-Wno-unused-value", + "-Wno-pointer-sign", + "-x", "c"}; + CompilerInvocation *CI = tooling::newInvocation(&Diags, CCArgs); + + FrontendOptions& Opts = CI->getFrontendOpts(); + Opts.Inputs.clear(); + Opts.Inputs.emplace_back(Path, IK_C); + return CI; +} + +std::unique_ptr +getModuleFromSource(StringRef Name, StringRef Content) +{ + CompilerInstance Clang; + Clang.createDiagnostics(); + + IntrusiveRefCntPtr VFS = buildVFS(Name, Content); + Clang.setVirtualFileSystem(&*VFS); + + IntrusiveRefCntPtr CI = + createCompilerInvocation(Name, Clang.getDiagnostics()); + Clang.setInvocation(&*CI); + + std::unique_ptr Act(new EmitLLVMOnlyAction(&*LLVMCtx)); + if (!Clang.ExecuteAction(*Act)) + return std::unique_ptr(nullptr); + + return Act->takeModule(); +} + +} + +extern "C" { +void perf_clang__init(void) +{ + perf::LLVMCtx.reset(new llvm::LLVMContext()); +} + +void perf_clang__cleanup(void) +{ + perf::LLVMCtx.reset(nullptr); + llvm::llvm_shutdown(); +} +} diff --git a/tools/perf/util/c++/clang.h b/tools/perf/util/c++/clang.h new file mode 100644 index 000000000000..f64483be43d0 --- /dev/null +++ b/tools/perf/util/c++/clang.h @@ -0,0 +1,16 @@ +#ifndef PERF_UTIL_CLANG_H +#define PERF_UTIL_CLANG_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include +namespace perf { + +using namespace llvm; + +std::unique_ptr +getModuleFromSource(StringRef Name, StringRef Content); + +} +#endif From 77dfa84a843c0bc935a6c8664f2556573e30845f Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Sat, 26 Nov 2016 07:03:35 +0000 Subject: [PATCH 09/20] perf clang: Use real file system for #include Utilize clang's OverlayFileSystem facility, allow CompilerInstance to access real file system. With this patch the '#include' directive can be used. Add a new getModuleFromSource for real file. Signed-off-by: Wang Nan Cc: Alexei Starovoitov Cc: He Kuang Cc: Jiri Olsa Cc: Joe Stringer Cc: Zefan Li Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/20161126070354.141764-12-wangnan0@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/c++/clang.cpp | 44 +++++++++++++++++++++++++---------- tools/perf/util/c++/clang.h | 3 +++ 2 files changed, 35 insertions(+), 12 deletions(-) diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp index c17b1176e25d..cf96199b4b6f 100644 --- a/tools/perf/util/c++/clang.cpp +++ b/tools/perf/util/c++/clang.cpp @@ -15,6 +15,7 @@ #include "clang/Tooling/Tooling.h" #include "llvm/IR/Module.h" #include "llvm/Option/Option.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/ManagedStatic.h" #include @@ -27,14 +28,6 @@ static std::unique_ptr LLVMCtx; using namespace clang; -static vfs::InMemoryFileSystem * -buildVFS(StringRef& Name, StringRef& Content) -{ - vfs::InMemoryFileSystem *VFS = new vfs::InMemoryFileSystem(true); - VFS->addFile(Twine(Name), 0, llvm::MemoryBuffer::getMemBuffer(Content)); - return VFS; -} - static CompilerInvocation * createCompilerInvocation(StringRef& Path, DiagnosticsEngine& Diags) { @@ -60,17 +53,17 @@ createCompilerInvocation(StringRef& Path, DiagnosticsEngine& Diags) return CI; } -std::unique_ptr -getModuleFromSource(StringRef Name, StringRef Content) +static std::unique_ptr +getModuleFromSource(StringRef Path, + IntrusiveRefCntPtr VFS) { CompilerInstance Clang; Clang.createDiagnostics(); - IntrusiveRefCntPtr VFS = buildVFS(Name, Content); Clang.setVirtualFileSystem(&*VFS); IntrusiveRefCntPtr CI = - createCompilerInvocation(Name, Clang.getDiagnostics()); + createCompilerInvocation(Path, Clang.getDiagnostics()); Clang.setInvocation(&*CI); std::unique_ptr Act(new EmitLLVMOnlyAction(&*LLVMCtx)); @@ -80,6 +73,33 @@ getModuleFromSource(StringRef Name, StringRef Content) return Act->takeModule(); } +std::unique_ptr +getModuleFromSource(StringRef Name, StringRef Content) +{ + using namespace vfs; + + llvm::IntrusiveRefCntPtr OverlayFS( + new OverlayFileSystem(getRealFileSystem())); + llvm::IntrusiveRefCntPtr MemFS( + new InMemoryFileSystem(true)); + + /* + * pushOverlay helps setting working dir for MemFS. Must call + * before addFile. + */ + OverlayFS->pushOverlay(MemFS); + MemFS->addFile(Twine(Name), 0, llvm::MemoryBuffer::getMemBuffer(Content)); + + return getModuleFromSource(Name, OverlayFS); +} + +std::unique_ptr +getModuleFromSource(StringRef Path) +{ + IntrusiveRefCntPtr VFS(vfs::getRealFileSystem()); + return getModuleFromSource(Path, VFS); +} + } extern "C" { diff --git a/tools/perf/util/c++/clang.h b/tools/perf/util/c++/clang.h index f64483be43d0..90aff0162f1c 100644 --- a/tools/perf/util/c++/clang.h +++ b/tools/perf/util/c++/clang.h @@ -12,5 +12,8 @@ using namespace llvm; std::unique_ptr getModuleFromSource(StringRef Name, StringRef Content); +std::unique_ptr +getModuleFromSource(StringRef Path); + } #endif From a9495fe9dc63bee1166772b6f10e199ef1747892 Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Sat, 26 Nov 2016 07:03:36 +0000 Subject: [PATCH 10/20] perf clang: Allow passing CFLAGS to builtin clang Improve getModuleFromSource() API to accept a cflags list. This feature will be used to pass LINUX_VERSION_CODE and -I flags. Signed-off-by: Wang Nan Cc: Alexei Starovoitov Cc: He Kuang Cc: Jiri Olsa Cc: Joe Stringer Cc: Zefan Li Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/20161126070354.141764-13-wangnan0@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/c++/clang-test.cpp | 5 +++-- tools/perf/util/c++/clang.cpp | 21 +++++++++++++-------- tools/perf/util/c++/clang.h | 8 ++++++-- 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/tools/perf/util/c++/clang-test.cpp b/tools/perf/util/c++/clang-test.cpp index 3da6bfa4bc54..0f484fbb2b58 100644 --- a/tools/perf/util/c++/clang-test.cpp +++ b/tools/perf/util/c++/clang-test.cpp @@ -16,8 +16,9 @@ int test__clang_to_IR(void) perf_clang_scope _scope; std::unique_ptr M = - perf::getModuleFromSource("perf-test.c", - "int myfunc(void) {return 1;}"); + perf::getModuleFromSource({"-DRESULT=1"}, + "perf-test.c", + "int myfunc(void) {return RESULT;}"); if (!M) return -1; diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp index cf96199b4b6f..715ca0a3dee0 100644 --- a/tools/perf/util/c++/clang.cpp +++ b/tools/perf/util/c++/clang.cpp @@ -29,7 +29,8 @@ static std::unique_ptr LLVMCtx; using namespace clang; static CompilerInvocation * -createCompilerInvocation(StringRef& Path, DiagnosticsEngine& Diags) +createCompilerInvocation(llvm::opt::ArgStringList CFlags, StringRef& Path, + DiagnosticsEngine& Diags) { llvm::opt::ArgStringList CCArgs { "-cc1", @@ -45,6 +46,8 @@ createCompilerInvocation(StringRef& Path, DiagnosticsEngine& Diags) "-Wno-unused-value", "-Wno-pointer-sign", "-x", "c"}; + + CCArgs.append(CFlags.begin(), CFlags.end()); CompilerInvocation *CI = tooling::newInvocation(&Diags, CCArgs); FrontendOptions& Opts = CI->getFrontendOpts(); @@ -54,8 +57,8 @@ createCompilerInvocation(StringRef& Path, DiagnosticsEngine& Diags) } static std::unique_ptr -getModuleFromSource(StringRef Path, - IntrusiveRefCntPtr VFS) +getModuleFromSource(llvm::opt::ArgStringList CFlags, + StringRef Path, IntrusiveRefCntPtr VFS) { CompilerInstance Clang; Clang.createDiagnostics(); @@ -63,7 +66,8 @@ getModuleFromSource(StringRef Path, Clang.setVirtualFileSystem(&*VFS); IntrusiveRefCntPtr CI = - createCompilerInvocation(Path, Clang.getDiagnostics()); + createCompilerInvocation(std::move(CFlags), Path, + Clang.getDiagnostics()); Clang.setInvocation(&*CI); std::unique_ptr Act(new EmitLLVMOnlyAction(&*LLVMCtx)); @@ -74,7 +78,8 @@ getModuleFromSource(StringRef Path, } std::unique_ptr -getModuleFromSource(StringRef Name, StringRef Content) +getModuleFromSource(llvm::opt::ArgStringList CFlags, + StringRef Name, StringRef Content) { using namespace vfs; @@ -90,14 +95,14 @@ getModuleFromSource(StringRef Name, StringRef Content) OverlayFS->pushOverlay(MemFS); MemFS->addFile(Twine(Name), 0, llvm::MemoryBuffer::getMemBuffer(Content)); - return getModuleFromSource(Name, OverlayFS); + return getModuleFromSource(std::move(CFlags), Name, OverlayFS); } std::unique_ptr -getModuleFromSource(StringRef Path) +getModuleFromSource(llvm::opt::ArgStringList CFlags, StringRef Path) { IntrusiveRefCntPtr VFS(vfs::getRealFileSystem()); - return getModuleFromSource(Path, VFS); + return getModuleFromSource(std::move(CFlags), Path, VFS); } } diff --git a/tools/perf/util/c++/clang.h b/tools/perf/util/c++/clang.h index 90aff0162f1c..b4fc2a96b79d 100644 --- a/tools/perf/util/c++/clang.h +++ b/tools/perf/util/c++/clang.h @@ -4,16 +4,20 @@ #include "llvm/ADT/StringRef.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" +#include "llvm/Option/Option.h" #include + namespace perf { using namespace llvm; std::unique_ptr -getModuleFromSource(StringRef Name, StringRef Content); +getModuleFromSource(opt::ArgStringList CFlags, + StringRef Name, StringRef Content); std::unique_ptr -getModuleFromSource(StringRef Path); +getModuleFromSource(opt::ArgStringList CFlags, + StringRef Path); } #endif From e67d52d411c3562263735479db2efd2ebd178db9 Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Sat, 26 Nov 2016 07:03:37 +0000 Subject: [PATCH 11/20] perf clang: Update test case to use real BPF script Allow C++ code to use util.h and tests/llvm.h. Let 'perf test' compile a real BPF script. Signed-off-by: Wang Nan Cc: Alexei Starovoitov Cc: He Kuang Cc: Jiri Olsa Cc: Joe Stringer Cc: Zefan Li Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/20161126070354.141764-14-wangnan0@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile.config | 27 +++++++++++++++------------ tools/perf/tests/llvm.h | 7 +++++++ tools/perf/util/c++/clang-test.cpp | 17 ++++++++++++++--- tools/perf/util/util-cxx.h | 26 ++++++++++++++++++++++++++ 4 files changed, 62 insertions(+), 15 deletions(-) create mode 100644 tools/perf/util/util-cxx.h diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config index b7c9c8051a33..09c2a9874f2f 100644 --- a/tools/perf/Makefile.config +++ b/tools/perf/Makefile.config @@ -212,24 +212,27 @@ ifeq ($(DEBUG),0) endif endif -CFLAGS += -I$(src-perf)/util/include -CFLAGS += -I$(src-perf)/arch/$(ARCH)/include -CFLAGS += -I$(srctree)/tools/include/uapi -CFLAGS += -I$(srctree)/tools/include/ -CFLAGS += -I$(srctree)/tools/arch/$(ARCH)/include/uapi -CFLAGS += -I$(srctree)/tools/arch/$(ARCH)/include/ -CFLAGS += -I$(srctree)/tools/arch/$(ARCH)/ +INC_FLAGS += -I$(src-perf)/util/include +INC_FLAGS += -I$(src-perf)/arch/$(ARCH)/include +INC_FLAGS += -I$(srctree)/tools/include/uapi +INC_FLAGS += -I$(srctree)/tools/include/ +INC_FLAGS += -I$(srctree)/tools/arch/$(ARCH)/include/uapi +INC_FLAGS += -I$(srctree)/tools/arch/$(ARCH)/include/ +INC_FLAGS += -I$(srctree)/tools/arch/$(ARCH)/ # $(obj-perf) for generated common-cmds.h # $(obj-perf)/util for generated bison/flex headers ifneq ($(OUTPUT),) -CFLAGS += -I$(obj-perf)/util -CFLAGS += -I$(obj-perf) +INC_FLAGS += -I$(obj-perf)/util +INC_FLAGS += -I$(obj-perf) endif -CFLAGS += -I$(src-perf)/util -CFLAGS += -I$(src-perf) -CFLAGS += -I$(srctree)/tools/lib/ +INC_FLAGS += -I$(src-perf)/util +INC_FLAGS += -I$(src-perf) +INC_FLAGS += -I$(srctree)/tools/lib/ + +CFLAGS += $(INC_FLAGS) +CXXFLAGS += $(INC_FLAGS) CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE 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 @@ #ifndef PERF_TEST_LLVM_H #define PERF_TEST_LLVM_H +#ifdef __cplusplus +extern "C" { +#endif + #include /* for size_t */ #include /* for bool */ @@ -20,4 +24,7 @@ enum test_llvm__testcase { int test_llvm__fetch_bpf_obj(void **p_obj_buf, size_t *p_obj_buf_sz, enum test_llvm__testcase index, bool force, bool *should_load_fail); +#ifdef __cplusplus +} +#endif #endif diff --git a/tools/perf/util/c++/clang-test.cpp b/tools/perf/util/c++/clang-test.cpp index 0f484fbb2b58..d84e760d2aab 100644 --- a/tools/perf/util/c++/clang-test.cpp +++ b/tools/perf/util/c++/clang-test.cpp @@ -3,6 +3,10 @@ #include "llvm/IR/Function.h" #include "llvm/IR/LLVMContext.h" +#include +#include +#include + class perf_clang_scope { public: explicit perf_clang_scope() {perf_clang__init();} @@ -14,17 +18,24 @@ extern "C" { int test__clang_to_IR(void) { perf_clang_scope _scope; + unsigned int kernel_version; + + if (fetch_kernel_version(&kernel_version, NULL, 0)) + return -1; + + std::string cflag_kver("-DLINUX_VERSION_CODE=" + + std::to_string(kernel_version)); std::unique_ptr M = - perf::getModuleFromSource({"-DRESULT=1"}, + perf::getModuleFromSource({cflag_kver.c_str()}, "perf-test.c", - "int myfunc(void) {return RESULT;}"); + test_llvm__bpf_base_prog); if (!M) return -1; for (llvm::Function& F : *M) - if (F.getName() == "myfunc") + if (F.getName() == "bpf_func__SyS_epoll_wait") return 0; return -1; } 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 @@ +/* + * Support C++ source use utilities defined in util.h + */ + +#ifndef PERF_UTIL_UTIL_CXX_H +#define PERF_UTIL_UTIL_CXX_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Now 'new' is the only C++ keyword found in util.h: + * in tools/include/linux/rbtree.h + * + * Other keywords, like class and delete, should be + * redefined if necessary. + */ +#define new _new +#include "util.h" +#undef new + +#ifdef __cplusplus +} +#endif +#endif From 5e08a76525b8f5e9aeb8b27d0466614abec070a9 Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Sat, 26 Nov 2016 07:03:38 +0000 Subject: [PATCH 12/20] perf clang: Support compile IR to BPF object and add testcase getBPFObjectFromModule() is introduced to compile LLVM IR(Module) to BPF object. Add new testcase for it. Test result: $ ./buildperf/perf test -v clang 51: builtin clang support : 51.1: builtin clang compile C source to IR : --- start --- test child forked, pid 21822 test child finished with 0 ---- end ---- builtin clang support subtest 0: Ok 51.2: builtin clang compile C source to ELF object : --- start --- test child forked, pid 21823 test child finished with 0 ---- end ---- builtin clang support subtest 1: Ok Signed-off-by: Wang Nan Cc: Alexei Starovoitov Cc: He Kuang Cc: Jiri Olsa Cc: Joe Stringer Cc: Zefan Li Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/20161126070354.141764-15-wangnan0@huawei.com [ Remove redundant "Test" from entry descriptions ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/clang.c | 6 +++- tools/perf/util/c++/clang-c.h | 1 + tools/perf/util/c++/clang-test.cpp | 31 ++++++++++++++++---- tools/perf/util/c++/clang.cpp | 45 ++++++++++++++++++++++++++++++ tools/perf/util/c++/clang.h | 3 ++ 5 files changed, 79 insertions(+), 7 deletions(-) diff --git a/tools/perf/tests/clang.c b/tools/perf/tests/clang.c index 636d6d0e9037..f853e242a86c 100644 --- a/tools/perf/tests/clang.c +++ b/tools/perf/tests/clang.c @@ -12,6 +12,10 @@ static struct { .func = test__clang_to_IR, .desc = "builtin clang compile C source to IR", }, + { + .func = test__clang_to_obj, + .desc = "builtin clang compile C source to ELF object", + }, #endif }; @@ -33,7 +37,7 @@ int test__clang(int i __maybe_unused) return TEST_SKIP; } #else -int test__clang(int i __maybe_unused) +int test__clang(int i) { if (i < 0 || i >= (int)ARRAY_SIZE(clang_testcase_table)) return TEST_FAIL; diff --git a/tools/perf/util/c++/clang-c.h b/tools/perf/util/c++/clang-c.h index dcde4b564f3b..22b3936d1f09 100644 --- a/tools/perf/util/c++/clang-c.h +++ b/tools/perf/util/c++/clang-c.h @@ -9,6 +9,7 @@ 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); #ifdef __cplusplus } diff --git a/tools/perf/util/c++/clang-test.cpp b/tools/perf/util/c++/clang-test.cpp index d84e760d2aab..9b11e8c82798 100644 --- a/tools/perf/util/c++/clang-test.cpp +++ b/tools/perf/util/c++/clang-test.cpp @@ -13,15 +13,13 @@ public: ~perf_clang_scope() {perf_clang__cleanup();} }; -extern "C" { - -int test__clang_to_IR(void) +static std::unique_ptr +__test__clang_to_IR(void) { - perf_clang_scope _scope; unsigned int kernel_version; if (fetch_kernel_version(&kernel_version, NULL, 0)) - return -1; + return std::unique_ptr(nullptr); std::string cflag_kver("-DLINUX_VERSION_CODE=" + std::to_string(kernel_version)); @@ -30,14 +28,35 @@ int test__clang_to_IR(void) perf::getModuleFromSource({cflag_kver.c_str()}, "perf-test.c", test_llvm__bpf_base_prog); + return M; +} +extern "C" { +int test__clang_to_IR(void) +{ + perf_clang_scope _scope; + + auto M = __test__clang_to_IR(); if (!M) return -1; - for (llvm::Function& F : *M) if (F.getName() == "bpf_func__SyS_epoll_wait") return 0; return -1; } +int test__clang_to_obj(void) +{ + perf_clang_scope _scope; + + auto M = __test__clang_to_IR(); + if (!M) + return -1; + + auto Buffer = perf::getBPFObjectFromModule(&*M); + if (!Buffer) + return -1; + return 0; +} + } diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp index 715ca0a3dee0..2a1a75df204f 100644 --- a/tools/perf/util/c++/clang.cpp +++ b/tools/perf/util/c++/clang.cpp @@ -13,10 +13,15 @@ #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/TextDiagnosticPrinter.h" #include "clang/Tooling/Tooling.h" +#include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" #include "llvm/Option/Option.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" #include #include "clang.h" @@ -105,12 +110,52 @@ getModuleFromSource(llvm::opt::ArgStringList CFlags, StringRef Path) return getModuleFromSource(std::move(CFlags), Path, VFS); } +std::unique_ptr> +getBPFObjectFromModule(llvm::Module *Module) +{ + using namespace llvm; + + std::string TargetTriple("bpf-pc-linux"); + std::string Error; + const Target* Target = TargetRegistry::lookupTarget(TargetTriple, Error); + if (!Target) { + llvm::errs() << Error; + return std::unique_ptr>(nullptr); + } + + llvm::TargetOptions Opt; + TargetMachine *TargetMachine = + Target->createTargetMachine(TargetTriple, + "generic", "", + Opt, Reloc::Static); + + Module->setDataLayout(TargetMachine->createDataLayout()); + Module->setTargetTriple(TargetTriple); + + std::unique_ptr> Buffer(new SmallVector()); + raw_svector_ostream ostream(*Buffer); + + legacy::PassManager PM; + if (TargetMachine->addPassesToEmitFile(PM, ostream, + TargetMachine::CGFT_ObjectFile)) { + llvm::errs() << "TargetMachine can't emit a file of this type\n"; + return std::unique_ptr>(nullptr);; + } + PM.run(*Module); + + return std::move(Buffer); +} + } extern "C" { void perf_clang__init(void) { perf::LLVMCtx.reset(new llvm::LLVMContext()); + LLVMInitializeBPFTargetInfo(); + LLVMInitializeBPFTarget(); + LLVMInitializeBPFTargetMC(); + LLVMInitializeBPFAsmPrinter(); } void perf_clang__cleanup(void) diff --git a/tools/perf/util/c++/clang.h b/tools/perf/util/c++/clang.h index b4fc2a96b79d..dd8b0427550d 100644 --- a/tools/perf/util/c++/clang.h +++ b/tools/perf/util/c++/clang.h @@ -19,5 +19,8 @@ std::unique_ptr getModuleFromSource(opt::ArgStringList CFlags, StringRef Path); +std::unique_ptr> +getBPFObjectFromModule(llvm::Module *Module); + } #endif From edd695b032ba3a90c3bb07d934500b2c390a61ff Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Sat, 26 Nov 2016 07:03:39 +0000 Subject: [PATCH 13/20] 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 Tested-by: Arnaldo Carvalho de Melo Cc: Alexei Starovoitov Cc: He Kuang Cc: Jiri Olsa Cc: Joe Stringer Cc: Zefan Li 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 --- 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 cf16b94115b5..36c861103291 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 compilation 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: successfull builtin compilation\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 22b3936d1f09..0eadd792ab1f 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 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) 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; +} } From a5ba0a1a5af312c4b4bfe78dc054d832103ec27d Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 4 Dec 2016 21:42:52 +0100 Subject: [PATCH 14/20] tools build: Make the .cmd file more readable Putting extra line between dependencies and cmd_* definition to make it more readable. Before: $ cat .builtin-top.o.cmd ... /home/jolsa/kernel/linux-perf/tools/include/linux/stringify.h \ /home/jolsa/kernel/linux-perf/tools/include/linux/time64.h cmd_builtin-top.o := gcc -Wp,-MD,./.builtin-top.o.d -Wp,-MT,builtin-... ... After: $ cat .builtin-top.o.cmd ... /home/jolsa/kernel/linux-perf/tools/include/linux/stringify.h \ /home/jolsa/kernel/linux-perf/tools/include/linux/time64.h cmd_builtin-top.o := gcc -Wp,-MD,./.builtin-top.o.d -Wp,-MT,builtin-... ... Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1480884178-8072-2-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/build/Build.include | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/build/Build.include b/tools/build/Build.include index 62dcf0c7aac2..475152c52871 100644 --- a/tools/build/Build.include +++ b/tools/build/Build.include @@ -65,7 +65,7 @@ dep-cmd = $(if $(wildcard $(fixdep)), printf '\# cannot find fixdep (%s)\n' $(fixdep) > $(dot-target).cmd; \ printf '\# using basic dep data\n\n' >> $(dot-target).cmd; \ cat $(depfile) >> $(dot-target).cmd; \ - printf '%s\n' 'cmd_$@ := $(make-cmd)' >> $(dot-target).cmd) + printf '\n%s\n' 'cmd_$@ := $(make-cmd)' >> $(dot-target).cmd) ### # if_changed_dep - execute command if any prerequisite is newer than From 2fedf79b69cf05b7e8e82a42d749c621155dd812 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 4 Dec 2016 21:42:53 +0100 Subject: [PATCH 15/20] tools build: Move tabs to spaces where suitable We've been hit several times by a Makefile bug where line indented by tab was falsely considered as target command. We prevent this by always using space indentation for everything except for the target commands. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1480884178-8072-3-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/build/Build.include | 12 +-- tools/build/Makefile.feature | 138 +++++++++++++++++------------------ tools/build/feature/Makefile | 102 +++++++++++++------------- 3 files changed, 126 insertions(+), 126 deletions(-) diff --git a/tools/build/Build.include b/tools/build/Build.include index 475152c52871..418871d02ebf 100644 --- a/tools/build/Build.include +++ b/tools/build/Build.include @@ -72,15 +72,15 @@ dep-cmd = $(if $(wildcard $(fixdep)), # target, or command line has changed and update # dependencies in the cmd file if_changed_dep = $(if $(strip $(any-prereq) $(arg-check)), \ - @set -e; \ - $(echo-cmd) $(cmd_$(1)) && $(dep-cmd)) + @set -e; \ + $(echo-cmd) $(cmd_$(1)) && $(dep-cmd)) # if_changed - execute command if any prerequisite is newer than # target, or command line has changed -if_changed = $(if $(strip $(any-prereq) $(arg-check)), \ - @set -e; \ - $(echo-cmd) $(cmd_$(1)); \ - printf '%s\n' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd) +if_changed = $(if $(strip $(any-prereq) $(arg-check)), \ + @set -e; \ + $(echo-cmd) $(cmd_$(1)); \ + printf '%s\n' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd) ### # C flags to be used in rule definitions, includes: diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature index ae52e029dd22..e3fb5ecbdcb6 100644 --- a/tools/build/Makefile.feature +++ b/tools/build/Makefile.feature @@ -27,58 +27,58 @@ endef # the rule that uses them - an example for that is the 'bionic' # feature check. ] # -FEATURE_TESTS_BASIC := \ - backtrace \ - dwarf \ - dwarf_getlocations \ - fortify-source \ - sync-compare-and-swap \ - glibc \ - gtk2 \ - gtk2-infobar \ - libaudit \ - libbfd \ - libelf \ - libelf-getphdrnum \ - libelf-gelf_getnote \ - libelf-getshdrstrndx \ - libelf-mmap \ - libnuma \ - numa_num_possible_cpus \ - libperl \ - libpython \ - libpython-version \ - libslang \ - libcrypto \ - libunwind \ - libunwind-x86 \ - libunwind-x86_64 \ - libunwind-arm \ - libunwind-aarch64 \ - pthread-attr-setaffinity-np \ - stackprotector-all \ - timerfd \ - libdw-dwarf-unwind \ - zlib \ - lzma \ - get_cpuid \ - bpf \ - sdt +FEATURE_TESTS_BASIC := \ + backtrace \ + dwarf \ + dwarf_getlocations \ + fortify-source \ + sync-compare-and-swap \ + glibc \ + gtk2 \ + gtk2-infobar \ + libaudit \ + libbfd \ + libelf \ + libelf-getphdrnum \ + libelf-gelf_getnote \ + libelf-getshdrstrndx \ + libelf-mmap \ + libnuma \ + numa_num_possible_cpus \ + libperl \ + libpython \ + libpython-version \ + libslang \ + libcrypto \ + libunwind \ + libunwind-x86 \ + libunwind-x86_64 \ + libunwind-arm \ + libunwind-aarch64 \ + pthread-attr-setaffinity-np \ + stackprotector-all \ + timerfd \ + libdw-dwarf-unwind \ + zlib \ + lzma \ + get_cpuid \ + bpf \ + sdt # FEATURE_TESTS_BASIC + FEATURE_TESTS_EXTRA is the complete list # of all feature tests -FEATURE_TESTS_EXTRA := \ - bionic \ - compile-32 \ - compile-x32 \ - cplus-demangle \ - hello \ - libbabeltrace \ - liberty \ - liberty-z \ - libunwind-debug-frame \ - libunwind-debug-frame-arm \ - libunwind-debug-frame-aarch64 +FEATURE_TESTS_EXTRA := \ + bionic \ + compile-32 \ + compile-x32 \ + cplus-demangle \ + hello \ + libbabeltrace \ + liberty \ + liberty-z \ + libunwind-debug-frame \ + libunwind-debug-frame-arm \ + libunwind-debug-frame-aarch64 FEATURE_TESTS ?= $(FEATURE_TESTS_BASIC) @@ -86,26 +86,26 @@ ifeq ($(FEATURE_TESTS),all) FEATURE_TESTS := $(FEATURE_TESTS_BASIC) $(FEATURE_TESTS_EXTRA) endif -FEATURE_DISPLAY ?= \ - dwarf \ - dwarf_getlocations \ - glibc \ - gtk2 \ - libaudit \ - libbfd \ - libelf \ - libnuma \ - numa_num_possible_cpus \ - libperl \ - libpython \ - libslang \ - libcrypto \ - libunwind \ - libdw-dwarf-unwind \ - zlib \ - lzma \ - get_cpuid \ - bpf +FEATURE_DISPLAY ?= \ + dwarf \ + dwarf_getlocations \ + glibc \ + gtk2 \ + libaudit \ + libbfd \ + libelf \ + libnuma \ + numa_num_possible_cpus \ + libperl \ + libpython \ + libslang \ + libcrypto \ + libunwind \ + libdw-dwarf-unwind \ + zlib \ + lzma \ + get_cpuid \ + bpf # Set FEATURE_CHECK_(C|LD)FLAGS-all for all FEATURE_TESTS features. # If in the future we need per-feature checks/flags for features not diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile index 871d5536951d..303196c16019 100644 --- a/tools/build/feature/Makefile +++ b/tools/build/feature/Makefile @@ -1,54 +1,54 @@ -FILES= \ - test-all.bin \ - test-backtrace.bin \ - test-bionic.bin \ - test-dwarf.bin \ - test-dwarf_getlocations.bin \ - test-fortify-source.bin \ - test-sync-compare-and-swap.bin \ - test-glibc.bin \ - test-gtk2.bin \ - test-gtk2-infobar.bin \ - test-hello.bin \ - test-libaudit.bin \ - test-libbfd.bin \ - test-liberty.bin \ - test-liberty-z.bin \ - test-cplus-demangle.bin \ - test-libelf.bin \ - test-libelf-getphdrnum.bin \ - test-libelf-gelf_getnote.bin \ - test-libelf-getshdrstrndx.bin \ - test-libelf-mmap.bin \ - test-libnuma.bin \ - test-numa_num_possible_cpus.bin \ - test-libperl.bin \ - test-libpython.bin \ - test-libpython-version.bin \ - test-libslang.bin \ - test-libcrypto.bin \ - test-libunwind.bin \ - test-libunwind-debug-frame.bin \ - test-libunwind-x86.bin \ - test-libunwind-x86_64.bin \ - test-libunwind-arm.bin \ - test-libunwind-aarch64.bin \ - test-libunwind-debug-frame-arm.bin \ - test-libunwind-debug-frame-aarch64.bin \ - test-pthread-attr-setaffinity-np.bin \ - test-stackprotector-all.bin \ - test-timerfd.bin \ - test-libdw-dwarf-unwind.bin \ - test-libbabeltrace.bin \ - test-compile-32.bin \ - test-compile-x32.bin \ - test-zlib.bin \ - test-lzma.bin \ - test-bpf.bin \ - test-get_cpuid.bin \ - test-sdt.bin \ - test-cxx.bin \ - test-jvmti.bin +FILES= \ + test-all.bin \ + test-backtrace.bin \ + test-bionic.bin \ + test-dwarf.bin \ + test-dwarf_getlocations.bin \ + test-fortify-source.bin \ + test-sync-compare-and-swap.bin \ + test-glibc.bin \ + test-gtk2.bin \ + test-gtk2-infobar.bin \ + test-hello.bin \ + test-libaudit.bin \ + test-libbfd.bin \ + test-liberty.bin \ + test-liberty-z.bin \ + test-cplus-demangle.bin \ + test-libelf.bin \ + test-libelf-getphdrnum.bin \ + test-libelf-gelf_getnote.bin \ + test-libelf-getshdrstrndx.bin \ + test-libelf-mmap.bin \ + test-libnuma.bin \ + test-numa_num_possible_cpus.bin \ + test-libperl.bin \ + test-libpython.bin \ + test-libpython-version.bin \ + test-libslang.bin \ + test-libcrypto.bin \ + test-libunwind.bin \ + test-libunwind-debug-frame.bin \ + test-libunwind-x86.bin \ + test-libunwind-x86_64.bin \ + test-libunwind-arm.bin \ + test-libunwind-aarch64.bin \ + test-libunwind-debug-frame-arm.bin \ + test-libunwind-debug-frame-aarch64.bin \ + test-pthread-attr-setaffinity-np.bin \ + test-stackprotector-all.bin \ + test-timerfd.bin \ + test-libdw-dwarf-unwind.bin \ + test-libbabeltrace.bin \ + test-compile-32.bin \ + test-compile-x32.bin \ + test-zlib.bin \ + test-lzma.bin \ + test-bpf.bin \ + test-get_cpuid.bin \ + test-sdt.bin \ + test-cxx.bin \ + test-jvmti.bin FILES := $(addprefix $(OUTPUT),$(FILES)) From 5c319a67b13da8323ec7bdb8d2ea729eb8a20735 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 4 Dec 2016 21:42:54 +0100 Subject: [PATCH 16/20] perf tools: Move install-gtk target into rules area The upcoming fixdep fix needs all targets at the same area, so they'll fit under a signal condition block. Move install-gtk target into the rules section. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1480884178-8072-4-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile.perf | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index dfb20dd31865..593d765d62ab 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -331,11 +331,6 @@ endif ifndef NO_GTK2 ALL_PROGRAMS += $(OUTPUT)libperf-gtk.so GTK_IN := $(OUTPUT)gtk-in.o - -install-gtk: $(OUTPUT)libperf-gtk.so - $(call QUIET_INSTALL, 'GTK UI') \ - $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(libdir_SQ)'; \ - $(INSTALL) $(OUTPUT)libperf-gtk.so '$(DESTDIR_SQ)$(libdir_SQ)' endif ifdef ASCIIDOC8 @@ -712,7 +707,14 @@ check: $(OUTPUT)common-cmds.h ### Installation rules +ifndef NO_GTK2 +install-gtk: $(OUTPUT)libperf-gtk.so + $(call QUIET_INSTALL, 'GTK UI') \ + $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(libdir_SQ)'; \ + $(INSTALL) $(OUTPUT)libperf-gtk.so '$(DESTDIR_SQ)$(libdir_SQ)' +else install-gtk: +endif install-tools: all install-gtk $(call QUIET_INSTALL, binaries) \ From 0b4d4b076251542dc81d128f481c3d3b5fc24863 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 4 Dec 2016 21:42:55 +0100 Subject: [PATCH 17/20] perf tools: Move python/perf.so target into rules area Following fixdep fix needs all targets at the same area, so they'll fit under signal condition block. Moving python/perf.so target into rules section and intentionally removing the perl script related comment. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1480884178-8072-5-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile.perf | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index 593d765d62ab..2784b5843aef 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -268,17 +268,6 @@ python-clean := $(call QUIET_CLEAN, python) $(RM) -r $(PYTHON_EXTBUILD) $(OUTPUT PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources) PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBAPI) -$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) $(LIBTRACEEVENT_DYNAMIC_LIST) - $(QUIET_GEN)LDSHARED="$(CC) -pthread -shared" \ - CFLAGS='$(CFLAGS)' LDFLAGS='$(LDFLAGS) $(LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS)' \ - $(PYTHON_WORD) util/setup.py \ - --quiet build_ext; \ - mkdir -p $(OUTPUT)python && \ - cp $(PYTHON_EXTBUILD_LIB)perf.so $(OUTPUT)python/ -# -# No Perl scripts right now: -# - SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) PROGRAMS += $(OUTPUT)perf @@ -362,6 +351,14 @@ SHELL = $(SHELL_PATH) all: shell_compatibility_test $(ALL_PROGRAMS) $(LANG_BINDINGS) $(OTHER_PROGRAMS) +$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) $(LIBTRACEEVENT_DYNAMIC_LIST) + $(QUIET_GEN)LDSHARED="$(CC) -pthread -shared" \ + CFLAGS='$(CFLAGS)' LDFLAGS='$(LDFLAGS) $(LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS)' \ + $(PYTHON_WORD) util/setup.py \ + --quiet build_ext; \ + mkdir -p $(OUTPUT)python && \ + cp $(PYTHON_EXTBUILD_LIB)perf.so $(OUTPUT)python/ + please_set_SHELL_PATH_to_a_more_modern_shell: $(Q)$$(:) From 207da4739e3e6ced6dbfebed7416b35c0440e591 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 4 Dec 2016 21:42:58 +0100 Subject: [PATCH 18/20] perf tools: Cleanup build directory before each test Cleanup the fixdep tool before every test. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1480884178-8072-8-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/make | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/tests/make b/tools/perf/tests/make index aa49b6600d1f..0784748f1670 100644 --- a/tools/perf/tests/make +++ b/tools/perf/tests/make @@ -280,7 +280,7 @@ endif MAKEFLAGS := --no-print-directory -clean := @(cd $(PERF); $(MAKE_F) -s $(O_OPT) clean >/dev/null) +clean := @(cd $(PERF); $(MAKE_F) -s $(O_OPT) clean >/dev/null && $(MAKE) -s $(O_OPT) -C ../build clean >/dev/null) $(run): $(call clean) From d4dcadec43def7b2a4a4c1cae7d727c17d2f25c5 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 4 Dec 2016 21:42:57 +0100 Subject: [PATCH 19/20] perf tools: Add non config targets Adding some missing non config targets that were for some reason omitted. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1480884178-8072-7-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile.perf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index 2784b5843aef..10495c9dbe71 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -177,7 +177,7 @@ SUBCMD_DIR = $(srctree)/tools/lib/subcmd/ # non-config cases config := 1 -NON_CONFIG_TARGETS := clean TAGS tags cscope help install-doc +NON_CONFIG_TARGETS := clean TAGS tags cscope help install-doc install-man install-html install-info install-pdf doc man html info pdf ifdef MAKECMDGOALS ifeq ($(filter-out $(NON_CONFIG_TARGETS),$(MAKECMDGOALS)),) From bec60e50af83741cde1786ab475d4bf472aed6f9 Mon Sep 17 00:00:00 2001 From: Ravi Bangoria Date: Mon, 5 Dec 2016 21:26:45 +0530 Subject: [PATCH 20/20] perf annotate: Show raw form for jump instruction with indirect target MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For jump instructions that does not include target address as direct operand, show the original disassembled line for them. This is needed for certain powerpc jump instructions that use target address in a register (such as bctr, btar, ...). Before: ld r12,32088(r12) mtctr r12 v bctr ffffffffffffca2c std r2,24(r1) addis r12,r2,-1 After: ld r12,32088(r12) mtctr r12 v bctr std r2,24(r1) addis r12,r2,-1 Committer notes: Testing it using a perf.data file and vmlinux for powerpc64, cross-annotating it on a x86_64 workstation: Before: .__bpf_prog_run vmlinux.powerpc │ std r10,512(r9) ▒ │ lbz r9,0(r31) ▒ │ rldicr r9,r9,3,60 ▒ │ ldx r9,r30,r9 ▒ │ mtctr r9 ▒ 100.00 │ ↓ bctr 3fffffffffe01510 ▒ │ lwa r10,4(r31) ▒ │ lwz r9,0(r31) ▒ Invalid jump offset: 3fffffffffe01510 After: .__bpf_prog_run vmlinux.powerpc │ std r10,512(r9) ▒ │ lbz r9,0(r31) ▒ │ rldicr r9,r9,3,60 ▒ │ ldx r9,r30,r9 ▒ │ mtctr r9 ▒ 100.00 │ ↓ bctr ▒ │ lwa r10,4(r31) ▒ │ lwz r9,0(r31) ▒ Invalid jump offset: 3fffffffffe01510 This, in turn, uncovers another problem with jumps without operands, the ENTER/-> operation, to jump to the target, still continues using the bogus target :-) BTW, this was the file used for the above tests: [acme@jouet ravi_bangoria]$ perf report --header-only -i perf.data.f22vm.powerdev # ======== # captured on: Thu Nov 24 12:40:38 2016 # hostname : pdev-f22-qemu # os release : 4.4.10-200.fc22.ppc64 # perf version : 4.9.rc1.g6298ce # arch : ppc64 # nrcpus online : 48 # nrcpus avail : 48 # cpudesc : POWER7 (architected), altivec supported # cpuid : 74,513 # total memory : 4158976 kB # cmdline : /home/ravi/Workspace/linux/tools/perf/perf record -a # event : name = cycles:ppp, , size = 112, { sample_period, sample_freq } = 4000, sample_type = IP|TID|TIME|CPU|PERIOD, disabled = 1, inherit = 1, mmap = 1, c # HEADER_CPU_TOPOLOGY info available, use -I to display # HEADER_NUMA_TOPOLOGY info available, use -I to display # pmu mappings: cpu = 4, software = 1, tracepoint = 2, breakpoint = 5 # missing features: HEADER_TRACING_DATA HEADER_BRANCH_STACK HEADER_GROUP_DESC HEADER_AUXTRACE HEADER_STAT HEADER_CACHE # ======== # [acme@jouet ravi_bangoria]$ Suggested-by: Michael Ellerman Signed-off-by: Ravi Bangoria Tested-by: Arnaldo Carvalho de Melo Cc: Alexander Shishkin Cc: Chris Riyder Cc: Kim Phillips Cc: Markus Trippelsdorf Cc: Masami Hiramatsu Cc: Naveen N. Rao Cc: Peter Zijlstra Cc: Taeung Song Cc: linuxppc-dev@lists.ozlabs.org Link: http://lkml.kernel.org/r/1480953407-7605-1-git-send-email-ravi.bangoria@linux.vnet.ibm.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/annotate.c | 3 +++ 1 file changed, 3 insertions(+) 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 static int jump__scnprintf(struct ins *ins, char *bf, size_t size, struct ins_operands *ops) { + if (!ops->target.addr) + return ins__raw_scnprintf(ins, bf, size, ops); + return scnprintf(bf, size, "%-6.6s %" PRIx64, ins->name, ops->target.offset); }