diff options
Diffstat (limited to 'tools/perf')
51 files changed, 355 insertions, 843 deletions
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 diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index e323eab10694..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))) @@ -521,7 +523,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/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."), diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 0b3b4e4984b9..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; @@ -1724,7 +1734,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; diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile index e7f83b15fcbf..cd121dfc4de9 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 $(srctree)/tools/build/Makefile.feature ifeq ($(feature-stackprotector-all), 1) CFLAGS += -fstack-protector-all @@ -636,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 @@ -763,80 +679,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_check = $(eval $(feature_check_code)) -define feature_check_code - ifneq ($(feature-$(1)), 1) - feature_display := 1 - endif -endef - -$(foreach feat,$(FEATURE_DISPLAY),$(call feature_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/feature-checks/.gitignore b/tools/perf/config/feature-checks/.gitignore deleted file mode 100644 index 80f3da0c3515..000000000000 --- a/tools/perf/config/feature-checks/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -*.d -*.bin diff --git a/tools/perf/config/feature-checks/Makefile b/tools/perf/config/feature-checks/Makefile deleted file mode 100644 index 0d694a94cda2..000000000000 --- a/tools/perf/config/feature-checks/Makefile +++ /dev/null @@ -1,160 +0,0 @@ - -FILES= \ - test-all.bin \ - test-backtrace.bin \ - test-bionic.bin \ - test-dwarf.bin \ - test-fortify-source.bin \ - test-sync-compare-and-swap.bin \ - test-glibc.bin \ - test-gtk2.bin \ - test-gtk2-infobar.bin \ - test-hello.bin \ - test-libaudit.bin \ - test-libbfd.bin \ - test-liberty.bin \ - test-liberty-z.bin \ - test-cplus-demangle.bin \ - test-libelf.bin \ - test-libelf-getphdrnum.bin \ - test-libelf-mmap.bin \ - test-libnuma.bin \ - test-libperl.bin \ - test-libpython.bin \ - test-libpython-version.bin \ - test-libslang.bin \ - test-libunwind.bin \ - test-libunwind-debug-frame.bin \ - test-pthread-attr-setaffinity-np.bin \ - test-stackprotector-all.bin \ - test-timerfd.bin \ - test-libdw-dwarf-unwind.bin \ - test-libbabeltrace.bin \ - test-compile-32.bin \ - test-compile-x32.bin \ - test-zlib.bin - -CC := $(CROSS_COMPILE)gcc -MD -PKG_CONFIG := $(CROSS_COMPILE)pkg-config - -all: $(FILES) - -__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 - -test-hello.bin: - $(BUILD) - -test-pthread-attr-setaffinity-np.bin: - $(BUILD) -D_GNU_SOURCE -lpthread - -test-stackprotector-all.bin: - $(BUILD) -fstack-protector-all - -test-fortify-source.bin: - $(BUILD) -O2 -D_FORTIFY_SOURCE=2 - -test-bionic.bin: - $(BUILD) - -test-libelf.bin: - $(BUILD) -lelf - -test-glibc.bin: - $(BUILD) - -test-dwarf.bin: - $(BUILD) -ldw - -test-libelf-mmap.bin: - $(BUILD) -lelf - -test-libelf-getphdrnum.bin: - $(BUILD) -lelf - -test-libnuma.bin: - $(BUILD) -lnuma - -test-libunwind.bin: - $(BUILD) -lelf - -test-libunwind-debug-frame.bin: - $(BUILD) -lelf - -test-libaudit.bin: - $(BUILD) -laudit - -test-libslang.bin: - $(BUILD) -I/usr/include/slang -lslang - -test-gtk2.bin: - $(BUILD) $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null) - -test-gtk2-infobar.bin: - $(BUILD) $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null) - -grep-libs = $(filter -l%,$(1)) -strip-libs = $(filter-out -l%,$(1)) - -PERL_EMBED_LDOPTS = $(shell perl -MExtUtils::Embed -e ldopts 2>/dev/null) -PERL_EMBED_LDFLAGS = $(call strip-libs,$(PERL_EMBED_LDOPTS)) -PERL_EMBED_LIBADD = $(call grep-libs,$(PERL_EMBED_LDOPTS)) -PERL_EMBED_CCOPTS = `perl -MExtUtils::Embed -e ccopts 2>/dev/null` -FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS) - -test-libperl.bin: - $(BUILD) $(FLAGS_PERL_EMBED) - -test-libpython.bin: - $(BUILD) - -test-libpython-version.bin: - $(BUILD) - -test-libbfd.bin: - $(BUILD) -DPACKAGE='"perf"' -lbfd -lz -liberty -ldl - -test-liberty.bin: - $(CC) -Wall -Werror -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty - -test-liberty-z.bin: - $(CC) -Wall -Werror -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty -lz - -test-cplus-demangle.bin: - $(BUILD) -liberty - -test-backtrace.bin: - $(BUILD) - -test-timerfd.bin: - $(BUILD) - -test-libdw-dwarf-unwind.bin: - $(BUILD) # -ldw provided by $(FEATURE_CHECK_LDFLAGS-libdw-dwarf-unwind) - -test-libbabeltrace.bin: - $(BUILD) # -lbabeltrace provided by $(FEATURE_CHECK_LDFLAGS-libbabeltrace) - -test-sync-compare-and-swap.bin: - $(BUILD) - -test-compile-32.bin: - $(CC) -m32 -o $(OUTPUT)$@ test-compile.c - -test-compile-x32.bin: - $(CC) -mx32 -o $(OUTPUT)$@ test-compile.c - -test-zlib.bin: - $(BUILD) -lz - --include *.d - -############################### - -clean: - rm -f $(FILES) *.d $(FILES:.bin=.make.output) diff --git a/tools/perf/config/feature-checks/test-all.c b/tools/perf/config/feature-checks/test-all.c deleted file mode 100644 index a61c20456705..000000000000 --- a/tools/perf/config/feature-checks/test-all.c +++ /dev/null @@ -1,143 +0,0 @@ -/* - * test-all.c: Try to build all the main testcases at once. - * - * A well-configured system will have all the prereqs installed, so we can speed - * up auto-detection on such systems. - */ - -/* - * Quirk: Python and Perl headers cannot be in arbitrary places, so keep - * these 3 testcases at the top: - */ -#define main main_test_libpython -# include "test-libpython.c" -#undef main - -#define main main_test_libpython_version -# include "test-libpython-version.c" -#undef main - -#define main main_test_libperl -# include "test-libperl.c" -#undef main - -#define main main_test_hello -# include "test-hello.c" -#undef main - -#define main main_test_libelf -# include "test-libelf.c" -#undef main - -#define main main_test_libelf_mmap -# include "test-libelf-mmap.c" -#undef main - -#define main main_test_glibc -# include "test-glibc.c" -#undef main - -#define main main_test_dwarf -# include "test-dwarf.c" -#undef main - -#define main main_test_libelf_getphdrnum -# include "test-libelf-getphdrnum.c" -#undef main - -#define main main_test_libunwind -# include "test-libunwind.c" -#undef main - -#define main main_test_libaudit -# include "test-libaudit.c" -#undef main - -#define main main_test_libslang -# include "test-libslang.c" -#undef main - -#define main main_test_gtk2 -# include "test-gtk2.c" -#undef main - -#define main main_test_gtk2_infobar -# include "test-gtk2-infobar.c" -#undef main - -#define main main_test_libbfd -# include "test-libbfd.c" -#undef main - -#define main main_test_backtrace -# include "test-backtrace.c" -#undef main - -#define main main_test_libnuma -# include "test-libnuma.c" -#undef main - -#define main main_test_timerfd -# include "test-timerfd.c" -#undef main - -#define main main_test_stackprotector_all -# include "test-stackprotector-all.c" -#undef main - -#define main main_test_libdw_dwarf_unwind -# include "test-libdw-dwarf-unwind.c" -#undef main - -#define main main_test_sync_compare_and_swap -# include "test-sync-compare-and-swap.c" -#undef main - -#define main main_test_zlib -# include "test-zlib.c" -#undef main - -#define main main_test_pthread_attr_setaffinity_np -# 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[]) -{ - main_test_libpython(); - main_test_libpython_version(); - main_test_libperl(); - main_test_hello(); - main_test_libelf(); - main_test_libelf_mmap(); - main_test_glibc(); - main_test_dwarf(); - main_test_libelf_getphdrnum(); - main_test_libunwind(); - main_test_libaudit(); - main_test_libslang(); - main_test_gtk2(argc, argv); - main_test_gtk2_infobar(argc, argv); - main_test_libbfd(); - main_test_backtrace(); - main_test_libnuma(); - main_test_timerfd(); - main_test_stackprotector_all(); - main_test_libdw_dwarf_unwind(); - main_test_sync_compare_and_swap(argc, argv); - main_test_zlib(); - main_test_pthread_attr_setaffinity_np(); - - return 0; -} diff --git a/tools/perf/config/feature-checks/test-backtrace.c b/tools/perf/config/feature-checks/test-backtrace.c deleted file mode 100644 index 7124aa1dc8fb..000000000000 --- a/tools/perf/config/feature-checks/test-backtrace.c +++ /dev/null @@ -1,13 +0,0 @@ -#include <execinfo.h> -#include <stdio.h> - -int main(void) -{ - void *backtrace_fns[10]; - size_t entries; - - entries = backtrace(backtrace_fns, 10); - backtrace_symbols_fd(backtrace_fns, entries, 1); - - return 0; -} diff --git a/tools/perf/config/feature-checks/test-bionic.c b/tools/perf/config/feature-checks/test-bionic.c deleted file mode 100644 index eac24e9513eb..000000000000 --- a/tools/perf/config/feature-checks/test-bionic.c +++ /dev/null @@ -1,6 +0,0 @@ -#include <android/api-level.h> - -int main(void) -{ - return __ANDROID_API__; -} diff --git a/tools/perf/config/feature-checks/test-compile.c b/tools/perf/config/feature-checks/test-compile.c deleted file mode 100644 index 31dbf45bf99c..000000000000 --- a/tools/perf/config/feature-checks/test-compile.c +++ /dev/null @@ -1,4 +0,0 @@ -int main(void) -{ - return 0; -} diff --git a/tools/perf/config/feature-checks/test-cplus-demangle.c b/tools/perf/config/feature-checks/test-cplus-demangle.c deleted file mode 100644 index 610c686e0009..000000000000 --- a/tools/perf/config/feature-checks/test-cplus-demangle.c +++ /dev/null @@ -1,14 +0,0 @@ -extern int printf(const char *format, ...); -extern char *cplus_demangle(const char *, int); - -int main(void) -{ - char symbol[4096] = "FieldName__9ClassNameFd"; - char *tmp; - - tmp = cplus_demangle(symbol, 0); - - printf("demangled symbol: {%s}\n", tmp); - - return 0; -} diff --git a/tools/perf/config/feature-checks/test-dwarf.c b/tools/perf/config/feature-checks/test-dwarf.c deleted file mode 100644 index 3fc1801ce4a9..000000000000 --- a/tools/perf/config/feature-checks/test-dwarf.c +++ /dev/null @@ -1,10 +0,0 @@ -#include <dwarf.h> -#include <elfutils/libdw.h> -#include <elfutils/version.h> - -int main(void) -{ - Dwarf *dbg = dwarf_begin(0, DWARF_C_READ); - - return (long)dbg; -} diff --git a/tools/perf/config/feature-checks/test-fortify-source.c b/tools/perf/config/feature-checks/test-fortify-source.c deleted file mode 100644 index c9f398d87868..000000000000 --- a/tools/perf/config/feature-checks/test-fortify-source.c +++ /dev/null @@ -1,6 +0,0 @@ -#include <stdio.h> - -int main(void) -{ - return puts("hi"); -} diff --git a/tools/perf/config/feature-checks/test-glibc.c b/tools/perf/config/feature-checks/test-glibc.c deleted file mode 100644 index b0820345cd98..000000000000 --- a/tools/perf/config/feature-checks/test-glibc.c +++ /dev/null @@ -1,8 +0,0 @@ -#include <gnu/libc-version.h> - -int main(void) -{ - const char *version = gnu_get_libc_version(); - - return (long)version; -} diff --git a/tools/perf/config/feature-checks/test-gtk2-infobar.c b/tools/perf/config/feature-checks/test-gtk2-infobar.c deleted file mode 100644 index 397b4646d066..000000000000 --- a/tools/perf/config/feature-checks/test-gtk2-infobar.c +++ /dev/null @@ -1,11 +0,0 @@ -#pragma GCC diagnostic ignored "-Wstrict-prototypes" -#include <gtk/gtk.h> -#pragma GCC diagnostic error "-Wstrict-prototypes" - -int main(int argc, char *argv[]) -{ - gtk_init(&argc, &argv); - gtk_info_bar_new(); - - return 0; -} diff --git a/tools/perf/config/feature-checks/test-gtk2.c b/tools/perf/config/feature-checks/test-gtk2.c deleted file mode 100644 index 6bd80e509439..000000000000 --- a/tools/perf/config/feature-checks/test-gtk2.c +++ /dev/null @@ -1,10 +0,0 @@ -#pragma GCC diagnostic ignored "-Wstrict-prototypes" -#include <gtk/gtk.h> -#pragma GCC diagnostic error "-Wstrict-prototypes" - -int main(int argc, char *argv[]) -{ - gtk_init(&argc, &argv); - - return 0; -} diff --git a/tools/perf/config/feature-checks/test-hello.c b/tools/perf/config/feature-checks/test-hello.c deleted file mode 100644 index c9f398d87868..000000000000 --- a/tools/perf/config/feature-checks/test-hello.c +++ /dev/null @@ -1,6 +0,0 @@ -#include <stdio.h> - -int main(void) -{ - return puts("hi"); -} diff --git a/tools/perf/config/feature-checks/test-libaudit.c b/tools/perf/config/feature-checks/test-libaudit.c deleted file mode 100644 index afc019f08641..000000000000 --- a/tools/perf/config/feature-checks/test-libaudit.c +++ /dev/null @@ -1,10 +0,0 @@ -#include <libaudit.h> - -extern int printf(const char *format, ...); - -int main(void) -{ - printf("error message: %s\n", audit_errno_to_name(0)); - - return audit_open(); -} diff --git a/tools/perf/config/feature-checks/test-libbabeltrace.c b/tools/perf/config/feature-checks/test-libbabeltrace.c deleted file mode 100644 index 9cf802a04885..000000000000 --- a/tools/perf/config/feature-checks/test-libbabeltrace.c +++ /dev/null @@ -1,9 +0,0 @@ - -#include <babeltrace/ctf-writer/writer.h> -#include <babeltrace/ctf-ir/stream-class.h> - -int main(void) -{ - bt_ctf_stream_class_get_packet_context_type((void *) 0); - return 0; -} diff --git a/tools/perf/config/feature-checks/test-libbfd.c b/tools/perf/config/feature-checks/test-libbfd.c deleted file mode 100644 index 24059907e990..000000000000 --- a/tools/perf/config/feature-checks/test-libbfd.c +++ /dev/null @@ -1,15 +0,0 @@ -#include <bfd.h> - -extern int printf(const char *format, ...); - -int main(void) -{ - char symbol[4096] = "FieldName__9ClassNameFd"; - char *tmp; - - tmp = bfd_demangle(0, symbol, 0); - - printf("demangled symbol: {%s}\n", tmp); - - return 0; -} diff --git a/tools/perf/config/feature-checks/test-libdw-dwarf-unwind.c b/tools/perf/config/feature-checks/test-libdw-dwarf-unwind.c deleted file mode 100644 index f676a3ff442a..000000000000 --- a/tools/perf/config/feature-checks/test-libdw-dwarf-unwind.c +++ /dev/null @@ -1,13 +0,0 @@ - -#include <elfutils/libdwfl.h> - -int main(void) -{ - /* - * This function is guarded via: __nonnull_attribute__ (1, 2). - * Passing '1' as arguments value. This code is never executed, - * only compiled. - */ - dwfl_thread_getframes((void *) 1, (void *) 1, NULL); - return 0; -} diff --git a/tools/perf/config/feature-checks/test-libelf-getphdrnum.c b/tools/perf/config/feature-checks/test-libelf-getphdrnum.c deleted file mode 100644 index d710459306c3..000000000000 --- a/tools/perf/config/feature-checks/test-libelf-getphdrnum.c +++ /dev/null @@ -1,8 +0,0 @@ -#include <libelf.h> - -int main(void) -{ - size_t dst; - - return elf_getphdrnum(0, &dst); -} diff --git a/tools/perf/config/feature-checks/test-libelf-mmap.c b/tools/perf/config/feature-checks/test-libelf-mmap.c deleted file mode 100644 index 564427d7ef18..000000000000 --- a/tools/perf/config/feature-checks/test-libelf-mmap.c +++ /dev/null @@ -1,8 +0,0 @@ -#include <libelf.h> - -int main(void) -{ - Elf *elf = elf_begin(0, ELF_C_READ_MMAP, 0); - - return (long)elf; -} diff --git a/tools/perf/config/feature-checks/test-libelf.c b/tools/perf/config/feature-checks/test-libelf.c deleted file mode 100644 index 08db322d8957..000000000000 --- a/tools/perf/config/feature-checks/test-libelf.c +++ /dev/null @@ -1,8 +0,0 @@ -#include <libelf.h> - -int main(void) -{ - Elf *elf = elf_begin(0, ELF_C_READ, 0); - - return (long)elf; -} diff --git a/tools/perf/config/feature-checks/test-libnuma.c b/tools/perf/config/feature-checks/test-libnuma.c deleted file mode 100644 index 4763d9cd587d..000000000000 --- a/tools/perf/config/feature-checks/test-libnuma.c +++ /dev/null @@ -1,9 +0,0 @@ -#include <numa.h> -#include <numaif.h> - -int main(void) -{ - numa_available(); - - return 0; -} diff --git a/tools/perf/config/feature-checks/test-libperl.c b/tools/perf/config/feature-checks/test-libperl.c deleted file mode 100644 index 8871f6a0fdb4..000000000000 --- a/tools/perf/config/feature-checks/test-libperl.c +++ /dev/null @@ -1,9 +0,0 @@ -#include <EXTERN.h> -#include <perl.h> - -int main(void) -{ - perl_alloc(); - - return 0; -} diff --git a/tools/perf/config/feature-checks/test-libpython-version.c b/tools/perf/config/feature-checks/test-libpython-version.c deleted file mode 100644 index facea122d812..000000000000 --- a/tools/perf/config/feature-checks/test-libpython-version.c +++ /dev/null @@ -1,10 +0,0 @@ -#include <Python.h> - -#if PY_VERSION_HEX >= 0x03000000 - #error -#endif - -int main(void) -{ - return 0; -} diff --git a/tools/perf/config/feature-checks/test-libpython.c b/tools/perf/config/feature-checks/test-libpython.c deleted file mode 100644 index b24b28ad6324..000000000000 --- a/tools/perf/config/feature-checks/test-libpython.c +++ /dev/null @@ -1,8 +0,0 @@ -#include <Python.h> - -int main(void) -{ - Py_Initialize(); - - return 0; -} diff --git a/tools/perf/config/feature-checks/test-libslang.c b/tools/perf/config/feature-checks/test-libslang.c deleted file mode 100644 index 22ff22ed94d1..000000000000 --- a/tools/perf/config/feature-checks/test-libslang.c +++ /dev/null @@ -1,6 +0,0 @@ -#include <slang.h> - -int main(void) -{ - return SLsmg_init_smg(); -} diff --git a/tools/perf/config/feature-checks/test-libunwind-debug-frame.c b/tools/perf/config/feature-checks/test-libunwind-debug-frame.c deleted file mode 100644 index 0ef8087a104a..000000000000 --- a/tools/perf/config/feature-checks/test-libunwind-debug-frame.c +++ /dev/null @@ -1,16 +0,0 @@ -#include <libunwind.h> -#include <stdlib.h> - -extern int -UNW_OBJ(dwarf_find_debug_frame) (int found, unw_dyn_info_t *di_debug, - unw_word_t ip, unw_word_t segbase, - const char *obj_name, unw_word_t start, - unw_word_t end); - -#define dwarf_find_debug_frame UNW_OBJ(dwarf_find_debug_frame) - -int main(void) -{ - dwarf_find_debug_frame(0, NULL, 0, 0, NULL, 0, 0); - return 0; -} diff --git a/tools/perf/config/feature-checks/test-libunwind.c b/tools/perf/config/feature-checks/test-libunwind.c deleted file mode 100644 index 43b9369bcab7..000000000000 --- a/tools/perf/config/feature-checks/test-libunwind.c +++ /dev/null @@ -1,27 +0,0 @@ -#include <libunwind.h> -#include <stdlib.h> - -extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as, - unw_word_t ip, - unw_dyn_info_t *di, - unw_proc_info_t *pi, - int need_unwind_info, void *arg); - - -#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table) - -static unw_accessors_t accessors; - -int main(void) -{ - unw_addr_space_t addr_space; - - addr_space = unw_create_addr_space(&accessors, 0); - if (addr_space) - return 0; - - unw_init_remote(NULL, addr_space, NULL); - dwarf_search_unwind_table(addr_space, 0, NULL, NULL, 0, NULL); - - return 0; -} diff --git a/tools/perf/config/feature-checks/test-pthread-attr-setaffinity-np.c b/tools/perf/config/feature-checks/test-pthread-attr-setaffinity-np.c deleted file mode 100644 index fdada5e8d454..000000000000 --- a/tools/perf/config/feature-checks/test-pthread-attr-setaffinity-np.c +++ /dev/null @@ -1,17 +0,0 @@ -#include <stdint.h> -#include <pthread.h> -#include <sched.h> - -int main(void) -{ - int ret = 0; - pthread_attr_t thread_attr; - cpu_set_t cs; - - pthread_attr_init(&thread_attr); - CPU_ZERO(&cs); - - ret = pthread_attr_setaffinity_np(&thread_attr, sizeof(cs), &cs); - - return ret; -} diff --git a/tools/perf/config/feature-checks/test-stackprotector-all.c b/tools/perf/config/feature-checks/test-stackprotector-all.c deleted file mode 100644 index c9f398d87868..000000000000 --- a/tools/perf/config/feature-checks/test-stackprotector-all.c +++ /dev/null @@ -1,6 +0,0 @@ -#include <stdio.h> - -int main(void) -{ - return puts("hi"); -} diff --git a/tools/perf/config/feature-checks/test-sync-compare-and-swap.c b/tools/perf/config/feature-checks/test-sync-compare-and-swap.c deleted file mode 100644 index c34d4ca4af56..000000000000 --- a/tools/perf/config/feature-checks/test-sync-compare-and-swap.c +++ /dev/null @@ -1,14 +0,0 @@ -#include <stdint.h> - -volatile uint64_t x; - -int main(int argc, char *argv[]) -{ - uint64_t old, new = argc; - - argv = argv; - do { - old = __sync_val_compare_and_swap(&x, 0, 0); - } while (!__sync_bool_compare_and_swap(&x, old, new)); - return old == new; -} diff --git a/tools/perf/config/feature-checks/test-timerfd.c b/tools/perf/config/feature-checks/test-timerfd.c deleted file mode 100644 index 8c5c083b4d3c..000000000000 --- a/tools/perf/config/feature-checks/test-timerfd.c +++ /dev/null @@ -1,18 +0,0 @@ -/* - * test for timerfd functions used by perf-kvm-stat-live - */ -#include <sys/timerfd.h> - -int main(void) -{ - struct itimerspec new_value; - - int fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK); - if (fd < 0) - return 1; - - if (timerfd_settime(fd, 0, &new_value, NULL) != 0) - return 1; - - return 0; -} diff --git a/tools/perf/config/feature-checks/test-zlib.c b/tools/perf/config/feature-checks/test-zlib.c deleted file mode 100644 index e111fff6240e..000000000000 --- a/tools/perf/config/feature-checks/test-zlib.c +++ /dev/null @@ -1,9 +0,0 @@ -#include <zlib.h> - -int main(void) -{ - z_stream zs; - - inflateInit(&zs); - return 0; -} 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 @@ -167,6 +167,10 @@ static struct test { .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 <stdbool.h> +#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/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); } 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/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; } diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index 814554d1b857..7a7c54b42b41 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -148,6 +148,9 @@ static const struct { #ifdef HAVE_ZLIB_SUPPORT { "gz", gzip_decompress_to_file }, #endif +#ifdef HAVE_LZMA_SUPPORT + { "xz", lzma_decompress_to_file }, +#endif { NULL, NULL }, }; @@ -209,6 +212,72 @@ bool dso__needs_decompress(struct dso *dso) } /* + * 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. */ static LIST_HEAD(dso__data_open); @@ -1002,21 +1071,24 @@ struct dso *dsos__find(const struct dsos *dsos, const char *name, return dso__find_by_longname(&dsos->root, name); } -struct dso *__dsos__findnew(struct dsos *dsos, const char *name) +struct dso *dsos__addnew(struct dsos *dsos, const char *name) { - struct dso *dso = dsos__find(dsos, name, false); + struct dso *dso = dso__new(name); - if (!dso) { - dso = dso__new(name); - if (dso != NULL) { - dsos__add(dsos, dso); - dso__set_basename(dso); - } + 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); + + return dso ? dso : dsos__addnew(dsos, name); +} + size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp, bool (skip)(struct dso *dso, int parm), int parm) { diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h index 408c65f1a757..3c81d8378bc7 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 @@ -250,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); 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 <lzma.h> +#include <stdio.h> +#include <linux/compiler.h> +#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/machine.c b/tools/perf/util/machine.c index 24f8c978cfd4..eb95b883fb44 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -460,30 +460,56 @@ int machine__process_lost_event(struct machine *machine __maybe_unused, return 0; } +static struct dso* +machine__module_dso(struct machine *machine, struct kmod_path *m, + const char *filename) +{ + struct dso *dso; + + dso = dsos__find(&machine->kernel_dsos, m->name, true); + if (!dso) { + dso = dsos__addnew(&machine->kernel_dsos, m->name); + 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 (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; +} + 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 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; - - 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++; + goto out; map_groups__insert(&machine->kmaps, map); + +out: + free(m.name); return map; } @@ -1044,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 + 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; 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 */ |