Эх сурвалжийг харах

Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core

Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:

User visible changes:

  - Bash completion for subcommands (Yunlong Song)

  - Allow annotating entries in callchains in the hists browser (top/report).
    TODO: give some visual cue to what entries in callchains have samples and thus
    can be annotated and/or allow showing the source code for functions without
    samples (Arnaldo Carvalho de Melo)

  - Don't allow empty argument for '-t' in perf report, fixing segfault (Wang Nan)

Infrastructure:

  - Prep work for moving the perf feature tests build system to tools/build (Jiri Olsa)

  - Fix perf-read-vdsox32 not building and lib64 install dir (H.J. Lu)

  - ARM64: fix building error and eh/debug frame offset cache fixes (Wang Nan)

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Ingo Molnar 10 жил өмнө
parent
commit
08b3f91390

+ 1 - 2
tools/perf/Makefile.perf

@@ -528,8 +528,7 @@ clean: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean config-clean
 	$(Q)find . -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete
 	$(Q)find . -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete
 	$(Q)$(RM) .config-detected
 	$(Q)$(RM) .config-detected
 	$(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf perf-read-vdso32 perf-read-vdsox32
 	$(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf perf-read-vdso32 perf-read-vdsox32
-	$(call QUIET_CLEAN, core-gen)   $(RM)  *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-FEATURES $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex*
-	$(call QUIET_CLEAN, feature-detect) $(RM) $(OUTPUT)config/feature-checks/.make-*.output
+	$(call QUIET_CLEAN, core-gen)   $(RM)  *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)FEATURE-DUMP $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex*
 	$(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean
 	$(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean
 	$(python-clean)
 	$(python-clean)
 
 

+ 4 - 2
tools/perf/builtin-data.c

@@ -22,7 +22,9 @@ static const struct option data_options[] = {
 	OPT_END()
 	OPT_END()
 };
 };
 
 
-static const char * const data_usage[] = {
+static const char * const data_subcommands[] = { "convert", NULL };
+
+static const char *data_usage[] = {
 	"perf data [<common options>] <command> [<options>]",
 	"perf data [<common options>] <command> [<options>]",
 	NULL
 	NULL
 };
 };
@@ -98,7 +100,7 @@ int cmd_data(int argc, const char **argv, const char *prefix)
 	if (argc < 2)
 	if (argc < 2)
 		goto usage;
 		goto usage;
 
 
-	argc = parse_options(argc, argv, data_options, data_usage,
+	argc = parse_options_subcommand(argc, argv, data_options, data_subcommands, data_usage,
 			     PARSE_OPT_STOP_AT_NON_OPTION);
 			     PARSE_OPT_STOP_AT_NON_OPTION);
 	if (argc < 1)
 	if (argc < 1)
 		goto usage;
 		goto usage;

+ 14 - 3
tools/perf/builtin-help.c

@@ -437,7 +437,18 @@ int cmd_help(int argc, const char **argv, const char *prefix __maybe_unused)
 			HELP_FORMAT_INFO),
 			HELP_FORMAT_INFO),
 	OPT_END(),
 	OPT_END(),
 	};
 	};
-	const char * const builtin_help_usage[] = {
+	const char * const builtin_help_subcommands[] = {
+		"buildid-cache", "buildid-list", "diff", "evlist", "help", "list",
+		"record", "report", "bench", "stat", "timechart", "top", "annotate",
+		"script", "sched", "kmem", "lock", "kvm", "test", "inject", "mem", "data",
+#ifdef HAVE_LIBELF_SUPPORT
+		"probe",
+#endif
+#ifdef HAVE_LIBAUDIT_SUPPORT
+		"trace",
+#endif
+	NULL };
+	const char *builtin_help_usage[] = {
 		"perf help [--all] [--man|--web|--info] [command]",
 		"perf help [--all] [--man|--web|--info] [command]",
 		NULL
 		NULL
 	};
 	};
@@ -448,8 +459,8 @@ int cmd_help(int argc, const char **argv, const char *prefix __maybe_unused)
 
 
 	perf_config(perf_help_config, &help_format);
 	perf_config(perf_help_config, &help_format);
 
 
-	argc = parse_options(argc, argv, builtin_help_options,
-			builtin_help_usage, 0);
+	argc = parse_options_subcommand(argc, argv, builtin_help_options,
+			builtin_help_subcommands, builtin_help_usage, 0);
 
 
 	if (show_all) {
 	if (show_all) {
 		printf("\n usage: %s\n\n", perf_usage_string);
 		printf("\n usage: %s\n\n", perf_usage_string);

+ 1 - 1
tools/perf/builtin-report.c

@@ -676,7 +676,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
 	OPT_STRING('w', "column-widths", &symbol_conf.col_width_list_str,
 	OPT_STRING('w', "column-widths", &symbol_conf.col_width_list_str,
 		   "width[,width...]",
 		   "width[,width...]",
 		   "don't try to adjust column width, use these fixed values"),
 		   "don't try to adjust column width, use these fixed values"),
-	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 "
 		   "separator for columns, no spaces will be added between "
 		   "columns '.' is reserved."),
 		   "columns '.' is reserved."),
 	OPT_BOOLEAN('U', "hide-unresolved", &report.hide_unresolved,
 	OPT_BOOLEAN('U', "hide-unresolved", &report.hide_unresolved,

+ 3 - 2
tools/perf/builtin-script.c

@@ -1572,7 +1572,8 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
 		    "Show the mmap events"),
 		    "Show the mmap events"),
 	OPT_END()
 	OPT_END()
 	};
 	};
-	const char * const script_usage[] = {
+	const char * const script_subcommands[] = { "record", "report", NULL };
+	const char *script_usage[] = {
 		"perf script [<options>]",
 		"perf script [<options>]",
 		"perf script [<options>] record <script> [<record-options>] <command>",
 		"perf script [<options>] record <script> [<record-options>] <command>",
 		"perf script [<options>] report <script> [script-args]",
 		"perf script [<options>] report <script> [script-args]",
@@ -1586,7 +1587,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
 
 
 	setup_scripting();
 	setup_scripting();
 
 
-	argc = parse_options(argc, argv, options, script_usage,
+	argc = parse_options_subcommand(argc, argv, options, script_subcommands, script_usage,
 			     PARSE_OPT_STOP_AT_NON_OPTION);
 			     PARSE_OPT_STOP_AT_NON_OPTION);
 
 
 	file.path = input_name;
 	file.path = input_name;

+ 4 - 3
tools/perf/builtin-timechart.c

@@ -1958,7 +1958,8 @@ int cmd_timechart(int argc, const char **argv,
 		     parse_time),
 		     parse_time),
 	OPT_END()
 	OPT_END()
 	};
 	};
