Commit 08b3f913 authored by Ingo Molnar's avatar Ingo Molnar

Merge tag 'perf-core-for-mingo' of...

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: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents c80e5c0c 0c8c2077
......@@ -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)$(RM) .config-detected
$(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
$(python-clean)
......
......@@ -22,7 +22,9 @@ static const struct option data_options[] = {
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>]",
NULL
};
......@@ -98,7 +100,7 @@ int cmd_data(int argc, const char **argv, const char *prefix)
if (argc < 2)
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);
if (argc < 1)
goto usage;
......
......@@ -437,7 +437,18 @@ int cmd_help(int argc, const char **argv, const char *prefix __maybe_unused)
HELP_FORMAT_INFO),
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]",
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);
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) {
printf("\n usage: %s\n\n", perf_usage_string);
......
......@@ -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,
"width[,width...]",
"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 "
"columns '.' is reserved."),
OPT_BOOLEAN('U', "hide-unresolved", &report.hide_unresolved,
......
......@@ -1572,7 +1572,8 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
"Show the mmap events"),
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>] record <script> [<record-options>] <command>",
"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();
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);
file.path = input_name;
......
......@@ -1958,7 +1958,8 @@ int cmd_timechart(int argc, const char **argv,
parse_time),
OPT_END()
};
const char * const timechart_usage[] = {
const char * const timechart_subcommands[] = { "record", NULL };
const char *timechart_usage[] = {
"perf timechart [<options>] {record}",
NULL
};
......@@ -1976,8 +1977,8 @@ int cmd_timechart(int argc, const char **argv,
"perf timechart record [<options>]",
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) {
pr_err("-P and -T options cannot be used at the same time.\n");
......
......@@ -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)
{
const char * const trace_usage[] = {
const char *trace_usage[] = {
"perf trace [<options>] [<command>]",
"perf trace [<options>] -- <command> [<options>]",
"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_END()
};
const char * const trace_subcommands[] = { "record", NULL };
int err;
char bf[BUFSIZ];
......@@ -2699,8 +2700,8 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
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) {
trace.opts.sample_address = true;
......
......@@ -15,7 +15,6 @@ $(shell echo -n > .config-detected)
detected = $(shell echo "$(1)=y" >> .config-detected)
detected_var = $(shell echo "$(1)=$($(1))" >> .config-detected)
LIB_INCLUDE := $(srctree)/tools/lib/
CFLAGS := $(EXTRA_CFLAGS) $(EXTRA_WARNINGS)
include $(src-perf)/config/Makefile.arch
......@@ -184,7 +183,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 > $(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
feature_set = $(eval $(feature_set_code))
......@@ -204,7 +203,7 @@ endef
# the rule that uses them - an example for that is the 'bionic'
# feature check. ]
#
CORE_FEATURE_TESTS = \
FEATURE_TESTS = \
backtrace \
dwarf \
fortify-source \
......@@ -227,10 +226,9 @@ CORE_FEATURE_TESTS = \
stackprotector-all \
timerfd \
libdw-dwarf-unwind \
libbabeltrace \
zlib
LIB_FEATURE_TESTS = \
FEATURE_DISPLAY = \
dwarf \
glibc \
gtk2 \
......@@ -243,29 +241,9 @@ LIB_FEATURE_TESTS = \
libslang \
libunwind \
libdw-dwarf-unwind \
libbabeltrace \
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
# mentioned in this list we need to refactor this ;-).
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))
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:
......@@ -289,10 +267,10 @@ ifeq ($(feature-all), 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
$(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
ifeq ($(feature-stackprotector-all), 1)
......@@ -322,7 +300,7 @@ endif
CFLAGS += -I$(src-perf)/util
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
......@@ -688,7 +666,7 @@ ifeq (${IS_64_BIT}, 1)
NO_PERF_READ_VDSO32 := 1
endif
endif
ifneq (${IS_X86_64}, 1)
ifneq ($(ARCH), x86)
NO_PERF_READ_VDSOX32 := 1
endif
ifndef NO_PERF_READ_VDSOX32
......@@ -705,14 +683,15 @@ else
endif
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)
LDFLAGS += $(LIBBABELTRACE_LDFLAGS)
EXTLIBS += -lbabeltrace-ctf
$(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
......@@ -748,7 +727,7 @@ sysconfdir = $(prefix)/etc
ETC_PERFCONFIG = etc/perfconfig
endif
ifndef lib
ifeq ($(IS_X86_64),1)
ifeq ($(ARCH)$(IS_64_BIT), x861)
lib = lib64
else
lib = lib
......@@ -797,8 +776,8 @@ define feature_print_status_code
endif
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)))
endef
......@@ -807,61 +786,63 @@ define feature_print_text_code
MSG = $(shell printf '...%30s: %s' $(1) $(2))
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)
PERF_FEATURES += dwarf-post-unwind($(dwarf-post-unwind-text))
FEATURE_DUMP += dwarf-post-unwind($(dwarf-post-unwind-text))
endif
# The $(display_lib) controls the default detection message
# The $(feature_display) controls the default detection message
# output. It's set if:
# - 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
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
feature_check = $(eval $(feature_check_code))
define feature_check_code
ifneq ($(feature-$(1)), 1)
display_lib := 1
feature_display := 1
endif
endef
$(foreach feat,$(LIB_FEATURE_TESTS),$(call feature_check,$(feat)))
$(foreach feat,$(FEATURE_DISPLAY),$(call feature_check,$(feat)))
ifeq ($(VF),1)
display_lib := 1
display_vf := 1
feature_display := 1
feature_verbose := 1
endif
ifeq ($(display_lib),1)
ifeq ($(feature_display),1)
$(info )
$(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)
$(call feature_print_text,"DWARF post unwind library", $(dwarf-post-unwind-text))
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
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 )
endif
......
......@@ -4,7 +4,7 @@ endif
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/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/ppc.*/powerpc/ -e s/mips.*/mips/ \
-e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ \
......
......@@ -39,12 +39,13 @@ PKG_CONFIG := $(CROSS_COMPILE)pkg-config
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:
$(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:
$(BUILD)
......@@ -156,4 +157,4 @@ test-zlib.bin:
###############################
clean:
rm -f $(FILES) *.d
rm -f $(FILES) *.d $(FILES:.bin=.make.output)
......@@ -98,12 +98,20 @@
#undef main
#define main main_test_pthread_attr_setaffinity_np
# include "test-pthread_attr_setaffinity_np.c"
# include "test-pthread-attr-setaffinity-np.c"
#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
# include "test-libbabeltrace.c"
#undef main
#endif
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_zlib();
main_test_pthread_attr_setaffinity_np();
main_test_libbabeltrace();
return 0;
}
......@@ -47,8 +47,16 @@ __my_reassemble_comp_words_by_ref()
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_
if [ "$1" = "-n" ]; then
......@@ -76,8 +84,16 @@ _get_comp_words_by_ref()
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
# Remove colon-word prefix from COMPREPLY items
......@@ -97,7 +113,32 @@ __perfcomp ()
__perfcomp_colon ()
{
__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 ()
......@@ -107,8 +148,10 @@ __perf_main ()
cmd=${words[0]}
COMPREPLY=()
# Skip options backward and find the last perf command
__perf_prev_skip_opts
# List perf subcommands or long options
if [ $cword -eq 1 ]; then
if [ -z $prev_skip_opts ]; then
if [[ $cur == --* ]]; then
cmds=$($cmd --list-opts)
else
......@@ -116,18 +159,25 @@ __perf_main ()
fi
__perfcomp "$cmds" "$cur"
# 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)
__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
}
......@@ -196,7 +246,11 @@ type perf &>/dev/null &&
_perf()
{
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
} &&
......
......@@ -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)
{
const char * const test_usage[] = {
const char *test_usage[] = {
"perf test [<options>] [{list <test-name-fragment>|[<test-name-fragments>|<test-numbers>]}]",
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)"),
OPT_END()
};
const char * const test_subcommands[] = { "list", NULL };
struct intlist *skiplist = NULL;
int ret = hists__init();
if (ret < 0)
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"))
return perf_test__list(argc, argv);
......
......@@ -5,7 +5,7 @@ include config/Makefile.arch
# FIXME looks like x86 is the only arch running tests ;-)
# we need some IS_(32/64) flag to make this generic
ifeq ($(IS_X86_64),1)
ifeq ($(ARCH)$(IS_64_BIT), x861)
lib = lib64
else
lib = lib
......
......@@ -829,10 +829,16 @@ static int annotate_browser__run(struct annotate_browser *browser,
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,
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,
......
......@@ -1612,28 +1612,30 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
if (!sort__has_sym)
goto add_exit_option;
if (browser->selection == NULL)
goto skip_annotation;
if (sort__mode == SORT_MODE__BRANCH) {
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 &&
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++;
}
if (browser->selection != NULL &&
bi &&
bi->to.sym != NULL &&
if (bi->to.sym != NULL &&
!bi->to.map->dso->annotate_warned &&
(bi->to.sym != bi->from.sym ||
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++;
}
} else {
if (browser->selection != NULL &&
browser->selection->sym != NULL &&
if (browser->selection->sym != NULL &&
!browser->selection->map->dso->annotate_warned) {
struct annotation *notes;
......@@ -1641,11 +1643,12 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
if (notes->src &&
asprintf(&options[nr_options], "Annotate %s",
browser->selection->sym->name) > 0)
browser->selection->sym->name) > 0) {
annotate = nr_options++;
}
}
}
skip_annotation:
if (thread != NULL &&
asprintf(&options[nr_options], "Zoom %s %s(%d) thread",
(browser->hists->thread_filter ? "out of" : "into"),
......@@ -1701,6 +1704,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
if (choice == annotate || choice == annotate_t || choice == annotate_f) {
struct hist_entry *he;
struct annotation *notes;
struct map_symbol ms;
int err;
do_annotate:
if (!objdump_path && perf_session_env__lookup_objdump(env))
......@@ -1710,30 +1714,21 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
if (he == NULL)
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) {
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)
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
* (if they exists) when returning from annotate
......
......@@ -139,7 +139,8 @@ struct dso {
u32 status_seen;
size_t file_size;
struct list_head open_entry;
u64 frame_offset;
u64 debug_frame_offset;
u64 eh_frame_hdr_offset;
} data;
union { /* Tool specific area */
......
......@@ -263,15 +263,9 @@ void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel)
while (next) {
n = rb_entry(next, struct hist_entry, 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 == '.') ||
(zap_kernel && n->level != '.') ||
hists__decay_entry(hists, n)) &&
!n->used) {
hists__decay_entry(hists, n))) {
hists__delete_entry(hists, n);
}
}
......
......@@ -303,6 +303,9 @@ struct hist_browser_timer {
#ifdef HAVE_SLANG_SUPPORT
#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,
struct hist_browser_timer *hbt);
......@@ -321,6 +324,12 @@ int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused,
{
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,
struct perf_evsel *evsel __maybe_unused,
......
......@@ -37,6 +37,7 @@ static int get_value(struct parse_opt_ctx_t *p,
{
const char *s, *arg = NULL;
const int unset = flags & OPT_UNSET;
int err;
if (unset && p->opt)
return opterror(opt, "takes no value", flags);
......@@ -114,13 +115,29 @@ static int get_value(struct parse_opt_ctx_t *p,
return 0;
case OPTION_STRING:
err = 0;
if (unset)
*(const char **)opt->value = NULL;
else if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
*(const char **)opt->value = (const char *)opt->defval;
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:
if (unset)
......
......@@ -40,6 +40,7 @@ enum parse_opt_option_flags {
PARSE_OPT_LASTARG_DEFAULT = 16,
PARSE_OPT_DISABLED = 32,
PARSE_OPT_EXCLUSIVE = 64,
PARSE_OPT_NOEMPTY = 128,
};
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_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_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) \
{ .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) \
......
......@@ -102,7 +102,6 @@ struct hist_entry {
bool init_have_children;
char level;
bool used;
u8 filtered;
char *srcline;
struct symbol *parent;
......
......@@ -266,7 +266,7 @@ static int read_unwind_spec_eh_frame(struct dso *dso, struct machine *machine,
u64 *fde_count)
{
int ret = -EINVAL, fd;
u64 offset = dso->data.frame_offset;
u64 offset = dso->data.eh_frame_hdr_offset;
if (offset == 0) {
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 */
offset = elf_section_offset(fd, ".eh_frame_hdr");
dso->data.frame_offset = offset;
dso->data.eh_frame_hdr_offset = offset;
}
if (offset)
......@@ -291,7 +291,7 @@ static int read_unwind_spec_debug_frame(struct dso *dso,
struct machine *machine, u64 *offset)
{
int fd;
u64 ofs = dso->data.frame_offset;
u64 ofs = dso->data.debug_frame_offset;
if (ofs == 0) {
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 */
ofs = elf_section_offset(fd, ".debug_frame");
dso->data.frame_offset = ofs;
dso->data.debug_frame_offset = ofs;
}
*offset = ofs;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment