From 0635b0f71424be7706793ac260d063491a2889a0 Mon Sep 17 00:00:00 2001 From: Milos Vyletel Date: Fri, 20 Mar 2015 11:37:25 +0100 Subject: [PATCH 01/19] perf tools: Fix race in build_id_cache__add_s() int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, const char *name, bool is_kallsyms, bool is_vdso) { ... if (access(filename, F_OK)) { ^--------------------------------------------------------- [1] if (is_kallsyms) { if (copyfile("/proc/kallsyms", filename)) goto out_free; } else if (link(realname, filename) && copyfile(name, filename)) ^-----------------------------^------------- [2] \------------ [3] goto out_free; } ... When multiple instances of perf record get to [1] at more or less same time and run access() one or more may get failure because the file does not exist yet (since the first instance did not have chance to link it yet). At this point the race moves to link() at [2] where first thread to get there links file and goes on but second one gets -EEXIST so it runs copyfile [3] which truncates the file. reproducer: rm -rf /root/.debug for cpu in $(awk '/processor/ {print $3}' /proc/cpuinfo); do perf record -a -v -T -F 1000 -C $cpu \ -o perf-${cpu}.data sleep 5 2> /dev/null & done wait and simply search for empty files by: find /lib/modules/`uname -r`/kernel/* -size 0 Signed-off-by: Milos Vyletel Acked-by: Jiri Olsa Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1426847846-11112-1-git-send-email-milos@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/build-id.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c index a19674666b4e..f7fb2587df69 100644 --- a/tools/perf/util/build-id.c +++ b/tools/perf/util/build-id.c @@ -374,7 +374,8 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name, if (is_kallsyms) { if (copyfile("/proc/kallsyms", filename)) goto out_free; - } else if (link(realname, filename) && copyfile(name, filename)) + } else if (link(realname, filename) && errno != EEXIST && + copyfile(name, filename)) goto out_free; } From 8b8ca6e15e392b366a7d69c6bf1abaae005f2b63 Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Fri, 20 Mar 2015 02:57:52 +0000 Subject: [PATCH 02/19] perf tools: Don't allow empty argument for field-separator Both 'perf diff' and 'perf mem' have 'field-separator' option, which causes segfault if passed with empty string. This patch uses previously introduced 'OPT_STRING_NOEMPTY' option macro to prevent fault. Signed-off-by: Wang Nan Tested-by: Arnaldo Carvalho de Melo Cc: pi3orama@163.com Cc: Namhyung Kim Cc: Zefan Li Link: http://lkml.kernel.org/r/1426820272-23302-1-git-send-email-wangnan0@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-diff.c | 2 +- tools/perf/builtin-mem.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index f800fc95f5d7..473887d1d61a 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c @@ -802,7 +802,7 @@ static const struct option options[] = { OPT_STRING('s', "sort", &sort_order, "key[,key2...]", "sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline, ..." " Please refer the man page for the complete list."), - OPT_STRING('t', "field-separator", &symbol_conf.field_sep, "separator", + OPT_STRING_NOEMPTY('t', "field-separator", &symbol_conf.field_sep, "separator", "separator for columns, no spaces will be added between " "columns '.' is reserved."), OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c index 46c69318de84..b4dcf0bfc029 100644 --- a/tools/perf/builtin-mem.c +++ b/tools/perf/builtin-mem.c @@ -286,7 +286,7 @@ int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused) "input file name"), OPT_STRING('C', "cpu", &mem.cpu_list, "cpu", "list of cpus to profile"), - OPT_STRING('x', "field-separator", &symbol_conf.field_sep, + OPT_STRING_NOEMPTY('x', "field-separator", &symbol_conf.field_sep, "separator", "separator for columns, no spaces will be added" " between columns '.' is reserved."), From 43f3e14f0cd16a6c3430137ee22176033d1960da Mon Sep 17 00:00:00 2001 From: Yunlong Song Date: Fri, 20 Mar 2015 11:20:37 +0800 Subject: [PATCH 03/19] perf build: Use FEATURE-DUMP instead of PERF-FEATURES in the .gitignore file Since commit 4ae61202b31c ("perf build: Rename PERF-FEATURES into FEATURE-DUMP") renames PERF-FEATURES into FEATURE-DUMP, the .gitignore file should also do this thing for consistency. Signed-off-by: Yunlong Song Acked-by: Jiri Olsa Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Wang Nan Link: http://lkml.kernel.org/r/1426821638-11227-2-git-send-email-yunlong.song@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/.gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/.gitignore b/tools/perf/.gitignore index 68328f517a2e..812f904193e8 100644 --- a/tools/perf/.gitignore +++ b/tools/perf/.gitignore @@ -1,7 +1,7 @@ PERF-CFLAGS PERF-GUI-VARS PERF-VERSION-FILE -PERF-FEATURES +FEATURE-DUMP perf perf-read-vdso32 perf-read-vdsox32 From 1c30f546f3b7a1ac8b002dc3b3e8f4e26d195fa0 Mon Sep 17 00:00:00 2001 From: Yunlong Song Date: Fri, 20 Mar 2015 11:20:38 +0800 Subject: [PATCH 04/19] perf build: Add config/feature-checks/*.output to the .gitignore file They are all auto-generated files during the perf building. Before this patch: $ git status Untracked files: (use "git add ..." to include in what will be committed) config/feature-checks/test-all.make.output config/feature-checks/test-backtrace.make.output config/feature-checks/test-bionic.make.output config/feature-checks/test-dwarf.make.output config/feature-checks/test-fortify-source.make.output config/feature-checks/test-glibc.make.output config/feature-checks/test-gtk2-infobar.make.output config/feature-checks/test-gtk2.make.output config/feature-checks/test-libaudit.make.output config/feature-checks/test-libbabeltrace.make.output config/feature-checks/test-libbfd.make.output config/feature-checks/test-libdw-dwarf-unwind.make.output config/feature-checks/test-libelf-getphdrnum.make.output config/feature-checks/test-libelf-mmap.make.output config/feature-checks/test-libelf.make.output config/feature-checks/test-libnuma.make.output config/feature-checks/test-libperl.make.output config/feature-checks/test-libpython-version.make.output config/feature-checks/test-libpython.make.output config/feature-checks/test-libslang.make.output config/feature-checks/test-libunwind.make.output config/feature-checks/test-pthread-attr-setaffinity-np.make.output config/feature-checks/test-stackprotector-all.make.output config/feature-checks/test-sync-compare-and-swap.make.output config/feature-checks/test-timerfd.make.output config/feature-checks/test-zlib.make.output After this patch: $ git status nothing to commit, working directory clean Signed-off-by: Yunlong Song Tested-by: Arnaldo Carvalho de Melo Acked-by: Jiri Olsa Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Wang Nan Link: http://lkml.kernel.org/r/1426821638-11227-3-git-send-email-yunlong.song@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/config/feature-checks/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/perf/config/feature-checks/.gitignore b/tools/perf/config/feature-checks/.gitignore index 80f3da0c3515..09b335b98842 100644 --- a/tools/perf/config/feature-checks/.gitignore +++ b/tools/perf/config/feature-checks/.gitignore @@ -1,2 +1,3 @@ *.d *.bin +*.output From 0560a0c4a12a45def9700e7ec3215da102cf914b Mon Sep 17 00:00:00 2001 From: He Kuang Date: Fri, 20 Mar 2015 09:56:56 +0800 Subject: [PATCH 05/19] perf probe: Fix failure to add multiple probes without debuginfo Perf tries to find probe function addresses from map when debuginfo could not be found. To the first added function, the value of ref_reloc_sym was set in maps__set_kallsyms_ref_reloc_sym() and can be obtained from host_machine->kmaps->maps. After that, new maps are added to host_machine->kmaps->maps in dso__load_kcore(), all these new added maps do not have a valid ref_reloc_sym. When adding a second function, get_target_map() may get a map without valid ref_reloc_sym, and raise the error "Relocated base symbol is not found". Fix this by using kernel_get_ref_reloc_sym() to get ref_reloc_sym. This problem can be reproduced as following: $ perf probe --add='sys_write' --add='sys_open' Relocated base symbol is not found! Error: Failed to add events. After this patch: $ perf probe --add='sys_write' --add='sys_open' Added new event: probe:sys_write (on sys_write) You can now use it in all perf tools, such as: perf record -e probe:sys_write -aR sleep 1 Added new event: probe:sys_open (on sys_open) You can now use it in all perf tools, such as: perf record -e probe:sys_open -aR sleep 1 Signed-off-by: He Kuang Tested-by: Arnaldo Carvalho de Melo Tested-by: Masami Hiramatsu Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Wang Nan Link: http://lkml.kernel.org/r/1426816616-2394-1-git-send-email-hekuang@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/probe-event.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index f272a711ad15..6b95985db5b0 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -2507,7 +2507,6 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev, int max_tevs, const char *target) { struct map *map = NULL; - struct kmap *kmap = NULL; struct ref_reloc_sym *reloc_sym = NULL; struct symbol *sym; struct probe_trace_event *tev; @@ -2540,8 +2539,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev, } if (!pev->uprobes && !pp->retprobe) { - kmap = map__kmap(map); - reloc_sym = kmap->ref_reloc_sym; + reloc_sym = kernel_get_ref_reloc_sym(); if (!reloc_sym) { pr_warning("Relocated base symbol is not found!\n"); ret = -EINVAL; From 13f22a2d4a5359867aa05562fc922f1ca24873a5 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Thu, 19 Mar 2015 12:23:03 -0600 Subject: [PATCH 06/19] perf trace: Fix summary_only option The intent of the -s/--summary-only option is to just show a summary of the system calls and statistics without any of the individual events. Commit e596663ebb2 broke that by showing the interrupted lines: perf trace -i perf.data -s ... 0.741 ( 0.000 ms): sleep/31316 fstat(fd: 4, statbuf: 0x7ffc75ceb830 ) ... 0.744 ( 0.000 ms): sleep/31316 mmap(len: 100244, prot: READ, flags: PRIVATE, fd: 4 ) ... 0.747 ( 0.000 ms): perf/31315 write(fd: 3, buf: 0x7d4bb0, count: 8 ) ... ... Fix by checking for the summary only option. Signed-off-by: David Ahern Link: http://lkml.kernel.org/r/1426789383-19023-1-git-send-email-dsahern@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 0b3b4e4984b9..6af6bcec930e 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -1724,7 +1724,8 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel, return -1; } - printed += trace__printf_interrupted_entry(trace, sample); + if (!trace->summary_only) + printed += trace__printf_interrupted_entry(trace, sample); ttrace->entry_time = sample->time; msg = ttrace->entry_str; From 58d4f00ff13f20468f8fa8edcb57a195c31af46d Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 19 Mar 2015 20:48:49 +0100 Subject: [PATCH 07/19] perf build: Fix feature_check name clash We have 2 feature_check functions, which conflict with each other. Fixing it by renaming the latter to feature_display_check. Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: David Ahern Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/n/tip-wmyccro6qeffseforipu5kcl@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/config/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile index e7f83b15fcbf..81d8c2bbc4df 100644 --- a/tools/perf/config/Makefile +++ b/tools/perf/config/Makefile @@ -805,14 +805,14 @@ ifneq ("$(FEATURE_DUMP)","$(FEATURE_DUMP_FILE)") feature_display := 1 endif -feature_check = $(eval $(feature_check_code)) -define feature_check_code +feature_display_check = $(eval $(feature_check_code)) +define feature_display_check_code ifneq ($(feature-$(1)), 1) feature_display := 1 endif endef -$(foreach feat,$(FEATURE_DISPLAY),$(call feature_check,$(feat))) +$(foreach feat,$(FEATURE_DISPLAY),$(call feature_display_check,$(feat))) ifeq ($(VF),1) feature_display := 1 From 0afc5cad387db56054b09bb14baf0e6e49df2fd2 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 1 Mar 2015 21:04:01 +0100 Subject: [PATCH 08/19] perf build: Separate feature make support into config/Makefile.feature Move feature related code into separate makefile. The new Makefile.feature is included from config/Makefile. It will be moved later into tools/build. Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: David Ahern Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/n/tip-kj76wphg05x83n6d5ff85ybx@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/config/Makefile | 165 +--------------------------- tools/perf/config/Makefile.feature | 167 +++++++++++++++++++++++++++++ 2 files changed, 168 insertions(+), 164 deletions(-) create mode 100644 tools/perf/config/Makefile.feature diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile index 81d8c2bbc4df..01278429965a 100644 --- a/tools/perf/config/Makefile +++ b/tools/perf/config/Makefile @@ -176,102 +176,7 @@ LDFLAGS += -Wl,-z,noexecstack EXTLIBS = -lpthread -lrt -lm -ldl -ifneq ($(OUTPUT),) - OUTPUT_FEATURES = $(OUTPUT)config/feature-checks/ - $(shell mkdir -p $(OUTPUT_FEATURES)) -endif - -feature_check = $(eval $(feature_check_code)) -define feature_check_code - feature-$(1) := $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS) $(FEATURE_CHECK_CFLAGS-$(1))" LDFLAGS="$(LDFLAGS) $(FEATURE_CHECK_LDFLAGS-$(1))" -C config/feature-checks test-$1.bin >/dev/null 2>/dev/null && echo 1 || echo 0) -endef - -feature_set = $(eval $(feature_set_code)) -define feature_set_code - feature-$(1) := 1 -endef - -# -# Build the feature check binaries in parallel, ignore errors, ignore return value and suppress output: -# - -# -# Note that this is not a complete list of all feature tests, just -# those that are typically built on a fully configured system. -# -# [ Feature tests not mentioned here have to be built explicitly in -# the rule that uses them - an example for that is the 'bionic' -# feature check. ] -# -FEATURE_TESTS = \ - backtrace \ - dwarf \ - fortify-source \ - sync-compare-and-swap \ - glibc \ - gtk2 \ - gtk2-infobar \ - libaudit \ - libbfd \ - libelf \ - libelf-getphdrnum \ - libelf-mmap \ - libnuma \ - libperl \ - libpython \ - libpython-version \ - libslang \ - libunwind \ - pthread-attr-setaffinity-np \ - stackprotector-all \ - timerfd \ - libdw-dwarf-unwind \ - zlib - -FEATURE_DISPLAY = \ - dwarf \ - glibc \ - gtk2 \ - libaudit \ - libbfd \ - libelf \ - libnuma \ - libperl \ - libpython \ - libslang \ - libunwind \ - libdw-dwarf-unwind \ - zlib - -# 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 -# mentioned in this list we need to refactor this ;-). -set_test_all_flags = $(eval $(set_test_all_flags_code)) -define set_test_all_flags_code - FEATURE_CHECK_CFLAGS-all += $(FEATURE_CHECK_CFLAGS-$(1)) - FEATURE_CHECK_LDFLAGS-all += $(FEATURE_CHECK_LDFLAGS-$(1)) -endef - -$(foreach feat,$(FEATURE_TESTS),$(call set_test_all_flags,$(feat))) - -# -# Special fast-path for the 'all features are available' case: -# -$(call feature_check,all,$(MSG)) - -# -# Just in case the build freshly failed, make sure we print the -# feature matrix: -# -ifeq ($(feature-all), 1) - # - # test-all.c passed - just set all the core feature flags to 1: - # - $(foreach feat,$(FEATURE_TESTS),$(call feature_set,$(feat))) -else - $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS)" LDFLAGS=$(LDFLAGS) -i -j -C config/feature-checks $(addsuffix .bin,$(FEATURE_TESTS)) >/dev/null 2>&1) - $(foreach feat,$(FEATURE_TESTS),$(call feature_check,$(feat))) -endif +include $(src-perf)/config/Makefile.feature ifeq ($(feature-stackprotector-all), 1) CFLAGS += -fstack-protector-all @@ -763,80 +668,12 @@ plugindir=$(libdir)/traceevent/plugins plugindir_SQ= $(subst ','\'',$(plugindir)) endif -# -# Print the result of the feature test: -# -feature_print_status = $(eval $(feature_print_status_code)) $(info $(MSG)) - -define feature_print_status_code - ifeq ($(feature-$(1)), 1) - MSG = $(shell printf '...%30s: [ \033[32mon\033[m ]' $(1)) - else - MSG = $(shell printf '...%30s: [ \033[31mOFF\033[m ]' $(1)) - endif -endef - print_var = $(eval $(print_var_code)) $(info $(MSG)) define print_var_code MSG = $(shell printf '...%30s: %s' $(1) $($(1))) endef -feature_print_text = $(eval $(feature_print_text_code)) $(info $(MSG)) -define feature_print_text_code - MSG = $(shell printf '...%30s: %s' $(1) $(2)) -endef - -FEATURE_DUMP := $(foreach feat,$(FEATURE_DISPLAY),feature-$(feat)($(feature-$(feat)))) -FEATURE_DUMP_FILE := $(shell touch $(OUTPUT)FEATURE-DUMP; cat $(OUTPUT)FEATURE-DUMP) - -ifeq ($(dwarf-post-unwind),1) - FEATURE_DUMP += dwarf-post-unwind($(dwarf-post-unwind-text)) -endif - -# The $(feature_display) controls the default detection message -# output. It's set if: -# - detected features differes from stored features from -# last build (in FEATURE-DUMP file) -# - one of the $(FEATURE_DISPLAY) is not detected -# - VF is enabled - -ifneq ("$(FEATURE_DUMP)","$(FEATURE_DUMP_FILE)") - $(shell echo "$(FEATURE_DUMP)" > $(OUTPUT)FEATURE-DUMP) - feature_display := 1 -endif - -feature_display_check = $(eval $(feature_check_code)) -define feature_display_check_code - ifneq ($(feature-$(1)), 1) - feature_display := 1 - endif -endef - -$(foreach feat,$(FEATURE_DISPLAY),$(call feature_display_check,$(feat))) - ifeq ($(VF),1) - feature_display := 1 - feature_verbose := 1 -endif - -ifeq ($(feature_display),1) - $(info ) - $(info Auto-detecting system features:) - $(foreach feat,$(FEATURE_DISPLAY),$(call feature_print_status,$(feat),)) - - ifeq ($(dwarf-post-unwind),1) - $(call feature_print_text,"DWARF post unwind library", $(dwarf-post-unwind-text)) - endif - - ifneq ($(feature_verbose),1) - $(info ) - endif -endif - -ifeq ($(feature_verbose),1) - TMP := $(filter-out $(FEATURE_DISPLAY),$(FEATURE_TESTS)) - $(foreach feat,$(TMP),$(call feature_print_status,$(feat),)) - $(info ) $(call print_var,prefix) $(call print_var,bindir) $(call print_var,libdir) diff --git a/tools/perf/config/Makefile.feature b/tools/perf/config/Makefile.feature new file mode 100644 index 000000000000..8c98bbce6031 --- /dev/null +++ b/tools/perf/config/Makefile.feature @@ -0,0 +1,167 @@ +ifneq ($(OUTPUT),) + OUTPUT_FEATURES = $(OUTPUT)config/feature-checks/ + $(shell mkdir -p $(OUTPUT_FEATURES)) +endif + +feature_check = $(eval $(feature_check_code)) +define feature_check_code + feature-$(1) := $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS) $(FEATURE_CHECK_CFLAGS-$(1))" LDFLAGS="$(LDFLAGS) $(FEATURE_CHECK_LDFLAGS-$(1))" -C config/feature-checks test-$1.bin >/dev/null 2>/dev/null && echo 1 || echo 0) +endef + +feature_set = $(eval $(feature_set_code)) +define feature_set_code + feature-$(1) := 1 +endef + +# +# Build the feature check binaries in parallel, ignore errors, ignore return value and suppress output: +# + +# +# Note that this is not a complete list of all feature tests, just +# those that are typically built on a fully configured system. +# +# [ Feature tests not mentioned here have to be built explicitly in +# the rule that uses them - an example for that is the 'bionic' +# feature check. ] +# +FEATURE_TESTS = \ + backtrace \ + dwarf \ + fortify-source \ + sync-compare-and-swap \ + glibc \ + gtk2 \ + gtk2-infobar \ + libaudit \ + libbfd \ + libelf \ + libelf-getphdrnum \ + libelf-mmap \ + libnuma \ + libperl \ + libpython \ + libpython-version \ + libslang \ + libunwind \ + pthread-attr-setaffinity-np \ + stackprotector-all \ + timerfd \ + libdw-dwarf-unwind \ + zlib + +FEATURE_DISPLAY = \ + dwarf \ + glibc \ + gtk2 \ + libaudit \ + libbfd \ + libelf \ + libnuma \ + libperl \ + libpython \ + libslang \ + libunwind \ + libdw-dwarf-unwind \ + zlib + +# 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 +# mentioned in this list we need to refactor this ;-). +set_test_all_flags = $(eval $(set_test_all_flags_code)) +define set_test_all_flags_code + FEATURE_CHECK_CFLAGS-all += $(FEATURE_CHECK_CFLAGS-$(1)) + FEATURE_CHECK_LDFLAGS-all += $(FEATURE_CHECK_LDFLAGS-$(1)) +endef + +$(foreach feat,$(FEATURE_TESTS),$(call set_test_all_flags,$(feat))) + +# +# Special fast-path for the 'all features are available' case: +# +$(call feature_check,all,$(MSG)) + +# +# Just in case the build freshly failed, make sure we print the +# feature matrix: +# +ifeq ($(feature-all), 1) + # + # test-all.c passed - just set all the core feature flags to 1: + # + $(foreach feat,$(FEATURE_TESTS),$(call feature_set,$(feat))) +else + $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS)" LDFLAGS=$(LDFLAGS) -i -j -C config/feature-checks $(addsuffix .bin,$(FEATURE_TESTS)) >/dev/null 2>&1) + $(foreach feat,$(FEATURE_TESTS),$(call feature_check,$(feat))) +endif + +# +# Print the result of the feature test: +# +feature_print_status = $(eval $(feature_print_status_code)) $(info $(MSG)) + +define feature_print_status_code + ifeq ($(feature-$(1)), 1) + MSG = $(shell printf '...%30s: [ \033[32mon\033[m ]' $(1)) + else + MSG = $(shell printf '...%30s: [ \033[31mOFF\033[m ]' $(1)) + endif +endef + +feature_print_text = $(eval $(feature_print_text_code)) $(info $(MSG)) +define feature_print_text_code + MSG = $(shell printf '...%30s: %s' $(1) $(2)) +endef + +FEATURE_DUMP := $(foreach feat,$(FEATURE_DISPLAY),feature-$(feat)($(feature-$(feat)))) +FEATURE_DUMP_FILE := $(shell touch $(OUTPUT)FEATURE-DUMP; cat $(OUTPUT)FEATURE-DUMP) + +ifeq ($(dwarf-post-unwind),1) + FEATURE_DUMP += dwarf-post-unwind($(dwarf-post-unwind-text)) +endif + +# The $(feature_display) controls the default detection message +# output. It's set if: +# - detected features differes from stored features from +# last build (in FEATURE-DUMP file) +# - one of the $(FEATURE_DISPLAY) is not detected +# - VF is enabled + +ifneq ("$(FEATURE_DUMP)","$(FEATURE_DUMP_FILE)") + $(shell echo "$(FEATURE_DUMP)" > $(OUTPUT)FEATURE-DUMP) + feature_display := 1 +endif + +feature_display_check = $(eval $(feature_check_code)) +define feature_display_check_code + ifneq ($(feature-$(1)), 1) + feature_display := 1 + endif +endef + +$(foreach feat,$(FEATURE_DISPLAY),$(call feature_display_check,$(feat))) + +ifeq ($(VF),1) + feature_display := 1 + feature_verbose := 1 +endif + +ifeq ($(feature_display),1) + $(info ) + $(info Auto-detecting system features:) + $(foreach feat,$(FEATURE_DISPLAY),$(call feature_print_status,$(feat),)) + + ifeq ($(dwarf-post-unwind),1) + $(call feature_print_text,"DWARF post unwind library", $(dwarf-post-unwind-text)) + endif + + ifneq ($(feature_verbose),1) + $(info ) + endif +endif + +ifeq ($(feature_verbose),1) + TMP := $(filter-out $(FEATURE_DISPLAY),$(FEATURE_TESTS)) + $(foreach feat,$(TMP),$(call feature_print_status,$(feat),)) + $(info ) +endif From 970e87b33820205b31306dfb734771842874767c Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 1 Mar 2015 21:12:25 +0100 Subject: [PATCH 09/19] perf build: Make features checks directory configurable Putting feature checks directory into $feature_dir, so it's easy to configure when we move it to bools/build later. Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: David Ahern Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/n/tip-sq2nsds6uk93372iyxcqcf6q@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/config/Makefile.feature | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/perf/config/Makefile.feature b/tools/perf/config/Makefile.feature index 8c98bbce6031..ea83a92630c0 100644 --- a/tools/perf/config/Makefile.feature +++ b/tools/perf/config/Makefile.feature @@ -1,3 +1,5 @@ +feature_dir := $(srctree)/tools/perf/config/feature-checks + ifneq ($(OUTPUT),) OUTPUT_FEATURES = $(OUTPUT)config/feature-checks/ $(shell mkdir -p $(OUTPUT_FEATURES)) @@ -5,7 +7,7 @@ endif feature_check = $(eval $(feature_check_code)) define feature_check_code - feature-$(1) := $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS) $(FEATURE_CHECK_CFLAGS-$(1))" LDFLAGS="$(LDFLAGS) $(FEATURE_CHECK_LDFLAGS-$(1))" -C config/feature-checks test-$1.bin >/dev/null 2>/dev/null && echo 1 || echo 0) + feature-$(1) := $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS) $(FEATURE_CHECK_CFLAGS-$(1))" LDFLAGS="$(LDFLAGS) $(FEATURE_CHECK_LDFLAGS-$(1))" -C $(feature_dir) test-$1.bin >/dev/null 2>/dev/null && echo 1 || echo 0) endef feature_set = $(eval $(feature_set_code)) @@ -91,7 +93,7 @@ ifeq ($(feature-all), 1) # $(foreach feat,$(FEATURE_TESTS),$(call feature_set,$(feat))) else - $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS)" LDFLAGS=$(LDFLAGS) -i -j -C config/feature-checks $(addsuffix .bin,$(FEATURE_TESTS)) >/dev/null 2>&1) + $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS)" LDFLAGS=$(LDFLAGS) -i -j -C $(feature_dir) $(addsuffix .bin,$(FEATURE_TESTS)) >/dev/null 2>&1) $(foreach feat,$(FEATURE_TESTS),$(call feature_check,$(feat))) endif From e6c76d620379fd65fc0310aee1785ff7b1b10236 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 1 Mar 2015 21:19:44 +0100 Subject: [PATCH 10/19] perf build: Move feature checks code under tools/build Moving feature checks code under tools/build directory. Changing also $feature_dir to point to new feature directory location and perf Makefiles to include Makefile.feature from new location. Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: David Ahern Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/n/tip-3lamtb30dhf4wo99y1n8kxg0@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/{perf/config => build}/Makefile.feature | 4 ++-- .../{perf/config/feature-checks => build/feature}/.gitignore | 0 tools/{perf/config/feature-checks => build/feature}/Makefile | 0 .../{perf/config/feature-checks => build/feature}/test-all.c | 0 .../config/feature-checks => build/feature}/test-backtrace.c | 0 .../config/feature-checks => build/feature}/test-bionic.c | 0 .../config/feature-checks => build/feature}/test-compile.c | 0 .../feature-checks => build/feature}/test-cplus-demangle.c | 0 .../config/feature-checks => build/feature}/test-dwarf.c | 0 .../feature-checks => build/feature}/test-fortify-source.c | 0 .../config/feature-checks => build/feature}/test-glibc.c | 0 .../feature-checks => build/feature}/test-gtk2-infobar.c | 0 .../{perf/config/feature-checks => build/feature}/test-gtk2.c | 0 .../config/feature-checks => build/feature}/test-hello.c | 0 .../config/feature-checks => build/feature}/test-libaudit.c | 0 .../feature-checks => build/feature}/test-libbabeltrace.c | 0 .../config/feature-checks => build/feature}/test-libbfd.c | 0 .../feature}/test-libdw-dwarf-unwind.c | 0 .../feature-checks => build/feature}/test-libelf-getphdrnum.c | 0 .../feature-checks => build/feature}/test-libelf-mmap.c | 0 .../config/feature-checks => build/feature}/test-libelf.c | 0 .../config/feature-checks => build/feature}/test-libnuma.c | 0 .../config/feature-checks => build/feature}/test-libperl.c | 0 .../feature-checks => build/feature}/test-libpython-version.c | 0 .../config/feature-checks => build/feature}/test-libpython.c | 0 .../config/feature-checks => build/feature}/test-libslang.c | 0 .../feature}/test-libunwind-debug-frame.c | 0 .../config/feature-checks => build/feature}/test-libunwind.c | 0 .../feature}/test-pthread-attr-setaffinity-np.c | 0 .../feature}/test-stackprotector-all.c | 0 .../feature}/test-sync-compare-and-swap.c | 0 .../config/feature-checks => build/feature}/test-timerfd.c | 0 .../{perf/config/feature-checks => build/feature}/test-zlib.c | 0 tools/perf/Makefile.perf | 2 +- tools/perf/config/Makefile | 2 +- 35 files changed, 4 insertions(+), 4 deletions(-) rename tools/{perf/config => build}/Makefile.feature (97%) rename tools/{perf/config/feature-checks => build/feature}/.gitignore (100%) rename tools/{perf/config/feature-checks => build/feature}/Makefile (100%) rename tools/{perf/config/feature-checks => build/feature}/test-all.c (100%) rename tools/{perf/config/feature-checks => build/feature}/test-backtrace.c (100%) rename tools/{perf/config/feature-checks => build/feature}/test-bionic.c (100%) rename tools/{perf/config/feature-checks => build/feature}/test-compile.c (100%) rename tools/{perf/config/feature-checks => build/feature}/test-cplus-demangle.c (100%) rename tools/{perf/config/feature-checks => build/feature}/test-dwarf.c (100%) rename tools/{perf/config/feature-checks => build/feature}/test-fortify-source.c (100%) rename tools/{perf/config/feature-checks => build/feature}/test-glibc.c (100%) rename tools/{perf/config/feature-checks => build/feature}/test-gtk2-infobar.c (100%) rename tools/{perf/config/feature-checks => build/feature}/test-gtk2.c (100%) rename tools/{perf/config/feature-checks => build/feature}/test-hello.c (100%) rename tools/{perf/config/feature-checks => build/feature}/test-libaudit.c (100%) rename tools/{perf/config/feature-checks => build/feature}/test-libbabeltrace.c (100%) rename tools/{perf/config/feature-checks => build/feature}/test-libbfd.c (100%) rename tools/{perf/config/feature-checks => build/feature}/test-libdw-dwarf-unwind.c (100%) rename tools/{perf/config/feature-checks => build/feature}/test-libelf-getphdrnum.c (100%) rename tools/{perf/config/feature-checks => build/feature}/test-libelf-mmap.c (100%) rename tools/{perf/config/feature-checks => build/feature}/test-libelf.c (100%) rename tools/{perf/config/feature-checks => build/feature}/test-libnuma.c (100%) rename tools/{perf/config/feature-checks => build/feature}/test-libperl.c (100%) rename tools/{perf/config/feature-checks => build/feature}/test-libpython-version.c (100%) rename tools/{perf/config/feature-checks => build/feature}/test-libpython.c (100%) rename tools/{perf/config/feature-checks => build/feature}/test-libslang.c (100%) rename tools/{perf/config/feature-checks => build/feature}/test-libunwind-debug-frame.c (100%) rename tools/{perf/config/feature-checks => build/feature}/test-libunwind.c (100%) rename tools/{perf/config/feature-checks => build/feature}/test-pthread-attr-setaffinity-np.c (100%) rename tools/{perf/config/feature-checks => build/feature}/test-stackprotector-all.c (100%) rename tools/{perf/config/feature-checks => build/feature}/test-sync-compare-and-swap.c (100%) rename tools/{perf/config/feature-checks => build/feature}/test-timerfd.c (100%) rename tools/{perf/config/feature-checks => build/feature}/test-zlib.c (100%) diff --git a/tools/perf/config/Makefile.feature b/tools/build/Makefile.feature similarity index 97% rename from tools/perf/config/Makefile.feature rename to tools/build/Makefile.feature index ea83a92630c0..c6f44894d4a1 100644 --- a/tools/perf/config/Makefile.feature +++ b/tools/build/Makefile.feature @@ -1,7 +1,7 @@ -feature_dir := $(srctree)/tools/perf/config/feature-checks +feature_dir := $(srctree)/tools/build/feature ifneq ($(OUTPUT),) - OUTPUT_FEATURES = $(OUTPUT)config/feature-checks/ + OUTPUT_FEATURES = $(OUTPUT)feature/ $(shell mkdir -p $(OUTPUT_FEATURES)) endif diff --git a/tools/perf/config/feature-checks/.gitignore b/tools/build/feature/.gitignore similarity index 100% rename from tools/perf/config/feature-checks/.gitignore rename to tools/build/feature/.gitignore diff --git a/tools/perf/config/feature-checks/Makefile b/tools/build/feature/Makefile similarity index 100% rename from tools/perf/config/feature-checks/Makefile rename to tools/build/feature/Makefile diff --git a/tools/perf/config/feature-checks/test-all.c b/tools/build/feature/test-all.c similarity index 100% rename from tools/perf/config/feature-checks/test-all.c rename to tools/build/feature/test-all.c diff --git a/tools/perf/config/feature-checks/test-backtrace.c b/tools/build/feature/test-backtrace.c similarity index 100% rename from tools/perf/config/feature-checks/test-backtrace.c rename to tools/build/feature/test-backtrace.c diff --git a/tools/perf/config/feature-checks/test-bionic.c b/tools/build/feature/test-bionic.c similarity index 100% rename from tools/perf/config/feature-checks/test-bionic.c rename to tools/build/feature/test-bionic.c diff --git a/tools/perf/config/feature-checks/test-compile.c b/tools/build/feature/test-compile.c similarity index 100% rename from tools/perf/config/feature-checks/test-compile.c rename to tools/build/feature/test-compile.c diff --git a/tools/perf/config/feature-checks/test-cplus-demangle.c b/tools/build/feature/test-cplus-demangle.c similarity index 100% rename from tools/perf/config/feature-checks/test-cplus-demangle.c rename to tools/build/feature/test-cplus-demangle.c diff --git a/tools/perf/config/feature-checks/test-dwarf.c b/tools/build/feature/test-dwarf.c similarity index 100% rename from tools/perf/config/feature-checks/test-dwarf.c rename to tools/build/feature/test-dwarf.c diff --git a/tools/perf/config/feature-checks/test-fortify-source.c b/tools/build/feature/test-fortify-source.c similarity index 100% rename from tools/perf/config/feature-checks/test-fortify-source.c rename to tools/build/feature/test-fortify-source.c diff --git a/tools/perf/config/feature-checks/test-glibc.c b/tools/build/feature/test-glibc.c similarity index 100% rename from tools/perf/config/feature-checks/test-glibc.c rename to tools/build/feature/test-glibc.c diff --git a/tools/perf/config/feature-checks/test-gtk2-infobar.c b/tools/build/feature/test-gtk2-infobar.c similarity index 100% rename from tools/perf/config/feature-checks/test-gtk2-infobar.c rename to tools/build/feature/test-gtk2-infobar.c diff --git a/tools/perf/config/feature-checks/test-gtk2.c b/tools/build/feature/test-gtk2.c similarity index 100% rename from tools/perf/config/feature-checks/test-gtk2.c rename to tools/build/feature/test-gtk2.c diff --git a/tools/perf/config/feature-checks/test-hello.c b/tools/build/feature/test-hello.c similarity index 100% rename from tools/perf/config/feature-checks/test-hello.c rename to tools/build/feature/test-hello.c diff --git a/tools/perf/config/feature-checks/test-libaudit.c b/tools/build/feature/test-libaudit.c similarity index 100% rename from tools/perf/config/feature-checks/test-libaudit.c rename to tools/build/feature/test-libaudit.c diff --git a/tools/perf/config/feature-checks/test-libbabeltrace.c b/tools/build/feature/test-libbabeltrace.c similarity index 100% rename from tools/perf/config/feature-checks/test-libbabeltrace.c rename to tools/build/feature/test-libbabeltrace.c diff --git a/tools/perf/config/feature-checks/test-libbfd.c b/tools/build/feature/test-libbfd.c similarity index 100% rename from tools/perf/config/feature-checks/test-libbfd.c rename to tools/build/feature/test-libbfd.c diff --git a/tools/perf/config/feature-checks/test-libdw-dwarf-unwind.c b/tools/build/feature/test-libdw-dwarf-unwind.c similarity index 100% rename from tools/perf/config/feature-checks/test-libdw-dwarf-unwind.c rename to tools/build/feature/test-libdw-dwarf-unwind.c diff --git a/tools/perf/config/feature-checks/test-libelf-getphdrnum.c b/tools/build/feature/test-libelf-getphdrnum.c similarity index 100% rename from tools/perf/config/feature-checks/test-libelf-getphdrnum.c rename to tools/build/feature/test-libelf-getphdrnum.c diff --git a/tools/perf/config/feature-checks/test-libelf-mmap.c b/tools/build/feature/test-libelf-mmap.c similarity index 100% rename from tools/perf/config/feature-checks/test-libelf-mmap.c rename to tools/build/feature/test-libelf-mmap.c diff --git a/tools/perf/config/feature-checks/test-libelf.c b/tools/build/feature/test-libelf.c similarity index 100% rename from tools/perf/config/feature-checks/test-libelf.c rename to tools/build/feature/test-libelf.c diff --git a/tools/perf/config/feature-checks/test-libnuma.c b/tools/build/feature/test-libnuma.c similarity index 100% rename from tools/perf/config/feature-checks/test-libnuma.c rename to tools/build/feature/test-libnuma.c diff --git a/tools/perf/config/feature-checks/test-libperl.c b/tools/build/feature/test-libperl.c similarity index 100% rename from tools/perf/config/feature-checks/test-libperl.c rename to tools/build/feature/test-libperl.c diff --git a/tools/perf/config/feature-checks/test-libpython-version.c b/tools/build/feature/test-libpython-version.c similarity index 100% rename from tools/perf/config/feature-checks/test-libpython-version.c rename to tools/build/feature/test-libpython-version.c diff --git a/tools/perf/config/feature-checks/test-libpython.c b/tools/build/feature/test-libpython.c similarity index 100% rename from tools/perf/config/feature-checks/test-libpython.c rename to tools/build/feature/test-libpython.c diff --git a/tools/perf/config/feature-checks/test-libslang.c b/tools/build/feature/test-libslang.c similarity index 100% rename from tools/perf/config/feature-checks/test-libslang.c rename to tools/build/feature/test-libslang.c diff --git a/tools/perf/config/feature-checks/test-libunwind-debug-frame.c b/tools/build/feature/test-libunwind-debug-frame.c similarity index 100% rename from tools/perf/config/feature-checks/test-libunwind-debug-frame.c rename to tools/build/feature/test-libunwind-debug-frame.c diff --git a/tools/perf/config/feature-checks/test-libunwind.c b/tools/build/feature/test-libunwind.c similarity index 100% rename from tools/perf/config/feature-checks/test-libunwind.c rename to tools/build/feature/test-libunwind.c diff --git a/tools/perf/config/feature-checks/test-pthread-attr-setaffinity-np.c b/tools/build/feature/test-pthread-attr-setaffinity-np.c similarity index 100% rename from tools/perf/config/feature-checks/test-pthread-attr-setaffinity-np.c rename to tools/build/feature/test-pthread-attr-setaffinity-np.c diff --git a/tools/perf/config/feature-checks/test-stackprotector-all.c b/tools/build/feature/test-stackprotector-all.c similarity index 100% rename from tools/perf/config/feature-checks/test-stackprotector-all.c rename to tools/build/feature/test-stackprotector-all.c diff --git a/tools/perf/config/feature-checks/test-sync-compare-and-swap.c b/tools/build/feature/test-sync-compare-and-swap.c similarity index 100% rename from tools/perf/config/feature-checks/test-sync-compare-and-swap.c rename to tools/build/feature/test-sync-compare-and-swap.c diff --git a/tools/perf/config/feature-checks/test-timerfd.c b/tools/build/feature/test-timerfd.c similarity index 100% rename from tools/perf/config/feature-checks/test-timerfd.c rename to tools/build/feature/test-timerfd.c diff --git a/tools/perf/config/feature-checks/test-zlib.c b/tools/build/feature/test-zlib.c similarity index 100% rename from tools/perf/config/feature-checks/test-zlib.c rename to tools/build/feature/test-zlib.c diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index e323eab10694..d5b9e0dae334 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -521,7 +521,7 @@ $(INSTALL_DOC_TARGETS): # config-clean: $(call QUIET_CLEAN, config) - $(Q)$(MAKE) -C config/feature-checks clean >/dev/null + $(Q)$(MAKE) -C $(srctree)/tools/build/feature/ clean >/dev/null clean: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean config-clean $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(LANG_BINDINGS) diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile index 01278429965a..6d1918a6b83b 100644 --- a/tools/perf/config/Makefile +++ b/tools/perf/config/Makefile @@ -176,7 +176,7 @@ LDFLAGS += -Wl,-z,noexecstack EXTLIBS = -lpthread -lrt -lm -ldl -include $(src-perf)/config/Makefile.feature +include $(srctree)/tools/build/Makefile.feature ifeq ($(feature-stackprotector-all), 1) CFLAGS += -fstack-protector-all From f208bd8df08d0659ecd9e09e992c79aab26cddfa Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 20 Mar 2015 17:46:53 -0300 Subject: [PATCH 11/19] perf trace: Handle legacy syscalls tracepoints Currently the code skips the first field with the expectation that it is 'nr'. But older kernels do not have the 'nr' field: field:int nr; offset:8; size:4; signed:1; Change perf-trace to drop the field if it exists after parsing the format file. This fixes the off-by-one problem with older kernels (e.g., RHEL6). e.g, perf-trace shows this for write: 1.515 ( 0.006 ms): dd/4245 write(buf: 2, count: 140733837536224 ) = 26 where 2 is really the fd, the huge number is really the buf address, etc. With this patch you get the more appropriate: 1.813 ( 0.003 ms): dd/6330 write(fd: 2, buf: 0x7fff22fc81f0, count: 25) = 25 Based-on-a-patch-by: David Ahern Acked-by: David Ahern Cc: Adrian Hunter Cc: Borislav Petkov Cc: Don Zickus Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Namhyung Kim Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-gvpdave4u2yq2jnzbcdznpvf@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-trace.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 6af6bcec930e..001c6ae9a1b1 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -1135,6 +1135,8 @@ static struct syscall_fmt *syscall_fmt__find(const char *name) struct syscall { struct event_format *tp_format; + int nr_args; + struct format_field *args; const char *name; bool filtered; bool is_exit; @@ -1442,14 +1444,14 @@ static int syscall__set_arg_fmts(struct syscall *sc) struct format_field *field; int idx = 0; - sc->arg_scnprintf = calloc(sc->tp_format->format.nr_fields - 1, sizeof(void *)); + sc->arg_scnprintf = calloc(sc->nr_args, sizeof(void *)); if (sc->arg_scnprintf == NULL) return -1; if (sc->fmt) sc->arg_parm = sc->fmt->arg_parm; - for (field = sc->tp_format->format.fields->next; field; field = field->next) { + for (field = sc->args; field; field = field->next) { if (sc->fmt && sc->fmt->arg_scnprintf[idx]) sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx]; else if (field->flags & FIELD_IS_POINTER) @@ -1515,6 +1517,14 @@ static int trace__read_syscall_info(struct trace *trace, int id) if (sc->tp_format == NULL) return -1; + sc->args = sc->tp_format->format.fields; + sc->nr_args = sc->tp_format->format.nr_fields; + /* drop nr field - not relevant here; does not exist on older kernels */ + if (sc->args && strcmp(sc->args->name, "nr") == 0) { + sc->args = sc->args->next; + --sc->nr_args; + } + sc->is_exit = !strcmp(name, "exit_group") || !strcmp(name, "exit"); return syscall__set_arg_fmts(sc); @@ -1537,7 +1547,7 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size, unsigned char *p; unsigned long val; - if (sc->tp_format != NULL) { + if (sc->args != NULL) { struct format_field *field; u8 bit = 1; struct syscall_arg arg = { @@ -1547,7 +1557,7 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size, .thread = thread, }; - for (field = sc->tp_format->format.fields->next; field; + for (field = sc->args; field; field = field->next, ++arg.idx, bit <<= 1) { if (arg.mask & bit) continue; From 70e972788888315851a5c1b4982efbcafcd03b5b Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 19 Mar 2015 16:07:21 -0300 Subject: [PATCH 12/19] perf hists browser: Indicate which callchain entries are annotated Now that we can annotate entries in a callchain, show which ones have an associated symbol and samples, by adding a right arrow just before the symbol name when in verbose mode. To toggle verbose mode press 'V'. Cc: Adrian Hunter Cc: Borislav Petkov Cc: David Ahern Cc: Don Zickus Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-d2rf1p3h5gdp7hdl2gf2bozl@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browsers/hists.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index cd7350aeb8e7..995b7a8596b1 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -511,6 +511,7 @@ static void hist_browser__show_callchain_entry(struct hist_browser *browser, { int color, width; char folded_sign = callchain_list__folded(chain); + bool show_annotated = browser->show_dso && chain->ms.sym && symbol__annotation(chain->ms.sym)->src; color = HE_COLORSET_NORMAL; width = browser->b.width - (offset + 2); @@ -523,7 +524,8 @@ static void hist_browser__show_callchain_entry(struct hist_browser *browser, ui_browser__set_color(&browser->b, color); hist_browser__gotorc(browser, row, 0); slsmg_write_nstring(" ", offset); - slsmg_printf("%c ", folded_sign); + slsmg_printf("%c", folded_sign); + ui_browser__write_graph(&browser->b, show_annotated ? SLSMG_RARROW_CHAR : ' '); slsmg_write_nstring(str, width); } From 00ae1127a03d20f5ef89f3c1fe7d4720270fc2a5 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Thu, 19 Mar 2015 12:36:21 -0600 Subject: [PATCH 13/19] tools lib traceevent: Add destructor for format_field Move the calls that frees the resources allocated for a struct format_field to a separate routine. Signed-off-by: David Ahern Acked-by: Steven Rostedt Link: http://lkml.kernel.org/r/1426790181-19118-1-git-send-email-dsahern@gmail.com [ Split this part from a larger patch, added pevent_ prefix as requested by Steven ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse.c | 11 ++++++++--- tools/lib/traceevent/event-parse.h | 1 + 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c index afe20ed9fac8..d7c37a7d9255 100644 --- a/tools/lib/traceevent/event-parse.c +++ b/tools/lib/traceevent/event-parse.c @@ -6228,15 +6228,20 @@ void pevent_ref(struct pevent *pevent) pevent->ref_count++; } +void pevent_free_format_field(struct format_field *field) +{ + free(field->type); + free(field->name); + free(field); +} + static void free_format_fields(struct format_field *field) { struct format_field *next; while (field) { next = field->next; - free(field->type); - free(field->name); - free(field); + pevent_free_format_field(field); field = next; } } diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index 5b4efc062320..6abda54d76f2 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -619,6 +619,7 @@ enum pevent_errno pevent_parse_format(struct pevent *pevent, const char *buf, unsigned long size, const char *sys); void pevent_free_format(struct event_format *event); +void pevent_free_format_field(struct format_field *field); void *pevent_get_field_raw(struct trace_seq *s, struct event_format *event, const char *name, struct pevent_record *record, From 6c6f0f6164fbf7a1667378496ee36ae48c18a9d6 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Wed, 4 Mar 2015 11:35:47 +0100 Subject: [PATCH 14/19] tools build: Add feature check for lzma library Will be used to decompress 'xz' objects. The check detects the liblzma.so devel library normally delivered by xz package. Signed-off-by: Jiri Olsa Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Arnaldo Carvalho de Melo Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian --- tools/build/Makefile.feature | 6 ++++-- tools/build/feature/Makefile | 8 ++++++-- tools/build/feature/test-all.c | 5 +++++ tools/build/feature/test-lzma.c | 10 ++++++++++ 4 files changed, 25 insertions(+), 4 deletions(-) create mode 100644 tools/build/feature/test-lzma.c diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature index c6f44894d4a1..3a0b0ca2a28c 100644 --- a/tools/build/Makefile.feature +++ b/tools/build/Makefile.feature @@ -50,7 +50,8 @@ FEATURE_TESTS = \ stackprotector-all \ timerfd \ libdw-dwarf-unwind \ - zlib + zlib \ + lzma FEATURE_DISPLAY = \ dwarf \ @@ -65,7 +66,8 @@ FEATURE_DISPLAY = \ libslang \ libunwind \ libdw-dwarf-unwind \ - zlib + zlib \ + lzma # 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 0d694a94cda2..463ed8f2a267 100644 --- a/tools/build/feature/Makefile +++ b/tools/build/feature/Makefile @@ -32,7 +32,8 @@ FILES= \ test-libbabeltrace.bin \ test-compile-32.bin \ test-compile-x32.bin \ - test-zlib.bin + test-zlib.bin \ + test-lzma.bin CC := $(CROSS_COMPILE)gcc -MD PKG_CONFIG := $(CROSS_COMPILE)pkg-config @@ -45,7 +46,7 @@ __BUILD = $(CC) $(CFLAGS) -Wall -Werror -o $(OUTPUT)$@ $(patsubst %.bin,%.c,$@) ############################### test-all.bin: - $(BUILD) -fstack-protector-all -O2 -D_FORTIFY_SOURCE=2 -ldw -lelf -lnuma -lelf -laudit -I/usr/include/slang -lslang $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null) $(FLAGS_PERL_EMBED) $(FLAGS_PYTHON_EMBED) -DPACKAGE='"perf"' -lbfd -ldl -lz + $(BUILD) -fstack-protector-all -O2 -D_FORTIFY_SOURCE=2 -ldw -lelf -lnuma -lelf -laudit -I/usr/include/slang -lslang $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null) $(FLAGS_PERL_EMBED) $(FLAGS_PYTHON_EMBED) -DPACKAGE='"perf"' -lbfd -ldl -lz -llzma test-hello.bin: $(BUILD) @@ -152,6 +153,9 @@ test-compile-x32.bin: test-zlib.bin: $(BUILD) -lz +test-lzma.bin: + $(BUILD) -llzma + -include *.d ############################### diff --git a/tools/build/feature/test-all.c b/tools/build/feature/test-all.c index a61c20456705..84689a67814a 100644 --- a/tools/build/feature/test-all.c +++ b/tools/build/feature/test-all.c @@ -113,6 +113,10 @@ #undef main #endif +#define main main_test_lzma +# include "test-lzma.c" +#undef main + int main(int argc, char *argv[]) { main_test_libpython(); @@ -138,6 +142,7 @@ int main(int argc, char *argv[]) main_test_sync_compare_and_swap(argc, argv); main_test_zlib(); main_test_pthread_attr_setaffinity_np(); + main_test_lzma(); return 0; } diff --git a/tools/build/feature/test-lzma.c b/tools/build/feature/test-lzma.c new file mode 100644 index 000000000000..95adc8ced3dd --- /dev/null +++ b/tools/build/feature/test-lzma.c @@ -0,0 +1,10 @@ +#include + +int main(void) +{ + lzma_stream strm = LZMA_STREAM_INIT; + int ret; + + ret = lzma_stream_decoder(&strm, UINT64_MAX, LZMA_CONCATENATED); + return ret ? -1 : 0; +} From 80a32e5b498a7547073e5e4b2b804edc7219979d Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 29 Jan 2015 13:29:39 +0100 Subject: [PATCH 15/19] perf tools: Add lzma decompression support for kernel module In short, Fedora compresses kernel modules now (since version 21) with lzma compression. Adding lzma decompress support into the dso.c:compressions array introduced by Namhyung earlier. Signed-off-by: Jiri Olsa Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-2glp65kdtbrk0gblmirsjsnt@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile.perf | 2 + tools/perf/config/Makefile | 11 +++++ tools/perf/util/Build | 1 + tools/perf/util/dso.c | 3 ++ tools/perf/util/lzma.c | 95 ++++++++++++++++++++++++++++++++++++++ tools/perf/util/util.h | 4 ++ 6 files changed, 116 insertions(+) create mode 100644 tools/perf/util/lzma.c diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index d5b9e0dae334..e9925e6ad1d0 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -71,6 +71,8 @@ include config/utilities.mak # # Define NO_LIBBABELTRACE if you do not want libbabeltrace support # for CTF data format. +# +# Define NO_LZMA if you do not want to support compressed (xz) kernel modules ifeq ($(srctree),) srctree := $(patsubst %/,%,$(dir $(shell pwd))) diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile index 6d1918a6b83b..cd121dfc4de9 100644 --- a/tools/perf/config/Makefile +++ b/tools/perf/config/Makefile @@ -541,6 +541,17 @@ ifndef NO_ZLIB endif endif +ifndef NO_LZMA + ifeq ($(feature-lzma), 1) + CFLAGS += -DHAVE_LZMA_SUPPORT + EXTLIBS += -llzma + $(call detected,CONFIG_LZMA) + else + msg := $(warning No liblzma found, disables xz kernel module decompression, please install xz-devel/liblzma-dev); + NO_LZMA := 1 + endif +endif + ifndef NO_BACKTRACE ifeq ($(feature-backtrace), 1) CFLAGS += -DHAVE_BACKTRACE_SUPPORT diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 972a6e0da7ad..797490a40075 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -94,6 +94,7 @@ libperf-y += scripting-engines/ libperf-$(CONFIG_PERF_REGS) += perf_regs.o libperf-$(CONFIG_ZLIB) += zlib.o +libperf-$(CONFIG_LZMA) += lzma.o CFLAGS_config.o += -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))" CFLAGS_exec_cmd.o += -DPERF_EXEC_PATH="BUILD_STR($(perfexecdir_SQ))" -DPREFIX="BUILD_STR($(prefix_SQ))" diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index 814554d1b857..be368414036c 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -147,6 +147,9 @@ static const struct { } compressions[] = { #ifdef HAVE_ZLIB_SUPPORT { "gz", gzip_decompress_to_file }, +#endif +#ifdef HAVE_LZMA_SUPPORT + { "xz", lzma_decompress_to_file }, #endif { NULL, NULL }, }; diff --git a/tools/perf/util/lzma.c b/tools/perf/util/lzma.c new file mode 100644 index 000000000000..95a1acb61245 --- /dev/null +++ b/tools/perf/util/lzma.c @@ -0,0 +1,95 @@ +#include +#include +#include +#include "util.h" +#include "debug.h" + +#define BUFSIZE 8192 + +static const char *lzma_strerror(lzma_ret ret) +{ + switch ((int) ret) { + case LZMA_MEM_ERROR: + return "Memory allocation failed"; + case LZMA_OPTIONS_ERROR: + return "Unsupported decompressor flags"; + case LZMA_FORMAT_ERROR: + return "The input is not in the .xz format"; + case LZMA_DATA_ERROR: + return "Compressed file is corrupt"; + case LZMA_BUF_ERROR: + return "Compressed file is truncated or otherwise corrupt"; + default: + return "Unknown error, possibly a bug"; + } +} + +int lzma_decompress_to_file(const char *input, int output_fd) +{ + lzma_action action = LZMA_RUN; + lzma_stream strm = LZMA_STREAM_INIT; + lzma_ret ret; + + u8 buf_in[BUFSIZE]; + u8 buf_out[BUFSIZE]; + FILE *infile; + + infile = fopen(input, "rb"); + if (!infile) { + pr_err("lzma: fopen failed on %s: '%s'\n", + input, strerror(errno)); + return -1; + } + + ret = lzma_stream_decoder(&strm, UINT64_MAX, LZMA_CONCATENATED); + if (ret != LZMA_OK) { + pr_err("lzma: lzma_stream_decoder failed %s (%d)\n", + lzma_strerror(ret), ret); + return -1; + } + + strm.next_in = NULL; + strm.avail_in = 0; + strm.next_out = buf_out; + strm.avail_out = sizeof(buf_out); + + while (1) { + if (strm.avail_in == 0 && !feof(infile)) { + strm.next_in = buf_in; + strm.avail_in = fread(buf_in, 1, sizeof(buf_in), infile); + + if (ferror(infile)) { + pr_err("lzma: read error: %s\n", strerror(errno)); + return -1; + } + + if (feof(infile)) + action = LZMA_FINISH; + } + + ret = lzma_code(&strm, action); + + if (strm.avail_out == 0 || ret == LZMA_STREAM_END) { + ssize_t write_size = sizeof(buf_out) - strm.avail_out; + + if (writen(output_fd, buf_out, write_size) != write_size) { + pr_err("lzma: write error: %s\n", strerror(errno)); + return -1; + } + + strm.next_out = buf_out; + strm.avail_out = sizeof(buf_out); + } + + if (ret != LZMA_OK) { + if (ret == LZMA_STREAM_END) + return 0; + + pr_err("lzma: failed %s\n", lzma_strerror(ret)); + return -1; + } + } + + fclose(infile); + return 0; +} diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index fbd598afc606..1ff23e04ad27 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h @@ -329,4 +329,8 @@ bool find_process(const char *name); int gzip_decompress_to_file(const char *input, int output_fd); #endif +#ifdef HAVE_LZMA_SUPPORT +int lzma_decompress_to_file(const char *input, int output_fd); +#endif + #endif /* GIT_COMPAT_UTIL_H */ From 3c8a67f50a1e68b912d1d74db6b455cac54ec4b4 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 5 Feb 2015 15:40:25 +0100 Subject: [PATCH 16/19] perf tools: Add kmod_path__parse function Provides united way of parsing kernel module path into several components. The new kmod_path__parse function and few defines: int __kmod_path__parse(struct kmod_path *m, const char *path, bool alloc_name, bool alloc_ext); #define kmod_path__parse(__m, __p) __kmod_path__parse(__m, __p, false, false) #define kmod_path__parse_name(__m, __p) __kmod_path__parse(__m, __p, true , false) #define kmod_path__parse_ext(__m, __p) __kmod_path__parse(__m, __p, false, true) parse kernel module @path and updates @m argument like: @comp - true if @path contains supported compression suffix, false otherwise @kmod - true if @path contains '.ko' suffix in right position, false otherwise @name - if (@alloc_name && @kmod) is true, it contains strdup-ed base name of the kernel module without suffixes, otherwise strudup-ed base name of @path @ext - if (@alloc_ext && @comp) is true, it contains strdup-ed string the compression suffix It returns 0 if there's no strdup error, -ENOMEM otherwise. Signed-off-by: Jiri Olsa Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-9t6eqg8j610r94l743hkntiv@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/Build | 1 + tools/perf/tests/builtin-test.c | 4 ++ tools/perf/tests/kmod-path.c | 73 +++++++++++++++++++++++++++++++++ tools/perf/tests/tests.h | 1 + tools/perf/util/dso.c | 66 +++++++++++++++++++++++++++++ tools/perf/util/dso.h | 14 +++++++ 6 files changed, 159 insertions(+) create mode 100644 tools/perf/tests/kmod-path.c diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build index 2de01a4b4084..6a8801b32017 100644 --- a/tools/perf/tests/Build +++ b/tools/perf/tests/Build @@ -30,6 +30,7 @@ perf-y += keep-tracking.o perf-y += code-reading.o perf-y += sample-parsing.o perf-y += parse-no-sample-id-all.o +perf-y += kmod-path.o perf-$(CONFIG_X86) += perf-time-to-tsc.o diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index ed8e05c6839a..4f4098167112 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -166,6 +166,10 @@ static struct test { .desc = "Add fd to a fdarray, making it autogrow", .func = test__fdarray__add, }, + { + .desc = "Test kmod_path__parse function", + .func = test__kmod_path__parse, + }, { .func = NULL, }, diff --git a/tools/perf/tests/kmod-path.c b/tools/perf/tests/kmod-path.c new file mode 100644 index 000000000000..e8d7cbb9320c --- /dev/null +++ b/tools/perf/tests/kmod-path.c @@ -0,0 +1,73 @@ +#include +#include "tests.h" +#include "dso.h" +#include "debug.h" + +static int test(const char *path, bool alloc_name, bool alloc_ext, + bool kmod, bool comp, const char *name, const char *ext) +{ + struct kmod_path m; + + memset(&m, 0x0, sizeof(m)); + + TEST_ASSERT_VAL("kmod_path__parse", + !__kmod_path__parse(&m, path, alloc_name, alloc_ext)); + + pr_debug("%s - alloc name %d, alloc ext %d, kmod %d, comp %d, name '%s', ext '%s'\n", + path, alloc_name, alloc_ext, m.kmod, m.comp, m.name, m.ext); + + TEST_ASSERT_VAL("wrong kmod", m.kmod == kmod); + TEST_ASSERT_VAL("wrong comp", m.comp == comp); + + if (ext) + TEST_ASSERT_VAL("wrong ext", m.ext && !strcmp(ext, m.ext)); + else + TEST_ASSERT_VAL("wrong ext", !m.ext); + + if (name) + TEST_ASSERT_VAL("wrong name", m.name && !strcmp(name, m.name)); + else + TEST_ASSERT_VAL("wrong name", !m.name); + + free(m.name); + free(m.ext); + return 0; +} + +#define T(path, an, ae, k, c, n, e) \ + TEST_ASSERT_VAL("failed", !test(path, an, ae, k, c, n, e)) + +int test__kmod_path__parse(void) +{ + /* path alloc_name alloc_ext kmod comp name ext */ + T("/xxxx/xxxx/x-x.ko", true , true , true, false, "[x_x]", NULL); + T("/xxxx/xxxx/x-x.ko", false , true , true, false, NULL , NULL); + T("/xxxx/xxxx/x-x.ko", true , false , true, false, "[x_x]", NULL); + T("/xxxx/xxxx/x-x.ko", false , false , true, false, NULL , NULL); + + /* path alloc_name alloc_ext kmod comp name ext */ + T("/xxxx/xxxx/x.ko.gz", true , true , true, true, "[x]", "gz"); + T("/xxxx/xxxx/x.ko.gz", false , true , true, true, NULL , "gz"); + T("/xxxx/xxxx/x.ko.gz", true , false , true, true, "[x]", NULL); + T("/xxxx/xxxx/x.ko.gz", false , false , true, true, NULL , NULL); + + /* path alloc_name alloc_ext kmod comp name ext */ + T("/xxxx/xxxx/x.gz", true , true , false, true, "x.gz" ,"gz"); + T("/xxxx/xxxx/x.gz", false , true , false, true, NULL ,"gz"); + T("/xxxx/xxxx/x.gz", true , false , false, true, "x.gz" , NULL); + T("/xxxx/xxxx/x.gz", false , false , false, true, NULL , NULL); + + /* path alloc_name alloc_ext kmod comp name ext */ + T("x.gz", true , true , false, true, "x.gz", "gz"); + T("x.gz", false , true , false, true, NULL , "gz"); + T("x.gz", true , false , false, true, "x.gz", NULL); + T("x.gz", false , false , false, true, NULL , NULL); + + /* path alloc_name alloc_ext kmod comp name ext */ + T("x.ko.gz", true , true , true, true, "[x]", "gz"); + T("x.ko.gz", false , true , true, true, NULL , "gz"); + T("x.ko.gz", true , false , true, true, "[x]", NULL); + T("x.ko.gz", false , false , true, true, NULL , NULL); + + return 0; +} diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index 00e776a87a9c..52758a33f64c 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h @@ -51,6 +51,7 @@ int test__hists_cumulate(void); int test__switch_tracking(void); int test__fdarray__filter(void); int test__fdarray__add(void); +int test__kmod_path__parse(void); #if defined(__x86_64__) || defined(__i386__) || defined(__arm__) #ifdef HAVE_DWARF_UNWIND_SUPPORT diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index be368414036c..3e6863feb066 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -211,6 +211,72 @@ bool dso__needs_decompress(struct dso *dso) dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE_COMP; } +/* + * Parses kernel module specified in @path and updates + * @m argument like: + * + * @comp - true if @path contains supported compression suffix, + * false otherwise + * @kmod - true if @path contains '.ko' suffix in right position, + * false otherwise + * @name - if (@alloc_name && @kmod) is true, it contains strdup-ed base name + * of the kernel module without suffixes, otherwise strudup-ed + * base name of @path + * @ext - if (@alloc_ext && @comp) is true, it contains strdup-ed string + * the compression suffix + * + * Returns 0 if there's no strdup error, -ENOMEM otherwise. + */ +int __kmod_path__parse(struct kmod_path *m, const char *path, + bool alloc_name, bool alloc_ext) +{ + const char *name = strrchr(path, '/'); + const char *ext = strrchr(path, '.'); + + memset(m, 0x0, sizeof(*m)); + name = name ? name + 1 : path; + + /* No extension, just return name. */ + if (ext == NULL) { + if (alloc_name) { + m->name = strdup(name); + return m->name ? 0 : -ENOMEM; + } + return 0; + } + + if (is_supported_compression(ext + 1)) { + m->comp = true; + ext -= 3; + } + + /* Check .ko extension only if there's enough name left. */ + if (ext > name) + m->kmod = !strncmp(ext, ".ko", 3); + + if (alloc_name) { + if (m->kmod) { + if (asprintf(&m->name, "[%.*s]", (int) (ext - name), name) == -1) + return -ENOMEM; + } else { + if (asprintf(&m->name, "%s", name) == -1) + return -ENOMEM; + } + + strxfrchar(m->name, '-', '_'); + } + + if (alloc_ext && m->comp) { + m->ext = strdup(ext + 4); + if (!m->ext) { + free((void *) m->name); + return -ENOMEM; + } + } + + return 0; +} + /* * Global list of open DSOs and the counter. */ diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h index 408c65f1a757..384cd2918e8f 100644 --- a/tools/perf/util/dso.h +++ b/tools/perf/util/dso.h @@ -195,6 +195,20 @@ bool is_kernel_module(const char *pathname, bool *compressed); bool decompress_to_file(const char *ext, const char *filename, int output_fd); bool dso__needs_decompress(struct dso *dso); +struct kmod_path { + char *name; + char *ext; + bool comp; + bool kmod; +}; + +int __kmod_path__parse(struct kmod_path *m, const char *path, + bool alloc_name, bool alloc_ext); + +#define kmod_path__parse(__m, __p) __kmod_path__parse(__m, __p, false, false) +#define kmod_path__parse_name(__m, __p) __kmod_path__parse(__m, __p, true , false) +#define kmod_path__parse_ext(__m, __p) __kmod_path__parse(__m, __p, false, true) + /* * The dso__data_* external interface provides following functions: * dso__data_fd From 701d8d7f861ec36f3bc60d1ddb185cceb7919c79 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 12 Feb 2015 22:06:09 +0100 Subject: [PATCH 17/19] perf tools: Add dsos__addnew function Separate the creation of new dso object and its addition to the dsos list. It will be used in following patch. Signed-off-by: Jiri Olsa Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-8j43jod97fdt5dwdsushwwae@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/dso.c | 21 ++++++++++++--------- tools/perf/util/dso.h | 1 + 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index 3e6863feb066..7a7c54b42b41 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -1071,19 +1071,22 @@ struct dso *dsos__find(const struct dsos *dsos, const char *name, return dso__find_by_longname(&dsos->root, name); } +struct dso *dsos__addnew(struct dsos *dsos, const char *name) +{ + struct dso *dso = dso__new(name); + + if (dso != NULL) { + dsos__add(dsos, dso); + dso__set_basename(dso); + } + return dso; +} + struct dso *__dsos__findnew(struct dsos *dsos, const char *name) { struct dso *dso = dsos__find(dsos, name, false); - if (!dso) { - dso = dso__new(name); - if (dso != NULL) { - dsos__add(dsos, dso); - dso__set_basename(dso); - } - } - - return dso; + return dso ? dso : dsos__addnew(dsos, name); } size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp, diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h index 384cd2918e8f..3c81d8378bc7 100644 --- a/tools/perf/util/dso.h +++ b/tools/perf/util/dso.h @@ -264,6 +264,7 @@ struct dso *dso__kernel_findnew(struct machine *machine, const char *name, const char *short_name, int dso_type); void dsos__add(struct dsos *dsos, struct dso *dso); +struct dso *dsos__addnew(struct dsos *dsos, const char *name); struct dso *dsos__find(const struct dsos *dsos, const char *name, bool cmp_short); struct dso *__dsos__findnew(struct dsos *dsos, const char *name); From da17ea33e5a5d0c5226a37c375575d689f6a741b Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 12 Feb 2015 22:10:52 +0100 Subject: [PATCH 18/19] perf tools: Add machine__module_dso function Separate the dso object addition and update when adding new kernel module. Currently we update dso's symtab_type any time we find it in the list, because we can't distinguish between new and found dso from __dsos__findnew function. Adding machine__module_dso that separates finding and adding new dso objects, so there's no superfluous update of dso. Signed-off-by: Jiri Olsa Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-uvqgs5tyq4wssnq6fm43hgvk@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/machine.c | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 24f8c978cfd4..dbb5f0367005 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -460,12 +460,35 @@ int machine__process_lost_event(struct machine *machine __maybe_unused, return 0; } +static struct dso *machine__module_dso(struct machine *machine, const char *filename) +{ + struct dso *dso; + bool compressed; + + dso = dsos__find(&machine->kernel_dsos, filename, false); + if (!dso) { + dso = dsos__addnew(&machine->kernel_dsos, filename); + if (dso == NULL) + return NULL; + + if (machine__is_host(machine)) + dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE; + else + dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE; + + /* _KMODULE_COMP should be next to _KMODULE */ + if (is_kernel_module(filename, &compressed) && compressed) + dso->symtab_type++; + } + + return dso; +} + struct map *machine__new_module(struct machine *machine, u64 start, const char *filename) { struct map *map; - struct dso *dso = __dsos__findnew(&machine->kernel_dsos, filename); - bool compressed; + struct dso *dso = machine__module_dso(machine, filename); if (dso == NULL) return NULL; @@ -474,15 +497,6 @@ struct map *machine__new_module(struct machine *machine, u64 start, if (map == NULL) return NULL; - if (machine__is_host(machine)) - dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE; - else - dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE; - - /* _KMODULE_COMP should be next to _KMODULE */ - if (is_kernel_module(filename, &compressed) && compressed) - dso->symtab_type++; - map_groups__insert(&machine->kmaps, map); return map; } From ca33380adf74afb985bf7aab09ec46707a5d2d57 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 17 Feb 2015 17:29:57 +0100 Subject: [PATCH 19/19] perf tools: Use kmod_path__parse for machine__new_dso Using kmod_path__parse to get the module name and update the dso short name within machine__new_dso function. This way it's done only first time when dso is created, unlike the current way when we update it all the time we process memory map of the kernel module. Signed-off-by: Jiri Olsa Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-8gjmt1ggf5ls1xkk7qi2ko4k@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/machine.c | 59 ++++++++++++++------------------------- 1 file changed, 21 insertions(+), 38 deletions(-) diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index dbb5f0367005..eb95b883fb44 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -460,14 +460,15 @@ int machine__process_lost_event(struct machine *machine __maybe_unused, return 0; } -static struct dso *machine__module_dso(struct machine *machine, const char *filename) +static struct dso* +machine__module_dso(struct machine *machine, struct kmod_path *m, + const char *filename) { struct dso *dso; - bool compressed; - dso = dsos__find(&machine->kernel_dsos, filename, false); + dso = dsos__find(&machine->kernel_dsos, m->name, true); if (!dso) { - dso = dsos__addnew(&machine->kernel_dsos, filename); + dso = dsos__addnew(&machine->kernel_dsos, m->name); if (dso == NULL) return NULL; @@ -477,8 +478,11 @@ static struct dso *machine__module_dso(struct machine *machine, const char *file dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE; /* _KMODULE_COMP should be next to _KMODULE */ - if (is_kernel_module(filename, &compressed) && compressed) + if (m->kmod && m->comp) dso->symtab_type++; + + dso__set_short_name(dso, strdup(m->name), true); + dso__set_long_name(dso, strdup(filename), true); } return dso; @@ -487,17 +491,25 @@ static struct dso *machine__module_dso(struct machine *machine, const char *file struct map *machine__new_module(struct machine *machine, u64 start, const char *filename) { - struct map *map; - struct dso *dso = machine__module_dso(machine, filename); + struct map *map = NULL; + struct dso *dso; + struct kmod_path m; - if (dso == NULL) + if (kmod_path__parse_name(&m, filename)) return NULL; + dso = machine__module_dso(machine, &m, filename); + if (dso == NULL) + goto out; + map = map__new2(start, dso, MAP__FUNCTION); if (map == NULL) - return NULL; + goto out; map_groups__insert(&machine->kmaps, map); + +out: + free(m.name); return map; } @@ -1058,40 +1070,11 @@ static int machine__process_kernel_mmap_event(struct machine *machine, strlen(kmmap_prefix) - 1) == 0; if (event->mmap.filename[0] == '/' || (!is_kernel_mmap && event->mmap.filename[0] == '[')) { - - char short_module_name[1024]; - char *name, *dot; - - if (event->mmap.filename[0] == '/') { - name = strrchr(event->mmap.filename, '/'); - if (name == NULL) - goto out_problem; - - ++name; /* skip / */ - dot = strrchr(name, '.'); - if (dot == NULL) - goto out_problem; - /* On some system, modules are compressed like .ko.gz */ - if (is_supported_compression(dot + 1)) - dot -= 3; - if (!is_kmodule_extension(dot + 1)) - goto out_problem; - snprintf(short_module_name, sizeof(short_module_name), - "[%.*s]", (int)(dot - name), name); - strxfrchar(short_module_name, '-', '_'); - } else - strcpy(short_module_name, event->mmap.filename); - map = machine__new_module(machine, event->mmap.start, event->mmap.filename); if (map == NULL) goto out_problem; - name = strdup(short_module_name); - if (name == NULL) - goto out_problem; - - dso__set_short_name(map->dso, name, true); map->end = map->start + event->mmap.len; } else if (is_kernel_mmap) { const char *symbol_name = (event->mmap.filename +