-	const char * const timechart_usage[] = {
+	const char * const timechart_subcommands[] = { "record", NULL };
+	const char *timechart_usage[] = {
 		"perf timechart [<options>] {record}",
 		"perf timechart [<options>] {record}",
 		NULL
 		NULL
 	};
 	};
@@ -1976,8 +1977,8 @@ int cmd_timechart(int argc, const char **argv,
 		"perf timechart record [<options>]",
 		"perf timechart record [<options>]",
 		NULL
 		NULL
 	};
 	};
-	argc = parse_options(argc, argv, timechart_options, timechart_usage,
-			PARSE_OPT_STOP_AT_NON_OPTION);
+	argc = parse_options_subcommand(argc, argv, timechart_options, timechart_subcommands,
+			timechart_usage, PARSE_OPT_STOP_AT_NON_OPTION);
 
 
 	if (tchart.power_only && tchart.tasks_only) {
 	if (tchart.power_only && tchart.tasks_only) {
 		pr_err("-P and -T options cannot be used at the same time.\n");
 		pr_err("-P and -T options cannot be used at the same time.\n");

+ 4 - 3
tools/perf/builtin-trace.c

@@ -2609,7 +2609,7 @@ static void evlist__set_evsel_handler(struct perf_evlist *evlist, void *handler)
 
 
 int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
 int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
 {
 {
-	const char * const trace_usage[] = {
+	const char *trace_usage[] = {
 		"perf trace [<options>] [<command>]",
 		"perf trace [<options>] [<command>]",
 		"perf trace [<options>] -- <command> [<options>]",
 		"perf trace [<options>] -- <command> [<options>]",
 		"perf trace record [<options>] [<command>]",
 		"perf trace record [<options>] [<command>]",
@@ -2684,6 +2684,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
 	OPT_BOOLEAN(0, "syscalls", &trace.trace_syscalls, "Trace syscalls"),
 	OPT_BOOLEAN(0, "syscalls", &trace.trace_syscalls, "Trace syscalls"),
 	OPT_END()
 	OPT_END()
 	};
 	};
+	const char * const trace_subcommands[] = { "record", NULL };
 	int err;
 	int err;
 	char bf[BUFSIZ];
 	char bf[BUFSIZ];
 
 
@@ -2699,8 +2700,8 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
 		goto out;
 		goto out;
 	}
 	}
 
 
-	argc = parse_options(argc, argv, trace_options, trace_usage,
-			     PARSE_OPT_STOP_AT_NON_OPTION);
+	argc = parse_options_subcommand(argc, argv, trace_options, trace_subcommands,
+				 trace_usage, PARSE_OPT_STOP_AT_NON_OPTION);
 
 
 	if (trace.trace_pgfaults) {
 	if (trace.trace_pgfaults) {
 		trace.opts.sample_address = true;
 		trace.opts.sample_address = true;

+ 46 - 65
tools/perf/config/Makefile

@@ -15,7 +15,6 @@ $(shell echo -n > .config-detected)
 detected     = $(shell echo "$(1)=y"       >> .config-detected)
 detected     = $(shell echo "$(1)=y"       >> .config-detected)
 detected_var = $(shell echo "$(1)=$($(1))" >> .config-detected)
 detected_var = $(shell echo "$(1)=$($(1))" >> .config-detected)
 
 
-LIB_INCLUDE := $(srctree)/tools/lib/
 CFLAGS := $(EXTRA_CFLAGS) $(EXTRA_WARNINGS)
 CFLAGS := $(EXTRA_CFLAGS) $(EXTRA_WARNINGS)
 
 
 include $(src-perf)/config/Makefile.arch
 include $(src-perf)/config/Makefile.arch
@@ -184,7 +183,7 @@ endif
 
 
 feature_check = $(eval $(feature_check_code))
 feature_check = $(eval $(feature_check_code))
 define 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 > $(OUTPUT)config/feature-checks/.make-$(1).output 2>&1 && 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 config/feature-checks test-$1.bin >/dev/null 2>/dev/null && echo 1 || echo 0)
 endef
 endef
 
 
 feature_set = $(eval $(feature_set_code))
 feature_set = $(eval $(feature_set_code))
@@ -204,7 +203,7 @@ endef
 #   the rule that uses them - an example for that is the 'bionic'
 #   the rule that uses them - an example for that is the 'bionic'
 #   feature check. ]
 #   feature check. ]
 #
 #
-CORE_FEATURE_TESTS =			\
+FEATURE_TESTS =			\
 	backtrace			\
 	backtrace			\
 	dwarf				\
 	dwarf				\
 	fortify-source			\
 	fortify-source			\
@@ -227,10 +226,9 @@ CORE_FEATURE_TESTS =			\
 	stackprotector-all		\
 	stackprotector-all		\
 	timerfd				\
 	timerfd				\
 	libdw-dwarf-unwind		\
 	libdw-dwarf-unwind		\
-	libbabeltrace			\
 	zlib
 	zlib
 
 
-LIB_FEATURE_TESTS =			\
+FEATURE_DISPLAY =			\
 	dwarf				\
 	dwarf				\
 	glibc				\
 	glibc				\
 	gtk2				\
 	gtk2				\
@@ -243,29 +241,9 @@ LIB_FEATURE_TESTS =			\
 	libslang			\
 	libslang			\
 	libunwind			\
 	libunwind			\
 	libdw-dwarf-unwind		\
 	libdw-dwarf-unwind		\
-	libbabeltrace			\
 	zlib
 	zlib
 
 
-VF_FEATURE_TESTS =			\
-	backtrace			\
-	fortify-source			\
-	sync-compare-and-swap		\
-	gtk2-infobar			\
-	libelf-getphdrnum		\
-	libelf-mmap			\
-	libpython-version		\
-	pthread-attr-setaffinity-np	\
-	stackprotector-all		\
-	timerfd				\
-	libunwind-debug-frame		\
-	bionic				\
-	liberty				\
-	liberty-z			\
-	cplus-demangle			\
-	compile-32			\
-	compile-x32
-
-# Set FEATURE_CHECK_(C|LD)FLAGS-all for all CORE_FEATURE_TESTS features.
+# 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
 # If in the future we need per-feature checks/flags for features not
 # mentioned in this list we need to refactor this ;-).
 # mentioned in this list we need to refactor this ;-).
 set_test_all_flags = $(eval $(set_test_all_flags_code))
 set_test_all_flags = $(eval $(set_test_all_flags_code))
@@ -274,7 +252,7 @@ define set_test_all_flags_code
   FEATURE_CHECK_LDFLAGS-all += $(FEATURE_CHECK_LDFLAGS-$(1))
   FEATURE_CHECK_LDFLAGS-all += $(FEATURE_CHECK_LDFLAGS-$(1))
 endef
 endef
 
 
-$(foreach feat,$(CORE_FEATURE_TESTS),$(call set_test_all_flags,$(feat)))
+$(foreach feat,$(FEATURE_TESTS),$(call set_test_all_flags,$(feat)))
 
 
 #
 #
 # Special fast-path for the 'all features are available' case:
 # Special fast-path for the 'all features are available' case:
@@ -289,10 +267,10 @@ ifeq ($(feature-all), 1)
   #
   #
   # test-all.c passed - just set all the core feature flags to 1:
   # test-all.c passed - just set all the core feature flags to 1:
   #
   #
-  $(foreach feat,$(CORE_FEATURE_TESTS),$(call feature_set,$(feat)))
+  $(foreach feat,$(FEATURE_TESTS),$(call feature_set,$(feat)))
 else
 else
-  $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS)" LDFLAGS=$(LDFLAGS) -i -j -C config/feature-checks $(addsuffix .bin,$(CORE_FEATURE_TESTS)) >/dev/null 2>&1)
-  $(foreach feat,$(CORE_FEATURE_TESTS),$(call feature_check,$(feat)))
+  $(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
 endif
 
 
 ifeq ($(feature-stackprotector-all), 1)
 ifeq ($(feature-stackprotector-all), 1)
@@ -322,7 +300,7 @@ endif
 
 
 CFLAGS += -I$(src-perf)/util
 CFLAGS += -I$(src-perf)/util
 CFLAGS += -I$(src-perf)
 CFLAGS += -I$(src-perf)
-CFLAGS += -I$(LIB_INCLUDE)
+CFLAGS += -I$(srctree)/tools/lib/
 
 
 CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
 CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
 
 
@@ -688,7 +666,7 @@ ifeq (${IS_64_BIT}, 1)
       NO_PERF_READ_VDSO32 := 1
       NO_PERF_READ_VDSO32 := 1
     endif
     endif
   endif
   endif
-  ifneq (${IS_X86_64}, 1)
+  ifneq ($(ARCH), x86)
     NO_PERF_READ_VDSOX32 := 1
     NO_PERF_READ_VDSOX32 := 1
   endif
   endif
   ifndef NO_PERF_READ_VDSOX32
   ifndef NO_PERF_READ_VDSOX32
@@ -705,14 +683,15 @@ else
 endif
 endif
 
 
 ifndef NO_LIBBABELTRACE
 ifndef NO_LIBBABELTRACE
-  ifeq ($(feature-libbabeltrace), 0)
-    msg := $(warning No libbabeltrace found, disables 'perf data' CTF format support, please install libbabeltrace-dev[el]/libbabeltrace-ctf-dev);
-    NO_LIBBABELTRACE := 1
-  else
+  $(call feature_check,libbabeltrace)
+  ifeq ($(feature-libbabeltrace), 1)
     CFLAGS += -DHAVE_LIBBABELTRACE_SUPPORT $(LIBBABELTRACE_CFLAGS)
     CFLAGS += -DHAVE_LIBBABELTRACE_SUPPORT $(LIBBABELTRACE_CFLAGS)
     LDFLAGS += $(LIBBABELTRACE_LDFLAGS)
     LDFLAGS += $(LIBBABELTRACE_LDFLAGS)
     EXTLIBS += -lbabeltrace-ctf
     EXTLIBS += -lbabeltrace-ctf
     $(call detected,CONFIG_LIBBABELTRACE)
     $(call detected,CONFIG_LIBBABELTRACE)
+  else
+    msg := $(warning No libbabeltrace found, disables 'perf data' CTF format support, please install libbabeltrace-dev[el]/libbabeltrace-ctf-dev);
+    NO_LIBBABELTRACE := 1
   endif
   endif
 endif
 endif
 
 
@@ -748,7 +727,7 @@ sysconfdir = $(prefix)/etc
 ETC_PERFCONFIG = etc/perfconfig
 ETC_PERFCONFIG = etc/perfconfig
 endif
 endif
 ifndef lib
 ifndef lib
-ifeq ($(IS_X86_64),1)
+ifeq ($(ARCH)$(IS_64_BIT), x861)
 lib = lib64
 lib = lib64
 else
 else
 lib = lib
 lib = lib
@@ -797,8 +776,8 @@ define feature_print_status_code
   endif
   endif
 endef
 endef
 
 
-feature_print_var = $(eval $(feature_print_var_code)) $(info $(MSG))
-define feature_print_var_code
+print_var = $(eval $(print_var_code)) $(info $(MSG))
+define print_var_code
     MSG = $(shell printf '...%30s: %s' $(1) $($(1)))
     MSG = $(shell printf '...%30s: %s' $(1) $($(1)))
 endef
 endef
 
 
@@ -807,61 +786,63 @@ define feature_print_text_code
     MSG = $(shell printf '...%30s: %s' $(1) $(2))
     MSG = $(shell printf '...%30s: %s' $(1) $(2))
 endef
 endef
 
 
-PERF_FEATURES := $(foreach feat,$(LIB_FEATURE_TESTS),feature-$(feat)($(feature-$(feat))))
-PERF_FEATURES_FILE := $(shell touch $(OUTPUT)PERF-FEATURES; cat $(OUTPUT)PERF-FEATURES)
+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)
 ifeq ($(dwarf-post-unwind),1)
-  PERF_FEATURES += dwarf-post-unwind($(dwarf-post-unwind-text))
+  FEATURE_DUMP += dwarf-post-unwind($(dwarf-post-unwind-text))
 endif
 endif
 
 
-# The $(display_lib) controls the default detection message
+# The $(feature_display) controls the default detection message
 # output. It's set if:
 # output. It's set if:
 # - detected features differes from stored features from
 # - detected features differes from stored features from
-#   last build (in PERF-FEATURES file)
-# - one of the $(LIB_FEATURE_TESTS) is not detected
+#   last build (in FEATURE-DUMP file)
+# - one of the $(FEATURE_DISPLAY) is not detected
 # - VF is enabled
 # - VF is enabled
 
 
-ifneq ("$(PERF_FEATURES)","$(PERF_FEATURES_FILE)")
-  $(shell echo "$(PERF_FEATURES)" > $(OUTPUT)PERF-FEATURES)
-  display_lib := 1
+ifneq ("$(FEATURE_DUMP)","$(FEATURE_DUMP_FILE)")
+  $(shell echo "$(FEATURE_DUMP)" > $(OUTPUT)FEATURE-DUMP)
+  feature_display := 1
 endif
 endif
 
 
 feature_check = $(eval $(feature_check_code))
 feature_check = $(eval $(feature_check_code))
 define feature_check_code
 define feature_check_code
   ifneq ($(feature-$(1)), 1)
   ifneq ($(feature-$(1)), 1)
-    display_lib := 1
+    feature_display := 1
   endif
   endif
 endef
 endef
 
 
-$(foreach feat,$(LIB_FEATURE_TESTS),$(call feature_check,$(feat)))
+$(foreach feat,$(FEATURE_DISPLAY),$(call feature_check,$(feat)))
 
 
 ifeq ($(VF),1)
 ifeq ($(VF),1)
-  display_lib := 1
-  display_vf := 1
+  feature_display := 1
+  feature_verbose := 1
 endif
 endif
 
 
-ifeq ($(display_lib),1)
+ifeq ($(feature_display),1)
   $(info )
   $(info )
   $(info Auto-detecting system features:)
   $(info Auto-detecting system features:)
-  $(foreach feat,$(LIB_FEATURE_TESTS),$(call feature_print_status,$(feat),))
+  $(foreach feat,$(FEATURE_DISPLAY),$(call feature_print_status,$(feat),))
 
 
   ifeq ($(dwarf-post-unwind),1)
   ifeq ($(dwarf-post-unwind),1)
     $(call feature_print_text,"DWARF post unwind library", $(dwarf-post-unwind-text))
     $(call feature_print_text,"DWARF post unwind library", $(dwarf-post-unwind-text))
   endif
   endif
-endif
 
 
-ifeq ($(display_vf),1)
-  $(foreach feat,$(VF_FEATURE_TESTS),$(call feature_print_status,$(feat),))
-  $(info )
-  $(call feature_print_var,prefix)
-  $(call feature_print_var,bindir)
-  $(call feature_print_var,libdir)
-  $(call feature_print_var,sysconfdir)
-  $(call feature_print_var,LIBUNWIND_DIR)
-  $(call feature_print_var,LIBDW_DIR)
+  ifneq ($(feature_verbose),1)
+    $(info )
+  endif
 endif
 endif
 
 
-ifeq ($(display_lib),1)
+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)
+  $(call print_var,sysconfdir)
+  $(call print_var,LIBUNWIND_DIR)
+  $(call print_var,LIBDW_DIR)
   $(info )
   $(info )
 endif
 endif
 
 

+ 1 - 1
tools/perf/config/Makefile.arch

@@ -4,7 +4,7 @@ endif
 
 
 ARCH := $(shell echo $(ARCH) | sed -e s/i.86/x86/ -e s/x86_64/x86/ \
 ARCH := $(shell echo $(ARCH) | sed -e s/i.86/x86/ -e s/x86_64/x86/ \
                                   -e s/sun4u/sparc/ -e s/sparc64/sparc/ \
                                   -e s/sun4u/sparc/ -e s/sparc64/sparc/ \
-                                  -e s/arm.*/arm/ -e s/sa110/arm/ \
+                                  -e /arm64/!s/arm.*/arm/ -e s/sa110/arm/ \
                                   -e s/s390x/s390/ -e s/parisc64/parisc/ \
                                   -e s/s390x/s390/ -e s/parisc64/parisc/ \
                                   -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \
                                   -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \
                                   -e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ \
                                   -e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ \

+ 4 - 3
tools/perf/config/feature-checks/Makefile

@@ -39,12 +39,13 @@ PKG_CONFIG := $(CROSS_COMPILE)pkg-config
 
 
 all: $(FILES)
 all: $(FILES)
 
 
-BUILD = $(CC) $(CFLAGS) -Wall -Werror -o $(OUTPUT)$@ $(patsubst %.bin,%.c,$@) $(LDFLAGS)
+__BUILD = $(CC) $(CFLAGS) -Wall -Werror -o $(OUTPUT)$@ $(patsubst %.bin,%.c,$@) $(LDFLAGS)
+  BUILD = $(__BUILD) > $(OUTPUT)$(@:.bin=.make.output) 2>&1
 
 
 ###############################
 ###############################
 
 
 test-all.bin:
 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 -lbabeltrace
+	$(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
 
 
 test-hello.bin:
 test-hello.bin:
 	$(BUILD)
 	$(BUILD)
@@ -156,4 +157,4 @@ test-zlib.bin:
 ###############################
 ###############################
 
 
 clean:
 clean:
-	rm -f $(FILES) *.d
+	rm -f $(FILES) *.d $(FILES:.bin=.make.output)

+ 9 - 2
tools/perf/config/feature-checks/test-all.c

@@ -98,12 +98,20 @@
 #undef main
 #undef main
 
 
 #define main main_test_pthread_attr_setaffinity_np
 #define main main_test_pthread_attr_setaffinity_np
-# include "test-pthread_attr_setaffinity_np.c"
+# include "test-pthread-attr-setaffinity-np.c"
 #undef main
 #undef main
 
 
+# if 0
+/*
+ * Disable libbabeltrace check for test-all, because the requested
+ * library version is not released yet in most distributions. Will
+ * reenable later.
+ */
+
 #define main main_test_libbabeltrace
 #define main main_test_libbabeltrace
 # include "test-libbabeltrace.c"
 # include "test-libbabeltrace.c"
 #undef main
 #undef main
+#endif
 
 
 int main(int argc, char *argv[])
 int main(int argc, char *argv[])
 {
 {
@@ -130,7 +138,6 @@ int main(int argc, char *argv[])
 	main_test_sync_compare_and_swap(argc, argv);
 	main_test_sync_compare_and_swap(argc, argv);
 	main_test_zlib();
 	main_test_zlib();
 	main_test_pthread_attr_setaffinity_np();
 	main_test_pthread_attr_setaffinity_np();
-	main_test_libbabeltrace();
 
 
 	return 0;
 	return 0;
 }
 }

+ 71 - 17
tools/perf/perf-completion.sh

@@ -47,8 +47,16 @@ __my_reassemble_comp_words_by_ref()
 	done
 	done
 }
 }
 
 
-type _get_comp_words_by_ref &>/dev/null ||
-_get_comp_words_by_ref()
+# Define preload_get_comp_words_by_ref="false", if the function
+# __perf_get_comp_words_by_ref() is required instead.
+preload_get_comp_words_by_ref="true"
+
+if [ $preload_get_comp_words_by_ref = "true" ]; then
+	type _get_comp_words_by_ref &>/dev/null ||
+	preload_get_comp_words_by_ref="false"
+fi
+[ $preload_get_comp_words_by_ref = "true" ] ||
+__perf_get_comp_words_by_ref()
 {
 {
 	local exclude cur_ words_ cword_
 	local exclude cur_ words_ cword_
 	if [ "$1" = "-n" ]; then
 	if [ "$1" = "-n" ]; then
@@ -76,8 +84,16 @@ _get_comp_words_by_ref()
 	done
 	done
 }
 }
 
 
-type __ltrim_colon_completions &>/dev/null ||
-__ltrim_colon_completions()
+# Define preload__ltrim_colon_completions="false", if the function
+# __perf__ltrim_colon_completions() is required instead.
+preload__ltrim_colon_completions="true"
+
+if [ $preload__ltrim_colon_completions = "true" ]; then
+	type __ltrim_colon_completions &>/dev/null ||
+	preload__ltrim_colon_completions="false"
+fi
+[ $preload__ltrim_colon_completions = "true" ] ||
+__perf__ltrim_colon_completions()
 {
 {
 	if [[ "$1" == *:* && "$COMP_WORDBREAKS" == *:* ]]; then
 	if [[ "$1" == *:* && "$COMP_WORDBREAKS" == *:* ]]; then
 		# Remove colon-word prefix from COMPREPLY items
 		# Remove colon-word prefix from COMPREPLY items
@@ -97,7 +113,32 @@ __perfcomp ()
 __perfcomp_colon ()
 __perfcomp_colon ()
 {
 {
 	__perfcomp "$1" "$2"
 	__perfcomp "$1" "$2"
-	__ltrim_colon_completions $cur
+	if [ $preload__ltrim_colon_completions = "true" ]; then
+		__ltrim_colon_completions $cur
+	else
+		__perf__ltrim_colon_completions $cur
+	fi
+}
+
+__perf_prev_skip_opts ()
+{
+	local i cmd_ cmds_
+
+	let i=cword-1
+	cmds_=$($cmd $1 --list-cmds)
+	prev_skip_opts=()
+	while [ $i -ge 0 ]; do
+		if [[ ${words[i]} == $1 ]]; then
+			return
+		fi
+		for cmd_ in $cmds_; do
+			if [[ ${words[i]} == $cmd_ ]]; then
+				prev_skip_opts=${words[i]}
+				return
+			fi
+		done
+		((i--))
+	done
 }
 }
 
 
 __perf_main ()
 __perf_main ()
@@ -107,8 +148,10 @@ __perf_main ()
 	cmd=${words[0]}
 	cmd=${words[0]}
 	COMPREPLY=()
 	COMPREPLY=()
 
 
+	# Skip options backward and find the last perf command
+	__perf_prev_skip_opts
 	# List perf subcommands or long options
 	# List perf subcommands or long options
-	if [ $cword -eq 1 ]; then
+	if [ -z $prev_skip_opts ]; then
 		if [[ $cur == --* ]]; then
 		if [[ $cur == --* ]]; then
 			cmds=$($cmd --list-opts)
 			cmds=$($cmd --list-opts)
 		else
 		else
@@ -116,18 +159,25 @@ __perf_main ()
 		fi
 		fi
 		__perfcomp "$cmds" "$cur"
 		__perfcomp "$cmds" "$cur"
 	# List possible events for -e option
 	# List possible events for -e option
-	elif [[ $prev == "-e" && "${words[1]}" == @(record|stat|top) ]]; then
+	elif [[ $prev == @("-e"|"--event") &&
+		$prev_skip_opts == @(record|stat|top) ]]; then
 		evts=$($cmd list --raw-dump)
 		evts=$($cmd list --raw-dump)
 		__perfcomp_colon "$evts" "$cur"
 		__perfcomp_colon "$evts" "$cur"
-	# List subcommands for perf commands
-	elif [[ $prev == @(kvm|kmem|mem|lock|sched) ]]; then
-		subcmds=$($cmd $prev --list-cmds)
-		__perfcomp_colon "$subcmds" "$cur"
-	# List long option names
-	elif [[ $cur == --* ]];  then
-		subcmd=${words[1]}
-		opts=$($cmd $subcmd --list-opts)
-		__perfcomp "$opts" "$cur"
+	else
+		# List subcommands for perf commands
+		if [[ $prev_skip_opts == @(kvm|kmem|mem|lock|sched|
+			|data|help|script|test|timechart|trace) ]]; then
+			subcmds=$($cmd $prev_skip_opts --list-cmds)
+			__perfcomp_colon "$subcmds" "$cur"
+		fi
+		# List long option names
+		if [[ $cur == --* ]];  then
+			subcmd=$prev_skip_opts
+			__perf_prev_skip_opts $subcmd
+			subcmd=$subcmd" "$prev_skip_opts
+			opts=$($cmd $subcmd --list-opts)
+			__perfcomp "$opts" "$cur"
+		fi
 	fi
 	fi
 }
 }
 
 
@@ -196,7 +246,11 @@ type perf &>/dev/null &&
 _perf()
 _perf()
 {
 {
 	local cur words cword prev
 	local cur words cword prev
-	_get_comp_words_by_ref -n =: cur words cword prev
+	if [ $preload_get_comp_words_by_ref = "true" ]; then
+		_get_comp_words_by_ref -n =: cur words cword prev
+	else
+		__perf_get_comp_words_by_ref -n =: cur words cword prev
+	fi
 	__perf_main
 	__perf_main
 } &&
 } &&
 
 

+ 3 - 2
tools/perf/tests/builtin-test.c

@@ -291,7 +291,7 @@ static int perf_test__list(int argc, const char **argv)
 
 
 int cmd_test(int argc, const char **argv, const char *prefix __maybe_unused)
 int cmd_test(int argc, const char **argv, const char *prefix __maybe_unused)
 {
 {
-	const char * const test_usage[] = {
+	const char *test_usage[] = {
 	"perf test [<options>] [{list <test-name-fragment>|[<test-name-fragments>|<test-numbers>]}]",
 	"perf test [<options>] [{list <test-name-fragment>|[<test-name-fragments>|<test-numbers>]}]",
 	NULL,
 	NULL,
 	};
 	};
@@ -302,13 +302,14 @@ int cmd_test(int argc, const char **argv, const char *prefix __maybe_unused)
 		    "be more verbose (show symbol address, etc)"),
 		    "be more verbose (show symbol address, etc)"),
 	OPT_END()
 	OPT_END()
 	};
 	};
+	const char * const test_subcommands[] = { "list", NULL };
 	struct intlist *skiplist = NULL;
 	struct intlist *skiplist = NULL;
         int ret = hists__init();
         int ret = hists__init();
 
 
         if (ret < 0)
         if (ret < 0)
                 return ret;
                 return ret;
 
 
-	argc = parse_options(argc, argv, test_options, test_usage, 0);
+	argc = parse_options_subcommand(argc, argv, test_options, test_subcommands, test_usage, 0);
 	if (argc >= 1 && !strcmp(argv[0], "list"))
 	if (argc >= 1 && !strcmp(argv[0], "list"))
 		return perf_test__list(argc, argv);
 		return perf_test__list(argc, argv);
 
 

+ 1 - 1
tools/perf/tests/make

@@ -5,7 +5,7 @@ include config/Makefile.arch
 
 
 # FIXME looks like x86 is the only arch running tests ;-)
 # FIXME looks like x86 is the only arch running tests ;-)
 # we need some IS_(32/64) flag to make this generic
 # we need some IS_(32/64) flag to make this generic
-ifeq ($(IS_X86_64),1)
+ifeq ($(ARCH)$(IS_64_BIT), x861)
 lib = lib64
 lib = lib64
 else
 else
 lib = lib
 lib = lib

+ 7 - 1
tools/perf/ui/browsers/annotate.c

@@ -829,10 +829,16 @@ out:
 	return key;
 	return key;
 }
 }
 
 
+int map_symbol__tui_annotate(struct map_symbol *ms, struct perf_evsel *evsel,
+			     struct hist_browser_timer *hbt)
+{
+	return symbol__tui_annotate(ms->sym, ms->map, evsel, hbt);
+}
+
 int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel,
 int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel,
 			     struct hist_browser_timer *hbt)
 			     struct hist_browser_timer *hbt)
 {
 {
-	return symbol__tui_annotate(he->ms.sym, he->ms.map, evsel, hbt);
+	return map_symbol__tui_annotate(&he->ms, evsel, hbt);
 }
 }
 
 
 static void annotate_browser__mark_jump_targets(struct annotate_browser *browser,
 static void annotate_browser__mark_jump_targets(struct annotate_browser *browser,

+ 27 - 32
tools/perf/ui/browsers/hists.c

@@ -1612,28 +1612,30 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
 		if (!sort__has_sym)
 		if (!sort__has_sym)
 			goto add_exit_option;
 			goto add_exit_option;
 
 
+		if (browser->selection == NULL)
+			goto skip_annotation;
+
 		if (sort__mode == SORT_MODE__BRANCH) {
 		if (sort__mode == SORT_MODE__BRANCH) {
 			bi = browser->he_selection->branch_info;
 			bi = browser->he_selection->branch_info;
-			if (browser->selection != NULL &&
-			    bi &&
-			    bi->from.sym != NULL &&
+
+			if (bi == NULL)
+				goto skip_annotation;
+
+			if (bi->from.sym != NULL &&
 			    !bi->from.map->dso->annotate_warned &&
 			    !bi->from.map->dso->annotate_warned &&
-				asprintf(&options[nr_options], "Annotate %s",
-					 bi->from.sym->name) > 0)
+			    asprintf(&options[nr_options], "Annotate %s", bi->from.sym->name) > 0) {
 				annotate_f = nr_options++;
 				annotate_f = nr_options++;
+			}
 
 
-			if (browser->selection != NULL &&
-			    bi &&
-			    bi->to.sym != NULL &&
+			if (bi->to.sym != NULL &&
 			    !bi->to.map->dso->annotate_warned &&
 			    !bi->to.map->dso->annotate_warned &&
 			    (bi->to.sym != bi->from.sym ||
 			    (bi->to.sym != bi->from.sym ||
 			     bi->to.map->dso != bi->from.map->dso) &&
 			     bi->to.map->dso != bi->from.map->dso) &&
-				asprintf(&options[nr_options], "Annotate %s",
-					 bi->to.sym->name) > 0)
+			    asprintf(&options[nr_options], "Annotate %s", bi->to.sym->name) > 0) {
 				annotate_t = nr_options++;
 				annotate_t = nr_options++;
+			}
 		} else {
 		} else {
-			if (browser->selection != NULL &&
-			    browser->selection->sym != NULL &&
+			if (browser->selection->sym != NULL &&
 			    !browser->selection->map->dso->annotate_warned) {
 			    !browser->selection->map->dso->annotate_warned) {
 				struct annotation *notes;
 				struct annotation *notes;
 
 
@@ -1641,11 +1643,12 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
 
 
 				if (notes->src &&
 				if (notes->src &&
 				    asprintf(&options[nr_options], "Annotate %s",
 				    asprintf(&options[nr_options], "Annotate %s",
-						 browser->selection->sym->name) > 0)
+						 browser->selection->sym->name) > 0) {
 					annotate = nr_options++;
 					annotate = nr_options++;
+				}
 			}
 			}
 		}
 		}
-
+skip_annotation:
 		if (thread != NULL &&
 		if (thread != NULL &&
 		    asprintf(&options[nr_options], "Zoom %s %s(%d) thread",
 		    asprintf(&options[nr_options], "Zoom %s %s(%d) thread",
 			     (browser->hists->thread_filter ? "out of" : "into"),
 			     (browser->hists->thread_filter ? "out of" : "into"),
@@ -1701,6 +1704,7 @@ retry_popup_menu:
 		if (choice == annotate || choice == annotate_t || choice == annotate_f) {
 		if (choice == annotate || choice == annotate_t || choice == annotate_f) {
 			struct hist_entry *he;
 			struct hist_entry *he;
 			struct annotation *notes;
 			struct annotation *notes;
+			struct map_symbol ms;
 			int err;
 			int err;
 do_annotate:
 do_annotate:
 			if (!objdump_path && perf_session_env__lookup_objdump(env))
 			if (!objdump_path && perf_session_env__lookup_objdump(env))
@@ -1710,30 +1714,21 @@ do_annotate:
 			if (he == NULL)
 			if (he == NULL)
 				continue;
 				continue;
 
 
-			/*
-			 * we stash the branch_info symbol + map into the
-			 * the ms so we don't have to rewrite all the annotation
-			 * code to use branch_info.
-			 * in branch mode, the ms struct is not used
-			 */
 			if (choice == annotate_f) {
 			if (choice == annotate_f) {
-				he->ms.sym = he->branch_info->from.sym;
-				he->ms.map = he->branch_info->from.map;
-			}  else if (choice == annotate_t) {
-				he->ms.sym = he->branch_info->to.sym;
-				he->ms.map = he->branch_info->to.map;
+				ms.map = he->branch_info->from.map;
+				ms.sym = he->branch_info->from.sym;
+			} else if (choice == annotate_t) {
+				ms.map = he->branch_info->to.map;
+				ms.sym = he->branch_info->to.sym;
+			} else {
+				ms = *browser->selection;
 			}
 			}
 
 
-			notes = symbol__annotation(he->ms.sym);
+			notes = symbol__annotation(ms.sym);
 			if (!notes->src)
 			if (!notes->src)
 				continue;
 				continue;
 
 
-			/*
-			 * Don't let this be freed, say, by hists__decay_entry.
-			 */
-			he->used = true;
-			err = hist_entry__tui_annotate(he, evsel, hbt);
-			he->used = false;
+			err = map_symbol__tui_annotate(&ms, evsel, hbt);
 			/*
 			/*
 			 * offer option to annotate the other branch source or target
 			 * offer option to annotate the other branch source or target
 			 * (if they exists) when returning from annotate
 			 * (if they exists) when returning from annotate

+ 2 - 1
tools/perf/util/dso.h

@@ -139,7 +139,8 @@ struct dso {
 		u32		 status_seen;
 		u32		 status_seen;
 		size_t		 file_size;
 		size_t		 file_size;
 		struct list_head open_entry;
 		struct list_head open_entry;
-		u64		 frame_offset;
+		u64		 debug_frame_offset;
+		u64		 eh_frame_hdr_offset;
 	} data;
 	} data;
 
 
 	union { /* Tool specific area */
 	union { /* Tool specific area */

+ 1 - 7
tools/perf/util/hist.c

@@ -263,15 +263,9 @@ void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel)
 	while (next) {
 	while (next) {
 		n = rb_entry(next, struct hist_entry, rb_node);
 		n = rb_entry(next, struct hist_entry, rb_node);
 		next = rb_next(&n->rb_node);
 		next = rb_next(&n->rb_node);
-		/*
-		 * We may be annotating this, for instance, so keep it here in
-		 * case some it gets new samples, we'll eventually free it when
-		 * the user stops browsing and it agains gets fully decayed.
-		 */
 		if (((zap_user && n->level == '.') ||
 		if (((zap_user && n->level == '.') ||
 		     (zap_kernel && n->level != '.') ||
 		     (zap_kernel && n->level != '.') ||
-		     hists__decay_entry(hists, n)) &&
-		    !n->used) {
+		     hists__decay_entry(hists, n))) {
 			hists__delete_entry(hists, n);
 			hists__delete_entry(hists, n);
 		}
 		}
 	}
 	}

+ 9 - 0
tools/perf/util/hist.h

@@ -303,6 +303,9 @@ struct hist_browser_timer {
 
 
 #ifdef HAVE_SLANG_SUPPORT
 #ifdef HAVE_SLANG_SUPPORT
 #include "../ui/keysyms.h"
 #include "../ui/keysyms.h"
+int map_symbol__tui_annotate(struct map_symbol *ms, struct perf_evsel *evsel,
+			     struct hist_browser_timer *hbt);
+
 int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel,
 int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel,
 			     struct hist_browser_timer *hbt);
 			     struct hist_browser_timer *hbt);
 
 
@@ -321,6 +324,12 @@ int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused,
 {
 {
 	return 0;
 	return 0;
 }
 }
+static inline int map_symbol__tui_annotate(struct map_symbol *ms __maybe_unused,
+					   struct perf_evsel *evsel __maybe_unused,
+					   struct hist_browser_timer *hbt __maybe_unused)
+{
+	return 0;
+}
 
 
 static inline int hist_entry__tui_annotate(struct hist_entry *he __maybe_unused,
 static inline int hist_entry__tui_annotate(struct hist_entry *he __maybe_unused,
 					   struct perf_evsel *evsel __maybe_unused,
 					   struct perf_evsel *evsel __maybe_unused,

+ 19 - 2
tools/perf/util/parse-options.c

@@ -37,6 +37,7 @@ static int get_value(struct parse_opt_ctx_t *p,
 {
 {
 	const char *s, *arg = NULL;
 	const char *s, *arg = NULL;
 	const int unset = flags & OPT_UNSET;
 	const int unset = flags & OPT_UNSET;
+	int err;
 
 
 	if (unset && p->opt)
 	if (unset && p->opt)
 		return opterror(opt, "takes no value", flags);
 		return opterror(opt, "takes no value", flags);
@@ -114,13 +115,29 @@ static int get_value(struct parse_opt_ctx_t *p,
 		return 0;
 		return 0;
 
 
 	case OPTION_STRING:
 	case OPTION_STRING:
+		err = 0;
 		if (unset)
 		if (unset)
 			*(const char **)opt->value = NULL;
 			*(const char **)opt->value = NULL;
 		else if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
 		else if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
 			*(const char **)opt->value = (const char *)opt->defval;
 			*(const char **)opt->value = (const char *)opt->defval;
 		else
 		else
-			return get_arg(p, opt, flags, (const char **)opt->value);
-		return 0;
+			err = get_arg(p, opt, flags, (const char **)opt->value);
+
+		/* PARSE_OPT_NOEMPTY: Allow NULL but disallow empty string. */
+		if (opt->flags & PARSE_OPT_NOEMPTY) {
+			const char *val = *(const char **)opt->value;
+
+			if (!val)
+				return err;
+
+			/* Similar to unset if we are given an empty string. */
+			if (val[0] == '\0') {
+				*(const char **)opt->value = NULL;
+				return 0;
+			}
+		}
+
+		return err;
 
 
 	case OPTION_CALLBACK:
 	case OPTION_CALLBACK:
 		if (unset)
 		if (unset)

+ 2 - 0
tools/perf/util/parse-options.h

@@ -40,6 +40,7 @@ enum parse_opt_option_flags {
 	PARSE_OPT_LASTARG_DEFAULT = 16,
 	PARSE_OPT_LASTARG_DEFAULT = 16,
 	PARSE_OPT_DISABLED = 32,
 	PARSE_OPT_DISABLED = 32,
 	PARSE_OPT_EXCLUSIVE = 64,
 	PARSE_OPT_EXCLUSIVE = 64,
+	PARSE_OPT_NOEMPTY  = 128,
 };
 };
 
 
 struct option;
 struct option;
@@ -122,6 +123,7 @@ struct option {
 #define OPT_LONG(s, l, v, h)        { .type = OPTION_LONG, .short_name = (s), .long_name = (l), .value = check_vtype(v, long *), .help = (h) }
 #define OPT_LONG(s, l, v, h)        { .type = OPTION_LONG, .short_name = (s), .long_name = (l), .value = check_vtype(v, long *), .help = (h) }
 #define OPT_U64(s, l, v, h)         { .type = OPTION_U64, .short_name = (s), .long_name = (l), .value = check_vtype(v, u64 *), .help = (h) }
 #define OPT_U64(s, l, v, h)         { .type = OPTION_U64, .short_name = (s), .long_name = (l), .value = check_vtype(v, u64 *), .help = (h) }
 #define OPT_STRING(s, l, v, a, h)   { .type = OPTION_STRING,  .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), (a), .help = (h) }
 #define OPT_STRING(s, l, v, a, h)   { .type = OPTION_STRING,  .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), (a), .help = (h) }
+#define OPT_STRING_NOEMPTY(s, l, v, a, h)   { .type = OPTION_STRING,  .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), (a), .help = (h), .flags = PARSE_OPT_NOEMPTY}
 #define OPT_DATE(s, l, v, h) \
 #define OPT_DATE(s, l, v, h) \
 	{ .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = "time", .help = (h), .callback = parse_opt_approxidate_cb }
 	{ .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = "time", .help = (h), .callback = parse_opt_approxidate_cb }
 #define OPT_CALLBACK(s, l, v, a, h, f) \
 #define OPT_CALLBACK(s, l, v, a, h, f) \

+ 0 - 1
tools/perf/util/sort.h

@@ -102,7 +102,6 @@ struct hist_entry {
 
 
 	bool			init_have_children;
 	bool			init_have_children;
 	char			level;
 	char			level;
-	bool			used;
 	u8			filtered;
 	u8			filtered;
 	char			*srcline;
 	char			*srcline;
 	struct symbol		*parent;
 	struct symbol		*parent;

+ 4 - 4
tools/perf/util/unwind-libunwind.c

@@ -266,7 +266,7 @@ static int read_unwind_spec_eh_frame(struct dso *dso, struct machine *machine,
 				     u64 *fde_count)
 				     u64 *fde_count)
 {
 {
 	int ret = -EINVAL, fd;
 	int ret = -EINVAL, fd;
-	u64 offset = dso->data.frame_offset;
+	u64 offset = dso->data.eh_frame_hdr_offset;
 
 
 	if (offset == 0) {
 	if (offset == 0) {
 		fd = dso__data_fd(dso, machine);
 		fd = dso__data_fd(dso, machine);
@@ -275,7 +275,7 @@ static int read_unwind_spec_eh_frame(struct dso *dso, struct machine *machine,
 
 
 		/* Check the .eh_frame section for unwinding info */
 		/* Check the .eh_frame section for unwinding info */
 		offset = elf_section_offset(fd, ".eh_frame_hdr");
 		offset = elf_section_offset(fd, ".eh_frame_hdr");
-		dso->data.frame_offset = offset;
+		dso->data.eh_frame_hdr_offset = offset;
 	}
 	}
 
 
 	if (offset)
 	if (offset)
@@ -291,7 +291,7 @@ static int read_unwind_spec_debug_frame(struct dso *dso,
 					struct machine *machine, u64 *offset)
 					struct machine *machine, u64 *offset)
 {
 {
 	int fd;
 	int fd;
-	u64 ofs = dso->data.frame_offset;
+	u64 ofs = dso->data.debug_frame_offset;
 
 
 	if (ofs == 0) {
 	if (ofs == 0) {
 		fd = dso__data_fd(dso, machine);
 		fd = dso__data_fd(dso, machine);
@@ -300,7 +300,7 @@ static int read_unwind_spec_debug_frame(struct dso *dso,
 
 
 		/* Check the .debug_frame section for unwinding info */
 		/* Check the .debug_frame section for unwinding info */
 		ofs = elf_section_offset(fd, ".debug_frame");
 		ofs = elf_section_offset(fd, ".debug_frame");
-		dso->data.frame_offset = ofs;
+		dso->data.debug_frame_offset = ofs;
 	}
 	}
 
 
 	*offset = ofs;
 	*offset = ofs;