aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2015-03-27 05:10:47 -0400
committerIngo Molnar <mingo@kernel.org>2015-03-27 05:10:47 -0400
commitb381e63b48a0b6befc7b4e55408c39012a0dcf8c (patch)
tree92e70447e1b0cf721ef40515db6b97cb881c5066 /tools
parent4e6d7c2aa95158315902647963b359b32da5c295 (diff)
parentccd41c86ad4d464d0ed4e48d80759ff85c2115b0 (diff)
Merge branch 'perf/core' into perf/timer, before applying new changes
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools')
-rw-r--r--tools/build/Build.include81
-rw-r--r--tools/build/Documentation/Build.txt139
-rw-r--r--tools/build/Makefile.build130
-rw-r--r--tools/build/Makefile.feature171
-rw-r--r--tools/build/feature/.gitignore (renamed from tools/perf/config/feature-checks/.gitignore)1
-rw-r--r--tools/build/feature/Makefile (renamed from tools/perf/config/feature-checks/Makefile)31
-rw-r--r--tools/build/feature/test-all.c (renamed from tools/perf/config/feature-checks/test-all.c)19
-rw-r--r--tools/build/feature/test-backtrace.c (renamed from tools/perf/config/feature-checks/test-backtrace.c)0
-rw-r--r--tools/build/feature/test-bionic.c (renamed from tools/perf/config/feature-checks/test-bionic.c)0
-rw-r--r--tools/build/feature/test-compile.c (renamed from tools/perf/config/feature-checks/test-compile.c)0
-rw-r--r--tools/build/feature/test-cplus-demangle.c (renamed from tools/perf/config/feature-checks/test-cplus-demangle.c)0
-rw-r--r--tools/build/feature/test-dwarf.c (renamed from tools/perf/config/feature-checks/test-dwarf.c)0
-rw-r--r--tools/build/feature/test-fortify-source.c (renamed from tools/perf/config/feature-checks/test-fortify-source.c)0
-rw-r--r--tools/build/feature/test-glibc.c (renamed from tools/perf/config/feature-checks/test-glibc.c)0
-rw-r--r--tools/build/feature/test-gtk2-infobar.c (renamed from tools/perf/config/feature-checks/test-gtk2-infobar.c)0
-rw-r--r--tools/build/feature/test-gtk2.c (renamed from tools/perf/config/feature-checks/test-gtk2.c)0
-rw-r--r--tools/build/feature/test-hello.c (renamed from tools/perf/config/feature-checks/test-hello.c)0
-rw-r--r--tools/build/feature/test-libaudit.c (renamed from tools/perf/config/feature-checks/test-libaudit.c)0
-rw-r--r--tools/build/feature/test-libbabeltrace.c9
-rw-r--r--tools/build/feature/test-libbfd.c (renamed from tools/perf/config/feature-checks/test-libbfd.c)0
-rw-r--r--tools/build/feature/test-libdw-dwarf-unwind.c (renamed from tools/perf/config/feature-checks/test-libdw-dwarf-unwind.c)0
-rw-r--r--tools/build/feature/test-libelf-getphdrnum.c (renamed from tools/perf/config/feature-checks/test-libelf-getphdrnum.c)0
-rw-r--r--tools/build/feature/test-libelf-mmap.c (renamed from tools/perf/config/feature-checks/test-libelf-mmap.c)0
-rw-r--r--tools/build/feature/test-libelf.c (renamed from tools/perf/config/feature-checks/test-libelf.c)0
-rw-r--r--tools/build/feature/test-libnuma.c (renamed from tools/perf/config/feature-checks/test-libnuma.c)0
-rw-r--r--tools/build/feature/test-libperl.c (renamed from tools/perf/config/feature-checks/test-libperl.c)0
-rw-r--r--tools/build/feature/test-libpython-version.c (renamed from tools/perf/config/feature-checks/test-libpython-version.c)0
-rw-r--r--tools/build/feature/test-libpython.c (renamed from tools/perf/config/feature-checks/test-libpython.c)0
-rw-r--r--tools/build/feature/test-libslang.c (renamed from tools/perf/config/feature-checks/test-libslang.c)0
-rw-r--r--tools/build/feature/test-libunwind-debug-frame.c (renamed from tools/perf/config/feature-checks/test-libunwind-debug-frame.c)0
-rw-r--r--tools/build/feature/test-libunwind.c (renamed from tools/perf/config/feature-checks/test-libunwind.c)0
-rw-r--r--tools/build/feature/test-lzma.c10
-rw-r--r--tools/build/feature/test-pthread-attr-setaffinity-np.c (renamed from tools/perf/config/feature-checks/test-pthread-attr-setaffinity-np.c)4
-rw-r--r--tools/build/feature/test-stackprotector-all.c (renamed from tools/perf/config/feature-checks/test-stackprotector-all.c)0
-rw-r--r--tools/build/feature/test-sync-compare-and-swap.c (renamed from tools/perf/config/feature-checks/test-sync-compare-and-swap.c)0
-rw-r--r--tools/build/feature/test-timerfd.c (renamed from tools/perf/config/feature-checks/test-timerfd.c)0
-rw-r--r--tools/build/feature/test-zlib.c (renamed from tools/perf/config/feature-checks/test-zlib.c)0
-rw-r--r--tools/build/tests/ex/Build8
-rw-r--r--tools/build/tests/ex/Makefile23
-rw-r--r--tools/build/tests/ex/a.c5
-rw-r--r--tools/build/tests/ex/arch/Build2
-rw-r--r--tools/build/tests/ex/arch/e.c5
-rw-r--r--tools/build/tests/ex/arch/f.c5
-rw-r--r--tools/build/tests/ex/b.c5
-rw-r--r--tools/build/tests/ex/c.c5
-rw-r--r--tools/build/tests/ex/d.c5
-rw-r--r--tools/build/tests/ex/empty/Build0
-rw-r--r--tools/build/tests/ex/ex.c19
-rwxr-xr-xtools/build/tests/run.sh42
-rw-r--r--tools/lib/api/Build2
-rw-r--r--tools/lib/api/Makefile58
-rw-r--r--tools/lib/api/fd/Build1
-rw-r--r--tools/lib/api/fs/Build4
-rw-r--r--tools/lib/api/fs/debugfs.c69
-rw-r--r--tools/lib/api/fs/debugfs.h13
-rw-r--r--tools/lib/api/fs/findfs.c63
-rw-r--r--tools/lib/api/fs/findfs.h23
-rw-r--r--tools/lib/api/fs/tracefs.c78
-rw-r--r--tools/lib/api/fs/tracefs.h21
-rw-r--r--tools/lib/lockdep/Build1
-rw-r--r--tools/lib/lockdep/Makefile132
-rw-r--r--tools/lib/traceevent/Build17
-rw-r--r--tools/lib/traceevent/Makefile169
-rw-r--r--tools/lib/traceevent/event-parse.c288
-rw-r--r--tools/lib/traceevent/event-parse.h24
-rw-r--r--tools/lib/traceevent/event-plugin.c60
-rw-r--r--tools/lib/traceevent/kbuffer-parse.c12
-rw-r--r--tools/lib/traceevent/kbuffer.h1
-rw-r--r--tools/lib/traceevent/parse-filter.c2
-rw-r--r--tools/lib/traceevent/trace-seq.c13
-rw-r--r--tools/perf/.gitignore1
-rw-r--r--tools/perf/Build44
-rw-r--r--tools/perf/Documentation/Build.txt49
-rw-r--r--tools/perf/Documentation/perf-buildid-cache.txt24
-rw-r--r--tools/perf/Documentation/perf-data.txt40
-rw-r--r--tools/perf/Documentation/perf-diff.txt8
-rw-r--r--tools/perf/Documentation/perf-kmem.txt4
-rw-r--r--tools/perf/Documentation/perf-list.txt6
-rw-r--r--tools/perf/Documentation/perf-probe.txt16
-rw-r--r--tools/perf/Documentation/perf-record.txt23
-rw-r--r--tools/perf/Documentation/perf-report.txt5
-rw-r--r--tools/perf/Documentation/perf-script.txt6
-rw-r--r--tools/perf/Documentation/perf-trace.txt6
-rw-r--r--tools/perf/Documentation/perf.txt7
-rw-r--r--tools/perf/MANIFEST1
-rw-r--r--tools/perf/Makefile4
-rw-r--r--tools/perf/Makefile.perf622
-rw-r--r--tools/perf/arch/Build2
-rw-r--r--tools/perf/arch/arm/Build2
-rw-r--r--tools/perf/arch/arm/Makefile11
-rw-r--r--tools/perf/arch/arm/tests/Build2
-rw-r--r--tools/perf/arch/arm/util/Build4
-rw-r--r--tools/perf/arch/arm64/Build1
-rw-r--r--tools/perf/arch/arm64/Makefile4
-rw-r--r--tools/perf/arch/arm64/util/Build2
-rw-r--r--tools/perf/arch/powerpc/Build1
-rw-r--r--tools/perf/arch/powerpc/Makefile3
-rw-r--r--tools/perf/arch/powerpc/util/Build4
-rw-r--r--tools/perf/arch/s390/Build1
-rw-r--r--tools/perf/arch/s390/Makefile3
-rw-r--r--tools/perf/arch/s390/util/Build4
-rw-r--r--tools/perf/arch/sh/Build1
-rw-r--r--tools/perf/arch/sh/Makefile1
-rw-r--r--tools/perf/arch/sh/util/Build1
-rw-r--r--tools/perf/arch/sparc/Build1
-rw-r--r--tools/perf/arch/sparc/Makefile1
-rw-r--r--tools/perf/arch/sparc/util/Build1
-rw-r--r--tools/perf/arch/x86/Build2
-rw-r--r--tools/perf/arch/x86/Makefile15
-rw-r--r--tools/perf/arch/x86/tests/Build2
-rw-r--r--tools/perf/arch/x86/util/Build8
-rw-r--r--tools/perf/bench/Build11
-rw-r--r--tools/perf/builtin-annotate.c2
-rw-r--r--tools/perf/builtin-buildid-cache.c107
-rw-r--r--tools/perf/builtin-buildid-list.c2
-rw-r--r--tools/perf/builtin-data.c121
-rw-r--r--tools/perf/builtin-diff.c6
-rw-r--r--tools/perf/builtin-help.c17
-rw-r--r--tools/perf/builtin-inject.c15
-rw-r--r--tools/perf/builtin-kmem.c28
-rw-r--r--tools/perf/builtin-kvm.c13
-rw-r--r--tools/perf/builtin-list.c28
-rw-r--r--tools/perf/builtin-lock.c2
-rw-r--r--tools/perf/builtin-mem.c4
-rw-r--r--tools/perf/builtin-record.c17
-rw-r--r--tools/perf/builtin-report.c14
-rw-r--r--tools/perf/builtin-sched.c34
-rw-r--r--tools/perf/builtin-script.c11
-rw-r--r--tools/perf/builtin-stat.c98
-rw-r--r--tools/perf/builtin-timechart.c9
-rw-r--r--tools/perf/builtin-top.c10
-rw-r--r--tools/perf/builtin-trace.c278
-rw-r--r--tools/perf/builtin.h1
-rw-r--r--tools/perf/command-list.txt1
-rw-r--r--tools/perf/config/Makefile294
-rw-r--r--tools/perf/config/Makefile.arch29
-rw-r--r--tools/perf/config/utilities.mak3
-rw-r--r--tools/perf/perf-completion.sh94
-rw-r--r--tools/perf/perf.c29
-rw-r--r--tools/perf/perf.h3
-rw-r--r--tools/perf/scripts/Build2
-rw-r--r--tools/perf/scripts/perl/Perf-Trace-Util/Build3
-rw-r--r--tools/perf/scripts/python/Perf-Trace-Util/Build3
-rw-r--r--tools/perf/tests/Build43
-rw-r--r--tools/perf/tests/builtin-test.c9
-rw-r--r--tools/perf/tests/dso-data.c22
-rw-r--r--tools/perf/tests/kmod-path.c73
-rw-r--r--tools/perf/tests/make2
-rw-r--r--tools/perf/tests/open-syscall-all-cpus.c7
-rw-r--r--tools/perf/tests/open-syscall.c7
-rw-r--r--tools/perf/tests/parse-events.c13
-rw-r--r--tools/perf/tests/tests.h1
-rw-r--r--tools/perf/ui/Build14
-rw-r--r--tools/perf/ui/browsers/Build10
-rw-r--r--tools/perf/ui/browsers/annotate.c8
-rw-r--r--tools/perf/ui/browsers/hists.c88
-rw-r--r--tools/perf/ui/gtk/Build9
-rw-r--r--tools/perf/ui/tui/Build4
-rw-r--r--tools/perf/util/Build145
-rw-r--r--tools/perf/util/annotate.c32
-rw-r--r--tools/perf/util/build-id.c207
-rw-r--r--tools/perf/util/build-id.h8
-rw-r--r--tools/perf/util/cache.h1
-rw-r--r--tools/perf/util/callchain.c8
-rw-r--r--tools/perf/util/callchain.h1
-rw-r--r--tools/perf/util/cloexec.c6
-rw-r--r--tools/perf/util/cloexec.h6
-rw-r--r--tools/perf/util/data-convert-bt.c856
-rw-r--r--tools/perf/util/data-convert-bt.h8
-rw-r--r--tools/perf/util/debug.c2
-rw-r--r--tools/perf/util/debug.h1
-rw-r--r--tools/perf/util/dso.c159
-rw-r--r--tools/perf/util/dso.h49
-rw-r--r--tools/perf/util/dwarf-aux.c15
-rw-r--r--tools/perf/util/dwarf-aux.h3
-rw-r--r--tools/perf/util/event.c36
-rw-r--r--tools/perf/util/evlist.c41
-rw-r--r--tools/perf/util/evlist.h5
-rw-r--r--tools/perf/util/evsel.c29
-rw-r--r--tools/perf/util/evsel.h4
-rw-r--r--tools/perf/util/header.c2
-rw-r--r--tools/perf/util/hist.c11
-rw-r--r--tools/perf/util/hist.h11
-rw-r--r--tools/perf/util/lzma.c95
-rw-r--r--tools/perf/util/machine.c301
-rw-r--r--tools/perf/util/machine.h1
-rw-r--r--tools/perf/util/ordered-events.c62
-rw-r--r--tools/perf/util/ordered-events.h27
-rw-r--r--tools/perf/util/parse-events.c234
-rw-r--r--tools/perf/util/parse-events.h13
-rw-r--r--tools/perf/util/parse-options.c32
-rw-r--r--tools/perf/util/parse-options.h2
-rw-r--r--tools/perf/util/probe-event.c365
-rw-r--r--tools/perf/util/probe-finder.c17
-rw-r--r--tools/perf/util/python-ext-sources1
-rw-r--r--tools/perf/util/scripting-engines/Build6
-rw-r--r--tools/perf/util/scripting-engines/trace-event-perl.c5
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c5
-rw-r--r--tools/perf/util/session.c305
-rw-r--r--tools/perf/util/session.h17
-rw-r--r--tools/perf/util/setup.py2
-rw-r--r--tools/perf/util/sort.c9
-rw-r--r--tools/perf/util/sort.h2
-rw-r--r--tools/perf/util/symbol-elf.c71
-rw-r--r--tools/perf/util/symbol-minimal.c7
-rw-r--r--tools/perf/util/symbol.c31
-rw-r--r--tools/perf/util/symbol.h8
-rw-r--r--tools/perf/util/target.c7
-rw-r--r--tools/perf/util/thread.c15
-rw-r--r--tools/perf/util/thread.h24
-rw-r--r--tools/perf/util/tool.h8
-rw-r--r--tools/perf/util/trace-event-parse.c12
-rw-r--r--tools/perf/util/trace-event.h3
-rw-r--r--tools/perf/util/unwind-libunwind.c8
-rw-r--r--tools/perf/util/util.c67
-rw-r--r--tools/perf/util/util.h6
216 files changed, 5636 insertions, 2090 deletions
diff --git a/tools/build/Build.include b/tools/build/Build.include
new file mode 100644
index 000000000000..4c8daaccb82a
--- /dev/null
+++ b/tools/build/Build.include
@@ -0,0 +1,81 @@
1###
2# build: Generic definitions
3#
4# Lots of this code have been borrowed or heavily inspired from parts
5# of kbuild code, which is not credited, but mostly developed by:
6#
7# Copyright (C) Sam Ravnborg <sam@mars.ravnborg.org>, 2015
8# Copyright (C) Linus Torvalds <torvalds@linux-foundation.org>, 2015
9#
10
11###
12# Convenient variables
13comma := ,
14squote := '
15
16###
17# Name of target with a '.' as filename prefix. foo/bar.o => foo/.bar.o
18dot-target = $(dir $@).$(notdir $@)
19
20###
21# filename of target with directory and extension stripped
22basetarget = $(basename $(notdir $@))
23
24###
25# The temporary file to save gcc -MD generated dependencies must not
26# contain a comma
27depfile = $(subst $(comma),_,$(dot-target).d)
28
29###
30# Check if both arguments has same arguments. Result is empty string if equal.
31arg-check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \
32 $(filter-out $(cmd_$@), $(cmd_$(1))) )
33
34###
35# Escape single quote for use in echo statements
36escsq = $(subst $(squote),'\$(squote)',$1)
37
38# Echo command
39# Short version is used, if $(quiet) equals `quiet_', otherwise full one.
40echo-cmd = $(if $($(quiet)cmd_$(1)),\
41 echo ' $(call escsq,$($(quiet)cmd_$(1)))';)
42
43###
44# Replace >$< with >$$< to preserve $ when reloading the .cmd file
45# (needed for make)
46# Replace >#< with >\#< to avoid starting a comment in the .cmd file
47# (needed for make)
48# Replace >'< with >'\''< to be able to enclose the whole string in '...'
49# (needed for the shell)
50make-cmd = $(call escsq,$(subst \#,\\\#,$(subst $$,$$$$,$(cmd_$(1)))))
51
52###
53# Find any prerequisites that is newer than target or that does not exist.
54# PHONY targets skipped in both cases.
55any-prereq = $(filter-out $(PHONY),$?) $(filter-out $(PHONY) $(wildcard $^),$^)
56
57###
58# if_changed_dep - execute command if any prerequisite is newer than
59# target, or command line has changed and update
60# dependencies in the cmd file
61if_changed_dep = $(if $(strip $(any-prereq) $(arg-check)), \
62 @set -e; \
63 $(echo-cmd) $(cmd_$(1)); \
64 cat $(depfile) > $(dot-target).cmd; \
65 printf '%s\n' 'cmd_$@ := $(make-cmd)' >> $(dot-target).cmd)
66
67# if_changed - execute command if any prerequisite is newer than
68# target, or command line has changed
69if_changed = $(if $(strip $(any-prereq) $(arg-check)), \
70 @set -e; \
71 $(echo-cmd) $(cmd_$(1)); \
72 printf '%s\n' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd)
73
74###
75# C flags to be used in rule definitions, includes:
76# - depfile generation
77# - global $(CFLAGS)
78# - per target C flags
79# - per object C flags
80# - BUILD_STR macro to allow '-D"$(variable)"' constructs
81c_flags = -Wp,-MD,$(depfile),-MT,$@ $(CFLAGS) -D"BUILD_STR(s)=\#s" $(CFLAGS_$(basetarget).o) $(CFLAGS_$(obj))
diff --git a/tools/build/Documentation/Build.txt b/tools/build/Documentation/Build.txt
new file mode 100644
index 000000000000..00ad2d608727
--- /dev/null
+++ b/tools/build/Documentation/Build.txt
@@ -0,0 +1,139 @@
1Build Framework
2===============
3
4The perf build framework was adopted from the kernel build system, hence the
5idea and the way how objects are built is the same.
6
7Basically the user provides set of 'Build' files that list objects and
8directories to nest for specific target to be build.
9
10Unlike the kernel we don't have a single build object 'obj-y' list that where
11we setup source objects, but we support more. This allows one 'Build' file to
12carry a sources list for multiple build objects.
13
14a) Build framework makefiles
15----------------------------
16
17The build framework consists of 2 Makefiles:
18
19 Build.include
20 Makefile.build
21
22While the 'Build.include' file contains just some generic definitions, the
23'Makefile.build' file is the makefile used from the outside. It's
24interface/usage is following:
25
26 $ make -f tools/build/Makefile srctree=$(KSRC) dir=$(DIR) obj=$(OBJECT)
27
28where:
29
30 KSRC - is the path to kernel sources
31 DIR - is the path to the project to be built
32 OBJECT - is the name of the build object
33
34When succefully finished the $(DIR) directory contains the final object file
35called $(OBJECT)-in.o:
36
37 $ ls $(DIR)/$(OBJECT)-in.o
38
39which includes all compiled sources described in 'Build' makefiles.
40
41a) Build makefiles
42------------------
43
44The user supplies 'Build' makefiles that contains a objects list, and connects
45the build to nested directories.
46
47Assume we have the following project structure:
48
49 ex/a.c
50 /b.c
51 /c.c
52 /d.c
53 /arch/e.c
54 /arch/f.c
55
56Out of which you build the 'ex' binary ' and the 'libex.a' library:
57
58 'ex' - consists of 'a.o', 'b.o' and libex.a
59 'libex.a' - consists of 'c.o', 'd.o', 'e.o' and 'f.o'
60
61The build framework does not create the 'ex' and 'libex.a' binaries for you, it
62only prepares proper objects to be compiled and grouped together.
63
64To follow the above example, the user provides following 'Build' files:
65
66 ex/Build:
67 ex-y += a.o
68 ex-y += b.o
69
70 libex-y += c.o
71 libex-y += d.o
72 libex-y += arch/
73
74 ex/arch/Build:
75 libex-y += e.o
76 libex-y += f.o
77
78and runs:
79
80 $ make -f tools/build/Makefile.build dir=. obj=ex
81 $ make -f tools/build/Makefile.build dir=. obj=libex
82
83which creates the following objects:
84
85 ex/ex-in.o
86 ex/libex-in.o
87
88that contain request objects names in Build files.
89
90It's only a matter of 2 single commands to create the final binaries:
91
92 $ ar rcs libex.a libex-in.o
93 $ gcc -o ex ex-in.o libex.a
94
95You can check the 'ex' example in 'tools/build/tests/ex' for more details.
96
97b) Rules
98--------
99
100The build framework provides standard compilation rules to handle .S and .c
101compilation.
102
103It's possible to include special rule if needed (like we do for flex or bison
104code generation).
105
106c) CFLAGS
107---------
108
109It's possible to alter the standard object C flags in the following way:
110
111 CFLAGS_perf.o += '...' - alters CFLAGS for perf.o object
112 CFLAGS_gtk += '...' - alters CFLAGS for gtk build object
113
114This C flags changes has the scope of the Build makefile they are defined in.
115
116
117d) Dependencies
118---------------
119
120For each built object file 'a.o' the '.a.cmd' is created and holds:
121
122 - Command line used to built that object
123 (for each object)
124
125 - Dependency rules generated by 'gcc -Wp,-MD,...'
126 (for compiled object)
127
128All existing '.cmd' files are included in the Build process to follow properly
129the dependencies and trigger a rebuild when necessary.
130
131
132e) Single rules
133---------------
134
135It's possible to build single object file by choice, like:
136
137 $ make util/map.o # objects
138 $ make util/map.i # preprocessor
139 $ make util/map.s # assembly
diff --git a/tools/build/Makefile.build b/tools/build/Makefile.build
new file mode 100644
index 000000000000..10df57237a66
--- /dev/null
+++ b/tools/build/Makefile.build
@@ -0,0 +1,130 @@
1###
2# Main build makefile.
3#
4# Lots of this code have been borrowed or heavily inspired from parts
5# of kbuild code, which is not credited, but mostly developed by:
6#
7# Copyright (C) Sam Ravnborg <sam@mars.ravnborg.org>, 2015
8# Copyright (C) Linus Torvalds <torvalds@linux-foundation.org>, 2015
9#
10
11PHONY := __build
12__build:
13
14ifeq ($(V),1)
15 quiet =
16 Q =
17else
18 quiet=quiet_
19 Q=@
20endif
21
22build-dir := $(srctree)/tools/build
23
24# Generic definitions
25include $(build-dir)/Build.include
26
27# do not force detected configuration
28-include .config-detected
29
30# Init all relevant variables used in build files so
31# 1) they have correct type
32# 2) they do not inherit any value from the environment
33subdir-y :=
34obj-y :=
35subdir-y :=
36subdir-obj-y :=
37
38# Build definitions
39build-file := $(dir)/Build
40include $(build-file)
41
42quiet_cmd_flex = FLEX $@
43quiet_cmd_bison = BISON $@
44
45# Create directory unless it exists
46quiet_cmd_mkdir = MKDIR $(dir $@)
47 cmd_mkdir = mkdir -p $(dir $@)
48 rule_mkdir = $(if $(wildcard $(dir $@)),,@$(call echo-cmd,mkdir) $(cmd_mkdir))
49
50# Compile command
51quiet_cmd_cc_o_c = CC $@
52 cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<
53
54quiet_cmd_cc_i_c = CPP $@
55 cmd_cc_i_c = $(CC) $(c_flags) -E -o $@ $<
56
57quiet_cmd_cc_s_c = AS $@
58 cmd_cc_s_c = $(CC) $(c_flags) -S -o $@ $<
59
60# Link agregate command
61# If there's nothing to link, create empty $@ object.
62quiet_cmd_ld_multi = LD $@
63 cmd_ld_multi = $(if $(strip $(obj-y)),\
64 $(LD) -r -o $@ $(obj-y),rm -f $@; $(AR) rcs $@)
65
66# Build rules
67$(OUTPUT)%.o: %.c FORCE
68 $(call rule_mkdir)
69 $(call if_changed_dep,cc_o_c)
70
71$(OUTPUT)%.o: %.S FORCE
72 $(call rule_mkdir)
73 $(call if_changed_dep,cc_o_c)
74
75$(OUTPUT)%.i: %.c FORCE
76 $(call rule_mkdir)
77 $(call if_changed_dep,cc_i_c)
78
79$(OUTPUT)%.i: %.S FORCE
80 $(call rule_mkdir)
81 $(call if_changed_dep,cc_i_c)
82
83$(OUTPUT)%.s: %.c FORCE
84 $(call rule_mkdir)
85 $(call if_changed_dep,cc_s_c)
86
87# Gather build data:
88# obj-y - list of build objects
89# subdir-y - list of directories to nest
90# subdir-obj-y - list of directories objects 'dir/$(obj)-in.o'
91obj-y := $($(obj)-y)
92subdir-y := $(patsubst %/,%,$(filter %/, $(obj-y)))
93obj-y := $(patsubst %/, %/$(obj)-in.o, $(obj-y))
94subdir-obj-y := $(filter %/$(obj)-in.o, $(obj-y))
95
96# '$(OUTPUT)/dir' prefix to all objects
97prefix := $(subst ./,,$(OUTPUT)$(dir)/)
98obj-y := $(addprefix $(prefix),$(obj-y))
99subdir-obj-y := $(addprefix $(prefix),$(subdir-obj-y))
100
101# Final '$(obj)-in.o' object
102in-target := $(prefix)$(obj)-in.o
103
104PHONY += $(subdir-y)
105
106$(subdir-y):
107 $(Q)$(MAKE) -f $(build-dir)/Makefile.build dir=$(dir)/$@ obj=$(obj)
108
109$(sort $(subdir-obj-y)): $(subdir-y) ;
110
111$(in-target): $(obj-y) FORCE
112 $(call rule_mkdir)
113 $(call if_changed,ld_multi)
114
115__build: $(in-target)
116 @:
117
118PHONY += FORCE
119FORCE:
120
121# Include all cmd files to get all the dependency rules
122# for all objects included
123targets := $(wildcard $(sort $(obj-y) $(in-target) $(MAKECMDGOALS)))
124cmd_files := $(wildcard $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd))
125
126ifneq ($(cmd_files),)
127 include $(cmd_files)
128endif
129
130.PHONY: $(PHONY)
diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature
new file mode 100644
index 000000000000..3a0b0ca2a28c
--- /dev/null
+++ b/tools/build/Makefile.feature
@@ -0,0 +1,171 @@
1feature_dir := $(srctree)/tools/build/feature
2
3ifneq ($(OUTPUT),)
4 OUTPUT_FEATURES = $(OUTPUT)feature/
5 $(shell mkdir -p $(OUTPUT_FEATURES))
6endif
7
8feature_check = $(eval $(feature_check_code))
9define feature_check_code
10 feature-$(1) := $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS) $(FEATURE_CHECK_CFLAGS-$(1))" LDFLAGS="$(LDFLAGS) $(FEATURE_CHECK_LDFLAGS-$(1))" -C $(feature_dir) test-$1.bin >/dev/null 2>/dev/null && echo 1 || echo 0)
11endef
12
13feature_set = $(eval $(feature_set_code))
14define feature_set_code
15 feature-$(1) := 1
16endef
17
18#
19# Build the feature check binaries in parallel, ignore errors, ignore return value and suppress output:
20#
21
22#
23# Note that this is not a complete list of all feature tests, just
24# those that are typically built on a fully configured system.
25#
26# [ Feature tests not mentioned here have to be built explicitly in
27# the rule that uses them - an example for that is the 'bionic'
28# feature check. ]
29#
30FEATURE_TESTS = \
31 backtrace \
32 dwarf \
33 fortify-source \
34 sync-compare-and-swap \
35 glibc \
36 gtk2 \
37 gtk2-infobar \
38 libaudit \
39 libbfd \
40 libelf \
41 libelf-getphdrnum \
42 libelf-mmap \
43 libnuma \
44 libperl \
45 libpython \
46 libpython-version \
47 libslang \
48 libunwind \
49 pthread-attr-setaffinity-np \
50 stackprotector-all \
51 timerfd \
52 libdw-dwarf-unwind \
53 zlib \
54 lzma
55
56FEATURE_DISPLAY = \
57 dwarf \
58 glibc \
59 gtk2 \
60 libaudit \
61 libbfd \
62 libelf \
63 libnuma \
64 libperl \
65 libpython \
66 libslang \
67 libunwind \
68 libdw-dwarf-unwind \
69 zlib \
70 lzma
71
72# Set FEATURE_CHECK_(C|LD)FLAGS-all for all FEATURE_TESTS features.
73# If in the future we need per-feature checks/flags for features not
74# mentioned in this list we need to refactor this ;-).
75set_test_all_flags = $(eval $(set_test_all_flags_code))
76define set_test_all_flags_code
77 FEATURE_CHECK_CFLAGS-all += $(FEATURE_CHECK_CFLAGS-$(1))
78 FEATURE_CHECK_LDFLAGS-all += $(FEATURE_CHECK_LDFLAGS-$(1))
79endef
80
81$(foreach feat,$(FEATURE_TESTS),$(call set_test_all_flags,$(feat)))
82
83#
84# Special fast-path for the 'all features are available' case:
85#
86$(call feature_check,all,$(MSG))
87
88#
89# Just in case the build freshly failed, make sure we print the
90# feature matrix:
91#
92ifeq ($(feature-all), 1)
93 #
94 # test-all.c passed - just set all the core feature flags to 1:
95 #
96 $(foreach feat,$(FEATURE_TESTS),$(call feature_set,$(feat)))
97else
98 $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS)" LDFLAGS=$(LDFLAGS) -i -j -C $(feature_dir) $(addsuffix .bin,$(FEATURE_TESTS)) >/dev/null 2>&1)
99 $(foreach feat,$(FEATURE_TESTS),$(call feature_check,$(feat)))
100endif
101
102#
103# Print the result of the feature test:
104#
105feature_print_status = $(eval $(feature_print_status_code)) $(info $(MSG))
106
107define feature_print_status_code
108 ifeq ($(feature-$(1)), 1)
109 MSG = $(shell printf '...%30s: [ \033[32mon\033[m ]' $(1))
110 else
111 MSG = $(shell printf '...%30s: [ \033[31mOFF\033[m ]' $(1))
112 endif
113endef
114
115feature_print_text = $(eval $(feature_print_text_code)) $(info $(MSG))
116define feature_print_text_code
117 MSG = $(shell printf '...%30s: %s' $(1) $(2))
118endef
119
120FEATURE_DUMP := $(foreach feat,$(FEATURE_DISPLAY),feature-$(feat)($(feature-$(feat))))
121FEATURE_DUMP_FILE := $(shell touch $(OUTPUT)FEATURE-DUMP; cat $(OUTPUT)FEATURE-DUMP)
122
123ifeq ($(dwarf-post-unwind),1)
124 FEATURE_DUMP += dwarf-post-unwind($(dwarf-post-unwind-text))
125endif
126
127# The $(feature_display) controls the default detection message
128# output. It's set if:
129# - detected features differes from stored features from
130# last build (in FEATURE-DUMP file)
131# - one of the $(FEATURE_DISPLAY) is not detected
132# - VF is enabled
133
134ifneq ("$(FEATURE_DUMP)","$(FEATURE_DUMP_FILE)")
135 $(shell echo "$(FEATURE_DUMP)" > $(OUTPUT)FEATURE-DUMP)
136 feature_display := 1
137endif
138
139feature_display_check = $(eval $(feature_check_code))
140define feature_display_check_code
141 ifneq ($(feature-$(1)), 1)
142 feature_display := 1
143 endif
144endef
145
146$(foreach feat,$(FEATURE_DISPLAY),$(call feature_display_check,$(feat)))
147
148ifeq ($(VF),1)
149 feature_display := 1
150 feature_verbose := 1
151endif
152
153ifeq ($(feature_display),1)
154 $(info )
155 $(info Auto-detecting system features:)
156 $(foreach feat,$(FEATURE_DISPLAY),$(call feature_print_status,$(feat),))
157
158 ifeq ($(dwarf-post-unwind),1)
159 $(call feature_print_text,"DWARF post unwind library", $(dwarf-post-unwind-text))
160 endif
161
162 ifneq ($(feature_verbose),1)
163 $(info )
164 endif
165endif
166
167ifeq ($(feature_verbose),1)
168 TMP := $(filter-out $(FEATURE_DISPLAY),$(FEATURE_TESTS))
169 $(foreach feat,$(TMP),$(call feature_print_status,$(feat),))
170 $(info )
171endif
diff --git a/tools/perf/config/feature-checks/.gitignore b/tools/build/feature/.gitignore
index 80f3da0c3515..09b335b98842 100644
--- a/tools/perf/config/feature-checks/.gitignore
+++ b/tools/build/feature/.gitignore
@@ -1,2 +1,3 @@
1*.d 1*.d
2*.bin 2*.bin
3*.output
diff --git a/tools/perf/config/feature-checks/Makefile b/tools/build/feature/Makefile
index b32ff3372514..463ed8f2a267 100644
--- a/tools/perf/config/feature-checks/Makefile
+++ b/tools/build/feature/Makefile
@@ -29,33 +29,36 @@ FILES= \
29 test-stackprotector-all.bin \ 29 test-stackprotector-all.bin \
30 test-timerfd.bin \ 30 test-timerfd.bin \
31 test-libdw-dwarf-unwind.bin \ 31 test-libdw-dwarf-unwind.bin \
32 test-libbabeltrace.bin \
32 test-compile-32.bin \ 33 test-compile-32.bin \
33 test-compile-x32.bin \ 34 test-compile-x32.bin \
34 test-zlib.bin 35 test-zlib.bin \
36 test-lzma.bin
35 37
36CC := $(CROSS_COMPILE)gcc -MD 38CC := $(CROSS_COMPILE)gcc -MD
37PKG_CONFIG := $(CROSS_COMPILE)pkg-config 39PKG_CONFIG := $(CROSS_COMPILE)pkg-config
38 40
39all: $(FILES) 41all: $(FILES)
40 42
41BUILD = $(CC) $(CFLAGS) -o $(OUTPUT)$@ $(patsubst %.bin,%.c,$@) $(LDFLAGS) 43__BUILD = $(CC) $(CFLAGS) -Wall -Werror -o $(OUTPUT)$@ $(patsubst %.bin,%.c,$@) $(LDFLAGS)
44 BUILD = $(__BUILD) > $(OUTPUT)$(@:.bin=.make.output) 2>&1
42 45
43############################### 46###############################
44 47
45test-all.bin: 48test-all.bin:
46 $(BUILD) -Werror -fstack-protector-all -O2 -Werror -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 49 $(BUILD) -fstack-protector-all -O2 -D_FORTIFY_SOURCE=2 -ldw -lelf -lnuma -lelf -laudit -I/usr/include/slang -lslang $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null) $(FLAGS_PERL_EMBED) $(FLAGS_PYTHON_EMBED) -DPACKAGE='"perf"' -lbfd -ldl -lz -llzma
47 50
48test-hello.bin: 51test-hello.bin:
49 $(BUILD) 52 $(BUILD)
50 53
51test-pthread-attr-setaffinity-np.bin: 54test-pthread-attr-setaffinity-np.bin:
52 $(BUILD) -D_GNU_SOURCE -Werror -lpthread 55 $(BUILD) -D_GNU_SOURCE -lpthread
53 56
54test-stackprotector-all.bin: 57test-stackprotector-all.bin:
55 $(BUILD) -Werror -fstack-protector-all 58 $(BUILD) -fstack-protector-all
56 59
57test-fortify-source.bin: 60test-fortify-source.bin:
58 $(BUILD) -O2 -Werror -D_FORTIFY_SOURCE=2 61 $(BUILD) -O2 -D_FORTIFY_SOURCE=2
59 62
60test-bionic.bin: 63test-bionic.bin:
61 $(BUILD) 64 $(BUILD)
@@ -118,10 +121,10 @@ test-libbfd.bin:
118 $(BUILD) -DPACKAGE='"perf"' -lbfd -lz -liberty -ldl 121 $(BUILD) -DPACKAGE='"perf"' -lbfd -lz -liberty -ldl
119 122
120test-liberty.bin: 123test-liberty.bin:
121 $(CC) -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty 124 $(CC) -Wall -Werror -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty
122 125
123test-liberty-z.bin: 126test-liberty-z.bin:
124 $(CC) -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty -lz 127 $(CC) -Wall -Werror -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty -lz
125 128
126test-cplus-demangle.bin: 129test-cplus-demangle.bin:
127 $(BUILD) -liberty 130 $(BUILD) -liberty
@@ -133,10 +136,13 @@ test-timerfd.bin:
133 $(BUILD) 136 $(BUILD)
134 137
135test-libdw-dwarf-unwind.bin: 138test-libdw-dwarf-unwind.bin:
136 $(BUILD) 139 $(BUILD) # -ldw provided by $(FEATURE_CHECK_LDFLAGS-libdw-dwarf-unwind)
140
141test-libbabeltrace.bin:
142 $(BUILD) # -lbabeltrace provided by $(FEATURE_CHECK_LDFLAGS-libbabeltrace)
137 143
138test-sync-compare-and-swap.bin: 144test-sync-compare-and-swap.bin:
139 $(BUILD) -Werror 145 $(BUILD)
140 146
141test-compile-32.bin: 147test-compile-32.bin:
142 $(CC) -m32 -o $(OUTPUT)$@ test-compile.c 148 $(CC) -m32 -o $(OUTPUT)$@ test-compile.c
@@ -147,9 +153,12 @@ test-compile-x32.bin:
147test-zlib.bin: 153test-zlib.bin:
148 $(BUILD) -lz 154 $(BUILD) -lz
149 155
156test-lzma.bin:
157 $(BUILD) -llzma
158
150-include *.d 159-include *.d
151 160
152############################### 161###############################
153 162
154clean: 163clean:
155 rm -f $(FILES) *.d 164 rm -f $(FILES) *.d $(FILES:.bin=.make.output)
diff --git a/tools/perf/config/feature-checks/test-all.c b/tools/build/feature/test-all.c
index 6d4d09323922..84689a67814a 100644
--- a/tools/perf/config/feature-checks/test-all.c
+++ b/tools/build/feature/test-all.c
@@ -98,7 +98,23 @@
98#undef main 98#undef main
99 99
100#define main main_test_pthread_attr_setaffinity_np 100#define main main_test_pthread_attr_setaffinity_np
101# include "test-pthread_attr_setaffinity_np.c" 101# include "test-pthread-attr-setaffinity-np.c"
102#undef main
103
104# if 0
105/*
106 * Disable libbabeltrace check for test-all, because the requested
107 * library version is not released yet in most distributions. Will
108 * reenable later.
109 */
110
111#define main main_test_libbabeltrace
112# include "test-libbabeltrace.c"
113#undef main
114#endif
115
116#define main main_test_lzma
117# include "test-lzma.c"
102#undef main 118#undef main
103 119
104int main(int argc, char *argv[]) 120int main(int argc, char *argv[])
@@ -126,6 +142,7 @@ int main(int argc, char *argv[])
126 main_test_sync_compare_and_swap(argc, argv); 142 main_test_sync_compare_and_swap(argc, argv);
127 main_test_zlib(); 143 main_test_zlib();
128 main_test_pthread_attr_setaffinity_np(); 144 main_test_pthread_attr_setaffinity_np();
145 main_test_lzma();
129 146
130 return 0; 147 return 0;
131} 148}
diff --git a/tools/perf/config/feature-checks/test-backtrace.c b/tools/build/feature/test-backtrace.c
index 7124aa1dc8fb..7124aa1dc8fb 100644
--- a/tools/perf/config/feature-checks/test-backtrace.c
+++ b/tools/build/feature/test-backtrace.c
diff --git a/tools/perf/config/feature-checks/test-bionic.c b/tools/build/feature/test-bionic.c
index eac24e9513eb..eac24e9513eb 100644
--- a/tools/perf/config/feature-checks/test-bionic.c
+++ b/tools/build/feature/test-bionic.c
diff --git a/tools/perf/config/feature-checks/test-compile.c b/tools/build/feature/test-compile.c
index 31dbf45bf99c..31dbf45bf99c 100644
--- a/tools/perf/config/feature-checks/test-compile.c
+++ b/tools/build/feature/test-compile.c
diff --git a/tools/perf/config/feature-checks/test-cplus-demangle.c b/tools/build/feature/test-cplus-demangle.c
index 610c686e0009..610c686e0009 100644
--- a/tools/perf/config/feature-checks/test-cplus-demangle.c
+++ b/tools/build/feature/test-cplus-demangle.c
diff --git a/tools/perf/config/feature-checks/test-dwarf.c b/tools/build/feature/test-dwarf.c
index 3fc1801ce4a9..3fc1801ce4a9 100644
--- a/tools/perf/config/feature-checks/test-dwarf.c
+++ b/tools/build/feature/test-dwarf.c
diff --git a/tools/perf/config/feature-checks/test-fortify-source.c b/tools/build/feature/test-fortify-source.c
index c9f398d87868..c9f398d87868 100644
--- a/tools/perf/config/feature-checks/test-fortify-source.c
+++ b/tools/build/feature/test-fortify-source.c
diff --git a/tools/perf/config/feature-checks/test-glibc.c b/tools/build/feature/test-glibc.c
index b0820345cd98..b0820345cd98 100644
--- a/tools/perf/config/feature-checks/test-glibc.c
+++ b/tools/build/feature/test-glibc.c
diff --git a/tools/perf/config/feature-checks/test-gtk2-infobar.c b/tools/build/feature/test-gtk2-infobar.c
index 397b4646d066..397b4646d066 100644
--- a/tools/perf/config/feature-checks/test-gtk2-infobar.c
+++ b/tools/build/feature/test-gtk2-infobar.c
diff --git a/tools/perf/config/feature-checks/test-gtk2.c b/tools/build/feature/test-gtk2.c
index 6bd80e509439..6bd80e509439 100644
--- a/tools/perf/config/feature-checks/test-gtk2.c
+++ b/tools/build/feature/test-gtk2.c
diff --git a/tools/perf/config/feature-checks/test-hello.c b/tools/build/feature/test-hello.c
index c9f398d87868..c9f398d87868 100644
--- a/tools/perf/config/feature-checks/test-hello.c
+++ b/tools/build/feature/test-hello.c
diff --git a/tools/perf/config/feature-checks/test-libaudit.c b/tools/build/feature/test-libaudit.c
index afc019f08641..afc019f08641 100644
--- a/tools/perf/config/feature-checks/test-libaudit.c
+++ b/tools/build/feature/test-libaudit.c
diff --git a/tools/build/feature/test-libbabeltrace.c b/tools/build/feature/test-libbabeltrace.c
new file mode 100644
index 000000000000..9cf802a04885
--- /dev/null
+++ b/tools/build/feature/test-libbabeltrace.c
@@ -0,0 +1,9 @@
1
2#include <babeltrace/ctf-writer/writer.h>
3#include <babeltrace/ctf-ir/stream-class.h>
4
5int main(void)
6{
7 bt_ctf_stream_class_get_packet_context_type((void *) 0);
8 return 0;
9}
diff --git a/tools/perf/config/feature-checks/test-libbfd.c b/tools/build/feature/test-libbfd.c
index 24059907e990..24059907e990 100644
--- a/tools/perf/config/feature-checks/test-libbfd.c
+++ b/tools/build/feature/test-libbfd.c
diff --git a/tools/perf/config/feature-checks/test-libdw-dwarf-unwind.c b/tools/build/feature/test-libdw-dwarf-unwind.c
index f676a3ff442a..f676a3ff442a 100644
--- a/tools/perf/config/feature-checks/test-libdw-dwarf-unwind.c
+++ b/tools/build/feature/test-libdw-dwarf-unwind.c
diff --git a/tools/perf/config/feature-checks/test-libelf-getphdrnum.c b/tools/build/feature/test-libelf-getphdrnum.c
index d710459306c3..d710459306c3 100644
--- a/tools/perf/config/feature-checks/test-libelf-getphdrnum.c
+++ b/tools/build/feature/test-libelf-getphdrnum.c
diff --git a/tools/perf/config/feature-checks/test-libelf-mmap.c b/tools/build/feature/test-libelf-mmap.c
index 564427d7ef18..564427d7ef18 100644
--- a/tools/perf/config/feature-checks/test-libelf-mmap.c
+++ b/tools/build/feature/test-libelf-mmap.c
diff --git a/tools/perf/config/feature-checks/test-libelf.c b/tools/build/feature/test-libelf.c
index 08db322d8957..08db322d8957 100644
--- a/tools/perf/config/feature-checks/test-libelf.c
+++ b/tools/build/feature/test-libelf.c
diff --git a/tools/perf/config/feature-checks/test-libnuma.c b/tools/build/feature/test-libnuma.c
index 4763d9cd587d..4763d9cd587d 100644
--- a/tools/perf/config/feature-checks/test-libnuma.c
+++ b/tools/build/feature/test-libnuma.c
diff --git a/tools/perf/config/feature-checks/test-libperl.c b/tools/build/feature/test-libperl.c
index 8871f6a0fdb4..8871f6a0fdb4 100644
--- a/tools/perf/config/feature-checks/test-libperl.c
+++ b/tools/build/feature/test-libperl.c
diff --git a/tools/perf/config/feature-checks/test-libpython-version.c b/tools/build/feature/test-libpython-version.c
index facea122d812..facea122d812 100644
--- a/tools/perf/config/feature-checks/test-libpython-version.c
+++ b/tools/build/feature/test-libpython-version.c
diff --git a/tools/perf/config/feature-checks/test-libpython.c b/tools/build/feature/test-libpython.c
index b24b28ad6324..b24b28ad6324 100644
--- a/tools/perf/config/feature-checks/test-libpython.c
+++ b/tools/build/feature/test-libpython.c
diff --git a/tools/perf/config/feature-checks/test-libslang.c b/tools/build/feature/test-libslang.c
index 22ff22ed94d1..22ff22ed94d1 100644
--- a/tools/perf/config/feature-checks/test-libslang.c
+++ b/tools/build/feature/test-libslang.c
diff --git a/tools/perf/config/feature-checks/test-libunwind-debug-frame.c b/tools/build/feature/test-libunwind-debug-frame.c
index 0ef8087a104a..0ef8087a104a 100644
--- a/tools/perf/config/feature-checks/test-libunwind-debug-frame.c
+++ b/tools/build/feature/test-libunwind-debug-frame.c
diff --git a/tools/perf/config/feature-checks/test-libunwind.c b/tools/build/feature/test-libunwind.c
index 43b9369bcab7..43b9369bcab7 100644
--- a/tools/perf/config/feature-checks/test-libunwind.c
+++ b/tools/build/feature/test-libunwind.c
diff --git a/tools/build/feature/test-lzma.c b/tools/build/feature/test-lzma.c
new file mode 100644
index 000000000000..95adc8ced3dd
--- /dev/null
+++ b/tools/build/feature/test-lzma.c
@@ -0,0 +1,10 @@
1#include <lzma.h>
2
3int main(void)
4{
5 lzma_stream strm = LZMA_STREAM_INIT;
6 int ret;
7
8 ret = lzma_stream_decoder(&strm, UINT64_MAX, LZMA_CONCATENATED);
9 return ret ? -1 : 0;
10}
diff --git a/tools/perf/config/feature-checks/test-pthread-attr-setaffinity-np.c b/tools/build/feature/test-pthread-attr-setaffinity-np.c
index 2b81b72eca23..fdada5e8d454 100644
--- a/tools/perf/config/feature-checks/test-pthread-attr-setaffinity-np.c
+++ b/tools/build/feature/test-pthread-attr-setaffinity-np.c
@@ -1,5 +1,6 @@
1#include <stdint.h> 1#include <stdint.h>
2#include <pthread.h> 2#include <pthread.h>
3#include <sched.h>
3 4
4int main(void) 5int main(void)
5{ 6{
@@ -8,7 +9,8 @@ int main(void)
8 cpu_set_t cs; 9 cpu_set_t cs;
9 10
10 pthread_attr_init(&thread_attr); 11 pthread_attr_init(&thread_attr);
11 /* don't care abt exact args, just the API itself in libpthread */ 12 CPU_ZERO(&cs);
13
12 ret = pthread_attr_setaffinity_np(&thread_attr, sizeof(cs), &cs); 14 ret = pthread_attr_setaffinity_np(&thread_attr, sizeof(cs), &cs);
13 15
14 return ret; 16 return ret;
diff --git a/tools/perf/config/feature-checks/test-stackprotector-all.c b/tools/build/feature/test-stackprotector-all.c
index c9f398d87868..c9f398d87868 100644
--- a/tools/perf/config/feature-checks/test-stackprotector-all.c
+++ b/tools/build/feature/test-stackprotector-all.c
diff --git a/tools/perf/config/feature-checks/test-sync-compare-and-swap.c b/tools/build/feature/test-sync-compare-and-swap.c
index c34d4ca4af56..c34d4ca4af56 100644
--- a/tools/perf/config/feature-checks/test-sync-compare-and-swap.c
+++ b/tools/build/feature/test-sync-compare-and-swap.c
diff --git a/tools/perf/config/feature-checks/test-timerfd.c b/tools/build/feature/test-timerfd.c
index 8c5c083b4d3c..8c5c083b4d3c 100644
--- a/tools/perf/config/feature-checks/test-timerfd.c
+++ b/tools/build/feature/test-timerfd.c
diff --git a/tools/perf/config/feature-checks/test-zlib.c b/tools/build/feature/test-zlib.c
index e111fff6240e..e111fff6240e 100644
--- a/tools/perf/config/feature-checks/test-zlib.c
+++ b/tools/build/feature/test-zlib.c
diff --git a/tools/build/tests/ex/Build b/tools/build/tests/ex/Build
new file mode 100644
index 000000000000..0e6c3e6767e6
--- /dev/null
+++ b/tools/build/tests/ex/Build
@@ -0,0 +1,8 @@
1ex-y += ex.o
2ex-y += a.o
3ex-y += b.o
4ex-y += empty/
5
6libex-y += c.o
7libex-y += d.o
8libex-y += arch/
diff --git a/tools/build/tests/ex/Makefile b/tools/build/tests/ex/Makefile
new file mode 100644
index 000000000000..52d2476073a3
--- /dev/null
+++ b/tools/build/tests/ex/Makefile
@@ -0,0 +1,23 @@
1export srctree := ../../../..
2export CC := gcc
3export LD := ld
4export AR := ar
5
6build := -f $(srctree)/tools/build/Makefile.build dir=. obj
7ex: ex-in.o libex-in.o
8 gcc -o $@ $^
9
10ex.%: FORCE
11 make -f $(srctree)/tools/build/Makefile.build dir=. $@
12
13ex-in.o: FORCE
14 make $(build)=ex
15
16libex-in.o: FORCE
17 make $(build)=libex
18
19clean:
20 find . -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete
21 rm -f ex ex.i ex.s
22
23.PHONY: FORCE
diff --git a/tools/build/tests/ex/a.c b/tools/build/tests/ex/a.c
new file mode 100644
index 000000000000..851762798c83
--- /dev/null
+++ b/tools/build/tests/ex/a.c
@@ -0,0 +1,5 @@
1
2int a(void)
3{
4 return 0;
5}
diff --git a/tools/build/tests/ex/arch/Build b/tools/build/tests/ex/arch/Build
new file mode 100644
index 000000000000..55506189efae
--- /dev/null
+++ b/tools/build/tests/ex/arch/Build
@@ -0,0 +1,2 @@
1libex-y += e.o
2libex-y += f.o
diff --git a/tools/build/tests/ex/arch/e.c b/tools/build/tests/ex/arch/e.c
new file mode 100644
index 000000000000..beaa4a1d7ba8
--- /dev/null
+++ b/tools/build/tests/ex/arch/e.c
@@ -0,0 +1,5 @@
1
2int e(void)
3{
4 return 0;
5}
diff --git a/tools/build/tests/ex/arch/f.c b/tools/build/tests/ex/arch/f.c
new file mode 100644
index 000000000000..7c3e9e9da5b7
--- /dev/null
+++ b/tools/build/tests/ex/arch/f.c
@@ -0,0 +1,5 @@
1
2int f(void)
3{
4 return 0;
5}
diff --git a/tools/build/tests/ex/b.c b/tools/build/tests/ex/b.c
new file mode 100644
index 000000000000..c24ff9ca9a97
--- /dev/null
+++ b/tools/build/tests/ex/b.c
@@ -0,0 +1,5 @@
1
2int b(void)
3{
4 return 0;
5}
diff --git a/tools/build/tests/ex/c.c b/tools/build/tests/ex/c.c
new file mode 100644
index 000000000000..e216d0217499
--- /dev/null
+++ b/tools/build/tests/ex/c.c
@@ -0,0 +1,5 @@
1
2int c(void)
3{
4 return 0;
5}
diff --git a/tools/build/tests/ex/d.c b/tools/build/tests/ex/d.c
new file mode 100644
index 000000000000..80dc0f06151b
--- /dev/null
+++ b/tools/build/tests/ex/d.c
@@ -0,0 +1,5 @@
1
2int d(void)
3{
4 return 0;
5}
diff --git a/tools/build/tests/ex/empty/Build b/tools/build/tests/ex/empty/Build
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/tools/build/tests/ex/empty/Build
diff --git a/tools/build/tests/ex/ex.c b/tools/build/tests/ex/ex.c
new file mode 100644
index 000000000000..dc42eb2e1a67
--- /dev/null
+++ b/tools/build/tests/ex/ex.c
@@ -0,0 +1,19 @@
1
2int a(void);
3int b(void);
4int c(void);
5int d(void);
6int e(void);
7int f(void);
8
9int main(void)
10{
11 a();
12 b();
13 c();
14 d();
15 e();
16 f();
17
18 return 0;
19}
diff --git a/tools/build/tests/run.sh b/tools/build/tests/run.sh
new file mode 100755
index 000000000000..5494f8ea7567
--- /dev/null
+++ b/tools/build/tests/run.sh
@@ -0,0 +1,42 @@
1#!/bin/sh
2
3function test_ex {
4 make -C ex V=1 clean > ex.out 2>&1
5 make -C ex V=1 >> ex.out 2>&1
6
7 if [ ! -x ./ex/ex ]; then
8 echo FAILED
9 exit -1
10 fi
11
12 make -C ex V=1 clean > /dev/null 2>&1
13 rm -f ex.out
14}
15
16function test_ex_suffix {
17 make -C ex V=1 clean > ex.out 2>&1
18
19 # use -rR to disable make's builtin rules
20 make -rR -C ex V=1 ex.o >> ex.out 2>&1
21 make -rR -C ex V=1 ex.i >> ex.out 2>&1
22 make -rR -C ex V=1 ex.s >> ex.out 2>&1
23
24 if [ -x ./ex/ex ]; then
25 echo FAILED
26 exit -1
27 fi
28
29 if [ ! -f ./ex/ex.o -o ! -f ./ex/ex.i -o ! -f ./ex/ex.s ]; then
30 echo FAILED
31 exit -1
32 fi
33
34 make -C ex V=1 clean > /dev/null 2>&1
35 rm -f ex.out
36}
37echo -n Testing..
38
39test_ex
40test_ex_suffix
41
42echo OK
diff --git a/tools/lib/api/Build b/tools/lib/api/Build
new file mode 100644
index 000000000000..3653965cf481
--- /dev/null
+++ b/tools/lib/api/Build
@@ -0,0 +1,2 @@
1libapi-y += fd/
2libapi-y += fs/
diff --git a/tools/lib/api/Makefile b/tools/lib/api/Makefile
index 36c08b1f4afb..d8fe29fc19a4 100644
--- a/tools/lib/api/Makefile
+++ b/tools/lib/api/Makefile
@@ -1,49 +1,43 @@
1include ../../scripts/Makefile.include 1include ../../scripts/Makefile.include
2include ../../perf/config/utilities.mak # QUIET_CLEAN 2include ../../perf/config/utilities.mak # QUIET_CLEAN
3 3
4ifeq ($(srctree),)
5srctree := $(patsubst %/,%,$(dir $(shell pwd)))
6srctree := $(patsubst %/,%,$(dir $(srctree)))
7srctree := $(patsubst %/,%,$(dir $(srctree)))
8#$(info Determined 'srctree' to be $(srctree))
9endif
10
4CC = $(CROSS_COMPILE)gcc 11CC = $(CROSS_COMPILE)gcc
5AR = $(CROSS_COMPILE)ar 12AR = $(CROSS_COMPILE)ar
6 13
7# guard against environment variables 14MAKEFLAGS += --no-print-directory
8LIB_H=
9LIB_OBJS=
10
11LIB_H += fs/debugfs.h
12LIB_H += fs/fs.h
13# See comment below about piggybacking...
14LIB_H += fd/array.h
15
16LIB_OBJS += $(OUTPUT)fs/debugfs.o
17LIB_OBJS += $(OUTPUT)fs/fs.o
18# XXX piggybacking here, need to introduce libapikfd, or rename this
19# to plain libapik.a and make it have it all api goodies
20LIB_OBJS += $(OUTPUT)fd/array.o
21 15
22LIBFILE = libapikfs.a 16LIBFILE = $(OUTPUT)libapi.a
23 17
24CFLAGS = -ggdb3 -Wall -Wextra -std=gnu99 -Werror -O6 -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) -fPIC 18CFLAGS := $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
25EXTLIBS = -lelf -lpthread -lrt -lm 19CFLAGS += -ggdb3 -Wall -Wextra -std=gnu99 -Werror -O6 -D_FORTIFY_SOURCE=2 -fPIC
26ALL_CFLAGS = $(CFLAGS) $(BASIC_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 20CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
27ALL_LDFLAGS = $(LDFLAGS)
28 21
29RM = rm -f 22RM = rm -f
30 23
31$(LIBFILE): $(LIB_OBJS) 24build := -f $(srctree)/tools/build/Makefile.build dir=. obj
32 $(QUIET_AR)$(RM) $@ && $(AR) rcs $(OUTPUT)$@ $(LIB_OBJS) 25API_IN := $(OUTPUT)libapi-in.o
33 26
34$(LIB_OBJS): $(LIB_H) 27export srctree OUTPUT CC LD CFLAGS V
35 28
36libapi_dirs: 29all: $(LIBFILE)
37 $(QUIET_MKDIR)mkdir -p $(OUTPUT)fd $(OUTPUT)fs
38 30
39$(OUTPUT)%.o: %.c libapi_dirs 31$(API_IN): FORCE
40 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $< 32 @$(MAKE) $(build)=libapi
41$(OUTPUT)%.s: %.c libapi_dirs 33
42 $(QUIET_CC)$(CC) -S $(ALL_CFLAGS) $< 34$(LIBFILE): $(API_IN)
43$(OUTPUT)%.o: %.S libapi_dirs 35 $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(API_IN)
44 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $<
45 36
46clean: 37clean:
47 $(call QUIET_CLEAN, libapi) $(RM) $(LIB_OBJS) $(LIBFILE) 38 $(call QUIET_CLEAN, libapi) $(RM) $(LIBFILE); \
39 find $(if $(OUTPUT),$(OUTPUT),.) -name \*.o | xargs $(RM)
40
41FORCE:
48 42
49.PHONY: clean 43.PHONY: clean FORCE
diff --git a/tools/lib/api/fd/Build b/tools/lib/api/fd/Build
new file mode 100644
index 000000000000..605d99f6d71a
--- /dev/null
+++ b/tools/lib/api/fd/Build
@@ -0,0 +1 @@
libapi-y += array.o
diff --git a/tools/lib/api/fs/Build b/tools/lib/api/fs/Build
new file mode 100644
index 000000000000..6de5a4f0b501
--- /dev/null
+++ b/tools/lib/api/fs/Build
@@ -0,0 +1,4 @@
1libapi-y += fs.o
2libapi-y += debugfs.o
3libapi-y += findfs.o
4libapi-y += tracefs.o
diff --git a/tools/lib/api/fs/debugfs.c b/tools/lib/api/fs/debugfs.c
index d2b18e887071..8305b3e9d48e 100644
--- a/tools/lib/api/fs/debugfs.c
+++ b/tools/lib/api/fs/debugfs.c
@@ -3,75 +3,50 @@
3#include <stdio.h> 3#include <stdio.h>
4#include <stdlib.h> 4#include <stdlib.h>
5#include <string.h> 5#include <string.h>
6#include <unistd.h>
6#include <stdbool.h> 7#include <stdbool.h>
7#include <sys/vfs.h> 8#include <sys/vfs.h>
9#include <sys/types.h>
10#include <sys/stat.h>
8#include <sys/mount.h> 11#include <sys/mount.h>
9#include <linux/kernel.h> 12#include <linux/kernel.h>
10 13
11#include "debugfs.h" 14#include "debugfs.h"
12 15
13char debugfs_mountpoint[PATH_MAX + 1] = "/sys/kernel/debug"; 16#ifndef DEBUGFS_DEFAULT_PATH
17#define DEBUGFS_DEFAULT_PATH "/sys/kernel/debug"
18#endif
19
20char debugfs_mountpoint[PATH_MAX + 1] = DEBUGFS_DEFAULT_PATH;
14 21
15static const char * const debugfs_known_mountpoints[] = { 22static const char * const debugfs_known_mountpoints[] = {
16 "/sys/kernel/debug", 23 DEBUGFS_DEFAULT_PATH,
17 "/debug", 24 "/debug",
18 0, 25 0,
19}; 26};
20 27
21static bool debugfs_found; 28static bool debugfs_found;
22 29
30bool debugfs_configured(void)
31{
32 return debugfs_find_mountpoint() != NULL;
33}
34
23/* find the path to the mounted debugfs */ 35/* find the path to the mounted debugfs */
24const char *debugfs_find_mountpoint(void) 36const char *debugfs_find_mountpoint(void)
25{ 37{
26 const char * const *ptr; 38 const char *ret;
27 char type[100];
28 FILE *fp;
29 39
30 if (debugfs_found) 40 if (debugfs_found)
31 return (const char *)debugfs_mountpoint; 41 return (const char *)debugfs_mountpoint;
32 42
33 ptr = debugfs_known_mountpoints; 43 ret = find_mountpoint("debugfs", (long) DEBUGFS_MAGIC,
34 while (*ptr) { 44 debugfs_mountpoint, PATH_MAX + 1,
35 if (debugfs_valid_mountpoint(*ptr) == 0) { 45 debugfs_known_mountpoints);
36 debugfs_found = true; 46 if (ret)
37 strcpy(debugfs_mountpoint, *ptr); 47 debugfs_found = true;
38 return debugfs_mountpoint;
39 }
40 ptr++;
41 }
42
43 /* give up and parse /proc/mounts */
44 fp = fopen("/proc/mounts", "r");
45 if (fp == NULL)
46 return NULL;
47
48 while (fscanf(fp, "%*s %" STR(PATH_MAX) "s %99s %*s %*d %*d\n",
49 debugfs_mountpoint, type) == 2) {
50 if (strcmp(type, "debugfs") == 0)
51 break;
52 }
53 fclose(fp);
54 48
55 if (strcmp(type, "debugfs") != 0) 49 return ret;
56 return NULL;
57
58 debugfs_found = true;
59
60 return debugfs_mountpoint;
61}
62
63/* verify that a mountpoint is actually a debugfs instance */
64
65int debugfs_valid_mountpoint(const char *debugfs)
66{
67 struct statfs st_fs;
68
69 if (statfs(debugfs, &st_fs) < 0)
70 return -ENOENT;
71 else if ((long)st_fs.f_type != (long)DEBUGFS_MAGIC)
72 return -ENOENT;
73
74 return 0;
75} 50}
76 51
77/* mount the debugfs somewhere if it's not mounted */ 52/* mount the debugfs somewhere if it's not mounted */
@@ -87,7 +62,7 @@ char *debugfs_mount(const char *mountpoint)
87 mountpoint = getenv(PERF_DEBUGFS_ENVIRONMENT); 62 mountpoint = getenv(PERF_DEBUGFS_ENVIRONMENT);
88 /* if no environment variable, use default */ 63 /* if no environment variable, use default */
89 if (mountpoint == NULL) 64 if (mountpoint == NULL)
90 mountpoint = "/sys/kernel/debug"; 65 mountpoint = DEBUGFS_DEFAULT_PATH;
91 } 66 }
92 67
93 if (mount(NULL, mountpoint, "debugfs", 0, NULL) < 0) 68 if (mount(NULL, mountpoint, "debugfs", 0, NULL) < 0)
diff --git a/tools/lib/api/fs/debugfs.h b/tools/lib/api/fs/debugfs.h
index 0739881a9897..455023698d2b 100644
--- a/tools/lib/api/fs/debugfs.h
+++ b/tools/lib/api/fs/debugfs.h
@@ -1,16 +1,7 @@
1#ifndef __API_DEBUGFS_H__ 1#ifndef __API_DEBUGFS_H__
2#define __API_DEBUGFS_H__ 2#define __API_DEBUGFS_H__
3 3
4#define _STR(x) #x 4#include "findfs.h"
5#define STR(x) _STR(x)
6
7/*
8 * On most systems <limits.h> would have given us this, but not on some systems
9 * (e.g. GNU/Hurd).
10 */
11#ifndef PATH_MAX
12#define PATH_MAX 4096
13#endif
14 5
15#ifndef DEBUGFS_MAGIC 6#ifndef DEBUGFS_MAGIC
16#define DEBUGFS_MAGIC 0x64626720 7#define DEBUGFS_MAGIC 0x64626720
@@ -20,8 +11,8 @@
20#define PERF_DEBUGFS_ENVIRONMENT "PERF_DEBUGFS_DIR" 11#define PERF_DEBUGFS_ENVIRONMENT "PERF_DEBUGFS_DIR"
21#endif 12#endif
22 13
14bool debugfs_configured(void);
23const char *debugfs_find_mountpoint(void); 15const char *debugfs_find_mountpoint(void);
24int debugfs_valid_mountpoint(const char *debugfs);
25char *debugfs_mount(const char *mountpoint); 16char *debugfs_mount(const char *mountpoint);
26 17
27extern char debugfs_mountpoint[]; 18extern char debugfs_mountpoint[];
diff --git a/tools/lib/api/fs/findfs.c b/tools/lib/api/fs/findfs.c
new file mode 100644
index 000000000000..49946cb6d7af
--- /dev/null
+++ b/tools/lib/api/fs/findfs.c
@@ -0,0 +1,63 @@
1#include <errno.h>
2#include <stdio.h>
3#include <stdlib.h>
4#include <string.h>
5#include <stdbool.h>
6#include <sys/vfs.h>
7
8#include "findfs.h"
9
10/* verify that a mountpoint is actually the type we want */
11
12int valid_mountpoint(const char *mount, long magic)
13{
14 struct statfs st_fs;
15
16 if (statfs(mount, &st_fs) < 0)
17 return -ENOENT;
18 else if ((long)st_fs.f_type != magic)
19 return -ENOENT;
20
21 return 0;
22}
23
24/* find the path to a mounted file system */
25const char *find_mountpoint(const char *fstype, long magic,
26 char *mountpoint, int len,
27 const char * const *known_mountpoints)
28{
29 const char * const *ptr;
30 char format[128];
31 char type[100];
32 FILE *fp;
33
34 if (known_mountpoints) {
35 ptr = known_mountpoints;
36 while (*ptr) {
37 if (valid_mountpoint(*ptr, magic) == 0) {
38 strncpy(mountpoint, *ptr, len - 1);
39 mountpoint[len-1] = 0;
40 return mountpoint;
41 }
42 ptr++;
43 }
44 }
45
46 /* give up and parse /proc/mounts */
47 fp = fopen("/proc/mounts", "r");
48 if (fp == NULL)
49 return NULL;
50
51 snprintf(format, 128, "%%*s %%%ds %%99s %%*s %%*d %%*d\n", len);
52
53 while (fscanf(fp, format, mountpoint, type) == 2) {
54 if (strcmp(type, fstype) == 0)
55 break;
56 }
57 fclose(fp);
58
59 if (strcmp(type, fstype) != 0)
60 return NULL;
61
62 return mountpoint;
63}
diff --git a/tools/lib/api/fs/findfs.h b/tools/lib/api/fs/findfs.h
new file mode 100644
index 000000000000..b6f5d05acc42
--- /dev/null
+++ b/tools/lib/api/fs/findfs.h
@@ -0,0 +1,23 @@
1#ifndef __API_FINDFS_H__
2#define __API_FINDFS_H__
3
4#include <stdbool.h>
5
6#define _STR(x) #x
7#define STR(x) _STR(x)
8
9/*
10 * On most systems <limits.h> would have given us this, but not on some systems
11 * (e.g. GNU/Hurd).
12 */
13#ifndef PATH_MAX
14#define PATH_MAX 4096
15#endif
16
17const char *find_mountpoint(const char *fstype, long magic,
18 char *mountpoint, int len,
19 const char * const *known_mountpoints);
20
21int valid_mountpoint(const char *mount, long magic);
22
23#endif /* __API_FINDFS_H__ */
diff --git a/tools/lib/api/fs/tracefs.c b/tools/lib/api/fs/tracefs.c
new file mode 100644
index 000000000000..e4aa9688b71e
--- /dev/null
+++ b/tools/lib/api/fs/tracefs.c
@@ -0,0 +1,78 @@
1#include <errno.h>
2#include <stdio.h>
3#include <stdlib.h>
4#include <string.h>
5#include <unistd.h>
6#include <stdbool.h>
7#include <sys/vfs.h>
8#include <sys/types.h>
9#include <sys/stat.h>
10#include <sys/mount.h>
11#include <linux/kernel.h>
12
13#include "tracefs.h"
14
15#ifndef TRACEFS_DEFAULT_PATH
16#define TRACEFS_DEFAULT_PATH "/sys/kernel/tracing"
17#endif
18
19char tracefs_mountpoint[PATH_MAX + 1] = TRACEFS_DEFAULT_PATH;
20
21static const char * const tracefs_known_mountpoints[] = {
22 TRACEFS_DEFAULT_PATH,
23 "/sys/kernel/debug/tracing",
24 "/tracing",
25 "/trace",
26 0,
27};
28
29static bool tracefs_found;
30
31bool tracefs_configured(void)
32{
33 return tracefs_find_mountpoint() != NULL;
34}
35
36/* find the path to the mounted tracefs */
37const char *tracefs_find_mountpoint(void)
38{
39 const char *ret;
40
41 if (tracefs_found)
42 return (const char *)tracefs_mountpoint;
43
44 ret = find_mountpoint("tracefs", (long) TRACEFS_MAGIC,
45 tracefs_mountpoint, PATH_MAX + 1,
46 tracefs_known_mountpoints);
47
48 if (ret)
49 tracefs_found = true;
50
51 return ret;
52}
53
54/* mount the tracefs somewhere if it's not mounted */
55char *tracefs_mount(const char *mountpoint)
56{
57 /* see if it's already mounted */
58 if (tracefs_find_mountpoint())
59 goto out;
60
61 /* if not mounted and no argument */
62 if (mountpoint == NULL) {
63 /* see if environment variable set */
64 mountpoint = getenv(PERF_TRACEFS_ENVIRONMENT);
65 /* if no environment variable, use default */
66 if (mountpoint == NULL)
67 mountpoint = TRACEFS_DEFAULT_PATH;
68 }
69
70 if (mount(NULL, mountpoint, "tracefs", 0, NULL) < 0)
71 return NULL;
72
73 /* save the mountpoint */
74 tracefs_found = true;
75 strncpy(tracefs_mountpoint, mountpoint, sizeof(tracefs_mountpoint));
76out:
77 return tracefs_mountpoint;
78}
diff --git a/tools/lib/api/fs/tracefs.h b/tools/lib/api/fs/tracefs.h
new file mode 100644
index 000000000000..da780ac49acb
--- /dev/null
+++ b/tools/lib/api/fs/tracefs.h
@@ -0,0 +1,21 @@
1#ifndef __API_TRACEFS_H__
2#define __API_TRACEFS_H__
3
4#include "findfs.h"
5
6#ifndef TRACEFS_MAGIC
7#define TRACEFS_MAGIC 0x74726163
8#endif
9
10#ifndef PERF_TRACEFS_ENVIRONMENT
11#define PERF_TRACEFS_ENVIRONMENT "PERF_TRACEFS_DIR"
12#endif
13
14bool tracefs_configured(void);
15const char *tracefs_find_mountpoint(void);
16int tracefs_valid_mountpoint(const char *debugfs);
17char *tracefs_mount(const char *mountpoint);
18
19extern char tracefs_mountpoint[];
20
21#endif /* __API_DEBUGFS_H__ */
diff --git a/tools/lib/lockdep/Build b/tools/lib/lockdep/Build
new file mode 100644
index 000000000000..6f667355b068
--- /dev/null
+++ b/tools/lib/lockdep/Build
@@ -0,0 +1 @@
liblockdep-y += common.o lockdep.o preload.o rbtree.o
diff --git a/tools/lib/lockdep/Makefile b/tools/lib/lockdep/Makefile
index 4b866c54f624..0c356fb65022 100644
--- a/tools/lib/lockdep/Makefile
+++ b/tools/lib/lockdep/Makefile
@@ -35,6 +35,10 @@ bindir = $(prefix)/$(bindir_relative)
35 35
36export DESTDIR DESTDIR_SQ INSTALL 36export DESTDIR DESTDIR_SQ INSTALL
37 37
38MAKEFLAGS += --no-print-directory
39
40include ../../scripts/Makefile.include
41
38# copy a bit from Linux kbuild 42# copy a bit from Linux kbuild
39 43
40ifeq ("$(origin V)", "command line") 44ifeq ("$(origin V)", "command line")
@@ -44,56 +48,21 @@ ifndef VERBOSE
44 VERBOSE = 0 48 VERBOSE = 0
45endif 49endif
46 50
47ifeq ("$(origin O)", "command line") 51ifeq ($(srctree),)
48 BUILD_OUTPUT := $(O) 52srctree := $(patsubst %/,%,$(dir $(shell pwd)))
53srctree := $(patsubst %/,%,$(dir $(srctree)))
54srctree := $(patsubst %/,%,$(dir $(srctree)))
55#$(info Determined 'srctree' to be $(srctree))
49endif 56endif
50 57
51ifeq ($(BUILD_SRC),)
52ifneq ($(BUILD_OUTPUT),)
53
54define build_output
55 $(if $(VERBOSE:1=),@)$(MAKE) -C $(BUILD_OUTPUT) \
56 BUILD_SRC=$(CURDIR) -f $(CURDIR)/Makefile $1
57endef
58
59saved-output := $(BUILD_OUTPUT)
60BUILD_OUTPUT := $(shell cd $(BUILD_OUTPUT) && /bin/pwd)
61$(if $(BUILD_OUTPUT),, \
62 $(error output directory "$(saved-output)" does not exist))
63
64all: sub-make
65
66gui: force
67 $(call build_output, all_cmd)
68
69$(filter-out gui,$(MAKECMDGOALS)): sub-make
70
71sub-make: force
72 $(call build_output, $(MAKECMDGOALS))
73
74
75# Leave processing to above invocation of make
76skip-makefile := 1
77
78endif # BUILD_OUTPUT
79endif # BUILD_SRC
80
81# We process the rest of the Makefile if this is the final invocation of make
82ifeq ($(skip-makefile),)
83
84srctree := $(realpath $(if $(BUILD_SRC),$(BUILD_SRC),$(CURDIR)))
85objtree := $(realpath $(CURDIR))
86src := $(srctree)
87obj := $(objtree)
88
89export prefix libdir bindir src obj
90
91# Shell quotes 58# Shell quotes
92libdir_SQ = $(subst ','\'',$(libdir)) 59libdir_SQ = $(subst ','\'',$(libdir))
93bindir_SQ = $(subst ','\'',$(bindir)) 60bindir_SQ = $(subst ','\'',$(bindir))
94 61
95LIB_FILE = liblockdep.a liblockdep.so.$(LIBLOCKDEP_VERSION) 62LIB_IN := $(OUTPUT)liblockdep-in.o
63
96BIN_FILE = lockdep 64BIN_FILE = lockdep
65LIB_FILE = $(OUTPUT)liblockdep.a $(OUTPUT)liblockdep.so.$(LIBLOCKDEP_VERSION)
97 66
98CONFIG_INCLUDES = 67CONFIG_INCLUDES =
99CONFIG_LIBS = 68CONFIG_LIBS =
@@ -108,33 +77,23 @@ INCLUDES = -I. -I./uinclude -I./include -I../../include $(CONFIG_INCLUDES)
108 77
109# Set compile option CFLAGS if not set elsewhere 78# Set compile option CFLAGS if not set elsewhere
110CFLAGS ?= -g -DCONFIG_LOCKDEP -DCONFIG_STACKTRACE -DCONFIG_PROVE_LOCKING -DBITS_PER_LONG=__WORDSIZE -DLIBLOCKDEP_VERSION='"$(LIBLOCKDEP_VERSION)"' -rdynamic -O0 -g 79CFLAGS ?= -g -DCONFIG_LOCKDEP -DCONFIG_STACKTRACE -DCONFIG_PROVE_LOCKING -DBITS_PER_LONG=__WORDSIZE -DLIBLOCKDEP_VERSION='"$(LIBLOCKDEP_VERSION)"' -rdynamic -O0 -g
80CFLAGS += -fPIC
111 81
112override CFLAGS += $(CONFIG_FLAGS) $(INCLUDES) $(PLUGIN_DIR_SQ) 82override CFLAGS += $(CONFIG_FLAGS) $(INCLUDES) $(PLUGIN_DIR_SQ)
113 83
114ifeq ($(VERBOSE),1) 84ifeq ($(VERBOSE),1)
115 Q = 85 Q =
116 print_compile =
117 print_app_build =
118 print_fpic_compile =
119 print_shared_lib_compile = 86 print_shared_lib_compile =
120 print_install = 87 print_install =
121else 88else
122 Q = @ 89 Q = @
123 print_compile = echo ' CC '$(OBJ); 90 print_shared_lib_compile = echo ' LD '$(OBJ);
124 print_app_build = echo ' BUILD '$(OBJ); 91 print_static_lib_build = echo ' LD '$(OBJ);
125 print_fpic_compile = echo ' CC FPIC '$(OBJ); 92 print_install = echo ' INSTALL '$1' to $(DESTDIR_SQ)$2';
126 print_shared_lib_compile = echo ' BUILD SHARED LIB '$(OBJ);
127 print_static_lib_build = echo ' BUILD STATIC LIB '$(OBJ);
128 print_install = echo ' INSTALL '$1' to $(DESTDIR_SQ)$2';
129endif 93endif
130 94
131do_fpic_compile = \ 95export srctree OUTPUT CC LD CFLAGS V
132 ($(print_fpic_compile) \ 96build := -f $(srctree)/tools/build/Makefile.build dir=. obj
133 $(CC) -c $(CFLAGS) $(EXT) -fPIC $< -o $@)
134
135do_app_build = \
136 ($(print_app_build) \
137 $(CC) $^ -rdynamic -o $@ $(CONFIG_LIBS) $(LIBS))
138 97
139do_compile_shared_library = \ 98do_compile_shared_library = \
140 ($(print_shared_lib_compile) \ 99 ($(print_shared_lib_compile) \
@@ -144,22 +103,6 @@ do_build_static_lib = \
144 ($(print_static_lib_build) \ 103 ($(print_static_lib_build) \
145 $(RM) $@; $(AR) rcs $@ $^) 104 $(RM) $@; $(AR) rcs $@ $^)
146 105
147
148define do_compile
149 $(print_compile) \
150 $(CC) -c $(CFLAGS) $(EXT) $< -o $(obj)/$@;
151endef
152
153$(obj)/%.o: $(src)/%.c
154 $(Q)$(call do_compile)
155
156%.o: $(src)/%.c
157 $(Q)$(call do_compile)
158
159PEVENT_LIB_OBJS = common.o lockdep.o preload.o rbtree.o
160
161ALL_OBJS = $(PEVENT_LIB_OBJS)
162
163CMD_TARGETS = $(LIB_FILE) 106CMD_TARGETS = $(LIB_FILE)
164 107
165TARGETS = $(CMD_TARGETS) 108TARGETS = $(CMD_TARGETS)
@@ -169,42 +112,15 @@ all: all_cmd
169 112
170all_cmd: $(CMD_TARGETS) 113all_cmd: $(CMD_TARGETS)
171 114
172liblockdep.so.$(LIBLOCKDEP_VERSION): $(PEVENT_LIB_OBJS) 115$(LIB_IN): force
116 $(Q)$(MAKE) $(build)=liblockdep
117
118liblockdep.so.$(LIBLOCKDEP_VERSION): $(LIB_IN)
173 $(Q)$(do_compile_shared_library) 119 $(Q)$(do_compile_shared_library)
174 120
175liblockdep.a: $(PEVENT_LIB_OBJS) 121liblockdep.a: $(LIB_IN)
176 $(Q)$(do_build_static_lib) 122 $(Q)$(do_build_static_lib)
177 123
178$(PEVENT_LIB_OBJS): %.o: $(src)/%.c
179 $(Q)$(do_fpic_compile)
180
181## make deps
182
183all_objs := $(sort $(ALL_OBJS))
184all_deps := $(all_objs:%.o=.%.d)
185
186# let .d file also depends on the source and header files
187define check_deps
188 @set -e; $(RM) $@; \
189 $(CC) -MM $(CFLAGS) $< > $@.$$$$; \
190 sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
191 $(RM) $@.$$$$
192endef
193
194$(all_deps): .%.d: $(src)/%.c
195 $(Q)$(call check_deps)
196
197$(all_objs) : %.o : .%.d
198
199dep_includes := $(wildcard $(all_deps))
200
201ifneq ($(dep_includes),)
202 include $(dep_includes)
203endif
204
205### Detect environment changes
206TRACK_CFLAGS = $(subst ','\'',$(CFLAGS)):$(ARCH):$(CROSS_COMPILE)
207
208tags: force 124tags: force
209 $(RM) tags 125 $(RM) tags
210 find . -name '*.[ch]' | xargs ctags --extra=+f --c-kinds=+px \ 126 find . -name '*.[ch]' | xargs ctags --extra=+f --c-kinds=+px \
@@ -233,8 +149,6 @@ clean:
233 $(RM) *.o *~ $(TARGETS) *.a *liblockdep*.so* $(VERSION_FILES) .*.d 149 $(RM) *.o *~ $(TARGETS) *.a *liblockdep*.so* $(VERSION_FILES) .*.d
234 $(RM) tags TAGS 150 $(RM) tags TAGS
235 151
236endif # skip-makefile
237
238PHONY += force 152PHONY += force
239force: 153force:
240 154
diff --git a/tools/lib/traceevent/Build b/tools/lib/traceevent/Build
new file mode 100644
index 000000000000..c681d0575d16
--- /dev/null
+++ b/tools/lib/traceevent/Build
@@ -0,0 +1,17 @@
1libtraceevent-y += event-parse.o
2libtraceevent-y += event-plugin.o
3libtraceevent-y += trace-seq.o
4libtraceevent-y += parse-filter.o
5libtraceevent-y += parse-utils.o
6libtraceevent-y += kbuffer-parse.o
7
8plugin_jbd2-y += plugin_jbd2.o
9plugin_hrtimer-y += plugin_hrtimer.o
10plugin_kmem-y += plugin_kmem.o
11plugin_kvm-y += plugin_kvm.o
12plugin_mac80211-y += plugin_mac80211.o
13plugin_sched_switch-y += plugin_sched_switch.o
14plugin_function-y += plugin_function.o
15plugin_xen-y += plugin_xen.o
16plugin_scsi-y += plugin_scsi.o
17plugin_cfg80211-y += plugin_cfg80211.o
diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile
index 005c9cc06935..d410da335e3d 100644
--- a/tools/lib/traceevent/Makefile
+++ b/tools/lib/traceevent/Makefile
@@ -67,7 +67,7 @@ PLUGIN_DIR = -DPLUGIN_DIR="$(plugin_dir)"
67PLUGIN_DIR_SQ = '$(subst ','\'',$(PLUGIN_DIR))' 67PLUGIN_DIR_SQ = '$(subst ','\'',$(PLUGIN_DIR))'
68endif 68endif
69 69
70include $(if $(BUILD_SRC),$(BUILD_SRC)/)../../scripts/Makefile.include 70include ../../scripts/Makefile.include
71 71
72# copy a bit from Linux kbuild 72# copy a bit from Linux kbuild
73 73
@@ -78,40 +78,13 @@ ifndef VERBOSE
78 VERBOSE = 0 78 VERBOSE = 0
79endif 79endif
80 80
81ifeq ("$(origin O)", "command line") 81ifeq ($(srctree),)
82 BUILD_OUTPUT := $(O) 82srctree := $(patsubst %/,%,$(dir $(shell pwd)))
83srctree := $(patsubst %/,%,$(dir $(srctree)))
84srctree := $(patsubst %/,%,$(dir $(srctree)))
85#$(info Determined 'srctree' to be $(srctree))
83endif 86endif
84 87
85ifeq ($(BUILD_SRC),)
86ifneq ($(OUTPUT),)
87
88define build_output
89 $(if $(VERBOSE:1=),@)+$(MAKE) -C $(OUTPUT) \
90 BUILD_SRC=$(CURDIR)/ -f $(CURDIR)/Makefile $1
91endef
92
93all: sub-make
94
95$(MAKECMDGOALS): sub-make
96
97sub-make: force
98 $(call build_output, $(MAKECMDGOALS))
99
100
101# Leave processing to above invocation of make
102skip-makefile := 1
103
104endif # OUTPUT
105endif # BUILD_SRC
106
107# We process the rest of the Makefile if this is the final invocation of make
108ifeq ($(skip-makefile),)
109
110srctree := $(if $(BUILD_SRC),$(BUILD_SRC),$(CURDIR))
111objtree := $(CURDIR)
112src := $(srctree)
113obj := $(objtree)
114
115export prefix bindir src obj 88export prefix bindir src obj
116 89
117# Shell quotes 90# Shell quotes
@@ -132,16 +105,19 @@ EXTRAVERSION = $(EP_EXTRAVERSION)
132OBJ = $@ 105OBJ = $@
133N = 106N =
134 107
135export Q VERBOSE
136
137EVENT_PARSE_VERSION = $(EP_VERSION).$(EP_PATCHLEVEL).$(EP_EXTRAVERSION) 108EVENT_PARSE_VERSION = $(EP_VERSION).$(EP_PATCHLEVEL).$(EP_EXTRAVERSION)
138 109
139INCLUDES = -I. -I $(srctree)/../../include $(CONFIG_INCLUDES) 110INCLUDES = -I. -I $(srctree)/tools/include $(CONFIG_INCLUDES)
140 111
141# Set compile option CFLAGS if not set elsewhere 112# Set compile option CFLAGS
142CFLAGS ?= -g -Wall 113ifdef EXTRA_CFLAGS
114 CFLAGS := $(EXTRA_CFLAGS)
115else
116 CFLAGS := -g -Wall
117endif
143 118
144# Append required CFLAGS 119# Append required CFLAGS
120override CFLAGS += -fPIC
145override CFLAGS += $(CONFIG_FLAGS) $(INCLUDES) $(PLUGIN_DIR_SQ) 121override CFLAGS += $(CONFIG_FLAGS) $(INCLUDES) $(PLUGIN_DIR_SQ)
146override CFLAGS += $(udis86-flags) -D_GNU_SOURCE 122override CFLAGS += $(udis86-flags) -D_GNU_SOURCE
147 123
@@ -151,74 +127,58 @@ else
151 Q = @ 127 Q = @
152endif 128endif
153 129
154do_compile_shared_library = \ 130# Disable command line variables (CFLAGS) overide from top
155 ($(print_shared_lib_compile) \ 131# level Makefile (perf), otherwise build Makefile will get
156 $(CC) --shared $^ -o $@) 132# the same command line setup.
157 133MAKEOVERRIDES=
158do_plugin_build = \
159 ($(print_plugin_build) \
160 $(CC) $(CFLAGS) -shared -nostartfiles -o $@ $<)
161
162do_build_static_lib = \
163 ($(print_static_lib_build) \
164 $(RM) $@; $(AR) rcs $@ $^)
165
166
167do_compile = $(QUIET_CC)$(CC) -c $(CFLAGS) $(EXT) $< -o $(obj)/$@;
168 134
169$(obj)/%.o: $(src)/%.c 135export srctree OUTPUT CC LD CFLAGS V
170 $(call do_compile) 136build := -f $(srctree)/tools/build/Makefile.build dir=. obj
171 137
172%.o: $(src)/%.c 138PLUGINS = plugin_jbd2.so
173 $(call do_compile) 139PLUGINS += plugin_hrtimer.so
140PLUGINS += plugin_kmem.so
141PLUGINS += plugin_kvm.so
142PLUGINS += plugin_mac80211.so
143PLUGINS += plugin_sched_switch.so
144PLUGINS += plugin_function.so
145PLUGINS += plugin_xen.so
146PLUGINS += plugin_scsi.so
147PLUGINS += plugin_cfg80211.so
174 148
175PEVENT_LIB_OBJS = event-parse.o 149PLUGINS := $(addprefix $(OUTPUT),$(PLUGINS))
176PEVENT_LIB_OBJS += event-plugin.o 150PLUGINS_IN := $(PLUGINS:.so=-in.o)
177PEVENT_LIB_OBJS += trace-seq.o
178PEVENT_LIB_OBJS += parse-filter.o
179PEVENT_LIB_OBJS += parse-utils.o
180PEVENT_LIB_OBJS += kbuffer-parse.o
181 151
182PLUGIN_OBJS = plugin_jbd2.o 152TE_IN := $(OUTPUT)libtraceevent-in.o
183PLUGIN_OBJS += plugin_hrtimer.o 153LIB_FILE := $(addprefix $(OUTPUT),$(LIB_FILE))
184PLUGIN_OBJS += plugin_kmem.o
185PLUGIN_OBJS += plugin_kvm.o
186PLUGIN_OBJS += plugin_mac80211.o
187PLUGIN_OBJS += plugin_sched_switch.o
188PLUGIN_OBJS += plugin_function.o
189PLUGIN_OBJS += plugin_xen.o
190PLUGIN_OBJS += plugin_scsi.o
191PLUGIN_OBJS += plugin_cfg80211.o
192
193PLUGINS := $(PLUGIN_OBJS:.o=.so)
194
195ALL_OBJS = $(PEVENT_LIB_OBJS) $(PLUGIN_OBJS)
196 154
197CMD_TARGETS = $(LIB_FILE) $(PLUGINS) 155CMD_TARGETS = $(LIB_FILE) $(PLUGINS)
198 156
199TARGETS = $(CMD_TARGETS) 157TARGETS = $(CMD_TARGETS)
200 158
201
202all: all_cmd 159all: all_cmd
203 160
204all_cmd: $(CMD_TARGETS) 161all_cmd: $(CMD_TARGETS)
205 162
206libtraceevent.so: $(PEVENT_LIB_OBJS) 163$(TE_IN): force
164 $(Q)$(MAKE) $(build)=libtraceevent
165
166$(OUTPUT)libtraceevent.so: $(TE_IN)
207 $(QUIET_LINK)$(CC) --shared $^ -o $@ 167 $(QUIET_LINK)$(CC) --shared $^ -o $@
208 168
209libtraceevent.a: $(PEVENT_LIB_OBJS) 169$(OUTPUT)libtraceevent.a: $(TE_IN)
210 $(QUIET_LINK)$(RM) $@; $(AR) rcs $@ $^ 170 $(QUIET_LINK)$(RM) $@; $(AR) rcs $@ $^
211 171
212plugins: $(PLUGINS) 172plugins: $(PLUGINS)
213 173
214$(PEVENT_LIB_OBJS): %.o: $(src)/%.c TRACEEVENT-CFLAGS 174__plugin_obj = $(notdir $@)
215 $(QUIET_CC_FPIC)$(CC) -c $(CFLAGS) $(EXT) -fPIC $< -o $@ 175 plugin_obj = $(__plugin_obj:-in.o=)
216 176
217$(PLUGIN_OBJS): %.o : $(src)/%.c 177$(PLUGINS_IN): force
218 $(QUIET_CC_FPIC)$(CC) -c $(CFLAGS) -fPIC -o $@ $< 178 $(Q)$(MAKE) $(build)=$(plugin_obj)
219 179
220$(PLUGINS): %.so: %.o 180$(OUTPUT)%.so: $(OUTPUT)%-in.o
221 $(QUIET_LINK)$(CC) $(CFLAGS) -shared -nostartfiles -o $@ $< 181 $(QUIET_LINK)$(CC) $(CFLAGS) -shared -nostartfiles -o $@ $^
222 182
223define make_version.h 183define make_version.h
224 (echo '/* This file is automatically generated. Do not modify. */'; \ 184 (echo '/* This file is automatically generated. Do not modify. */'; \
@@ -255,40 +215,6 @@ define update_dir
255 fi); 215 fi);
256endef 216endef
257 217
258## make deps
259
260all_objs := $(sort $(ALL_OBJS))
261all_deps := $(all_objs:%.o=.%.d)
262
263# let .d file also depends on the source and header files
264define check_deps
265 @set -e; $(RM) $@; \
266 $(CC) -MM $(CFLAGS) $< > $@.$$$$; \
267 sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
268 $(RM) $@.$$$$
269endef
270
271$(all_deps): .%.d: $(src)/%.c
272 $(Q)$(call check_deps)
273
274$(all_objs) : %.o : .%.d
275
276dep_includes := $(wildcard $(all_deps))
277
278ifneq ($(dep_includes),)
279 include $(dep_includes)
280endif
281
282### Detect environment changes
283TRACK_CFLAGS = $(subst ','\'',$(CFLAGS)):$(ARCH):$(CROSS_COMPILE)
284
285TRACEEVENT-CFLAGS: force
286 @FLAGS='$(TRACK_CFLAGS)'; \
287 if test x"$$FLAGS" != x"`cat TRACEEVENT-CFLAGS 2>/dev/null`" ; then \
288 echo 1>&2 " FLAGS: * new build flags or cross compiler"; \
289 echo "$$FLAGS" >TRACEEVENT-CFLAGS; \
290 fi
291
292tags: force 218tags: force
293 $(RM) tags 219 $(RM) tags
294 find . -name '*.[ch]' | xargs ctags --extra=+f --c-kinds=+px \ 220 find . -name '*.[ch]' | xargs ctags --extra=+f --c-kinds=+px \
@@ -327,14 +253,9 @@ clean:
327 $(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d \ 253 $(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d \
328 $(RM) TRACEEVENT-CFLAGS tags TAGS 254 $(RM) TRACEEVENT-CFLAGS tags TAGS
329 255
330endif # skip-makefile
331
332PHONY += force plugins 256PHONY += force plugins
333force: 257force:
334 258
335plugins:
336 @echo > /dev/null
337
338# Declare the contents of the .PHONY variable as phony. We keep that 259# Declare the contents of the .PHONY variable as phony. We keep that
339# information in a variable so we can use it in if_changed and friends. 260# information in a variable so we can use it in if_changed and friends.
340.PHONY: $(PHONY) 261.PHONY: $(PHONY)
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
index afe20ed9fac8..6d31b6419d37 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -304,7 +304,10 @@ int pevent_register_comm(struct pevent *pevent, const char *comm, int pid)
304 if (!item) 304 if (!item)
305 return -1; 305 return -1;
306 306
307 item->comm = strdup(comm); 307 if (comm)
308 item->comm = strdup(comm);
309 else
310 item->comm = strdup("<...>");
308 if (!item->comm) { 311 if (!item->comm) {
309 free(item); 312 free(item);
310 return -1; 313 return -1;
@@ -318,9 +321,14 @@ int pevent_register_comm(struct pevent *pevent, const char *comm, int pid)
318 return 0; 321 return 0;
319} 322}
320 323
321void pevent_register_trace_clock(struct pevent *pevent, char *trace_clock) 324int pevent_register_trace_clock(struct pevent *pevent, const char *trace_clock)
322{ 325{
323 pevent->trace_clock = trace_clock; 326 pevent->trace_clock = strdup(trace_clock);
327 if (!pevent->trace_clock) {
328 errno = ENOMEM;
329 return -1;
330 }
331 return 0;
324} 332}
325 333
326struct func_map { 334struct func_map {
@@ -758,6 +766,11 @@ static void free_arg(struct print_arg *arg)
758 free_arg(arg->hex.field); 766 free_arg(arg->hex.field);
759 free_arg(arg->hex.size); 767 free_arg(arg->hex.size);
760 break; 768 break;
769 case PRINT_INT_ARRAY:
770 free_arg(arg->int_array.field);
771 free_arg(arg->int_array.count);
772 free_arg(arg->int_array.el_size);
773 break;
761 case PRINT_TYPE: 774 case PRINT_TYPE:
762 free(arg->typecast.type); 775 free(arg->typecast.type);
763 free_arg(arg->typecast.item); 776 free_arg(arg->typecast.item);
@@ -2014,6 +2027,38 @@ process_entry(struct event_format *event __maybe_unused, struct print_arg *arg,
2014 return EVENT_ERROR; 2027 return EVENT_ERROR;
2015} 2028}
2016 2029
2030static int alloc_and_process_delim(struct event_format *event, char *next_token,
2031 struct print_arg **print_arg)
2032{
2033 struct print_arg *field;
2034 enum event_type type;
2035 char *token;
2036 int ret = 0;
2037
2038 field = alloc_arg();
2039 if (!field) {
2040 do_warning_event(event, "%s: not enough memory!", __func__);
2041 errno = ENOMEM;
2042 return -1;
2043 }
2044
2045 type = process_arg(event, field, &token);
2046
2047 if (test_type_token(type, token, EVENT_DELIM, next_token)) {
2048 errno = EINVAL;
2049 ret = -1;
2050 free_arg(field);
2051 goto out_free_token;
2052 }
2053
2054 *print_arg = field;
2055
2056out_free_token:
2057 free_token(token);
2058
2059 return ret;
2060}
2061
2017static char *arg_eval (struct print_arg *arg); 2062static char *arg_eval (struct print_arg *arg);
2018 2063
2019static unsigned long long 2064static unsigned long long
@@ -2486,49 +2531,46 @@ out_free:
2486static enum event_type 2531static enum event_type
2487process_hex(struct event_format *event, struct print_arg *arg, char **tok) 2532process_hex(struct event_format *event, struct print_arg *arg, char **tok)
2488{ 2533{
2489 struct print_arg *field;
2490 enum event_type type;
2491 char *token = NULL;
2492
2493 memset(arg, 0, sizeof(*arg)); 2534 memset(arg, 0, sizeof(*arg));
2494 arg->type = PRINT_HEX; 2535 arg->type = PRINT_HEX;
2495 2536
2496 field = alloc_arg(); 2537 if (alloc_and_process_delim(event, ",", &arg->hex.field))
2497 if (!field) { 2538 goto out;
2498 do_warning_event(event, "%s: not enough memory!", __func__);
2499 goto out_free;
2500 }
2501
2502 type = process_arg(event, field, &token);
2503 2539
2504 if (test_type_token(type, token, EVENT_DELIM, ",")) 2540 if (alloc_and_process_delim(event, ")", &arg->hex.size))
2505 goto out_free; 2541 goto free_field;
2506 2542
2507 arg->hex.field = field; 2543 return read_token_item(tok);
2508 2544
2509 free_token(token); 2545free_field:
2546 free_arg(arg->hex.field);
2547out:
2548 *tok = NULL;
2549 return EVENT_ERROR;
2550}
2510 2551
2511 field = alloc_arg(); 2552static enum event_type
2512 if (!field) { 2553process_int_array(struct event_format *event, struct print_arg *arg, char **tok)
2513 do_warning_event(event, "%s: not enough memory!", __func__); 2554{
2514 *tok = NULL; 2555 memset(arg, 0, sizeof(*arg));
2515 return EVENT_ERROR; 2556 arg->type = PRINT_INT_ARRAY;
2516 }
2517 2557
2518 type = process_arg(event, field, &token); 2558 if (alloc_and_process_delim(event, ",", &arg->int_array.field))
2559 goto out;
2519 2560
2520 if (test_type_token(type, token, EVENT_DELIM, ")")) 2561 if (alloc_and_process_delim(event, ",", &arg->int_array.count))
2521 goto out_free; 2562 goto free_field;
2522 2563
2523 arg->hex.size = field; 2564 if (alloc_and_process_delim(event, ")", &arg->int_array.el_size))
2565 goto free_size;
2524 2566
2525 free_token(token); 2567 return read_token_item(tok);
2526 type = read_token_item(tok);
2527 return type;
2528 2568
2529 out_free: 2569free_size:
2530 free_arg(field); 2570 free_arg(arg->int_array.count);
2531 free_token(token); 2571free_field:
2572 free_arg(arg->int_array.field);
2573out:
2532 *tok = NULL; 2574 *tok = NULL;
2533 return EVENT_ERROR; 2575 return EVENT_ERROR;
2534} 2576}
@@ -2828,6 +2870,10 @@ process_function(struct event_format *event, struct print_arg *arg,
2828 free_token(token); 2870 free_token(token);
2829 return process_hex(event, arg, tok); 2871 return process_hex(event, arg, tok);
2830 } 2872 }
2873 if (strcmp(token, "__print_array") == 0) {
2874 free_token(token);
2875 return process_int_array(event, arg, tok);
2876 }
2831 if (strcmp(token, "__get_str") == 0) { 2877 if (strcmp(token, "__get_str") == 0) {
2832 free_token(token); 2878 free_token(token);
2833 return process_str(event, arg, tok); 2879 return process_str(event, arg, tok);
@@ -3356,6 +3402,7 @@ eval_num_arg(void *data, int size, struct event_format *event, struct print_arg
3356 break; 3402 break;
3357 case PRINT_FLAGS: 3403 case PRINT_FLAGS:
3358 case PRINT_SYMBOL: 3404 case PRINT_SYMBOL:
3405 case PRINT_INT_ARRAY:
3359 case PRINT_HEX: 3406 case PRINT_HEX:
3360 break; 3407 break;
3361 case PRINT_TYPE: 3408 case PRINT_TYPE:
@@ -3568,7 +3615,7 @@ static const struct flag flags[] = {
3568 { "HRTIMER_RESTART", 1 }, 3615 { "HRTIMER_RESTART", 1 },
3569}; 3616};
3570 3617
3571static unsigned long long eval_flag(const char *flag) 3618static long long eval_flag(const char *flag)
3572{ 3619{
3573 int i; 3620 int i;
3574 3621
@@ -3584,7 +3631,7 @@ static unsigned long long eval_flag(const char *flag)
3584 if (strcmp(flags[i].name, flag) == 0) 3631 if (strcmp(flags[i].name, flag) == 0)
3585 return flags[i].value; 3632 return flags[i].value;
3586 3633
3587 return 0; 3634 return -1LL;
3588} 3635}
3589 3636
3590static void print_str_to_seq(struct trace_seq *s, const char *format, 3637static void print_str_to_seq(struct trace_seq *s, const char *format,
@@ -3658,7 +3705,7 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
3658 struct print_flag_sym *flag; 3705 struct print_flag_sym *flag;
3659 struct format_field *field; 3706 struct format_field *field;
3660 struct printk_map *printk; 3707 struct printk_map *printk;
3661 unsigned long long val, fval; 3708 long long val, fval;
3662 unsigned long addr; 3709 unsigned long addr;
3663 char *str; 3710 char *str;
3664 unsigned char *hex; 3711 unsigned char *hex;
@@ -3717,11 +3764,11 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
3717 print = 0; 3764 print = 0;
3718 for (flag = arg->flags.flags; flag; flag = flag->next) { 3765 for (flag = arg->flags.flags; flag; flag = flag->next) {
3719 fval = eval_flag(flag->value); 3766 fval = eval_flag(flag->value);
3720 if (!val && !fval) { 3767 if (!val && fval < 0) {
3721 print_str_to_seq(s, format, len_arg, flag->str); 3768 print_str_to_seq(s, format, len_arg, flag->str);
3722 break; 3769 break;
3723 } 3770 }
3724 if (fval && (val & fval) == fval) { 3771 if (fval > 0 && (val & fval) == fval) {
3725 if (print && arg->flags.delim) 3772 if (print && arg->flags.delim)
3726 trace_seq_puts(s, arg->flags.delim); 3773 trace_seq_puts(s, arg->flags.delim);
3727 print_str_to_seq(s, format, len_arg, flag->str); 3774 print_str_to_seq(s, format, len_arg, flag->str);
@@ -3766,6 +3813,54 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
3766 } 3813 }
3767 break; 3814 break;
3768 3815
3816 case PRINT_INT_ARRAY: {
3817 void *num;
3818 int el_size;
3819
3820 if (arg->int_array.field->type == PRINT_DYNAMIC_ARRAY) {
3821 unsigned long offset;
3822 struct format_field *field =
3823 arg->int_array.field->dynarray.field;
3824 offset = pevent_read_number(pevent,
3825 data + field->offset,
3826 field->size);
3827 num = data + (offset & 0xffff);
3828 } else {
3829 field = arg->int_array.field->field.field;
3830 if (!field) {
3831 str = arg->int_array.field->field.name;
3832 field = pevent_find_any_field(event, str);
3833 if (!field)
3834 goto out_warning_field;
3835 arg->int_array.field->field.field = field;
3836 }
3837 num = data + field->offset;
3838 }
3839 len = eval_num_arg(data, size, event, arg->int_array.count);
3840 el_size = eval_num_arg(data, size, event,
3841 arg->int_array.el_size);
3842 for (i = 0; i < len; i++) {
3843 if (i)
3844 trace_seq_putc(s, ' ');
3845
3846 if (el_size == 1) {
3847 trace_seq_printf(s, "%u", *(uint8_t *)num);
3848 } else if (el_size == 2) {
3849 trace_seq_printf(s, "%u", *(uint16_t *)num);
3850 } else if (el_size == 4) {
3851 trace_seq_printf(s, "%u", *(uint32_t *)num);
3852 } else if (el_size == 8) {
3853 trace_seq_printf(s, "%lu", *(uint64_t *)num);
3854 } else {
3855 trace_seq_printf(s, "BAD SIZE:%d 0x%x",
3856 el_size, *(uint8_t *)num);
3857 el_size = 1;
3858 }
3859
3860 num += el_size;
3861 }
3862 break;
3863 }
3769 case PRINT_TYPE: 3864 case PRINT_TYPE:
3770 break; 3865 break;
3771 case PRINT_STRING: { 3866 case PRINT_STRING: {
@@ -3997,6 +4092,10 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc
3997 goto process_again; 4092 goto process_again;
3998 case '.': 4093 case '.':
3999 goto process_again; 4094 goto process_again;
4095 case 'z':
4096 case 'Z':
4097 ls = 1;
4098 goto process_again;
4000 case 'p': 4099 case 'p':
4001 ls = 1; 4100 ls = 1;
4002 /* fall through */ 4101 /* fall through */
@@ -4939,6 +5038,96 @@ const char *pevent_data_comm_from_pid(struct pevent *pevent, int pid)
4939 return comm; 5038 return comm;
4940} 5039}
4941 5040
5041static struct cmdline *
5042pid_from_cmdlist(struct pevent *pevent, const char *comm, struct cmdline *next)
5043{
5044 struct cmdline_list *cmdlist = (struct cmdline_list *)next;
5045
5046 if (cmdlist)
5047 cmdlist = cmdlist->next;
5048 else
5049 cmdlist = pevent->cmdlist;
5050
5051 while (cmdlist && strcmp(cmdlist->comm, comm) != 0)
5052 cmdlist = cmdlist->next;
5053
5054 return (struct cmdline *)cmdlist;
5055}
5056
5057/**
5058 * pevent_data_pid_from_comm - return the pid from a given comm
5059 * @pevent: a handle to the pevent
5060 * @comm: the cmdline to find the pid from
5061 * @next: the cmdline structure to find the next comm
5062 *
5063 * This returns the cmdline structure that holds a pid for a given
5064 * comm, or NULL if none found. As there may be more than one pid for
5065 * a given comm, the result of this call can be passed back into
5066 * a recurring call in the @next paramater, and then it will find the
5067 * next pid.
5068 * Also, it does a linear seach, so it may be slow.
5069 */
5070struct cmdline *pevent_data_pid_from_comm(struct pevent *pevent, const char *comm,
5071 struct cmdline *next)
5072{
5073 struct cmdline *cmdline;
5074
5075 /*
5076 * If the cmdlines have not been converted yet, then use
5077 * the list.
5078 */
5079 if (!pevent->cmdlines)
5080 return pid_from_cmdlist(pevent, comm, next);
5081
5082 if (next) {
5083 /*
5084 * The next pointer could have been still from
5085 * a previous call before cmdlines were created
5086 */
5087 if (next < pevent->cmdlines ||
5088 next >= pevent->cmdlines + pevent->cmdline_count)
5089 next = NULL;
5090 else
5091 cmdline = next++;
5092 }
5093
5094 if (!next)
5095 cmdline = pevent->cmdlines;
5096
5097 while (cmdline < pevent->cmdlines + pevent->cmdline_count) {
5098 if (strcmp(cmdline->comm, comm) == 0)
5099 return cmdline;
5100 cmdline++;
5101 }
5102 return NULL;
5103}
5104
5105/**
5106 * pevent_cmdline_pid - return the pid associated to a given cmdline
5107 * @cmdline: The cmdline structure to get the pid from
5108 *
5109 * Returns the pid for a give cmdline. If @cmdline is NULL, then
5110 * -1 is returned.
5111 */
5112int pevent_cmdline_pid(struct pevent *pevent, struct cmdline *cmdline)
5113{
5114 struct cmdline_list *cmdlist = (struct cmdline_list *)cmdline;
5115
5116 if (!cmdline)
5117 return -1;
5118
5119 /*
5120 * If cmdlines have not been created yet, or cmdline is
5121 * not part of the array, then treat it as a cmdlist instead.
5122 */
5123 if (!pevent->cmdlines ||
5124 cmdline < pevent->cmdlines ||
5125 cmdline >= pevent->cmdlines + pevent->cmdline_count)
5126 return cmdlist->pid;
5127
5128 return cmdline->pid;
5129}
5130
4942/** 5131/**
4943 * pevent_data_comm_from_pid - parse the data into the print format 5132 * pevent_data_comm_from_pid - parse the data into the print format
4944 * @s: the trace_seq to write to 5133 * @s: the trace_seq to write to
@@ -5256,6 +5445,15 @@ static void print_args(struct print_arg *args)
5256 print_args(args->hex.size); 5445 print_args(args->hex.size);
5257 printf(")"); 5446 printf(")");
5258 break; 5447 break;
5448 case PRINT_INT_ARRAY:
5449 printf("__print_array(");
5450 print_args(args->int_array.field);
5451 printf(", ");
5452 print_args(args->int_array.count);
5453 printf(", ");
5454 print_args(args->int_array.el_size);
5455 printf(")");
5456 break;
5259 case PRINT_STRING: 5457 case PRINT_STRING:
5260 case PRINT_BSTRING: 5458 case PRINT_BSTRING:
5261 printf("__get_str(%s)", args->string.string); 5459 printf("__get_str(%s)", args->string.string);
@@ -6228,15 +6426,20 @@ void pevent_ref(struct pevent *pevent)
6228 pevent->ref_count++; 6426 pevent->ref_count++;
6229} 6427}
6230 6428
6429void pevent_free_format_field(struct format_field *field)
6430{
6431 free(field->type);
6432 free(field->name);
6433 free(field);
6434}
6435
6231static void free_format_fields(struct format_field *field) 6436static void free_format_fields(struct format_field *field)
6232{ 6437{
6233 struct format_field *next; 6438 struct format_field *next;
6234 6439
6235 while (field) { 6440 while (field) {
6236 next = field->next; 6441 next = field->next;
6237 free(field->type); 6442 pevent_free_format_field(field);
6238 free(field->name);
6239 free(field);
6240 field = next; 6443 field = next;
6241 } 6444 }
6242} 6445}
@@ -6341,6 +6544,7 @@ void pevent_free(struct pevent *pevent)
6341 free_handler(handle); 6544 free_handler(handle);
6342 } 6545 }
6343 6546
6547 free(pevent->trace_clock);
6344 free(pevent->events); 6548 free(pevent->events);
6345 free(pevent->sort_events); 6549 free(pevent->sort_events);
6346 6550
diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h
index 7a3873ff9a4f..86a5839fb048 100644
--- a/tools/lib/traceevent/event-parse.h
+++ b/tools/lib/traceevent/event-parse.h
@@ -22,6 +22,7 @@
22 22
23#include <stdbool.h> 23#include <stdbool.h>
24#include <stdarg.h> 24#include <stdarg.h>
25#include <stdio.h>
25#include <regex.h> 26#include <regex.h>
26#include <string.h> 27#include <string.h>
27 28
@@ -91,6 +92,7 @@ extern int trace_seq_putc(struct trace_seq *s, unsigned char c);
91 92
92extern void trace_seq_terminate(struct trace_seq *s); 93extern void trace_seq_terminate(struct trace_seq *s);
93 94
95extern int trace_seq_do_fprintf(struct trace_seq *s, FILE *fp);
94extern int trace_seq_do_printf(struct trace_seq *s); 96extern int trace_seq_do_printf(struct trace_seq *s);
95 97
96 98
@@ -114,7 +116,7 @@ struct pevent_plugin_option {
114 char *name; 116 char *name;
115 char *plugin_alias; 117 char *plugin_alias;
116 char *description; 118 char *description;
117 char *value; 119 const char *value;
118 void *priv; 120 void *priv;
119 int set; 121 int set;
120}; 122};
@@ -152,6 +154,10 @@ struct pevent_plugin_option {
152 * .plugin_alias is used to give a shorter name to access 154 * .plugin_alias is used to give a shorter name to access
153 * the vairable. Useful if a plugin handles more than one event. 155 * the vairable. Useful if a plugin handles more than one event.
154 * 156 *
157 * If .value is not set, then it is considered a boolean and only
158 * .set will be processed. If .value is defined, then it is considered
159 * a string option and .set will be ignored.
160 *
155 * PEVENT_PLUGIN_ALIAS: (optional) 161 * PEVENT_PLUGIN_ALIAS: (optional)
156 * The name to use for finding options (uses filename if not defined) 162 * The name to use for finding options (uses filename if not defined)
157 */ 163 */
@@ -245,6 +251,12 @@ struct print_arg_hex {
245 struct print_arg *size; 251 struct print_arg *size;
246}; 252};
247 253
254struct print_arg_int_array {
255 struct print_arg *field;
256 struct print_arg *count;
257 struct print_arg *el_size;
258};
259
248struct print_arg_dynarray { 260struct print_arg_dynarray {
249 struct format_field *field; 261 struct format_field *field;
250 struct print_arg *index; 262 struct print_arg *index;
@@ -273,6 +285,7 @@ enum print_arg_type {
273 PRINT_FLAGS, 285 PRINT_FLAGS,
274 PRINT_SYMBOL, 286 PRINT_SYMBOL,
275 PRINT_HEX, 287 PRINT_HEX,
288 PRINT_INT_ARRAY,
276 PRINT_TYPE, 289 PRINT_TYPE,
277 PRINT_STRING, 290 PRINT_STRING,
278 PRINT_BSTRING, 291 PRINT_BSTRING,
@@ -292,6 +305,7 @@ struct print_arg {
292 struct print_arg_flags flags; 305 struct print_arg_flags flags;
293 struct print_arg_symbol symbol; 306 struct print_arg_symbol symbol;
294 struct print_arg_hex hex; 307 struct print_arg_hex hex;
308 struct print_arg_int_array int_array;
295 struct print_arg_func func; 309 struct print_arg_func func;
296 struct print_arg_string string; 310 struct print_arg_string string;
297 struct print_arg_bitmask bitmask; 311 struct print_arg_bitmask bitmask;
@@ -597,7 +611,7 @@ enum trace_flag_type {
597}; 611};
598 612
599int pevent_register_comm(struct pevent *pevent, const char *comm, int pid); 613int pevent_register_comm(struct pevent *pevent, const char *comm, int pid);
600void pevent_register_trace_clock(struct pevent *pevent, char *trace_clock); 614int pevent_register_trace_clock(struct pevent *pevent, const char *trace_clock);
601int pevent_register_function(struct pevent *pevent, char *name, 615int pevent_register_function(struct pevent *pevent, char *name,
602 unsigned long long addr, char *mod); 616 unsigned long long addr, char *mod);
603int pevent_register_print_string(struct pevent *pevent, const char *fmt, 617int pevent_register_print_string(struct pevent *pevent, const char *fmt,
@@ -617,6 +631,7 @@ enum pevent_errno pevent_parse_format(struct pevent *pevent,
617 const char *buf, 631 const char *buf,
618 unsigned long size, const char *sys); 632 unsigned long size, const char *sys);
619void pevent_free_format(struct event_format *event); 633void pevent_free_format(struct event_format *event);
634void pevent_free_format_field(struct format_field *field);
620 635
621void *pevent_get_field_raw(struct trace_seq *s, struct event_format *event, 636void *pevent_get_field_raw(struct trace_seq *s, struct event_format *event,
622 const char *name, struct pevent_record *record, 637 const char *name, struct pevent_record *record,
@@ -675,6 +690,11 @@ int pevent_data_type(struct pevent *pevent, struct pevent_record *rec);
675struct event_format *pevent_data_event_from_type(struct pevent *pevent, int type); 690struct event_format *pevent_data_event_from_type(struct pevent *pevent, int type);
676int pevent_data_pid(struct pevent *pevent, struct pevent_record *rec); 691int pevent_data_pid(struct pevent *pevent, struct pevent_record *rec);
677const char *pevent_data_comm_from_pid(struct pevent *pevent, int pid); 692const char *pevent_data_comm_from_pid(struct pevent *pevent, int pid);
693struct cmdline;
694struct cmdline *pevent_data_pid_from_comm(struct pevent *pevent, const char *comm,
695 struct cmdline *next);
696int pevent_cmdline_pid(struct pevent *pevent, struct cmdline *cmdline);
697
678void pevent_event_info(struct trace_seq *s, struct event_format *event, 698void pevent_event_info(struct trace_seq *s, struct event_format *event,
679 struct pevent_record *record); 699 struct pevent_record *record);
680int pevent_strerror(struct pevent *pevent, enum pevent_errno errnum, 700int pevent_strerror(struct pevent *pevent, enum pevent_errno errnum,
diff --git a/tools/lib/traceevent/event-plugin.c b/tools/lib/traceevent/event-plugin.c
index 136162c03af1..a16756ae3526 100644
--- a/tools/lib/traceevent/event-plugin.c
+++ b/tools/lib/traceevent/event-plugin.c
@@ -18,6 +18,7 @@
18 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 18 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
19 */ 19 */
20 20
21#include <ctype.h>
21#include <stdio.h> 22#include <stdio.h>
22#include <string.h> 23#include <string.h>
23#include <dlfcn.h> 24#include <dlfcn.h>
@@ -49,6 +50,52 @@ struct plugin_list {
49 void *handle; 50 void *handle;
50}; 51};
51 52
53static void lower_case(char *str)
54{
55 if (!str)
56 return;
57 for (; *str; str++)
58 *str = tolower(*str);
59}
60
61static int update_option_value(struct pevent_plugin_option *op, const char *val)
62{
63 char *op_val;
64
65 if (!val) {
66 /* toggle, only if option is boolean */
67 if (op->value)
68 /* Warn? */
69 return 0;
70 op->set ^= 1;
71 return 0;
72 }
73
74 /*
75 * If the option has a value then it takes a string
76 * otherwise the option is a boolean.
77 */
78 if (op->value) {
79 op->value = val;
80 return 0;
81 }
82
83 /* Option is boolean, must be either "1", "0", "true" or "false" */
84
85 op_val = strdup(val);
86 if (!op_val)
87 return -1;
88 lower_case(op_val);
89
90 if (strcmp(val, "1") == 0 || strcmp(val, "true") == 0)
91 op->set = 1;
92 else if (strcmp(val, "0") == 0 || strcmp(val, "false") == 0)
93 op->set = 0;
94 free(op_val);
95
96 return 0;
97}
98
52/** 99/**
53 * traceevent_plugin_list_options - get list of plugin options 100 * traceevent_plugin_list_options - get list of plugin options
54 * 101 *
@@ -120,6 +167,7 @@ update_option(const char *file, struct pevent_plugin_option *option)
120{ 167{
121 struct trace_plugin_options *op; 168 struct trace_plugin_options *op;
122 char *plugin; 169 char *plugin;
170 int ret = 0;
123 171
124 if (option->plugin_alias) { 172 if (option->plugin_alias) {
125 plugin = strdup(option->plugin_alias); 173 plugin = strdup(option->plugin_alias);
@@ -144,9 +192,10 @@ update_option(const char *file, struct pevent_plugin_option *option)
144 if (strcmp(op->option, option->name) != 0) 192 if (strcmp(op->option, option->name) != 0)
145 continue; 193 continue;
146 194
147 option->value = op->value; 195 ret = update_option_value(option, op->value);
148 option->set ^= 1; 196 if (ret)
149 goto out; 197 goto out;
198 break;
150 } 199 }
151 200
152 /* first look for unnamed options */ 201 /* first look for unnamed options */
@@ -156,14 +205,13 @@ update_option(const char *file, struct pevent_plugin_option *option)
156 if (strcmp(op->option, option->name) != 0) 205 if (strcmp(op->option, option->name) != 0)
157 continue; 206 continue;
158 207
159 option->value = op->value; 208 ret = update_option_value(option, op->value);
160 option->set ^= 1;
161 break; 209 break;
162 } 210 }
163 211
164 out: 212 out:
165 free(plugin); 213 free(plugin);
166 return 0; 214 return ret;
167} 215}
168 216
169/** 217/**
diff --git a/tools/lib/traceevent/kbuffer-parse.c b/tools/lib/traceevent/kbuffer-parse.c
index dcc665228c71..3bcada3ae05a 100644
--- a/tools/lib/traceevent/kbuffer-parse.c
+++ b/tools/lib/traceevent/kbuffer-parse.c
@@ -372,7 +372,6 @@ translate_data(struct kbuffer *kbuf, void *data, void **rptr,
372 switch (type_len) { 372 switch (type_len) {
373 case KBUFFER_TYPE_PADDING: 373 case KBUFFER_TYPE_PADDING:
374 *length = read_4(kbuf, data); 374 *length = read_4(kbuf, data);
375 data += *length;
376 break; 375 break;
377 376
378 case KBUFFER_TYPE_TIME_EXTEND: 377 case KBUFFER_TYPE_TIME_EXTEND:
@@ -730,3 +729,14 @@ void kbuffer_set_old_format(struct kbuffer *kbuf)
730 729
731 kbuf->next_event = __old_next_event; 730 kbuf->next_event = __old_next_event;
732} 731}
732
733/**
734 * kbuffer_start_of_data - return offset of where data starts on subbuffer
735 * @kbuf: The kbuffer
736 *
737 * Returns the location on the subbuffer where the data starts.
738 */
739int kbuffer_start_of_data(struct kbuffer *kbuf)
740{
741 return kbuf->start;
742}
diff --git a/tools/lib/traceevent/kbuffer.h b/tools/lib/traceevent/kbuffer.h
index c831f64b17a0..03dce757553f 100644
--- a/tools/lib/traceevent/kbuffer.h
+++ b/tools/lib/traceevent/kbuffer.h
@@ -63,5 +63,6 @@ int kbuffer_missed_events(struct kbuffer *kbuf);
63int kbuffer_subbuffer_size(struct kbuffer *kbuf); 63int kbuffer_subbuffer_size(struct kbuffer *kbuf);
64 64
65void kbuffer_set_old_format(struct kbuffer *kbuf); 65void kbuffer_set_old_format(struct kbuffer *kbuf);
66int kbuffer_start_of_data(struct kbuffer *kbuf);
66 67
67#endif /* _K_BUFFER_H */ 68#endif /* _K_BUFFER_H */
diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c
index b50234402fc2..0144b3d1bb77 100644
--- a/tools/lib/traceevent/parse-filter.c
+++ b/tools/lib/traceevent/parse-filter.c
@@ -1058,6 +1058,7 @@ process_filter(struct event_format *event, struct filter_arg **parg,
1058 *parg = current_op; 1058 *parg = current_op;
1059 else 1059 else
1060 *parg = current_exp; 1060 *parg = current_exp;
1061 free(token);
1061 return PEVENT_ERRNO__UNBALANCED_PAREN; 1062 return PEVENT_ERRNO__UNBALANCED_PAREN;
1062 } 1063 }
1063 break; 1064 break;
@@ -1168,6 +1169,7 @@ process_filter(struct event_format *event, struct filter_arg **parg,
1168 1169
1169 *parg = current_op; 1170 *parg = current_op;
1170 1171
1172 free(token);
1171 return 0; 1173 return 0;
1172 1174
1173 fail_alloc: 1175 fail_alloc:
diff --git a/tools/lib/traceevent/trace-seq.c b/tools/lib/traceevent/trace-seq.c
index ec3bd16a5488..292dc9f1d233 100644
--- a/tools/lib/traceevent/trace-seq.c
+++ b/tools/lib/traceevent/trace-seq.c
@@ -231,19 +231,24 @@ void trace_seq_terminate(struct trace_seq *s)
231 s->buffer[s->len] = 0; 231 s->buffer[s->len] = 0;
232} 232}
233 233
234int trace_seq_do_printf(struct trace_seq *s) 234int trace_seq_do_fprintf(struct trace_seq *s, FILE *fp)
235{ 235{
236 TRACE_SEQ_CHECK(s); 236 TRACE_SEQ_CHECK(s);
237 237
238 switch (s->state) { 238 switch (s->state) {
239 case TRACE_SEQ__GOOD: 239 case TRACE_SEQ__GOOD:
240 return printf("%.*s", s->len, s->buffer); 240 return fprintf(fp, "%.*s", s->len, s->buffer);
241 case TRACE_SEQ__BUFFER_POISONED: 241 case TRACE_SEQ__BUFFER_POISONED:
242 puts("Usage of trace_seq after it was destroyed"); 242 fprintf(fp, "%s\n", "Usage of trace_seq after it was destroyed");
243 break; 243 break;
244 case TRACE_SEQ__MEM_ALLOC_FAILED: 244 case TRACE_SEQ__MEM_ALLOC_FAILED:
245 puts("Can't allocate trace_seq buffer memory"); 245 fprintf(fp, "%s\n", "Can't allocate trace_seq buffer memory");
246 break; 246 break;
247 } 247 }
248 return -1; 248 return -1;
249} 249}
250
251int trace_seq_do_printf(struct trace_seq *s)
252{
253 return trace_seq_do_fprintf(s, stdout);
254}
diff --git a/tools/perf/.gitignore b/tools/perf/.gitignore
index 40399c3d97d6..812f904193e8 100644
--- a/tools/perf/.gitignore
+++ b/tools/perf/.gitignore
@@ -1,6 +1,7 @@
1PERF-CFLAGS 1PERF-CFLAGS
2PERF-GUI-VARS 2PERF-GUI-VARS
3PERF-VERSION-FILE 3PERF-VERSION-FILE
4FEATURE-DUMP
4perf 5perf
5perf-read-vdso32 6perf-read-vdso32
6perf-read-vdsox32 7perf-read-vdsox32
diff --git a/tools/perf/Build b/tools/perf/Build
new file mode 100644
index 000000000000..b77370ef7005
--- /dev/null
+++ b/tools/perf/Build
@@ -0,0 +1,44 @@
1perf-y += builtin-bench.o
2perf-y += builtin-annotate.o
3perf-y += builtin-diff.o
4perf-y += builtin-evlist.o
5perf-y += builtin-help.o
6perf-y += builtin-sched.o
7perf-y += builtin-buildid-list.o
8perf-y += builtin-buildid-cache.o
9perf-y += builtin-list.o
10perf-y += builtin-record.o
11perf-y += builtin-report.o
12perf-y += builtin-stat.o
13perf-y += builtin-timechart.o
14perf-y += builtin-top.o
15perf-y += builtin-script.o
16perf-y += builtin-kmem.o
17perf-y += builtin-lock.o
18perf-y += builtin-kvm.o
19perf-y += builtin-inject.o
20perf-y += builtin-mem.o
21perf-y += builtin-data.o
22
23perf-$(CONFIG_AUDIT) += builtin-trace.o
24perf-$(CONFIG_LIBELF) += builtin-probe.o
25
26perf-y += bench/
27perf-y += tests/
28
29perf-y += perf.o
30
31paths += -DPERF_HTML_PATH="BUILD_STR($(htmldir_SQ))"
32paths += -DPERF_INFO_PATH="BUILD_STR($(infodir_SQ))"
33paths += -DPERF_MAN_PATH="BUILD_STR($(mandir_SQ))"
34
35CFLAGS_builtin-help.o += $(paths)
36CFLAGS_builtin-timechart.o += $(paths)
37CFLAGS_perf.o += -DPERF_HTML_PATH="BUILD_STR($(htmldir_SQ))" -include $(OUTPUT)PERF-VERSION-FILE
38
39libperf-y += util/
40libperf-y += arch/
41libperf-y += ui/
42libperf-y += scripts/
43
44gtk-y += ui/gtk/
diff --git a/tools/perf/Documentation/Build.txt b/tools/perf/Documentation/Build.txt
new file mode 100644
index 000000000000..f6fc6507ba55
--- /dev/null
+++ b/tools/perf/Documentation/Build.txt
@@ -0,0 +1,49 @@
1
21) perf build
3=============
4The perf build process consists of several separated building blocks,
5which are linked together to form the perf binary:
6 - libperf library (static)
7 - perf builtin commands
8 - traceevent library (static)
9 - GTK ui library
10
11Several makefiles govern the perf build:
12
13 - Makefile
14 top level Makefile working as a wrapper that calls the main
15 Makefile.perf with a -j option to do parallel builds.
16
17 - Makefile.perf
18 main makefile that triggers build of all perf objects including
19 installation and documentation processing.
20
21 - tools/build/Makefile.build
22 main makefile of the build framework
23
24 - tools/build/Build.include
25 build framework generic definitions
26
27 - Build makefiles
28 makefiles that defines build objects
29
30Please refer to tools/build/Documentation/Build.txt for more
31information about build framework.
32
33
342) perf build
35=============
36The Makefile.perf triggers the build framework for build objects:
37 perf, libperf, gtk
38
39resulting in following objects:
40 $ ls *-in.o
41 gtk-in.o libperf-in.o perf-in.o
42
43Those objects are then used in final linking:
44 libperf-gtk.so <- gtk-in.o libperf-in.o
45 perf <- perf-in.o libperf-in.o
46
47
48NOTE this description is omitting other libraries involved, only
49 focusing on build framework outcomes
diff --git a/tools/perf/Documentation/perf-buildid-cache.txt b/tools/perf/Documentation/perf-buildid-cache.txt
index 0294c57b1f5e..dd07b55f58d8 100644
--- a/tools/perf/Documentation/perf-buildid-cache.txt
+++ b/tools/perf/Documentation/perf-buildid-cache.txt
@@ -12,9 +12,9 @@ SYNOPSIS
12 12
13DESCRIPTION 13DESCRIPTION
14----------- 14-----------
15This command manages the build-id cache. It can add and remove files to/from 15This command manages the build-id cache. It can add, remove, update and purge
16the cache. In the future it should as well purge older entries, set upper 16files to/from the cache. In the future it should as well set upper limits for
17limits for the space used by the cache, etc. 17the space used by the cache, etc.
18 18
19OPTIONS 19OPTIONS
20------- 20-------
@@ -36,14 +36,24 @@ OPTIONS
36 actually made. 36 actually made.
37-r:: 37-r::
38--remove=:: 38--remove=::
39 Remove specified file from the cache. 39 Remove a cached binary which has same build-id of specified file
40 from the cache.
41-p::
42--purge=::
43 Purge all cached binaries including older caches which have specified
44 path from the cache.
40-M:: 45-M::
41--missing=:: 46--missing=::
42 List missing build ids in the cache for the specified file. 47 List missing build ids in the cache for the specified file.
43-u:: 48-u::
44--update:: 49--update=::
45 Update specified file of the cache. It can be used to update kallsyms 50 Update specified file of the cache. Note that this doesn't remove
46 kernel dso to vmlinux in order to support annotation. 51 older entires since those may be still needed for annotating old
52 (or remote) perf.data. Only if there is already a cache which has
53 exactly same build-id, that is replaced by new one. It can be used
54 to update kallsyms and kernel dso to vmlinux in order to support
55 annotation.
56
47-v:: 57-v::
48--verbose:: 58--verbose::
49 Be more verbose. 59 Be more verbose.
diff --git a/tools/perf/Documentation/perf-data.txt b/tools/perf/Documentation/perf-data.txt
new file mode 100644
index 000000000000..be8fa1a0a97e
--- /dev/null
+++ b/tools/perf/Documentation/perf-data.txt
@@ -0,0 +1,40 @@
1perf-data(1)
2==============
3
4NAME
5----
6perf-data - Data file related processing
7
8SYNOPSIS
9--------
10[verse]
11'perf data' [<common options>] <command> [<options>]",
12
13DESCRIPTION
14-----------
15Data file related processing.
16
17COMMANDS
18--------
19convert::
20 Converts perf data file into another format (only CTF [1] format is support by now).
21 It's possible to set data-convert debug variable to get debug messages from conversion,
22 like:
23 perf --debug data-convert data convert ...
24
25OPTIONS for 'convert'
26---------------------
27--to-ctf::
28 Triggers the CTF conversion, specify the path of CTF data directory.
29
30-i::
31 Specify input perf data file path.
32
33-v::
34--verbose::
35 Be more verbose (show counter open errors, etc).
36
37SEE ALSO
38--------
39linkperf:perf[1]
40[1] Common Trace Format - http://www.efficios.com/ctf
diff --git a/tools/perf/Documentation/perf-diff.txt b/tools/perf/Documentation/perf-diff.txt
index e463caa3eb49..d1deb573877f 100644
--- a/tools/perf/Documentation/perf-diff.txt
+++ b/tools/perf/Documentation/perf-diff.txt
@@ -20,12 +20,20 @@ If no parameters are passed it will assume perf.data.old and perf.data.
20The differential profile is displayed only for events matching both 20The differential profile is displayed only for events matching both
21specified perf.data files. 21specified perf.data files.
22 22
23If no parameters are passed the samples will be sorted by dso and symbol.
24As the perf.data files could come from different binaries, the symbols addresses
25could vary. So perf diff is based on the comparison of the files and
26symbols name.
27
23OPTIONS 28OPTIONS
24------- 29-------
25-D:: 30-D::
26--dump-raw-trace:: 31--dump-raw-trace::
27 Dump raw trace in ASCII. 32 Dump raw trace in ASCII.
28 33
34--kallsyms=<file>::
35 kallsyms pathname
36
29-m:: 37-m::
30--modules:: 38--modules::
31 Load module symbols. WARNING: use only with -k and LIVE kernel 39 Load module symbols. WARNING: use only with -k and LIVE kernel
diff --git a/tools/perf/Documentation/perf-kmem.txt b/tools/perf/Documentation/perf-kmem.txt
index 7c8fbbf3f61c..150253cc3c97 100644
--- a/tools/perf/Documentation/perf-kmem.txt
+++ b/tools/perf/Documentation/perf-kmem.txt
@@ -25,6 +25,10 @@ OPTIONS
25--input=<file>:: 25--input=<file>::
26 Select the input file (default: perf.data unless stdin is a fifo) 26 Select the input file (default: perf.data unless stdin is a fifo)
27 27
28-v::
29--verbose::
30 Be more verbose. (show symbol address, etc)
31
28--caller:: 32--caller::
29 Show per-callsite statistics 33 Show per-callsite statistics
30 34
diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt
index 3e2aec94f806..4692d277980b 100644
--- a/tools/perf/Documentation/perf-list.txt
+++ b/tools/perf/Documentation/perf-list.txt
@@ -127,6 +127,12 @@ To limit the list use:
127One or more types can be used at the same time, listing the events for the 127One or more types can be used at the same time, listing the events for the
128types specified. 128types specified.
129 129
130Support raw format:
131
132. '--raw-dump', shows the raw-dump of all the events.
133. '--raw-dump [hw|sw|cache|tracepoint|pmu|event_glob]', shows the raw-dump of
134 a certain kind of events.
135
130SEE ALSO 136SEE ALSO
131-------- 137--------
132linkperf:perf-stat[1], linkperf:perf-top[1], 138linkperf:perf-stat[1], linkperf:perf-top[1],
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index aaa869be3dc1..239609c09f83 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -47,6 +47,12 @@ OPTIONS
47-v:: 47-v::
48--verbose:: 48--verbose::
49 Be more verbose (show parsed arguments, etc). 49 Be more verbose (show parsed arguments, etc).
50 Can not use with -q.
51
52-q::
53--quiet::
54 Be quiet (do not show any messages including errors).
55 Can not use with -v.
50 56
51-a:: 57-a::
52--add=:: 58--add=::
@@ -96,7 +102,7 @@ OPTIONS
96 Dry run. With this option, --add and --del doesn't execute actual 102 Dry run. With this option, --add and --del doesn't execute actual
97 adding and removal operations. 103 adding and removal operations.
98 104
99--max-probes:: 105--max-probes=NUM::
100 Set the maximum number of probe points for an event. Default is 128. 106 Set the maximum number of probe points for an event. Default is 128.
101 107
102-x:: 108-x::
@@ -104,8 +110,13 @@ OPTIONS
104 Specify path to the executable or shared library file for user 110 Specify path to the executable or shared library file for user
105 space tracing. Can also be used with --funcs option. 111 space tracing. Can also be used with --funcs option.
106 112
113--demangle::
114 Demangle application symbols. --no-demangle is also available
115 for disabling demangling.
116
107--demangle-kernel:: 117--demangle-kernel::
108 Demangle kernel symbols. 118 Demangle kernel symbols. --no-demangle-kernel is also available
119 for disabling kernel demangling.
109 120
110In absence of -m/-x options, perf probe checks if the first argument after 121In absence of -m/-x options, perf probe checks if the first argument after
111the options is an absolute path name. If its an absolute path, perf probe 122the options is an absolute path name. If its an absolute path, perf probe
@@ -137,6 +148,7 @@ Each probe argument follows below syntax.
137 [NAME=]LOCALVAR|$retval|%REG|@SYMBOL[:TYPE] 148 [NAME=]LOCALVAR|$retval|%REG|@SYMBOL[:TYPE]
138 149
139'NAME' specifies the name of this argument (optional). You can use the name of local variable, local data structure member (e.g. var->field, var.field2), local array with fixed index (e.g. array[1], var->array[0], var->pointer[2]), or kprobe-tracer argument format (e.g. $retval, %ax, etc). Note that the name of this argument will be set as the last member name if you specify a local data structure member (e.g. field2 for 'var->field1.field2'.) 150'NAME' specifies the name of this argument (optional). You can use the name of local variable, local data structure member (e.g. var->field, var.field2), local array with fixed index (e.g. array[1], var->array[0], var->pointer[2]), or kprobe-tracer argument format (e.g. $retval, %ax, etc). Note that the name of this argument will be set as the last member name if you specify a local data structure member (e.g. field2 for 'var->field1.field2'.)
151'$vars' special argument is also available for NAME, it is expanded to the local variables which can access at given probe point.
140'TYPE' casts the type of this argument (optional). If omitted, perf probe automatically set the type based on debuginfo. You can specify 'string' type only for the local variable or structure member which is an array of or a pointer to 'char' or 'unsigned char' type. 152'TYPE' casts the type of this argument (optional). If omitted, perf probe automatically set the type based on debuginfo. You can specify 'string' type only for the local variable or structure member which is an array of or a pointer to 'char' or 'unsigned char' type.
141 153
142On x86 systems %REG is always the short form of the register: for example %AX. %RAX or %EAX is not valid. 154On x86 systems %REG is always the short form of the register: for example %AX. %RAX or %EAX is not valid.
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 31e977459c51..355c4f5569b5 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -55,6 +55,11 @@ OPTIONS
55 If you want to profile write accesses in [0x1000~1008), just set 55 If you want to profile write accesses in [0x1000~1008), just set
56 'mem:0x1000/8:w'. 56 'mem:0x1000/8:w'.
57 57
58 - a group of events surrounded by a pair of brace ("{event1,event2,...}").
59 Each event is separated by commas and the group should be quoted to
60 prevent the shell interpretation. You also need to use --group on
61 "perf report" to view group events together.
62
58--filter=<filter>:: 63--filter=<filter>::
59 Event filter. 64 Event filter.
60 65
@@ -62,9 +67,6 @@ OPTIONS
62--all-cpus:: 67--all-cpus::
63 System-wide collection from all CPUs. 68 System-wide collection from all CPUs.
64 69
65-l::
66 Scale counter values.
67
68-p:: 70-p::
69--pid=:: 71--pid=::
70 Record events on existing process ID (comma separated list). 72 Record events on existing process ID (comma separated list).
@@ -107,6 +109,10 @@ OPTIONS
107 specification with appended unit character - B/K/M/G. The 109 specification with appended unit character - B/K/M/G. The
108 size is rounded up to have nearest pages power of two value. 110 size is rounded up to have nearest pages power of two value.
109 111
112--group::
113 Put all events in a single event group. This precedes the --event
114 option and remains only for backward compatibility. See --event.
115
110-g:: 116-g::
111 Enables call-graph (stack chain/backtrace) recording. 117 Enables call-graph (stack chain/backtrace) recording.
112 118
@@ -115,13 +121,19 @@ OPTIONS
115 implies -g. 121 implies -g.
116 122
117 Allows specifying "fp" (frame pointer) or "dwarf" 123 Allows specifying "fp" (frame pointer) or "dwarf"
118 (DWARF's CFI - Call Frame Information) as the method to collect 124 (DWARF's CFI - Call Frame Information) or "lbr"
125 (Hardware Last Branch Record facility) as the method to collect
119 the information used to show the call graphs. 126 the information used to show the call graphs.
120 127
121 In some systems, where binaries are build with gcc 128 In some systems, where binaries are build with gcc
122 --fomit-frame-pointer, using the "fp" method will produce bogus 129 --fomit-frame-pointer, using the "fp" method will produce bogus
123 call graphs, using "dwarf", if available (perf tools linked to 130 call graphs, using "dwarf", if available (perf tools linked to
124 the libunwind library) should be used instead. 131 the libunwind library) should be used instead.
132 Using the "lbr" method doesn't require any compiler options. It
133 will produce call graphs from the hardware LBR registers. The
134 main limition is that it is only available on new Intel
135 platforms, such as Haswell. It can only get user call chain. It
136 doesn't work with branch stack sampling at the same time.
125 137
126-q:: 138-q::
127--quiet:: 139--quiet::
@@ -235,6 +247,9 @@ Capture machine state (registers) at interrupt, i.e., on counter overflows for
235each sample. List of captured registers depends on the architecture. This option 247each sample. List of captured registers depends on the architecture. This option
236is off by default. 248is off by default.
237 249
250--running-time::
251Record running and enabled time for read events (:S)
252
238SEE ALSO 253SEE ALSO
239-------- 254--------
240linkperf:perf-stat[1], linkperf:perf-list[1] 255linkperf:perf-stat[1], linkperf:perf-list[1]
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index dd7cccdde498..4879cf638824 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -40,6 +40,11 @@ OPTIONS
40 Only consider symbols in these comms. CSV that understands 40 Only consider symbols in these comms. CSV that understands
41 file://filename entries. This option will affect the percentage of 41 file://filename entries. This option will affect the percentage of
42 the overhead column. See --percentage for more info. 42 the overhead column. See --percentage for more info.
43--pid=::
44 Only show events for given process ID (comma separated list).
45
46--tid=::
47 Only show events for given thread ID (comma separated list).
43-d:: 48-d::
44--dsos=:: 49--dsos=::
45 Only consider symbols in these dsos. CSV that understands 50 Only consider symbols in these dsos. CSV that understands
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index a21eec05bc42..79445750fcb3 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -193,6 +193,12 @@ OPTIONS
193 Only display events for these comms. CSV that understands 193 Only display events for these comms. CSV that understands
194 file://filename entries. 194 file://filename entries.
195 195
196--pid=::
197 Only show events for given process ID (comma separated list).
198
199--tid=::
200 Only show events for given thread ID (comma separated list).
201
196-I:: 202-I::
197--show-info:: 203--show-info::
198 Display extended information about the perf.data file. This adds 204 Display extended information about the perf.data file. This adds
diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt
index 7e1b1f2bb83c..ba03fd5d1a54 100644
--- a/tools/perf/Documentation/perf-trace.txt
+++ b/tools/perf/Documentation/perf-trace.txt
@@ -55,6 +55,9 @@ OPTIONS
55--uid=:: 55--uid=::
56 Record events in threads owned by uid. Name or number. 56 Record events in threads owned by uid. Name or number.
57 57
58--filter-pids=::
59 Filter out events for these pids and for 'trace' itself (comma separated list).
60
58-v:: 61-v::
59--verbose=:: 62--verbose=::
60 Verbosity level. 63 Verbosity level.
@@ -115,6 +118,9 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs.
115--syscalls:: 118--syscalls::
116 Trace system calls. This options is enabled by default. 119 Trace system calls. This options is enabled by default.
117 120
121--event::
122 Trace other events, see 'perf list' for a complete list.
123
118PAGEFAULTS 124PAGEFAULTS
119---------- 125----------
120 126
diff --git a/tools/perf/Documentation/perf.txt b/tools/perf/Documentation/perf.txt
index 1e8e400b4493..2b131776363e 100644
--- a/tools/perf/Documentation/perf.txt
+++ b/tools/perf/Documentation/perf.txt
@@ -13,11 +13,16 @@ SYNOPSIS
13OPTIONS 13OPTIONS
14------- 14-------
15--debug:: 15--debug::
16 Setup debug variable (just verbose for now) in value 16 Setup debug variable (see list below) in value
17 range (0, 10). Use like: 17 range (0, 10). Use like:
18 --debug verbose # sets verbose = 1 18 --debug verbose # sets verbose = 1
19 --debug verbose=2 # sets verbose = 2 19 --debug verbose=2 # sets verbose = 2
20 20
21 List of debug variables allowed to set:
22 verbose - general debug messages
23 ordered-events - ordered events object debug messages
24 data-convert - data convert command debug messages
25
21--buildid-dir:: 26--buildid-dir::
22 Setup buildid cache directory. It has higher priority than 27 Setup buildid cache directory. It has higher priority than
23 buildid.dir config file option. 28 buildid.dir config file option.
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST
index fbbfdc39271d..11ccbb22ea2b 100644
--- a/tools/perf/MANIFEST
+++ b/tools/perf/MANIFEST
@@ -1,5 +1,6 @@
1tools/perf 1tools/perf
2tools/scripts 2tools/scripts
3tools/build
3tools/lib/traceevent 4tools/lib/traceevent
4tools/lib/api 5tools/lib/api
5tools/lib/symbol/kallsyms.c 6tools/lib/symbol/kallsyms.c
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index cb2e5868c8e8..c699dc35eef9 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -24,8 +24,8 @@ unexport MAKEFLAGS
24# (To override it, run 'make JOBS=1' and similar.) 24# (To override it, run 'make JOBS=1' and similar.)
25# 25#
26ifeq ($(JOBS),) 26ifeq ($(JOBS),)
27 JOBS := $(shell grep -c ^processor /proc/cpuinfo 2>/dev/null) 27 JOBS := $(shell egrep -c '^processor|^CPU' /proc/cpuinfo 2>/dev/null)
28 ifeq ($(JOBS),) 28 ifeq ($(JOBS),0)
29 JOBS := 1 29 JOBS := 1
30 endif 30 endif
31endif 31endif
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index aa6a50447c32..e9925e6ad1d0 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -68,7 +68,11 @@ include config/utilities.mak
68# for reading the x32 mode 32-bit compatibility VDSO in 64-bit mode 68# for reading the x32 mode 32-bit compatibility VDSO in 64-bit mode
69# 69#
70# Define NO_ZLIB if you do not want to support compressed kernel modules 70# Define NO_ZLIB if you do not want to support compressed kernel modules
71 71#
72# Define NO_LIBBABELTRACE if you do not want libbabeltrace support
73# for CTF data format.
74#
75# Define NO_LZMA if you do not want to support compressed (xz) kernel modules
72 76
73ifeq ($(srctree),) 77ifeq ($(srctree),)
74srctree := $(patsubst %/,%,$(dir $(shell pwd))) 78srctree := $(patsubst %/,%,$(dir $(shell pwd)))
@@ -82,13 +86,29 @@ endif
82 86
83ifneq ($(OUTPUT),) 87ifneq ($(OUTPUT),)
84#$(info Determined 'OUTPUT' to be $(OUTPUT)) 88#$(info Determined 'OUTPUT' to be $(OUTPUT))
89# Adding $(OUTPUT) as a directory to look for source files,
90# because use generated output files as sources dependency
91# for flex/bison parsers.
92VPATH += $(OUTPUT)
93export VPATH
85endif 94endif
86 95
96ifeq ($(V),1)
97 Q =
98else
99 Q = @
100endif
101
102# Do not use make's built-in rules
103# (this improves performance and avoids hard-to-debug behaviour);
104MAKEFLAGS += -r
105
87$(OUTPUT)PERF-VERSION-FILE: ../../.git/HEAD 106$(OUTPUT)PERF-VERSION-FILE: ../../.git/HEAD
88 @$(SHELL_PATH) util/PERF-VERSION-GEN $(OUTPUT) 107 $(Q)$(SHELL_PATH) util/PERF-VERSION-GEN $(OUTPUT)
89 @touch $(OUTPUT)PERF-VERSION-FILE 108 $(Q)touch $(OUTPUT)PERF-VERSION-FILE
90 109
91CC = $(CROSS_COMPILE)gcc 110CC = $(CROSS_COMPILE)gcc
111LD = $(CROSS_COMPILE)ld
92AR = $(CROSS_COMPILE)ar 112AR = $(CROSS_COMPILE)ar
93PKG_CONFIG = $(CROSS_COMPILE)pkg-config 113PKG_CONFIG = $(CROSS_COMPILE)pkg-config
94 114
@@ -127,10 +147,6 @@ export prefix bindir sharedir sysconfdir DESTDIR
127SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__ 147SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__
128 148
129# Guard against environment variables 149# Guard against environment variables
130BUILTIN_OBJS =
131LIB_H =
132LIB_OBJS =
133GTK_OBJS =
134PYRF_OBJS = 150PYRF_OBJS =
135SCRIPT_SH = 151SCRIPT_SH =
136 152
@@ -155,8 +171,8 @@ endif
155LIBTRACEEVENT = $(TE_PATH)libtraceevent.a 171LIBTRACEEVENT = $(TE_PATH)libtraceevent.a
156export LIBTRACEEVENT 172export LIBTRACEEVENT
157 173
158LIBAPIKFS = $(LIB_PATH)libapikfs.a 174LIBAPI = $(LIB_PATH)libapi.a
159export LIBAPIKFS 175export LIBAPI
160 176
161# python extension build directories 177# python extension build directories
162PYTHON_EXTBUILD := $(OUTPUT)python_ext_build/ 178PYTHON_EXTBUILD := $(OUTPUT)python_ext_build/
@@ -167,7 +183,7 @@ export PYTHON_EXTBUILD_LIB PYTHON_EXTBUILD_TMP
167python-clean := $(call QUIET_CLEAN, python) $(RM) -r $(PYTHON_EXTBUILD) $(OUTPUT)python/perf.so 183python-clean := $(call QUIET_CLEAN, python) $(RM) -r $(PYTHON_EXTBUILD) $(OUTPUT)python/perf.so
168 184
169PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources) 185PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources)
170PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBAPIKFS) 186PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBAPI)
171 187
172$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) 188$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS)
173 $(QUIET_GEN)CFLAGS='$(CFLAGS)' $(PYTHON_WORD) util/setup.py \ 189 $(QUIET_GEN)CFLAGS='$(CFLAGS)' $(PYTHON_WORD) util/setup.py \
@@ -206,297 +222,9 @@ endif
206 222
207export PERL_PATH 223export PERL_PATH
208 224
209$(OUTPUT)util/parse-events-flex.c: util/parse-events.l $(OUTPUT)util/parse-events-bison.c
210 $(QUIET_FLEX)$(FLEX) -o $@ --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) util/parse-events.l
211
212$(OUTPUT)util/parse-events-bison.c: util/parse-events.y
213 $(QUIET_BISON)$(BISON) -v util/parse-events.y -d $(PARSER_DEBUG_BISON) -o $(OUTPUT)util/parse-events-bison.c -p parse_events_
214
215$(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c
216 $(QUIET_FLEX)$(FLEX) -o $@ --header-file=$(OUTPUT)util/pmu-flex.h util/pmu.l
217
218$(OUTPUT)util/pmu-bison.c: util/pmu.y
219 $(QUIET_BISON)$(BISON) -v util/pmu.y -d -o $(OUTPUT)util/pmu-bison.c -p perf_pmu_
220
221$(OUTPUT)util/parse-events.o: $(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-bison.c
222$(OUTPUT)util/pmu.o: $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-bison.c
223
224LIB_FILE=$(OUTPUT)libperf.a 225LIB_FILE=$(OUTPUT)libperf.a
225 226
226LIB_H += ../lib/symbol/kallsyms.h 227PERFLIBS = $(LIB_FILE) $(LIBAPI) $(LIBTRACEEVENT)
227LIB_H += ../../include/uapi/linux/perf_event.h
228LIB_H += ../../include/linux/rbtree.h
229LIB_H += ../../include/linux/list.h
230LIB_H += ../../include/uapi/linux/const.h
231LIB_H += ../include/linux/hash.h
232LIB_H += ../../include/linux/stringify.h
233LIB_H += util/include/linux/bitmap.h
234LIB_H += ../include/linux/bitops.h
235LIB_H += ../include/asm-generic/bitops/arch_hweight.h
236LIB_H += ../include/asm-generic/bitops/atomic.h
237LIB_H += ../include/asm-generic/bitops/const_hweight.h
238LIB_H += ../include/asm-generic/bitops/find.h
239LIB_H += ../include/asm-generic/bitops/fls64.h
240LIB_H += ../include/asm-generic/bitops/fls.h
241LIB_H += ../include/asm-generic/bitops/__ffs.h
242LIB_H += ../include/asm-generic/bitops/__fls.h
243LIB_H += ../include/asm-generic/bitops/hweight.h
244LIB_H += ../include/asm-generic/bitops.h
245LIB_H += ../include/linux/compiler.h
246LIB_H += ../include/linux/log2.h
247LIB_H += util/include/linux/const.h
248LIB_H += util/include/linux/ctype.h
249LIB_H += util/include/linux/kernel.h
250LIB_H += util/include/linux/list.h
251LIB_H += ../include/linux/export.h
252LIB_H += util/include/linux/poison.h
253LIB_H += util/include/linux/rbtree.h
254LIB_H += util/include/linux/rbtree_augmented.h
255LIB_H += util/include/linux/string.h
256LIB_H += ../include/linux/types.h
257LIB_H += util/include/linux/linkage.h
258LIB_H += util/include/asm/asm-offsets.h
259LIB_H += ../include/asm/bug.h
260LIB_H += util/include/asm/byteorder.h
261LIB_H += util/include/asm/swab.h
262LIB_H += util/include/asm/system.h
263LIB_H += util/include/asm/uaccess.h
264LIB_H += util/include/dwarf-regs.h
265LIB_H += util/include/asm/dwarf2.h
266LIB_H += util/include/asm/cpufeature.h
267LIB_H += util/include/asm/unistd_32.h
268LIB_H += util/include/asm/unistd_64.h
269LIB_H += perf.h
270LIB_H += util/annotate.h
271LIB_H += util/cache.h
272LIB_H += util/callchain.h
273LIB_H += util/build-id.h
274LIB_H += util/db-export.h
275LIB_H += util/debug.h
276LIB_H += util/pmu.h
277LIB_H += util/event.h
278LIB_H += util/evsel.h
279LIB_H += util/evlist.h
280LIB_H += util/exec_cmd.h
281LIB_H += util/find-vdso-map.c
282LIB_H += util/levenshtein.h
283LIB_H += util/machine.h
284LIB_H += util/map.h
285LIB_H += util/parse-options.h
286LIB_H += util/parse-events.h
287LIB_H += util/quote.h
288LIB_H += util/util.h
289LIB_H += util/xyarray.h
290LIB_H += util/header.h
291LIB_H += util/help.h
292LIB_H += util/session.h
293LIB_H += util/ordered-events.h
294LIB_H += util/strbuf.h
295LIB_H += util/strlist.h
296LIB_H += util/strfilter.h
297LIB_H += util/svghelper.h
298LIB_H += util/tool.h
299LIB_H += util/run-command.h
300LIB_H += util/sigchain.h
301LIB_H += util/dso.h
302LIB_H += util/symbol.h
303LIB_H += util/color.h
304LIB_H += util/values.h
305LIB_H += util/sort.h
306LIB_H += util/hist.h
307LIB_H += util/comm.h
308LIB_H += util/thread.h
309LIB_H += util/thread_map.h
310LIB_H += util/trace-event.h
311LIB_H += util/probe-finder.h
312LIB_H += util/dwarf-aux.h
313LIB_H += util/probe-event.h
314LIB_H += util/pstack.h
315LIB_H += util/cpumap.h
316LIB_H += util/top.h
317LIB_H += $(ARCH_INCLUDE)
318LIB_H += util/cgroup.h
319LIB_H += $(LIB_INCLUDE)traceevent/event-parse.h
320LIB_H += util/target.h
321LIB_H += util/rblist.h
322LIB_H += util/intlist.h
323LIB_H += util/perf_regs.h
324LIB_H += util/unwind.h
325LIB_H += util/vdso.h
326LIB_H += util/tsc.h
327LIB_H += ui/helpline.h
328LIB_H += ui/progress.h
329LIB_H += ui/util.h
330LIB_H += ui/ui.h
331LIB_H += util/data.h
332LIB_H += util/kvm-stat.h
333LIB_H += util/thread-stack.h
334
335LIB_OBJS += $(OUTPUT)util/abspath.o
336LIB_OBJS += $(OUTPUT)util/alias.o
337LIB_OBJS += $(OUTPUT)util/annotate.o
338LIB_OBJS += $(OUTPUT)util/build-id.o
339LIB_OBJS += $(OUTPUT)util/config.o
340LIB_OBJS += $(OUTPUT)util/ctype.o
341LIB_OBJS += $(OUTPUT)util/db-export.o
342LIB_OBJS += $(OUTPUT)util/pmu.o
343LIB_OBJS += $(OUTPUT)util/environment.o
344LIB_OBJS += $(OUTPUT)util/event.o
345LIB_OBJS += $(OUTPUT)util/evlist.o
346LIB_OBJS += $(OUTPUT)util/evsel.o
347LIB_OBJS += $(OUTPUT)util/exec_cmd.o
348LIB_OBJS += $(OUTPUT)util/find_next_bit.o
349LIB_OBJS += $(OUTPUT)util/help.o
350LIB_OBJS += $(OUTPUT)util/kallsyms.o
351LIB_OBJS += $(OUTPUT)util/levenshtein.o
352LIB_OBJS += $(OUTPUT)util/parse-options.o
353LIB_OBJS += $(OUTPUT)util/parse-events.o
354LIB_OBJS += $(OUTPUT)util/path.o
355LIB_OBJS += $(OUTPUT)util/rbtree.o
356LIB_OBJS += $(OUTPUT)util/bitmap.o
357LIB_OBJS += $(OUTPUT)util/hweight.o
358LIB_OBJS += $(OUTPUT)util/run-command.o
359LIB_OBJS += $(OUTPUT)util/quote.o
360LIB_OBJS += $(OUTPUT)util/strbuf.o
361LIB_OBJS += $(OUTPUT)util/string.o
362LIB_OBJS += $(OUTPUT)util/strlist.o
363LIB_OBJS += $(OUTPUT)util/strfilter.o
364LIB_OBJS += $(OUTPUT)util/top.o
365LIB_OBJS += $(OUTPUT)util/usage.o
366LIB_OBJS += $(OUTPUT)util/wrapper.o
367LIB_OBJS += $(OUTPUT)util/sigchain.o
368LIB_OBJS += $(OUTPUT)util/dso.o
369LIB_OBJS += $(OUTPUT)util/symbol.o
370LIB_OBJS += $(OUTPUT)util/symbol-elf.o
371LIB_OBJS += $(OUTPUT)util/color.o
372LIB_OBJS += $(OUTPUT)util/pager.o
373LIB_OBJS += $(OUTPUT)util/header.o
374LIB_OBJS += $(OUTPUT)util/callchain.o
375LIB_OBJS += $(OUTPUT)util/values.o
376LIB_OBJS += $(OUTPUT)util/debug.o
377LIB_OBJS += $(OUTPUT)util/machine.o
378LIB_OBJS += $(OUTPUT)util/map.o
379LIB_OBJS += $(OUTPUT)util/pstack.o
380LIB_OBJS += $(OUTPUT)util/session.o
381LIB_OBJS += $(OUTPUT)util/ordered-events.o
382LIB_OBJS += $(OUTPUT)util/comm.o
383LIB_OBJS += $(OUTPUT)util/thread.o
384LIB_OBJS += $(OUTPUT)util/thread_map.o
385LIB_OBJS += $(OUTPUT)util/trace-event-parse.o
386LIB_OBJS += $(OUTPUT)util/parse-events-flex.o
387LIB_OBJS += $(OUTPUT)util/parse-events-bison.o
388LIB_OBJS += $(OUTPUT)util/pmu-flex.o
389LIB_OBJS += $(OUTPUT)util/pmu-bison.o
390LIB_OBJS += $(OUTPUT)util/trace-event-read.o
391LIB_OBJS += $(OUTPUT)util/trace-event-info.o
392LIB_OBJS += $(OUTPUT)util/trace-event-scripting.o
393LIB_OBJS += $(OUTPUT)util/trace-event.o
394LIB_OBJS += $(OUTPUT)util/svghelper.o
395LIB_OBJS += $(OUTPUT)util/sort.o
396LIB_OBJS += $(OUTPUT)util/hist.o
397LIB_OBJS += $(OUTPUT)util/probe-event.o
398LIB_OBJS += $(OUTPUT)util/util.o
399LIB_OBJS += $(OUTPUT)util/xyarray.o
400LIB_OBJS += $(OUTPUT)util/cpumap.o
401LIB_OBJS += $(OUTPUT)util/cgroup.o
402LIB_OBJS += $(OUTPUT)util/target.o
403LIB_OBJS += $(OUTPUT)util/rblist.o
404LIB_OBJS += $(OUTPUT)util/intlist.o
405LIB_OBJS += $(OUTPUT)util/vdso.o
406LIB_OBJS += $(OUTPUT)util/stat.o
407LIB_OBJS += $(OUTPUT)util/record.o
408LIB_OBJS += $(OUTPUT)util/srcline.o
409LIB_OBJS += $(OUTPUT)util/data.o
410LIB_OBJS += $(OUTPUT)util/tsc.o
411LIB_OBJS += $(OUTPUT)util/cloexec.o
412LIB_OBJS += $(OUTPUT)util/thread-stack.o
413
414LIB_OBJS += $(OUTPUT)ui/setup.o
415LIB_OBJS += $(OUTPUT)ui/helpline.o
416LIB_OBJS += $(OUTPUT)ui/progress.o
417LIB_OBJS += $(OUTPUT)ui/util.o
418LIB_OBJS += $(OUTPUT)ui/hist.o
419LIB_OBJS += $(OUTPUT)ui/stdio/hist.o
420
421LIB_OBJS += $(OUTPUT)arch/common.o
422
423LIB_OBJS += $(OUTPUT)tests/parse-events.o
424LIB_OBJS += $(OUTPUT)tests/dso-data.o
425LIB_OBJS += $(OUTPUT)tests/attr.o
426LIB_OBJS += $(OUTPUT)tests/vmlinux-kallsyms.o
427LIB_OBJS += $(OUTPUT)tests/open-syscall.o
428LIB_OBJS += $(OUTPUT)tests/open-syscall-all-cpus.o
429LIB_OBJS += $(OUTPUT)tests/open-syscall-tp-fields.o
430LIB_OBJS += $(OUTPUT)tests/mmap-basic.o
431LIB_OBJS += $(OUTPUT)tests/perf-record.o
432LIB_OBJS += $(OUTPUT)tests/rdpmc.o
433LIB_OBJS += $(OUTPUT)tests/evsel-roundtrip-name.o
434LIB_OBJS += $(OUTPUT)tests/evsel-tp-sched.o
435LIB_OBJS += $(OUTPUT)tests/fdarray.o
436LIB_OBJS += $(OUTPUT)tests/pmu.o
437LIB_OBJS += $(OUTPUT)tests/hists_common.o
438LIB_OBJS += $(OUTPUT)tests/hists_link.o
439LIB_OBJS += $(OUTPUT)tests/hists_filter.o
440LIB_OBJS += $(OUTPUT)tests/hists_output.o
441LIB_OBJS += $(OUTPUT)tests/hists_cumulate.o
442LIB_OBJS += $(OUTPUT)tests/python-use.o
443LIB_OBJS += $(OUTPUT)tests/bp_signal.o
444LIB_OBJS += $(OUTPUT)tests/bp_signal_overflow.o
445LIB_OBJS += $(OUTPUT)tests/task-exit.o
446LIB_OBJS += $(OUTPUT)tests/sw-clock.o
447ifeq ($(ARCH),x86)
448LIB_OBJS += $(OUTPUT)tests/perf-time-to-tsc.o
449endif
450LIB_OBJS += $(OUTPUT)tests/code-reading.o
451LIB_OBJS += $(OUTPUT)tests/sample-parsing.o
452LIB_OBJS += $(OUTPUT)tests/parse-no-sample-id-all.o
453ifndef NO_DWARF_UNWIND
454ifeq ($(ARCH),$(filter $(ARCH),x86 arm))
455LIB_OBJS += $(OUTPUT)tests/dwarf-unwind.o
456endif
457endif
458LIB_OBJS += $(OUTPUT)tests/mmap-thread-lookup.o
459LIB_OBJS += $(OUTPUT)tests/thread-mg-share.o
460LIB_OBJS += $(OUTPUT)tests/switch-tracking.o
461
462BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
463BUILTIN_OBJS += $(OUTPUT)builtin-bench.o
464# Benchmark modules
465BUILTIN_OBJS += $(OUTPUT)bench/sched-messaging.o
466BUILTIN_OBJS += $(OUTPUT)bench/sched-pipe.o
467ifeq ($(ARCH), x86)
468ifeq ($(IS_64_BIT), 1)
469BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy-x86-64-asm.o
470BUILTIN_OBJS += $(OUTPUT)bench/mem-memset-x86-64-asm.o
471endif
472endif
473BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o
474BUILTIN_OBJS += $(OUTPUT)bench/futex-hash.o
475BUILTIN_OBJS += $(OUTPUT)bench/futex-wake.o
476BUILTIN_OBJS += $(OUTPUT)bench/futex-requeue.o
477
478BUILTIN_OBJS += $(OUTPUT)builtin-diff.o
479BUILTIN_OBJS += $(OUTPUT)builtin-evlist.o
480BUILTIN_OBJS += $(OUTPUT)builtin-help.o
481BUILTIN_OBJS += $(OUTPUT)builtin-sched.o
482BUILTIN_OBJS += $(OUTPUT)builtin-buildid-list.o
483BUILTIN_OBJS += $(OUTPUT)builtin-buildid-cache.o
484BUILTIN_OBJS += $(OUTPUT)builtin-list.o
485BUILTIN_OBJS += $(OUTPUT)builtin-record.o
486BUILTIN_OBJS += $(OUTPUT)builtin-report.o
487BUILTIN_OBJS += $(OUTPUT)builtin-stat.o
488BUILTIN_OBJS += $(OUTPUT)builtin-timechart.o
489BUILTIN_OBJS += $(OUTPUT)builtin-top.o
490BUILTIN_OBJS += $(OUTPUT)builtin-script.o
491BUILTIN_OBJS += $(OUTPUT)builtin-probe.o
492BUILTIN_OBJS += $(OUTPUT)builtin-kmem.o
493BUILTIN_OBJS += $(OUTPUT)builtin-lock.o
494BUILTIN_OBJS += $(OUTPUT)builtin-kvm.o
495BUILTIN_OBJS += $(OUTPUT)builtin-inject.o
496BUILTIN_OBJS += $(OUTPUT)tests/builtin-test.o
497BUILTIN_OBJS += $(OUTPUT)builtin-mem.o
498
499PERFLIBS = $(LIB_FILE) $(LIBAPIKFS) $(LIBTRACEEVENT)
500 228
501# We choose to avoid "if .. else if .. else .. endif endif" 229# We choose to avoid "if .. else if .. else .. endif endif"
502# because maintaining the nesting to match is a pain. If 230# because maintaining the nesting to match is a pain. If
@@ -508,67 +236,9 @@ ifneq ($(OUTPUT),)
508 CFLAGS += -I$(OUTPUT) 236 CFLAGS += -I$(OUTPUT)
509endif 237endif
510 238
511ifdef NO_LIBELF
512# Remove ELF/DWARF dependent codes
513LIB_OBJS := $(filter-out $(OUTPUT)util/symbol-elf.o,$(LIB_OBJS))
514LIB_OBJS := $(filter-out $(OUTPUT)util/dwarf-aux.o,$(LIB_OBJS))
515LIB_OBJS := $(filter-out $(OUTPUT)util/probe-event.o,$(LIB_OBJS))
516LIB_OBJS := $(filter-out $(OUTPUT)util/probe-finder.o,$(LIB_OBJS))
517
518BUILTIN_OBJS := $(filter-out $(OUTPUT)builtin-probe.o,$(BUILTIN_OBJS))
519
520# Use minimal symbol handling
521LIB_OBJS += $(OUTPUT)util/symbol-minimal.o
522
523else # NO_LIBELF
524ifndef NO_DWARF
525 LIB_OBJS += $(OUTPUT)util/probe-finder.o
526 LIB_OBJS += $(OUTPUT)util/dwarf-aux.o
527endif # NO_DWARF
528endif # NO_LIBELF
529
530ifndef NO_LIBDW_DWARF_UNWIND
531 LIB_OBJS += $(OUTPUT)util/unwind-libdw.o
532 LIB_H += util/unwind-libdw.h
533endif
534
535ifndef NO_LIBUNWIND
536 LIB_OBJS += $(OUTPUT)util/unwind-libunwind.o
537endif
538LIB_OBJS += $(OUTPUT)tests/keep-tracking.o
539
540ifndef NO_LIBAUDIT
541 BUILTIN_OBJS += $(OUTPUT)builtin-trace.o
542endif
543
544ifndef NO_SLANG
545 LIB_OBJS += $(OUTPUT)ui/browser.o
546 LIB_OBJS += $(OUTPUT)ui/browsers/annotate.o
547 LIB_OBJS += $(OUTPUT)ui/browsers/hists.o
548 LIB_OBJS += $(OUTPUT)ui/browsers/map.o
549 LIB_OBJS += $(OUTPUT)ui/browsers/scripts.o
550 LIB_OBJS += $(OUTPUT)ui/browsers/header.o
551 LIB_OBJS += $(OUTPUT)ui/tui/setup.o
552 LIB_OBJS += $(OUTPUT)ui/tui/util.o
553 LIB_OBJS += $(OUTPUT)ui/tui/helpline.o
554 LIB_OBJS += $(OUTPUT)ui/tui/progress.o
555 LIB_H += ui/tui/tui.h
556 LIB_H += ui/browser.h
557 LIB_H += ui/browsers/map.h
558 LIB_H += ui/keysyms.h
559 LIB_H += ui/libslang.h
560endif
561
562ifndef NO_GTK2 239ifndef NO_GTK2
563 ALL_PROGRAMS += $(OUTPUT)libperf-gtk.so 240 ALL_PROGRAMS += $(OUTPUT)libperf-gtk.so
564 241 GTK_IN := $(OUTPUT)gtk-in.o
565 GTK_OBJS += $(OUTPUT)ui/gtk/browser.o
566 GTK_OBJS += $(OUTPUT)ui/gtk/hists.o
567 GTK_OBJS += $(OUTPUT)ui/gtk/setup.o
568 GTK_OBJS += $(OUTPUT)ui/gtk/util.o
569 GTK_OBJS += $(OUTPUT)ui/gtk/helpline.o
570 GTK_OBJS += $(OUTPUT)ui/gtk/progress.o
571 GTK_OBJS += $(OUTPUT)ui/gtk/annotate.o
572 242
573install-gtk: $(OUTPUT)libperf-gtk.so 243install-gtk: $(OUTPUT)libperf-gtk.so
574 $(call QUIET_INSTALL, 'GTK UI') \ 244 $(call QUIET_INSTALL, 'GTK UI') \
@@ -576,31 +246,6 @@ install-gtk: $(OUTPUT)libperf-gtk.so
576 $(INSTALL) $(OUTPUT)libperf-gtk.so '$(DESTDIR_SQ)$(libdir_SQ)' 246 $(INSTALL) $(OUTPUT)libperf-gtk.so '$(DESTDIR_SQ)$(libdir_SQ)'
577endif 247endif
578 248
579ifndef NO_LIBPERL
580 LIB_OBJS += $(OUTPUT)util/scripting-engines/trace-event-perl.o
581 LIB_OBJS += $(OUTPUT)scripts/perl/Perf-Trace-Util/Context.o
582endif
583
584ifndef NO_LIBPYTHON
585 LIB_OBJS += $(OUTPUT)util/scripting-engines/trace-event-python.o
586 LIB_OBJS += $(OUTPUT)scripts/python/Perf-Trace-Util/Context.o
587endif
588
589ifeq ($(NO_PERF_REGS),0)
590 ifeq ($(ARCH),x86)
591 LIB_H += arch/x86/include/perf_regs.h
592 endif
593 LIB_OBJS += $(OUTPUT)util/perf_regs.o
594endif
595
596ifndef NO_LIBNUMA
597 BUILTIN_OBJS += $(OUTPUT)bench/numa.o
598endif
599
600ifndef NO_ZLIB
601 LIB_OBJS += $(OUTPUT)util/zlib.o
602endif
603
604ifdef ASCIIDOC8 249ifdef ASCIIDOC8
605 export ASCIIDOC8 250 export ASCIIDOC8
606endif 251endif
@@ -616,39 +261,29 @@ SHELL = $(SHELL_PATH)
616all: shell_compatibility_test $(ALL_PROGRAMS) $(LANG_BINDINGS) $(OTHER_PROGRAMS) 261all: shell_compatibility_test $(ALL_PROGRAMS) $(LANG_BINDINGS) $(OTHER_PROGRAMS)
617 262
618please_set_SHELL_PATH_to_a_more_modern_shell: 263please_set_SHELL_PATH_to_a_more_modern_shell:
619 @$$(:) 264 $(Q)$$(:)
620 265
621shell_compatibility_test: please_set_SHELL_PATH_to_a_more_modern_shell 266shell_compatibility_test: please_set_SHELL_PATH_to_a_more_modern_shell
622 267
623strip: $(PROGRAMS) $(OUTPUT)perf 268strip: $(PROGRAMS) $(OUTPUT)perf
624 $(STRIP) $(STRIP_OPTS) $(PROGRAMS) $(OUTPUT)perf 269 $(STRIP) $(STRIP_OPTS) $(PROGRAMS) $(OUTPUT)perf
625 270
626$(OUTPUT)perf.o: perf.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS 271PERF_IN := $(OUTPUT)perf-in.o
627 $(QUIET_CC)$(CC) -include $(OUTPUT)PERF-VERSION-FILE \
628 '-DPERF_HTML_PATH="$(htmldir_SQ)"' \
629 $(CFLAGS) -c $(filter %.c,$^) -o $@
630 272
631$(OUTPUT)perf: $(OUTPUT)perf.o $(BUILTIN_OBJS) $(PERFLIBS) 273export srctree OUTPUT RM CC LD AR CFLAGS V BISON FLEX
632 $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $(OUTPUT)perf.o \ 274build := -f $(srctree)/tools/build/Makefile.build dir=. obj
633 $(BUILTIN_OBJS) $(LIBS) -o $@
634 275
635$(GTK_OBJS): $(OUTPUT)%.o: %.c $(LIB_H) 276$(PERF_IN): $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h FORCE
636 $(QUIET_CC)$(CC) -o $@ -c -fPIC $(CFLAGS) $(GTK_CFLAGS) $< 277 $(Q)$(MAKE) $(build)=perf
637 278
638$(OUTPUT)libperf-gtk.so: $(GTK_OBJS) $(PERFLIBS) 279$(OUTPUT)perf: $(PERFLIBS) $(PERF_IN)
639 $(QUIET_LINK)$(CC) -o $@ -shared $(LDFLAGS) $(filter %.o,$^) $(GTK_LIBS) 280 $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $(PERF_IN) $(LIBS) -o $@
640 281
641$(OUTPUT)builtin-help.o: builtin-help.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS 282$(GTK_IN): FORCE
642 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \ 283 $(Q)$(MAKE) $(build)=gtk
643 '-DPERF_HTML_PATH="$(htmldir_SQ)"' \
644 '-DPERF_MAN_PATH="$(mandir_SQ)"' \
645 '-DPERF_INFO_PATH="$(infodir_SQ)"' $<
646 284
647$(OUTPUT)builtin-timechart.o: builtin-timechart.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS 285$(OUTPUT)libperf-gtk.so: $(GTK_IN) $(PERFLIBS)
648 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \ 286 $(QUIET_LINK)$(CC) -o $@ -shared $(LDFLAGS) $(filter %.o,$^) $(GTK_LIBS)
649 '-DPERF_HTML_PATH="$(htmldir_SQ)"' \
650 '-DPERF_MAN_PATH="$(mandir_SQ)"' \
651 '-DPERF_INFO_PATH="$(infodir_SQ)"' $<
652 287
653$(OUTPUT)common-cmds.h: util/generate-cmdlist.sh command-list.txt 288$(OUTPUT)common-cmds.h: util/generate-cmdlist.sh command-list.txt
654 289
@@ -659,8 +294,7 @@ $(SCRIPTS) : % : %.sh
659 $(QUIET_GEN)$(INSTALL) '$@.sh' '$(OUTPUT)$@' 294 $(QUIET_GEN)$(INSTALL) '$@.sh' '$(OUTPUT)$@'
660 295
661# These can record PERF_VERSION 296# These can record PERF_VERSION
662$(OUTPUT)perf.o perf.spec \ 297perf.spec $(SCRIPTS) \
663 $(SCRIPTS) \
664 : $(OUTPUT)PERF-VERSION-FILE 298 : $(OUTPUT)PERF-VERSION-FILE
665 299
666.SUFFIXES: 300.SUFFIXES:
@@ -683,90 +317,33 @@ endif
683# These two need to be here so that when O= is not used they take precedence 317# These two need to be here so that when O= is not used they take precedence
684# over the general rule for .o 318# over the general rule for .o
685 319
686$(OUTPUT)util/%-flex.o: $(OUTPUT)util/%-flex.c $(OUTPUT)PERF-CFLAGS 320# get relative building directory (to $(OUTPUT))
687 $(QUIET_CC)$(CC) -o $@ -c -Iutil/ $(CFLAGS) -w $< 321# and '.' if it's $(OUTPUT) itself
688 322__build-dir = $(subst $(OUTPUT),,$(dir $@))
689$(OUTPUT)util/%-bison.o: $(OUTPUT)util/%-bison.c $(OUTPUT)PERF-CFLAGS 323build-dir = $(if $(__build-dir),$(__build-dir),.)
690 $(QUIET_CC)$(CC) -o $@ -c -Iutil/ $(CFLAGS) -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w $<
691
692$(OUTPUT)%.o: %.c $(OUTPUT)PERF-CFLAGS
693 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $<
694$(OUTPUT)%.i: %.c $(OUTPUT)PERF-CFLAGS
695 $(QUIET_CC)$(CC) -o $@ -E $(CFLAGS) $<
696$(OUTPUT)%.s: %.c $(OUTPUT)PERF-CFLAGS
697 $(QUIET_CC)$(CC) -o $@ -S $(CFLAGS) $<
698$(OUTPUT)%.o: %.S
699 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $<
700$(OUTPUT)%.s: %.S
701 $(QUIET_CC)$(CC) -o $@ -E $(CFLAGS) $<
702
703$(OUTPUT)util/exec_cmd.o: util/exec_cmd.c $(OUTPUT)PERF-CFLAGS
704 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
705 '-DPERF_EXEC_PATH="$(perfexecdir_SQ)"' \
706 '-DPREFIX="$(prefix_SQ)"' \
707 $<
708
709$(OUTPUT)tests/attr.o: tests/attr.c $(OUTPUT)PERF-CFLAGS
710 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
711 '-DBINDIR="$(bindir_SQ)"' -DPYTHON='"$(PYTHON_WORD)"' \
712 $<
713
714$(OUTPUT)tests/python-use.o: tests/python-use.c $(OUTPUT)PERF-CFLAGS
715 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
716 -DPYTHONPATH='"$(OUTPUT)python"' \
717 -DPYTHON='"$(PYTHON_WORD)"' \
718 $<
719
720$(OUTPUT)tests/dwarf-unwind.o: tests/dwarf-unwind.c
721 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -fno-optimize-sibling-calls $<
722 324
723$(OUTPUT)util/config.o: util/config.c $(OUTPUT)PERF-CFLAGS 325single_dep: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h
724 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
725 326
726$(OUTPUT)ui/setup.o: ui/setup.c $(OUTPUT)PERF-CFLAGS 327$(OUTPUT)%.o: %.c single_dep FORCE
727 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DLIBDIR='"$(libdir_SQ)"' $< 328 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@
728 329
729$(OUTPUT)ui/browser.o: ui/browser.c $(OUTPUT)PERF-CFLAGS 330$(OUTPUT)%.i: %.c single_dep FORCE
730 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $< 331 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@
731 332
732$(OUTPUT)ui/browsers/annotate.o: ui/browsers/annotate.c $(OUTPUT)PERF-CFLAGS 333$(OUTPUT)%.s: %.c single_dep FORCE
733 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $< 334 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@
734 335
735$(OUTPUT)ui/browsers/hists.o: ui/browsers/hists.c $(OUTPUT)PERF-CFLAGS 336$(OUTPUT)%-bison.o: %.c single_dep FORCE
736 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $< 337 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@
737 338
738$(OUTPUT)ui/browsers/map.o: ui/browsers/map.c $(OUTPUT)PERF-CFLAGS 339$(OUTPUT)%-flex.o: %.c single_dep FORCE
739 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $< 340 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@
740 341
741$(OUTPUT)ui/browsers/scripts.o: ui/browsers/scripts.c $(OUTPUT)PERF-CFLAGS 342$(OUTPUT)%.o: %.S single_dep FORCE
742 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $< 343 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@
743 344
744$(OUTPUT)util/kallsyms.o: ../lib/symbol/kallsyms.c $(OUTPUT)PERF-CFLAGS 345$(OUTPUT)%.i: %.S single_dep FORCE
745 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $< 346 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@
746
747$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS
748 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
749
750$(OUTPUT)util/hweight.o: ../../lib/hweight.c $(OUTPUT)PERF-CFLAGS
751 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
752
753$(OUTPUT)util/find_next_bit.o: ../lib/util/find_next_bit.c $(OUTPUT)PERF-CFLAGS
754 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
755
756$(OUTPUT)util/parse-events.o: util/parse-events.c $(OUTPUT)PERF-CFLAGS
757 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-redundant-decls $<
758
759$(OUTPUT)util/scripting-engines/trace-event-perl.o: util/scripting-engines/trace-event-perl.c $(OUTPUT)PERF-CFLAGS
760 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow -Wno-undef -Wno-switch-default $<
761
762$(OUTPUT)scripts/perl/Perf-Trace-Util/Context.o: scripts/perl/Perf-Trace-Util/Context.c $(OUTPUT)PERF-CFLAGS
763 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs -Wno-undef -Wno-switch-default $<
764
765$(OUTPUT)util/scripting-engines/trace-event-python.o: util/scripting-engines/trace-event-python.c $(OUTPUT)PERF-CFLAGS
766 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow $<
767
768$(OUTPUT)scripts/python/Perf-Trace-Util/Context.o: scripts/python/Perf-Trace-Util/Context.c $(OUTPUT)PERF-CFLAGS
769 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs $<
770 347
771$(OUTPUT)perf-%: %.o $(PERFLIBS) 348$(OUTPUT)perf-%: %.o $(PERFLIBS)
772 $(QUIET_LINK)$(CC) $(CFLAGS) -o $@ $(LDFLAGS) $(filter %.o,$^) $(LIBS) 349 $(QUIET_LINK)$(CC) $(CFLAGS) -o $@ $(LDFLAGS) $(filter %.o,$^) $(LIBS)
@@ -781,58 +358,34 @@ $(OUTPUT)perf-read-vdsox32: perf-read-vdso.c util/find-vdso-map.c
781 $(QUIET_CC)$(CC) -mx32 $(filter -static,$(LDFLAGS)) -Wall -Werror -o $@ perf-read-vdso.c 358 $(QUIET_CC)$(CC) -mx32 $(filter -static,$(LDFLAGS)) -Wall -Werror -o $@ perf-read-vdso.c
782endif 359endif
783 360
784$(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H) 361$(patsubst perf-%,%.o,$(PROGRAMS)): $(wildcard */*.h)
785$(patsubst perf-%,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h)
786 362
787# we compile into subdirectories. if the target directory is not the source directory, they might not exists. So 363LIBPERF_IN := $(OUTPUT)libperf-in.o
788# we depend the various files onto their directories.
789DIRECTORY_DEPS = $(LIB_OBJS) $(BUILTIN_OBJS) $(GTK_OBJS)
790DIRECTORY_DEPS += $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h
791# no need to add flex objects, because they depend on bison ones
792DIRECTORY_DEPS += $(OUTPUT)util/parse-events-bison.c
793DIRECTORY_DEPS += $(OUTPUT)util/pmu-bison.c
794 364
795OUTPUT_DIRECTORIES := $(sort $(dir $(DIRECTORY_DEPS))) 365$(LIBPERF_IN): FORCE
366 $(Q)$(MAKE) $(build)=libperf
796 367
797$(DIRECTORY_DEPS): | $(OUTPUT_DIRECTORIES) 368$(LIB_FILE): $(LIBPERF_IN)
798# In the second step, we make a rule to actually create these directories 369 $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIBPERF_IN) $(LIB_OBJS)
799$(OUTPUT_DIRECTORIES):
800 $(QUIET_MKDIR)$(MKDIR) -p $@ 2>/dev/null
801 370
802$(LIB_FILE): $(LIB_OBJS)
803 $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIB_OBJS)
804
805# libtraceevent.a
806TE_SOURCES = $(wildcard $(TRACE_EVENT_DIR)*.[ch])
807
808LIBTRACEEVENT_FLAGS = $(QUIET_SUBDIR1) O=$(OUTPUT)
809LIBTRACEEVENT_FLAGS += CFLAGS="-g -Wall $(EXTRA_CFLAGS)"
810LIBTRACEEVENT_FLAGS += plugin_dir=$(plugindir_SQ) 371LIBTRACEEVENT_FLAGS += plugin_dir=$(plugindir_SQ)
811 372
812$(LIBTRACEEVENT): $(TE_SOURCES) $(OUTPUT)PERF-CFLAGS 373$(LIBTRACEEVENT): FORCE
813 $(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) libtraceevent.a plugins 374 $(Q)$(MAKE) -C $(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) O=$(OUTPUT) $(OUTPUT)libtraceevent.a plugins
814 375
815$(LIBTRACEEVENT)-clean: 376$(LIBTRACEEVENT)-clean:
816 $(call QUIET_CLEAN, libtraceevent) 377 $(call QUIET_CLEAN, libtraceevent)
817 @$(MAKE) -C $(TRACE_EVENT_DIR) O=$(OUTPUT) clean >/dev/null 378 $(Q)$(MAKE) -C $(TRACE_EVENT_DIR) O=$(OUTPUT) clean >/dev/null
818 379
819install-traceevent-plugins: $(LIBTRACEEVENT) 380install-traceevent-plugins: $(LIBTRACEEVENT)
820 $(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) install_plugins 381 $(Q)$(MAKE) -C $(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) O=$(OUTPUT) install_plugins
821 382
822LIBAPIKFS_SOURCES = $(wildcard $(LIB_PATH)fs/*.[ch] $(LIB_PATH)fd/*.[ch]) 383$(LIBAPI): FORCE
823 384 $(Q)$(MAKE) -C $(LIB_DIR) O=$(OUTPUT) $(OUTPUT)libapi.a
824# if subdir is set, we've been called from above so target has been built
825# already
826$(LIBAPIKFS): $(LIBAPIKFS_SOURCES)
827ifeq ($(subdir),)
828 $(QUIET_SUBDIR0)$(LIB_DIR) $(QUIET_SUBDIR1) O=$(OUTPUT) libapikfs.a
829endif
830 385
831$(LIBAPIKFS)-clean: 386$(LIBAPI)-clean:
832ifeq ($(subdir),) 387 $(call QUIET_CLEAN, libapi)
833 $(call QUIET_CLEAN, libapikfs) 388 $(Q)$(MAKE) -C $(LIB_DIR) O=$(OUTPUT) clean >/dev/null
834 @$(MAKE) -C $(LIB_DIR) O=$(OUTPUT) clean >/dev/null
835endif
836 389
837help: 390help:
838 @echo 'Perf make targets:' 391 @echo 'Perf make targets:'
@@ -888,17 +441,6 @@ cscope:
888 $(QUIET_GEN)$(RM) cscope*; \ 441 $(QUIET_GEN)$(RM) cscope*; \
889 $(FIND) $(TAG_FOLDERS) -name '*.[hcS]' -print | xargs cscope -b $(TAG_FILES) 442 $(FIND) $(TAG_FOLDERS) -name '*.[hcS]' -print | xargs cscope -b $(TAG_FILES)
890 443
891### Detect prefix changes
892TRACK_CFLAGS = $(subst ','\'',$(CFLAGS)):\
893 $(bindir_SQ):$(perfexecdir_SQ):$(template_dir_SQ):$(prefix_SQ):$(plugindir_SQ)
894
895$(OUTPUT)PERF-CFLAGS: .FORCE-PERF-CFLAGS
896 @FLAGS='$(TRACK_CFLAGS)'; \
897 if test x"$$FLAGS" != x"`cat $(OUTPUT)PERF-CFLAGS 2>/dev/null`" ; then \
898 echo 1>&2 " FLAGS: * new build flags or prefix"; \
899 echo "$$FLAGS" >$(OUTPUT)PERF-CFLAGS; \
900 fi
901
902### Testing rules 444### Testing rules
903 445
904# GNU make supports exporting all variables by "export" without parameters. 446# GNU make supports exporting all variables by "export" without parameters.
@@ -981,12 +523,14 @@ $(INSTALL_DOC_TARGETS):
981# 523#
982config-clean: 524config-clean:
983 $(call QUIET_CLEAN, config) 525 $(call QUIET_CLEAN, config)
984 @$(MAKE) -C config/feature-checks clean >/dev/null 526 $(Q)$(MAKE) -C $(srctree)/tools/build/feature/ clean >/dev/null
985 527
986clean: $(LIBTRACEEVENT)-clean $(LIBAPIKFS)-clean config-clean 528clean: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean config-clean
987 $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(OUTPUT)perf.o $(LANG_BINDINGS) $(GTK_OBJS) 529 $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(LANG_BINDINGS)
530 $(Q)find . -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete
531 $(Q)$(RM) .config-detected
988 $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf perf-read-vdso32 perf-read-vdsox32 532 $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf perf-read-vdso32 perf-read-vdsox32
989 $(call QUIET_CLEAN, core-gen) $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS $(OUTPUT)PERF-FEATURES $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex* 533 $(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*
990 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean 534 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean
991 $(python-clean) 535 $(python-clean)
992 536
@@ -1000,7 +544,9 @@ else
1000 GIT-HEAD-PHONY = 544 GIT-HEAD-PHONY =
1001endif 545endif
1002 546
547FORCE:
548
1003.PHONY: all install clean config-clean strip install-gtk 549.PHONY: all install clean config-clean strip install-gtk
1004.PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell 550.PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell
1005.PHONY: $(GIT-HEAD-PHONY) TAGS tags cscope .FORCE-PERF-CFLAGS 551.PHONY: $(GIT-HEAD-PHONY) TAGS tags cscope FORCE single_dep
1006 552
diff --git a/tools/perf/arch/Build b/tools/perf/arch/Build
new file mode 100644
index 000000000000..109eb75cf7de
--- /dev/null
+++ b/tools/perf/arch/Build
@@ -0,0 +1,2 @@
1libperf-y += common.o
2libperf-y += $(ARCH)/
diff --git a/tools/perf/arch/arm/Build b/tools/perf/arch/arm/Build
new file mode 100644
index 000000000000..41bf61da476a
--- /dev/null
+++ b/tools/perf/arch/arm/Build
@@ -0,0 +1,2 @@
1libperf-y += util/
2libperf-$(CONFIG_DWARF_UNWIND) += tests/
diff --git a/tools/perf/arch/arm/Makefile b/tools/perf/arch/arm/Makefile
index 09d62153d384..7fbca175099e 100644
--- a/tools/perf/arch/arm/Makefile
+++ b/tools/perf/arch/arm/Makefile
@@ -1,14 +1,3 @@
1ifndef NO_DWARF 1ifndef NO_DWARF
2PERF_HAVE_DWARF_REGS := 1 2PERF_HAVE_DWARF_REGS := 1
3LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
4endif
5ifndef NO_LIBUNWIND
6LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind-libunwind.o
7endif
8ifndef NO_LIBDW_DWARF_UNWIND
9LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind-libdw.o
10endif
11ifndef NO_DWARF_UNWIND
12LIB_OBJS += $(OUTPUT)arch/$(ARCH)/tests/regs_load.o
13LIB_OBJS += $(OUTPUT)arch/$(ARCH)/tests/dwarf-unwind.o
14endif 3endif
diff --git a/tools/perf/arch/arm/tests/Build b/tools/perf/arch/arm/tests/Build
new file mode 100644
index 000000000000..b30eff9bcc83
--- /dev/null
+++ b/tools/perf/arch/arm/tests/Build
@@ -0,0 +1,2 @@
1libperf-y += regs_load.o
2libperf-y += dwarf-unwind.o
diff --git a/tools/perf/arch/arm/util/Build b/tools/perf/arch/arm/util/Build
new file mode 100644
index 000000000000..d22e3d07de3d
--- /dev/null
+++ b/tools/perf/arch/arm/util/Build
@@ -0,0 +1,4 @@
1libperf-$(CONFIG_DWARF) += dwarf-regs.o
2
3libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o
4libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
diff --git a/tools/perf/arch/arm64/Build b/tools/perf/arch/arm64/Build
new file mode 100644
index 000000000000..54afe4a467e7
--- /dev/null
+++ b/tools/perf/arch/arm64/Build
@@ -0,0 +1 @@
libperf-y += util/
diff --git a/tools/perf/arch/arm64/Makefile b/tools/perf/arch/arm64/Makefile
index 67e9b3d38e89..7fbca175099e 100644
--- a/tools/perf/arch/arm64/Makefile
+++ b/tools/perf/arch/arm64/Makefile
@@ -1,7 +1,3 @@
1ifndef NO_DWARF 1ifndef NO_DWARF
2PERF_HAVE_DWARF_REGS := 1 2PERF_HAVE_DWARF_REGS := 1
3LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
4endif
5ifndef NO_LIBUNWIND
6LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind-libunwind.o
7endif 3endif
diff --git a/tools/perf/arch/arm64/util/Build b/tools/perf/arch/arm64/util/Build
new file mode 100644
index 000000000000..e58123a8912b
--- /dev/null
+++ b/tools/perf/arch/arm64/util/Build
@@ -0,0 +1,2 @@
1libperf-$(CONFIG_DWARF) += dwarf-regs.o
2libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o
diff --git a/tools/perf/arch/powerpc/Build b/tools/perf/arch/powerpc/Build
new file mode 100644
index 000000000000..54afe4a467e7
--- /dev/null
+++ b/tools/perf/arch/powerpc/Build
@@ -0,0 +1 @@
libperf-y += util/
diff --git a/tools/perf/arch/powerpc/Makefile b/tools/perf/arch/powerpc/Makefile
index 6f7782bea5dd..7fbca175099e 100644
--- a/tools/perf/arch/powerpc/Makefile
+++ b/tools/perf/arch/powerpc/Makefile
@@ -1,6 +1,3 @@
1ifndef NO_DWARF 1ifndef NO_DWARF
2PERF_HAVE_DWARF_REGS := 1 2PERF_HAVE_DWARF_REGS := 1
3LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
4LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/skip-callchain-idx.o
5endif 3endif
6LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o
diff --git a/tools/perf/arch/powerpc/util/Build b/tools/perf/arch/powerpc/util/Build
new file mode 100644
index 000000000000..0af6e9b3f728
--- /dev/null
+++ b/tools/perf/arch/powerpc/util/Build
@@ -0,0 +1,4 @@
1libperf-y += header.o
2
3libperf-$(CONFIG_DWARF) += dwarf-regs.o
4libperf-$(CONFIG_DWARF) += skip-callchain-idx.o
diff --git a/tools/perf/arch/s390/Build b/tools/perf/arch/s390/Build
new file mode 100644
index 000000000000..54afe4a467e7
--- /dev/null
+++ b/tools/perf/arch/s390/Build
@@ -0,0 +1 @@
libperf-y += util/
diff --git a/tools/perf/arch/s390/Makefile b/tools/perf/arch/s390/Makefile
index 798ac7379c5f..21322e0385b8 100644
--- a/tools/perf/arch/s390/Makefile
+++ b/tools/perf/arch/s390/Makefile
@@ -1,7 +1,4 @@
1ifndef NO_DWARF 1ifndef NO_DWARF
2PERF_HAVE_DWARF_REGS := 1 2PERF_HAVE_DWARF_REGS := 1
3LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
4endif 3endif
5LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o
6HAVE_KVM_STAT_SUPPORT := 1 4HAVE_KVM_STAT_SUPPORT := 1
7LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/kvm-stat.o
diff --git a/tools/perf/arch/s390/util/Build b/tools/perf/arch/s390/util/Build
new file mode 100644
index 000000000000..8a61372bb47a
--- /dev/null
+++ b/tools/perf/arch/s390/util/Build
@@ -0,0 +1,4 @@
1libperf-y += header.o
2libperf-y += kvm-stat.o
3
4libperf-$(CONFIG_DWARF) += dwarf-regs.o
diff --git a/tools/perf/arch/sh/Build b/tools/perf/arch/sh/Build
new file mode 100644
index 000000000000..54afe4a467e7
--- /dev/null
+++ b/tools/perf/arch/sh/Build
@@ -0,0 +1 @@
libperf-y += util/
diff --git a/tools/perf/arch/sh/Makefile b/tools/perf/arch/sh/Makefile
index 15130b50dfe3..7fbca175099e 100644
--- a/tools/perf/arch/sh/Makefile
+++ b/tools/perf/arch/sh/Makefile
@@ -1,4 +1,3 @@
1ifndef NO_DWARF 1ifndef NO_DWARF
2PERF_HAVE_DWARF_REGS := 1 2PERF_HAVE_DWARF_REGS := 1
3LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
4endif 3endif
diff --git a/tools/perf/arch/sh/util/Build b/tools/perf/arch/sh/util/Build
new file mode 100644
index 000000000000..954e287bbb89
--- /dev/null
+++ b/tools/perf/arch/sh/util/Build
@@ -0,0 +1 @@
libperf-$(CONFIG_DWARF) += dwarf-regs.o
diff --git a/tools/perf/arch/sparc/Build b/tools/perf/arch/sparc/Build
new file mode 100644
index 000000000000..54afe4a467e7
--- /dev/null
+++ b/tools/perf/arch/sparc/Build
@@ -0,0 +1 @@
libperf-y += util/
diff --git a/tools/perf/arch/sparc/Makefile b/tools/perf/arch/sparc/Makefile
index 15130b50dfe3..7fbca175099e 100644
--- a/tools/perf/arch/sparc/Makefile
+++ b/tools/perf/arch/sparc/Makefile
@@ -1,4 +1,3 @@
1ifndef NO_DWARF 1ifndef NO_DWARF
2PERF_HAVE_DWARF_REGS := 1 2PERF_HAVE_DWARF_REGS := 1
3LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
4endif 3endif
diff --git a/tools/perf/arch/sparc/util/Build b/tools/perf/arch/sparc/util/Build
new file mode 100644
index 000000000000..954e287bbb89
--- /dev/null
+++ b/tools/perf/arch/sparc/util/Build
@@ -0,0 +1 @@
libperf-$(CONFIG_DWARF) += dwarf-regs.o
diff --git a/tools/perf/arch/x86/Build b/tools/perf/arch/x86/Build
new file mode 100644
index 000000000000..41bf61da476a
--- /dev/null
+++ b/tools/perf/arch/x86/Build
@@ -0,0 +1,2 @@
1libperf-y += util/
2libperf-$(CONFIG_DWARF_UNWIND) += tests/
diff --git a/tools/perf/arch/x86/Makefile b/tools/perf/arch/x86/Makefile
index 9b21881db52f..21322e0385b8 100644
--- a/tools/perf/arch/x86/Makefile
+++ b/tools/perf/arch/x86/Makefile
@@ -1,19 +1,4 @@
1ifndef NO_DWARF 1ifndef NO_DWARF
2PERF_HAVE_DWARF_REGS := 1 2PERF_HAVE_DWARF_REGS := 1
3LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
4endif 3endif
5ifndef NO_LIBUNWIND
6LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind-libunwind.o
7endif
8ifndef NO_LIBDW_DWARF_UNWIND
9LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind-libdw.o
10endif
11ifndef NO_DWARF_UNWIND
12LIB_OBJS += $(OUTPUT)arch/$(ARCH)/tests/regs_load.o
13LIB_OBJS += $(OUTPUT)arch/$(ARCH)/tests/dwarf-unwind.o
14endif
15LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o
16LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/tsc.o
17LIB_H += arch/$(ARCH)/util/tsc.h
18HAVE_KVM_STAT_SUPPORT := 1 4HAVE_KVM_STAT_SUPPORT := 1
19LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/kvm-stat.o
diff --git a/tools/perf/arch/x86/tests/Build b/tools/perf/arch/x86/tests/Build
new file mode 100644
index 000000000000..b30eff9bcc83
--- /dev/null
+++ b/tools/perf/arch/x86/tests/Build
@@ -0,0 +1,2 @@
1libperf-y += regs_load.o
2libperf-y += dwarf-unwind.o
diff --git a/tools/perf/arch/x86/util/Build b/tools/perf/arch/x86/util/Build
new file mode 100644
index 000000000000..cfbccc4e3187
--- /dev/null
+++ b/tools/perf/arch/x86/util/Build
@@ -0,0 +1,8 @@
1libperf-y += header.o
2libperf-y += tsc.o
3libperf-y += kvm-stat.o
4
5libperf-$(CONFIG_DWARF) += dwarf-regs.o
6
7libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o
8libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
diff --git a/tools/perf/bench/Build b/tools/perf/bench/Build
new file mode 100644
index 000000000000..5ce98023d518
--- /dev/null
+++ b/tools/perf/bench/Build
@@ -0,0 +1,11 @@
1perf-y += sched-messaging.o
2perf-y += sched-pipe.o
3perf-y += mem-memcpy.o
4perf-y += futex-hash.o
5perf-y += futex-wake.o
6perf-y += futex-requeue.o
7
8perf-$(CONFIG_X86_64) += mem-memcpy-x86-64-asm.o
9perf-$(CONFIG_X86_64) += mem-memset-x86-64-asm.o
10
11perf-$(CONFIG_NUMA) += numa.o
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 747f86103599..71bf7451c0ca 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -208,7 +208,7 @@ static int __cmd_annotate(struct perf_annotate *ann)
208 goto out; 208 goto out;
209 } 209 }
210 210
211 ret = perf_session__process_events(session, &ann->tool); 211 ret = perf_session__process_events(session);
212 if (ret) 212 if (ret)
213 goto out; 213 goto out;
214 214
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c
index 50e6b66aea1f..d47a0cdc71c9 100644
--- a/tools/perf/builtin-buildid-cache.c
+++ b/tools/perf/builtin-buildid-cache.c
@@ -125,8 +125,7 @@ static int build_id_cache__kcore_existing(const char *from_dir, char *to_dir,
125 return ret; 125 return ret;
126} 126}
127 127
128static int build_id_cache__add_kcore(const char *filename, const char *debugdir, 128static int build_id_cache__add_kcore(const char *filename, bool force)
129 bool force)
130{ 129{
131 char dir[32], sbuildid[BUILD_ID_SIZE * 2 + 1]; 130 char dir[32], sbuildid[BUILD_ID_SIZE * 2 + 1];
132 char from_dir[PATH_MAX], to_dir[PATH_MAX]; 131 char from_dir[PATH_MAX], to_dir[PATH_MAX];
@@ -143,7 +142,7 @@ static int build_id_cache__add_kcore(const char *filename, const char *debugdir,
143 return -1; 142 return -1;
144 143
145 scnprintf(to_dir, sizeof(to_dir), "%s/[kernel.kcore]/%s", 144 scnprintf(to_dir, sizeof(to_dir), "%s/[kernel.kcore]/%s",
146 debugdir, sbuildid); 145 buildid_dir, sbuildid);
147 146
148 if (!force && 147 if (!force &&
149 !build_id_cache__kcore_existing(from_dir, to_dir, sizeof(to_dir))) { 148 !build_id_cache__kcore_existing(from_dir, to_dir, sizeof(to_dir))) {
@@ -155,7 +154,7 @@ static int build_id_cache__add_kcore(const char *filename, const char *debugdir,
155 return -1; 154 return -1;
156 155
157 scnprintf(to_dir, sizeof(to_dir), "%s/[kernel.kcore]/%s/%s", 156 scnprintf(to_dir, sizeof(to_dir), "%s/[kernel.kcore]/%s/%s",
158 debugdir, sbuildid, dir); 157 buildid_dir, sbuildid, dir);
159 158
160 if (mkdir_p(to_dir, 0755)) 159 if (mkdir_p(to_dir, 0755))
161 return -1; 160 return -1;
@@ -183,7 +182,7 @@ static int build_id_cache__add_kcore(const char *filename, const char *debugdir,
183 return 0; 182 return 0;
184} 183}
185 184
186static int build_id_cache__add_file(const char *filename, const char *debugdir) 185static int build_id_cache__add_file(const char *filename)
187{ 186{
188 char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 187 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
189 u8 build_id[BUILD_ID_SIZE]; 188 u8 build_id[BUILD_ID_SIZE];
@@ -195,16 +194,14 @@ static int build_id_cache__add_file(const char *filename, const char *debugdir)
195 } 194 }
196 195
197 build_id__sprintf(build_id, sizeof(build_id), sbuild_id); 196 build_id__sprintf(build_id, sizeof(build_id), sbuild_id);
198 err = build_id_cache__add_s(sbuild_id, debugdir, filename, 197 err = build_id_cache__add_s(sbuild_id, filename,
199 false, false); 198 false, false);
200 if (verbose) 199 pr_debug("Adding %s %s: %s\n", sbuild_id, filename,
201 pr_info("Adding %s %s: %s\n", sbuild_id, filename, 200 err ? "FAIL" : "Ok");
202 err ? "FAIL" : "Ok");
203 return err; 201 return err;
204} 202}
205 203
206static int build_id_cache__remove_file(const char *filename, 204static int build_id_cache__remove_file(const char *filename)
207 const char *debugdir)
208{ 205{
209 u8 build_id[BUILD_ID_SIZE]; 206 u8 build_id[BUILD_ID_SIZE];
210 char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 207 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
@@ -217,10 +214,34 @@ static int build_id_cache__remove_file(const char *filename,
217 } 214 }
218 215
219 build_id__sprintf(build_id, sizeof(build_id), sbuild_id); 216 build_id__sprintf(build_id, sizeof(build_id), sbuild_id);
220 err = build_id_cache__remove_s(sbuild_id, debugdir); 217 err = build_id_cache__remove_s(sbuild_id);
221 if (verbose) 218 pr_debug("Removing %s %s: %s\n", sbuild_id, filename,
222 pr_info("Removing %s %s: %s\n", sbuild_id, filename, 219 err ? "FAIL" : "Ok");
223 err ? "FAIL" : "Ok"); 220
221 return err;
222}
223
224static int build_id_cache__purge_path(const char *pathname)
225{
226 struct strlist *list;
227 struct str_node *pos;
228 int err;
229
230 err = build_id_cache__list_build_ids(pathname, &list);
231 if (err)
232 goto out;
233
234 strlist__for_each(pos, list) {
235 err = build_id_cache__remove_s(pos->s);
236 pr_debug("Removing %s %s: %s\n", pos->s, pathname,
237 err ? "FAIL" : "Ok");
238 if (err)
239 break;
240 }
241 strlist__delete(list);
242
243out:
244 pr_debug("Purging %s: %s\n", pathname, err ? "FAIL" : "Ok");
224 245
225 return err; 246 return err;
226} 247}
@@ -252,13 +273,12 @@ static int build_id_cache__fprintf_missing(struct perf_session *session, FILE *f
252 return 0; 273 return 0;
253} 274}
254 275
255static int build_id_cache__update_file(const char *filename, 276static int build_id_cache__update_file(const char *filename)
256 const char *debugdir)
257{ 277{
258 u8 build_id[BUILD_ID_SIZE]; 278 u8 build_id[BUILD_ID_SIZE];
259 char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 279 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
260 280
261 int err; 281 int err = 0;
262 282
263 if (filename__read_build_id(filename, &build_id, sizeof(build_id)) < 0) { 283 if (filename__read_build_id(filename, &build_id, sizeof(build_id)) < 0) {
264 pr_debug("Couldn't read a build-id in %s\n", filename); 284 pr_debug("Couldn't read a build-id in %s\n", filename);
@@ -266,14 +286,14 @@ static int build_id_cache__update_file(const char *filename,
266 } 286 }
267 287
268 build_id__sprintf(build_id, sizeof(build_id), sbuild_id); 288 build_id__sprintf(build_id, sizeof(build_id), sbuild_id);
269 err = build_id_cache__remove_s(sbuild_id, debugdir); 289 if (build_id_cache__cached(sbuild_id))
270 if (!err) { 290 err = build_id_cache__remove_s(sbuild_id);
271 err = build_id_cache__add_s(sbuild_id, debugdir, filename, 291
272 false, false); 292 if (!err)
273 } 293 err = build_id_cache__add_s(sbuild_id, filename, false, false);
274 if (verbose) 294
275 pr_info("Updating %s %s: %s\n", sbuild_id, filename, 295 pr_debug("Updating %s %s: %s\n", sbuild_id, filename,
276 err ? "FAIL" : "Ok"); 296 err ? "FAIL" : "Ok");
277 297
278 return err; 298 return err;
279} 299}
@@ -287,6 +307,7 @@ int cmd_buildid_cache(int argc, const char **argv,
287 bool force = false; 307 bool force = false;
288 char const *add_name_list_str = NULL, 308 char const *add_name_list_str = NULL,
289 *remove_name_list_str = NULL, 309 *remove_name_list_str = NULL,
310 *purge_name_list_str = NULL,
290 *missing_filename = NULL, 311 *missing_filename = NULL,
291 *update_name_list_str = NULL, 312 *update_name_list_str = NULL,
292 *kcore_filename = NULL; 313 *kcore_filename = NULL;
@@ -304,6 +325,8 @@ int cmd_buildid_cache(int argc, const char **argv,
304 "file", "kcore file to add"), 325 "file", "kcore file to add"),
305 OPT_STRING('r', "remove", &remove_name_list_str, "file list", 326 OPT_STRING('r', "remove", &remove_name_list_str, "file list",
306 "file(s) to remove"), 327 "file(s) to remove"),
328 OPT_STRING('p', "purge", &purge_name_list_str, "path list",
329 "path(s) to remove (remove old caches too)"),
307 OPT_STRING('M', "missing", &missing_filename, "file", 330 OPT_STRING('M', "missing", &missing_filename, "file",
308 "to find missing build ids in the cache"), 331 "to find missing build ids in the cache"),
309 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"), 332 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
@@ -320,6 +343,11 @@ int cmd_buildid_cache(int argc, const char **argv,
320 argc = parse_options(argc, argv, buildid_cache_options, 343 argc = parse_options(argc, argv, buildid_cache_options,
321 buildid_cache_usage, 0); 344 buildid_cache_usage, 0);
322 345
346 if (argc || (!add_name_list_str && !kcore_filename &&
347 !remove_name_list_str && !purge_name_list_str &&
348 !missing_filename && !update_name_list_str))
349 usage_with_options(buildid_cache_usage, buildid_cache_options);
350
323 if (missing_filename) { 351 if (missing_filename) {
324 file.path = missing_filename; 352 file.path = missing_filename;
325 file.force = force; 353 file.force = force;
@@ -338,7 +366,7 @@ int cmd_buildid_cache(int argc, const char **argv,
338 list = strlist__new(true, add_name_list_str); 366 list = strlist__new(true, add_name_list_str);
339 if (list) { 367 if (list) {
340 strlist__for_each(pos, list) 368 strlist__for_each(pos, list)
341 if (build_id_cache__add_file(pos->s, buildid_dir)) { 369 if (build_id_cache__add_file(pos->s)) {
342 if (errno == EEXIST) { 370 if (errno == EEXIST) {
343 pr_debug("%s already in the cache\n", 371 pr_debug("%s already in the cache\n",
344 pos->s); 372 pos->s);
@@ -356,7 +384,25 @@ int cmd_buildid_cache(int argc, const char **argv,
356 list = strlist__new(true, remove_name_list_str); 384 list = strlist__new(true, remove_name_list_str);
357 if (list) { 385 if (list) {
358 strlist__for_each(pos, list) 386 strlist__for_each(pos, list)
359 if (build_id_cache__remove_file(pos->s, buildid_dir)) { 387 if (build_id_cache__remove_file(pos->s)) {
388 if (errno == ENOENT) {
389 pr_debug("%s wasn't in the cache\n",
390 pos->s);
391 continue;
392 }
393 pr_warning("Couldn't remove %s: %s\n",
394 pos->s, strerror_r(errno, sbuf, sizeof(sbuf)));
395 }
396
397 strlist__delete(list);
398 }
399 }
400
401 if (purge_name_list_str) {
402 list = strlist__new(true, purge_name_list_str);
403 if (list) {
404 strlist__for_each(pos, list)
405 if (build_id_cache__purge_path(pos->s)) {
360 if (errno == ENOENT) { 406 if (errno == ENOENT) {
361 pr_debug("%s wasn't in the cache\n", 407 pr_debug("%s wasn't in the cache\n",
362 pos->s); 408 pos->s);
@@ -377,7 +423,7 @@ int cmd_buildid_cache(int argc, const char **argv,
377 list = strlist__new(true, update_name_list_str); 423 list = strlist__new(true, update_name_list_str);
378 if (list) { 424 if (list) {
379 strlist__for_each(pos, list) 425 strlist__for_each(pos, list)
380 if (build_id_cache__update_file(pos->s, buildid_dir)) { 426 if (build_id_cache__update_file(pos->s)) {
381 if (errno == ENOENT) { 427 if (errno == ENOENT) {
382 pr_debug("%s wasn't in the cache\n", 428 pr_debug("%s wasn't in the cache\n",
383 pos->s); 429 pos->s);
@@ -391,8 +437,7 @@ int cmd_buildid_cache(int argc, const char **argv,
391 } 437 }
392 } 438 }
393 439
394 if (kcore_filename && 440 if (kcore_filename && build_id_cache__add_kcore(kcore_filename, force))
395 build_id_cache__add_kcore(kcore_filename, buildid_dir, force))
396 pr_warning("Couldn't add %s\n", kcore_filename); 441 pr_warning("Couldn't add %s\n", kcore_filename);
397 442
398out: 443out:
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index ed3873b3e238..feb420f74c2d 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -74,7 +74,7 @@ static int perf_session__list_build_ids(bool force, bool with_hits)
74 * the record stream. Buildids are stored as RECORD_HEADER_BUILD_ID 74 * the record stream. Buildids are stored as RECORD_HEADER_BUILD_ID
75 */ 75 */
76 if (with_hits || perf_data_file__is_pipe(&file)) 76 if (with_hits || perf_data_file__is_pipe(&file))
77 perf_session__process_events(session, &build_id__mark_dso_hit_ops); 77 perf_session__process_events(session);
78 78
79 perf_session__fprintf_dsos_buildid(session, stdout, dso__skip_buildid, with_hits); 79 perf_session__fprintf_dsos_buildid(session, stdout, dso__skip_buildid, with_hits);
80 perf_session__delete(session); 80 perf_session__delete(session);
diff --git a/tools/perf/builtin-data.c b/tools/perf/builtin-data.c
new file mode 100644
index 000000000000..709152a7b408
--- /dev/null
+++ b/tools/perf/builtin-data.c
@@ -0,0 +1,121 @@
1#include <linux/compiler.h>
2#include "builtin.h"
3#include "perf.h"
4#include "debug.h"
5#include "parse-options.h"
6#include "data-convert-bt.h"
7
8typedef int (*data_cmd_fn_t)(int argc, const char **argv, const char *prefix);
9
10struct data_cmd {
11 const char *name;
12 const char *summary;
13 data_cmd_fn_t fn;
14};
15
16static struct data_cmd data_cmds[];
17
18#define for_each_cmd(cmd) \
19 for (cmd = data_cmds; cmd && cmd->name; cmd++)
20
21static const struct option data_options[] = {
22 OPT_END()
23};
24
25static const char * const data_subcommands[] = { "convert", NULL };
26
27static const char *data_usage[] = {
28 "perf data [<common options>] <command> [<options>]",
29 NULL
30};
31
32static void print_usage(void)
33{
34 struct data_cmd *cmd;
35
36 printf("Usage:\n");
37 printf("\t%s\n\n", data_usage[0]);
38 printf("\tAvailable commands:\n");
39
40 for_each_cmd(cmd) {
41 printf("\t %s\t- %s\n", cmd->name, cmd->summary);
42 }
43
44 printf("\n");
45}
46
47static const char * const data_convert_usage[] = {
48 "perf data convert [<options>]",
49 NULL
50};
51
52static int cmd_data_convert(int argc, const char **argv,
53 const char *prefix __maybe_unused)
54{
55 const char *to_ctf = NULL;
56 const struct option options[] = {
57 OPT_INCR('v', "verbose", &verbose, "be more verbose"),
58 OPT_STRING('i', "input", &input_name, "file", "input file name"),
59#ifdef HAVE_LIBBABELTRACE_SUPPORT
60 OPT_STRING(0, "to-ctf", &to_ctf, NULL, "Convert to CTF format"),
61#endif
62 OPT_END()
63 };
64
65#ifndef HAVE_LIBBABELTRACE_SUPPORT
66 pr_err("No conversion support compiled in.\n");
67 return -1;
68#endif
69
70 argc = parse_options(argc, argv, options,
71 data_convert_usage, 0);
72 if (argc) {
73 usage_with_options(data_convert_usage, options);
74 return -1;
75 }
76
77 if (to_ctf) {
78#ifdef HAVE_LIBBABELTRACE_SUPPORT
79 return bt_convert__perf2ctf(input_name, to_ctf);
80#else
81 pr_err("The libbabeltrace support is not compiled in.\n");
82 return -1;
83#endif
84 }
85
86 return 0;
87}
88
89static struct data_cmd data_cmds[] = {
90 { "convert", "converts data file between formats", cmd_data_convert },
91 { .name = NULL, },
92};
93
94int cmd_data(int argc, const char **argv, const char *prefix)
95{
96 struct data_cmd *cmd;
97 const char *cmdstr;
98
99 /* No command specified. */
100 if (argc < 2)
101 goto usage;
102
103 argc = parse_options_subcommand(argc, argv, data_options, data_subcommands, data_usage,
104 PARSE_OPT_STOP_AT_NON_OPTION);
105 if (argc < 1)
106 goto usage;
107
108 cmdstr = argv[0];
109
110 for_each_cmd(cmd) {
111 if (strcmp(cmd->name, cmdstr))
112 continue;
113
114 return cmd->fn(argc, argv, prefix);
115 }
116
117 pr_err("Unknown command: %s\n", cmdstr);
118usage:
119 print_usage();
120 return -1;
121}
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 74aada554b12..df6307b4050a 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -747,7 +747,7 @@ static int __cmd_diff(void)
747 goto out_delete; 747 goto out_delete;
748 } 748 }
749 749
750 ret = perf_session__process_events(d->session, &tool); 750 ret = perf_session__process_events(d->session);
751 if (ret) { 751 if (ret) {
752 pr_err("Failed to process %s\n", d->file.path); 752 pr_err("Failed to process %s\n", d->file.path);
753 goto out_delete; 753 goto out_delete;
@@ -791,6 +791,8 @@ static const struct option options[] = {
791 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 791 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
792 "dump raw trace in ASCII"), 792 "dump raw trace in ASCII"),
793 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"), 793 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
794 OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name,
795 "file", "kallsyms pathname"),
794 OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules, 796 OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
795 "load module symbols - WARNING: use only with -k and LIVE kernel"), 797 "load module symbols - WARNING: use only with -k and LIVE kernel"),
796 OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]", 798 OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
@@ -802,7 +804,7 @@ static const struct option options[] = {
802 OPT_STRING('s', "sort", &sort_order, "key[,key2...]", 804 OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
803 "sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline, ..." 805 "sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline, ..."
804 " Please refer the man page for the complete list."), 806 " Please refer the man page for the complete list."),
805 OPT_STRING('t', "field-separator", &symbol_conf.field_sep, "separator", 807 OPT_STRING_NOEMPTY('t', "field-separator", &symbol_conf.field_sep, "separator",
806 "separator for columns, no spaces will be added between " 808 "separator for columns, no spaces will be added between "
807 "columns '.' is reserved."), 809 "columns '.' is reserved."),
808 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", 810 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c
index 25d20628212e..36486eade1ef 100644
--- a/tools/perf/builtin-help.c
+++ b/tools/perf/builtin-help.c
@@ -437,7 +437,18 @@ int cmd_help(int argc, const char **argv, const char *prefix __maybe_unused)
437 HELP_FORMAT_INFO), 437 HELP_FORMAT_INFO),
438 OPT_END(), 438 OPT_END(),
439 }; 439 };
440 const char * const builtin_help_usage[] = { 440 const char * const builtin_help_subcommands[] = {
441 "buildid-cache", "buildid-list", "diff", "evlist", "help", "list",
442 "record", "report", "bench", "stat", "timechart", "top", "annotate",
443 "script", "sched", "kmem", "lock", "kvm", "test", "inject", "mem", "data",
444#ifdef HAVE_LIBELF_SUPPORT
445 "probe",
446#endif
447#ifdef HAVE_LIBAUDIT_SUPPORT
448 "trace",
449#endif
450 NULL };
451 const char *builtin_help_usage[] = {
441 "perf help [--all] [--man|--web|--info] [command]", 452 "perf help [--all] [--man|--web|--info] [command]",
442 NULL 453 NULL
443 }; 454 };
@@ -448,8 +459,8 @@ int cmd_help(int argc, const char **argv, const char *prefix __maybe_unused)
448 459
449 perf_config(perf_help_config, &help_format); 460 perf_config(perf_help_config, &help_format);
450 461
451 argc = parse_options(argc, argv, builtin_help_options, 462 argc = parse_options_subcommand(argc, argv, builtin_help_options,
452 builtin_help_usage, 0); 463 builtin_help_subcommands, builtin_help_usage, 0);
453 464
454 if (show_all) { 465 if (show_all) {
455 printf("\n usage: %s\n\n", perf_usage_string); 466 printf("\n usage: %s\n\n", perf_usage_string);
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index a13641e066f5..ea46df25368c 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -53,6 +53,13 @@ static int perf_event__repipe_synth(struct perf_tool *tool,
53 return 0; 53 return 0;
54} 54}
55 55
56static int perf_event__repipe_oe_synth(struct perf_tool *tool,
57 union perf_event *event,
58 struct ordered_events *oe __maybe_unused)
59{
60 return perf_event__repipe_synth(tool, event);
61}
62
56static int perf_event__repipe_op2_synth(struct perf_tool *tool, 63static int perf_event__repipe_op2_synth(struct perf_tool *tool,
57 union perf_event *event, 64 union perf_event *event,
58 struct perf_session *session 65 struct perf_session *session
@@ -359,8 +366,6 @@ static int __cmd_inject(struct perf_inject *inject)
359 } else if (inject->sched_stat) { 366 } else if (inject->sched_stat) {
360 struct perf_evsel *evsel; 367 struct perf_evsel *evsel;
361 368
362 inject->tool.ordered_events = true;
363
364 evlist__for_each(session->evlist, evsel) { 369 evlist__for_each(session->evlist, evsel) {
365 const char *name = perf_evsel__name(evsel); 370 const char *name = perf_evsel__name(evsel);
366 371
@@ -379,7 +384,7 @@ static int __cmd_inject(struct perf_inject *inject)
379 if (!file_out->is_pipe) 384 if (!file_out->is_pipe)
380 lseek(fd, session->header.data_offset, SEEK_SET); 385 lseek(fd, session->header.data_offset, SEEK_SET);
381 386
382 ret = perf_session__process_events(session, &inject->tool); 387 ret = perf_session__process_events(session);
383 388
384 if (!file_out->is_pipe) { 389 if (!file_out->is_pipe) {
385 if (inject->build_ids) 390 if (inject->build_ids)
@@ -408,7 +413,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
408 .unthrottle = perf_event__repipe, 413 .unthrottle = perf_event__repipe,
409 .attr = perf_event__repipe_attr, 414 .attr = perf_event__repipe_attr,
410 .tracing_data = perf_event__repipe_op2_synth, 415 .tracing_data = perf_event__repipe_op2_synth,
411 .finished_round = perf_event__repipe_op2_synth, 416 .finished_round = perf_event__repipe_oe_synth,
412 .build_id = perf_event__repipe_op2_synth, 417 .build_id = perf_event__repipe_op2_synth,
413 .id_index = perf_event__repipe_op2_synth, 418 .id_index = perf_event__repipe_op2_synth,
414 }, 419 },
@@ -458,6 +463,8 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
458 return -1; 463 return -1;
459 } 464 }
460 465
466 inject.tool.ordered_events = inject.sched_stat;
467
461 file.path = inject.input_name; 468 file.path = inject.input_name;
462 inject.session = perf_session__new(&file, true, &inject.tool); 469 inject.session = perf_session__new(&file, true, &inject.tool);
463 if (inject.session == NULL) 470 if (inject.session == NULL)
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index f295141025bc..64d3623d45a0 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -20,6 +20,7 @@
20 20
21#include <linux/rbtree.h> 21#include <linux/rbtree.h>
22#include <linux/string.h> 22#include <linux/string.h>
23#include <locale.h>
23 24
24struct alloc_stat; 25struct alloc_stat;
25typedef int (*sort_fn_t)(struct alloc_stat *, struct alloc_stat *); 26typedef int (*sort_fn_t)(struct alloc_stat *, struct alloc_stat *);
@@ -275,10 +276,10 @@ static void __print_result(struct rb_root *root, struct perf_session *session,
275 struct rb_node *next; 276 struct rb_node *next;
276 struct machine *machine = &session->machines.host; 277 struct machine *machine = &session->machines.host;
277 278
278 printf("%.102s\n", graph_dotted_line); 279 printf("%.105s\n", graph_dotted_line);
279 printf(" %-34s |", is_caller ? "Callsite": "Alloc Ptr"); 280 printf(" %-34s |", is_caller ? "Callsite": "Alloc Ptr");
280 printf(" Total_alloc/Per | Total_req/Per | Hit | Ping-pong | Frag\n"); 281 printf(" Total_alloc/Per | Total_req/Per | Hit | Ping-pong | Frag\n");
281 printf("%.102s\n", graph_dotted_line); 282 printf("%.105s\n", graph_dotted_line);
282 283
283 next = rb_first(root); 284 next = rb_first(root);
284 285
@@ -304,7 +305,7 @@ static void __print_result(struct rb_root *root, struct perf_session *session,
304 snprintf(buf, sizeof(buf), "%#" PRIx64 "", addr); 305 snprintf(buf, sizeof(buf), "%#" PRIx64 "", addr);
305 printf(" %-34s |", buf); 306 printf(" %-34s |", buf);
306 307
307 printf(" %9llu/%-5lu | %9llu/%-5lu | %8lu | %8lu | %6.3f%%\n", 308 printf(" %9llu/%-5lu | %9llu/%-5lu | %8lu | %9lu | %6.3f%%\n",
308 (unsigned long long)data->bytes_alloc, 309 (unsigned long long)data->bytes_alloc,
309 (unsigned long)data->bytes_alloc / data->hit, 310 (unsigned long)data->bytes_alloc / data->hit,
310 (unsigned long long)data->bytes_req, 311 (unsigned long long)data->bytes_req,
@@ -317,21 +318,21 @@ static void __print_result(struct rb_root *root, struct perf_session *session,
317 } 318 }
318 319
319 if (n_lines == -1) 320 if (n_lines == -1)
320 printf(" ... | ... | ... | ... | ... | ... \n"); 321 printf(" ... | ... | ... | ... | ... | ... \n");
321 322
322 printf("%.102s\n", graph_dotted_line); 323 printf("%.105s\n", graph_dotted_line);
323} 324}
324 325
325static void print_summary(void) 326static void print_summary(void)
326{ 327{
327 printf("\nSUMMARY\n=======\n"); 328 printf("\nSUMMARY\n=======\n");
328 printf("Total bytes requested: %lu\n", total_requested); 329 printf("Total bytes requested: %'lu\n", total_requested);
329 printf("Total bytes allocated: %lu\n", total_allocated); 330 printf("Total bytes allocated: %'lu\n", total_allocated);
330 printf("Total bytes wasted on internal fragmentation: %lu\n", 331 printf("Total bytes wasted on internal fragmentation: %'lu\n",
331 total_allocated - total_requested); 332 total_allocated - total_requested);
332 printf("Internal fragmentation: %f%%\n", 333 printf("Internal fragmentation: %f%%\n",
333 fragmentation(total_requested, total_allocated)); 334 fragmentation(total_requested, total_allocated));
334 printf("Cross CPU allocations: %lu/%lu\n", nr_cross_allocs, nr_allocs); 335 printf("Cross CPU allocations: %'lu/%'lu\n", nr_cross_allocs, nr_allocs);
335} 336}
336 337
337static void print_result(struct perf_session *session) 338static void print_result(struct perf_session *session)
@@ -426,7 +427,7 @@ static int __cmd_kmem(struct perf_session *session)
426 } 427 }
427 428
428 setup_pager(); 429 setup_pager();
429 err = perf_session__process_events(session, &perf_kmem); 430 err = perf_session__process_events(session);
430 if (err != 0) 431 if (err != 0)
431 goto out; 432 goto out;
432 sort_result(); 433 sort_result();
@@ -559,6 +560,7 @@ static int setup_sorting(struct list_head *sort_list, const char *arg)
559{ 560{
560 char *tok; 561 char *tok;
561 char *str = strdup(arg); 562 char *str = strdup(arg);
563 char *pos = str;
562 564
563 if (!str) { 565 if (!str) {
564 pr_err("%s: strdup failed\n", __func__); 566 pr_err("%s: strdup failed\n", __func__);
@@ -566,7 +568,7 @@ static int setup_sorting(struct list_head *sort_list, const char *arg)
566 } 568 }
567 569
568 while (true) { 570 while (true) {
569 tok = strsep(&str, ","); 571 tok = strsep(&pos, ",");
570 if (!tok) 572 if (!tok)
571 break; 573 break;
572 if (sort_dimension__add(tok, sort_list) < 0) { 574 if (sort_dimension__add(tok, sort_list) < 0) {
@@ -662,6 +664,8 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
662 const char * const default_sort_order = "frag,hit,bytes"; 664 const char * const default_sort_order = "frag,hit,bytes";
663 const struct option kmem_options[] = { 665 const struct option kmem_options[] = {
664 OPT_STRING('i', "input", &input_name, "file", "input file name"), 666 OPT_STRING('i', "input", &input_name, "file", "input file name"),
667 OPT_INCR('v', "verbose", &verbose,
668 "be more verbose (show symbol address, etc)"),
665 OPT_CALLBACK_NOOPT(0, "caller", NULL, NULL, 669 OPT_CALLBACK_NOOPT(0, "caller", NULL, NULL,
666 "show per-callsite statistics", parse_caller_opt), 670 "show per-callsite statistics", parse_caller_opt),
667 OPT_CALLBACK_NOOPT(0, "alloc", NULL, NULL, 671 OPT_CALLBACK_NOOPT(0, "alloc", NULL, NULL,
@@ -703,6 +707,8 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
703 symbol__init(&session->header.env); 707 symbol__init(&session->header.env);
704 708
705 if (!strcmp(argv[0], "stat")) { 709 if (!strcmp(argv[0], "stat")) {
710 setlocale(LC_ALL, "");
711
706 if (cpu__setup_cpunode_map()) 712 if (cpu__setup_cpunode_map())
707 goto out_delete; 713 goto out_delete;
708 714
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 0894a817f67e..643722f40075 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -18,6 +18,7 @@
18#include "util/stat.h" 18#include "util/stat.h"
19#include "util/top.h" 19#include "util/top.h"
20#include "util/data.h" 20#include "util/data.h"
21#include "util/ordered-events.h"
21 22
22#include <sys/prctl.h> 23#include <sys/prctl.h>
23#ifdef HAVE_TIMERFD_SUPPORT 24#ifdef HAVE_TIMERFD_SUPPORT
@@ -730,9 +731,9 @@ static s64 perf_kvm__mmap_read_idx(struct perf_kvm_stat *kvm, int idx,
730 return -1; 731 return -1;
731 } 732 }
732 733
733 err = perf_session_queue_event(kvm->session, event, &kvm->tool, &sample, 0); 734 err = perf_session__queue_event(kvm->session, event, &sample, 0);
734 /* 735 /*
735 * FIXME: Here we can't consume the event, as perf_session_queue_event will 736 * FIXME: Here we can't consume the event, as perf_session__queue_event will
736 * point to it, and it'll get possibly overwritten by the kernel. 737 * point to it, and it'll get possibly overwritten by the kernel.
737 */ 738 */
738 perf_evlist__mmap_consume(kvm->evlist, idx); 739 perf_evlist__mmap_consume(kvm->evlist, idx);
@@ -783,8 +784,10 @@ static int perf_kvm__mmap_read(struct perf_kvm_stat *kvm)
783 784
784 /* flush queue after each round in which we processed events */ 785 /* flush queue after each round in which we processed events */
785 if (ntotal) { 786 if (ntotal) {
786 kvm->session->ordered_events.next_flush = flush_time; 787 struct ordered_events *oe = &kvm->session->ordered_events;
787 err = kvm->tool.finished_round(&kvm->tool, NULL, kvm->session); 788
789 oe->next_flush = flush_time;
790 err = ordered_events__flush(oe, OE_FLUSH__ROUND);
788 if (err) { 791 if (err) {
789 if (kvm->lost_events) 792 if (kvm->lost_events)
790 pr_info("\nLost events: %" PRIu64 "\n\n", 793 pr_info("\nLost events: %" PRIu64 "\n\n",
@@ -1066,7 +1069,7 @@ static int read_events(struct perf_kvm_stat *kvm)
1066 if (ret < 0) 1069 if (ret < 0)
1067 return ret; 1070 return ret;
1068 1071
1069 return perf_session__process_events(kvm->session, &kvm->tool); 1072 return perf_session__process_events(kvm->session);
1070} 1073}
1071 1074
1072static int parse_target_str(struct perf_kvm_stat *kvm) 1075static int parse_target_str(struct perf_kvm_stat *kvm)
diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
index 198f3c3aff95..af5bd0514108 100644
--- a/tools/perf/builtin-list.c
+++ b/tools/perf/builtin-list.c
@@ -36,38 +36,36 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
36 36
37 setup_pager(); 37 setup_pager();
38 38
39 if (raw_dump) { 39 if (!raw_dump)
40 print_events(NULL, true); 40 printf("\nList of pre-defined events (to be used in -e):\n\n");
41 return 0;
42 }
43 41
44 if (argc == 0) { 42 if (argc == 0) {
45 print_events(NULL, false); 43 print_events(NULL, raw_dump);
46 return 0; 44 return 0;
47 } 45 }
48 46
49 for (i = 0; i < argc; ++i) { 47 for (i = 0; i < argc; ++i) {
50 if (i) 48 if (strcmp(argv[i], "tracepoint") == 0)
51 putchar('\n'); 49 print_tracepoint_events(NULL, NULL, raw_dump);
52 if (strncmp(argv[i], "tracepoint", 10) == 0)
53 print_tracepoint_events(NULL, NULL, false);
54 else if (strcmp(argv[i], "hw") == 0 || 50 else if (strcmp(argv[i], "hw") == 0 ||
55 strcmp(argv[i], "hardware") == 0) 51 strcmp(argv[i], "hardware") == 0)
56 print_events_type(PERF_TYPE_HARDWARE); 52 print_symbol_events(NULL, PERF_TYPE_HARDWARE,
53 event_symbols_hw, PERF_COUNT_HW_MAX, raw_dump);
57 else if (strcmp(argv[i], "sw") == 0 || 54 else if (strcmp(argv[i], "sw") == 0 ||
58 strcmp(argv[i], "software") == 0) 55 strcmp(argv[i], "software") == 0)
59 print_events_type(PERF_TYPE_SOFTWARE); 56 print_symbol_events(NULL, PERF_TYPE_SOFTWARE,
57 event_symbols_sw, PERF_COUNT_SW_MAX, raw_dump);
60 else if (strcmp(argv[i], "cache") == 0 || 58 else if (strcmp(argv[i], "cache") == 0 ||
61 strcmp(argv[i], "hwcache") == 0) 59 strcmp(argv[i], "hwcache") == 0)
62 print_hwcache_events(NULL, false); 60 print_hwcache_events(NULL, raw_dump);
63 else if (strcmp(argv[i], "pmu") == 0) 61 else if (strcmp(argv[i], "pmu") == 0)
64 print_pmu_events(NULL, false); 62 print_pmu_events(NULL, raw_dump);
65 else { 63 else {
66 char *sep = strchr(argv[i], ':'), *s; 64 char *sep = strchr(argv[i], ':'), *s;
67 int sep_idx; 65 int sep_idx;
68 66
69 if (sep == NULL) { 67 if (sep == NULL) {
70 print_events(argv[i], false); 68 print_events(argv[i], raw_dump);
71 continue; 69 continue;
72 } 70 }
73 sep_idx = sep - argv[i]; 71 sep_idx = sep - argv[i];
@@ -76,7 +74,7 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
76 return -1; 74 return -1;
77 75
78 s[sep_idx] = '\0'; 76 s[sep_idx] = '\0';
79 print_tracepoint_events(s, s + sep_idx + 1, false); 77 print_tracepoint_events(s, s + sep_idx + 1, raw_dump);
80 free(s); 78 free(s);
81 } 79 }
82 } 80 }
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index e7ec71589da6..7893a9bba2a7 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -878,7 +878,7 @@ static int __cmd_report(bool display_info)
878 if (select_key()) 878 if (select_key())
879 goto out_delete; 879 goto out_delete;
880 880
881 err = perf_session__process_events(session, &eops); 881 err = perf_session__process_events(session);
882 if (err) 882 if (err)
883 goto out_delete; 883 goto out_delete;
884 884
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
index 9b5663950a4d..b4dcf0bfc029 100644
--- a/tools/perf/builtin-mem.c
+++ b/tools/perf/builtin-mem.c
@@ -141,7 +141,7 @@ static int report_raw_events(struct perf_mem *mem)
141 141
142 printf("# PID, TID, IP, ADDR, LOCAL WEIGHT, DSRC, SYMBOL\n"); 142 printf("# PID, TID, IP, ADDR, LOCAL WEIGHT, DSRC, SYMBOL\n");
143 143
144 err = perf_session__process_events(session, &mem->tool); 144 err = perf_session__process_events(session);
145 if (err) 145 if (err)
146 return err; 146 return err;
147 147
@@ -286,7 +286,7 @@ int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused)
286 "input file name"), 286 "input file name"),
287 OPT_STRING('C', "cpu", &mem.cpu_list, "cpu", 287 OPT_STRING('C', "cpu", &mem.cpu_list, "cpu",
288 "list of cpus to profile"), 288 "list of cpus to profile"),
289 OPT_STRING('x', "field-separator", &symbol_conf.field_sep, 289 OPT_STRING_NOEMPTY('x', "field-separator", &symbol_conf.field_sep,
290 "separator", 290 "separator",
291 "separator for columns, no spaces will be added" 291 "separator for columns, no spaces will be added"
292 " between columns '.' is reserved."), 292 " between columns '.' is reserved."),
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 404ab3434052..18aad239b401 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -161,8 +161,9 @@ try_again:
161 } 161 }
162 } 162 }
163 163
164 if (perf_evlist__apply_filters(evlist)) { 164 if (perf_evlist__apply_filters(evlist, &pos)) {
165 error("failed to set filter with %d (%s)\n", errno, 165 error("failed to set filter \"%s\" on event %s with %d (%s)\n",
166 pos->filter, perf_evsel__name(pos), errno,
166 strerror_r(errno, msg, sizeof(msg))); 167 strerror_r(errno, msg, sizeof(msg)));
167 rc = -1; 168 rc = -1;
168 goto out; 169 goto out;
@@ -225,7 +226,7 @@ static int process_buildids(struct record *rec)
225 */ 226 */
226 symbol_conf.ignore_vmlinux_buildid = true; 227 symbol_conf.ignore_vmlinux_buildid = true;
227 228
228 return perf_session__process_events(session, &rec->tool); 229 return perf_session__process_events(session);
229} 230}
230 231
231static void perf_event__synthesize_guest_os(struct machine *machine, void *data) 232static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
@@ -343,7 +344,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
343 signal(SIGINT, sig_handler); 344 signal(SIGINT, sig_handler);
344 signal(SIGTERM, sig_handler); 345 signal(SIGTERM, sig_handler);
345 346
346 session = perf_session__new(file, false, NULL); 347 session = perf_session__new(file, false, tool);
347 if (session == NULL) { 348 if (session == NULL) {
348 pr_err("Perf session creation failed.\n"); 349 pr_err("Perf session creation failed.\n");
349 return -1; 350 return -1;
@@ -658,7 +659,7 @@ error:
658 659
659static void callchain_debug(void) 660static void callchain_debug(void)
660{ 661{
661 static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF" }; 662 static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" };
662 663
663 pr_debug("callchain: type %s\n", str[callchain_param.record_mode]); 664 pr_debug("callchain: type %s\n", str[callchain_param.record_mode]);
664 665
@@ -751,9 +752,9 @@ static struct record record = {
751#define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace) recording: " 752#define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace) recording: "
752 753
753#ifdef HAVE_DWARF_UNWIND_SUPPORT 754#ifdef HAVE_DWARF_UNWIND_SUPPORT
754const char record_callchain_help[] = CALLCHAIN_HELP "fp dwarf"; 755const char record_callchain_help[] = CALLCHAIN_HELP "fp dwarf lbr";
755#else 756#else
756const char record_callchain_help[] = CALLCHAIN_HELP "fp"; 757const char record_callchain_help[] = CALLCHAIN_HELP "fp lbr";
757#endif 758#endif
758 759
759/* 760/*
@@ -839,6 +840,8 @@ struct option __record_options[] = {
839 "use per-thread mmaps"), 840 "use per-thread mmaps"),
840 OPT_BOOLEAN('I', "intr-regs", &record.opts.sample_intr_regs, 841 OPT_BOOLEAN('I', "intr-regs", &record.opts.sample_intr_regs,
841 "Sample machine registers on interrupt"), 842 "Sample machine registers on interrupt"),
843 OPT_BOOLEAN(0, "running-time", &record.opts.running_time,
844 "Record running/enabled time of read (:S) events"),
842 OPT_END() 845 OPT_END()
843}; 846};
844 847
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 2f91094e228b..b5b2ad4ca9c4 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -249,6 +249,8 @@ static int report__setup_sample_type(struct report *rep)
249 if ((sample_type & PERF_SAMPLE_REGS_USER) && 249 if ((sample_type & PERF_SAMPLE_REGS_USER) &&
250 (sample_type & PERF_SAMPLE_STACK_USER)) 250 (sample_type & PERF_SAMPLE_STACK_USER))
251 callchain_param.record_mode = CALLCHAIN_DWARF; 251 callchain_param.record_mode = CALLCHAIN_DWARF;
252 else if (sample_type & PERF_SAMPLE_BRANCH_STACK)
253 callchain_param.record_mode = CALLCHAIN_LBR;
252 else 254 else
253 callchain_param.record_mode = CALLCHAIN_FP; 255 callchain_param.record_mode = CALLCHAIN_FP;
254 } 256 }
@@ -302,7 +304,7 @@ static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report
302 304
303 if (rep->mem_mode) { 305 if (rep->mem_mode) {
304 ret += fprintf(fp, "\n# Total weight : %" PRIu64, nr_events); 306 ret += fprintf(fp, "\n# Total weight : %" PRIu64, nr_events);
305 ret += fprintf(fp, "\n# Sort order : %s", sort_order); 307 ret += fprintf(fp, "\n# Sort order : %s", sort_order ? : default_mem_sort_order);
306 } else 308 } else
307 ret += fprintf(fp, "\n# Event count (approx.): %" PRIu64, nr_events); 309 ret += fprintf(fp, "\n# Event count (approx.): %" PRIu64, nr_events);
308 return ret + fprintf(fp, "\n#\n"); 310 return ret + fprintf(fp, "\n#\n");
@@ -480,7 +482,7 @@ static int __cmd_report(struct report *rep)
480 if (ret) 482 if (ret)
481 return ret; 483 return ret;
482 484
483 ret = perf_session__process_events(session, &rep->tool); 485 ret = perf_session__process_events(session);
484 if (ret) 486 if (ret)
485 return ret; 487 return ret;
486 488
@@ -667,6 +669,10 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
667 "only consider symbols in these dsos"), 669 "only consider symbols in these dsos"),
668 OPT_STRING('c', "comms", &symbol_conf.comm_list_str, "comm[,comm...]", 670 OPT_STRING('c', "comms", &symbol_conf.comm_list_str, "comm[,comm...]",
669 "only consider symbols in these comms"), 671 "only consider symbols in these comms"),
672 OPT_STRING(0, "pid", &symbol_conf.pid_list_str, "pid[,pid...]",
673 "only consider symbols in these pids"),
674 OPT_STRING(0, "tid", &symbol_conf.tid_list_str, "tid[,tid...]",
675 "only consider symbols in these tids"),
670 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]", 676 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
671 "only consider these symbols"), 677 "only consider these symbols"),
672 OPT_STRING(0, "symbol-filter", &report.symbol_filter_str, "filter", 678 OPT_STRING(0, "symbol-filter", &report.symbol_filter_str, "filter",
@@ -674,7 +680,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
674 OPT_STRING('w', "column-widths", &symbol_conf.col_width_list_str, 680 OPT_STRING('w', "column-widths", &symbol_conf.col_width_list_str,
675 "width[,width...]", 681 "width[,width...]",
676 "don't try to adjust column width, use these fixed values"), 682 "don't try to adjust column width, use these fixed values"),
677 OPT_STRING('t', "field-separator", &symbol_conf.field_sep, "separator", 683 OPT_STRING_NOEMPTY('t', "field-separator", &symbol_conf.field_sep, "separator",
678 "separator for columns, no spaces will be added between " 684 "separator for columns, no spaces will be added between "
679 "columns '.' is reserved."), 685 "columns '.' is reserved."),
680 OPT_BOOLEAN('U', "hide-unresolved", &report.hide_unresolved, 686 OPT_BOOLEAN('U', "hide-unresolved", &report.hide_unresolved,
@@ -766,7 +772,7 @@ repeat:
766 * 0/1 means the user chose a mode. 772 * 0/1 means the user chose a mode.
767 */ 773 */
768 if (((branch_mode == -1 && has_br_stack) || branch_mode == 1) && 774 if (((branch_mode == -1 && has_br_stack) || branch_mode == 1) &&
769 branch_call_mode == -1) { 775 !branch_call_mode) {
770 sort__mode = SORT_MODE__BRANCH; 776 sort__mode = SORT_MODE__BRANCH;
771 symbol_conf.cumulate_callchain = false; 777 symbol_conf.cumulate_callchain = false;
772 } 778 }
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 891c3930080e..3b3a5bb97059 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -831,7 +831,7 @@ static int thread_atoms_insert(struct perf_sched *sched, struct thread *thread)
831 return -1; 831 return -1;
832 } 832 }
833 833
834 atoms->thread = thread; 834 atoms->thread = thread__get(thread);
835 INIT_LIST_HEAD(&atoms->work_list); 835 INIT_LIST_HEAD(&atoms->work_list);
836 __thread_latency_insert(&sched->atom_root, atoms, &sched->cmp_pid); 836 __thread_latency_insert(&sched->atom_root, atoms, &sched->cmp_pid);
837 return 0; 837 return 0;
@@ -1439,8 +1439,7 @@ static int perf_sched__process_tracepoint_sample(struct perf_tool *tool __maybe_
1439 return err; 1439 return err;
1440} 1440}
1441 1441
1442static int perf_sched__read_events(struct perf_sched *sched, 1442static int perf_sched__read_events(struct perf_sched *sched)
1443 struct perf_session **psession)
1444{ 1443{
1445 const struct perf_evsel_str_handler handlers[] = { 1444 const struct perf_evsel_str_handler handlers[] = {
1446 { "sched:sched_switch", process_sched_switch_event, }, 1445 { "sched:sched_switch", process_sched_switch_event, },
@@ -1454,6 +1453,7 @@ static int perf_sched__read_events(struct perf_sched *sched,
1454 .path = input_name, 1453 .path = input_name,
1455 .mode = PERF_DATA_MODE_READ, 1454 .mode = PERF_DATA_MODE_READ,
1456 }; 1455 };
1456 int rc = -1;
1457 1457
1458 session = perf_session__new(&file, false, &sched->tool); 1458 session = perf_session__new(&file, false, &sched->tool);
1459 if (session == NULL) { 1459 if (session == NULL) {
@@ -1467,27 +1467,21 @@ static int perf_sched__read_events(struct perf_sched *sched,
1467 goto out_delete; 1467 goto out_delete;
1468 1468
1469 if (perf_session__has_traces(session, "record -R")) { 1469 if (perf_session__has_traces(session, "record -R")) {
1470 int err = perf_session__process_events(session, &sched->tool); 1470 int err = perf_session__process_events(session);
1471 if (err) { 1471 if (err) {
1472 pr_err("Failed to process events, error %d", err); 1472 pr_err("Failed to process events, error %d", err);
1473 goto out_delete; 1473 goto out_delete;
1474 } 1474 }
1475 1475
1476 sched->nr_events = session->stats.nr_events[0]; 1476 sched->nr_events = session->evlist->stats.nr_events[0];
1477 sched->nr_lost_events = session->stats.total_lost; 1477 sched->nr_lost_events = session->evlist->stats.total_lost;
1478 sched->nr_lost_chunks = session->stats.nr_events[PERF_RECORD_LOST]; 1478 sched->nr_lost_chunks = session->evlist->stats.nr_events[PERF_RECORD_LOST];
1479 } 1479 }
1480 1480
1481 if (psession) 1481 rc = 0;
1482 *psession = session;
1483 else
1484 perf_session__delete(session);
1485
1486 return 0;
1487
1488out_delete: 1482out_delete:
1489 perf_session__delete(session); 1483 perf_session__delete(session);
1490 return -1; 1484 return rc;
1491} 1485}
1492 1486
1493static void print_bad_events(struct perf_sched *sched) 1487static void print_bad_events(struct perf_sched *sched)
@@ -1515,12 +1509,10 @@ static void print_bad_events(struct perf_sched *sched)
1515static int perf_sched__lat(struct perf_sched *sched) 1509static int perf_sched__lat(struct perf_sched *sched)
1516{ 1510{
1517 struct rb_node *next; 1511 struct rb_node *next;
1518 struct perf_session *session;
1519 1512
1520 setup_pager(); 1513 setup_pager();
1521 1514
1522 /* save session -- references to threads are held in work_list */ 1515 if (perf_sched__read_events(sched))
1523 if (perf_sched__read_events(sched, &session))
1524 return -1; 1516 return -1;
1525 1517
1526 perf_sched__sort_lat(sched); 1518 perf_sched__sort_lat(sched);
@@ -1537,6 +1529,7 @@ static int perf_sched__lat(struct perf_sched *sched)
1537 work_list = rb_entry(next, struct work_atoms, node); 1529 work_list = rb_entry(next, struct work_atoms, node);
1538 output_lat_thread(sched, work_list); 1530 output_lat_thread(sched, work_list);
1539 next = rb_next(next); 1531 next = rb_next(next);
1532 thread__zput(work_list->thread);
1540 } 1533 }
1541 1534
1542 printf(" -----------------------------------------------------------------------------------------------------------------\n"); 1535 printf(" -----------------------------------------------------------------------------------------------------------------\n");
@@ -1548,7 +1541,6 @@ static int perf_sched__lat(struct perf_sched *sched)
1548 print_bad_events(sched); 1541 print_bad_events(sched);
1549 printf("\n"); 1542 printf("\n");
1550 1543
1551 perf_session__delete(session);
1552 return 0; 1544 return 0;
1553} 1545}
1554 1546
@@ -1557,7 +1549,7 @@ static int perf_sched__map(struct perf_sched *sched)
1557 sched->max_cpu = sysconf(_SC_NPROCESSORS_CONF); 1549 sched->max_cpu = sysconf(_SC_NPROCESSORS_CONF);
1558 1550
1559 setup_pager(); 1551 setup_pager();
1560 if (perf_sched__read_events(sched, NULL)) 1552 if (perf_sched__read_events(sched))
1561 return -1; 1553 return -1;
1562 print_bad_events(sched); 1554 print_bad_events(sched);
1563 return 0; 1555 return 0;
@@ -1572,7 +1564,7 @@ static int perf_sched__replay(struct perf_sched *sched)
1572 1564
1573 test_calibrations(sched); 1565 test_calibrations(sched);
1574 1566
1575 if (perf_sched__read_events(sched, NULL)) 1567 if (perf_sched__read_events(sched))
1576 return -1; 1568 return -1;
1577 1569
1578 printf("nr_run_events: %ld\n", sched->nr_run_events); 1570 printf("nr_run_events: %ld\n", sched->nr_run_events);
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index ce304dfd962a..662366ceb572 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -800,7 +800,7 @@ static int __cmd_script(struct perf_script *script)
800 script->tool.mmap2 = process_mmap2_event; 800 script->tool.mmap2 = process_mmap2_event;
801 } 801 }
802 802
803 ret = perf_session__process_events(script->session, &script->tool); 803 ret = perf_session__process_events(script->session);
804 804
805 if (debug_mode) 805 if (debug_mode)
806 pr_err("Misordered timestamps: %" PRIu64 "\n", nr_unordered); 806 pr_err("Misordered timestamps: %" PRIu64 "\n", nr_unordered);
@@ -1562,6 +1562,10 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1562 OPT_STRING('C', "cpu", &cpu_list, "cpu", "list of cpus to profile"), 1562 OPT_STRING('C', "cpu", &cpu_list, "cpu", "list of cpus to profile"),
1563 OPT_STRING('c', "comms", &symbol_conf.comm_list_str, "comm[,comm...]", 1563 OPT_STRING('c', "comms", &symbol_conf.comm_list_str, "comm[,comm...]",
1564 "only display events for these comms"), 1564 "only display events for these comms"),
1565 OPT_STRING(0, "pid", &symbol_conf.pid_list_str, "pid[,pid...]",
1566 "only consider symbols in these pids"),
1567 OPT_STRING(0, "tid", &symbol_conf.tid_list_str, "tid[,tid...]",
1568 "only consider symbols in these tids"),
1565 OPT_BOOLEAN('I', "show-info", &show_full_info, 1569 OPT_BOOLEAN('I', "show-info", &show_full_info,
1566 "display extended information from perf.data file"), 1570 "display extended information from perf.data file"),
1567 OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path, 1571 OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path,
@@ -1572,7 +1576,8 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1572 "Show the mmap events"), 1576 "Show the mmap events"),
1573 OPT_END() 1577 OPT_END()
1574 }; 1578 };
1575 const char * const script_usage[] = { 1579 const char * const script_subcommands[] = { "record", "report", NULL };
1580 const char *script_usage[] = {
1576 "perf script [<options>]", 1581 "perf script [<options>]",
1577 "perf script [<options>] record <script> [<record-options>] <command>", 1582 "perf script [<options>] record <script> [<record-options>] <command>",
1578 "perf script [<options>] report <script> [script-args]", 1583 "perf script [<options>] report <script> [script-args]",
@@ -1586,7 +1591,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1586 1591
1587 setup_scripting(); 1592 setup_scripting();
1588 1593
1589 argc = parse_options(argc, argv, options, script_usage, 1594 argc = parse_options_subcommand(argc, argv, options, script_subcommands, script_usage,
1590 PARSE_OPT_STOP_AT_NON_OPTION); 1595 PARSE_OPT_STOP_AT_NON_OPTION);
1591 1596
1592 file.path = input_name; 1597 file.path = input_name;
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index e598e4e98170..f7b8218785f6 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -353,39 +353,40 @@ static struct perf_evsel *nth_evsel(int n)
353 * more semantic information such as miss/hit ratios, 353 * more semantic information such as miss/hit ratios,
354 * instruction rates, etc: 354 * instruction rates, etc:
355 */ 355 */
356static void update_shadow_stats(struct perf_evsel *counter, u64 *count) 356static void update_shadow_stats(struct perf_evsel *counter, u64 *count,
357 int cpu)
357{ 358{
358 if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK)) 359 if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK))
359 update_stats(&runtime_nsecs_stats[0], count[0]); 360 update_stats(&runtime_nsecs_stats[cpu], count[0]);
360 else if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES)) 361 else if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES))
361 update_stats(&runtime_cycles_stats[0], count[0]); 362 update_stats(&runtime_cycles_stats[cpu], count[0]);
362 else if (transaction_run && 363 else if (transaction_run &&
363 perf_evsel__cmp(counter, nth_evsel(T_CYCLES_IN_TX))) 364 perf_evsel__cmp(counter, nth_evsel(T_CYCLES_IN_TX)))
364 update_stats(&runtime_cycles_in_tx_stats[0], count[0]); 365 update_stats(&runtime_cycles_in_tx_stats[cpu], count[0]);
365 else if (transaction_run && 366 else if (transaction_run &&
366 perf_evsel__cmp(counter, nth_evsel(T_TRANSACTION_START))) 367 perf_evsel__cmp(counter, nth_evsel(T_TRANSACTION_START)))
367 update_stats(&runtime_transaction_stats[0], count[0]); 368 update_stats(&runtime_transaction_stats[cpu], count[0]);
368 else if (transaction_run && 369 else if (transaction_run &&
369 perf_evsel__cmp(counter, nth_evsel(T_ELISION_START))) 370 perf_evsel__cmp(counter, nth_evsel(T_ELISION_START)))
370 update_stats(&runtime_elision_stats[0], count[0]); 371 update_stats(&runtime_elision_stats[cpu], count[0]);
371 else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_FRONTEND)) 372 else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_FRONTEND))
372 update_stats(&runtime_stalled_cycles_front_stats[0], count[0]); 373 update_stats(&runtime_stalled_cycles_front_stats[cpu], count[0]);
373 else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_BACKEND)) 374 else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_BACKEND))
374 update_stats(&runtime_stalled_cycles_back_stats[0], count[0]); 375 update_stats(&runtime_stalled_cycles_back_stats[cpu], count[0]);
375 else if (perf_evsel__match(counter, HARDWARE, HW_BRANCH_INSTRUCTIONS)) 376 else if (perf_evsel__match(counter, HARDWARE, HW_BRANCH_INSTRUCTIONS))
376 update_stats(&runtime_branches_stats[0], count[0]); 377 update_stats(&runtime_branches_stats[cpu], count[0]);
377 else if (perf_evsel__match(counter, HARDWARE, HW_CACHE_REFERENCES)) 378 else if (perf_evsel__match(counter, HARDWARE, HW_CACHE_REFERENCES))
378 update_stats(&runtime_cacherefs_stats[0], count[0]); 379 update_stats(&runtime_cacherefs_stats[cpu], count[0]);
379 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_L1D)) 380 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_L1D))
380 update_stats(&runtime_l1_dcache_stats[0], count[0]); 381 update_stats(&runtime_l1_dcache_stats[cpu], count[0]);
381 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_L1I)) 382 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_L1I))
382 update_stats(&runtime_l1_icache_stats[0], count[0]); 383 update_stats(&runtime_l1_icache_stats[cpu], count[0]);
383 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_LL)) 384 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_LL))
384 update_stats(&runtime_ll_cache_stats[0], count[0]); 385 update_stats(&runtime_ll_cache_stats[cpu], count[0]);
385 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_DTLB)) 386 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_DTLB))
386 update_stats(&runtime_dtlb_cache_stats[0], count[0]); 387 update_stats(&runtime_dtlb_cache_stats[cpu], count[0]);
387 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_ITLB)) 388 else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_ITLB))
388 update_stats(&runtime_itlb_cache_stats[0], count[0]); 389 update_stats(&runtime_itlb_cache_stats[cpu], count[0]);
389} 390}
390 391
391static void zero_per_pkg(struct perf_evsel *counter) 392static void zero_per_pkg(struct perf_evsel *counter)
@@ -447,7 +448,8 @@ static int read_cb(struct perf_evsel *evsel, int cpu, int thread __maybe_unused,
447 perf_evsel__compute_deltas(evsel, cpu, count); 448 perf_evsel__compute_deltas(evsel, cpu, count);
448 perf_counts_values__scale(count, scale, NULL); 449 perf_counts_values__scale(count, scale, NULL);
449 evsel->counts->cpu[cpu] = *count; 450 evsel->counts->cpu[cpu] = *count;
450 update_shadow_stats(evsel, count->values); 451 if (aggr_mode == AGGR_NONE)
452 update_shadow_stats(evsel, count->values, cpu);
451 break; 453 break;
452 case AGGR_GLOBAL: 454 case AGGR_GLOBAL:
453 aggr->val += count->val; 455 aggr->val += count->val;
@@ -495,7 +497,7 @@ static int read_counter_aggr(struct perf_evsel *counter)
495 /* 497 /*
496 * Save the full runtime - to allow normalization during printout: 498 * Save the full runtime - to allow normalization during printout:
497 */ 499 */
498 update_shadow_stats(counter, count); 500 update_shadow_stats(counter, count, 0);
499 501
500 return 0; 502 return 0;
501} 503}
@@ -510,6 +512,9 @@ static int read_counter(struct perf_evsel *counter)
510 int ncpus = perf_evsel__nr_cpus(counter); 512 int ncpus = perf_evsel__nr_cpus(counter);
511 int cpu, thread; 513 int cpu, thread;
512 514
515 if (!counter->supported)
516 return -ENOENT;
517
513 if (counter->system_wide) 518 if (counter->system_wide)
514 nthreads = 1; 519 nthreads = 1;
515 520
@@ -679,8 +684,9 @@ static int __run_perf_stat(int argc, const char **argv)
679 unit_width = l; 684 unit_width = l;
680 } 685 }
681 686
682 if (perf_evlist__apply_filters(evsel_list)) { 687 if (perf_evlist__apply_filters(evsel_list, &counter)) {
683 error("failed to set filter with %d (%s)\n", errno, 688 error("failed to set filter \"%s\" on event %s with %d (%s)\n",
689 counter->filter, perf_evsel__name(counter), errno,
684 strerror_r(errno, msg, sizeof(msg))); 690 strerror_r(errno, msg, sizeof(msg)));
685 return -1; 691 return -1;
686 } 692 }
@@ -766,6 +772,19 @@ static int run_perf_stat(int argc, const char **argv)
766 return ret; 772 return ret;
767} 773}
768 774
775static void print_running(u64 run, u64 ena)
776{
777 if (csv_output) {
778 fprintf(output, "%s%" PRIu64 "%s%.2f",
779 csv_sep,
780 run,
781 csv_sep,
782 ena ? 100.0 * run / ena : 100.0);
783 } else if (run != ena) {
784 fprintf(output, " (%.2f%%)", 100.0 * run / ena);
785 }
786}
787
769static void print_noise_pct(double total, double avg) 788static void print_noise_pct(double total, double avg)
770{ 789{
771 double pct = rel_stddev_stats(total, avg); 790 double pct = rel_stddev_stats(total, avg);
@@ -1076,6 +1095,8 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
1076 if (total) { 1095 if (total) {
1077 ratio = avg / total; 1096 ratio = avg / total;
1078 fprintf(output, " # %5.2f insns per cycle ", ratio); 1097 fprintf(output, " # %5.2f insns per cycle ", ratio);
1098 } else {
1099 fprintf(output, " ");
1079 } 1100 }
1080 total = avg_stats(&runtime_stalled_cycles_front_stats[cpu]); 1101 total = avg_stats(&runtime_stalled_cycles_front_stats[cpu]);
1081 total = max(total, avg_stats(&runtime_stalled_cycles_back_stats[cpu])); 1102 total = max(total, avg_stats(&runtime_stalled_cycles_back_stats[cpu]));
@@ -1145,6 +1166,8 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
1145 if (total) { 1166 if (total) {
1146 ratio = avg / total; 1167 ratio = avg / total;
1147 fprintf(output, " # %8.3f GHz ", ratio); 1168 fprintf(output, " # %8.3f GHz ", ratio);
1169 } else {
1170 fprintf(output, " ");
1148 } 1171 }
1149 } else if (transaction_run && 1172 } else if (transaction_run &&
1150 perf_evsel__cmp(evsel, nth_evsel(T_CYCLES_IN_TX))) { 1173 perf_evsel__cmp(evsel, nth_evsel(T_CYCLES_IN_TX))) {
@@ -1249,6 +1272,7 @@ static void print_aggr(char *prefix)
1249 fprintf(output, "%s%s", 1272 fprintf(output, "%s%s",
1250 csv_sep, counter->cgrp->name); 1273 csv_sep, counter->cgrp->name);
1251 1274
1275 print_running(run, ena);
1252 fputc('\n', output); 1276 fputc('\n', output);
1253 continue; 1277 continue;
1254 } 1278 }
@@ -1259,13 +1283,10 @@ static void print_aggr(char *prefix)
1259 else 1283 else
1260 abs_printout(id, nr, counter, uval); 1284 abs_printout(id, nr, counter, uval);
1261 1285
1262 if (!csv_output) { 1286 if (!csv_output)
1263 print_noise(counter, 1.0); 1287 print_noise(counter, 1.0);
1264 1288
1265 if (run != ena) 1289 print_running(run, ena);
1266 fprintf(output, " (%.2f%%)",
1267 100.0 * run / ena);
1268 }
1269 fputc('\n', output); 1290 fputc('\n', output);
1270 } 1291 }
1271 } 1292 }
@@ -1281,11 +1302,15 @@ static void print_counter_aggr(struct perf_evsel *counter, char *prefix)
1281 double avg = avg_stats(&ps->res_stats[0]); 1302 double avg = avg_stats(&ps->res_stats[0]);
1282 int scaled = counter->counts->scaled; 1303 int scaled = counter->counts->scaled;
1283 double uval; 1304 double uval;
1305 double avg_enabled, avg_running;
1306
1307 avg_enabled = avg_stats(&ps->res_stats[1]);
1308 avg_running = avg_stats(&ps->res_stats[2]);
1284 1309
1285 if (prefix) 1310 if (prefix)
1286 fprintf(output, "%s", prefix); 1311 fprintf(output, "%s", prefix);
1287 1312
1288 if (scaled == -1) { 1313 if (scaled == -1 || !counter->supported) {
1289 fprintf(output, "%*s%s", 1314 fprintf(output, "%*s%s",
1290 csv_output ? 0 : 18, 1315 csv_output ? 0 : 18,
1291 counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED, 1316 counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
@@ -1300,6 +1325,7 @@ static void print_counter_aggr(struct perf_evsel *counter, char *prefix)
1300 if (counter->cgrp) 1325 if (counter->cgrp)
1301 fprintf(output, "%s%s", csv_sep, counter->cgrp->name); 1326 fprintf(output, "%s%s", csv_sep, counter->cgrp->name);
1302 1327
1328 print_running(avg_running, avg_enabled);
1303 fputc('\n', output); 1329 fputc('\n', output);
1304 return; 1330 return;
1305 } 1331 }
@@ -1313,19 +1339,7 @@ static void print_counter_aggr(struct perf_evsel *counter, char *prefix)
1313 1339
1314 print_noise(counter, avg); 1340 print_noise(counter, avg);
1315 1341
1316 if (csv_output) { 1342 print_running(avg_running, avg_enabled);
1317 fputc('\n', output);
1318 return;
1319 }
1320
1321 if (scaled) {
1322 double avg_enabled, avg_running;
1323
1324 avg_enabled = avg_stats(&ps->res_stats[1]);
1325 avg_running = avg_stats(&ps->res_stats[2]);
1326
1327 fprintf(output, " [%5.2f%%]", 100 * avg_running / avg_enabled);
1328 }
1329 fprintf(output, "\n"); 1343 fprintf(output, "\n");
1330} 1344}
1331 1345
@@ -1367,6 +1381,7 @@ static void print_counter(struct perf_evsel *counter, char *prefix)
1367 fprintf(output, "%s%s", 1381 fprintf(output, "%s%s",
1368 csv_sep, counter->cgrp->name); 1382 csv_sep, counter->cgrp->name);
1369 1383
1384 print_running(run, ena);
1370 fputc('\n', output); 1385 fputc('\n', output);
1371 continue; 1386 continue;
1372 } 1387 }
@@ -1378,13 +1393,10 @@ static void print_counter(struct perf_evsel *counter, char *prefix)
1378 else 1393 else
1379 abs_printout(cpu, 0, counter, uval); 1394 abs_printout(cpu, 0, counter, uval);
1380 1395
1381 if (!csv_output) { 1396 if (!csv_output)
1382 print_noise(counter, 1.0); 1397 print_noise(counter, 1.0);
1398 print_running(run, ena);
1383 1399
1384 if (run != ena)
1385 fprintf(output, " (%.2f%%)",
1386 100.0 * run / ena);
1387 }
1388 fputc('\n', output); 1400 fputc('\n', output);
1389 } 1401 }
1390} 1402}
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index f3bb1a4bf060..494b3bbe5ea4 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -1623,7 +1623,7 @@ static int __cmd_timechart(struct timechart *tchart, const char *output_name)
1623 goto out_delete; 1623 goto out_delete;
1624 } 1624 }
1625 1625
1626 ret = perf_session__process_events(session, &tchart->tool); 1626 ret = perf_session__process_events(session);
1627 if (ret) 1627 if (ret)
1628 goto out_delete; 1628 goto out_delete;
1629 1629
@@ -1958,7 +1958,8 @@ int cmd_timechart(int argc, const char **argv,
1958 parse_time), 1958 parse_time),
1959 OPT_END() 1959 OPT_END()
1960 }; 1960 };
1961 const char * const timechart_usage[] = { 1961 const char * const timechart_subcommands[] = { "record", NULL };
1962 const char *timechart_usage[] = {
1962 "perf timechart [<options>] {record}", 1963 "perf timechart [<options>] {record}",
1963 NULL 1964 NULL
1964 }; 1965 };
@@ -1976,8 +1977,8 @@ int cmd_timechart(int argc, const char **argv,
1976 "perf timechart record [<options>]", 1977 "perf timechart record [<options>]",
1977 NULL 1978 NULL
1978 }; 1979 };
1979 argc = parse_options(argc, argv, timechart_options, timechart_usage, 1980 argc = parse_options_subcommand(argc, argv, timechart_options, timechart_subcommands,
1980 PARSE_OPT_STOP_AT_NON_OPTION); 1981 timechart_usage, PARSE_OPT_STOP_AT_NON_OPTION);
1981 1982
1982 if (tchart.power_only && tchart.tasks_only) { 1983 if (tchart.power_only && tchart.tasks_only) {
1983 pr_err("-P and -T options cannot be used at the same time.\n"); 1984 pr_err("-P and -T options cannot be used at the same time.\n");
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index c4c7eac69de4..1cb3436276d1 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -716,7 +716,7 @@ static void perf_event__process_sample(struct perf_tool *tool,
716 716
717 if (!machine) { 717 if (!machine) {
718 pr_err("%u unprocessable samples recorded.\r", 718 pr_err("%u unprocessable samples recorded.\r",
719 top->session->stats.nr_unprocessable_samples++); 719 top->session->evlist->stats.nr_unprocessable_samples++);
720 return; 720 return;
721 } 721 }
722 722
@@ -757,8 +757,10 @@ static void perf_event__process_sample(struct perf_tool *tool,
757 al.map == machine->vmlinux_maps[MAP__FUNCTION] && 757 al.map == machine->vmlinux_maps[MAP__FUNCTION] &&
758 RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION])) { 758 RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION])) {
759 if (symbol_conf.vmlinux_name) { 759 if (symbol_conf.vmlinux_name) {
760 ui__warning("The %s file can't be used.\n%s", 760 char serr[256];
761 symbol_conf.vmlinux_name, msg); 761 dso__strerror_load(al.map->dso, serr, sizeof(serr));
762 ui__warning("The %s file can't be used: %s\n%s",
763 symbol_conf.vmlinux_name, serr, msg);
762 } else { 764 } else {
763 ui__warning("A vmlinux file was not found.\n%s", 765 ui__warning("A vmlinux file was not found.\n%s",
764 msg); 766 msg);
@@ -856,7 +858,7 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
856 hists__inc_nr_events(evsel__hists(evsel), event->header.type); 858 hists__inc_nr_events(evsel__hists(evsel), event->header.type);
857 machine__process_event(machine, event, &sample); 859 machine__process_event(machine, event, &sample);
858 } else 860 } else
859 ++session->stats.nr_unknown_events; 861 ++session->evlist->stats.nr_unknown_events;
860next_event: 862next_event:
861 perf_evlist__mmap_consume(top->evlist, idx); 863 perf_evlist__mmap_consume(top->evlist, idx);
862 } 864 }
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 7e935f1083ec..bcc98ce3e5b8 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -52,7 +52,9 @@ struct tp_field {
52#define TP_UINT_FIELD(bits) \ 52#define TP_UINT_FIELD(bits) \
53static u64 tp_field__u##bits(struct tp_field *field, struct perf_sample *sample) \ 53static u64 tp_field__u##bits(struct tp_field *field, struct perf_sample *sample) \
54{ \ 54{ \
55 return *(u##bits *)(sample->raw_data + field->offset); \ 55 u##bits value; \
56 memcpy(&value, sample->raw_data + field->offset, sizeof(value)); \
57 return value; \
56} 58}
57 59
58TP_UINT_FIELD(8); 60TP_UINT_FIELD(8);
@@ -63,7 +65,8 @@ TP_UINT_FIELD(64);
63#define TP_UINT_FIELD__SWAPPED(bits) \ 65#define TP_UINT_FIELD__SWAPPED(bits) \
64static u64 tp_field__swapped_u##bits(struct tp_field *field, struct perf_sample *sample) \ 66static u64 tp_field__swapped_u##bits(struct tp_field *field, struct perf_sample *sample) \
65{ \ 67{ \
66 u##bits value = *(u##bits *)(sample->raw_data + field->offset); \ 68 u##bits value; \
69 memcpy(&value, sample->raw_data + field->offset, sizeof(value)); \
67 return bswap_##bits(value);\ 70 return bswap_##bits(value);\
68} 71}
69 72
@@ -1132,6 +1135,8 @@ static struct syscall_fmt *syscall_fmt__find(const char *name)
1132 1135
1133struct syscall { 1136struct syscall {
1134 struct event_format *tp_format; 1137 struct event_format *tp_format;
1138 int nr_args;
1139 struct format_field *args;
1135 const char *name; 1140 const char *name;
1136 bool filtered; 1141 bool filtered;
1137 bool is_exit; 1142 bool is_exit;
@@ -1219,7 +1224,9 @@ struct trace {
1219 struct syscall *table; 1224 struct syscall *table;
1220 } syscalls; 1225 } syscalls;
1221 struct record_opts opts; 1226 struct record_opts opts;
1227 struct perf_evlist *evlist;
1222 struct machine *host; 1228 struct machine *host;
1229 struct thread *current;
1223 u64 base_time; 1230 u64 base_time;
1224 FILE *output; 1231 FILE *output;
1225 unsigned long nr_events; 1232 unsigned long nr_events;
@@ -1227,6 +1234,10 @@ struct trace {
1227 const char *last_vfs_getname; 1234 const char *last_vfs_getname;
1228 struct intlist *tid_list; 1235 struct intlist *tid_list;
1229 struct intlist *pid_list; 1236 struct intlist *pid_list;
1237 struct {
1238 size_t nr;
1239 pid_t *entries;
1240 } filter_pids;
1230 double duration_filter; 1241 double duration_filter;
1231 double runtime_ms; 1242 double runtime_ms;
1232 struct { 1243 struct {
@@ -1433,14 +1444,14 @@ static int syscall__set_arg_fmts(struct syscall *sc)
1433 struct format_field *field; 1444 struct format_field *field;
1434 int idx = 0; 1445 int idx = 0;
1435 1446
1436 sc->arg_scnprintf = calloc(sc->tp_format->format.nr_fields - 1, sizeof(void *)); 1447 sc->arg_scnprintf = calloc(sc->nr_args, sizeof(void *));
1437 if (sc->arg_scnprintf == NULL) 1448 if (sc->arg_scnprintf == NULL)
1438 return -1; 1449 return -1;
1439 1450
1440 if (sc->fmt) 1451 if (sc->fmt)
1441 sc->arg_parm = sc->fmt->arg_parm; 1452 sc->arg_parm = sc->fmt->arg_parm;
1442 1453
1443 for (field = sc->tp_format->format.fields->next; field; field = field->next) { 1454 for (field = sc->args; field; field = field->next) {
1444 if (sc->fmt && sc->fmt->arg_scnprintf[idx]) 1455 if (sc->fmt && sc->fmt->arg_scnprintf[idx])
1445 sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx]; 1456 sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx];
1446 else if (field->flags & FIELD_IS_POINTER) 1457 else if (field->flags & FIELD_IS_POINTER)
@@ -1506,18 +1517,37 @@ static int trace__read_syscall_info(struct trace *trace, int id)
1506 if (sc->tp_format == NULL) 1517 if (sc->tp_format == NULL)
1507 return -1; 1518 return -1;
1508 1519
1520 sc->args = sc->tp_format->format.fields;
1521 sc->nr_args = sc->tp_format->format.nr_fields;
1522 /* drop nr field - not relevant here; does not exist on older kernels */
1523 if (sc->args && strcmp(sc->args->name, "nr") == 0) {
1524 sc->args = sc->args->next;
1525 --sc->nr_args;
1526 }
1527
1509 sc->is_exit = !strcmp(name, "exit_group") || !strcmp(name, "exit"); 1528 sc->is_exit = !strcmp(name, "exit_group") || !strcmp(name, "exit");
1510 1529
1511 return syscall__set_arg_fmts(sc); 1530 return syscall__set_arg_fmts(sc);
1512} 1531}
1513 1532
1533/*
1534 * args is to be interpreted as a series of longs but we need to handle
1535 * 8-byte unaligned accesses. args points to raw_data within the event
1536 * and raw_data is guaranteed to be 8-byte unaligned because it is
1537 * preceded by raw_size which is a u32. So we need to copy args to a temp
1538 * variable to read it. Most notably this avoids extended load instructions
1539 * on unaligned addresses
1540 */
1541
1514static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size, 1542static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
1515 unsigned long *args, struct trace *trace, 1543 unsigned char *args, struct trace *trace,
1516 struct thread *thread) 1544 struct thread *thread)
1517{ 1545{
1518 size_t printed = 0; 1546 size_t printed = 0;
1547 unsigned char *p;
1548 unsigned long val;
1519 1549
1520 if (sc->tp_format != NULL) { 1550 if (sc->args != NULL) {
1521 struct format_field *field; 1551 struct format_field *field;
1522 u8 bit = 1; 1552 u8 bit = 1;
1523 struct syscall_arg arg = { 1553 struct syscall_arg arg = {
@@ -1527,16 +1557,21 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
1527 .thread = thread, 1557 .thread = thread,
1528 }; 1558 };
1529 1559
1530 for (field = sc->tp_format->format.fields->next; field; 1560 for (field = sc->args; field;
1531 field = field->next, ++arg.idx, bit <<= 1) { 1561 field = field->next, ++arg.idx, bit <<= 1) {
1532 if (arg.mask & bit) 1562 if (arg.mask & bit)
1533 continue; 1563 continue;
1564
1565 /* special care for unaligned accesses */
1566 p = args + sizeof(unsigned long) * arg.idx;
1567 memcpy(&val, p, sizeof(val));
1568
1534 /* 1569 /*
1535 * Suppress this argument if its value is zero and 1570 * Suppress this argument if its value is zero and
1536 * and we don't have a string associated in an 1571 * and we don't have a string associated in an
1537 * strarray for it. 1572 * strarray for it.
1538 */ 1573 */
1539 if (args[arg.idx] == 0 && 1574 if (val == 0 &&
1540 !(sc->arg_scnprintf && 1575 !(sc->arg_scnprintf &&
1541 sc->arg_scnprintf[arg.idx] == SCA_STRARRAY && 1576 sc->arg_scnprintf[arg.idx] == SCA_STRARRAY &&
1542 sc->arg_parm[arg.idx])) 1577 sc->arg_parm[arg.idx]))
@@ -1545,23 +1580,26 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
1545 printed += scnprintf(bf + printed, size - printed, 1580 printed += scnprintf(bf + printed, size - printed,
1546 "%s%s: ", printed ? ", " : "", field->name); 1581 "%s%s: ", printed ? ", " : "", field->name);
1547 if (sc->arg_scnprintf && sc->arg_scnprintf[arg.idx]) { 1582 if (sc->arg_scnprintf && sc->arg_scnprintf[arg.idx]) {
1548 arg.val = args[arg.idx]; 1583 arg.val = val;
1549 if (sc->arg_parm) 1584 if (sc->arg_parm)
1550 arg.parm = sc->arg_parm[arg.idx]; 1585 arg.parm = sc->arg_parm[arg.idx];
1551 printed += sc->arg_scnprintf[arg.idx](bf + printed, 1586 printed += sc->arg_scnprintf[arg.idx](bf + printed,
1552 size - printed, &arg); 1587 size - printed, &arg);
1553 } else { 1588 } else {
1554 printed += scnprintf(bf + printed, size - printed, 1589 printed += scnprintf(bf + printed, size - printed,
1555 "%ld", args[arg.idx]); 1590 "%ld", val);
1556 } 1591 }
1557 } 1592 }
1558 } else { 1593 } else {
1559 int i = 0; 1594 int i = 0;
1560 1595
1561 while (i < 6) { 1596 while (i < 6) {
1597 /* special care for unaligned accesses */
1598 p = args + sizeof(unsigned long) * i;
1599 memcpy(&val, p, sizeof(val));
1562 printed += scnprintf(bf + printed, size - printed, 1600 printed += scnprintf(bf + printed, size - printed,
1563 "%sarg%d: %ld", 1601 "%sarg%d: %ld",
1564 printed ? ", " : "", i, args[i]); 1602 printed ? ", " : "", i, val);
1565 ++i; 1603 ++i;
1566 } 1604 }
1567 } 1605 }
@@ -1642,6 +1680,29 @@ static void thread__update_stats(struct thread_trace *ttrace,
1642 update_stats(stats, duration); 1680 update_stats(stats, duration);
1643} 1681}
1644 1682
1683static int trace__printf_interrupted_entry(struct trace *trace, struct perf_sample *sample)
1684{
1685 struct thread_trace *ttrace;
1686 u64 duration;
1687 size_t printed;
1688
1689 if (trace->current == NULL)
1690 return 0;
1691
1692 ttrace = thread__priv(trace->current);
1693
1694 if (!ttrace->entry_pending)
1695 return 0;
1696
1697 duration = sample->time - ttrace->entry_time;
1698
1699 printed = trace__fprintf_entry_head(trace, trace->current, duration, sample->time, trace->output);
1700 printed += fprintf(trace->output, "%-70s) ...\n", ttrace->entry_str);
1701 ttrace->entry_pending = false;
1702
1703 return printed;
1704}
1705
1645static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel, 1706static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
1646 union perf_event *event __maybe_unused, 1707 union perf_event *event __maybe_unused,
1647 struct perf_sample *sample) 1708 struct perf_sample *sample)
@@ -1673,6 +1734,9 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
1673 return -1; 1734 return -1;
1674 } 1735 }
1675 1736
1737 if (!trace->summary_only)
1738 trace__printf_interrupted_entry(trace, sample);
1739
1676 ttrace->entry_time = sample->time; 1740 ttrace->entry_time = sample->time;
1677 msg = ttrace->entry_str; 1741 msg = ttrace->entry_str;
1678 printed += scnprintf(msg + printed, 1024 - printed, "%s(", sc->name); 1742 printed += scnprintf(msg + printed, 1024 - printed, "%s(", sc->name);
@@ -1688,6 +1752,11 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
1688 } else 1752 } else
1689 ttrace->entry_pending = true; 1753 ttrace->entry_pending = true;
1690 1754
1755 if (trace->current != thread) {
1756 thread__put(trace->current);
1757 trace->current = thread__get(thread);
1758 }
1759
1691 return 0; 1760 return 0;
1692} 1761}
1693 1762
@@ -1805,6 +1874,28 @@ out_dump:
1805 return 0; 1874 return 0;
1806} 1875}
1807 1876
1877static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
1878 union perf_event *event __maybe_unused,
1879 struct perf_sample *sample)
1880{
1881 trace__printf_interrupted_entry(trace, sample);
1882 trace__fprintf_tstamp(trace, sample->time, trace->output);
1883
1884 if (trace->trace_syscalls)
1885 fprintf(trace->output, "( ): ");
1886
1887 fprintf(trace->output, "%s:", evsel->name);
1888
1889 if (evsel->tp_format) {
1890 event_format__fprintf(evsel->tp_format, sample->cpu,
1891 sample->raw_data, sample->raw_size,
1892 trace->output);
1893 }
1894
1895 fprintf(trace->output, ")\n");
1896 return 0;
1897}
1898
1808static void print_location(FILE *f, struct perf_sample *sample, 1899static void print_location(FILE *f, struct perf_sample *sample,
1809 struct addr_location *al, 1900 struct addr_location *al,
1810 bool print_dso, bool print_sym) 1901 bool print_dso, bool print_sym)
@@ -2037,10 +2128,39 @@ static int perf_evlist__add_pgfault(struct perf_evlist *evlist,
2037 return 0; 2128 return 0;
2038} 2129}
2039 2130
2040static int trace__run(struct trace *trace, int argc, const char **argv) 2131static void trace__handle_event(struct trace *trace, union perf_event *event, struct perf_sample *sample)
2041{ 2132{
2042 struct perf_evlist *evlist = perf_evlist__new(); 2133 const u32 type = event->header.type;
2043 struct perf_evsel *evsel; 2134 struct perf_evsel *evsel;
2135
2136 if (!trace->full_time && trace->base_time == 0)
2137 trace->base_time = sample->time;
2138
2139 if (type != PERF_RECORD_SAMPLE) {
2140 trace__process_event(trace, trace->host, event, sample);
2141 return;
2142 }
2143
2144 evsel = perf_evlist__id2evsel(trace->evlist, sample->id);
2145 if (evsel == NULL) {
2146 fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...\n", sample->id);
2147 return;
2148 }
2149
2150 if (evsel->attr.type == PERF_TYPE_TRACEPOINT &&
2151 sample->raw_data == NULL) {
2152 fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
2153 perf_evsel__name(evsel), sample->tid,
2154 sample->cpu, sample->raw_size);
2155 } else {
2156 tracepoint_handler handler = evsel->handler;
2157 handler(trace, evsel, event, sample);
2158 }
2159}
2160
2161static int trace__run(struct trace *trace, int argc, const char **argv)
2162{
2163 struct perf_evlist *evlist = trace->evlist;
2044 int err = -1, i; 2164 int err = -1, i;
2045 unsigned long before; 2165 unsigned long before;
2046 const bool forks = argc > 0; 2166 const bool forks = argc > 0;
@@ -2048,11 +2168,6 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
2048 2168
2049 trace->live = true; 2169 trace->live = true;
2050 2170
2051 if (evlist == NULL) {
2052 fprintf(trace->output, "Not enough memory to run!\n");
2053 goto out;
2054 }
2055
2056 if (trace->trace_syscalls && 2171 if (trace->trace_syscalls &&
2057 perf_evlist__add_syscall_newtp(evlist, trace__sys_enter, 2172 perf_evlist__add_syscall_newtp(evlist, trace__sys_enter,
2058 trace__sys_exit)) 2173 trace__sys_exit))
@@ -2105,16 +2220,34 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
2105 if (err < 0) 2220 if (err < 0)
2106 goto out_error_open; 2221 goto out_error_open;
2107 2222
2223 /*
2224 * Better not use !target__has_task() here because we need to cover the
2225 * case where no threads were specified in the command line, but a
2226 * workload was, and in that case we will fill in the thread_map when
2227 * we fork the workload in perf_evlist__prepare_workload.
2228 */
2229 if (trace->filter_pids.nr > 0)
2230 err = perf_evlist__set_filter_pids(evlist, trace->filter_pids.nr, trace->filter_pids.entries);
2231 else if (evlist->threads->map[0] == -1)
2232 err = perf_evlist__set_filter_pid(evlist, getpid());
2233
2234 if (err < 0) {
2235 printf("err=%d,%s\n", -err, strerror(-err));
2236 exit(1);
2237 }
2238
2108 err = perf_evlist__mmap(evlist, trace->opts.mmap_pages, false); 2239 err = perf_evlist__mmap(evlist, trace->opts.mmap_pages, false);
2109 if (err < 0) 2240 if (err < 0)
2110 goto out_error_mmap; 2241 goto out_error_mmap;
2111 2242
2112 perf_evlist__enable(evlist);
2113
2114 if (forks) 2243 if (forks)
2115 perf_evlist__start_workload(evlist); 2244 perf_evlist__start_workload(evlist);
2245 else
2246 perf_evlist__enable(evlist);
2116 2247
2117 trace->multiple_threads = evlist->threads->map[0] == -1 || evlist->threads->nr > 1; 2248 trace->multiple_threads = evlist->threads->map[0] == -1 ||
2249 evlist->threads->nr > 1 ||
2250 perf_evlist__first(evlist)->attr.inherit;
2118again: 2251again:
2119 before = trace->nr_events; 2252 before = trace->nr_events;
2120 2253
@@ -2122,8 +2255,6 @@ again:
2122 union perf_event *event; 2255 union perf_event *event;
2123 2256
2124 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { 2257 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
2125 const u32 type = event->header.type;
2126 tracepoint_handler handler;
2127 struct perf_sample sample; 2258 struct perf_sample sample;
2128 2259
2129 ++trace->nr_events; 2260 ++trace->nr_events;
@@ -2134,30 +2265,7 @@ again:
2134 goto next_event; 2265 goto next_event;
2135 } 2266 }
2136 2267
2137 if (!trace->full_time && trace->base_time == 0) 2268 trace__handle_event(trace, event, &sample);
2138 trace->base_time = sample.time;
2139
2140 if (type != PERF_RECORD_SAMPLE) {
2141 trace__process_event(trace, trace->host, event, &sample);
2142 continue;
2143 }
2144
2145 evsel = perf_evlist__id2evsel(evlist, sample.id);
2146 if (evsel == NULL) {
2147 fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...\n", sample.id);
2148 goto next_event;
2149 }
2150
2151 if (evsel->attr.type == PERF_TYPE_TRACEPOINT &&
2152 sample.raw_data == NULL) {
2153 fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
2154 perf_evsel__name(evsel), sample.tid,
2155 sample.cpu, sample.raw_size);
2156 goto next_event;
2157 }
2158
2159 handler = evsel->handler;
2160 handler(trace, evsel, event, &sample);
2161next_event: 2269next_event:
2162 perf_evlist__mmap_consume(evlist, i); 2270 perf_evlist__mmap_consume(evlist, i);
2163 2271
@@ -2180,6 +2288,8 @@ next_event:
2180 } 2288 }
2181 2289
2182out_disable: 2290out_disable:
2291 thread__zput(trace->current);
2292
2183 perf_evlist__disable(evlist); 2293 perf_evlist__disable(evlist);
2184 2294
2185 if (!err) { 2295 if (!err) {
@@ -2197,7 +2307,7 @@ out_disable:
2197 2307
2198out_delete_evlist: 2308out_delete_evlist:
2199 perf_evlist__delete(evlist); 2309 perf_evlist__delete(evlist);
2200out: 2310 trace->evlist = NULL;
2201 trace->live = false; 2311 trace->live = false;
2202 return err; 2312 return err;
2203{ 2313{
@@ -2309,7 +2419,7 @@ static int trace__replay(struct trace *trace)
2309 2419
2310 setup_pager(); 2420 setup_pager();
2311 2421
2312 err = perf_session__process_events(session, &trace->tool); 2422 err = perf_session__process_events(session);
2313 if (err) 2423 if (err)
2314 pr_err("Failed to process events, error %d", err); 2424 pr_err("Failed to process events, error %d", err);
2315 2425
@@ -2434,6 +2544,38 @@ static int trace__set_duration(const struct option *opt, const char *str,
2434 return 0; 2544 return 0;
2435} 2545}
2436 2546
2547static int trace__set_filter_pids(const struct option *opt, const char *str,
2548 int unset __maybe_unused)
2549{
2550 int ret = -1;
2551 size_t i;
2552 struct trace *trace = opt->value;
2553 /*
2554 * FIXME: introduce a intarray class, plain parse csv and create a
2555 * { int nr, int entries[] } struct...
2556 */
2557 struct intlist *list = intlist__new(str);
2558
2559 if (list == NULL)
2560 return -1;
2561
2562 i = trace->filter_pids.nr = intlist__nr_entries(list) + 1;
2563 trace->filter_pids.entries = calloc(i, sizeof(pid_t));
2564
2565 if (trace->filter_pids.entries == NULL)
2566 goto out;
2567
2568 trace->filter_pids.entries[0] = getpid();
2569
2570 for (i = 1; i < trace->filter_pids.nr; ++i)
2571 trace->filter_pids.entries[i] = intlist__entry(list, i - 1)->i;
2572
2573 intlist__delete(list);
2574 ret = 0;
2575out:
2576 return ret;
2577}
2578
2437static int trace__open_output(struct trace *trace, const char *filename) 2579static int trace__open_output(struct trace *trace, const char *filename)
2438{ 2580{
2439 struct stat st; 2581 struct stat st;
@@ -2468,9 +2610,17 @@ static int parse_pagefaults(const struct option *opt, const char *str,
2468 return 0; 2610 return 0;
2469} 2611}
2470 2612
2613static void evlist__set_evsel_handler(struct perf_evlist *evlist, void *handler)
2614{
2615 struct perf_evsel *evsel;
2616
2617 evlist__for_each(evlist, evsel)
2618 evsel->handler = handler;
2619}
2620
2471int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) 2621int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
2472{ 2622{
2473 const char * const trace_usage[] = { 2623 const char *trace_usage[] = {
2474 "perf trace [<options>] [<command>]", 2624 "perf trace [<options>] [<command>]",
2475 "perf trace [<options>] -- <command> [<options>]", 2625 "perf trace [<options>] -- <command> [<options>]",
2476 "perf trace record [<options>] [<command>]", 2626 "perf trace record [<options>] [<command>]",
@@ -2502,6 +2652,9 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
2502 const char *output_name = NULL; 2652 const char *output_name = NULL;
2503 const char *ev_qualifier_str = NULL; 2653 const char *ev_qualifier_str = NULL;
2504 const struct option trace_options[] = { 2654 const struct option trace_options[] = {
2655 OPT_CALLBACK(0, "event", &trace.evlist, "event",
2656 "event selector. use 'perf list' to list available events",
2657 parse_events_option),
2505 OPT_BOOLEAN(0, "comm", &trace.show_comm, 2658 OPT_BOOLEAN(0, "comm", &trace.show_comm,
2506 "show the thread COMM next to its id"), 2659 "show the thread COMM next to its id"),
2507 OPT_BOOLEAN(0, "tool_stats", &trace.show_tool_stats, "show tool stats"), 2660 OPT_BOOLEAN(0, "tool_stats", &trace.show_tool_stats, "show tool stats"),
@@ -2513,6 +2666,8 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
2513 "trace events on existing process id"), 2666 "trace events on existing process id"),
2514 OPT_STRING('t', "tid", &trace.opts.target.tid, "tid", 2667 OPT_STRING('t', "tid", &trace.opts.target.tid, "tid",
2515 "trace events on existing thread id"), 2668 "trace events on existing thread id"),
2669 OPT_CALLBACK(0, "filter-pids", &trace, "float",
2670 "show only events with duration > N.M ms", trace__set_filter_pids),
2516 OPT_BOOLEAN('a', "all-cpus", &trace.opts.target.system_wide, 2671 OPT_BOOLEAN('a', "all-cpus", &trace.opts.target.system_wide,
2517 "system-wide collection from all CPUs"), 2672 "system-wide collection from all CPUs"),
2518 OPT_STRING('C', "cpu", &trace.opts.target.cpu_list, "cpu", 2673 OPT_STRING('C', "cpu", &trace.opts.target.cpu_list, "cpu",
@@ -2540,17 +2695,33 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
2540 OPT_BOOLEAN(0, "syscalls", &trace.trace_syscalls, "Trace syscalls"), 2695 OPT_BOOLEAN(0, "syscalls", &trace.trace_syscalls, "Trace syscalls"),
2541 OPT_END() 2696 OPT_END()
2542 }; 2697 };
2698 const char * const trace_subcommands[] = { "record", NULL };
2543 int err; 2699 int err;
2544 char bf[BUFSIZ]; 2700 char bf[BUFSIZ];
2545 2701
2546 argc = parse_options(argc, argv, trace_options, trace_usage, 2702 signal(SIGSEGV, sighandler_dump_stack);
2547 PARSE_OPT_STOP_AT_NON_OPTION); 2703 signal(SIGFPE, sighandler_dump_stack);
2704
2705 trace.evlist = perf_evlist__new();
2706 if (trace.evlist == NULL)
2707 return -ENOMEM;
2708
2709 if (trace.evlist == NULL) {
2710 pr_err("Not enough memory to run!\n");
2711 goto out;
2712 }
2713
2714 argc = parse_options_subcommand(argc, argv, trace_options, trace_subcommands,
2715 trace_usage, PARSE_OPT_STOP_AT_NON_OPTION);
2548 2716
2549 if (trace.trace_pgfaults) { 2717 if (trace.trace_pgfaults) {
2550 trace.opts.sample_address = true; 2718 trace.opts.sample_address = true;
2551 trace.opts.sample_time = true; 2719 trace.opts.sample_time = true;
2552 } 2720 }
2553 2721
2722 if (trace.evlist->nr_entries > 0)
2723 evlist__set_evsel_handler(trace.evlist, trace__event_handler);
2724
2554 if ((argc >= 1) && (strcmp(argv[0], "record") == 0)) 2725 if ((argc >= 1) && (strcmp(argv[0], "record") == 0))
2555 return trace__record(&trace, argc-1, &argv[1]); 2726 return trace__record(&trace, argc-1, &argv[1]);
2556 2727
@@ -2558,7 +2729,8 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
2558 if (trace.summary_only) 2729 if (trace.summary_only)
2559 trace.summary = trace.summary_only; 2730 trace.summary = trace.summary_only;
2560 2731
2561 if (!trace.trace_syscalls && !trace.trace_pgfaults) { 2732 if (!trace.trace_syscalls && !trace.trace_pgfaults &&
2733 trace.evlist->nr_entries == 0 /* Was --events used? */) {
2562 pr_err("Please specify something to trace.\n"); 2734 pr_err("Please specify something to trace.\n");
2563 return -1; 2735 return -1;
2564 } 2736 }
diff --git a/tools/perf/builtin.h b/tools/perf/builtin.h
index b210d62907e4..3688ad29085f 100644
--- a/tools/perf/builtin.h
+++ b/tools/perf/builtin.h
@@ -37,6 +37,7 @@ extern int cmd_test(int argc, const char **argv, const char *prefix);
37extern int cmd_trace(int argc, const char **argv, const char *prefix); 37extern int cmd_trace(int argc, const char **argv, const char *prefix);
38extern int cmd_inject(int argc, const char **argv, const char *prefix); 38extern int cmd_inject(int argc, const char **argv, const char *prefix);
39extern int cmd_mem(int argc, const char **argv, const char *prefix); 39extern int cmd_mem(int argc, const char **argv, const char *prefix);
40extern int cmd_data(int argc, const char **argv, const char *prefix);
40 41
41extern int find_scripts(char **scripts_array, char **scripts_path_array); 42extern int find_scripts(char **scripts_array, char **scripts_path_array);
42#endif 43#endif
diff --git a/tools/perf/command-list.txt b/tools/perf/command-list.txt
index 0906fc401c52..00fcaf8a5b8d 100644
--- a/tools/perf/command-list.txt
+++ b/tools/perf/command-list.txt
@@ -7,6 +7,7 @@ perf-archive mainporcelain common
7perf-bench mainporcelain common 7perf-bench mainporcelain common
8perf-buildid-cache mainporcelain common 8perf-buildid-cache mainporcelain common
9perf-buildid-list mainporcelain common 9perf-buildid-list mainporcelain common
10perf-data mainporcelain common
10perf-diff mainporcelain common 11perf-diff mainporcelain common
11perf-evlist mainporcelain common 12perf-evlist mainporcelain common
12perf-inject mainporcelain common 13perf-inject mainporcelain common
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index cc224080b525..cd121dfc4de9 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -11,19 +11,26 @@ ifneq ($(obj-perf),)
11obj-perf := $(abspath $(obj-perf))/ 11obj-perf := $(abspath $(obj-perf))/
12endif 12endif
13 13
14LIB_INCLUDE := $(srctree)/tools/lib/ 14$(shell echo -n > .config-detected)
15detected = $(shell echo "$(1)=y" >> .config-detected)
16detected_var = $(shell echo "$(1)=$($(1))" >> .config-detected)
17
15CFLAGS := $(EXTRA_CFLAGS) $(EXTRA_WARNINGS) 18CFLAGS := $(EXTRA_CFLAGS) $(EXTRA_WARNINGS)
16 19
17include $(src-perf)/config/Makefile.arch 20include $(src-perf)/config/Makefile.arch
18 21
22$(call detected_var,ARCH)
23
19NO_PERF_REGS := 1 24NO_PERF_REGS := 1
20 25
21# Additional ARCH settings for x86 26# Additional ARCH settings for x86
22ifeq ($(ARCH),x86) 27ifeq ($(ARCH),x86)
28 $(call detected,CONFIG_X86)
23 ifeq (${IS_64_BIT}, 1) 29 ifeq (${IS_64_BIT}, 1)
24 CFLAGS += -DHAVE_ARCH_X86_64_SUPPORT 30 CFLAGS += -DHAVE_ARCH_X86_64_SUPPORT
25 ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S 31 ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S
26 LIBUNWIND_LIBS = -lunwind -lunwind-x86_64 32 LIBUNWIND_LIBS = -lunwind -lunwind-x86_64
33 $(call detected,CONFIG_X86_64)
27 else 34 else
28 LIBUNWIND_LIBS = -lunwind -lunwind-x86 35 LIBUNWIND_LIBS = -lunwind -lunwind-x86
29 endif 36 endif
@@ -40,6 +47,10 @@ ifeq ($(ARCH),arm64)
40 LIBUNWIND_LIBS = -lunwind -lunwind-aarch64 47 LIBUNWIND_LIBS = -lunwind -lunwind-aarch64
41endif 48endif
42 49
50ifeq ($(NO_PERF_REGS),0)
51 $(call detected,CONFIG_PERF_REGS)
52endif
53
43# So far there's only x86 and arm libdw unwind support merged in perf. 54# So far there's only x86 and arm libdw unwind support merged in perf.
44# Disable it on all other architectures in case libdw unwind 55# Disable it on all other architectures in case libdw unwind
45# support is detected in system. Add supported architectures 56# support is detected in system. Add supported architectures
@@ -84,6 +95,17 @@ ifndef NO_LIBELF
84 FEATURE_CHECK_LDFLAGS-libdw-dwarf-unwind := $(LIBDW_LDFLAGS) -ldw 95 FEATURE_CHECK_LDFLAGS-libdw-dwarf-unwind := $(LIBDW_LDFLAGS) -ldw
85endif 96endif
86 97
98ifndef NO_LIBBABELTRACE
99 # for linking with debug library, run like:
100 # make DEBUG=1 LIBBABELTRACE_DIR=/opt/libbabeltrace/
101 ifdef LIBBABELTRACE_DIR
102 LIBBABELTRACE_CFLAGS := -I$(LIBBABELTRACE_DIR)/include
103 LIBBABELTRACE_LDFLAGS := -L$(LIBBABELTRACE_DIR)/lib
104 endif
105 FEATURE_CHECK_CFLAGS-libbabeltrace := $(LIBBABELTRACE_CFLAGS)
106 FEATURE_CHECK_LDFLAGS-libbabeltrace := $(LIBBABELTRACE_LDFLAGS) -lbabeltrace-ctf
107endif
108
87# include ARCH specific config 109# include ARCH specific config
88-include $(src-perf)/arch/$(ARCH)/Makefile 110-include $(src-perf)/arch/$(ARCH)/Makefile
89 111
@@ -114,6 +136,8 @@ ifdef PARSER_DEBUG
114 PARSER_DEBUG_BISON := -t 136 PARSER_DEBUG_BISON := -t
115 PARSER_DEBUG_FLEX := -d 137 PARSER_DEBUG_FLEX := -d
116 CFLAGS += -DPARSER_DEBUG 138 CFLAGS += -DPARSER_DEBUG
139 $(call detected_var,PARSER_DEBUG_BISON)
140 $(call detected_var,PARSER_DEBUG_FLEX)
117endif 141endif
118 142
119ifndef NO_LIBPYTHON 143ifndef NO_LIBPYTHON
@@ -152,121 +176,7 @@ LDFLAGS += -Wl,-z,noexecstack
152 176
153EXTLIBS = -lpthread -lrt -lm -ldl 177EXTLIBS = -lpthread -lrt -lm -ldl
154 178
155ifneq ($(OUTPUT),) 179include $(srctree)/tools/build/Makefile.feature
156 OUTPUT_FEATURES = $(OUTPUT)config/feature-checks/
157 $(shell mkdir -p $(OUTPUT_FEATURES))
158endif
159
160feature_check = $(eval $(feature_check_code))
161define feature_check_code
162 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)
163endef
164
165feature_set = $(eval $(feature_set_code))
166define feature_set_code
167 feature-$(1) := 1
168endef
169
170#
171# Build the feature check binaries in parallel, ignore errors, ignore return value and suppress output:
172#
173
174#
175# Note that this is not a complete list of all feature tests, just
176# those that are typically built on a fully configured system.
177#
178# [ Feature tests not mentioned here have to be built explicitly in
179# the rule that uses them - an example for that is the 'bionic'
180# feature check. ]
181#
182CORE_FEATURE_TESTS = \
183 backtrace \
184 dwarf \
185 fortify-source \
186 sync-compare-and-swap \
187 glibc \
188 gtk2 \
189 gtk2-infobar \
190 libaudit \
191 libbfd \
192 libelf \
193 libelf-getphdrnum \
194 libelf-mmap \
195 libnuma \
196 libperl \
197 libpython \
198 libpython-version \
199 libslang \
200 libunwind \
201 pthread-attr-setaffinity-np \
202 stackprotector-all \
203 timerfd \
204 libdw-dwarf-unwind \
205 zlib
206
207LIB_FEATURE_TESTS = \
208 dwarf \
209 glibc \
210 gtk2 \
211 libaudit \
212 libbfd \
213 libelf \
214 libnuma \
215 libperl \
216 libpython \
217 libslang \
218 libunwind \
219 libdw-dwarf-unwind \
220 zlib
221
222VF_FEATURE_TESTS = \
223 backtrace \
224 fortify-source \
225 sync-compare-and-swap \
226 gtk2-infobar \
227 libelf-getphdrnum \
228 libelf-mmap \
229 libpython-version \
230 pthread-attr-setaffinity-np \
231 stackprotector-all \
232 timerfd \
233 libunwind-debug-frame \
234 bionic \
235 liberty \
236 liberty-z \
237 cplus-demangle \
238 compile-32 \
239 compile-x32
240
241# Set FEATURE_CHECK_(C|LD)FLAGS-all for all CORE_FEATURE_TESTS features.
242# If in the future we need per-feature checks/flags for features not
243# mentioned in this list we need to refactor this ;-).
244set_test_all_flags = $(eval $(set_test_all_flags_code))
245define set_test_all_flags_code
246 FEATURE_CHECK_CFLAGS-all += $(FEATURE_CHECK_CFLAGS-$(1))
247 FEATURE_CHECK_LDFLAGS-all += $(FEATURE_CHECK_LDFLAGS-$(1))
248endef
249
250$(foreach feat,$(CORE_FEATURE_TESTS),$(call set_test_all_flags,$(feat)))
251
252#
253# Special fast-path for the 'all features are available' case:
254#
255$(call feature_check,all,$(MSG))
256
257#
258# Just in case the build freshly failed, make sure we print the
259# feature matrix:
260#
261ifeq ($(feature-all), 1)
262 #
263 # test-all.c passed - just set all the core feature flags to 1:
264 #
265 $(foreach feat,$(CORE_FEATURE_TESTS),$(call feature_set,$(feat)))
266else
267 $(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)
268 $(foreach feat,$(CORE_FEATURE_TESTS),$(call feature_check,$(feat)))
269endif
270 180
271ifeq ($(feature-stackprotector-all), 1) 181ifeq ($(feature-stackprotector-all), 1)
272 CFLAGS += -fstack-protector-all 182 CFLAGS += -fstack-protector-all
@@ -295,7 +205,7 @@ endif
295 205
296CFLAGS += -I$(src-perf)/util 206CFLAGS += -I$(src-perf)/util
297CFLAGS += -I$(src-perf) 207CFLAGS += -I$(src-perf)
298CFLAGS += -I$(LIB_INCLUDE) 208CFLAGS += -I$(srctree)/tools/lib/
299 209
300CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE 210CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
301 211
@@ -361,6 +271,7 @@ endif # NO_LIBELF
361ifndef NO_LIBELF 271ifndef NO_LIBELF
362 CFLAGS += -DHAVE_LIBELF_SUPPORT 272 CFLAGS += -DHAVE_LIBELF_SUPPORT
363 EXTLIBS += -lelf 273 EXTLIBS += -lelf
274 $(call detected,CONFIG_LIBELF)
364 275
365 ifeq ($(feature-libelf-mmap), 1) 276 ifeq ($(feature-libelf-mmap), 1)
366 CFLAGS += -DHAVE_LIBELF_MMAP_SUPPORT 277 CFLAGS += -DHAVE_LIBELF_MMAP_SUPPORT
@@ -381,6 +292,7 @@ ifndef NO_LIBELF
381 CFLAGS += -DHAVE_DWARF_SUPPORT $(LIBDW_CFLAGS) 292 CFLAGS += -DHAVE_DWARF_SUPPORT $(LIBDW_CFLAGS)
382 LDFLAGS += $(LIBDW_LDFLAGS) 293 LDFLAGS += $(LIBDW_LDFLAGS)
383 EXTLIBS += -ldw 294 EXTLIBS += -ldw
295 $(call detected,CONFIG_DWARF)
384 endif # PERF_HAVE_DWARF_REGS 296 endif # PERF_HAVE_DWARF_REGS
385 endif # NO_DWARF 297 endif # NO_DWARF
386endif # NO_LIBELF 298endif # NO_LIBELF
@@ -408,9 +320,11 @@ ifdef NO_LIBUNWIND
408 dwarf-post-unwind := 0 320 dwarf-post-unwind := 0
409 else 321 else
410 dwarf-post-unwind-text := libdw 322 dwarf-post-unwind-text := libdw
323 $(call detected,CONFIG_LIBDW_DWARF_UNWIND)
411 endif 324 endif
412else 325else
413 dwarf-post-unwind-text := libunwind 326 dwarf-post-unwind-text := libunwind
327 $(call detected,CONFIG_LIBUNWIND)
414 # Enable libunwind support by default. 328 # Enable libunwind support by default.
415 ifndef NO_LIBDW_DWARF_UNWIND 329 ifndef NO_LIBDW_DWARF_UNWIND
416 NO_LIBDW_DWARF_UNWIND := 1 330 NO_LIBDW_DWARF_UNWIND := 1
@@ -419,6 +333,7 @@ endif
419 333
420ifeq ($(dwarf-post-unwind),1) 334ifeq ($(dwarf-post-unwind),1)
421 CFLAGS += -DHAVE_DWARF_UNWIND_SUPPORT 335 CFLAGS += -DHAVE_DWARF_UNWIND_SUPPORT
336 $(call detected,CONFIG_DWARF_UNWIND)
422else 337else
423 NO_DWARF_UNWIND := 1 338 NO_DWARF_UNWIND := 1
424endif 339endif
@@ -447,6 +362,7 @@ ifndef NO_LIBAUDIT
447 else 362 else
448 CFLAGS += -DHAVE_LIBAUDIT_SUPPORT 363 CFLAGS += -DHAVE_LIBAUDIT_SUPPORT
449 EXTLIBS += -laudit 364 EXTLIBS += -laudit
365 $(call detected,CONFIG_AUDIT)
450 endif 366 endif
451endif 367endif
452 368
@@ -463,6 +379,7 @@ ifndef NO_SLANG
463 CFLAGS += -I/usr/include/slang 379 CFLAGS += -I/usr/include/slang
464 CFLAGS += -DHAVE_SLANG_SUPPORT 380 CFLAGS += -DHAVE_SLANG_SUPPORT
465 EXTLIBS += -lslang 381 EXTLIBS += -lslang
382 $(call detected,CONFIG_SLANG)
466 endif 383 endif
467endif 384endif
468 385
@@ -497,10 +414,11 @@ else
497 ifneq ($(feature-libperl), 1) 414 ifneq ($(feature-libperl), 1)
498 CFLAGS += -DNO_LIBPERL 415 CFLAGS += -DNO_LIBPERL
499 NO_LIBPERL := 1 416 NO_LIBPERL := 1
500 msg := $(warning Missing perl devel files. Disabling perl scripting support, consider installing perl-ExtUtils-Embed); 417 msg := $(warning Missing perl devel files. Disabling perl scripting support, please install perl-ExtUtils-Embed/libperl-dev);
501 else 418 else
502 LDFLAGS += $(PERL_EMBED_LDFLAGS) 419 LDFLAGS += $(PERL_EMBED_LDFLAGS)
503 EXTLIBS += $(PERL_EMBED_LIBADD) 420 EXTLIBS += $(PERL_EMBED_LIBADD)
421 $(call detected,CONFIG_LIBPERL)
504 endif 422 endif
505endif 423endif
506 424
@@ -513,22 +431,21 @@ endif
513disable-python = $(eval $(disable-python_code)) 431disable-python = $(eval $(disable-python_code))
514define disable-python_code 432define disable-python_code
515 CFLAGS += -DNO_LIBPYTHON 433 CFLAGS += -DNO_LIBPYTHON
516 $(if $(1),$(warning No $(1) was found)) 434 $(warning $1)
517 $(warning Python support will not be built)
518 NO_LIBPYTHON := 1 435 NO_LIBPYTHON := 1
519endef 436endef
520 437
521ifdef NO_LIBPYTHON 438ifdef NO_LIBPYTHON
522 $(call disable-python) 439 $(call disable-python,Python support disabled by user)
523else 440else
524 441
525 ifndef PYTHON 442 ifndef PYTHON
526 $(call disable-python,python interpreter) 443 $(call disable-python,No python interpreter was found: disables Python support - please install python-devel/python-dev)
527 else 444 else
528 PYTHON_WORD := $(call shell-wordify,$(PYTHON)) 445 PYTHON_WORD := $(call shell-wordify,$(PYTHON))
529 446
530 ifndef PYTHON_CONFIG 447 ifndef PYTHON_CONFIG
531 $(call disable-python,python-config tool) 448 $(call disable-python,No 'python-config' tool was found: disables Python support - please install python-devel/python-dev)
532 else 449 else
533 450
534 PYTHON_CONFIG_SQ := $(call shell-sq,$(PYTHON_CONFIG)) 451 PYTHON_CONFIG_SQ := $(call shell-sq,$(PYTHON_CONFIG))
@@ -540,7 +457,7 @@ else
540 FLAGS_PYTHON_EMBED := $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS) 457 FLAGS_PYTHON_EMBED := $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS)
541 458
542 ifneq ($(feature-libpython), 1) 459 ifneq ($(feature-libpython), 1)
543 $(call disable-python,Python.h (for Python 2.x)) 460 $(call disable-python,No 'Python.h' (for Python 2.x support) was found: disables Python support - please install python-devel/python-dev)
544 else 461 else
545 462
546 ifneq ($(feature-libpython-version), 1) 463 ifneq ($(feature-libpython-version), 1)
@@ -560,6 +477,7 @@ else
560 LDFLAGS += $(PYTHON_EMBED_LDFLAGS) 477 LDFLAGS += $(PYTHON_EMBED_LDFLAGS)
561 EXTLIBS += $(PYTHON_EMBED_LIBADD) 478 EXTLIBS += $(PYTHON_EMBED_LIBADD)
562 LANG_BINDINGS += $(obj-perf)python/perf.so 479 LANG_BINDINGS += $(obj-perf)python/perf.so
480 $(call detected,CONFIG_LIBPYTHON)
563 endif 481 endif
564 endif 482 endif
565 endif 483 endif
@@ -600,7 +518,7 @@ else
600 EXTLIBS += -liberty 518 EXTLIBS += -liberty
601 CFLAGS += -DHAVE_CPLUS_DEMANGLE_SUPPORT 519 CFLAGS += -DHAVE_CPLUS_DEMANGLE_SUPPORT
602 else 520 else
603 msg := $(warning No bfd.h/libbfd found, install binutils-dev[el]/zlib-static to gain symbol demangling) 521 msg := $(warning No bfd.h/libbfd found, please install binutils-dev[el]/zlib-static/libiberty-dev to gain symbol demangling)
604 CFLAGS += -DNO_DEMANGLE 522 CFLAGS += -DNO_DEMANGLE
605 endif 523 endif
606 endif 524 endif
@@ -617,11 +535,23 @@ ifndef NO_ZLIB
617 ifeq ($(feature-zlib), 1) 535 ifeq ($(feature-zlib), 1)
618 CFLAGS += -DHAVE_ZLIB_SUPPORT 536 CFLAGS += -DHAVE_ZLIB_SUPPORT
619 EXTLIBS += -lz 537 EXTLIBS += -lz
538 $(call detected,CONFIG_ZLIB)
620 else 539 else
621 NO_ZLIB := 1 540 NO_ZLIB := 1
622 endif 541 endif
623endif 542endif
624 543
544ifndef NO_LZMA
545 ifeq ($(feature-lzma), 1)
546 CFLAGS += -DHAVE_LZMA_SUPPORT
547 EXTLIBS += -llzma
548 $(call detected,CONFIG_LZMA)
549 else
550 msg := $(warning No liblzma found, disables xz kernel module decompression, please install xz-devel/liblzma-dev);
551 NO_LZMA := 1
552 endif
553endif
554
625ifndef NO_BACKTRACE 555ifndef NO_BACKTRACE
626 ifeq ($(feature-backtrace), 1) 556 ifeq ($(feature-backtrace), 1)
627 CFLAGS += -DHAVE_BACKTRACE_SUPPORT 557 CFLAGS += -DHAVE_BACKTRACE_SUPPORT
@@ -635,6 +565,7 @@ ifndef NO_LIBNUMA
635 else 565 else
636 CFLAGS += -DHAVE_LIBNUMA_SUPPORT 566 CFLAGS += -DHAVE_LIBNUMA_SUPPORT
637 EXTLIBS += -lnuma 567 EXTLIBS += -lnuma
568 $(call detected,CONFIG_NUMA)
638 endif 569 endif
639endif 570endif
640 571
@@ -651,7 +582,7 @@ ifeq (${IS_64_BIT}, 1)
651 NO_PERF_READ_VDSO32 := 1 582 NO_PERF_READ_VDSO32 := 1
652 endif 583 endif
653 endif 584 endif
654 ifneq (${IS_X86_64}, 1) 585 ifneq ($(ARCH), x86)
655 NO_PERF_READ_VDSOX32 := 1 586 NO_PERF_READ_VDSOX32 := 1
656 endif 587 endif
657 ifndef NO_PERF_READ_VDSOX32 588 ifndef NO_PERF_READ_VDSOX32
@@ -667,6 +598,19 @@ else
667 NO_PERF_READ_VDSOX32 := 1 598 NO_PERF_READ_VDSOX32 := 1
668endif 599endif
669 600
601ifndef NO_LIBBABELTRACE
602 $(call feature_check,libbabeltrace)
603 ifeq ($(feature-libbabeltrace), 1)
604 CFLAGS += -DHAVE_LIBBABELTRACE_SUPPORT $(LIBBABELTRACE_CFLAGS)
605 LDFLAGS += $(LIBBABELTRACE_LDFLAGS)
606 EXTLIBS += -lbabeltrace-ctf
607 $(call detected,CONFIG_LIBBABELTRACE)
608 else
609 msg := $(warning No libbabeltrace found, disables 'perf data' CTF format support, please install libbabeltrace-dev[el]/libbabeltrace-ctf-dev);
610 NO_LIBBABELTRACE := 1
611 endif
612endif
613
670# Among the variables below, these: 614# Among the variables below, these:
671# perfexecdir 615# perfexecdir
672# template_dir 616# template_dir
@@ -699,7 +643,7 @@ sysconfdir = $(prefix)/etc
699ETC_PERFCONFIG = etc/perfconfig 643ETC_PERFCONFIG = etc/perfconfig
700endif 644endif
701ifndef lib 645ifndef lib
702ifeq ($(IS_X86_64),1) 646ifeq ($(ARCH)$(IS_64_BIT), x861)
703lib = lib64 647lib = lib64
704else 648else
705lib = lib 649lib = lib
@@ -735,83 +679,33 @@ plugindir=$(libdir)/traceevent/plugins
735plugindir_SQ= $(subst ','\'',$(plugindir)) 679plugindir_SQ= $(subst ','\'',$(plugindir))
736endif 680endif
737 681
738# 682print_var = $(eval $(print_var_code)) $(info $(MSG))
739# Print the result of the feature test: 683define print_var_code
740#
741feature_print_status = $(eval $(feature_print_status_code)) $(info $(MSG))
742
743define feature_print_status_code
744 ifeq ($(feature-$(1)), 1)
745 MSG = $(shell printf '...%30s: [ \033[32mon\033[m ]' $(1))
746 else
747 MSG = $(shell printf '...%30s: [ \033[31mOFF\033[m ]' $(1))
748 endif
749endef
750
751feature_print_var = $(eval $(feature_print_var_code)) $(info $(MSG))
752define feature_print_var_code
753 MSG = $(shell printf '...%30s: %s' $(1) $($(1))) 684 MSG = $(shell printf '...%30s: %s' $(1) $($(1)))
754endef 685endef
755 686
756feature_print_text = $(eval $(feature_print_text_code)) $(info $(MSG))
757define feature_print_text_code
758 MSG = $(shell printf '...%30s: %s' $(1) $(2))
759endef
760
761PERF_FEATURES := $(foreach feat,$(LIB_FEATURE_TESTS),feature-$(feat)($(feature-$(feat))))
762PERF_FEATURES_FILE := $(shell touch $(OUTPUT)PERF-FEATURES; cat $(OUTPUT)PERF-FEATURES)
763
764ifeq ($(dwarf-post-unwind),1)
765 PERF_FEATURES += dwarf-post-unwind($(dwarf-post-unwind-text))
766endif
767
768# The $(display_lib) controls the default detection message
769# output. It's set if:
770# - detected features differes from stored features from
771# last build (in PERF-FEATURES file)
772# - one of the $(LIB_FEATURE_TESTS) is not detected
773# - VF is enabled
774
775ifneq ("$(PERF_FEATURES)","$(PERF_FEATURES_FILE)")
776 $(shell echo "$(PERF_FEATURES)" > $(OUTPUT)PERF-FEATURES)
777 display_lib := 1
778endif
779
780feature_check = $(eval $(feature_check_code))
781define feature_check_code
782 ifneq ($(feature-$(1)), 1)
783 display_lib := 1
784 endif
785endef
786
787$(foreach feat,$(LIB_FEATURE_TESTS),$(call feature_check,$(feat)))
788
789ifeq ($(VF),1) 687ifeq ($(VF),1)
790 display_lib := 1 688 $(call print_var,prefix)
791 display_vf := 1 689 $(call print_var,bindir)
792endif 690 $(call print_var,libdir)
793 691 $(call print_var,sysconfdir)
794ifeq ($(display_lib),1) 692 $(call print_var,LIBUNWIND_DIR)
693 $(call print_var,LIBDW_DIR)
795 $(info ) 694 $(info )
796 $(info Auto-detecting system features:)
797 $(foreach feat,$(LIB_FEATURE_TESTS),$(call feature_print_status,$(feat),))
798
799 ifeq ($(dwarf-post-unwind),1)
800 $(call feature_print_text,"DWARF post unwind library", $(dwarf-post-unwind-text))
801 endif
802endif
803
804ifeq ($(display_vf),1)
805 $(foreach feat,$(VF_FEATURE_TESTS),$(call feature_print_status,$(feat),))
806 $(info )
807 $(call feature_print_var,prefix)
808 $(call feature_print_var,bindir)
809 $(call feature_print_var,libdir)
810 $(call feature_print_var,sysconfdir)
811 $(call feature_print_var,LIBUNWIND_DIR)
812 $(call feature_print_var,LIBDW_DIR)
813endif 695endif
814 696
815ifeq ($(display_lib),1) 697$(call detected_var,bindir_SQ)
816 $(info ) 698$(call detected_var,PYTHON_WORD)
817endif 699ifneq ($(OUTPUT),)
700$(call detected_var,OUTPUT)
701endif
702$(call detected_var,htmldir_SQ)
703$(call detected_var,infodir_SQ)
704$(call detected_var,mandir_SQ)
705$(call detected_var,ETC_PERFCONFIG_SQ)
706$(call detected_var,prefix_SQ)
707$(call detected_var,perfexecdir_SQ)
708$(call detected_var,LIBDIR)
709$(call detected_var,GTK_CFLAGS)
710$(call detected_var,PERL_EMBED_CCOPTS)
711$(call detected_var,PYTHON_EMBED_CCOPTS)
diff --git a/tools/perf/config/Makefile.arch b/tools/perf/config/Makefile.arch
index ac8721ffa6c8..e11fbd6fae78 100644
--- a/tools/perf/config/Makefile.arch
+++ b/tools/perf/config/Makefile.arch
@@ -1,32 +1,15 @@
1ifndef ARCH
2ARCH := $(shell uname -m 2>/dev/null || echo not)
3endif
1 4
2uname_M := $(shell uname -m 2>/dev/null || echo not) 5ARCH := $(shell echo $(ARCH) | sed -e s/i.86/x86/ -e s/x86_64/x86/ \
3 6 -e s/sun4u/sparc/ -e s/sparc64/sparc/ \
4RAW_ARCH := $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ 7 -e /arm64/!s/arm.*/arm/ -e s/sa110/arm/ \
5 -e s/arm.*/arm/ -e s/sa110/arm/ \
6 -e s/s390x/s390/ -e s/parisc64/parisc/ \ 8 -e s/s390x/s390/ -e s/parisc64/parisc/ \
7 -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \ 9 -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \
8 -e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ \ 10 -e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ \
9 -e s/tile.*/tile/ ) 11 -e s/tile.*/tile/ )
10 12
11# Additional ARCH settings for x86
12ifeq ($(RAW_ARCH),i386)
13 ARCH ?= x86
14endif
15
16ifeq ($(RAW_ARCH),x86_64)
17 ARCH ?= x86
18
19 ifneq (, $(findstring m32,$(CFLAGS)))
20 RAW_ARCH := x86_32
21 endif
22endif
23
24ifeq ($(RAW_ARCH),sparc64)
25 ARCH ?= sparc
26endif
27
28ARCH ?= $(RAW_ARCH)
29
30LP64 := $(shell echo __LP64__ | ${CC} ${CFLAGS} -E -x c - | tail -n 1) 13LP64 := $(shell echo __LP64__ | ${CC} ${CFLAGS} -E -x c - | tail -n 1)
31ifeq ($(LP64), 1) 14ifeq ($(LP64), 1)
32 IS_64_BIT := 1 15 IS_64_BIT := 1
diff --git a/tools/perf/config/utilities.mak b/tools/perf/config/utilities.mak
index 7076a62d0ff7..c16ce833079c 100644
--- a/tools/perf/config/utilities.mak
+++ b/tools/perf/config/utilities.mak
@@ -175,6 +175,5 @@ _ge-abspath = $(if $(is-executable),$(1))
175define get-executable-or-default 175define get-executable-or-default
176$(if $($(1)),$(call _ge_attempt,$($(1)),$(1)),$(call _ge_attempt,$(2))) 176$(if $($(1)),$(call _ge_attempt,$($(1)),$(1)),$(call _ge_attempt,$(2)))
177endef 177endef
178_ge_attempt = $(if $(get-executable),$(get-executable),$(_gea_warn)$(call _gea_err,$(2))) 178_ge_attempt = $(if $(get-executable),$(get-executable),$(call _gea_err,$(2)))
179_gea_warn = $(warning The path '$(1)' is not executable.)
180_gea_err = $(if $(1),$(error Please set '$(1)' appropriately)) 179_gea_err = $(if $(1),$(error Please set '$(1)' appropriately))
diff --git a/tools/perf/perf-completion.sh b/tools/perf/perf-completion.sh
index 33569847fdcc..3ba80b2359cc 100644
--- a/tools/perf/perf-completion.sh
+++ b/tools/perf/perf-completion.sh
@@ -47,8 +47,16 @@ __my_reassemble_comp_words_by_ref()
47 done 47 done
48} 48}
49 49
50type _get_comp_words_by_ref &>/dev/null || 50# Define preload_get_comp_words_by_ref="false", if the function
51_get_comp_words_by_ref() 51# __perf_get_comp_words_by_ref() is required instead.
52preload_get_comp_words_by_ref="true"
53
54if [ $preload_get_comp_words_by_ref = "true" ]; then
55 type _get_comp_words_by_ref &>/dev/null ||
56 preload_get_comp_words_by_ref="false"
57fi
58[ $preload_get_comp_words_by_ref = "true" ] ||
59__perf_get_comp_words_by_ref()
52{ 60{
53 local exclude cur_ words_ cword_ 61 local exclude cur_ words_ cword_
54 if [ "$1" = "-n" ]; then 62 if [ "$1" = "-n" ]; then
@@ -76,8 +84,16 @@ _get_comp_words_by_ref()
76 done 84 done
77} 85}
78 86
79type __ltrim_colon_completions &>/dev/null || 87# Define preload__ltrim_colon_completions="false", if the function
80__ltrim_colon_completions() 88# __perf__ltrim_colon_completions() is required instead.
89preload__ltrim_colon_completions="true"
90
91if [ $preload__ltrim_colon_completions = "true" ]; then
92 type __ltrim_colon_completions &>/dev/null ||
93 preload__ltrim_colon_completions="false"
94fi
95[ $preload__ltrim_colon_completions = "true" ] ||
96__perf__ltrim_colon_completions()
81{ 97{
82 if [[ "$1" == *:* && "$COMP_WORDBREAKS" == *:* ]]; then 98 if [[ "$1" == *:* && "$COMP_WORDBREAKS" == *:* ]]; then
83 # Remove colon-word prefix from COMPREPLY items 99 # Remove colon-word prefix from COMPREPLY items
@@ -97,7 +113,32 @@ __perfcomp ()
97__perfcomp_colon () 113__perfcomp_colon ()
98{ 114{
99 __perfcomp "$1" "$2" 115 __perfcomp "$1" "$2"
100 __ltrim_colon_completions $cur 116 if [ $preload__ltrim_colon_completions = "true" ]; then
117 __ltrim_colon_completions $cur
118 else
119 __perf__ltrim_colon_completions $cur
120 fi
121}
122
123__perf_prev_skip_opts ()
124{
125 local i cmd_ cmds_
126
127 let i=cword-1
128 cmds_=$($cmd $1 --list-cmds)
129 prev_skip_opts=()
130 while [ $i -ge 0 ]; do
131 if [[ ${words[i]} == $1 ]]; then
132 return
133 fi
134 for cmd_ in $cmds_; do
135 if [[ ${words[i]} == $cmd_ ]]; then
136 prev_skip_opts=${words[i]}
137 return
138 fi
139 done
140 ((i--))
141 done
101} 142}
102 143
103__perf_main () 144__perf_main ()
@@ -107,29 +148,36 @@ __perf_main ()
107 cmd=${words[0]} 148 cmd=${words[0]}
108 COMPREPLY=() 149 COMPREPLY=()
109 150
151 # Skip options backward and find the last perf command
152 __perf_prev_skip_opts
110 # List perf subcommands or long options 153 # List perf subcommands or long options
111 if [ $cword -eq 1 ]; then 154 if [ -z $prev_skip_opts ]; then
112 if [[ $cur == --* ]]; then 155 if [[ $cur == --* ]]; then
113 __perfcomp '--help --version \ 156 cmds=$($cmd --list-opts)
114 --exec-path --html-path --paginate --no-pager \
115 --perf-dir --work-tree --debugfs-dir' -- "$cur"
116 else 157 else
117 cmds=$($cmd --list-cmds) 158 cmds=$($cmd --list-cmds)
118 __perfcomp "$cmds" "$cur"
119 fi 159 fi
160 __perfcomp "$cmds" "$cur"
120 # List possible events for -e option 161 # List possible events for -e option
121 elif [[ $prev == "-e" && "${words[1]}" == @(record|stat|top) ]]; then 162 elif [[ $prev == @("-e"|"--event") &&
163 $prev_skip_opts == @(record|stat|top) ]]; then
122 evts=$($cmd list --raw-dump) 164 evts=$($cmd list --raw-dump)
123 __perfcomp_colon "$evts" "$cur" 165 __perfcomp_colon "$evts" "$cur"
124 # List subcommands for perf commands 166 else
125 elif [[ $prev == @(kvm|kmem|mem|lock|sched) ]]; then 167 # List subcommands for perf commands
126 subcmds=$($cmd $prev --list-cmds) 168 if [[ $prev_skip_opts == @(kvm|kmem|mem|lock|sched|
127 __perfcomp_colon "$subcmds" "$cur" 169 |data|help|script|test|timechart|trace) ]]; then
128 # List long option names 170 subcmds=$($cmd $prev_skip_opts --list-cmds)
129 elif [[ $cur == --* ]]; then 171 __perfcomp_colon "$subcmds" "$cur"
130 subcmd=${words[1]} 172 fi
131 opts=$($cmd $subcmd --list-opts) 173 # List long option names
132 __perfcomp "$opts" "$cur" 174 if [[ $cur == --* ]]; then
175 subcmd=$prev_skip_opts
176 __perf_prev_skip_opts $subcmd
177 subcmd=$subcmd" "$prev_skip_opts
178 opts=$($cmd $subcmd --list-opts)
179 __perfcomp "$opts" "$cur"
180 fi
133 fi 181 fi
134} 182}
135 183
@@ -198,7 +246,11 @@ type perf &>/dev/null &&
198_perf() 246_perf()
199{ 247{
200 local cur words cword prev 248 local cur words cword prev
201 _get_comp_words_by_ref -n =: cur words cword prev 249 if [ $preload_get_comp_words_by_ref = "true" ]; then
250 _get_comp_words_by_ref -n =: cur words cword prev
251 else
252 __perf_get_comp_words_by_ref -n =: cur words cword prev
253 fi
202 __perf_main 254 __perf_main
203} && 255} &&
204 256
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 3700a7faca6c..b857fcbd00cf 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -13,6 +13,7 @@
13#include "util/quote.h" 13#include "util/quote.h"
14#include "util/run-command.h" 14#include "util/run-command.h"
15#include "util/parse-events.h" 15#include "util/parse-events.h"
16#include "util/parse-options.h"
16#include "util/debug.h" 17#include "util/debug.h"
17#include <api/fs/debugfs.h> 18#include <api/fs/debugfs.h>
18#include <pthread.h> 19#include <pthread.h>
@@ -62,6 +63,7 @@ static struct cmd_struct commands[] = {
62#endif 63#endif
63 { "inject", cmd_inject, 0 }, 64 { "inject", cmd_inject, 0 },
64 { "mem", cmd_mem, 0 }, 65 { "mem", cmd_mem, 0 },
66 { "data", cmd_data, 0 },
65}; 67};
66 68
67struct pager_config { 69struct pager_config {
@@ -124,6 +126,23 @@ static void commit_pager_choice(void)
124 } 126 }
125} 127}
126 128
129struct option options[] = {
130 OPT_ARGUMENT("help", "help"),
131 OPT_ARGUMENT("version", "version"),
132 OPT_ARGUMENT("exec-path", "exec-path"),
133 OPT_ARGUMENT("html-path", "html-path"),
134 OPT_ARGUMENT("paginate", "paginate"),
135 OPT_ARGUMENT("no-pager", "no-pager"),
136 OPT_ARGUMENT("perf-dir", "perf-dir"),
137 OPT_ARGUMENT("work-tree", "work-tree"),
138 OPT_ARGUMENT("debugfs-dir", "debugfs-dir"),
139 OPT_ARGUMENT("buildid-dir", "buildid-dir"),
140 OPT_ARGUMENT("list-cmds", "list-cmds"),
141 OPT_ARGUMENT("list-opts", "list-opts"),
142 OPT_ARGUMENT("debug", "debug"),
143 OPT_END()
144};
145
127static int handle_options(const char ***argv, int *argc, int *envchanged) 146static int handle_options(const char ***argv, int *argc, int *envchanged)
128{ 147{
129 int handled = 0; 148 int handled = 0;
@@ -222,6 +241,16 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
222 struct cmd_struct *p = commands+i; 241 struct cmd_struct *p = commands+i;
223 printf("%s ", p->cmd); 242 printf("%s ", p->cmd);
224 } 243 }
244 putchar('\n');
245 exit(0);
246 } else if (!strcmp(cmd, "--list-opts")) {
247 unsigned int i;
248
249 for (i = 0; i < ARRAY_SIZE(options)-1; i++) {
250 struct option *p = options+i;
251 printf("--%s ", p->long_name);
252 }
253 putchar('\n');
225 exit(0); 254 exit(0);
226 } else if (!strcmp(cmd, "--debug")) { 255 } else if (!strcmp(cmd, "--debug")) {
227 if (*argc < 2) { 256 if (*argc < 2) {
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 1dabb8553499..c38a085a5571 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -29,7 +29,7 @@ static inline unsigned long long rdclock(void)
29 return ts.tv_sec * 1000000000ULL + ts.tv_nsec; 29 return ts.tv_sec * 1000000000ULL + ts.tv_nsec;
30} 30}
31 31
32#define MAX_NR_CPUS 256 32#define MAX_NR_CPUS 1024
33 33
34extern const char *input_name; 34extern const char *input_name;
35extern bool perf_host, perf_guest; 35extern bool perf_host, perf_guest;
@@ -53,6 +53,7 @@ struct record_opts {
53 bool sample_time; 53 bool sample_time;
54 bool period; 54 bool period;
55 bool sample_intr_regs; 55 bool sample_intr_regs;
56 bool running_time;
56 unsigned int freq; 57 unsigned int freq;
57 unsigned int mmap_pages; 58 unsigned int mmap_pages;
58 unsigned int user_freq; 59 unsigned int user_freq;
diff --git a/tools/perf/scripts/Build b/tools/perf/scripts/Build
new file mode 100644
index 000000000000..41efd7e368b3
--- /dev/null
+++ b/tools/perf/scripts/Build
@@ -0,0 +1,2 @@
1libperf-$(CONFIG_LIBPERL) += perl/Perf-Trace-Util/
2libperf-$(CONFIG_LIBPYTHON) += python/Perf-Trace-Util/
diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/Build b/tools/perf/scripts/perl/Perf-Trace-Util/Build
new file mode 100644
index 000000000000..928e110179cb
--- /dev/null
+++ b/tools/perf/scripts/perl/Perf-Trace-Util/Build
@@ -0,0 +1,3 @@
1libperf-y += Context.o
2
3CFLAGS_Context.o += $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs -Wno-undef -Wno-switch-default
diff --git a/tools/perf/scripts/python/Perf-Trace-Util/Build b/tools/perf/scripts/python/Perf-Trace-Util/Build
new file mode 100644
index 000000000000..aefc15c9444a
--- /dev/null
+++ b/tools/perf/scripts/python/Perf-Trace-Util/Build
@@ -0,0 +1,3 @@
1libperf-y += Context.o
2
3CFLAGS_Context.o += $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs
diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
new file mode 100644
index 000000000000..6a8801b32017
--- /dev/null
+++ b/tools/perf/tests/Build
@@ -0,0 +1,43 @@
1perf-y += builtin-test.o
2perf-y += parse-events.o
3perf-y += dso-data.o
4perf-y += attr.o
5perf-y += vmlinux-kallsyms.o
6perf-y += open-syscall.o
7perf-y += open-syscall-all-cpus.o
8perf-y += open-syscall-tp-fields.o
9perf-y += mmap-basic.o
10perf-y += perf-record.o
11perf-y += rdpmc.o
12perf-y += evsel-roundtrip-name.o
13perf-y += evsel-tp-sched.o
14perf-y += fdarray.o
15perf-y += pmu.o
16perf-y += hists_common.o
17perf-y += hists_link.o
18perf-y += hists_filter.o
19perf-y += hists_output.o
20perf-y += hists_cumulate.o
21perf-y += python-use.o
22perf-y += bp_signal.o
23perf-y += bp_signal_overflow.o
24perf-y += task-exit.o
25perf-y += sw-clock.o
26perf-y += mmap-thread-lookup.o
27perf-y += thread-mg-share.o
28perf-y += switch-tracking.o
29perf-y += keep-tracking.o
30perf-y += code-reading.o
31perf-y += sample-parsing.o
32perf-y += parse-no-sample-id-all.o
33perf-y += kmod-path.o
34
35perf-$(CONFIG_X86) += perf-time-to-tsc.o
36
37ifeq ($(ARCH),$(filter $(ARCH),x86 arm))
38perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o
39endif
40
41CFLAGS_attr.o += -DBINDIR="BUILD_STR($(bindir_SQ))" -DPYTHON="BUILD_STR($(PYTHON_WORD))"
42CFLAGS_python-use.o += -DPYTHONPATH="BUILD_STR($(OUTPUT)python)" -DPYTHON="BUILD_STR($(PYTHON_WORD))"
43CFLAGS_dwarf-unwind.o += -fno-optimize-sibling-calls
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 4b7d9ab0f049..4f4098167112 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -167,6 +167,10 @@ static struct test {
167 .func = test__fdarray__add, 167 .func = test__fdarray__add,
168 }, 168 },
169 { 169 {
170 .desc = "Test kmod_path__parse function",
171 .func = test__kmod_path__parse,
172 },
173 {
170 .func = NULL, 174 .func = NULL,
171 }, 175 },
172}; 176};
@@ -291,7 +295,7 @@ static int perf_test__list(int argc, const char **argv)
291 295
292int cmd_test(int argc, const char **argv, const char *prefix __maybe_unused) 296int cmd_test(int argc, const char **argv, const char *prefix __maybe_unused)
293{ 297{
294 const char * const test_usage[] = { 298 const char *test_usage[] = {
295 "perf test [<options>] [{list <test-name-fragment>|[<test-name-fragments>|<test-numbers>]}]", 299 "perf test [<options>] [{list <test-name-fragment>|[<test-name-fragments>|<test-numbers>]}]",
296 NULL, 300 NULL,
297 }; 301 };
@@ -302,13 +306,14 @@ int cmd_test(int argc, const char **argv, const char *prefix __maybe_unused)
302 "be more verbose (show symbol address, etc)"), 306 "be more verbose (show symbol address, etc)"),
303 OPT_END() 307 OPT_END()
304 }; 308 };
309 const char * const test_subcommands[] = { "list", NULL };
305 struct intlist *skiplist = NULL; 310 struct intlist *skiplist = NULL;
306 int ret = hists__init(); 311 int ret = hists__init();
307 312
308 if (ret < 0) 313 if (ret < 0)
309 return ret; 314 return ret;
310 315
311 argc = parse_options(argc, argv, test_options, test_usage, 0); 316 argc = parse_options_subcommand(argc, argv, test_options, test_subcommands, test_usage, 0);
312 if (argc >= 1 && !strcmp(argv[0], "list")) 317 if (argc >= 1 && !strcmp(argv[0], "list"))
313 return perf_test__list(argc, argv); 318 return perf_test__list(argc, argv);
314 319
diff --git a/tools/perf/tests/dso-data.c b/tools/perf/tests/dso-data.c
index caaf37f079b1..513e5febbe5a 100644
--- a/tools/perf/tests/dso-data.c
+++ b/tools/perf/tests/dso-data.c
@@ -112,6 +112,9 @@ int test__dso_data(void)
112 112
113 dso = dso__new((const char *)file); 113 dso = dso__new((const char *)file);
114 114
115 TEST_ASSERT_VAL("Failed to access to dso",
116 dso__data_fd(dso, &machine) >= 0);
117
115 /* Basic 10 bytes tests. */ 118 /* Basic 10 bytes tests. */
116 for (i = 0; i < ARRAY_SIZE(offsets); i++) { 119 for (i = 0; i < ARRAY_SIZE(offsets); i++) {
117 struct test_data_offset *data = &offsets[i]; 120 struct test_data_offset *data = &offsets[i];
@@ -243,8 +246,8 @@ int test__dso_data_cache(void)
243 limit = nr * 4; 246 limit = nr * 4;
244 TEST_ASSERT_VAL("failed to set file limit", !set_fd_limit(limit)); 247 TEST_ASSERT_VAL("failed to set file limit", !set_fd_limit(limit));
245 248
246 /* and this is now our dso open FDs limit + 1 extra */ 249 /* and this is now our dso open FDs limit */
247 dso_cnt = limit / 2 + 1; 250 dso_cnt = limit / 2;
248 TEST_ASSERT_VAL("failed to create dsos\n", 251 TEST_ASSERT_VAL("failed to create dsos\n",
249 !dsos__create(dso_cnt, TEST_FILE_SIZE)); 252 !dsos__create(dso_cnt, TEST_FILE_SIZE));
250 253
@@ -252,13 +255,13 @@ int test__dso_data_cache(void)
252 struct dso *dso = dsos[i]; 255 struct dso *dso = dsos[i];
253 256
254 /* 257 /*
255 * Open dsos via dso__data_fd or dso__data_read_offset. 258 * Open dsos via dso__data_fd(), it opens the data
256 * Both opens the data file and keep it open. 259 * file and keep it open (unless open file limit).
257 */ 260 */
261 fd = dso__data_fd(dso, &machine);
262 TEST_ASSERT_VAL("failed to get fd", fd > 0);
263
258 if (i % 2) { 264 if (i % 2) {
259 fd = dso__data_fd(dso, &machine);
260 TEST_ASSERT_VAL("failed to get fd", fd > 0);
261 } else {
262 #define BUFSIZE 10 265 #define BUFSIZE 10
263 u8 buf[BUFSIZE]; 266 u8 buf[BUFSIZE];
264 ssize_t n; 267 ssize_t n;
@@ -268,7 +271,10 @@ int test__dso_data_cache(void)
268 } 271 }
269 } 272 }
270 273
271 /* open +1 dso over the allowed limit */ 274 /* verify the first one is already open */
275 TEST_ASSERT_VAL("dsos[0] is not open", dsos[0]->data.fd != -1);
276
277 /* open +1 dso to reach the allowed limit */
272 fd = dso__data_fd(dsos[i], &machine); 278 fd = dso__data_fd(dsos[i], &machine);
273 TEST_ASSERT_VAL("failed to get fd", fd > 0); 279 TEST_ASSERT_VAL("failed to get fd", fd > 0);
274 280
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 @@
1#include <stdbool.h>
2#include "tests.h"
3#include "dso.h"
4#include "debug.h"
5
6static int test(const char *path, bool alloc_name, bool alloc_ext,
7 bool kmod, bool comp, const char *name, const char *ext)
8{
9 struct kmod_path m;
10
11 memset(&m, 0x0, sizeof(m));
12
13 TEST_ASSERT_VAL("kmod_path__parse",
14 !__kmod_path__parse(&m, path, alloc_name, alloc_ext));
15
16 pr_debug("%s - alloc name %d, alloc ext %d, kmod %d, comp %d, name '%s', ext '%s'\n",
17 path, alloc_name, alloc_ext, m.kmod, m.comp, m.name, m.ext);
18
19 TEST_ASSERT_VAL("wrong kmod", m.kmod == kmod);
20 TEST_ASSERT_VAL("wrong comp", m.comp == comp);
21
22 if (ext)
23 TEST_ASSERT_VAL("wrong ext", m.ext && !strcmp(ext, m.ext));
24 else
25 TEST_ASSERT_VAL("wrong ext", !m.ext);
26
27 if (name)
28 TEST_ASSERT_VAL("wrong name", m.name && !strcmp(name, m.name));
29 else
30 TEST_ASSERT_VAL("wrong name", !m.name);
31
32 free(m.name);
33 free(m.ext);
34 return 0;
35}
36
37#define T(path, an, ae, k, c, n, e) \
38 TEST_ASSERT_VAL("failed", !test(path, an, ae, k, c, n, e))
39
40int test__kmod_path__parse(void)
41{
42 /* path alloc_name alloc_ext kmod comp name ext */
43 T("/xxxx/xxxx/x-x.ko", true , true , true, false, "[x_x]", NULL);
44 T("/xxxx/xxxx/x-x.ko", false , true , true, false, NULL , NULL);
45 T("/xxxx/xxxx/x-x.ko", true , false , true, false, "[x_x]", NULL);
46 T("/xxxx/xxxx/x-x.ko", false , false , true, false, NULL , NULL);
47
48 /* path alloc_name alloc_ext kmod comp name ext */
49 T("/xxxx/xxxx/x.ko.gz", true , true , true, true, "[x]", "gz");
50 T("/xxxx/xxxx/x.ko.gz", false , true , true, true, NULL , "gz");
51 T("/xxxx/xxxx/x.ko.gz", true , false , true, true, "[x]", NULL);
52 T("/xxxx/xxxx/x.ko.gz", false , false , true, true, NULL , NULL);
53
54 /* path alloc_name alloc_ext kmod comp name ext */
55 T("/xxxx/xxxx/x.gz", true , true , false, true, "x.gz" ,"gz");
56 T("/xxxx/xxxx/x.gz", false , true , false, true, NULL ,"gz");
57 T("/xxxx/xxxx/x.gz", true , false , false, true, "x.gz" , NULL);
58 T("/xxxx/xxxx/x.gz", false , false , false, true, NULL , NULL);
59
60 /* path alloc_name alloc_ext kmod comp name ext */
61 T("x.gz", true , true , false, true, "x.gz", "gz");
62 T("x.gz", false , true , false, true, NULL , "gz");
63 T("x.gz", true , false , false, true, "x.gz", NULL);
64 T("x.gz", false , false , false, true, NULL , NULL);
65
66 /* path alloc_name alloc_ext kmod comp name ext */
67 T("x.ko.gz", true , true , true, true, "[x]", "gz");
68 T("x.ko.gz", false , true , true, true, NULL , "gz");
69 T("x.ko.gz", true , false , true, true, "[x]", NULL);
70 T("x.ko.gz", false , false , true, true, NULL , NULL);
71
72 return 0;
73}
diff --git a/tools/perf/tests/make b/tools/perf/tests/make
index 75709d2b17b4..bff85324f799 100644
--- a/tools/perf/tests/make
+++ b/tools/perf/tests/make
@@ -5,7 +5,7 @@ include config/Makefile.arch
5 5
6# FIXME looks like x86 is the only arch running tests ;-) 6# FIXME looks like x86 is the only arch running tests ;-)
7# we need some IS_(32/64) flag to make this generic 7# we need some IS_(32/64) flag to make this generic
8ifeq ($(IS_X86_64),1) 8ifeq ($(ARCH)$(IS_64_BIT), x861)
9lib = lib64 9lib = lib64
10else 10else
11lib = lib 11lib = lib
diff --git a/tools/perf/tests/open-syscall-all-cpus.c b/tools/perf/tests/open-syscall-all-cpus.c
index 8fa82d1700c7..3ec885c48f8f 100644
--- a/tools/perf/tests/open-syscall-all-cpus.c
+++ b/tools/perf/tests/open-syscall-all-cpus.c
@@ -29,7 +29,12 @@ int test__open_syscall_event_on_all_cpus(void)
29 29
30 evsel = perf_evsel__newtp("syscalls", "sys_enter_open"); 30 evsel = perf_evsel__newtp("syscalls", "sys_enter_open");
31 if (evsel == NULL) { 31 if (evsel == NULL) {
32 pr_debug("is debugfs mounted on /sys/kernel/debug?\n"); 32 if (tracefs_configured())
33 pr_debug("is tracefs mounted on /sys/kernel/tracing?\n");
34 else if (debugfs_configured())
35 pr_debug("is debugfs mounted on /sys/kernel/debug?\n");
36 else
37 pr_debug("Neither tracefs or debugfs is enabled in this kernel\n");
33 goto out_thread_map_delete; 38 goto out_thread_map_delete;
34 } 39 }
35 40
diff --git a/tools/perf/tests/open-syscall.c b/tools/perf/tests/open-syscall.c
index a33b2daae40f..07aa319bf334 100644
--- a/tools/perf/tests/open-syscall.c
+++ b/tools/perf/tests/open-syscall.c
@@ -18,7 +18,12 @@ int test__open_syscall_event(void)
18 18
19 evsel = perf_evsel__newtp("syscalls", "sys_enter_open"); 19 evsel = perf_evsel__newtp("syscalls", "sys_enter_open");
20 if (evsel == NULL) { 20 if (evsel == NULL) {
21 pr_debug("is debugfs mounted on /sys/kernel/debug?\n"); 21 if (tracefs_configured())
22 pr_debug("is tracefs mounted on /sys/kernel/tracing?\n");
23 else if (debugfs_configured())
24 pr_debug("is debugfs mounted on /sys/kernel/debug?\n");
25 else
26 pr_debug("Neither tracefs or debugfs is enabled in this kernel\n");
22 goto out_thread_map_delete; 27 goto out_thread_map_delete;
23 } 28 }
24 29
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c
index 1cdab0ce00e2..ac243ebcb20a 100644
--- a/tools/perf/tests/parse-events.c
+++ b/tools/perf/tests/parse-events.c
@@ -3,6 +3,7 @@
3#include "evsel.h" 3#include "evsel.h"
4#include "evlist.h" 4#include "evlist.h"
5#include <api/fs/fs.h> 5#include <api/fs/fs.h>
6#include <api/fs/tracefs.h>
6#include <api/fs/debugfs.h> 7#include <api/fs/debugfs.h>
7#include "tests.h" 8#include "tests.h"
8#include "debug.h" 9#include "debug.h"
@@ -1192,11 +1193,19 @@ static int count_tracepoints(void)
1192{ 1193{
1193 char events_path[PATH_MAX]; 1194 char events_path[PATH_MAX];
1194 struct dirent *events_ent; 1195 struct dirent *events_ent;
1196 const char *mountpoint;
1195 DIR *events_dir; 1197 DIR *events_dir;
1196 int cnt = 0; 1198 int cnt = 0;
1197 1199
1198 scnprintf(events_path, PATH_MAX, "%s/tracing/events", 1200 mountpoint = tracefs_find_mountpoint();
1199 debugfs_find_mountpoint()); 1201 if (mountpoint) {
1202 scnprintf(events_path, PATH_MAX, "%s/events",
1203 mountpoint);
1204 } else {
1205 mountpoint = debugfs_find_mountpoint();
1206 scnprintf(events_path, PATH_MAX, "%s/tracing/events",
1207 mountpoint);
1208 }
1200 1209
1201 events_dir = opendir(events_path); 1210 events_dir = opendir(events_path);
1202 1211
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);
51int test__switch_tracking(void); 51int test__switch_tracking(void);
52int test__fdarray__filter(void); 52int test__fdarray__filter(void);
53int test__fdarray__add(void); 53int test__fdarray__add(void);
54int test__kmod_path__parse(void);
54 55
55#if defined(__x86_64__) || defined(__i386__) || defined(__arm__) 56#if defined(__x86_64__) || defined(__i386__) || defined(__arm__)
56#ifdef HAVE_DWARF_UNWIND_SUPPORT 57#ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/ui/Build b/tools/perf/ui/Build
new file mode 100644
index 000000000000..0a73538c0441
--- /dev/null
+++ b/tools/perf/ui/Build
@@ -0,0 +1,14 @@
1libperf-y += setup.o
2libperf-y += helpline.o
3libperf-y += progress.o
4libperf-y += util.o
5libperf-y += hist.o
6libperf-y += stdio/hist.o
7
8CFLAGS_setup.o += -DLIBDIR="BUILD_STR($(LIBDIR))"
9
10libperf-$(CONFIG_SLANG) += browser.o
11libperf-$(CONFIG_SLANG) += browsers/
12libperf-$(CONFIG_SLANG) += tui/
13
14CFLAGS_browser.o += -DENABLE_SLFUTURE_CONST
diff --git a/tools/perf/ui/browsers/Build b/tools/perf/ui/browsers/Build
new file mode 100644
index 000000000000..de223f5bed58
--- /dev/null
+++ b/tools/perf/ui/browsers/Build
@@ -0,0 +1,10 @@
1libperf-y += annotate.o
2libperf-y += hists.o
3libperf-y += map.o
4libperf-y += scripts.o
5libperf-y += header.o
6
7CFLAGS_annotate.o += -DENABLE_SLFUTURE_CONST
8CFLAGS_hists.o += -DENABLE_SLFUTURE_CONST
9CFLAGS_map.o += -DENABLE_SLFUTURE_CONST
10CFLAGS_scripts.o += -DENABLE_SLFUTURE_CONST
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index 9d32e3c0cfee..e5250eb2dd57 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -829,10 +829,16 @@ out:
829 return key; 829 return key;
830} 830}
831 831
832int map_symbol__tui_annotate(struct map_symbol *ms, struct perf_evsel *evsel,
833 struct hist_browser_timer *hbt)
834{
835 return symbol__tui_annotate(ms->sym, ms->map, evsel, hbt);
836}
837
832int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel, 838int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel,
833 struct hist_browser_timer *hbt) 839 struct hist_browser_timer *hbt)
834{ 840{
835 return symbol__tui_annotate(he->ms.sym, he->ms.map, evsel, hbt); 841 return map_symbol__tui_annotate(&he->ms, evsel, hbt);
836} 842}
837 843
838static void annotate_browser__mark_jump_targets(struct annotate_browser *browser, 844static void annotate_browser__mark_jump_targets(struct annotate_browser *browser,
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 788506eef567..995b7a8596b1 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -48,6 +48,24 @@ static bool hist_browser__has_filter(struct hist_browser *hb)
48 return hists__has_filter(hb->hists) || hb->min_pcnt; 48 return hists__has_filter(hb->hists) || hb->min_pcnt;
49} 49}
50 50
51static int hist_browser__get_folding(struct hist_browser *browser)
52{
53 struct rb_node *nd;
54 struct hists *hists = browser->hists;
55 int unfolded_rows = 0;
56
57 for (nd = rb_first(&hists->entries);
58 (nd = hists__filter_entries(nd, browser->min_pcnt)) != NULL;
59 nd = rb_next(nd)) {
60 struct hist_entry *he =
61 rb_entry(nd, struct hist_entry, rb_node);
62
63 if (he->ms.unfolded)
64 unfolded_rows += he->nr_rows;
65 }
66 return unfolded_rows;
67}
68
51static u32 hist_browser__nr_entries(struct hist_browser *hb) 69static u32 hist_browser__nr_entries(struct hist_browser *hb)
52{ 70{
53 u32 nr_entries; 71 u32 nr_entries;
@@ -57,6 +75,7 @@ static u32 hist_browser__nr_entries(struct hist_browser *hb)
57 else 75 else
58 nr_entries = hb->hists->nr_entries; 76 nr_entries = hb->hists->nr_entries;
59 77
78 hb->nr_callchain_rows = hist_browser__get_folding(hb);
60 return nr_entries + hb->nr_callchain_rows; 79 return nr_entries + hb->nr_callchain_rows;
61} 80}
62 81
@@ -492,6 +511,7 @@ static void hist_browser__show_callchain_entry(struct hist_browser *browser,
492{ 511{
493 int color, width; 512 int color, width;
494 char folded_sign = callchain_list__folded(chain); 513 char folded_sign = callchain_list__folded(chain);
514 bool show_annotated = browser->show_dso && chain->ms.sym && symbol__annotation(chain->ms.sym)->src;
495 515
496 color = HE_COLORSET_NORMAL; 516 color = HE_COLORSET_NORMAL;
497 width = browser->b.width - (offset + 2); 517 width = browser->b.width - (offset + 2);
@@ -504,7 +524,8 @@ static void hist_browser__show_callchain_entry(struct hist_browser *browser,
504 ui_browser__set_color(&browser->b, color); 524 ui_browser__set_color(&browser->b, color);
505 hist_browser__gotorc(browser, row, 0); 525 hist_browser__gotorc(browser, row, 0);
506 slsmg_write_nstring(" ", offset); 526 slsmg_write_nstring(" ", offset);
507 slsmg_printf("%c ", folded_sign); 527 slsmg_printf("%c", folded_sign);
528 ui_browser__write_graph(&browser->b, show_annotated ? SLSMG_RARROW_CHAR : ' ');
508 slsmg_write_nstring(str, width); 529 slsmg_write_nstring(str, width);
509} 530}
510 531
@@ -1467,7 +1488,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1467 perf_hpp__set_user_width(symbol_conf.col_width_list_str); 1488 perf_hpp__set_user_width(symbol_conf.col_width_list_str);
1468 1489
1469 while (1) { 1490 while (1) {
1470 const struct thread *thread = NULL; 1491 struct thread *thread = NULL;
1471 const struct dso *dso = NULL; 1492 const struct dso *dso = NULL;
1472 int choice = 0, 1493 int choice = 0,
1473 annotate = -2, zoom_dso = -2, zoom_thread = -2, 1494 annotate = -2, zoom_dso = -2, zoom_thread = -2,
@@ -1593,28 +1614,30 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1593 if (!sort__has_sym) 1614 if (!sort__has_sym)
1594 goto add_exit_option; 1615 goto add_exit_option;
1595 1616
1617 if (browser->selection == NULL)
1618 goto skip_annotation;
1619
1596 if (sort__mode == SORT_MODE__BRANCH) { 1620 if (sort__mode == SORT_MODE__BRANCH) {
1597 bi = browser->he_selection->branch_info; 1621 bi = browser->he_selection->branch_info;
1598 if (browser->selection != NULL && 1622
1599 bi && 1623 if (bi == NULL)
1600 bi->from.sym != NULL && 1624 goto skip_annotation;
1625
1626 if (bi->from.sym != NULL &&
1601 !bi->from.map->dso->annotate_warned && 1627 !bi->from.map->dso->annotate_warned &&
1602 asprintf(&options[nr_options], "Annotate %s", 1628 asprintf(&options[nr_options], "Annotate %s", bi->from.sym->name) > 0) {
1603 bi->from.sym->name) > 0)
1604 annotate_f = nr_options++; 1629 annotate_f = nr_options++;
1630 }
1605 1631
1606 if (browser->selection != NULL && 1632 if (bi->to.sym != NULL &&
1607 bi &&
1608 bi->to.sym != NULL &&
1609 !bi->to.map->dso->annotate_warned && 1633 !bi->to.map->dso->annotate_warned &&
1610 (bi->to.sym != bi->from.sym || 1634 (bi->to.sym != bi->from.sym ||
1611 bi->to.map->dso != bi->from.map->dso) && 1635 bi->to.map->dso != bi->from.map->dso) &&
1612 asprintf(&options[nr_options], "Annotate %s", 1636 asprintf(&options[nr_options], "Annotate %s", bi->to.sym->name) > 0) {
1613 bi->to.sym->name) > 0)
1614 annotate_t = nr_options++; 1637 annotate_t = nr_options++;
1638 }
1615 } else { 1639 } else {
1616 if (browser->selection != NULL && 1640 if (browser->selection->sym != NULL &&
1617 browser->selection->sym != NULL &&
1618 !browser->selection->map->dso->annotate_warned) { 1641 !browser->selection->map->dso->annotate_warned) {
1619 struct annotation *notes; 1642 struct annotation *notes;
1620 1643
@@ -1622,11 +1645,12 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1622 1645
1623 if (notes->src && 1646 if (notes->src &&
1624 asprintf(&options[nr_options], "Annotate %s", 1647 asprintf(&options[nr_options], "Annotate %s",
1625 browser->selection->sym->name) > 0) 1648 browser->selection->sym->name) > 0) {
1626 annotate = nr_options++; 1649 annotate = nr_options++;
1650 }
1627 } 1651 }
1628 } 1652 }
1629 1653skip_annotation:
1630 if (thread != NULL && 1654 if (thread != NULL &&
1631 asprintf(&options[nr_options], "Zoom %s %s(%d) thread", 1655 asprintf(&options[nr_options], "Zoom %s %s(%d) thread",
1632 (browser->hists->thread_filter ? "out of" : "into"), 1656 (browser->hists->thread_filter ? "out of" : "into"),
@@ -1682,6 +1706,7 @@ retry_popup_menu:
1682 if (choice == annotate || choice == annotate_t || choice == annotate_f) { 1706 if (choice == annotate || choice == annotate_t || choice == annotate_f) {
1683 struct hist_entry *he; 1707 struct hist_entry *he;
1684 struct annotation *notes; 1708 struct annotation *notes;
1709 struct map_symbol ms;
1685 int err; 1710 int err;
1686do_annotate: 1711do_annotate:
1687 if (!objdump_path && perf_session_env__lookup_objdump(env)) 1712 if (!objdump_path && perf_session_env__lookup_objdump(env))
@@ -1691,30 +1716,21 @@ do_annotate:
1691 if (he == NULL) 1716 if (he == NULL)
1692 continue; 1717 continue;
1693 1718
1694 /*
1695 * we stash the branch_info symbol + map into the
1696 * the ms so we don't have to rewrite all the annotation
1697 * code to use branch_info.
1698 * in branch mode, the ms struct is not used
1699 */
1700 if (choice == annotate_f) { 1719 if (choice == annotate_f) {
1701 he->ms.sym = he->branch_info->from.sym; 1720 ms.map = he->branch_info->from.map;
1702 he->ms.map = he->branch_info->from.map; 1721 ms.sym = he->branch_info->from.sym;
1703 } else if (choice == annotate_t) { 1722 } else if (choice == annotate_t) {
1704 he->ms.sym = he->branch_info->to.sym; 1723 ms.map = he->branch_info->to.map;
1705 he->ms.map = he->branch_info->to.map; 1724 ms.sym = he->branch_info->to.sym;
1725 } else {
1726 ms = *browser->selection;
1706 } 1727 }
1707 1728
1708 notes = symbol__annotation(he->ms.sym); 1729 notes = symbol__annotation(ms.sym);
1709 if (!notes->src) 1730 if (!notes->src)
1710 continue; 1731 continue;
1711 1732
1712 /* 1733 err = map_symbol__tui_annotate(&ms, evsel, hbt);
1713 * Don't let this be freed, say, by hists__decay_entry.
1714 */
1715 he->used = true;
1716 err = hist_entry__tui_annotate(he, evsel, hbt);
1717 he->used = false;
1718 /* 1734 /*
1719 * offer option to annotate the other branch source or target 1735 * offer option to annotate the other branch source or target
1720 * (if they exists) when returning from annotate 1736 * (if they exists) when returning from annotate
@@ -1754,13 +1770,13 @@ zoom_thread:
1754 pstack__remove(fstack, &browser->hists->thread_filter); 1770 pstack__remove(fstack, &browser->hists->thread_filter);
1755zoom_out_thread: 1771zoom_out_thread:
1756 ui_helpline__pop(); 1772 ui_helpline__pop();
1757 browser->hists->thread_filter = NULL; 1773 thread__zput(browser->hists->thread_filter);
1758 perf_hpp__set_elide(HISTC_THREAD, false); 1774 perf_hpp__set_elide(HISTC_THREAD, false);
1759 } else { 1775 } else {
1760 ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s(%d) thread\"", 1776 ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s(%d) thread\"",
1761 thread->comm_set ? thread__comm_str(thread) : "", 1777 thread->comm_set ? thread__comm_str(thread) : "",
1762 thread->tid); 1778 thread->tid);
1763 browser->hists->thread_filter = thread; 1779 browser->hists->thread_filter = thread__get(thread);
1764 perf_hpp__set_elide(HISTC_THREAD, false); 1780 perf_hpp__set_elide(HISTC_THREAD, false);
1765 pstack__push(fstack, &browser->hists->thread_filter); 1781 pstack__push(fstack, &browser->hists->thread_filter);
1766 } 1782 }
diff --git a/tools/perf/ui/gtk/Build b/tools/perf/ui/gtk/Build
new file mode 100644
index 000000000000..ec22e899a224
--- /dev/null
+++ b/tools/perf/ui/gtk/Build
@@ -0,0 +1,9 @@
1CFLAGS_gtk += -fPIC $(GTK_CFLAGS)
2
3gtk-y += browser.o
4gtk-y += hists.o
5gtk-y += setup.o
6gtk-y += util.o
7gtk-y += helpline.o
8gtk-y += progress.o
9gtk-y += annotate.o
diff --git a/tools/perf/ui/tui/Build b/tools/perf/ui/tui/Build
new file mode 100644
index 000000000000..9e4c6ca41a9f
--- /dev/null
+++ b/tools/perf/ui/tui/Build
@@ -0,0 +1,4 @@
1libperf-y += setup.o
2libperf-y += util.o
3libperf-y += helpline.o
4libperf-y += progress.o
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
new file mode 100644
index 000000000000..797490a40075
--- /dev/null
+++ b/tools/perf/util/Build
@@ -0,0 +1,145 @@
1libperf-y += abspath.o
2libperf-y += alias.o
3libperf-y += annotate.o
4libperf-y += build-id.o
5libperf-y += config.o
6libperf-y += ctype.o
7libperf-y += db-export.o
8libperf-y += environment.o
9libperf-y += event.o
10libperf-y += evlist.o
11libperf-y += evsel.o
12libperf-y += exec_cmd.o
13libperf-y += find_next_bit.o
14libperf-y += help.o
15libperf-y += kallsyms.o
16libperf-y += levenshtein.o
17libperf-y += parse-options.o
18libperf-y += parse-events.o
19libperf-y += path.o
20libperf-y += rbtree.o
21libperf-y += bitmap.o
22libperf-y += hweight.o
23libperf-y += run-command.o
24libperf-y += quote.o
25libperf-y += strbuf.o
26libperf-y += string.o
27libperf-y += strlist.o
28libperf-y += strfilter.o
29libperf-y += top.o
30libperf-y += usage.o
31libperf-y += wrapper.o
32libperf-y += sigchain.o
33libperf-y += dso.o
34libperf-y += symbol.o
35libperf-y += color.o
36libperf-y += pager.o
37libperf-y += header.o
38libperf-y += callchain.o
39libperf-y += values.o
40libperf-y += debug.o
41libperf-y += machine.o
42libperf-y += map.o
43libperf-y += pstack.o
44libperf-y += session.o
45libperf-y += ordered-events.o
46libperf-y += comm.o
47libperf-y += thread.o
48libperf-y += thread_map.o
49libperf-y += trace-event-parse.o
50libperf-y += parse-events-flex.o
51libperf-y += parse-events-bison.o
52libperf-y += pmu.o
53libperf-y += pmu-flex.o
54libperf-y += pmu-bison.o
55libperf-y += trace-event-read.o
56libperf-y += trace-event-info.o
57libperf-y += trace-event-scripting.o
58libperf-y += trace-event.o
59libperf-y += svghelper.o
60libperf-y += sort.o
61libperf-y += hist.o
62libperf-y += util.o
63libperf-y += xyarray.o
64libperf-y += cpumap.o
65libperf-y += cgroup.o
66libperf-y += target.o
67libperf-y += rblist.o
68libperf-y += intlist.o
69libperf-y += vdso.o
70libperf-y += stat.o
71libperf-y += record.o
72libperf-y += srcline.o
73libperf-y += data.o
74libperf-$(CONFIG_X86) += tsc.o
75libperf-y += cloexec.o
76libperf-y += thread-stack.o
77
78libperf-$(CONFIG_LIBELF) += symbol-elf.o
79libperf-$(CONFIG_LIBELF) += probe-event.o
80
81ifndef CONFIG_LIBELF
82libperf-y += symbol-minimal.o
83endif
84
85libperf-$(CONFIG_DWARF) += probe-finder.o
86libperf-$(CONFIG_DWARF) += dwarf-aux.o
87
88libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
89libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o
90
91libperf-$(CONFIG_LIBBABELTRACE) += data-convert-bt.o
92
93libperf-y += scripting-engines/
94
95libperf-$(CONFIG_PERF_REGS) += perf_regs.o
96libperf-$(CONFIG_ZLIB) += zlib.o
97libperf-$(CONFIG_LZMA) += lzma.o
98
99CFLAGS_config.o += -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))"
100CFLAGS_exec_cmd.o += -DPERF_EXEC_PATH="BUILD_STR($(perfexecdir_SQ))" -DPREFIX="BUILD_STR($(prefix_SQ))"
101
102$(OUTPUT)util/parse-events-flex.c: util/parse-events.l $(OUTPUT)util/parse-events-bison.c
103 $(call rule_mkdir)
104 @$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) util/parse-events.l
105
106$(OUTPUT)util/parse-events-bison.c: util/parse-events.y
107 $(call rule_mkdir)
108 @$(call echo-cmd,bison)$(BISON) -v util/parse-events.y -d $(PARSER_DEBUG_BISON) -o $@ -p parse_events_
109
110$(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c
111 $(call rule_mkdir)
112 @$(call echo-cmd,flex)$(FLEX) -o $@ --header-file=$(OUTPUT)util/pmu-flex.h util/pmu.l
113
114$(OUTPUT)util/pmu-bison.c: util/pmu.y
115 $(call rule_mkdir)
116 @$(call echo-cmd,bison)$(BISON) -v util/pmu.y -d -o $@ -p perf_pmu_
117
118CFLAGS_parse-events-flex.o += -w
119CFLAGS_pmu-flex.o += -w
120CFLAGS_parse-events-bison.o += -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w
121CFLAGS_pmu-bison.o += -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w
122
123$(OUTPUT)util/parse-events.o: $(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-bison.c
124$(OUTPUT)util/pmu.o: $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-bison.c
125
126CFLAGS_find_next_bit.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))"
127CFLAGS_rbtree.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))"
128CFLAGS_hweight.o += -Wno-unused-parameter -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))"
129CFLAGS_parse-events.o += -Wno-redundant-decls
130
131$(OUTPUT)util/kallsyms.o: ../lib/symbol/kallsyms.c FORCE
132 $(call rule_mkdir)
133 $(call if_changed_dep,cc_o_c)
134
135$(OUTPUT)util/find_next_bit.o: ../lib/util/find_next_bit.c FORCE
136 $(call rule_mkdir)
137 $(call if_changed_dep,cc_o_c)
138
139$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c FORCE
140 $(call rule_mkdir)
141 $(call if_changed_dep,cc_o_c)
142
143$(OUTPUT)util/hweight.o: ../../lib/hweight.c FORCE
144 $(call rule_mkdir)
145 $(call if_changed_dep,cc_o_c)
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 9d9db3b296dd..7f5bdfc9bc87 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -1010,6 +1010,32 @@ fallback:
1010 } 1010 }
1011 filename = symfs_filename; 1011 filename = symfs_filename;
1012 } 1012 }
1013 } else if (dso__needs_decompress(dso)) {
1014 char tmp[PATH_MAX];
1015 struct kmod_path m;
1016 int fd;
1017 bool ret;
1018
1019 if (kmod_path__parse_ext(&m, symfs_filename))
1020 goto out_free_filename;
1021
1022 snprintf(tmp, PATH_MAX, "/tmp/perf-kmod-XXXXXX");
1023
1024 fd = mkstemp(tmp);
1025 if (fd < 0) {
1026 free(m.ext);
1027 goto out_free_filename;
1028 }
1029
1030 ret = decompress_to_file(m.ext, symfs_filename, fd);
1031
1032 free(m.ext);
1033 close(fd);
1034
1035 if (!ret)
1036 goto out_free_filename;
1037
1038 strcpy(symfs_filename, tmp);
1013 } 1039 }
1014 1040
1015 snprintf(command, sizeof(command), 1041 snprintf(command, sizeof(command),
@@ -1029,7 +1055,7 @@ fallback:
1029 1055
1030 file = popen(command, "r"); 1056 file = popen(command, "r");
1031 if (!file) 1057 if (!file)
1032 goto out_free_filename; 1058 goto out_remove_tmp;
1033 1059
1034 while (!feof(file)) 1060 while (!feof(file))
1035 if (symbol__parse_objdump_line(sym, map, file, privsize, 1061 if (symbol__parse_objdump_line(sym, map, file, privsize,
@@ -1044,6 +1070,10 @@ fallback:
1044 delete_last_nop(sym); 1070 delete_last_nop(sym);
1045 1071
1046 pclose(file); 1072 pclose(file);
1073
1074out_remove_tmp:
1075 if (dso__needs_decompress(dso))
1076 unlink(symfs_filename);
1047out_free_filename: 1077out_free_filename:
1048 if (delete_extract) 1078 if (delete_extract)
1049 kcore_extract__delete(&kce); 1079 kcore_extract__delete(&kce);
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 0c72680a977f..f7fb2587df69 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -61,8 +61,9 @@ static int perf_event__exit_del_thread(struct perf_tool *tool __maybe_unused,
61 61
62 if (thread) { 62 if (thread) {
63 rb_erase(&thread->rb_node, &machine->threads); 63 rb_erase(&thread->rb_node, &machine->threads);
64 machine->last_match = NULL; 64 if (machine->last_match == thread)
65 thread__delete(thread); 65 thread__zput(machine->last_match);
66 thread__put(thread);
66 } 67 }
67 68
68 return 0; 69 return 0;
@@ -93,6 +94,35 @@ int build_id__sprintf(const u8 *build_id, int len, char *bf)
93 return raw - build_id; 94 return raw - build_id;
94} 95}
95 96
97/* asnprintf consolidates asprintf and snprintf */
98static int asnprintf(char **strp, size_t size, const char *fmt, ...)
99{
100 va_list ap;
101 int ret;
102
103 if (!strp)
104 return -EINVAL;
105
106 va_start(ap, fmt);
107 if (*strp)
108 ret = vsnprintf(*strp, size, fmt, ap);
109 else
110 ret = vasprintf(strp, fmt, ap);
111 va_end(ap);
112
113 return ret;
114}
115
116static char *build_id__filename(const char *sbuild_id, char *bf, size_t size)
117{
118 char *tmp = bf;
119 int ret = asnprintf(&bf, size, "%s/.build-id/%.2s/%s", buildid_dir,
120 sbuild_id, sbuild_id + 2);
121 if (ret < 0 || (tmp && size < (unsigned int)ret))
122 return NULL;
123 return bf;
124}
125
96char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size) 126char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size)
97{ 127{
98 char build_id_hex[BUILD_ID_SIZE * 2 + 1]; 128 char build_id_hex[BUILD_ID_SIZE * 2 + 1];
@@ -101,14 +131,7 @@ char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size)
101 return NULL; 131 return NULL;
102 132
103 build_id__sprintf(dso->build_id, sizeof(dso->build_id), build_id_hex); 133 build_id__sprintf(dso->build_id, sizeof(dso->build_id), build_id_hex);
104 if (bf == NULL) { 134 return build_id__filename(build_id_hex, bf, size);
105 if (asprintf(&bf, "%s/.build-id/%.2s/%s", buildid_dir,
106 build_id_hex, build_id_hex + 2) < 0)
107 return NULL;
108 } else
109 snprintf(bf, size, "%s/.build-id/%.2s/%s", buildid_dir,
110 build_id_hex, build_id_hex + 2);
111 return bf;
112} 135}
113 136
114#define dsos__for_each_with_build_id(pos, head) \ 137#define dsos__for_each_with_build_id(pos, head) \
@@ -259,52 +282,113 @@ void disable_buildid_cache(void)
259 no_buildid_cache = true; 282 no_buildid_cache = true;
260} 283}
261 284
262int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, 285static char *build_id_cache__dirname_from_path(const char *name,
263 const char *name, bool is_kallsyms, bool is_vdso) 286 bool is_kallsyms, bool is_vdso)
264{ 287{
265 const size_t size = PATH_MAX; 288 char *realname = (char *)name, *filename;
266 char *realname, *filename = zalloc(size),
267 *linkname = zalloc(size), *targetname;
268 int len, err = -1;
269 bool slash = is_kallsyms || is_vdso; 289 bool slash = is_kallsyms || is_vdso;
270 290
271 if (is_kallsyms) { 291 if (!slash) {
272 if (symbol_conf.kptr_restrict) { 292 realname = realpath(name, NULL);
273 pr_debug("Not caching a kptr_restrict'ed /proc/kallsyms\n"); 293 if (!realname)
274 err = 0; 294 return NULL;
275 goto out_free; 295 }
276 } 296
277 realname = (char *) name; 297 if (asprintf(&filename, "%s%s%s", buildid_dir, slash ? "/" : "",
278 } else 298 is_vdso ? DSO__NAME_VDSO : realname) < 0)
299 filename = NULL;
300
301 if (!slash)
302 free(realname);
303
304 return filename;
305}
306
307int build_id_cache__list_build_ids(const char *pathname,
308 struct strlist **result)
309{
310 struct strlist *list;
311 char *dir_name;
312 DIR *dir;
313 struct dirent *d;
314 int ret = 0;
315
316 list = strlist__new(true, NULL);
317 dir_name = build_id_cache__dirname_from_path(pathname, false, false);
318 if (!list || !dir_name) {
319 ret = -ENOMEM;
320 goto out;
321 }
322
323 /* List up all dirents */
324 dir = opendir(dir_name);
325 if (!dir) {
326 ret = -errno;
327 goto out;
328 }
329
330 while ((d = readdir(dir)) != NULL) {
331 if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
332 continue;
333 strlist__add(list, d->d_name);
334 }
335 closedir(dir);
336
337out:
338 free(dir_name);
339 if (ret)
340 strlist__delete(list);
341 else
342 *result = list;
343
344 return ret;
345}
346
347int build_id_cache__add_s(const char *sbuild_id, const char *name,
348 bool is_kallsyms, bool is_vdso)
349{
350 const size_t size = PATH_MAX;
351 char *realname = NULL, *filename = NULL, *dir_name = NULL,
352 *linkname = zalloc(size), *targetname, *tmp;
353 int err = -1;
354
355 if (!is_kallsyms) {
279 realname = realpath(name, NULL); 356 realname = realpath(name, NULL);
357 if (!realname)
358 goto out_free;
359 }
280 360
281 if (realname == NULL || filename == NULL || linkname == NULL) 361 dir_name = build_id_cache__dirname_from_path(name, is_kallsyms, is_vdso);
362 if (!dir_name)
282 goto out_free; 363 goto out_free;
283 364
284 len = scnprintf(filename, size, "%s%s%s", 365 if (mkdir_p(dir_name, 0755))
285 debugdir, slash ? "/" : "",
286 is_vdso ? DSO__NAME_VDSO : realname);
287 if (mkdir_p(filename, 0755))
288 goto out_free; 366 goto out_free;
289 367
290 snprintf(filename + len, size - len, "/%s", sbuild_id); 368 if (asprintf(&filename, "%s/%s", dir_name, sbuild_id) < 0) {
369 filename = NULL;
370 goto out_free;
371 }
291 372
292 if (access(filename, F_OK)) { 373 if (access(filename, F_OK)) {
293 if (is_kallsyms) { 374 if (is_kallsyms) {
294 if (copyfile("/proc/kallsyms", filename)) 375 if (copyfile("/proc/kallsyms", filename))
295 goto out_free; 376 goto out_free;
296 } else if (link(realname, filename) && copyfile(name, filename)) 377 } else if (link(realname, filename) && errno != EEXIST &&
378 copyfile(name, filename))
297 goto out_free; 379 goto out_free;
298 } 380 }
299 381
300 len = scnprintf(linkname, size, "%s/.build-id/%.2s", 382 if (!build_id__filename(sbuild_id, linkname, size))
301 debugdir, sbuild_id); 383 goto out_free;
384 tmp = strrchr(linkname, '/');
385 *tmp = '\0';
302 386
303 if (access(linkname, X_OK) && mkdir_p(linkname, 0755)) 387 if (access(linkname, X_OK) && mkdir_p(linkname, 0755))
304 goto out_free; 388 goto out_free;
305 389
306 snprintf(linkname + len, size - len, "/%s", sbuild_id + 2); 390 *tmp = '/';
307 targetname = filename + strlen(debugdir) - 5; 391 targetname = filename + strlen(buildid_dir) - 5;
308 memcpy(targetname, "../..", 5); 392 memcpy(targetname, "../..", 5);
309 393
310 if (symlink(targetname, linkname) == 0) 394 if (symlink(targetname, linkname) == 0)
@@ -313,34 +397,46 @@ out_free:
313 if (!is_kallsyms) 397 if (!is_kallsyms)
314 free(realname); 398 free(realname);
315 free(filename); 399 free(filename);
400 free(dir_name);
316 free(linkname); 401 free(linkname);
317 return err; 402 return err;
318} 403}
319 404
320static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size, 405static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size,
321 const char *name, const char *debugdir, 406 const char *name, bool is_kallsyms,
322 bool is_kallsyms, bool is_vdso) 407 bool is_vdso)
323{ 408{
324 char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 409 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
325 410
326 build_id__sprintf(build_id, build_id_size, sbuild_id); 411 build_id__sprintf(build_id, build_id_size, sbuild_id);
327 412
328 return build_id_cache__add_s(sbuild_id, debugdir, name, 413 return build_id_cache__add_s(sbuild_id, name, is_kallsyms, is_vdso);
329 is_kallsyms, is_vdso); 414}
415
416bool build_id_cache__cached(const char *sbuild_id)
417{
418 bool ret = false;
419 char *filename = build_id__filename(sbuild_id, NULL, 0);
420
421 if (filename && !access(filename, F_OK))
422 ret = true;
423 free(filename);
424
425 return ret;
330} 426}
331 427
332int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir) 428int build_id_cache__remove_s(const char *sbuild_id)
333{ 429{
334 const size_t size = PATH_MAX; 430 const size_t size = PATH_MAX;
335 char *filename = zalloc(size), 431 char *filename = zalloc(size),
336 *linkname = zalloc(size); 432 *linkname = zalloc(size), *tmp;
337 int err = -1; 433 int err = -1;
338 434
339 if (filename == NULL || linkname == NULL) 435 if (filename == NULL || linkname == NULL)
340 goto out_free; 436 goto out_free;
341 437
342 snprintf(linkname, size, "%s/.build-id/%.2s/%s", 438 if (!build_id__filename(sbuild_id, linkname, size))
343 debugdir, sbuild_id, sbuild_id + 2); 439 goto out_free;
344 440
345 if (access(linkname, F_OK)) 441 if (access(linkname, F_OK))
346 goto out_free; 442 goto out_free;
@@ -354,8 +450,8 @@ int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir)
354 /* 450 /*
355 * Since the link is relative, we must make it absolute: 451 * Since the link is relative, we must make it absolute:
356 */ 452 */
357 snprintf(linkname, size, "%s/.build-id/%.2s/%s", 453 tmp = strrchr(linkname, '/') + 1;
358 debugdir, sbuild_id, filename); 454 snprintf(tmp, size - (tmp - linkname), "%s", filename);
359 455
360 if (unlink(linkname)) 456 if (unlink(linkname))
361 goto out_free; 457 goto out_free;
@@ -367,8 +463,7 @@ out_free:
367 return err; 463 return err;
368} 464}
369 465
370static int dso__cache_build_id(struct dso *dso, struct machine *machine, 466static int dso__cache_build_id(struct dso *dso, struct machine *machine)
371 const char *debugdir)
372{ 467{
373 bool is_kallsyms = dso->kernel && dso->long_name[0] != '/'; 468 bool is_kallsyms = dso->kernel && dso->long_name[0] != '/';
374 bool is_vdso = dso__is_vdso(dso); 469 bool is_vdso = dso__is_vdso(dso);
@@ -381,28 +476,26 @@ static int dso__cache_build_id(struct dso *dso, struct machine *machine,
381 name = nm; 476 name = nm;
382 } 477 }
383 return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id), name, 478 return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id), name,
384 debugdir, is_kallsyms, is_vdso); 479 is_kallsyms, is_vdso);
385} 480}
386 481
387static int __dsos__cache_build_ids(struct list_head *head, 482static int __dsos__cache_build_ids(struct list_head *head,
388 struct machine *machine, const char *debugdir) 483 struct machine *machine)
389{ 484{
390 struct dso *pos; 485 struct dso *pos;
391 int err = 0; 486 int err = 0;
392 487
393 dsos__for_each_with_build_id(pos, head) 488 dsos__for_each_with_build_id(pos, head)
394 if (dso__cache_build_id(pos, machine, debugdir)) 489 if (dso__cache_build_id(pos, machine))
395 err = -1; 490 err = -1;
396 491
397 return err; 492 return err;
398} 493}
399 494
400static int machine__cache_build_ids(struct machine *machine, const char *debugdir) 495static int machine__cache_build_ids(struct machine *machine)
401{ 496{
402 int ret = __dsos__cache_build_ids(&machine->kernel_dsos.head, machine, 497 int ret = __dsos__cache_build_ids(&machine->kernel_dsos.head, machine);
403 debugdir); 498 ret |= __dsos__cache_build_ids(&machine->user_dsos.head, machine);
404 ret |= __dsos__cache_build_ids(&machine->user_dsos.head, machine,
405 debugdir);
406 return ret; 499 return ret;
407} 500}
408 501
@@ -417,11 +510,11 @@ int perf_session__cache_build_ids(struct perf_session *session)
417 if (mkdir(buildid_dir, 0755) != 0 && errno != EEXIST) 510 if (mkdir(buildid_dir, 0755) != 0 && errno != EEXIST)
418 return -1; 511 return -1;
419 512
420 ret = machine__cache_build_ids(&session->machines.host, buildid_dir); 513 ret = machine__cache_build_ids(&session->machines.host);
421 514
422 for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) { 515 for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
423 struct machine *pos = rb_entry(nd, struct machine, rb_node); 516 struct machine *pos = rb_entry(nd, struct machine, rb_node);
424 ret |= machine__cache_build_ids(pos, buildid_dir); 517 ret |= machine__cache_build_ids(pos);
425 } 518 }
426 return ret ? -1 : 0; 519 return ret ? -1 : 0;
427} 520}
diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h
index 8236319514d5..85011222cc14 100644
--- a/tools/perf/util/build-id.h
+++ b/tools/perf/util/build-id.h
@@ -4,6 +4,7 @@
4#define BUILD_ID_SIZE 20 4#define BUILD_ID_SIZE 20
5 5
6#include "tool.h" 6#include "tool.h"
7#include "strlist.h"
7#include <linux/types.h> 8#include <linux/types.h>
8 9
9extern struct perf_tool build_id__mark_dso_hit_ops; 10extern struct perf_tool build_id__mark_dso_hit_ops;
@@ -22,9 +23,12 @@ bool perf_session__read_build_ids(struct perf_session *session, bool with_hits);
22int perf_session__write_buildid_table(struct perf_session *session, int fd); 23int perf_session__write_buildid_table(struct perf_session *session, int fd);
23int perf_session__cache_build_ids(struct perf_session *session); 24int perf_session__cache_build_ids(struct perf_session *session);
24 25
25int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, 26int build_id_cache__list_build_ids(const char *pathname,
27 struct strlist **result);
28bool build_id_cache__cached(const char *sbuild_id);
29int build_id_cache__add_s(const char *sbuild_id,
26 const char *name, bool is_kallsyms, bool is_vdso); 30 const char *name, bool is_kallsyms, bool is_vdso);
27int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir); 31int build_id_cache__remove_s(const char *sbuild_id);
28void disable_buildid_cache(void); 32void disable_buildid_cache(void);
29 33
30#endif 34#endif
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index d04d770d90f6..fbcca21d66ab 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -17,6 +17,7 @@
17#define EXEC_PATH_ENVIRONMENT "PERF_EXEC_PATH" 17#define EXEC_PATH_ENVIRONMENT "PERF_EXEC_PATH"
18#define DEFAULT_PERF_DIR_ENVIRONMENT ".perf" 18#define DEFAULT_PERF_DIR_ENVIRONMENT ".perf"
19#define PERF_DEBUGFS_ENVIRONMENT "PERF_DEBUGFS_DIR" 19#define PERF_DEBUGFS_ENVIRONMENT "PERF_DEBUGFS_DIR"
20#define PERF_TRACEFS_ENVIRONMENT "PERF_TRACEFS_DIR"
20 21
21typedef int (*config_fn_t)(const char *, const char *, void *); 22typedef int (*config_fn_t)(const char *, const char *, void *);
22extern int perf_default_config(const char *, const char *, void *); 23extern int perf_default_config(const char *, const char *, void *);
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 14e7a123d43b..9f643ee77001 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -97,6 +97,14 @@ int parse_callchain_record_opt(const char *arg)
97 callchain_param.dump_size = size; 97 callchain_param.dump_size = size;
98 } 98 }
99#endif /* HAVE_DWARF_UNWIND_SUPPORT */ 99#endif /* HAVE_DWARF_UNWIND_SUPPORT */
100 } else if (!strncmp(name, "lbr", sizeof("lbr"))) {
101 if (!strtok_r(NULL, ",", &saveptr)) {
102 callchain_param.record_mode = CALLCHAIN_LBR;
103 ret = 0;
104 } else
105 pr_err("callchain: No more arguments "
106 "needed for --call-graph lbr\n");
107 break;
100 } else { 108 } else {
101 pr_err("callchain: Unknown --call-graph option " 109 pr_err("callchain: Unknown --call-graph option "
102 "value: %s\n", arg); 110 "value: %s\n", arg);
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index c0ec1acc38e4..6033a0a212ca 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -11,6 +11,7 @@ enum perf_call_graph_mode {
11 CALLCHAIN_NONE, 11 CALLCHAIN_NONE,
12 CALLCHAIN_FP, 12 CALLCHAIN_FP,
13 CALLCHAIN_DWARF, 13 CALLCHAIN_DWARF,
14 CALLCHAIN_LBR,
14 CALLCHAIN_MAX 15 CALLCHAIN_MAX
15}; 16};
16 17
diff --git a/tools/perf/util/cloexec.c b/tools/perf/util/cloexec.c
index 6da965bdbc2c..85b523885f9d 100644
--- a/tools/perf/util/cloexec.c
+++ b/tools/perf/util/cloexec.c
@@ -7,6 +7,12 @@
7 7
8static unsigned long flag = PERF_FLAG_FD_CLOEXEC; 8static unsigned long flag = PERF_FLAG_FD_CLOEXEC;
9 9
10int __weak sched_getcpu(void)
11{
12 errno = ENOSYS;
13 return -1;
14}
15
10static int perf_flag_probe(void) 16static int perf_flag_probe(void)
11{ 17{
12 /* use 'safest' configuration as used in perf_evsel__fallback() */ 18 /* use 'safest' configuration as used in perf_evsel__fallback() */
diff --git a/tools/perf/util/cloexec.h b/tools/perf/util/cloexec.h
index 94a5a7d829d5..68888c29b04a 100644
--- a/tools/perf/util/cloexec.h
+++ b/tools/perf/util/cloexec.h
@@ -3,4 +3,10 @@
3 3
4unsigned long perf_event_open_cloexec_flag(void); 4unsigned long perf_event_open_cloexec_flag(void);
5 5
6#ifdef __GLIBC_PREREQ
7#if !__GLIBC_PREREQ(2, 6)
8extern int sched_getcpu(void) __THROW;
9#endif
10#endif
11
6#endif /* __PERF_CLOEXEC_H */ 12#endif /* __PERF_CLOEXEC_H */
diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c
new file mode 100644
index 000000000000..c6d62268cc2a
--- /dev/null
+++ b/tools/perf/util/data-convert-bt.c
@@ -0,0 +1,856 @@
1/*
2 * CTF writing support via babeltrace.
3 *
4 * Copyright (C) 2014, Jiri Olsa <jolsa@redhat.com>
5 * Copyright (C) 2014, Sebastian Andrzej Siewior <bigeasy@linutronix.de>
6 *
7 * Released under the GPL v2. (and only v2, not any later version)
8 */
9
10#include <linux/compiler.h>
11#include <babeltrace/ctf-writer/writer.h>
12#include <babeltrace/ctf-writer/clock.h>
13#include <babeltrace/ctf-writer/stream.h>
14#include <babeltrace/ctf-writer/event.h>
15#include <babeltrace/ctf-writer/event-types.h>
16#include <babeltrace/ctf-writer/event-fields.h>
17#include <babeltrace/ctf/events.h>
18#include <traceevent/event-parse.h>
19#include "asm/bug.h"
20#include "data-convert-bt.h"
21#include "session.h"
22#include "util.h"
23#include "debug.h"
24#include "tool.h"
25#include "evlist.h"
26#include "evsel.h"
27#include "machine.h"
28
29#define pr_N(n, fmt, ...) \
30 eprintf(n, debug_data_convert, fmt, ##__VA_ARGS__)
31
32#define pr(fmt, ...) pr_N(1, pr_fmt(fmt), ##__VA_ARGS__)
33#define pr2(fmt, ...) pr_N(2, pr_fmt(fmt), ##__VA_ARGS__)
34
35#define pr_time2(t, fmt, ...) pr_time_N(2, debug_data_convert, t, pr_fmt(fmt), ##__VA_ARGS__)
36
37struct evsel_priv {
38 struct bt_ctf_event_class *event_class;
39};
40
41struct ctf_writer {
42 /* writer primitives */
43 struct bt_ctf_writer *writer;
44 struct bt_ctf_stream *stream;
45 struct bt_ctf_stream_class *stream_class;
46 struct bt_ctf_clock *clock;
47
48 /* data types */
49 union {
50 struct {
51 struct bt_ctf_field_type *s64;
52 struct bt_ctf_field_type *u64;
53 struct bt_ctf_field_type *s32;
54 struct bt_ctf_field_type *u32;
55 struct bt_ctf_field_type *string;
56 struct bt_ctf_field_type *u64_hex;
57 };
58 struct bt_ctf_field_type *array[6];
59 } data;
60};
61
62struct convert {
63 struct perf_tool tool;
64 struct ctf_writer writer;
65
66 u64 events_size;
67 u64 events_count;
68};
69
70static int value_set(struct bt_ctf_field_type *type,
71 struct bt_ctf_event *event,
72 const char *name, u64 val)
73{
74 struct bt_ctf_field *field;
75 bool sign = bt_ctf_field_type_integer_get_signed(type);
76 int ret;
77
78 field = bt_ctf_field_create(type);
79 if (!field) {
80 pr_err("failed to create a field %s\n", name);
81 return -1;
82 }
83
84 if (sign) {
85 ret = bt_ctf_field_signed_integer_set_value(field, val);
86 if (ret) {
87 pr_err("failed to set field value %s\n", name);
88 goto err;
89 }
90 } else {
91 ret = bt_ctf_field_unsigned_integer_set_value(field, val);
92 if (ret) {
93 pr_err("failed to set field value %s\n", name);
94 goto err;
95 }
96 }
97
98 ret = bt_ctf_event_set_payload(event, name, field);
99 if (ret) {
100 pr_err("failed to set payload %s\n", name);
101 goto err;
102 }
103
104 pr2(" SET [%s = %" PRIu64 "]\n", name, val);
105
106err:
107 bt_ctf_field_put(field);
108 return ret;
109}
110
111#define __FUNC_VALUE_SET(_name, _val_type) \
112static __maybe_unused int value_set_##_name(struct ctf_writer *cw, \
113 struct bt_ctf_event *event, \
114 const char *name, \
115 _val_type val) \
116{ \
117 struct bt_ctf_field_type *type = cw->data._name; \
118 return value_set(type, event, name, (u64) val); \
119}
120
121#define FUNC_VALUE_SET(_name) __FUNC_VALUE_SET(_name, _name)
122
123FUNC_VALUE_SET(s32)
124FUNC_VALUE_SET(u32)
125FUNC_VALUE_SET(s64)
126FUNC_VALUE_SET(u64)
127__FUNC_VALUE_SET(u64_hex, u64)
128
129static struct bt_ctf_field_type*
130get_tracepoint_field_type(struct ctf_writer *cw, struct format_field *field)
131{
132 unsigned long flags = field->flags;
133
134 if (flags & FIELD_IS_STRING)
135 return cw->data.string;
136
137 if (!(flags & FIELD_IS_SIGNED)) {
138 /* unsigned long are mostly pointers */
139 if (flags & FIELD_IS_LONG || flags & FIELD_IS_POINTER)
140 return cw->data.u64_hex;
141 }
142
143 if (flags & FIELD_IS_SIGNED) {
144 if (field->size == 8)
145 return cw->data.s64;
146 else
147 return cw->data.s32;
148 }
149
150 if (field->size == 8)
151 return cw->data.u64;
152 else
153 return cw->data.u32;
154}
155
156static int add_tracepoint_field_value(struct ctf_writer *cw,
157 struct bt_ctf_event_class *event_class,
158 struct bt_ctf_event *event,
159 struct perf_sample *sample,
160 struct format_field *fmtf)
161{
162 struct bt_ctf_field_type *type;
163 struct bt_ctf_field *array_field;
164 struct bt_ctf_field *field;
165 const char *name = fmtf->name;
166 void *data = sample->raw_data;
167 unsigned long long value_int;
168 unsigned long flags = fmtf->flags;
169 unsigned int n_items;
170 unsigned int i;
171 unsigned int offset;
172 unsigned int len;
173 int ret;
174
175 offset = fmtf->offset;
176 len = fmtf->size;
177 if (flags & FIELD_IS_STRING)
178 flags &= ~FIELD_IS_ARRAY;
179
180 if (flags & FIELD_IS_DYNAMIC) {
181 unsigned long long tmp_val;
182
183 tmp_val = pevent_read_number(fmtf->event->pevent,
184 data + offset, len);
185 offset = tmp_val;
186 len = offset >> 16;
187 offset &= 0xffff;
188 }
189
190 if (flags & FIELD_IS_ARRAY) {
191
192 type = bt_ctf_event_class_get_field_by_name(
193 event_class, name);
194 array_field = bt_ctf_field_create(type);
195 bt_ctf_field_type_put(type);
196 if (!array_field) {
197 pr_err("Failed to create array type %s\n", name);
198 return -1;
199 }
200
201 len = fmtf->size / fmtf->arraylen;
202 n_items = fmtf->arraylen;
203 } else {
204 n_items = 1;
205 array_field = NULL;
206 }
207
208 type = get_tracepoint_field_type(cw, fmtf);
209
210 for (i = 0; i < n_items; i++) {
211 if (!(flags & FIELD_IS_STRING))
212 value_int = pevent_read_number(
213 fmtf->event->pevent,
214 data + offset + i * len, len);
215
216 if (flags & FIELD_IS_ARRAY)
217 field = bt_ctf_field_array_get_field(array_field, i);
218 else
219 field = bt_ctf_field_create(type);
220
221 if (!field) {
222 pr_err("failed to create a field %s\n", name);
223 return -1;
224 }
225
226 if (flags & FIELD_IS_STRING)
227 ret = bt_ctf_field_string_set_value(field,
228 data + offset + i * len);
229 else if (!(flags & FIELD_IS_SIGNED))
230 ret = bt_ctf_field_unsigned_integer_set_value(
231 field, value_int);
232 else
233 ret = bt_ctf_field_signed_integer_set_value(
234 field, value_int);
235 if (ret) {
236 pr_err("failed to set file value %s\n", name);
237 goto err_put_field;
238 }
239 if (!(flags & FIELD_IS_ARRAY)) {
240 ret = bt_ctf_event_set_payload(event, name, field);
241 if (ret) {
242 pr_err("failed to set payload %s\n", name);
243 goto err_put_field;
244 }
245 }
246 bt_ctf_field_put(field);
247 }
248 if (flags & FIELD_IS_ARRAY) {
249 ret = bt_ctf_event_set_payload(event, name, array_field);
250 if (ret) {
251 pr_err("Failed add payload array %s\n", name);
252 return -1;
253 }
254 bt_ctf_field_put(array_field);
255 }
256 return 0;
257
258err_put_field:
259 bt_ctf_field_put(field);
260 return -1;
261}
262
263static int add_tracepoint_fields_values(struct ctf_writer *cw,
264 struct bt_ctf_event_class *event_class,
265 struct bt_ctf_event *event,
266 struct format_field *fields,
267 struct perf_sample *sample)
268{
269 struct format_field *field;
270 int ret;
271
272 for (field = fields; field; field = field->next) {
273 ret = add_tracepoint_field_value(cw, event_class, event, sample,
274 field);
275 if (ret)
276 return -1;
277 }
278 return 0;
279}
280
281static int add_tracepoint_values(struct ctf_writer *cw,
282 struct bt_ctf_event_class *event_class,
283 struct bt_ctf_event *event,
284 struct perf_evsel *evsel,
285 struct perf_sample *sample)
286{
287 struct format_field *common_fields = evsel->tp_format->format.common_fields;
288 struct format_field *fields = evsel->tp_format->format.fields;
289 int ret;
290
291 ret = add_tracepoint_fields_values(cw, event_class, event,
292 common_fields, sample);
293 if (!ret)
294 ret = add_tracepoint_fields_values(cw, event_class, event,
295 fields, sample);
296
297 return ret;
298}
299
300static int add_generic_values(struct ctf_writer *cw,
301 struct bt_ctf_event *event,
302 struct perf_evsel *evsel,
303 struct perf_sample *sample)
304{
305 u64 type = evsel->attr.sample_type;
306 int ret;
307
308 /*
309 * missing:
310 * PERF_SAMPLE_TIME - not needed as we have it in
311 * ctf event header
312 * PERF_SAMPLE_READ - TODO
313 * PERF_SAMPLE_CALLCHAIN - TODO
314 * PERF_SAMPLE_RAW - tracepoint fields are handled separately
315 * PERF_SAMPLE_BRANCH_STACK - TODO
316 * PERF_SAMPLE_REGS_USER - TODO
317 * PERF_SAMPLE_STACK_USER - TODO
318 */
319
320 if (type & PERF_SAMPLE_IP) {
321 ret = value_set_u64_hex(cw, event, "perf_ip", sample->ip);
322 if (ret)
323 return -1;
324 }
325
326 if (type & PERF_SAMPLE_TID) {
327 ret = value_set_s32(cw, event, "perf_tid", sample->tid);
328 if (ret)
329 return -1;
330
331 ret = value_set_s32(cw, event, "perf_pid", sample->pid);
332 if (ret)
333 return -1;
334 }
335
336 if ((type & PERF_SAMPLE_ID) ||
337 (type & PERF_SAMPLE_IDENTIFIER)) {
338 ret = value_set_u64(cw, event, "perf_id", sample->id);
339 if (ret)
340 return -1;
341 }
342
343 if (type & PERF_SAMPLE_STREAM_ID) {
344 ret = value_set_u64(cw, event, "perf_stream_id", sample->stream_id);
345 if (ret)
346 return -1;
347 }
348
349 if (type & PERF_SAMPLE_CPU) {
350 ret = value_set_u32(cw, event, "perf_cpu", sample->cpu);
351 if (ret)
352 return -1;
353 }
354
355 if (type & PERF_SAMPLE_PERIOD) {
356 ret = value_set_u64(cw, event, "perf_period", sample->period);
357 if (ret)
358 return -1;
359 }
360
361 if (type & PERF_SAMPLE_WEIGHT) {
362 ret = value_set_u64(cw, event, "perf_weight", sample->weight);
363 if (ret)
364 return -1;
365 }
366
367 if (type & PERF_SAMPLE_DATA_SRC) {
368 ret = value_set_u64(cw, event, "perf_data_src",
369 sample->data_src);
370 if (ret)
371 return -1;
372 }
373
374 if (type & PERF_SAMPLE_TRANSACTION) {
375 ret = value_set_u64(cw, event, "perf_transaction",
376 sample->transaction);
377 if (ret)
378 return -1;
379 }
380
381 return 0;
382}
383
384static int process_sample_event(struct perf_tool *tool,
385 union perf_event *_event __maybe_unused,
386 struct perf_sample *sample,
387 struct perf_evsel *evsel,
388 struct machine *machine __maybe_unused)
389{
390 struct convert *c = container_of(tool, struct convert, tool);
391 struct evsel_priv *priv = evsel->priv;
392 struct ctf_writer *cw = &c->writer;
393 struct bt_ctf_event_class *event_class;
394 struct bt_ctf_event *event;
395 int ret;
396
397 if (WARN_ONCE(!priv, "Failed to setup all events.\n"))
398 return 0;
399
400 event_class = priv->event_class;
401
402 /* update stats */
403 c->events_count++;
404 c->events_size += _event->header.size;
405
406 pr_time2(sample->time, "sample %" PRIu64 "\n", c->events_count);
407
408 event = bt_ctf_event_create(event_class);
409 if (!event) {
410 pr_err("Failed to create an CTF event\n");
411 return -1;
412 }
413
414 bt_ctf_clock_set_time(cw->clock, sample->time);
415
416 ret = add_generic_values(cw, event, evsel, sample);
417 if (ret)
418 return -1;
419
420 if (evsel->attr.type == PERF_TYPE_TRACEPOINT) {
421 ret = add_tracepoint_values(cw, event_class, event,
422 evsel, sample);
423 if (ret)
424 return -1;
425 }
426
427 bt_ctf_stream_append_event(cw->stream, event);
428 bt_ctf_event_put(event);
429 return 0;
430}
431
432static int add_tracepoint_fields_types(struct ctf_writer *cw,
433 struct format_field *fields,
434 struct bt_ctf_event_class *event_class)
435{
436 struct format_field *field;
437 int ret;
438
439 for (field = fields; field; field = field->next) {
440 struct bt_ctf_field_type *type;
441 unsigned long flags = field->flags;
442
443 pr2(" field '%s'\n", field->name);
444
445 type = get_tracepoint_field_type(cw, field);
446 if (!type)
447 return -1;
448
449 /*
450 * A string is an array of chars. For this we use the string
451 * type and don't care that it is an array. What we don't
452 * support is an array of strings.
453 */
454 if (flags & FIELD_IS_STRING)
455 flags &= ~FIELD_IS_ARRAY;
456
457 if (flags & FIELD_IS_ARRAY)
458 type = bt_ctf_field_type_array_create(type, field->arraylen);
459
460 ret = bt_ctf_event_class_add_field(event_class, type,
461 field->name);
462
463 if (flags & FIELD_IS_ARRAY)
464 bt_ctf_field_type_put(type);
465
466 if (ret) {
467 pr_err("Failed to add field '%s\n", field->name);
468 return -1;
469 }
470 }
471
472 return 0;
473}
474
475static int add_tracepoint_types(struct ctf_writer *cw,
476 struct perf_evsel *evsel,
477 struct bt_ctf_event_class *class)
478{
479 struct format_field *common_fields = evsel->tp_format->format.common_fields;
480 struct format_field *fields = evsel->tp_format->format.fields;
481 int ret;
482
483 ret = add_tracepoint_fields_types(cw, common_fields, class);
484 if (!ret)
485 ret = add_tracepoint_fields_types(cw, fields, class);
486
487 return ret;
488}
489
490static int add_generic_types(struct ctf_writer *cw, struct perf_evsel *evsel,
491 struct bt_ctf_event_class *event_class)
492{
493 u64 type = evsel->attr.sample_type;
494
495 /*
496 * missing:
497 * PERF_SAMPLE_TIME - not needed as we have it in
498 * ctf event header
499 * PERF_SAMPLE_READ - TODO
500 * PERF_SAMPLE_CALLCHAIN - TODO
501 * PERF_SAMPLE_RAW - tracepoint fields are handled separately
502 * PERF_SAMPLE_BRANCH_STACK - TODO
503 * PERF_SAMPLE_REGS_USER - TODO
504 * PERF_SAMPLE_STACK_USER - TODO
505 */
506
507#define ADD_FIELD(cl, t, n) \
508 do { \
509 pr2(" field '%s'\n", n); \
510 if (bt_ctf_event_class_add_field(cl, t, n)) { \
511 pr_err("Failed to add field '%s;\n", n); \
512 return -1; \
513 } \
514 } while (0)
515
516 if (type & PERF_SAMPLE_IP)
517 ADD_FIELD(event_class, cw->data.u64_hex, "perf_ip");
518
519 if (type & PERF_SAMPLE_TID) {
520 ADD_FIELD(event_class, cw->data.s32, "perf_tid");
521 ADD_FIELD(event_class, cw->data.s32, "perf_pid");
522 }
523
524 if ((type & PERF_SAMPLE_ID) ||
525 (type & PERF_SAMPLE_IDENTIFIER))
526 ADD_FIELD(event_class, cw->data.u64, "perf_id");
527
528 if (type & PERF_SAMPLE_STREAM_ID)
529 ADD_FIELD(event_class, cw->data.u64, "perf_stream_id");
530
531 if (type & PERF_SAMPLE_CPU)
532 ADD_FIELD(event_class, cw->data.u32, "perf_cpu");
533
534 if (type & PERF_SAMPLE_PERIOD)
535 ADD_FIELD(event_class, cw->data.u64, "perf_period");
536
537 if (type & PERF_SAMPLE_WEIGHT)
538 ADD_FIELD(event_class, cw->data.u64, "perf_weight");
539
540 if (type & PERF_SAMPLE_DATA_SRC)
541 ADD_FIELD(event_class, cw->data.u64, "perf_data_src");
542
543 if (type & PERF_SAMPLE_TRANSACTION)
544 ADD_FIELD(event_class, cw->data.u64, "perf_transaction");
545
546#undef ADD_FIELD
547 return 0;
548}
549
550static int add_event(struct ctf_writer *cw, struct perf_evsel *evsel)
551{
552 struct bt_ctf_event_class *event_class;
553 struct evsel_priv *priv;
554 const char *name = perf_evsel__name(evsel);
555 int ret;
556
557 pr("Adding event '%s' (type %d)\n", name, evsel->attr.type);
558
559 event_class = bt_ctf_event_class_create(name);
560 if (!event_class)
561 return -1;
562
563 ret = add_generic_types(cw, evsel, event_class);
564 if (ret)
565 goto err;
566
567 if (evsel->attr.type == PERF_TYPE_TRACEPOINT) {
568 ret = add_tracepoint_types(cw, evsel, event_class);
569 if (ret)
570 goto err;
571 }
572
573 ret = bt_ctf_stream_class_add_event_class(cw->stream_class, event_class);
574 if (ret) {
575 pr("Failed to add event class into stream.\n");
576 goto err;
577 }
578
579 priv = malloc(sizeof(*priv));
580 if (!priv)
581 goto err;
582
583 priv->event_class = event_class;
584 evsel->priv = priv;
585 return 0;
586
587err:
588 bt_ctf_event_class_put(event_class);
589 pr_err("Failed to add event '%s'.\n", name);
590 return -1;
591}
592
593static int setup_events(struct ctf_writer *cw, struct perf_session *session)
594{
595 struct perf_evlist *evlist = session->evlist;
596 struct perf_evsel *evsel;
597 int ret;
598
599 evlist__for_each(evlist, evsel) {
600 ret = add_event(cw, evsel);
601 if (ret)
602 return ret;
603 }
604 return 0;
605}
606
607static int ctf_writer__setup_env(struct ctf_writer *cw,
608 struct perf_session *session)
609{
610 struct perf_header *header = &session->header;
611 struct bt_ctf_writer *writer = cw->writer;
612
613#define ADD(__n, __v) \
614do { \
615 if (bt_ctf_writer_add_environment_field(writer, __n, __v)) \
616 return -1; \
617} while (0)
618
619 ADD("host", header->env.hostname);
620 ADD("sysname", "Linux");
621 ADD("release", header->env.os_release);
622 ADD("version", header->env.version);
623 ADD("machine", header->env.arch);
624 ADD("domain", "kernel");
625 ADD("tracer_name", "perf");
626
627#undef ADD
628 return 0;
629}
630
631static int ctf_writer__setup_clock(struct ctf_writer *cw)
632{
633 struct bt_ctf_clock *clock = cw->clock;
634
635 bt_ctf_clock_set_description(clock, "perf clock");
636
637#define SET(__n, __v) \
638do { \
639 if (bt_ctf_clock_set_##__n(clock, __v)) \
640 return -1; \
641} while (0)
642
643 SET(frequency, 1000000000);
644 SET(offset_s, 0);
645 SET(offset, 0);
646 SET(precision, 10);
647 SET(is_absolute, 0);
648
649#undef SET
650 return 0;
651}
652
653static struct bt_ctf_field_type *create_int_type(int size, bool sign, bool hex)
654{
655 struct bt_ctf_field_type *type;
656
657 type = bt_ctf_field_type_integer_create(size);
658 if (!type)
659 return NULL;
660
661 if (sign &&
662 bt_ctf_field_type_integer_set_signed(type, 1))
663 goto err;
664
665 if (hex &&
666 bt_ctf_field_type_integer_set_base(type, BT_CTF_INTEGER_BASE_HEXADECIMAL))
667 goto err;
668
669 pr2("Created type: INTEGER %d-bit %ssigned %s\n",
670 size, sign ? "un" : "", hex ? "hex" : "");
671 return type;
672
673err:
674 bt_ctf_field_type_put(type);
675 return NULL;
676}
677
678static void ctf_writer__cleanup_data(struct ctf_writer *cw)
679{
680 unsigned int i;
681
682 for (i = 0; i < ARRAY_SIZE(cw->data.array); i++)
683 bt_ctf_field_type_put(cw->data.array[i]);
684}
685
686static int ctf_writer__init_data(struct ctf_writer *cw)
687{
688#define CREATE_INT_TYPE(type, size, sign, hex) \
689do { \
690 (type) = create_int_type(size, sign, hex); \
691 if (!(type)) \
692 goto err; \
693} while (0)
694
695 CREATE_INT_TYPE(cw->data.s64, 64, true, false);
696 CREATE_INT_TYPE(cw->data.u64, 64, false, false);
697 CREATE_INT_TYPE(cw->data.s32, 32, true, false);
698 CREATE_INT_TYPE(cw->data.u32, 32, false, false);
699 CREATE_INT_TYPE(cw->data.u64_hex, 64, false, true);
700
701 cw->data.string = bt_ctf_field_type_string_create();
702 if (cw->data.string)
703 return 0;
704
705err:
706 ctf_writer__cleanup_data(cw);
707 pr_err("Failed to create data types.\n");
708 return -1;
709}
710
711static void ctf_writer__cleanup(struct ctf_writer *cw)
712{
713 ctf_writer__cleanup_data(cw);
714
715 bt_ctf_clock_put(cw->clock);
716 bt_ctf_stream_put(cw->stream);
717 bt_ctf_stream_class_put(cw->stream_class);
718 bt_ctf_writer_put(cw->writer);
719
720 /* and NULL all the pointers */
721 memset(cw, 0, sizeof(*cw));
722}
723
724static int ctf_writer__init(struct ctf_writer *cw, const char *path)
725{
726 struct bt_ctf_writer *writer;
727 struct bt_ctf_stream_class *stream_class;
728 struct bt_ctf_stream *stream;
729 struct bt_ctf_clock *clock;
730
731 /* CTF writer */
732 writer = bt_ctf_writer_create(path);
733 if (!writer)
734 goto err;
735
736 cw->writer = writer;
737
738 /* CTF clock */
739 clock = bt_ctf_clock_create("perf_clock");
740 if (!clock) {
741 pr("Failed to create CTF clock.\n");
742 goto err_cleanup;
743 }
744
745 cw->clock = clock;
746
747 if (ctf_writer__setup_clock(cw)) {
748 pr("Failed to setup CTF clock.\n");
749 goto err_cleanup;
750 }
751
752 /* CTF stream class */
753 stream_class = bt_ctf_stream_class_create("perf_stream");
754 if (!stream_class) {
755 pr("Failed to create CTF stream class.\n");
756 goto err_cleanup;
757 }
758
759 cw->stream_class = stream_class;
760
761 /* CTF clock stream setup */
762 if (bt_ctf_stream_class_set_clock(stream_class, clock)) {
763 pr("Failed to assign CTF clock to stream class.\n");
764 goto err_cleanup;
765 }
766
767 if (ctf_writer__init_data(cw))
768 goto err_cleanup;
769
770 /* CTF stream instance */
771 stream = bt_ctf_writer_create_stream(writer, stream_class);
772 if (!stream) {
773 pr("Failed to create CTF stream.\n");
774 goto err_cleanup;
775 }
776
777 cw->stream = stream;
778
779 /* CTF clock writer setup */
780 if (bt_ctf_writer_add_clock(writer, clock)) {
781 pr("Failed to assign CTF clock to writer.\n");
782 goto err_cleanup;
783 }
784
785 return 0;
786
787err_cleanup:
788 ctf_writer__cleanup(cw);
789err:
790 pr_err("Failed to setup CTF writer.\n");
791 return -1;
792}
793
794int bt_convert__perf2ctf(const char *input, const char *path)
795{
796 struct perf_session *session;
797 struct perf_data_file file = {
798 .path = input,
799 .mode = PERF_DATA_MODE_READ,
800 };
801 struct convert c = {
802 .tool = {
803 .sample = process_sample_event,
804 .mmap = perf_event__process_mmap,
805 .mmap2 = perf_event__process_mmap2,
806 .comm = perf_event__process_comm,
807 .exit = perf_event__process_exit,
808 .fork = perf_event__process_fork,
809 .lost = perf_event__process_lost,
810 .tracing_data = perf_event__process_tracing_data,
811 .build_id = perf_event__process_build_id,
812 .ordered_events = true,
813 .ordering_requires_timestamps = true,
814 },
815 };
816 struct ctf_writer *cw = &c.writer;
817 int err = -1;
818
819 /* CTF writer */
820 if (ctf_writer__init(cw, path))
821 return -1;
822
823 /* perf.data session */
824 session = perf_session__new(&file, 0, &c.tool);
825 if (!session)
826 goto free_writer;
827
828 /* CTF writer env/clock setup */
829 if (ctf_writer__setup_env(cw, session))
830 goto free_session;
831
832 /* CTF events setup */
833 if (setup_events(cw, session))
834 goto free_session;
835
836 err = perf_session__process_events(session);
837 if (!err)
838 err = bt_ctf_stream_flush(cw->stream);
839
840 fprintf(stderr,
841 "[ perf data convert: Converted '%s' into CTF data '%s' ]\n",
842 file.path, path);
843
844 fprintf(stderr,
845 "[ perf data convert: Converted and wrote %.3f MB (%" PRIu64 " samples) ]\n",
846 (double) c.events_size / 1024.0 / 1024.0,
847 c.events_count);
848
849 /* its all good */
850free_session:
851 perf_session__delete(session);
852
853free_writer:
854 ctf_writer__cleanup(cw);
855 return err;
856}
diff --git a/tools/perf/util/data-convert-bt.h b/tools/perf/util/data-convert-bt.h
new file mode 100644
index 000000000000..dda30c5d0792
--- /dev/null
+++ b/tools/perf/util/data-convert-bt.h
@@ -0,0 +1,8 @@
1#ifndef __DATA_CONVERT_BT_H
2#define __DATA_CONVERT_BT_H
3#ifdef HAVE_LIBBABELTRACE_SUPPORT
4
5int bt_convert__perf2ctf(const char *input_name, const char *to_ctf);
6
7#endif /* HAVE_LIBBABELTRACE_SUPPORT */
8#endif /* __DATA_CONVERT_BT_H */
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index ad60b2f20258..2da5581ec74d 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -20,6 +20,7 @@ int verbose;
20bool dump_trace = false, quiet = false; 20bool dump_trace = false, quiet = false;
21int debug_ordered_events; 21int debug_ordered_events;
22static int redirect_to_stderr; 22static int redirect_to_stderr;
23int debug_data_convert;
23 24
24static int _eprintf(int level, int var, const char *fmt, va_list args) 25static int _eprintf(int level, int var, const char *fmt, va_list args)
25{ 26{
@@ -147,6 +148,7 @@ static struct debug_variable {
147 { .name = "verbose", .ptr = &verbose }, 148 { .name = "verbose", .ptr = &verbose },
148 { .name = "ordered-events", .ptr = &debug_ordered_events}, 149 { .name = "ordered-events", .ptr = &debug_ordered_events},
149 { .name = "stderr", .ptr = &redirect_to_stderr}, 150 { .name = "stderr", .ptr = &redirect_to_stderr},
151 { .name = "data-convert", .ptr = &debug_data_convert },
150 { .name = NULL, } 152 { .name = NULL, }
151}; 153};
152 154
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index be264d6f3b30..caac2fdc6105 100644
--- a/tools/perf/util/debug.h
+++ b/tools/perf/util/debug.h
@@ -12,6 +12,7 @@
12extern int verbose; 12extern int verbose;
13extern bool quiet, dump_trace; 13extern bool quiet, dump_trace;
14extern int debug_ordered_events; 14extern int debug_ordered_events;
15extern int debug_data_convert;
15 16
16#ifndef pr_fmt 17#ifndef pr_fmt
17#define pr_fmt(fmt) fmt 18#define pr_fmt(fmt) fmt
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index c2f7d3b90966..fc0ddd5792a9 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -45,13 +45,13 @@ int dso__read_binary_type_filename(const struct dso *dso,
45 case DSO_BINARY_TYPE__DEBUGLINK: { 45 case DSO_BINARY_TYPE__DEBUGLINK: {
46 char *debuglink; 46 char *debuglink;
47 47
48 strncpy(filename, dso->long_name, size); 48 len = __symbol__join_symfs(filename, size, dso->long_name);
49 debuglink = filename + dso->long_name_len; 49 debuglink = filename + len;
50 while (debuglink != filename && *debuglink != '/') 50 while (debuglink != filename && *debuglink != '/')
51 debuglink--; 51 debuglink--;
52 if (*debuglink == '/') 52 if (*debuglink == '/')
53 debuglink++; 53 debuglink++;
54 ret = filename__read_debuglink(dso->long_name, debuglink, 54 ret = filename__read_debuglink(filename, debuglink,
55 size - (debuglink - filename)); 55 size - (debuglink - filename));
56 } 56 }
57 break; 57 break;
@@ -148,6 +148,9 @@ static const struct {
148#ifdef HAVE_ZLIB_SUPPORT 148#ifdef HAVE_ZLIB_SUPPORT
149 { "gz", gzip_decompress_to_file }, 149 { "gz", gzip_decompress_to_file },
150#endif 150#endif
151#ifdef HAVE_LZMA_SUPPORT
152 { "xz", lzma_decompress_to_file },
153#endif
151 { NULL, NULL }, 154 { NULL, NULL },
152}; 155};
153 156
@@ -162,32 +165,14 @@ bool is_supported_compression(const char *ext)
162 return false; 165 return false;
163} 166}
164 167
165bool is_kmodule_extension(const char *ext) 168bool is_kernel_module(const char *pathname)
166{
167 if (strncmp(ext, "ko", 2))
168 return false;
169
170 if (ext[2] == '\0' || (ext[2] == '.' && is_supported_compression(ext+3)))
171 return true;
172
173 return false;
174}
175
176bool is_kernel_module(const char *pathname, bool *compressed)
177{ 169{
178 const char *ext = strrchr(pathname, '.'); 170 struct kmod_path m;
179 171
180 if (ext == NULL) 172 if (kmod_path__parse(&m, pathname))
181 return false; 173 return NULL;
182
183 if (is_supported_compression(ext + 1)) {
184 if (compressed)
185 *compressed = true;
186 ext -= 3;
187 } else if (compressed)
188 *compressed = false;
189 174
190 return is_kmodule_extension(ext + 1); 175 return m.kmod;
191} 176}
192 177
193bool decompress_to_file(const char *ext, const char *filename, int output_fd) 178bool decompress_to_file(const char *ext, const char *filename, int output_fd)
@@ -209,6 +194,72 @@ bool dso__needs_decompress(struct dso *dso)
209} 194}
210 195
211/* 196/*
197 * Parses kernel module specified in @path and updates
198 * @m argument like:
199 *
200 * @comp - true if @path contains supported compression suffix,
201 * false otherwise
202 * @kmod - true if @path contains '.ko' suffix in right position,
203 * false otherwise
204 * @name - if (@alloc_name && @kmod) is true, it contains strdup-ed base name
205 * of the kernel module without suffixes, otherwise strudup-ed
206 * base name of @path
207 * @ext - if (@alloc_ext && @comp) is true, it contains strdup-ed string
208 * the compression suffix
209 *
210 * Returns 0 if there's no strdup error, -ENOMEM otherwise.
211 */
212int __kmod_path__parse(struct kmod_path *m, const char *path,
213 bool alloc_name, bool alloc_ext)
214{
215 const char *name = strrchr(path, '/');
216 const char *ext = strrchr(path, '.');
217
218 memset(m, 0x0, sizeof(*m));
219 name = name ? name + 1 : path;
220
221 /* No extension, just return name. */
222 if (ext == NULL) {
223 if (alloc_name) {
224 m->name = strdup(name);
225 return m->name ? 0 : -ENOMEM;
226 }
227 return 0;
228 }
229
230 if (is_supported_compression(ext + 1)) {
231 m->comp = true;
232 ext -= 3;
233 }
234
235 /* Check .ko extension only if there's enough name left. */
236 if (ext > name)
237 m->kmod = !strncmp(ext, ".ko", 3);
238
239 if (alloc_name) {
240 if (m->kmod) {
241 if (asprintf(&m->name, "[%.*s]", (int) (ext - name), name) == -1)
242 return -ENOMEM;
243 } else {
244 if (asprintf(&m->name, "%s", name) == -1)
245 return -ENOMEM;
246 }
247
248 strxfrchar(m->name, '-', '_');
249 }
250
251 if (alloc_ext && m->comp) {
252 m->ext = strdup(ext + 4);
253 if (!m->ext) {
254 free((void *) m->name);
255 return -ENOMEM;
256 }
257 }
258
259 return 0;
260}
261
262/*
212 * Global list of open DSOs and the counter. 263 * Global list of open DSOs and the counter.
213 */ 264 */
214static LIST_HEAD(dso__data_open); 265static LIST_HEAD(dso__data_open);
@@ -240,7 +291,7 @@ static int do_open(char *name)
240 if (fd >= 0) 291 if (fd >= 0)
241 return fd; 292 return fd;
242 293
243 pr_debug("dso open failed, mmap: %s\n", 294 pr_debug("dso open failed: %s\n",
244 strerror_r(errno, sbuf, sizeof(sbuf))); 295 strerror_r(errno, sbuf, sizeof(sbuf)));
245 if (!dso__data_open_cnt || errno != EMFILE) 296 if (!dso__data_open_cnt || errno != EMFILE)
246 break; 297 break;
@@ -1002,21 +1053,24 @@ struct dso *dsos__find(const struct dsos *dsos, const char *name,
1002 return dso__find_by_longname(&dsos->root, name); 1053 return dso__find_by_longname(&dsos->root, name);
1003} 1054}
1004 1055
1005struct dso *__dsos__findnew(struct dsos *dsos, const char *name) 1056struct dso *dsos__addnew(struct dsos *dsos, const char *name)
1006{ 1057{
1007 struct dso *dso = dsos__find(dsos, name, false); 1058 struct dso *dso = dso__new(name);
1008 1059
1009 if (!dso) { 1060 if (dso != NULL) {
1010 dso = dso__new(name); 1061 dsos__add(dsos, dso);
1011 if (dso != NULL) { 1062 dso__set_basename(dso);
1012 dsos__add(dsos, dso);
1013 dso__set_basename(dso);
1014 }
1015 } 1063 }
1016
1017 return dso; 1064 return dso;
1018} 1065}
1019 1066
1067struct dso *__dsos__findnew(struct dsos *dsos, const char *name)
1068{
1069 struct dso *dso = dsos__find(dsos, name, false);
1070
1071 return dso ? dso : dsos__addnew(dsos, name);
1072}
1073
1020size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp, 1074size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp,
1021 bool (skip)(struct dso *dso, int parm), int parm) 1075 bool (skip)(struct dso *dso, int parm), int parm)
1022{ 1076{
@@ -1083,3 +1137,36 @@ enum dso_type dso__type(struct dso *dso, struct machine *machine)
1083 1137
1084 return dso__type_fd(fd); 1138 return dso__type_fd(fd);
1085} 1139}
1140
1141int dso__strerror_load(struct dso *dso, char *buf, size_t buflen)
1142{
1143 int idx, errnum = dso->load_errno;
1144 /*
1145 * This must have a same ordering as the enum dso_load_errno.
1146 */
1147 static const char *dso_load__error_str[] = {
1148 "Internal tools/perf/ library error",
1149 "Invalid ELF file",
1150 "Can not read build id",
1151 "Mismatching build id",
1152 "Decompression failure",
1153 };
1154
1155 BUG_ON(buflen == 0);
1156
1157 if (errnum >= 0) {
1158 const char *err = strerror_r(errnum, buf, buflen);
1159
1160 if (err != buf)
1161 scnprintf(buf, buflen, "%s", err);
1162
1163 return 0;
1164 }
1165
1166 if (errnum < __DSO_LOAD_ERRNO__START || errnum >= __DSO_LOAD_ERRNO__END)
1167 return -1;
1168
1169 idx = errnum - __DSO_LOAD_ERRNO__START;
1170 scnprintf(buf, buflen, "%s", dso_load__error_str[idx]);
1171 return 0;
1172}
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index ced92841ff97..e0901b4ed8de 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -60,6 +60,31 @@ enum dso_type {
60 DSO__TYPE_X32BIT, 60 DSO__TYPE_X32BIT,
61}; 61};
62 62
63enum dso_load_errno {
64 DSO_LOAD_ERRNO__SUCCESS = 0,
65
66 /*
67 * Choose an arbitrary negative big number not to clash with standard
68 * errno since SUS requires the errno has distinct positive values.
69 * See 'Issue 6' in the link below.
70 *
71 * http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html
72 */
73 __DSO_LOAD_ERRNO__START = -10000,
74
75 DSO_LOAD_ERRNO__INTERNAL_ERROR = __DSO_LOAD_ERRNO__START,
76
77 /* for symsrc__init() */
78 DSO_LOAD_ERRNO__INVALID_ELF,
79 DSO_LOAD_ERRNO__CANNOT_READ_BUILDID,
80 DSO_LOAD_ERRNO__MISMATCHING_BUILDID,
81
82 /* for decompress_kmodule */
83 DSO_LOAD_ERRNO__DECOMPRESSION_FAILURE,
84
85 __DSO_LOAD_ERRNO__END,
86};
87
63#define DSO__SWAP(dso, type, val) \ 88#define DSO__SWAP(dso, type, val) \
64({ \ 89({ \
65 type ____r = val; \ 90 type ____r = val; \
@@ -113,6 +138,7 @@ struct dso {
113 enum dso_swap_type needs_swap; 138 enum dso_swap_type needs_swap;
114 enum dso_binary_type symtab_type; 139 enum dso_binary_type symtab_type;
115 enum dso_binary_type binary_type; 140 enum dso_binary_type binary_type;
141 enum dso_load_errno load_errno;
116 u8 adjust_symbols:1; 142 u8 adjust_symbols:1;
117 u8 has_build_id:1; 143 u8 has_build_id:1;
118 u8 has_srcline:1; 144 u8 has_srcline:1;
@@ -139,7 +165,8 @@ struct dso {
139 u32 status_seen; 165 u32 status_seen;
140 size_t file_size; 166 size_t file_size;
141 struct list_head open_entry; 167 struct list_head open_entry;
142 u64 frame_offset; 168 u64 debug_frame_offset;
169 u64 eh_frame_hdr_offset;
143 } data; 170 } data;
144 171
145 union { /* Tool specific area */ 172 union { /* Tool specific area */
@@ -189,11 +216,24 @@ char dso__symtab_origin(const struct dso *dso);
189int dso__read_binary_type_filename(const struct dso *dso, enum dso_binary_type type, 216int dso__read_binary_type_filename(const struct dso *dso, enum dso_binary_type type,
190 char *root_dir, char *filename, size_t size); 217 char *root_dir, char *filename, size_t size);
191bool is_supported_compression(const char *ext); 218bool is_supported_compression(const char *ext);
192bool is_kmodule_extension(const char *ext); 219bool is_kernel_module(const char *pathname);
193bool is_kernel_module(const char *pathname, bool *compressed);
194bool decompress_to_file(const char *ext, const char *filename, int output_fd); 220bool decompress_to_file(const char *ext, const char *filename, int output_fd);
195bool dso__needs_decompress(struct dso *dso); 221bool dso__needs_decompress(struct dso *dso);
196 222
223struct kmod_path {
224 char *name;
225 char *ext;
226 bool comp;
227 bool kmod;
228};
229
230int __kmod_path__parse(struct kmod_path *m, const char *path,
231 bool alloc_name, bool alloc_ext);
232
233#define kmod_path__parse(__m, __p) __kmod_path__parse(__m, __p, false, false)
234#define kmod_path__parse_name(__m, __p) __kmod_path__parse(__m, __p, true , false)
235#define kmod_path__parse_ext(__m, __p) __kmod_path__parse(__m, __p, false, true)
236
197/* 237/*
198 * The dso__data_* external interface provides following functions: 238 * The dso__data_* external interface provides following functions:
199 * dso__data_fd 239 * dso__data_fd
@@ -249,6 +289,7 @@ struct dso *dso__kernel_findnew(struct machine *machine, const char *name,
249 const char *short_name, int dso_type); 289 const char *short_name, int dso_type);
250 290
251void dsos__add(struct dsos *dsos, struct dso *dso); 291void dsos__add(struct dsos *dsos, struct dso *dso);
292struct dso *dsos__addnew(struct dsos *dsos, const char *name);
252struct dso *dsos__find(const struct dsos *dsos, const char *name, 293struct dso *dsos__find(const struct dsos *dsos, const char *name,
253 bool cmp_short); 294 bool cmp_short);
254struct dso *__dsos__findnew(struct dsos *dsos, const char *name); 295struct dso *__dsos__findnew(struct dsos *dsos, const char *name);
@@ -279,4 +320,6 @@ void dso__free_a2l(struct dso *dso);
279 320
280enum dso_type dso__type(struct dso *dso, struct machine *machine); 321enum dso_type dso__type(struct dso *dso, struct machine *machine);
281 322
323int dso__strerror_load(struct dso *dso, char *buf, size_t buflen);
324
282#endif /* __PERF_DSO */ 325#endif /* __PERF_DSO */
diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c
index cc66c4049e09..780b2bc11128 100644
--- a/tools/perf/util/dwarf-aux.c
+++ b/tools/perf/util/dwarf-aux.c
@@ -278,6 +278,21 @@ bool die_is_func_def(Dwarf_Die *dw_die)
278} 278}
279 279
280/** 280/**
281 * die_is_func_instance - Ensure that this DIE is an instance of a subprogram
282 * @dw_die: a DIE
283 *
284 * Ensure that this DIE is an instance (which has an entry address).
285 * This returns true if @dw_die is a function instance. If not, you need to
286 * call die_walk_instances() to find actual instances.
287 **/
288bool die_is_func_instance(Dwarf_Die *dw_die)
289{
290 Dwarf_Addr tmp;
291
292 /* Actually gcc optimizes non-inline as like as inlined */
293 return !dwarf_func_inline(dw_die) && dwarf_entrypc(dw_die, &tmp) == 0;
294}
295/**
281 * die_get_data_member_location - Get the data-member offset 296 * die_get_data_member_location - Get the data-member offset
282 * @mb_die: a DIE of a member of a data structure 297 * @mb_die: a DIE of a member of a data structure
283 * @offs: The offset of the member in the data structure 298 * @offs: The offset of the member in the data structure
diff --git a/tools/perf/util/dwarf-aux.h b/tools/perf/util/dwarf-aux.h
index b4fe90c6cb2d..af7dbcd5f929 100644
--- a/tools/perf/util/dwarf-aux.h
+++ b/tools/perf/util/dwarf-aux.h
@@ -41,6 +41,9 @@ extern int cu_walk_functions_at(Dwarf_Die *cu_die, Dwarf_Addr addr,
41/* Ensure that this DIE is a subprogram and definition (not declaration) */ 41/* Ensure that this DIE is a subprogram and definition (not declaration) */
42extern bool die_is_func_def(Dwarf_Die *dw_die); 42extern bool die_is_func_def(Dwarf_Die *dw_die);
43 43
44/* Ensure that this DIE is an instance of a subprogram */
45extern bool die_is_func_instance(Dwarf_Die *dw_die);
46
44/* Compare diename and tname */ 47/* Compare diename and tname */
45extern bool die_compare_name(Dwarf_Die *dw_die, const char *tname); 48extern bool die_compare_name(Dwarf_Die *dw_die, const char *tname);
46 49
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 6c6d044e959a..d5efa5092ce6 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -95,9 +95,7 @@ static pid_t perf_event__get_comm_tgid(pid_t pid, char *comm, size_t len)
95 return tgid; 95 return tgid;
96} 96}
97 97
98static pid_t perf_event__synthesize_comm(struct perf_tool *tool, 98static pid_t perf_event__prepare_comm(union perf_event *event, pid_t pid,
99 union perf_event *event, pid_t pid,
100 perf_event__handler_t process,
101 struct machine *machine) 99 struct machine *machine)
102{ 100{
103 size_t size; 101 size_t size;
@@ -124,6 +122,19 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
124 (sizeof(event->comm.comm) - size) + 122 (sizeof(event->comm.comm) - size) +
125 machine->id_hdr_size); 123 machine->id_hdr_size);
126 event->comm.tid = pid; 124 event->comm.tid = pid;
125out:
126 return tgid;
127}
128
129static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
130 union perf_event *event, pid_t pid,
131 perf_event__handler_t process,
132 struct machine *machine)
133{
134 pid_t tgid = perf_event__prepare_comm(event, pid, machine);
135
136 if (tgid == -1)
137 goto out;
127 138
128 if (process(tool, event, &synth_sample, machine) != 0) 139 if (process(tool, event, &synth_sample, machine) != 0)
129 return -1; 140 return -1;
@@ -139,7 +150,6 @@ static int perf_event__synthesize_fork(struct perf_tool *tool,
139{ 150{
140 memset(&event->fork, 0, sizeof(event->fork) + machine->id_hdr_size); 151 memset(&event->fork, 0, sizeof(event->fork) + machine->id_hdr_size);
141 152
142 /* this is really a clone event but we use fork to synthesize it */
143 event->fork.ppid = tgid; 153 event->fork.ppid = tgid;
144 event->fork.ptid = tgid; 154 event->fork.ptid = tgid;
145 event->fork.pid = tgid; 155 event->fork.pid = tgid;
@@ -368,19 +378,23 @@ static int __event__synthesize_thread(union perf_event *comm_event,
368 if (*end) 378 if (*end)
369 continue; 379 continue;
370 380
371 tgid = perf_event__synthesize_comm(tool, comm_event, _pid, 381 tgid = perf_event__prepare_comm(comm_event, _pid, machine);
372 process, machine);
373 if (tgid == -1) 382 if (tgid == -1)
374 return -1; 383 return -1;
375 384
385 if (perf_event__synthesize_fork(tool, fork_event, _pid, tgid,
386 process, machine) < 0)
387 return -1;
388 /*
389 * Send the prepared comm event
390 */
391 if (process(tool, comm_event, &synth_sample, machine) != 0)
392 return -1;
393
376 if (_pid == pid) { 394 if (_pid == pid) {
377 /* process the parent's maps too */ 395 /* process the parent's maps too */
378 rc = perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid, 396 rc = perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid,
379 process, machine, mmap_data); 397 process, machine, mmap_data);
380 } else {
381 /* only fork the tid's map, to save time */
382 rc = perf_event__synthesize_fork(tool, fork_event, _pid, tgid,
383 process, machine);
384 } 398 }
385 399
386 if (rc) 400 if (rc)
@@ -615,7 +629,7 @@ size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp)
615 else 629 else
616 s = ""; 630 s = "";
617 631
618 return fprintf(fp, "%s: %s:%d\n", s, event->comm.comm, event->comm.tid); 632 return fprintf(fp, "%s: %s:%d/%d\n", s, event->comm.comm, event->comm.pid, event->comm.tid);
619} 633}
620 634
621int perf_event__process_comm(struct perf_tool *tool __maybe_unused, 635int perf_event__process_comm(struct perf_tool *tool __maybe_unused,
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 28b8ce86bf12..82bf224bbee9 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -7,7 +7,6 @@
7 * Released under the GPL v2. (and only v2, not any later version) 7 * Released under the GPL v2. (and only v2, not any later version)
8 */ 8 */
9#include "util.h" 9#include "util.h"
10#include <api/fs/debugfs.h>
11#include <api/fs/fs.h> 10#include <api/fs/fs.h>
12#include <poll.h> 11#include <poll.h>
13#include "cpumap.h" 12#include "cpumap.h"
@@ -1051,7 +1050,7 @@ out_delete_threads:
1051 return -1; 1050 return -1;
1052} 1051}
1053 1052
1054int perf_evlist__apply_filters(struct perf_evlist *evlist) 1053int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **err_evsel)
1055{ 1054{
1056 struct perf_evsel *evsel; 1055 struct perf_evsel *evsel;
1057 int err = 0; 1056 int err = 0;
@@ -1063,8 +1062,10 @@ int perf_evlist__apply_filters(struct perf_evlist *evlist)
1063 continue; 1062 continue;
1064 1063
1065 err = perf_evsel__set_filter(evsel, ncpus, nthreads, evsel->filter); 1064 err = perf_evsel__set_filter(evsel, ncpus, nthreads, evsel->filter);
1066 if (err) 1065 if (err) {
1066 *err_evsel = evsel;
1067 break; 1067 break;
1068 }
1068 } 1069 }
1069 1070
1070 return err; 1071 return err;
@@ -1086,6 +1087,38 @@ int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter)
1086 return err; 1087 return err;
1087} 1088}
1088 1089
1090int perf_evlist__set_filter_pids(struct perf_evlist *evlist, size_t npids, pid_t *pids)
1091{
1092 char *filter;
1093 int ret = -1;
1094 size_t i;
1095
1096 for (i = 0; i < npids; ++i) {
1097 if (i == 0) {
1098 if (asprintf(&filter, "common_pid != %d", pids[i]) < 0)
1099 return -1;
1100 } else {
1101 char *tmp;
1102
1103 if (asprintf(&tmp, "%s && common_pid != %d", filter, pids[i]) < 0)
1104 goto out_free;
1105
1106 free(filter);
1107 filter = tmp;
1108 }
1109 }
1110
1111 ret = perf_evlist__set_filter(evlist, filter);
1112out_free:
1113 free(filter);
1114 return ret;
1115}
1116
1117int perf_evlist__set_filter_pid(struct perf_evlist *evlist, pid_t pid)
1118{
1119 return perf_evlist__set_filter_pids(evlist, 1, &pid);
1120}
1121
1089bool perf_evlist__valid_sample_type(struct perf_evlist *evlist) 1122bool perf_evlist__valid_sample_type(struct perf_evlist *evlist)
1090{ 1123{
1091 struct perf_evsel *pos; 1124 struct perf_evsel *pos;
@@ -1329,7 +1362,7 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *tar
1329 * writing exactly one byte, in workload.cork_fd, usually via 1362 * writing exactly one byte, in workload.cork_fd, usually via
1330 * perf_evlist__start_workload(). 1363 * perf_evlist__start_workload().
1331 * 1364 *
1332 * For cancelling the workload without actuallin running it, 1365 * For cancelling the workload without actually running it,
1333 * the parent will just close workload.cork_fd, without writing 1366 * the parent will just close workload.cork_fd, without writing
1334 * anything, i.e. read will return zero and we just exit() 1367 * anything, i.e. read will return zero and we just exit()
1335 * here. 1368 * here.
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index e99a67632831..fb19c47b8aac 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -51,6 +51,7 @@ struct perf_evlist {
51 struct thread_map *threads; 51 struct thread_map *threads;
52 struct cpu_map *cpus; 52 struct cpu_map *cpus;
53 struct perf_evsel *selected; 53 struct perf_evsel *selected;
54 struct events_stats stats;
54}; 55};
55 56
56struct perf_evsel_str_handler { 57struct perf_evsel_str_handler {
@@ -77,6 +78,8 @@ int perf_evlist__add_newtp(struct perf_evlist *evlist,
77 const char *sys, const char *name, void *handler); 78 const char *sys, const char *name, void *handler);
78 79
79int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter); 80int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter);
81int perf_evlist__set_filter_pid(struct perf_evlist *evlist, pid_t pid);
82int perf_evlist__set_filter_pids(struct perf_evlist *evlist, size_t npids, pid_t *pids);
80 83
81struct perf_evsel * 84struct perf_evsel *
82perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id); 85perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id);
@@ -149,7 +152,7 @@ static inline void perf_evlist__set_maps(struct perf_evlist *evlist,
149} 152}
150 153
151int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target); 154int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target);
152int perf_evlist__apply_filters(struct perf_evlist *evlist); 155int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **err_evsel);
153 156
154void __perf_evlist__set_leader(struct list_head *list); 157void __perf_evlist__set_leader(struct list_head *list);
155void perf_evlist__set_leader(struct perf_evlist *evlist); 158void perf_evlist__set_leader(struct perf_evlist *evlist);
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index ea51a90e20a0..358e5954baa8 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -537,13 +537,30 @@ int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size)
537} 537}
538 538
539static void 539static void
540perf_evsel__config_callgraph(struct perf_evsel *evsel) 540perf_evsel__config_callgraph(struct perf_evsel *evsel,
541 struct record_opts *opts)
541{ 542{
542 bool function = perf_evsel__is_function_event(evsel); 543 bool function = perf_evsel__is_function_event(evsel);
543 struct perf_event_attr *attr = &evsel->attr; 544 struct perf_event_attr *attr = &evsel->attr;
544 545
545 perf_evsel__set_sample_bit(evsel, CALLCHAIN); 546 perf_evsel__set_sample_bit(evsel, CALLCHAIN);
546 547
548 if (callchain_param.record_mode == CALLCHAIN_LBR) {
549 if (!opts->branch_stack) {
550 if (attr->exclude_user) {
551 pr_warning("LBR callstack option is only available "
552 "to get user callchain information. "
553 "Falling back to framepointers.\n");
554 } else {
555 perf_evsel__set_sample_bit(evsel, BRANCH_STACK);
556 attr->branch_sample_type = PERF_SAMPLE_BRANCH_USER |
557 PERF_SAMPLE_BRANCH_CALL_STACK;
558 }
559 } else
560 pr_warning("Cannot use LBR callstack with branch stack. "
561 "Falling back to framepointers.\n");
562 }
563
547 if (callchain_param.record_mode == CALLCHAIN_DWARF) { 564 if (callchain_param.record_mode == CALLCHAIN_DWARF) {
548 if (!function) { 565 if (!function) {
549 perf_evsel__set_sample_bit(evsel, REGS_USER); 566 perf_evsel__set_sample_bit(evsel, REGS_USER);
@@ -667,7 +684,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
667 evsel->attr.exclude_callchain_user = 1; 684 evsel->attr.exclude_callchain_user = 1;
668 685
669 if (callchain_param.enabled && !evsel->no_aux_samples) 686 if (callchain_param.enabled && !evsel->no_aux_samples)
670 perf_evsel__config_callgraph(evsel); 687 perf_evsel__config_callgraph(evsel, opts);
671 688
672 if (opts->sample_intr_regs) { 689 if (opts->sample_intr_regs) {
673 attr->sample_regs_intr = PERF_REGS_MASK; 690 attr->sample_regs_intr = PERF_REGS_MASK;
@@ -717,6 +734,12 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
717 if (opts->sample_transaction) 734 if (opts->sample_transaction)
718 perf_evsel__set_sample_bit(evsel, TRANSACTION); 735 perf_evsel__set_sample_bit(evsel, TRANSACTION);
719 736
737 if (opts->running_time) {
738 evsel->attr.read_format |=
739 PERF_FORMAT_TOTAL_TIME_ENABLED |
740 PERF_FORMAT_TOTAL_TIME_RUNNING;
741 }
742
720 /* 743 /*
721 * XXX see the function comment above 744 * XXX see the function comment above
722 * 745 *
@@ -1892,7 +1915,7 @@ u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample,
1892 value = *(u32 *)ptr; 1915 value = *(u32 *)ptr;
1893 break; 1916 break;
1894 case 8: 1917 case 8:
1895 value = *(u64 *)ptr; 1918 memcpy(&value, ptr, sizeof(u64));
1896 break; 1919 break;
1897 default: 1920 default:
1898 return 0; 1921 return 0;
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 38622747d130..dcf202aebe9f 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -355,4 +355,8 @@ for ((_evsel) = list_entry((_leader)->node.next, struct perf_evsel, node); \
355 (_evsel) && (_evsel)->leader == (_leader); \ 355 (_evsel) && (_evsel)->leader == (_leader); \
356 (_evsel) = list_entry((_evsel)->node.next, struct perf_evsel, node)) 356 (_evsel) = list_entry((_evsel)->node.next, struct perf_evsel, node))
357 357
358static inline bool has_branch_callstack(struct perf_evsel *evsel)
359{
360 return evsel->attr.branch_sample_type & PERF_SAMPLE_BRANCH_CALL_STACK;
361}
358#endif /* __PERF_EVSEL_H */ 362#endif /* __PERF_EVSEL_H */
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 1f407f7352a7..fb432153e2aa 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -1266,7 +1266,7 @@ static int __event_process_build_id(struct build_id_event *bev,
1266 1266
1267 dso__set_build_id(dso, &bev->build_id); 1267 dso__set_build_id(dso, &bev->build_id);
1268 1268
1269 if (!is_kernel_module(filename, NULL)) 1269 if (!is_kernel_module(filename))
1270 dso->kernel = dso_type; 1270 dso->kernel = dso_type;
1271 1271
1272 build_id__sprintf(dso->build_id, sizeof(dso->build_id), 1272 build_id__sprintf(dso->build_id, sizeof(dso->build_id),
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 70b48a65064c..cc22b9158b93 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -263,15 +263,9 @@ void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel)
263 while (next) { 263 while (next) {
264 n = rb_entry(next, struct hist_entry, rb_node); 264 n = rb_entry(next, struct hist_entry, rb_node);
265 next = rb_next(&n->rb_node); 265 next = rb_next(&n->rb_node);
266 /*
267 * We may be annotating this, for instance, so keep it here in
268 * case some it gets new samples, we'll eventually free it when
269 * the user stops browsing and it agains gets fully decayed.
270 */
271 if (((zap_user && n->level == '.') || 266 if (((zap_user && n->level == '.') ||
272 (zap_kernel && n->level != '.') || 267 (zap_kernel && n->level != '.') ||
273 hists__decay_entry(hists, n)) && 268 hists__decay_entry(hists, n))) {
274 !n->used) {
275 hists__delete_entry(hists, n); 269 hists__delete_entry(hists, n);
276 } 270 }
277 } 271 }
@@ -355,6 +349,7 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template,
355 callchain_init(he->callchain); 349 callchain_init(he->callchain);
356 350
357 INIT_LIST_HEAD(&he->pairs.node); 351 INIT_LIST_HEAD(&he->pairs.node);
352 thread__get(he->thread);
358 } 353 }
359 354
360 return he; 355 return he;
@@ -941,6 +936,7 @@ hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
941 936
942void hist_entry__delete(struct hist_entry *he) 937void hist_entry__delete(struct hist_entry *he)
943{ 938{
939 thread__zput(he->thread);
944 zfree(&he->branch_info); 940 zfree(&he->branch_info);
945 zfree(&he->mem_info); 941 zfree(&he->mem_info);
946 zfree(&he->stat_acc); 942 zfree(&he->stat_acc);
@@ -1169,6 +1165,7 @@ static void hists__remove_entry_filter(struct hists *hists, struct hist_entry *h
1169 /* force fold unfiltered entry for simplicity */ 1165 /* force fold unfiltered entry for simplicity */
1170 h->ms.unfolded = false; 1166 h->ms.unfolded = false;
1171 h->row_offset = 0; 1167 h->row_offset = 0;
1168 h->nr_rows = 0;
1172 1169
1173 hists->stats.nr_non_filtered_samples += h->stat.nr_events; 1170 hists->stats.nr_non_filtered_samples += h->stat.nr_events;
1174 1171
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 2b690d028907..9f31b89a527a 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -60,7 +60,7 @@ struct hists {
60 struct rb_root entries_collapsed; 60 struct rb_root entries_collapsed;
61 u64 nr_entries; 61 u64 nr_entries;
62 u64 nr_non_filtered_entries; 62 u64 nr_non_filtered_entries;
63 const struct thread *thread_filter; 63 struct thread *thread_filter;
64 const struct dso *dso_filter; 64 const struct dso *dso_filter;
65 const char *uid_filter_str; 65 const char *uid_filter_str;
66 const char *symbol_filter_str; 66 const char *symbol_filter_str;
@@ -303,6 +303,9 @@ struct hist_browser_timer {
303 303
304#ifdef HAVE_SLANG_SUPPORT 304#ifdef HAVE_SLANG_SUPPORT
305#include "../ui/keysyms.h" 305#include "../ui/keysyms.h"
306int map_symbol__tui_annotate(struct map_symbol *ms, struct perf_evsel *evsel,
307 struct hist_browser_timer *hbt);
308
306int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel, 309int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel,
307 struct hist_browser_timer *hbt); 310 struct hist_browser_timer *hbt);
308 311
@@ -321,6 +324,12 @@ int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused,
321{ 324{
322 return 0; 325 return 0;
323} 326}
327static inline int map_symbol__tui_annotate(struct map_symbol *ms __maybe_unused,
328 struct perf_evsel *evsel __maybe_unused,
329 struct hist_browser_timer *hbt __maybe_unused)
330{
331 return 0;
332}
324 333
325static inline int hist_entry__tui_annotate(struct hist_entry *he __maybe_unused, 334static inline int hist_entry__tui_annotate(struct hist_entry *he __maybe_unused,
326 struct perf_evsel *evsel __maybe_unused, 335 struct perf_evsel *evsel __maybe_unused,
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 @@
1#include <lzma.h>
2#include <stdio.h>
3#include <linux/compiler.h>
4#include "util.h"
5#include "debug.h"
6
7#define BUFSIZE 8192
8
9static const char *lzma_strerror(lzma_ret ret)
10{
11 switch ((int) ret) {
12 case LZMA_MEM_ERROR:
13 return "Memory allocation failed";
14 case LZMA_OPTIONS_ERROR:
15 return "Unsupported decompressor flags";
16 case LZMA_FORMAT_ERROR:
17 return "The input is not in the .xz format";
18 case LZMA_DATA_ERROR:
19 return "Compressed file is corrupt";
20 case LZMA_BUF_ERROR:
21 return "Compressed file is truncated or otherwise corrupt";
22 default:
23 return "Unknown error, possibly a bug";
24 }
25}
26
27int lzma_decompress_to_file(const char *input, int output_fd)
28{
29 lzma_action action = LZMA_RUN;
30 lzma_stream strm = LZMA_STREAM_INIT;
31 lzma_ret ret;
32
33 u8 buf_in[BUFSIZE];
34 u8 buf_out[BUFSIZE];
35 FILE *infile;
36
37 infile = fopen(input, "rb");
38 if (!infile) {
39 pr_err("lzma: fopen failed on %s: '%s'\n",
40 input, strerror(errno));
41 return -1;
42 }
43
44 ret = lzma_stream_decoder(&strm, UINT64_MAX, LZMA_CONCATENATED);
45 if (ret != LZMA_OK) {
46 pr_err("lzma: lzma_stream_decoder failed %s (%d)\n",
47 lzma_strerror(ret), ret);
48 return -1;
49 }
50
51 strm.next_in = NULL;
52 strm.avail_in = 0;
53 strm.next_out = buf_out;
54 strm.avail_out = sizeof(buf_out);
55
56 while (1) {
57 if (strm.avail_in == 0 && !feof(infile)) {
58 strm.next_in = buf_in;
59 strm.avail_in = fread(buf_in, 1, sizeof(buf_in), infile);
60
61 if (ferror(infile)) {
62 pr_err("lzma: read error: %s\n", strerror(errno));
63 return -1;
64 }
65
66 if (feof(infile))
67 action = LZMA_FINISH;
68 }
69
70 ret = lzma_code(&strm, action);
71
72 if (strm.avail_out == 0 || ret == LZMA_STREAM_END) {
73 ssize_t write_size = sizeof(buf_out) - strm.avail_out;
74
75 if (writen(output_fd, buf_out, write_size) != write_size) {
76 pr_err("lzma: write error: %s\n", strerror(errno));
77 return -1;
78 }
79
80 strm.next_out = buf_out;
81 strm.avail_out = sizeof(buf_out);
82 }
83
84 if (ret != LZMA_OK) {
85 if (ret == LZMA_STREAM_END)
86 return 0;
87
88 pr_err("lzma: failed %s\n", lzma_strerror(ret));
89 return -1;
90 }
91 }
92
93 fclose(infile);
94 return 0;
95}
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 1bca3a9f2b16..e3353307330c 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -14,6 +14,8 @@
14#include "unwind.h" 14#include "unwind.h"
15#include "linux/hash.h" 15#include "linux/hash.h"
16 16
17static void machine__remove_thread(struct machine *machine, struct thread *th);
18
17static void dsos__init(struct dsos *dsos) 19static void dsos__init(struct dsos *dsos)
18{ 20{
19 INIT_LIST_HEAD(&dsos->head); 21 INIT_LIST_HEAD(&dsos->head);
@@ -89,16 +91,6 @@ static void dsos__delete(struct dsos *dsos)
89 } 91 }
90} 92}
91 93
92void machine__delete_dead_threads(struct machine *machine)
93{
94 struct thread *n, *t;
95
96 list_for_each_entry_safe(t, n, &machine->dead_threads, node) {
97 list_del(&t->node);
98 thread__delete(t);
99 }
100}
101
102void machine__delete_threads(struct machine *machine) 94void machine__delete_threads(struct machine *machine)
103{ 95{
104 struct rb_node *nd = rb_first(&machine->threads); 96 struct rb_node *nd = rb_first(&machine->threads);
@@ -106,9 +98,8 @@ void machine__delete_threads(struct machine *machine)
106 while (nd) { 98 while (nd) {
107 struct thread *t = rb_entry(nd, struct thread, rb_node); 99 struct thread *t = rb_entry(nd, struct thread, rb_node);
108 100
109 rb_erase(&t->rb_node, &machine->threads);
110 nd = rb_next(nd); 101 nd = rb_next(nd);
111 thread__delete(t); 102 machine__remove_thread(machine, t);
112 } 103 }
113} 104}
114 105
@@ -361,9 +352,13 @@ static struct thread *__machine__findnew_thread(struct machine *machine,
361 * the full rbtree: 352 * the full rbtree:
362 */ 353 */
363 th = machine->last_match; 354 th = machine->last_match;
364 if (th && th->tid == tid) { 355 if (th != NULL) {
365 machine__update_thread_pid(machine, th, pid); 356 if (th->tid == tid) {
366 return th; 357 machine__update_thread_pid(machine, th, pid);
358 return th;
359 }
360
361 thread__zput(machine->last_match);
367 } 362 }
368 363
369 while (*p != NULL) { 364 while (*p != NULL) {
@@ -371,7 +366,7 @@ static struct thread *__machine__findnew_thread(struct machine *machine,
371 th = rb_entry(parent, struct thread, rb_node); 366 th = rb_entry(parent, struct thread, rb_node);
372 367
373 if (th->tid == tid) { 368 if (th->tid == tid) {
374 machine->last_match = th; 369 machine->last_match = thread__get(th);
375 machine__update_thread_pid(machine, th, pid); 370 machine__update_thread_pid(machine, th, pid);
376 return th; 371 return th;
377 } 372 }
@@ -403,8 +398,11 @@ static struct thread *__machine__findnew_thread(struct machine *machine,
403 thread__delete(th); 398 thread__delete(th);
404 return NULL; 399 return NULL;
405 } 400 }
406 401 /*
407 machine->last_match = th; 402 * It is now in the rbtree, get a ref
403 */
404 thread__get(th);
405 machine->last_match = thread__get(th);
408 } 406 }
409 407
410 return th; 408 return th;
@@ -462,30 +460,61 @@ int machine__process_lost_event(struct machine *machine __maybe_unused,
462 return 0; 460 return 0;
463} 461}
464 462
463static struct dso*
464machine__module_dso(struct machine *machine, struct kmod_path *m,
465 const char *filename)
466{
467 struct dso *dso;
468
469 dso = dsos__find(&machine->kernel_dsos, m->name, true);
470 if (!dso) {
471 dso = dsos__addnew(&machine->kernel_dsos, m->name);
472 if (dso == NULL)
473 return NULL;
474
475 if (machine__is_host(machine))
476 dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE;
477 else
478 dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE;
479
480 /* _KMODULE_COMP should be next to _KMODULE */
481 if (m->kmod && m->comp)
482 dso->symtab_type++;
483
484 dso__set_short_name(dso, strdup(m->name), true);
485 dso__set_long_name(dso, strdup(filename), true);
486 }
487
488 return dso;
489}
490
465struct map *machine__new_module(struct machine *machine, u64 start, 491struct map *machine__new_module(struct machine *machine, u64 start,
466 const char *filename) 492 const char *filename)
467{ 493{
468 struct map *map; 494 struct map *map = NULL;
469 struct dso *dso = __dsos__findnew(&machine->kernel_dsos, filename); 495 struct dso *dso;
470 bool compressed; 496 struct kmod_path m;
471 497
472 if (dso == NULL) 498 if (kmod_path__parse_name(&m, filename))
473 return NULL; 499 return NULL;
474 500
475 map = map__new2(start, dso, MAP__FUNCTION); 501 map = map_groups__find_by_name(&machine->kmaps, MAP__FUNCTION,
476 if (map == NULL) 502 m.name);
477 return NULL; 503 if (map)
504 goto out;
478 505
479 if (machine__is_host(machine)) 506 dso = machine__module_dso(machine, &m, filename);
480 dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE; 507 if (dso == NULL)
481 else 508 goto out;
482 dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE;
483 509
484 /* _KMODULE_COMP should be next to _KMODULE */ 510 map = map__new2(start, dso, MAP__FUNCTION);
485 if (is_kernel_module(filename, &compressed) && compressed) 511 if (map == NULL)
486 dso->symtab_type++; 512 goto out;
487 513
488 map_groups__insert(&machine->kmaps, map); 514 map_groups__insert(&machine->kmaps, map);
515
516out:
517 free(m.name);
489 return map; 518 return map;
490} 519}
491 520
@@ -827,6 +856,39 @@ static char *get_kernel_version(const char *root_dir)
827 return strdup(name); 856 return strdup(name);
828} 857}
829 858
859static bool is_kmod_dso(struct dso *dso)
860{
861 return dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE ||
862 dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE;
863}
864
865static int map_groups__set_module_path(struct map_groups *mg, const char *path,
866 struct kmod_path *m)
867{
868 struct map *map;
869 char *long_name;
870
871 map = map_groups__find_by_name(mg, MAP__FUNCTION, m->name);
872 if (map == NULL)
873 return 0;
874
875 long_name = strdup(path);
876 if (long_name == NULL)
877 return -ENOMEM;
878
879 dso__set_long_name(map->dso, long_name, true);
880 dso__kernel_module_get_build_id(map->dso, "");
881
882 /*
883 * Full name could reveal us kmod compression, so
884 * we need to update the symtab_type if needed.
885 */
886 if (m->comp && is_kmod_dso(map->dso))
887 map->dso->symtab_type++;
888
889 return 0;
890}
891
830static int map_groups__set_modules_path_dir(struct map_groups *mg, 892static int map_groups__set_modules_path_dir(struct map_groups *mg,
831 const char *dir_name, int depth) 893 const char *dir_name, int depth)
832{ 894{
@@ -865,35 +927,19 @@ static int map_groups__set_modules_path_dir(struct map_groups *mg,
865 if (ret < 0) 927 if (ret < 0)
866 goto out; 928 goto out;
867 } else { 929 } else {
868 char *dot = strrchr(dent->d_name, '.'), 930 struct kmod_path m;
869 dso_name[PATH_MAX];
870 struct map *map;
871 char *long_name;
872 931
873 if (dot == NULL) 932 ret = kmod_path__parse_name(&m, dent->d_name);
874 continue; 933 if (ret)
934 goto out;
875 935
876 /* On some system, modules are compressed like .ko.gz */ 936 if (m.kmod)
877 if (is_supported_compression(dot + 1) && 937 ret = map_groups__set_module_path(mg, path, &m);
878 is_kmodule_extension(dot - 2))
879 dot -= 3;
880 938
881 snprintf(dso_name, sizeof(dso_name), "[%.*s]", 939 free(m.name);
882 (int)(dot - dent->d_name), dent->d_name);
883 940
884 strxfrchar(dso_name, '-', '_'); 941 if (ret)
885 map = map_groups__find_by_name(mg, MAP__FUNCTION,
886 dso_name);
887 if (map == NULL)
888 continue;
889
890 long_name = strdup(path);
891 if (long_name == NULL) {
892 ret = -1;
893 goto out; 942 goto out;
894 }
895 dso__set_long_name(map->dso, long_name, true);
896 dso__kernel_module_get_build_id(map->dso, "");
897 } 943 }
898 } 944 }
899 945
@@ -1046,40 +1092,11 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
1046 strlen(kmmap_prefix) - 1) == 0; 1092 strlen(kmmap_prefix) - 1) == 0;
1047 if (event->mmap.filename[0] == '/' || 1093 if (event->mmap.filename[0] == '/' ||
1048 (!is_kernel_mmap && event->mmap.filename[0] == '[')) { 1094 (!is_kernel_mmap && event->mmap.filename[0] == '[')) {
1049
1050 char short_module_name[1024];
1051 char *name, *dot;
1052
1053 if (event->mmap.filename[0] == '/') {
1054 name = strrchr(event->mmap.filename, '/');
1055 if (name == NULL)
1056 goto out_problem;
1057
1058 ++name; /* skip / */
1059 dot = strrchr(name, '.');
1060 if (dot == NULL)
1061 goto out_problem;
1062 /* On some system, modules are compressed like .ko.gz */
1063 if (is_supported_compression(dot + 1))
1064 dot -= 3;
1065 if (!is_kmodule_extension(dot + 1))
1066 goto out_problem;
1067 snprintf(short_module_name, sizeof(short_module_name),
1068 "[%.*s]", (int)(dot - name), name);
1069 strxfrchar(short_module_name, '-', '_');
1070 } else
1071 strcpy(short_module_name, event->mmap.filename);
1072
1073 map = machine__new_module(machine, event->mmap.start, 1095 map = machine__new_module(machine, event->mmap.start,
1074 event->mmap.filename); 1096 event->mmap.filename);
1075 if (map == NULL) 1097 if (map == NULL)
1076 goto out_problem; 1098 goto out_problem;
1077 1099
1078 name = strdup(short_module_name);
1079 if (name == NULL)
1080 goto out_problem;
1081
1082 dso__set_short_name(map->dso, name, true);
1083 map->end = map->start + event->mmap.len; 1100 map->end = map->start + event->mmap.len;
1084 } else if (is_kernel_mmap) { 1101 } else if (is_kernel_mmap) {
1085 const char *symbol_name = (event->mmap.filename + 1102 const char *symbol_name = (event->mmap.filename +
@@ -1092,7 +1109,7 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
1092 struct dso *dso; 1109 struct dso *dso;
1093 1110
1094 list_for_each_entry(dso, &machine->kernel_dsos.head, node) { 1111 list_for_each_entry(dso, &machine->kernel_dsos.head, node) {
1095 if (is_kernel_module(dso->long_name, NULL)) 1112 if (is_kernel_module(dso->long_name))
1096 continue; 1113 continue;
1097 1114
1098 kernel = dso; 1115 kernel = dso;
@@ -1238,13 +1255,17 @@ out_problem:
1238 1255
1239static void machine__remove_thread(struct machine *machine, struct thread *th) 1256static void machine__remove_thread(struct machine *machine, struct thread *th)
1240{ 1257{
1241 machine->last_match = NULL; 1258 if (machine->last_match == th)
1259 thread__zput(machine->last_match);
1260
1242 rb_erase(&th->rb_node, &machine->threads); 1261 rb_erase(&th->rb_node, &machine->threads);
1243 /* 1262 /*
1244 * We may have references to this thread, for instance in some hist_entry 1263 * Move it first to the dead_threads list, then drop the reference,
1245 * instances, so just move them to a separate list. 1264 * if this is the last reference, then the thread__delete destructor
1265 * will be called and we will remove it from the dead_threads list.
1246 */ 1266 */
1247 list_add_tail(&th->node, &machine->dead_threads); 1267 list_add_tail(&th->node, &machine->dead_threads);
1268 thread__put(th);
1248} 1269}
1249 1270
1250int machine__process_fork_event(struct machine *machine, union perf_event *event, 1271int machine__process_fork_event(struct machine *machine, union perf_event *event,
@@ -1502,18 +1523,100 @@ static int remove_loops(struct branch_entry *l, int nr)
1502 return nr; 1523 return nr;
1503} 1524}
1504 1525
1505static int thread__resolve_callchain_sample(struct thread *thread, 1526/*
1506 struct ip_callchain *chain, 1527 * Recolve LBR callstack chain sample
1507 struct branch_stack *branch, 1528 * Return:
1508 struct symbol **parent, 1529 * 1 on success get LBR callchain information
1509 struct addr_location *root_al, 1530 * 0 no available LBR callchain information, should try fp
1510 int max_stack) 1531 * negative error code on other errors.
1532 */
1533static int resolve_lbr_callchain_sample(struct thread *thread,
1534 struct perf_sample *sample,
1535 struct symbol **parent,
1536 struct addr_location *root_al,
1537 int max_stack)
1511{ 1538{
1539 struct ip_callchain *chain = sample->callchain;
1540 int chain_nr = min(max_stack, (int)chain->nr);
1541 int i, j, err;
1542 u64 ip;
1543
1544 for (i = 0; i < chain_nr; i++) {
1545 if (chain->ips[i] == PERF_CONTEXT_USER)
1546 break;
1547 }
1548
1549 /* LBR only affects the user callchain */
1550 if (i != chain_nr) {
1551 struct branch_stack *lbr_stack = sample->branch_stack;
1552 int lbr_nr = lbr_stack->nr;
1553 /*
1554 * LBR callstack can only get user call chain.
1555 * The mix_chain_nr is kernel call chain
1556 * number plus LBR user call chain number.
1557 * i is kernel call chain number,
1558 * 1 is PERF_CONTEXT_USER,
1559 * lbr_nr + 1 is the user call chain number.
1560 * For details, please refer to the comments
1561 * in callchain__printf
1562 */
1563 int mix_chain_nr = i + 1 + lbr_nr + 1;
1564
1565 if (mix_chain_nr > PERF_MAX_STACK_DEPTH + PERF_MAX_BRANCH_DEPTH) {
1566 pr_warning("corrupted callchain. skipping...\n");
1567 return 0;
1568 }
1569
1570 for (j = 0; j < mix_chain_nr; j++) {
1571 if (callchain_param.order == ORDER_CALLEE) {
1572 if (j < i + 1)
1573 ip = chain->ips[j];
1574 else if (j > i + 1)
1575 ip = lbr_stack->entries[j - i - 2].from;
1576 else
1577 ip = lbr_stack->entries[0].to;
1578 } else {
1579 if (j < lbr_nr)
1580 ip = lbr_stack->entries[lbr_nr - j - 1].from;
1581 else if (j > lbr_nr)
1582 ip = chain->ips[i + 1 - (j - lbr_nr)];
1583 else
1584 ip = lbr_stack->entries[0].to;
1585 }
1586
1587 err = add_callchain_ip(thread, parent, root_al, false, ip);
1588 if (err)
1589 return (err < 0) ? err : 0;
1590 }
1591 return 1;
1592 }
1593
1594 return 0;
1595}
1596
1597static int thread__resolve_callchain_sample(struct thread *thread,
1598 struct perf_evsel *evsel,
1599 struct perf_sample *sample,
1600 struct symbol **parent,
1601 struct addr_location *root_al,
1602 int max_stack)
1603{
1604 struct branch_stack *branch = sample->branch_stack;
1605 struct ip_callchain *chain = sample->callchain;
1512 int chain_nr = min(max_stack, (int)chain->nr); 1606 int chain_nr = min(max_stack, (int)chain->nr);
1513 int i, j, err; 1607 int i, j, err;
1514 int skip_idx = -1; 1608 int skip_idx = -1;
1515 int first_call = 0; 1609 int first_call = 0;
1516 1610
1611 callchain_cursor_reset(&callchain_cursor);
1612
1613 if (has_branch_callstack(evsel)) {
1614 err = resolve_lbr_callchain_sample(thread, sample, parent,
1615 root_al, max_stack);
1616 if (err)
1617 return (err < 0) ? err : 0;
1618 }
1619
1517 /* 1620 /*
1518 * Based on DWARF debug information, some architectures skip 1621 * Based on DWARF debug information, some architectures skip
1519 * a callchain entry saved by the kernel. 1622 * a callchain entry saved by the kernel.
@@ -1521,8 +1624,6 @@ static int thread__resolve_callchain_sample(struct thread *thread,
1521 if (chain->nr < PERF_MAX_STACK_DEPTH) 1624 if (chain->nr < PERF_MAX_STACK_DEPTH)
1522 skip_idx = arch_skip_callchain_idx(thread, chain); 1625 skip_idx = arch_skip_callchain_idx(thread, chain);
1523 1626
1524 callchain_cursor_reset(&callchain_cursor);
1525
1526 /* 1627 /*
1527 * Add branches to call stack for easier browsing. This gives 1628 * Add branches to call stack for easier browsing. This gives
1528 * more context for a sample than just the callers. 1629 * more context for a sample than just the callers.
@@ -1623,9 +1724,9 @@ int thread__resolve_callchain(struct thread *thread,
1623 struct addr_location *root_al, 1724 struct addr_location *root_al,
1624 int max_stack) 1725 int max_stack)
1625{ 1726{
1626 int ret = thread__resolve_callchain_sample(thread, sample->callchain, 1727 int ret = thread__resolve_callchain_sample(thread, evsel,
1627 sample->branch_stack, 1728 sample, parent,
1628 parent, root_al, max_stack); 1729 root_al, max_stack);
1629 if (ret) 1730 if (ret)
1630 return ret; 1731 return ret;
1631 1732
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index e8b7779a0a3f..e2faf3b47e7b 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -118,7 +118,6 @@ void machines__set_comm_exec(struct machines *machines, bool comm_exec);
118struct machine *machine__new_host(void); 118struct machine *machine__new_host(void);
119int machine__init(struct machine *machine, const char *root_dir, pid_t pid); 119int machine__init(struct machine *machine, const char *root_dir, pid_t pid);
120void machine__exit(struct machine *machine); 120void machine__exit(struct machine *machine);
121void machine__delete_dead_threads(struct machine *machine);
122void machine__delete_threads(struct machine *machine); 121void machine__delete_threads(struct machine *machine);
123void machine__delete(struct machine *machine); 122void machine__delete(struct machine *machine);
124 123
diff --git a/tools/perf/util/ordered-events.c b/tools/perf/util/ordered-events.c
index fd4be94125fb..6002fa3fcf77 100644
--- a/tools/perf/util/ordered-events.c
+++ b/tools/perf/util/ordered-events.c
@@ -131,8 +131,8 @@ static struct ordered_event *alloc_event(struct ordered_events *oe,
131 return new; 131 return new;
132} 132}
133 133
134struct ordered_event * 134static struct ordered_event *
135ordered_events__new(struct ordered_events *oe, u64 timestamp, 135ordered_events__new_event(struct ordered_events *oe, u64 timestamp,
136 union perf_event *event) 136 union perf_event *event)
137{ 137{
138 struct ordered_event *new; 138 struct ordered_event *new;
@@ -153,10 +153,38 @@ void ordered_events__delete(struct ordered_events *oe, struct ordered_event *eve
153 free_dup_event(oe, event->event); 153 free_dup_event(oe, event->event);
154} 154}
155 155
156static int __ordered_events__flush(struct perf_session *s, 156int ordered_events__queue(struct ordered_events *oe, union perf_event *event,
157 struct perf_tool *tool) 157 struct perf_sample *sample, u64 file_offset)
158{
159 u64 timestamp = sample->time;
160 struct ordered_event *oevent;
161
162 if (!timestamp || timestamp == ~0ULL)
163 return -ETIME;
164
165 if (timestamp < oe->last_flush) {
166 pr_oe_time(timestamp, "out of order event\n");
167 pr_oe_time(oe->last_flush, "last flush, last_flush_type %d\n",
168 oe->last_flush_type);
169
170 oe->evlist->stats.nr_unordered_events++;
171 }
172
173 oevent = ordered_events__new_event(oe, timestamp, event);
174 if (!oevent) {
175 ordered_events__flush(oe, OE_FLUSH__HALF);
176 oevent = ordered_events__new_event(oe, timestamp, event);
177 }
178
179 if (!oevent)
180 return -ENOMEM;
181
182 oevent->file_offset = file_offset;
183 return 0;
184}
185
186static int __ordered_events__flush(struct ordered_events *oe)
158{ 187{
159 struct ordered_events *oe = &s->ordered_events;
160 struct list_head *head = &oe->events; 188 struct list_head *head = &oe->events;
161 struct ordered_event *tmp, *iter; 189 struct ordered_event *tmp, *iter;
162 struct perf_sample sample; 190 struct perf_sample sample;
@@ -166,7 +194,7 @@ static int __ordered_events__flush(struct perf_session *s,
166 struct ui_progress prog; 194 struct ui_progress prog;
167 int ret; 195 int ret;
168 196
169 if (!tool->ordered_events || !limit) 197 if (!limit)
170 return 0; 198 return 0;
171 199
172 if (show_progress) 200 if (show_progress)
@@ -179,12 +207,11 @@ static int __ordered_events__flush(struct perf_session *s,
179 if (iter->timestamp > limit) 207 if (iter->timestamp > limit)
180 break; 208 break;
181 209
182 ret = perf_evlist__parse_sample(s->evlist, iter->event, &sample); 210 ret = perf_evlist__parse_sample(oe->evlist, iter->event, &sample);
183 if (ret) 211 if (ret)
184 pr_err("Can't parse sample, err = %d\n", ret); 212 pr_err("Can't parse sample, err = %d\n", ret);
185 else { 213 else {
186 ret = perf_session__deliver_event(s, iter->event, &sample, tool, 214 ret = oe->deliver(oe, iter, &sample);
187 iter->file_offset);
188 if (ret) 215 if (ret)
189 return ret; 216 return ret;
190 } 217 }
@@ -204,10 +231,8 @@ static int __ordered_events__flush(struct perf_session *s,
204 return 0; 231 return 0;
205} 232}
206 233
207int ordered_events__flush(struct perf_session *s, struct perf_tool *tool, 234int ordered_events__flush(struct ordered_events *oe, enum oe_flush how)
208 enum oe_flush how)
209{ 235{
210 struct ordered_events *oe = &s->ordered_events;
211 static const char * const str[] = { 236 static const char * const str[] = {
212 "NONE", 237 "NONE",
213 "FINAL", 238 "FINAL",
@@ -216,6 +241,9 @@ int ordered_events__flush(struct perf_session *s, struct perf_tool *tool,
216 }; 241 };
217 int err; 242 int err;
218 243
244 if (oe->nr_events == 0)
245 return 0;
246
219 switch (how) { 247 switch (how) {
220 case OE_FLUSH__FINAL: 248 case OE_FLUSH__FINAL:
221 oe->next_flush = ULLONG_MAX; 249 oe->next_flush = ULLONG_MAX;
@@ -248,7 +276,7 @@ int ordered_events__flush(struct perf_session *s, struct perf_tool *tool,
248 str[how], oe->nr_events); 276 str[how], oe->nr_events);
249 pr_oe_time(oe->max_timestamp, "max_timestamp\n"); 277 pr_oe_time(oe->max_timestamp, "max_timestamp\n");
250 278
251 err = __ordered_events__flush(s, tool); 279 err = __ordered_events__flush(oe);
252 280
253 if (!err) { 281 if (!err) {
254 if (how == OE_FLUSH__ROUND) 282 if (how == OE_FLUSH__ROUND)
@@ -264,13 +292,19 @@ int ordered_events__flush(struct perf_session *s, struct perf_tool *tool,
264 return err; 292 return err;
265} 293}
266 294
267void ordered_events__init(struct ordered_events *oe) 295void ordered_events__init(struct ordered_events *oe, struct machines *machines,
296 struct perf_evlist *evlist, struct perf_tool *tool,
297 ordered_events__deliver_t deliver)
268{ 298{
269 INIT_LIST_HEAD(&oe->events); 299 INIT_LIST_HEAD(&oe->events);
270 INIT_LIST_HEAD(&oe->cache); 300 INIT_LIST_HEAD(&oe->cache);
271 INIT_LIST_HEAD(&oe->to_free); 301 INIT_LIST_HEAD(&oe->to_free);
272 oe->max_alloc_size = (u64) -1; 302 oe->max_alloc_size = (u64) -1;
273 oe->cur_alloc_size = 0; 303 oe->cur_alloc_size = 0;
304 oe->evlist = evlist;
305 oe->machines = machines;
306 oe->tool = tool;
307 oe->deliver = deliver;
274} 308}
275 309
276void ordered_events__free(struct ordered_events *oe) 310void ordered_events__free(struct ordered_events *oe)
diff --git a/tools/perf/util/ordered-events.h b/tools/perf/util/ordered-events.h
index 7b8f9b011f38..173e13f28c08 100644
--- a/tools/perf/util/ordered-events.h
+++ b/tools/perf/util/ordered-events.h
@@ -2,9 +2,11 @@
2#define __ORDERED_EVENTS_H 2#define __ORDERED_EVENTS_H
3 3
4#include <linux/types.h> 4#include <linux/types.h>
5#include "tool.h"
6 5
7struct perf_session; 6struct perf_tool;
7struct perf_evlist;
8struct perf_sample;
9struct machines;
8 10
9struct ordered_event { 11struct ordered_event {
10 u64 timestamp; 12 u64 timestamp;
@@ -20,6 +22,12 @@ enum oe_flush {
20 OE_FLUSH__HALF, 22 OE_FLUSH__HALF,
21}; 23};
22 24
25struct ordered_events;
26
27typedef int (*ordered_events__deliver_t)(struct ordered_events *oe,
28 struct ordered_event *event,
29 struct perf_sample *sample);
30
23struct ordered_events { 31struct ordered_events {
24 u64 last_flush; 32 u64 last_flush;
25 u64 next_flush; 33 u64 next_flush;
@@ -31,18 +39,23 @@ struct ordered_events {
31 struct list_head to_free; 39 struct list_head to_free;
32 struct ordered_event *buffer; 40 struct ordered_event *buffer;
33 struct ordered_event *last; 41 struct ordered_event *last;
42 struct machines *machines;
43 struct perf_evlist *evlist;
44 struct perf_tool *tool;
45 ordered_events__deliver_t deliver;
34 int buffer_idx; 46 int buffer_idx;
35 unsigned int nr_events; 47 unsigned int nr_events;
36 enum oe_flush last_flush_type; 48 enum oe_flush last_flush_type;
37 bool copy_on_queue; 49 bool copy_on_queue;
38}; 50};
39 51
40struct ordered_event *ordered_events__new(struct ordered_events *oe, u64 timestamp, 52int ordered_events__queue(struct ordered_events *oe, union perf_event *event,
41 union perf_event *event); 53 struct perf_sample *sample, u64 file_offset);
42void ordered_events__delete(struct ordered_events *oe, struct ordered_event *event); 54void ordered_events__delete(struct ordered_events *oe, struct ordered_event *event);
43int ordered_events__flush(struct perf_session *s, struct perf_tool *tool, 55int ordered_events__flush(struct ordered_events *oe, enum oe_flush how);
44 enum oe_flush how); 56void ordered_events__init(struct ordered_events *oe, struct machines *machines,
45void ordered_events__init(struct ordered_events *oe); 57 struct perf_evlist *evlsit, struct perf_tool *tool,
58 ordered_events__deliver_t deliver);
46void ordered_events__free(struct ordered_events *oe); 59void ordered_events__free(struct ordered_events *oe);
47 60
48static inline 61static inline
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 7f8ec6ce2823..fe07573d5ed4 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -20,11 +20,6 @@
20 20
21#define MAX_NAME_LEN 100 21#define MAX_NAME_LEN 100
22 22
23struct event_symbol {
24 const char *symbol;
25 const char *alias;
26};
27
28#ifdef PARSER_DEBUG 23#ifdef PARSER_DEBUG
29extern int parse_events_debug; 24extern int parse_events_debug;
30#endif 25#endif
@@ -39,7 +34,7 @@ static struct perf_pmu_event_symbol *perf_pmu_events_list;
39 */ 34 */
40static int perf_pmu_events_list_num; 35static int perf_pmu_events_list_num;
41 36
42static struct event_symbol event_symbols_hw[PERF_COUNT_HW_MAX] = { 37struct event_symbol event_symbols_hw[PERF_COUNT_HW_MAX] = {
43 [PERF_COUNT_HW_CPU_CYCLES] = { 38 [PERF_COUNT_HW_CPU_CYCLES] = {
44 .symbol = "cpu-cycles", 39 .symbol = "cpu-cycles",
45 .alias = "cycles", 40 .alias = "cycles",
@@ -82,7 +77,7 @@ static struct event_symbol event_symbols_hw[PERF_COUNT_HW_MAX] = {
82 }, 77 },
83}; 78};
84 79
85static struct event_symbol event_symbols_sw[PERF_COUNT_SW_MAX] = { 80struct event_symbol event_symbols_sw[PERF_COUNT_SW_MAX] = {
86 [PERF_COUNT_SW_CPU_CLOCK] = { 81 [PERF_COUNT_SW_CPU_CLOCK] = {
87 .symbol = "cpu-clock", 82 .symbol = "cpu-clock",
88 .alias = "", 83 .alias = "",
@@ -175,9 +170,6 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config)
175 char evt_path[MAXPATHLEN]; 170 char evt_path[MAXPATHLEN];
176 char dir_path[MAXPATHLEN]; 171 char dir_path[MAXPATHLEN];
177 172
178 if (debugfs_valid_mountpoint(tracing_events_path))
179 return NULL;
180
181 sys_dir = opendir(tracing_events_path); 173 sys_dir = opendir(tracing_events_path);
182 if (!sys_dir) 174 if (!sys_dir)
183 return NULL; 175 return NULL;
@@ -473,12 +465,6 @@ static int add_tracepoint_multi_sys(struct list_head *list, int *idx,
473int parse_events_add_tracepoint(struct list_head *list, int *idx, 465int parse_events_add_tracepoint(struct list_head *list, int *idx,
474 char *sys, char *event) 466 char *sys, char *event)
475{ 467{
476 int ret;
477
478 ret = debugfs_valid_mountpoint(tracing_events_path);
479 if (ret)
480 return ret;
481
482 if (strpbrk(sys, "*?")) 468 if (strpbrk(sys, "*?"))
483 return add_tracepoint_multi_sys(list, idx, sys, event); 469 return add_tracepoint_multi_sys(list, idx, sys, event);
484 else 470 else
@@ -1098,6 +1084,14 @@ static const char * const event_type_descriptors[] = {
1098 "Hardware breakpoint", 1084 "Hardware breakpoint",
1099}; 1085};
1100 1086
1087static int cmp_string(const void *a, const void *b)
1088{
1089 const char * const *as = a;
1090 const char * const *bs = b;
1091
1092 return strcmp(*as, *bs);
1093}
1094
1101/* 1095/*
1102 * Print the events from <debugfs_mount_point>/tracing/events 1096 * Print the events from <debugfs_mount_point>/tracing/events
1103 */ 1097 */
@@ -1109,18 +1103,21 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
1109 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; 1103 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
1110 char evt_path[MAXPATHLEN]; 1104 char evt_path[MAXPATHLEN];
1111 char dir_path[MAXPATHLEN]; 1105 char dir_path[MAXPATHLEN];
1112 char sbuf[STRERR_BUFSIZE]; 1106 char **evt_list = NULL;
1113 1107 unsigned int evt_i = 0, evt_num = 0;
1114 if (debugfs_valid_mountpoint(tracing_events_path)) { 1108 bool evt_num_known = false;
1115 printf(" [ Tracepoints not available: %s ]\n",
1116 strerror_r(errno, sbuf, sizeof(sbuf)));
1117 return;
1118 }
1119 1109
1110restart:
1120 sys_dir = opendir(tracing_events_path); 1111 sys_dir = opendir(tracing_events_path);
1121 if (!sys_dir) 1112 if (!sys_dir)
1122 return; 1113 return;
1123 1114
1115 if (evt_num_known) {
1116 evt_list = zalloc(sizeof(char *) * evt_num);
1117 if (!evt_list)
1118 goto out_close_sys_dir;
1119 }
1120
1124 for_each_subsystem(sys_dir, sys_dirent, sys_next) { 1121 for_each_subsystem(sys_dir, sys_dirent, sys_next) {
1125 if (subsys_glob != NULL && 1122 if (subsys_glob != NULL &&
1126 !strglobmatch(sys_dirent.d_name, subsys_glob)) 1123 !strglobmatch(sys_dirent.d_name, subsys_glob))
@@ -1137,19 +1134,56 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
1137 !strglobmatch(evt_dirent.d_name, event_glob)) 1134 !strglobmatch(evt_dirent.d_name, event_glob))
1138 continue; 1135 continue;
1139 1136
1140 if (name_only) { 1137 if (!evt_num_known) {
1141 printf("%s:%s ", sys_dirent.d_name, evt_dirent.d_name); 1138 evt_num++;
1142 continue; 1139 continue;
1143 } 1140 }
1144 1141
1145 snprintf(evt_path, MAXPATHLEN, "%s:%s", 1142 snprintf(evt_path, MAXPATHLEN, "%s:%s",
1146 sys_dirent.d_name, evt_dirent.d_name); 1143 sys_dirent.d_name, evt_dirent.d_name);
1147 printf(" %-50s [%s]\n", evt_path, 1144
1148 event_type_descriptors[PERF_TYPE_TRACEPOINT]); 1145 evt_list[evt_i] = strdup(evt_path);
1146 if (evt_list[evt_i] == NULL)
1147 goto out_close_evt_dir;
1148 evt_i++;
1149 } 1149 }
1150 closedir(evt_dir); 1150 closedir(evt_dir);
1151 } 1151 }
1152 closedir(sys_dir); 1152 closedir(sys_dir);
1153
1154 if (!evt_num_known) {
1155 evt_num_known = true;
1156 goto restart;
1157 }
1158 qsort(evt_list, evt_num, sizeof(char *), cmp_string);
1159 evt_i = 0;
1160 while (evt_i < evt_num) {
1161 if (name_only) {
1162 printf("%s ", evt_list[evt_i++]);
1163 continue;
1164 }
1165 printf(" %-50s [%s]\n", evt_list[evt_i++],
1166 event_type_descriptors[PERF_TYPE_TRACEPOINT]);
1167 }
1168 if (evt_num)
1169 printf("\n");
1170
1171out_free:
1172 evt_num = evt_i;
1173 for (evt_i = 0; evt_i < evt_num; evt_i++)
1174 zfree(&evt_list[evt_i]);
1175 zfree(&evt_list);
1176 return;
1177
1178out_close_evt_dir:
1179 closedir(evt_dir);
1180out_close_sys_dir:
1181 closedir(sys_dir);
1182
1183 printf("FATAL: not enough memory to print %s\n",
1184 event_type_descriptors[PERF_TYPE_TRACEPOINT]);
1185 if (evt_list)
1186 goto out_free;
1153} 1187}
1154 1188
1155/* 1189/*
@@ -1163,9 +1197,6 @@ int is_valid_tracepoint(const char *event_string)
1163 char evt_path[MAXPATHLEN]; 1197 char evt_path[MAXPATHLEN];
1164 char dir_path[MAXPATHLEN]; 1198 char dir_path[MAXPATHLEN];
1165 1199
1166 if (debugfs_valid_mountpoint(tracing_events_path))
1167 return 0;
1168
1169 sys_dir = opendir(tracing_events_path); 1200 sys_dir = opendir(tracing_events_path);
1170 if (!sys_dir) 1201 if (!sys_dir)
1171 return 0; 1202 return 0;
@@ -1233,38 +1264,19 @@ static bool is_event_supported(u8 type, unsigned config)
1233 return ret; 1264 return ret;
1234} 1265}
1235 1266
1236static void __print_events_type(u8 type, struct event_symbol *syms,
1237 unsigned max)
1238{
1239 char name[64];
1240 unsigned i;
1241
1242 for (i = 0; i < max ; i++, syms++) {
1243 if (!is_event_supported(type, i))
1244 continue;
1245
1246 if (strlen(syms->alias))
1247 snprintf(name, sizeof(name), "%s OR %s",
1248 syms->symbol, syms->alias);
1249 else
1250 snprintf(name, sizeof(name), "%s", syms->symbol);
1251
1252 printf(" %-50s [%s]\n", name, event_type_descriptors[type]);
1253 }
1254}
1255
1256void print_events_type(u8 type)
1257{
1258 if (type == PERF_TYPE_SOFTWARE)
1259 __print_events_type(type, event_symbols_sw, PERF_COUNT_SW_MAX);
1260 else
1261 __print_events_type(type, event_symbols_hw, PERF_COUNT_HW_MAX);
1262}
1263
1264int print_hwcache_events(const char *event_glob, bool name_only) 1267int print_hwcache_events(const char *event_glob, bool name_only)
1265{ 1268{
1266 unsigned int type, op, i, printed = 0; 1269 unsigned int type, op, i, evt_i = 0, evt_num = 0;
1267 char name[64]; 1270 char name[64];
1271 char **evt_list = NULL;
1272 bool evt_num_known = false;
1273
1274restart:
1275 if (evt_num_known) {
1276 evt_list = zalloc(sizeof(char *) * evt_num);
1277 if (!evt_list)
1278 goto out_enomem;
1279 }
1268 1280
1269 for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) { 1281 for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
1270 for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) { 1282 for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
@@ -1282,27 +1294,66 @@ int print_hwcache_events(const char *event_glob, bool name_only)
1282 type | (op << 8) | (i << 16))) 1294 type | (op << 8) | (i << 16)))
1283 continue; 1295 continue;
1284 1296
1285 if (name_only) 1297 if (!evt_num_known) {
1286 printf("%s ", name); 1298 evt_num++;
1287 else 1299 continue;
1288 printf(" %-50s [%s]\n", name, 1300 }
1289 event_type_descriptors[PERF_TYPE_HW_CACHE]); 1301
1290 ++printed; 1302 evt_list[evt_i] = strdup(name);
1303 if (evt_list[evt_i] == NULL)
1304 goto out_enomem;
1305 evt_i++;
1291 } 1306 }
1292 } 1307 }
1293 } 1308 }
1294 1309
1295 if (printed) 1310 if (!evt_num_known) {
1311 evt_num_known = true;
1312 goto restart;
1313 }
1314 qsort(evt_list, evt_num, sizeof(char *), cmp_string);
1315 evt_i = 0;
1316 while (evt_i < evt_num) {
1317 if (name_only) {
1318 printf("%s ", evt_list[evt_i++]);
1319 continue;
1320 }
1321 printf(" %-50s [%s]\n", evt_list[evt_i++],
1322 event_type_descriptors[PERF_TYPE_HW_CACHE]);
1323 }
1324 if (evt_num)
1296 printf("\n"); 1325 printf("\n");
1297 return printed; 1326
1327out_free:
1328 evt_num = evt_i;
1329 for (evt_i = 0; evt_i < evt_num; evt_i++)
1330 zfree(&evt_list[evt_i]);
1331 zfree(&evt_list);
1332 return evt_num;
1333
1334out_enomem:
1335 printf("FATAL: not enough memory to print %s\n", event_type_descriptors[PERF_TYPE_HW_CACHE]);
1336 if (evt_list)
1337 goto out_free;
1338 return evt_num;
1298} 1339}
1299 1340
1300static void print_symbol_events(const char *event_glob, unsigned type, 1341void print_symbol_events(const char *event_glob, unsigned type,
1301 struct event_symbol *syms, unsigned max, 1342 struct event_symbol *syms, unsigned max,
1302 bool name_only) 1343 bool name_only)
1303{ 1344{
1304 unsigned i, printed = 0; 1345 unsigned int i, evt_i = 0, evt_num = 0;
1305 char name[MAX_NAME_LEN]; 1346 char name[MAX_NAME_LEN];
1347 char **evt_list = NULL;
1348 bool evt_num_known = false;
1349
1350restart:
1351 if (evt_num_known) {
1352 evt_list = zalloc(sizeof(char *) * evt_num);
1353 if (!evt_list)
1354 goto out_enomem;
1355 syms -= max;
1356 }
1306 1357
1307 for (i = 0; i < max; i++, syms++) { 1358 for (i = 0; i < max; i++, syms++) {
1308 1359
@@ -1314,23 +1365,49 @@ static void print_symbol_events(const char *event_glob, unsigned type,
1314 if (!is_event_supported(type, i)) 1365 if (!is_event_supported(type, i))
1315 continue; 1366 continue;
1316 1367
1317 if (name_only) { 1368 if (!evt_num_known) {
1318 printf("%s ", syms->symbol); 1369 evt_num++;
1319 continue; 1370 continue;
1320 } 1371 }
1321 1372
1322 if (strlen(syms->alias)) 1373 if (!name_only && strlen(syms->alias))
1323 snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias); 1374 snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias);
1324 else 1375 else
1325 strncpy(name, syms->symbol, MAX_NAME_LEN); 1376 strncpy(name, syms->symbol, MAX_NAME_LEN);
1326 1377
1327 printf(" %-50s [%s]\n", name, event_type_descriptors[type]); 1378 evt_list[evt_i] = strdup(name);
1328 1379 if (evt_list[evt_i] == NULL)
1329 printed++; 1380 goto out_enomem;
1381 evt_i++;
1330 } 1382 }
1331 1383
1332 if (printed) 1384 if (!evt_num_known) {
1385 evt_num_known = true;
1386 goto restart;
1387 }
1388 qsort(evt_list, evt_num, sizeof(char *), cmp_string);
1389 evt_i = 0;
1390 while (evt_i < evt_num) {
1391 if (name_only) {
1392 printf("%s ", evt_list[evt_i++]);
1393 continue;
1394 }
1395 printf(" %-50s [%s]\n", evt_list[evt_i++], event_type_descriptors[type]);
1396 }
1397 if (evt_num)
1333 printf("\n"); 1398 printf("\n");
1399
1400out_free:
1401 evt_num = evt_i;
1402 for (evt_i = 0; evt_i < evt_num; evt_i++)
1403 zfree(&evt_list[evt_i]);
1404 zfree(&evt_list);
1405 return;
1406
1407out_enomem:
1408 printf("FATAL: not enough memory to print %s\n", event_type_descriptors[type]);
1409 if (evt_list)
1410 goto out_free;
1334} 1411}
1335 1412
1336/* 1413/*
@@ -1338,11 +1415,6 @@ static void print_symbol_events(const char *event_glob, unsigned type,
1338 */ 1415 */
1339void print_events(const char *event_glob, bool name_only) 1416void print_events(const char *event_glob, bool name_only)
1340{ 1417{
1341 if (!name_only) {
1342 printf("\n");
1343 printf("List of pre-defined events (to be used in -e):\n");
1344 }
1345
1346 print_symbol_events(event_glob, PERF_TYPE_HARDWARE, 1418 print_symbol_events(event_glob, PERF_TYPE_HARDWARE,
1347 event_symbols_hw, PERF_COUNT_HW_MAX, name_only); 1419 event_symbols_hw, PERF_COUNT_HW_MAX, name_only);
1348 1420
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index ff6e1fa4111e..52a2dda4f954 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -116,12 +116,21 @@ void parse_events_update_lists(struct list_head *list_event,
116void parse_events_error(void *data, void *scanner, char const *msg); 116void parse_events_error(void *data, void *scanner, char const *msg);
117 117
118void print_events(const char *event_glob, bool name_only); 118void print_events(const char *event_glob, bool name_only);
119void print_events_type(u8 type); 119
120struct event_symbol {
121 const char *symbol;
122 const char *alias;
123};
124extern struct event_symbol event_symbols_hw[];
125extern struct event_symbol event_symbols_sw[];
126void print_symbol_events(const char *event_glob, unsigned type,
127 struct event_symbol *syms, unsigned max,
128 bool name_only);
120void print_tracepoint_events(const char *subsys_glob, const char *event_glob, 129void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
121 bool name_only); 130 bool name_only);
122int print_hwcache_events(const char *event_glob, bool name_only); 131int print_hwcache_events(const char *event_glob, bool name_only);
123extern int is_valid_tracepoint(const char *event_string); 132extern int is_valid_tracepoint(const char *event_string);
124 133
125extern int valid_debugfs_mount(const char *debugfs); 134int valid_event_mount(const char *eventfs);
126 135
127#endif /* __PERF_PARSE_EVENTS_H */ 136#endif /* __PERF_PARSE_EVENTS_H */
diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c
index 4a015f77e2b5..01626be2a8eb 100644
--- a/tools/perf/util/parse-options.c
+++ b/tools/perf/util/parse-options.c
@@ -37,6 +37,7 @@ static int get_value(struct parse_opt_ctx_t *p,
37{ 37{
38 const char *s, *arg = NULL; 38 const char *s, *arg = NULL;
39 const int unset = flags & OPT_UNSET; 39 const int unset = flags & OPT_UNSET;
40 int err;
40 41
41 if (unset && p->opt) 42 if (unset && p->opt)
42 return opterror(opt, "takes no value", flags); 43 return opterror(opt, "takes no value", flags);
@@ -114,13 +115,29 @@ static int get_value(struct parse_opt_ctx_t *p,
114 return 0; 115 return 0;
115 116
116 case OPTION_STRING: 117 case OPTION_STRING:
118 err = 0;
117 if (unset) 119 if (unset)
118 *(const char **)opt->value = NULL; 120 *(const char **)opt->value = NULL;
119 else if (opt->flags & PARSE_OPT_OPTARG && !p->opt) 121 else if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
120 *(const char **)opt->value = (const char *)opt->defval; 122 *(const char **)opt->value = (const char *)opt->defval;
121 else 123 else
122 return get_arg(p, opt, flags, (const char **)opt->value); 124 err = get_arg(p, opt, flags, (const char **)opt->value);
123 return 0; 125
126 /* PARSE_OPT_NOEMPTY: Allow NULL but disallow empty string. */
127 if (opt->flags & PARSE_OPT_NOEMPTY) {
128 const char *val = *(const char **)opt->value;
129
130 if (!val)
131 return err;
132
133 /* Similar to unset if we are given an empty string. */
134 if (val[0] == '\0') {
135 *(const char **)opt->value = NULL;
136 return 0;
137 }
138 }
139
140 return err;
124 141
125 case OPTION_CALLBACK: 142 case OPTION_CALLBACK:
126 if (unset) 143 if (unset)
@@ -505,13 +522,18 @@ int parse_options_subcommand(int argc, const char **argv, const struct option *o
505 break; 522 break;
506 case PARSE_OPT_LIST_OPTS: 523 case PARSE_OPT_LIST_OPTS:
507 while (options->type != OPTION_END) { 524 while (options->type != OPTION_END) {
508 printf("--%s ", options->long_name); 525 if (options->long_name)
526 printf("--%s ", options->long_name);
509 options++; 527 options++;
510 } 528 }
529 putchar('\n');
511 exit(130); 530 exit(130);
512 case PARSE_OPT_LIST_SUBCMDS: 531 case PARSE_OPT_LIST_SUBCMDS:
513 for (int i = 0; subcommands[i]; i++) 532 if (subcommands) {
514 printf("%s ", subcommands[i]); 533 for (int i = 0; subcommands[i]; i++)
534 printf("%s ", subcommands[i]);
535 }
536 putchar('\n');
515 exit(130); 537 exit(130);
516 default: /* PARSE_OPT_UNKNOWN */ 538 default: /* PARSE_OPT_UNKNOWN */
517 if (ctx.argv[0][1] == '-') { 539 if (ctx.argv[0][1] == '-') {
diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h
index 97b153fb4999..59561fd86278 100644
--- a/tools/perf/util/parse-options.h
+++ b/tools/perf/util/parse-options.h
@@ -40,6 +40,7 @@ enum parse_opt_option_flags {
40 PARSE_OPT_LASTARG_DEFAULT = 16, 40 PARSE_OPT_LASTARG_DEFAULT = 16,
41 PARSE_OPT_DISABLED = 32, 41 PARSE_OPT_DISABLED = 32,
42 PARSE_OPT_EXCLUSIVE = 64, 42 PARSE_OPT_EXCLUSIVE = 64,
43 PARSE_OPT_NOEMPTY = 128,
43}; 44};
44 45
45struct option; 46struct option;
@@ -122,6 +123,7 @@ struct option {
122#define OPT_LONG(s, l, v, h) { .type = OPTION_LONG, .short_name = (s), .long_name = (l), .value = check_vtype(v, long *), .help = (h) } 123#define OPT_LONG(s, l, v, h) { .type = OPTION_LONG, .short_name = (s), .long_name = (l), .value = check_vtype(v, long *), .help = (h) }
123#define OPT_U64(s, l, v, h) { .type = OPTION_U64, .short_name = (s), .long_name = (l), .value = check_vtype(v, u64 *), .help = (h) } 124#define OPT_U64(s, l, v, h) { .type = OPTION_U64, .short_name = (s), .long_name = (l), .value = check_vtype(v, u64 *), .help = (h) }
124#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) } 125#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) }
126#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}
125#define OPT_DATE(s, l, v, h) \ 127#define OPT_DATE(s, l, v, h) \
126 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = "time", .help = (h), .callback = parse_opt_approxidate_cb } 128 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = "time", .help = (h), .callback = parse_opt_approxidate_cb }
127#define OPT_CALLBACK(s, l, v, a, h, f) \ 129#define OPT_CALLBACK(s, l, v, a, h, f) \
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 919937eb0be2..8feac0774c41 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -41,6 +41,7 @@
41#include "symbol.h" 41#include "symbol.h"
42#include "thread.h" 42#include "thread.h"
43#include <api/fs/debugfs.h> 43#include <api/fs/debugfs.h>
44#include <api/fs/tracefs.h>
44#include "trace-event.h" /* For __maybe_unused */ 45#include "trace-event.h" /* For __maybe_unused */
45#include "probe-event.h" 46#include "probe-event.h"
46#include "probe-finder.h" 47#include "probe-finder.h"
@@ -79,6 +80,7 @@ static int init_symbol_maps(bool user_only)
79 int ret; 80 int ret;
80 81
81 symbol_conf.sort_by_name = true; 82 symbol_conf.sort_by_name = true;
83 symbol_conf.allow_aliases = true;
82 ret = symbol__init(NULL); 84 ret = symbol__init(NULL);
83 if (ret < 0) { 85 if (ret < 0) {
84 pr_debug("Failed to init symbol map.\n"); 86 pr_debug("Failed to init symbol map.\n");
@@ -150,7 +152,7 @@ static u64 kernel_get_symbol_address_by_name(const char *name, bool reloc)
150 sym = __find_kernel_function_by_name(name, &map); 152 sym = __find_kernel_function_by_name(name, &map);
151 if (sym) 153 if (sym)
152 return map->unmap_ip(map, sym->start) - 154 return map->unmap_ip(map, sym->start) -
153 (reloc) ? 0 : map->reloc; 155 ((reloc) ? 0 : map->reloc);
154 } 156 }
155 return 0; 157 return 0;
156} 158}
@@ -177,6 +179,25 @@ static struct map *kernel_get_module_map(const char *module)
177 return NULL; 179 return NULL;
178} 180}
179 181
182static struct map *get_target_map(const char *target, bool user)
183{
184 /* Init maps of given executable or kernel */
185 if (user)
186 return dso__new_map(target);
187 else
188 return kernel_get_module_map(target);
189}
190
191static void put_target_map(struct map *map, bool user)
192{
193 if (map && user) {
194 /* Only the user map needs to be released */
195 dso__delete(map->dso);
196 map__delete(map);
197 }
198}
199
200
180static struct dso *kernel_get_module_dso(const char *module) 201static struct dso *kernel_get_module_dso(const char *module)
181{ 202{
182 struct dso *dso; 203 struct dso *dso;
@@ -248,6 +269,13 @@ out:
248 return ret; 269 return ret;
249} 270}
250 271
272static void clear_perf_probe_point(struct perf_probe_point *pp)
273{
274 free(pp->file);
275 free(pp->function);
276 free(pp->lazy_line);
277}
278
251static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs) 279static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs)
252{ 280{
253 int i; 281 int i;
@@ -257,6 +285,102 @@ static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs)
257} 285}
258 286
259#ifdef HAVE_DWARF_SUPPORT 287#ifdef HAVE_DWARF_SUPPORT
288/*
289 * Some binaries like glibc have special symbols which are on the symbol
290 * table, but not in the debuginfo. If we can find the address of the
291 * symbol from map, we can translate the address back to the probe point.
292 */
293static int find_alternative_probe_point(struct debuginfo *dinfo,
294 struct perf_probe_point *pp,
295 struct perf_probe_point *result,
296 const char *target, bool uprobes)
297{
298 struct map *map = NULL;
299 struct symbol *sym;
300 u64 address = 0;
301 int ret = -ENOENT;
302
303 /* This can work only for function-name based one */
304 if (!pp->function || pp->file)
305 return -ENOTSUP;
306
307 map = get_target_map(target, uprobes);
308 if (!map)
309 return -EINVAL;
310
311 /* Find the address of given function */
312 map__for_each_symbol_by_name(map, pp->function, sym) {
313 if (uprobes)
314 address = sym->start;
315 else
316 address = map->unmap_ip(map, sym->start);
317 break;
318 }
319 if (!address) {
320 ret = -ENOENT;
321 goto out;
322 }
323 pr_debug("Symbol %s address found : %lx\n", pp->function, address);
324
325 ret = debuginfo__find_probe_point(dinfo, (unsigned long)address,
326 result);
327 if (ret <= 0)
328 ret = (!ret) ? -ENOENT : ret;
329 else {
330 result->offset += pp->offset;
331 result->line += pp->line;
332 ret = 0;
333 }
334
335out:
336 put_target_map(map, uprobes);
337 return ret;
338
339}
340
341static int get_alternative_probe_event(struct debuginfo *dinfo,
342 struct perf_probe_event *pev,
343 struct perf_probe_point *tmp,
344 const char *target)
345{
346 int ret;
347
348 memcpy(tmp, &pev->point, sizeof(*tmp));
349 memset(&pev->point, 0, sizeof(pev->point));
350 ret = find_alternative_probe_point(dinfo, tmp, &pev->point,
351 target, pev->uprobes);
352 if (ret < 0)
353 memcpy(&pev->point, tmp, sizeof(*tmp));
354
355 return ret;
356}
357
358static int get_alternative_line_range(struct debuginfo *dinfo,
359 struct line_range *lr,
360 const char *target, bool user)
361{
362 struct perf_probe_point pp = { .function = lr->function,
363 .file = lr->file,
364 .line = lr->start };
365 struct perf_probe_point result;
366 int ret, len = 0;
367
368 memset(&result, 0, sizeof(result));
369
370 if (lr->end != INT_MAX)
371 len = lr->end - lr->start;
372 ret = find_alternative_probe_point(dinfo, &pp, &result,
373 target, user);
374 if (!ret) {
375 lr->function = result.function;
376 lr->file = result.file;
377 lr->start = result.line;
378 if (lr->end != INT_MAX)
379 lr->end = lr->start + len;
380 clear_perf_probe_point(&pp);
381 }
382 return ret;
383}
260 384
261/* Open new debuginfo of given module */ 385/* Open new debuginfo of given module */
262static struct debuginfo *open_debuginfo(const char *module, bool silent) 386static struct debuginfo *open_debuginfo(const char *module, bool silent)
@@ -465,6 +589,7 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
465 int max_tevs, const char *target) 589 int max_tevs, const char *target)
466{ 590{
467 bool need_dwarf = perf_probe_event_need_dwarf(pev); 591 bool need_dwarf = perf_probe_event_need_dwarf(pev);
592 struct perf_probe_point tmp;
468 struct debuginfo *dinfo; 593 struct debuginfo *dinfo;
469 int ntevs, ret = 0; 594 int ntevs, ret = 0;
470 595
@@ -481,6 +606,20 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
481 /* Searching trace events corresponding to a probe event */ 606 /* Searching trace events corresponding to a probe event */
482 ntevs = debuginfo__find_trace_events(dinfo, pev, tevs, max_tevs); 607 ntevs = debuginfo__find_trace_events(dinfo, pev, tevs, max_tevs);
483 608
609 if (ntevs == 0) { /* Not found, retry with an alternative */
610 ret = get_alternative_probe_event(dinfo, pev, &tmp, target);
611 if (!ret) {
612 ntevs = debuginfo__find_trace_events(dinfo, pev,
613 tevs, max_tevs);
614 /*
615 * Write back to the original probe_event for
616 * setting appropriate (user given) event name
617 */
618 clear_perf_probe_point(&pev->point);
619 memcpy(&pev->point, &tmp, sizeof(tmp));
620 }
621 }
622
484 debuginfo__delete(dinfo); 623 debuginfo__delete(dinfo);
485 624
486 if (ntevs > 0) { /* Succeeded to find trace events */ 625 if (ntevs > 0) { /* Succeeded to find trace events */
@@ -495,11 +634,9 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
495 } 634 }
496 635
497 if (ntevs == 0) { /* No error but failed to find probe point. */ 636 if (ntevs == 0) { /* No error but failed to find probe point. */
498 pr_warning("Probe point '%s' not found in debuginfo.\n", 637 pr_warning("Probe point '%s' not found.\n",
499 synthesize_perf_probe_point(&pev->point)); 638 synthesize_perf_probe_point(&pev->point));
500 if (need_dwarf) 639 return -ENOENT;
501 return -ENOENT;
502 return 0;
503 } 640 }
504 /* Error path : ntevs < 0 */ 641 /* Error path : ntevs < 0 */
505 pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs); 642 pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs);
@@ -532,7 +669,7 @@ static int get_real_path(const char *raw_path, const char *comp_dir,
532 else { 669 else {
533 if (access(raw_path, R_OK) == 0) { 670 if (access(raw_path, R_OK) == 0) {
534 *new_path = strdup(raw_path); 671 *new_path = strdup(raw_path);
535 return 0; 672 return *new_path ? 0 : -ENOMEM;
536 } else 673 } else
537 return -errno; 674 return -errno;
538 } 675 }
@@ -548,9 +685,11 @@ static int get_real_path(const char *raw_path, const char *comp_dir,
548 if (access(*new_path, R_OK) == 0) 685 if (access(*new_path, R_OK) == 0)
549 return 0; 686 return 0;
550 687
551 if (!symbol_conf.source_prefix) 688 if (!symbol_conf.source_prefix) {
552 /* In case of searching comp_dir, don't retry */ 689 /* In case of searching comp_dir, don't retry */
690 zfree(new_path);
553 return -errno; 691 return -errno;
692 }
554 693
555 switch (errno) { 694 switch (errno) {
556 case ENAMETOOLONG: 695 case ENAMETOOLONG:
@@ -622,7 +761,8 @@ static int _show_one_line(FILE *fp, int l, bool skip, bool show_num)
622 * Show line-range always requires debuginfo to find source file and 761 * Show line-range always requires debuginfo to find source file and
623 * line number. 762 * line number.
624 */ 763 */
625static int __show_line_range(struct line_range *lr, const char *module) 764static int __show_line_range(struct line_range *lr, const char *module,
765 bool user)
626{ 766{
627 int l = 1; 767 int l = 1;
628 struct int_node *ln; 768 struct int_node *ln;
@@ -638,6 +778,11 @@ static int __show_line_range(struct line_range *lr, const char *module)
638 return -ENOENT; 778 return -ENOENT;
639 779
640 ret = debuginfo__find_line_range(dinfo, lr); 780 ret = debuginfo__find_line_range(dinfo, lr);
781 if (!ret) { /* Not found, retry with an alternative */
782 ret = get_alternative_line_range(dinfo, lr, module, user);
783 if (!ret)
784 ret = debuginfo__find_line_range(dinfo, lr);
785 }
641 debuginfo__delete(dinfo); 786 debuginfo__delete(dinfo);
642 if (ret == 0 || ret == -ENOENT) { 787 if (ret == 0 || ret == -ENOENT) {
643 pr_warning("Specified source line is not found.\n"); 788 pr_warning("Specified source line is not found.\n");
@@ -650,7 +795,11 @@ static int __show_line_range(struct line_range *lr, const char *module)
650 /* Convert source file path */ 795 /* Convert source file path */
651 tmp = lr->path; 796 tmp = lr->path;
652 ret = get_real_path(tmp, lr->comp_dir, &lr->path); 797 ret = get_real_path(tmp, lr->comp_dir, &lr->path);
653 free(tmp); /* Free old path */ 798
799 /* Free old path when new path is assigned */
800 if (tmp != lr->path)
801 free(tmp);
802
654 if (ret < 0) { 803 if (ret < 0) {
655 pr_warning("Failed to find source file path.\n"); 804 pr_warning("Failed to find source file path.\n");
656 return ret; 805 return ret;
@@ -707,7 +856,7 @@ int show_line_range(struct line_range *lr, const char *module, bool user)
707 ret = init_symbol_maps(user); 856 ret = init_symbol_maps(user);
708 if (ret < 0) 857 if (ret < 0)
709 return ret; 858 return ret;
710 ret = __show_line_range(lr, module); 859 ret = __show_line_range(lr, module, user);
711 exit_symbol_maps(); 860 exit_symbol_maps();
712 861
713 return ret; 862 return ret;
@@ -716,12 +865,13 @@ int show_line_range(struct line_range *lr, const char *module, bool user)
716static int show_available_vars_at(struct debuginfo *dinfo, 865static int show_available_vars_at(struct debuginfo *dinfo,
717 struct perf_probe_event *pev, 866 struct perf_probe_event *pev,
718 int max_vls, struct strfilter *_filter, 867 int max_vls, struct strfilter *_filter,
719 bool externs) 868 bool externs, const char *target)
720{ 869{
721 char *buf; 870 char *buf;
722 int ret, i, nvars; 871 int ret, i, nvars;
723 struct str_node *node; 872 struct str_node *node;
724 struct variable_list *vls = NULL, *vl; 873 struct variable_list *vls = NULL, *vl;
874 struct perf_probe_point tmp;
725 const char *var; 875 const char *var;
726 876
727 buf = synthesize_perf_probe_point(&pev->point); 877 buf = synthesize_perf_probe_point(&pev->point);
@@ -731,6 +881,15 @@ static int show_available_vars_at(struct debuginfo *dinfo,
731 881
732 ret = debuginfo__find_available_vars_at(dinfo, pev, &vls, 882 ret = debuginfo__find_available_vars_at(dinfo, pev, &vls,
733 max_vls, externs); 883 max_vls, externs);
884 if (!ret) { /* Not found, retry with an alternative */
885 ret = get_alternative_probe_event(dinfo, pev, &tmp, target);
886 if (!ret) {
887 ret = debuginfo__find_available_vars_at(dinfo, pev,
888 &vls, max_vls, externs);
889 /* Release the old probe_point */
890 clear_perf_probe_point(&tmp);
891 }
892 }
734 if (ret <= 0) { 893 if (ret <= 0) {
735 if (ret == 0 || ret == -ENOENT) { 894 if (ret == 0 || ret == -ENOENT) {
736 pr_err("Failed to find the address of %s\n", buf); 895 pr_err("Failed to find the address of %s\n", buf);
@@ -793,7 +952,7 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
793 952
794 for (i = 0; i < npevs && ret >= 0; i++) 953 for (i = 0; i < npevs && ret >= 0; i++)
795 ret = show_available_vars_at(dinfo, &pevs[i], max_vls, _filter, 954 ret = show_available_vars_at(dinfo, &pevs[i], max_vls, _filter,
796 externs); 955 externs, module);
797 956
798 debuginfo__delete(dinfo); 957 debuginfo__delete(dinfo);
799out: 958out:
@@ -1739,15 +1898,12 @@ static int convert_to_perf_probe_event(struct probe_trace_event *tev,
1739 1898
1740void clear_perf_probe_event(struct perf_probe_event *pev) 1899void clear_perf_probe_event(struct perf_probe_event *pev)
1741{ 1900{
1742 struct perf_probe_point *pp = &pev->point;
1743 struct perf_probe_arg_field *field, *next; 1901 struct perf_probe_arg_field *field, *next;
1744 int i; 1902 int i;
1745 1903
1746 free(pev->event); 1904 free(pev->event);
1747 free(pev->group); 1905 free(pev->group);
1748 free(pp->file); 1906 clear_perf_probe_point(&pev->point);
1749 free(pp->function);
1750 free(pp->lazy_line);
1751 1907
1752 for (i = 0; i < pev->nargs; i++) { 1908 for (i = 0; i < pev->nargs; i++) {
1753 free(pev->args[i].name); 1909 free(pev->args[i].name);
@@ -1805,7 +1961,7 @@ static void print_open_warning(int err, bool is_kprobe)
1805 " - please rebuild kernel with %s.\n", 1961 " - please rebuild kernel with %s.\n",
1806 is_kprobe ? 'k' : 'u', config); 1962 is_kprobe ? 'k' : 'u', config);
1807 } else if (err == -ENOTSUP) 1963 } else if (err == -ENOTSUP)
1808 pr_warning("Debugfs is not mounted.\n"); 1964 pr_warning("Tracefs or debugfs is not mounted.\n");
1809 else 1965 else
1810 pr_warning("Failed to open %cprobe_events: %s\n", 1966 pr_warning("Failed to open %cprobe_events: %s\n",
1811 is_kprobe ? 'k' : 'u', 1967 is_kprobe ? 'k' : 'u',
@@ -1816,7 +1972,7 @@ static void print_both_open_warning(int kerr, int uerr)
1816{ 1972{
1817 /* Both kprobes and uprobes are disabled, warn it. */ 1973 /* Both kprobes and uprobes are disabled, warn it. */
1818 if (kerr == -ENOTSUP && uerr == -ENOTSUP) 1974 if (kerr == -ENOTSUP && uerr == -ENOTSUP)
1819 pr_warning("Debugfs is not mounted.\n"); 1975 pr_warning("Tracefs or debugfs is not mounted.\n");
1820 else if (kerr == -ENOENT && uerr == -ENOENT) 1976 else if (kerr == -ENOENT && uerr == -ENOENT)
1821 pr_warning("Please rebuild kernel with CONFIG_KPROBE_EVENTS " 1977 pr_warning("Please rebuild kernel with CONFIG_KPROBE_EVENTS "
1822 "or/and CONFIG_UPROBE_EVENTS.\n"); 1978 "or/and CONFIG_UPROBE_EVENTS.\n");
@@ -1833,13 +1989,20 @@ static int open_probe_events(const char *trace_file, bool readwrite)
1833{ 1989{
1834 char buf[PATH_MAX]; 1990 char buf[PATH_MAX];
1835 const char *__debugfs; 1991 const char *__debugfs;
1992 const char *tracing_dir = "";
1836 int ret; 1993 int ret;
1837 1994
1838 __debugfs = debugfs_find_mountpoint(); 1995 __debugfs = tracefs_find_mountpoint();
1839 if (__debugfs == NULL) 1996 if (__debugfs == NULL) {
1840 return -ENOTSUP; 1997 tracing_dir = "tracing/";
1998
1999 __debugfs = debugfs_find_mountpoint();
2000 if (__debugfs == NULL)
2001 return -ENOTSUP;
2002 }
1841 2003
1842 ret = e_snprintf(buf, PATH_MAX, "%s/%s", __debugfs, trace_file); 2004 ret = e_snprintf(buf, PATH_MAX, "%s/%s%s",
2005 __debugfs, tracing_dir, trace_file);
1843 if (ret >= 0) { 2006 if (ret >= 0) {
1844 pr_debug("Opening %s write=%d\n", buf, readwrite); 2007 pr_debug("Opening %s write=%d\n", buf, readwrite);
1845 if (readwrite && !probe_event_dry_run) 2008 if (readwrite && !probe_event_dry_run)
@@ -1855,12 +2018,12 @@ static int open_probe_events(const char *trace_file, bool readwrite)
1855 2018
1856static int open_kprobe_events(bool readwrite) 2019static int open_kprobe_events(bool readwrite)
1857{ 2020{
1858 return open_probe_events("tracing/kprobe_events", readwrite); 2021 return open_probe_events("kprobe_events", readwrite);
1859} 2022}
1860 2023
1861static int open_uprobe_events(bool readwrite) 2024static int open_uprobe_events(bool readwrite)
1862{ 2025{
1863 return open_probe_events("tracing/uprobe_events", readwrite); 2026 return open_probe_events("uprobe_events", readwrite);
1864} 2027}
1865 2028
1866/* Get raw string list of current kprobe_events or uprobe_events */ 2029/* Get raw string list of current kprobe_events or uprobe_events */
@@ -1895,6 +2058,95 @@ static struct strlist *get_probe_trace_command_rawlist(int fd)
1895 return sl; 2058 return sl;
1896} 2059}
1897 2060
2061struct kprobe_blacklist_node {
2062 struct list_head list;
2063 unsigned long start;
2064 unsigned long end;
2065 char *symbol;
2066};
2067
2068static void kprobe_blacklist__delete(struct list_head *blacklist)
2069{
2070 struct kprobe_blacklist_node *node;
2071
2072 while (!list_empty(blacklist)) {
2073 node = list_first_entry(blacklist,
2074 struct kprobe_blacklist_node, list);
2075 list_del(&node->list);
2076 free(node->symbol);
2077 free(node);
2078 }
2079}
2080
2081static int kprobe_blacklist__load(struct list_head *blacklist)
2082{
2083 struct kprobe_blacklist_node *node;
2084 const char *__debugfs = debugfs_find_mountpoint();
2085 char buf[PATH_MAX], *p;
2086 FILE *fp;
2087 int ret;
2088
2089 if (__debugfs == NULL)
2090 return -ENOTSUP;
2091
2092 ret = e_snprintf(buf, PATH_MAX, "%s/kprobes/blacklist", __debugfs);
2093 if (ret < 0)
2094 return ret;
2095
2096 fp = fopen(buf, "r");
2097 if (!fp)
2098 return -errno;
2099
2100 ret = 0;
2101 while (fgets(buf, PATH_MAX, fp)) {
2102 node = zalloc(sizeof(*node));
2103 if (!node) {
2104 ret = -ENOMEM;
2105 break;
2106 }
2107 INIT_LIST_HEAD(&node->list);
2108 list_add_tail(&node->list, blacklist);
2109 if (sscanf(buf, "0x%lx-0x%lx", &node->start, &node->end) != 2) {
2110 ret = -EINVAL;
2111 break;
2112 }
2113 p = strchr(buf, '\t');
2114 if (p) {
2115 p++;
2116 if (p[strlen(p) - 1] == '\n')
2117 p[strlen(p) - 1] = '\0';
2118 } else
2119 p = (char *)"unknown";
2120 node->symbol = strdup(p);
2121 if (!node->symbol) {
2122 ret = -ENOMEM;
2123 break;
2124 }
2125 pr_debug2("Blacklist: 0x%lx-0x%lx, %s\n",
2126 node->start, node->end, node->symbol);
2127 ret++;
2128 }
2129 if (ret < 0)
2130 kprobe_blacklist__delete(blacklist);
2131 fclose(fp);
2132
2133 return ret;
2134}
2135
2136static struct kprobe_blacklist_node *
2137kprobe_blacklist__find_by_address(struct list_head *blacklist,
2138 unsigned long address)
2139{
2140 struct kprobe_blacklist_node *node;
2141
2142 list_for_each_entry(node, blacklist, list) {
2143 if (node->start <= address && address <= node->end)
2144 return node;
2145 }
2146
2147 return NULL;
2148}
2149
1898/* Show an event */ 2150/* Show an event */
1899static int show_perf_probe_event(struct perf_probe_event *pev, 2151static int show_perf_probe_event(struct perf_probe_event *pev,
1900 const char *module) 2152 const char *module)
@@ -2100,6 +2352,27 @@ static int get_new_event_name(char *buf, size_t len, const char *base,
2100 return ret; 2352 return ret;
2101} 2353}
2102 2354
2355/* Warn if the current kernel's uprobe implementation is old */
2356static void warn_uprobe_event_compat(struct probe_trace_event *tev)
2357{
2358 int i;
2359 char *buf = synthesize_probe_trace_command(tev);
2360
2361 /* Old uprobe event doesn't support memory dereference */
2362 if (!tev->uprobes || tev->nargs == 0 || !buf)
2363 goto out;
2364
2365 for (i = 0; i < tev->nargs; i++)
2366 if (strglobmatch(tev->args[i].value, "[$@+-]*")) {
2367 pr_warning("Please upgrade your kernel to at least "
2368 "3.14 to have access to feature %s\n",
2369 tev->args[i].value);
2370 break;
2371 }
2372out:
2373 free(buf);
2374}
2375
2103static int __add_probe_trace_events(struct perf_probe_event *pev, 2376static int __add_probe_trace_events(struct perf_probe_event *pev,
2104 struct probe_trace_event *tevs, 2377 struct probe_trace_event *tevs,
2105 int ntevs, bool allow_suffix) 2378 int ntevs, bool allow_suffix)
@@ -2109,6 +2382,8 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
2109 char buf[64]; 2382 char buf[64];
2110 const char *event, *group; 2383 const char *event, *group;
2111 struct strlist *namelist; 2384 struct strlist *namelist;
2385 LIST_HEAD(blacklist);
2386 struct kprobe_blacklist_node *node;
2112 2387
2113 if (pev->uprobes) 2388 if (pev->uprobes)
2114 fd = open_uprobe_events(true); 2389 fd = open_uprobe_events(true);
@@ -2126,11 +2401,25 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
2126 pr_debug("Failed to get current event list.\n"); 2401 pr_debug("Failed to get current event list.\n");
2127 return -EIO; 2402 return -EIO;
2128 } 2403 }
2404 /* Get kprobe blacklist if exists */
2405 if (!pev->uprobes) {
2406 ret = kprobe_blacklist__load(&blacklist);
2407 if (ret < 0)
2408 pr_debug("No kprobe blacklist support, ignored\n");
2409 }
2129 2410
2130 ret = 0; 2411 ret = 0;
2131 pr_info("Added new event%s\n", (ntevs > 1) ? "s:" : ":"); 2412 pr_info("Added new event%s\n", (ntevs > 1) ? "s:" : ":");
2132 for (i = 0; i < ntevs; i++) { 2413 for (i = 0; i < ntevs; i++) {
2133 tev = &tevs[i]; 2414 tev = &tevs[i];
2415 /* Ensure that the address is NOT blacklisted */
2416 node = kprobe_blacklist__find_by_address(&blacklist,
2417 tev->point.address);
2418 if (node) {
2419 pr_warning("Warning: Skipped probing on blacklisted function: %s\n", node->symbol);
2420 continue;
2421 }
2422
2134 if (pev->event) 2423 if (pev->event)
2135 event = pev->event; 2424 event = pev->event;
2136 else 2425 else
@@ -2180,14 +2469,18 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
2180 */ 2469 */
2181 allow_suffix = true; 2470 allow_suffix = true;
2182 } 2471 }
2472 if (ret == -EINVAL && pev->uprobes)
2473 warn_uprobe_event_compat(tev);
2183 2474
2184 if (ret >= 0) { 2475 /* Note that it is possible to skip all events because of blacklist */
2476 if (ret >= 0 && tev->event) {
2185 /* Show how to use the event. */ 2477 /* Show how to use the event. */
2186 pr_info("\nYou can now use it in all perf tools, such as:\n\n"); 2478 pr_info("\nYou can now use it in all perf tools, such as:\n\n");
2187 pr_info("\tperf record -e %s:%s -aR sleep 1\n\n", tev->group, 2479 pr_info("\tperf record -e %s:%s -aR sleep 1\n\n", tev->group,
2188 tev->event); 2480 tev->event);
2189 } 2481 }
2190 2482
2483 kprobe_blacklist__delete(&blacklist);
2191 strlist__delete(namelist); 2484 strlist__delete(namelist);
2192 close(fd); 2485 close(fd);
2193 return ret; 2486 return ret;
@@ -2199,8 +2492,7 @@ static int find_probe_functions(struct map *map, char *name)
2199 struct symbol *sym; 2492 struct symbol *sym;
2200 2493
2201 map__for_each_symbol_by_name(map, name, sym) { 2494 map__for_each_symbol_by_name(map, name, sym) {
2202 if (sym->binding == STB_GLOBAL || sym->binding == STB_LOCAL) 2495 found++;
2203 found++;
2204 } 2496 }
2205 2497
2206 return found; 2498 return found;
@@ -2218,7 +2510,6 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
2218 int max_tevs, const char *target) 2510 int max_tevs, const char *target)
2219{ 2511{
2220 struct map *map = NULL; 2512 struct map *map = NULL;
2221 struct kmap *kmap = NULL;
2222 struct ref_reloc_sym *reloc_sym = NULL; 2513 struct ref_reloc_sym *reloc_sym = NULL;
2223 struct symbol *sym; 2514 struct symbol *sym;
2224 struct probe_trace_event *tev; 2515 struct probe_trace_event *tev;
@@ -2227,11 +2518,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
2227 int num_matched_functions; 2518 int num_matched_functions;
2228 int ret, i; 2519 int ret, i;
2229 2520
2230 /* Init maps of given executable or kernel */ 2521 map = get_target_map(target, pev->uprobes);
2231 if (pev->uprobes)
2232 map = dso__new_map(target);
2233 else
2234 map = kernel_get_module_map(target);
2235 if (!map) { 2522 if (!map) {
2236 ret = -EINVAL; 2523 ret = -EINVAL;
2237 goto out; 2524 goto out;
@@ -2255,8 +2542,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
2255 } 2542 }
2256 2543
2257 if (!pev->uprobes && !pp->retprobe) { 2544 if (!pev->uprobes && !pp->retprobe) {
2258 kmap = map__kmap(map); 2545 reloc_sym = kernel_get_ref_reloc_sym();
2259 reloc_sym = kmap->ref_reloc_sym;
2260 if (!reloc_sym) { 2546 if (!reloc_sym) {
2261 pr_warning("Relocated base symbol is not found!\n"); 2547 pr_warning("Relocated base symbol is not found!\n");
2262 ret = -EINVAL; 2548 ret = -EINVAL;
@@ -2324,11 +2610,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
2324 } 2610 }
2325 2611
2326out: 2612out:
2327 if (map && pev->uprobes) { 2613 put_target_map(map, pev->uprobes);
2328 /* Only when using uprobe(exec) map needs to be released */
2329 dso__delete(map->dso);
2330 map__delete(map);
2331 }
2332 return ret; 2614 return ret;
2333 2615
2334nomem_out: 2616nomem_out:
@@ -2568,8 +2850,7 @@ static struct strfilter *available_func_filter;
2568static int filter_available_functions(struct map *map __maybe_unused, 2850static int filter_available_functions(struct map *map __maybe_unused,
2569 struct symbol *sym) 2851 struct symbol *sym)
2570{ 2852{
2571 if ((sym->binding == STB_GLOBAL || sym->binding == STB_LOCAL) && 2853 if (strfilter__compare(available_func_filter, sym->name))
2572 strfilter__compare(available_func_filter, sym->name))
2573 return 0; 2854 return 0;
2574 return 1; 2855 return 1;
2575} 2856}
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index b5247d777f0e..46f009aa486c 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -915,17 +915,13 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
915 dwarf_decl_line(sp_die, &pf->lno); 915 dwarf_decl_line(sp_die, &pf->lno);
916 pf->lno += pp->line; 916 pf->lno += pp->line;
917 param->retval = find_probe_point_by_line(pf); 917 param->retval = find_probe_point_by_line(pf);
918 } else if (!dwarf_func_inline(sp_die)) { 918 } else if (die_is_func_instance(sp_die)) {
919 /* Instances always have the entry address */
920 dwarf_entrypc(sp_die, &pf->addr);
919 /* Real function */ 921 /* Real function */
920 if (pp->lazy_line) 922 if (pp->lazy_line)
921 param->retval = find_probe_point_lazy(sp_die, pf); 923 param->retval = find_probe_point_lazy(sp_die, pf);
922 else { 924 else {
923 if (dwarf_entrypc(sp_die, &pf->addr) != 0) {
924 pr_warning("Failed to get entry address of "
925 "%s.\n", dwarf_diename(sp_die));
926 param->retval = -ENOENT;
927 return DWARF_CB_ABORT;
928 }
929 pf->addr += pp->offset; 925 pf->addr += pp->offset;
930 /* TODO: Check the address in this function */ 926 /* TODO: Check the address in this function */
931 param->retval = call_probe_finder(sp_die, pf); 927 param->retval = call_probe_finder(sp_die, pf);
@@ -1349,11 +1345,8 @@ int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr,
1349 const char *fname = NULL, *func = NULL, *basefunc = NULL, *tmp; 1345 const char *fname = NULL, *func = NULL, *basefunc = NULL, *tmp;
1350 int baseline = 0, lineno = 0, ret = 0; 1346 int baseline = 0, lineno = 0, ret = 0;
1351 1347
1352 /* Adjust address with bias */
1353 addr += dbg->bias;
1354
1355 /* Find cu die */ 1348 /* Find cu die */
1356 if (!dwarf_addrdie(dbg->dbg, (Dwarf_Addr)addr - dbg->bias, &cudie)) { 1349 if (!dwarf_addrdie(dbg->dbg, (Dwarf_Addr)addr, &cudie)) {
1357 pr_warning("Failed to find debug information for address %lx\n", 1350 pr_warning("Failed to find debug information for address %lx\n",
1358 addr); 1351 addr);
1359 ret = -EINVAL; 1352 ret = -EINVAL;
@@ -1536,7 +1529,7 @@ static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
1536 pr_debug("New line range: %d to %d\n", lf->lno_s, lf->lno_e); 1529 pr_debug("New line range: %d to %d\n", lf->lno_s, lf->lno_e);
1537 lr->start = lf->lno_s; 1530 lr->start = lf->lno_s;
1538 lr->end = lf->lno_e; 1531 lr->end = lf->lno_e;
1539 if (dwarf_func_inline(sp_die)) 1532 if (!die_is_func_instance(sp_die))
1540 param->retval = die_walk_instances(sp_die, 1533 param->retval = die_walk_instances(sp_die,
1541 line_range_inline_cb, lf); 1534 line_range_inline_cb, lf);
1542 else 1535 else
diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources
index 6c6a6953fa93..4d28624a1eca 100644
--- a/tools/perf/util/python-ext-sources
+++ b/tools/perf/util/python-ext-sources
@@ -17,6 +17,5 @@ util/xyarray.c
17util/cgroup.c 17util/cgroup.c
18util/rblist.c 18util/rblist.c
19util/strlist.c 19util/strlist.c
20../lib/api/fs/fs.c
21util/trace-event.c 20util/trace-event.c
22../../lib/rbtree.c 21../../lib/rbtree.c
diff --git a/tools/perf/util/scripting-engines/Build b/tools/perf/util/scripting-engines/Build
new file mode 100644
index 000000000000..6516e220c247
--- /dev/null
+++ b/tools/perf/util/scripting-engines/Build
@@ -0,0 +1,6 @@
1libperf-$(CONFIG_LIBPERL) += trace-event-perl.o
2libperf-$(CONFIG_LIBPYTHON) += trace-event-python.o
3
4CFLAGS_trace-event-perl.o += $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow -Wno-undef -Wno-switch-default
5
6CFLAGS_trace-event-python.o += $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index 22ebc46226e7..8171fed4136e 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -214,6 +214,11 @@ static void define_event_symbols(struct event_format *event,
214 define_event_symbols(event, ev_name, args->hex.field); 214 define_event_symbols(event, ev_name, args->hex.field);
215 define_event_symbols(event, ev_name, args->hex.size); 215 define_event_symbols(event, ev_name, args->hex.size);
216 break; 216 break;
217 case PRINT_INT_ARRAY:
218 define_event_symbols(event, ev_name, args->int_array.field);
219 define_event_symbols(event, ev_name, args->int_array.count);
220 define_event_symbols(event, ev_name, args->int_array.el_size);
221 break;
217 case PRINT_BSTRING: 222 case PRINT_BSTRING:
218 case PRINT_DYNAMIC_ARRAY: 223 case PRINT_DYNAMIC_ARRAY:
219 case PRINT_STRING: 224 case PRINT_STRING:
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 0c815a40a6e8..2ec5dfb5a456 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -231,6 +231,11 @@ static void define_event_symbols(struct event_format *event,
231 define_event_symbols(event, ev_name, args->hex.field); 231 define_event_symbols(event, ev_name, args->hex.field);
232 define_event_symbols(event, ev_name, args->hex.size); 232 define_event_symbols(event, ev_name, args->hex.size);
233 break; 233 break;
234 case PRINT_INT_ARRAY:
235 define_event_symbols(event, ev_name, args->int_array.field);
236 define_event_symbols(event, ev_name, args->int_array.count);
237 define_event_symbols(event, ev_name, args->int_array.el_size);
238 break;
234 case PRINT_STRING: 239 case PRINT_STRING:
235 break; 240 break;
236 case PRINT_TYPE: 241 case PRINT_TYPE:
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 0baf75f12b7c..adf0740c563b 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -16,6 +16,12 @@
16#include "perf_regs.h" 16#include "perf_regs.h"
17#include "asm/bug.h" 17#include "asm/bug.h"
18 18
19static int machines__deliver_event(struct machines *machines,
20 struct perf_evlist *evlist,
21 union perf_event *event,
22 struct perf_sample *sample,
23 struct perf_tool *tool, u64 file_offset);
24
19static int perf_session__open(struct perf_session *session) 25static int perf_session__open(struct perf_session *session)
20{ 26{
21 struct perf_data_file *file = session->file; 27 struct perf_data_file *file = session->file;
@@ -86,6 +92,14 @@ static void perf_session__set_comm_exec(struct perf_session *session)
86 machines__set_comm_exec(&session->machines, comm_exec); 92 machines__set_comm_exec(&session->machines, comm_exec);
87} 93}
88 94
95static int ordered_events__deliver_event(struct ordered_events *oe,
96 struct ordered_event *event,
97 struct perf_sample *sample)
98{
99 return machines__deliver_event(oe->machines, oe->evlist, event->event,
100 sample, oe->tool, event->file_offset);
101}
102
89struct perf_session *perf_session__new(struct perf_data_file *file, 103struct perf_session *perf_session__new(struct perf_data_file *file,
90 bool repipe, struct perf_tool *tool) 104 bool repipe, struct perf_tool *tool)
91{ 105{
@@ -95,7 +109,6 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
95 goto out; 109 goto out;
96 110
97 session->repipe = repipe; 111 session->repipe = repipe;
98 ordered_events__init(&session->ordered_events);
99 machines__init(&session->machines); 112 machines__init(&session->machines);
100 113
101 if (file) { 114 if (file) {
@@ -126,6 +139,9 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
126 tool->ordered_events && !perf_evlist__sample_id_all(session->evlist)) { 139 tool->ordered_events && !perf_evlist__sample_id_all(session->evlist)) {
127 dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n"); 140 dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n");
128 tool->ordered_events = false; 141 tool->ordered_events = false;
142 } else {
143 ordered_events__init(&session->ordered_events, &session->machines,
144 session->evlist, tool, ordered_events__deliver_event);
129 } 145 }
130 146
131 return session; 147 return session;
@@ -138,11 +154,6 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
138 return NULL; 154 return NULL;
139} 155}
140 156
141static void perf_session__delete_dead_threads(struct perf_session *session)
142{
143 machine__delete_dead_threads(&session->machines.host);
144}
145
146static void perf_session__delete_threads(struct perf_session *session) 157static void perf_session__delete_threads(struct perf_session *session)
147{ 158{
148 machine__delete_threads(&session->machines.host); 159 machine__delete_threads(&session->machines.host);
@@ -167,7 +178,6 @@ static void perf_session_env__delete(struct perf_session_env *env)
167void perf_session__delete(struct perf_session *session) 178void perf_session__delete(struct perf_session *session)
168{ 179{
169 perf_session__destroy_kernel_maps(session); 180 perf_session__destroy_kernel_maps(session);
170 perf_session__delete_dead_threads(session);
171 perf_session__delete_threads(session); 181 perf_session__delete_threads(session);
172 perf_session_env__delete(&session->header.env); 182 perf_session_env__delete(&session->header.env);
173 machines__exit(&session->machines); 183 machines__exit(&session->machines);
@@ -215,10 +225,17 @@ static int process_event_stub(struct perf_tool *tool __maybe_unused,
215 return 0; 225 return 0;
216} 226}
217 227
228static int process_build_id_stub(struct perf_tool *tool __maybe_unused,
229 union perf_event *event __maybe_unused,
230 struct perf_session *session __maybe_unused)
231{
232 dump_printf(": unhandled!\n");
233 return 0;
234}
235
218static int process_finished_round_stub(struct perf_tool *tool __maybe_unused, 236static int process_finished_round_stub(struct perf_tool *tool __maybe_unused,
219 union perf_event *event __maybe_unused, 237 union perf_event *event __maybe_unused,
220 struct perf_session *perf_session 238 struct ordered_events *oe __maybe_unused)
221 __maybe_unused)
222{ 239{
223 dump_printf(": unhandled!\n"); 240 dump_printf(": unhandled!\n");
224 return 0; 241 return 0;
@@ -226,7 +243,7 @@ static int process_finished_round_stub(struct perf_tool *tool __maybe_unused,
226 243
227static int process_finished_round(struct perf_tool *tool, 244static int process_finished_round(struct perf_tool *tool,
228 union perf_event *event, 245 union perf_event *event,
229 struct perf_session *session); 246 struct ordered_events *oe);
230 247
231static int process_id_index_stub(struct perf_tool *tool __maybe_unused, 248static int process_id_index_stub(struct perf_tool *tool __maybe_unused,
232 union perf_event *event __maybe_unused, 249 union perf_event *event __maybe_unused,
@@ -264,7 +281,7 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
264 if (tool->tracing_data == NULL) 281 if (tool->tracing_data == NULL)
265 tool->tracing_data = process_event_synth_tracing_data_stub; 282 tool->tracing_data = process_event_synth_tracing_data_stub;
266 if (tool->build_id == NULL) 283 if (tool->build_id == NULL)
267 tool->build_id = process_finished_round_stub; 284 tool->build_id = process_build_id_stub;
268 if (tool->finished_round == NULL) { 285 if (tool->finished_round == NULL) {
269 if (tool->ordered_events) 286 if (tool->ordered_events)
270 tool->finished_round = process_finished_round; 287 tool->finished_round = process_finished_round;
@@ -514,54 +531,80 @@ static perf_event__swap_op perf_event__swap_ops[] = {
514 * Flush every events below timestamp 7 531 * Flush every events below timestamp 7
515 * etc... 532 * etc...
516 */ 533 */
517static int process_finished_round(struct perf_tool *tool, 534static int process_finished_round(struct perf_tool *tool __maybe_unused,
518 union perf_event *event __maybe_unused, 535 union perf_event *event __maybe_unused,
519 struct perf_session *session) 536 struct ordered_events *oe)
520{ 537{
521 return ordered_events__flush(session, tool, OE_FLUSH__ROUND); 538 return ordered_events__flush(oe, OE_FLUSH__ROUND);
522} 539}
523 540
524int perf_session_queue_event(struct perf_session *s, union perf_event *event, 541int perf_session__queue_event(struct perf_session *s, union perf_event *event,
525 struct perf_tool *tool, struct perf_sample *sample, 542 struct perf_sample *sample, u64 file_offset)
526 u64 file_offset)
527{ 543{
528 struct ordered_events *oe = &s->ordered_events; 544 return ordered_events__queue(&s->ordered_events, event, sample, file_offset);
529 u64 timestamp = sample->time; 545}
530 struct ordered_event *new;
531
532 if (!timestamp || timestamp == ~0ULL)
533 return -ETIME;
534 546
535 if (timestamp < oe->last_flush) { 547static void callchain__lbr_callstack_printf(struct perf_sample *sample)
536 pr_oe_time(timestamp, "out of order event\n"); 548{
537 pr_oe_time(oe->last_flush, "last flush, last_flush_type %d\n", 549 struct ip_callchain *callchain = sample->callchain;
538 oe->last_flush_type); 550 struct branch_stack *lbr_stack = sample->branch_stack;
551 u64 kernel_callchain_nr = callchain->nr;
552 unsigned int i;
539 553
540 s->stats.nr_unordered_events++; 554 for (i = 0; i < kernel_callchain_nr; i++) {
555 if (callchain->ips[i] == PERF_CONTEXT_USER)
556 break;
541 } 557 }
542 558
543 new = ordered_events__new(oe, timestamp, event); 559 if ((i != kernel_callchain_nr) && lbr_stack->nr) {
544 if (!new) { 560 u64 total_nr;
545 ordered_events__flush(s, tool, OE_FLUSH__HALF); 561 /*
546 new = ordered_events__new(oe, timestamp, event); 562 * LBR callstack can only get user call chain,
547 } 563 * i is kernel call chain number,
564 * 1 is PERF_CONTEXT_USER.
565 *
566 * The user call chain is stored in LBR registers.
567 * LBR are pair registers. The caller is stored
568 * in "from" register, while the callee is stored
569 * in "to" register.
570 * For example, there is a call stack
571 * "A"->"B"->"C"->"D".
572 * The LBR registers will recorde like
573 * "C"->"D", "B"->"C", "A"->"B".
574 * So only the first "to" register and all "from"
575 * registers are needed to construct the whole stack.
576 */
577 total_nr = i + 1 + lbr_stack->nr + 1;
578 kernel_callchain_nr = i + 1;
548 579
549 if (!new) 580 printf("... LBR call chain: nr:%" PRIu64 "\n", total_nr);
550 return -ENOMEM;
551 581
552 new->file_offset = file_offset; 582 for (i = 0; i < kernel_callchain_nr; i++)
553 return 0; 583 printf("..... %2d: %016" PRIx64 "\n",
584 i, callchain->ips[i]);
585
586 printf("..... %2d: %016" PRIx64 "\n",
587 (int)(kernel_callchain_nr), lbr_stack->entries[0].to);
588 for (i = 0; i < lbr_stack->nr; i++)
589 printf("..... %2d: %016" PRIx64 "\n",
590 (int)(i + kernel_callchain_nr + 1), lbr_stack->entries[i].from);
591 }
554} 592}
555 593
556static void callchain__printf(struct perf_sample *sample) 594static void callchain__printf(struct perf_evsel *evsel,
595 struct perf_sample *sample)
557{ 596{
558 unsigned int i; 597 unsigned int i;
598 struct ip_callchain *callchain = sample->callchain;
559 599
560 printf("... chain: nr:%" PRIu64 "\n", sample->callchain->nr); 600 if (has_branch_callstack(evsel))
601 callchain__lbr_callstack_printf(sample);
561 602
562 for (i = 0; i < sample->callchain->nr; i++) 603 printf("... FP chain: nr:%" PRIu64 "\n", callchain->nr);
604
605 for (i = 0; i < callchain->nr; i++)
563 printf("..... %2d: %016" PRIx64 "\n", 606 printf("..... %2d: %016" PRIx64 "\n",
564 i, sample->callchain->ips[i]); 607 i, callchain->ips[i]);
565} 608}
566 609
567static void branch_stack__printf(struct perf_sample *sample) 610static void branch_stack__printf(struct perf_sample *sample)
@@ -636,14 +679,14 @@ static void stack_user__printf(struct stack_dump *dump)
636 dump->size, dump->offset); 679 dump->size, dump->offset);
637} 680}
638 681
639static void perf_session__print_tstamp(struct perf_session *session, 682static void perf_evlist__print_tstamp(struct perf_evlist *evlist,
640 union perf_event *event, 683 union perf_event *event,
641 struct perf_sample *sample) 684 struct perf_sample *sample)
642{ 685{
643 u64 sample_type = __perf_evlist__combined_sample_type(session->evlist); 686 u64 sample_type = __perf_evlist__combined_sample_type(evlist);
644 687
645 if (event->header.type != PERF_RECORD_SAMPLE && 688 if (event->header.type != PERF_RECORD_SAMPLE &&
646 !perf_evlist__sample_id_all(session->evlist)) { 689 !perf_evlist__sample_id_all(evlist)) {
647 fputs("-1 -1 ", stdout); 690 fputs("-1 -1 ", stdout);
648 return; 691 return;
649 } 692 }
@@ -685,7 +728,7 @@ static void sample_read__printf(struct perf_sample *sample, u64 read_format)
685 sample->read.one.id, sample->read.one.value); 728 sample->read.one.id, sample->read.one.value);
686} 729}
687 730
688static void dump_event(struct perf_session *session, union perf_event *event, 731static void dump_event(struct perf_evlist *evlist, union perf_event *event,
689 u64 file_offset, struct perf_sample *sample) 732 u64 file_offset, struct perf_sample *sample)
690{ 733{
691 if (!dump_trace) 734 if (!dump_trace)
@@ -697,7 +740,7 @@ static void dump_event(struct perf_session *session, union perf_event *event,
697 trace_event(event); 740 trace_event(event);
698 741
699 if (sample) 742 if (sample)
700 perf_session__print_tstamp(session, event, sample); 743 perf_evlist__print_tstamp(evlist, event, sample);
701 744
702 printf("%#" PRIx64 " [%#x]: PERF_RECORD_%s", file_offset, 745 printf("%#" PRIx64 " [%#x]: PERF_RECORD_%s", file_offset,
703 event->header.size, perf_event__name(event->header.type)); 746 event->header.size, perf_event__name(event->header.type));
@@ -718,9 +761,9 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event,
718 sample_type = evsel->attr.sample_type; 761 sample_type = evsel->attr.sample_type;
719 762
720 if (sample_type & PERF_SAMPLE_CALLCHAIN) 763 if (sample_type & PERF_SAMPLE_CALLCHAIN)
721 callchain__printf(sample); 764 callchain__printf(evsel, sample);
722 765
723 if (sample_type & PERF_SAMPLE_BRANCH_STACK) 766 if ((sample_type & PERF_SAMPLE_BRANCH_STACK) && !has_branch_callstack(evsel))
724 branch_stack__printf(sample); 767 branch_stack__printf(sample);
725 768
726 if (sample_type & PERF_SAMPLE_REGS_USER) 769 if (sample_type & PERF_SAMPLE_REGS_USER)
@@ -745,8 +788,7 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event,
745 sample_read__printf(sample, evsel->attr.read_format); 788 sample_read__printf(sample, evsel->attr.read_format);
746} 789}
747 790
748static struct machine * 791static struct machine *machines__find_for_cpumode(struct machines *machines,
749 perf_session__find_machine_for_cpumode(struct perf_session *session,
750 union perf_event *event, 792 union perf_event *event,
751 struct perf_sample *sample) 793 struct perf_sample *sample)
752{ 794{
@@ -764,26 +806,24 @@ static struct machine *
764 else 806 else
765 pid = sample->pid; 807 pid = sample->pid;
766 808
767 machine = perf_session__find_machine(session, pid); 809 machine = machines__find(machines, pid);
768 if (!machine) 810 if (!machine)
769 machine = perf_session__findnew_machine(session, 811 machine = machines__find(machines, DEFAULT_GUEST_KERNEL_ID);
770 DEFAULT_GUEST_KERNEL_ID);
771 return machine; 812 return machine;
772 } 813 }
773 814
774 return &session->machines.host; 815 return &machines->host;
775} 816}
776 817
777static int deliver_sample_value(struct perf_session *session, 818static int deliver_sample_value(struct perf_evlist *evlist,
778 struct perf_tool *tool, 819 struct perf_tool *tool,
779 union perf_event *event, 820 union perf_event *event,
780 struct perf_sample *sample, 821 struct perf_sample *sample,
781 struct sample_read_value *v, 822 struct sample_read_value *v,
782 struct machine *machine) 823 struct machine *machine)
783{ 824{
784 struct perf_sample_id *sid; 825 struct perf_sample_id *sid = perf_evlist__id2sid(evlist, v->id);
785 826
786 sid = perf_evlist__id2sid(session->evlist, v->id);
787 if (sid) { 827 if (sid) {
788 sample->id = v->id; 828 sample->id = v->id;
789 sample->period = v->value - sid->period; 829 sample->period = v->value - sid->period;
@@ -791,14 +831,14 @@ static int deliver_sample_value(struct perf_session *session,
791 } 831 }
792 832
793 if (!sid || sid->evsel == NULL) { 833 if (!sid || sid->evsel == NULL) {
794 ++session->stats.nr_unknown_id; 834 ++evlist->stats.nr_unknown_id;
795 return 0; 835 return 0;
796 } 836 }
797 837
798 return tool->sample(tool, event, sample, sid->evsel, machine); 838 return tool->sample(tool, event, sample, sid->evsel, machine);
799} 839}
800 840
801static int deliver_sample_group(struct perf_session *session, 841static int deliver_sample_group(struct perf_evlist *evlist,
802 struct perf_tool *tool, 842 struct perf_tool *tool,
803 union perf_event *event, 843 union perf_event *event,
804 struct perf_sample *sample, 844 struct perf_sample *sample,
@@ -808,7 +848,7 @@ static int deliver_sample_group(struct perf_session *session,
808 u64 i; 848 u64 i;
809 849
810 for (i = 0; i < sample->read.group.nr; i++) { 850 for (i = 0; i < sample->read.group.nr; i++) {
811 ret = deliver_sample_value(session, tool, event, sample, 851 ret = deliver_sample_value(evlist, tool, event, sample,
812 &sample->read.group.values[i], 852 &sample->read.group.values[i],
813 machine); 853 machine);
814 if (ret) 854 if (ret)
@@ -819,7 +859,7 @@ static int deliver_sample_group(struct perf_session *session,
819} 859}
820 860
821static int 861static int
822perf_session__deliver_sample(struct perf_session *session, 862 perf_evlist__deliver_sample(struct perf_evlist *evlist,
823 struct perf_tool *tool, 863 struct perf_tool *tool,
824 union perf_event *event, 864 union perf_event *event,
825 struct perf_sample *sample, 865 struct perf_sample *sample,
@@ -836,41 +876,40 @@ perf_session__deliver_sample(struct perf_session *session,
836 876
837 /* For PERF_SAMPLE_READ we have either single or group mode. */ 877 /* For PERF_SAMPLE_READ we have either single or group mode. */
838 if (read_format & PERF_FORMAT_GROUP) 878 if (read_format & PERF_FORMAT_GROUP)
839 return deliver_sample_group(session, tool, event, sample, 879 return deliver_sample_group(evlist, tool, event, sample,
840 machine); 880 machine);
841 else 881 else
842 return deliver_sample_value(session, tool, event, sample, 882 return deliver_sample_value(evlist, tool, event, sample,
843 &sample->read.one, machine); 883 &sample->read.one, machine);
844} 884}
845 885
846int perf_session__deliver_event(struct perf_session *session, 886static int machines__deliver_event(struct machines *machines,
847 union perf_event *event, 887 struct perf_evlist *evlist,
848 struct perf_sample *sample, 888 union perf_event *event,
849 struct perf_tool *tool, u64 file_offset) 889 struct perf_sample *sample,
890 struct perf_tool *tool, u64 file_offset)
850{ 891{
851 struct perf_evsel *evsel; 892 struct perf_evsel *evsel;
852 struct machine *machine; 893 struct machine *machine;
853 894
854 dump_event(session, event, file_offset, sample); 895 dump_event(evlist, event, file_offset, sample);
855 896
856 evsel = perf_evlist__id2evsel(session->evlist, sample->id); 897 evsel = perf_evlist__id2evsel(evlist, sample->id);
857 898
858 machine = perf_session__find_machine_for_cpumode(session, event, 899 machine = machines__find_for_cpumode(machines, event, sample);
859 sample);
860 900
861 switch (event->header.type) { 901 switch (event->header.type) {
862 case PERF_RECORD_SAMPLE: 902 case PERF_RECORD_SAMPLE:
863 dump_sample(evsel, event, sample); 903 dump_sample(evsel, event, sample);
864 if (evsel == NULL) { 904 if (evsel == NULL) {
865 ++session->stats.nr_unknown_id; 905 ++evlist->stats.nr_unknown_id;
866 return 0; 906 return 0;
867 } 907 }
868 if (machine == NULL) { 908 if (machine == NULL) {
869 ++session->stats.nr_unprocessable_samples; 909 ++evlist->stats.nr_unprocessable_samples;
870 return 0; 910 return 0;
871 } 911 }
872 return perf_session__deliver_sample(session, tool, event, 912 return perf_evlist__deliver_sample(evlist, tool, event, sample, evsel, machine);
873 sample, evsel, machine);
874 case PERF_RECORD_MMAP: 913 case PERF_RECORD_MMAP:
875 return tool->mmap(tool, event, sample, machine); 914 return tool->mmap(tool, event, sample, machine);
876 case PERF_RECORD_MMAP2: 915 case PERF_RECORD_MMAP2:
@@ -883,7 +922,7 @@ int perf_session__deliver_event(struct perf_session *session,
883 return tool->exit(tool, event, sample, machine); 922 return tool->exit(tool, event, sample, machine);
884 case PERF_RECORD_LOST: 923 case PERF_RECORD_LOST:
885 if (tool->lost == perf_event__process_lost) 924 if (tool->lost == perf_event__process_lost)
886 session->stats.total_lost += event->lost.lost; 925 evlist->stats.total_lost += event->lost.lost;
887 return tool->lost(tool, event, sample, machine); 926 return tool->lost(tool, event, sample, machine);
888 case PERF_RECORD_READ: 927 case PERF_RECORD_READ:
889 return tool->read(tool, event, sample, evsel, machine); 928 return tool->read(tool, event, sample, evsel, machine);
@@ -892,20 +931,21 @@ int perf_session__deliver_event(struct perf_session *session,
892 case PERF_RECORD_UNTHROTTLE: 931 case PERF_RECORD_UNTHROTTLE:
893 return tool->unthrottle(tool, event, sample, machine); 932 return tool->unthrottle(tool, event, sample, machine);
894 default: 933 default:
895 ++session->stats.nr_unknown_events; 934 ++evlist->stats.nr_unknown_events;
896 return -1; 935 return -1;
897 } 936 }
898} 937}
899 938
900static s64 perf_session__process_user_event(struct perf_session *session, 939static s64 perf_session__process_user_event(struct perf_session *session,
901 union perf_event *event, 940 union perf_event *event,
902 struct perf_tool *tool,
903 u64 file_offset) 941 u64 file_offset)
904{ 942{
943 struct ordered_events *oe = &session->ordered_events;
944 struct perf_tool *tool = oe->tool;
905 int fd = perf_data_file__fd(session->file); 945 int fd = perf_data_file__fd(session->file);
906 int err; 946 int err;
907 947
908 dump_event(session, event, file_offset, NULL); 948 dump_event(session->evlist, event, file_offset, NULL);
909 949
910 /* These events are processed right away */ 950 /* These events are processed right away */
911 switch (event->header.type) { 951 switch (event->header.type) {
@@ -929,7 +969,7 @@ static s64 perf_session__process_user_event(struct perf_session *session,
929 case PERF_RECORD_HEADER_BUILD_ID: 969 case PERF_RECORD_HEADER_BUILD_ID:
930 return tool->build_id(tool, event, session); 970 return tool->build_id(tool, event, session);
931 case PERF_RECORD_FINISHED_ROUND: 971 case PERF_RECORD_FINISHED_ROUND:
932 return tool->finished_round(tool, event, session); 972 return tool->finished_round(tool, event, oe);
933 case PERF_RECORD_ID_INDEX: 973 case PERF_RECORD_ID_INDEX:
934 return tool->id_index(tool, event, session); 974 return tool->id_index(tool, event, session);
935 default: 975 default:
@@ -939,15 +979,17 @@ static s64 perf_session__process_user_event(struct perf_session *session,
939 979
940int perf_session__deliver_synth_event(struct perf_session *session, 980int perf_session__deliver_synth_event(struct perf_session *session,
941 union perf_event *event, 981 union perf_event *event,
942 struct perf_sample *sample, 982 struct perf_sample *sample)
943 struct perf_tool *tool)
944{ 983{
945 events_stats__inc(&session->stats, event->header.type); 984 struct perf_evlist *evlist = session->evlist;
985 struct perf_tool *tool = session->ordered_events.tool;
986
987 events_stats__inc(&evlist->stats, event->header.type);
946 988
947 if (event->header.type >= PERF_RECORD_USER_TYPE_START) 989 if (event->header.type >= PERF_RECORD_USER_TYPE_START)
948 return perf_session__process_user_event(session, event, tool, 0); 990 return perf_session__process_user_event(session, event, 0);
949 991
950 return perf_session__deliver_event(session, event, sample, tool, 0); 992 return machines__deliver_event(&session->machines, evlist, event, sample, tool, 0);
951} 993}
952 994
953static void event_swap(union perf_event *event, bool sample_id_all) 995static void event_swap(union perf_event *event, bool sample_id_all)
@@ -1015,40 +1057,39 @@ out_parse_sample:
1015} 1057}
1016 1058
1017static s64 perf_session__process_event(struct perf_session *session, 1059static s64 perf_session__process_event(struct perf_session *session,
1018 union perf_event *event, 1060 union perf_event *event, u64 file_offset)
1019 struct perf_tool *tool,
1020 u64 file_offset)
1021{ 1061{
1062 struct perf_evlist *evlist = session->evlist;
1063 struct perf_tool *tool = session->ordered_events.tool;
1022 struct perf_sample sample; 1064 struct perf_sample sample;
1023 int ret; 1065 int ret;
1024 1066
1025 if (session->header.needs_swap) 1067 if (session->header.needs_swap)
1026 event_swap(event, perf_evlist__sample_id_all(session->evlist)); 1068 event_swap(event, perf_evlist__sample_id_all(evlist));
1027 1069
1028 if (event->header.type >= PERF_RECORD_HEADER_MAX) 1070 if (event->header.type >= PERF_RECORD_HEADER_MAX)
1029 return -EINVAL; 1071 return -EINVAL;
1030 1072
1031 events_stats__inc(&session->stats, event->header.type); 1073 events_stats__inc(&evlist->stats, event->header.type);
1032 1074
1033 if (event->header.type >= PERF_RECORD_USER_TYPE_START) 1075 if (event->header.type >= PERF_RECORD_USER_TYPE_START)
1034 return perf_session__process_user_event(session, event, tool, file_offset); 1076 return perf_session__process_user_event(session, event, file_offset);
1035 1077
1036 /* 1078 /*
1037 * For all kernel events we get the sample data 1079 * For all kernel events we get the sample data
1038 */ 1080 */
1039 ret = perf_evlist__parse_sample(session->evlist, event, &sample); 1081 ret = perf_evlist__parse_sample(evlist, event, &sample);
1040 if (ret) 1082 if (ret)
1041 return ret; 1083 return ret;
1042 1084
1043 if (tool->ordered_events) { 1085 if (tool->ordered_events) {
1044 ret = perf_session_queue_event(session, event, tool, &sample, 1086 ret = perf_session__queue_event(session, event, &sample, file_offset);
1045 file_offset);
1046 if (ret != -ETIME) 1087 if (ret != -ETIME)
1047 return ret; 1088 return ret;
1048 } 1089 }
1049 1090
1050 return perf_session__deliver_event(session, event, &sample, tool, 1091 return machines__deliver_event(&session->machines, evlist, event,
1051 file_offset); 1092 &sample, tool, file_offset);
1052} 1093}
1053 1094
1054void perf_event_header__bswap(struct perf_event_header *hdr) 1095void perf_event_header__bswap(struct perf_event_header *hdr)
@@ -1076,54 +1117,55 @@ static struct thread *perf_session__register_idle_thread(struct perf_session *se
1076 return thread; 1117 return thread;
1077} 1118}
1078 1119
1079static void perf_session__warn_about_errors(const struct perf_session *session, 1120static void perf_tool__warn_about_errors(const struct perf_tool *tool,
1080 const struct perf_tool *tool) 1121 const struct events_stats *stats)
1081{ 1122{
1082 if (tool->lost == perf_event__process_lost && 1123 if (tool->lost == perf_event__process_lost &&
1083 session->stats.nr_events[PERF_RECORD_LOST] != 0) { 1124 stats->nr_events[PERF_RECORD_LOST] != 0) {
1084 ui__warning("Processed %d events and lost %d chunks!\n\n" 1125 ui__warning("Processed %d events and lost %d chunks!\n\n"
1085 "Check IO/CPU overload!\n\n", 1126 "Check IO/CPU overload!\n\n",
1086 session->stats.nr_events[0], 1127 stats->nr_events[0],
1087 session->stats.nr_events[PERF_RECORD_LOST]); 1128 stats->nr_events[PERF_RECORD_LOST]);
1088 } 1129 }
1089 1130
1090 if (session->stats.nr_unknown_events != 0) { 1131 if (stats->nr_unknown_events != 0) {
1091 ui__warning("Found %u unknown events!\n\n" 1132 ui__warning("Found %u unknown events!\n\n"
1092 "Is this an older tool processing a perf.data " 1133 "Is this an older tool processing a perf.data "
1093 "file generated by a more recent tool?\n\n" 1134 "file generated by a more recent tool?\n\n"
1094 "If that is not the case, consider " 1135 "If that is not the case, consider "
1095 "reporting to linux-kernel@vger.kernel.org.\n\n", 1136 "reporting to linux-kernel@vger.kernel.org.\n\n",
1096 session->stats.nr_unknown_events); 1137 stats->nr_unknown_events);
1097 } 1138 }
1098 1139
1099 if (session->stats.nr_unknown_id != 0) { 1140 if (stats->nr_unknown_id != 0) {
1100 ui__warning("%u samples with id not present in the header\n", 1141 ui__warning("%u samples with id not present in the header\n",
1101 session->stats.nr_unknown_id); 1142 stats->nr_unknown_id);
1102 } 1143 }
1103 1144
1104 if (session->stats.nr_invalid_chains != 0) { 1145 if (stats->nr_invalid_chains != 0) {
1105 ui__warning("Found invalid callchains!\n\n" 1146 ui__warning("Found invalid callchains!\n\n"
1106 "%u out of %u events were discarded for this reason.\n\n" 1147 "%u out of %u events were discarded for this reason.\n\n"
1107 "Consider reporting to linux-kernel@vger.kernel.org.\n\n", 1148 "Consider reporting to linux-kernel@vger.kernel.org.\n\n",
1108 session->stats.nr_invalid_chains, 1149 stats->nr_invalid_chains,
1109 session->stats.nr_events[PERF_RECORD_SAMPLE]); 1150 stats->nr_events[PERF_RECORD_SAMPLE]);
1110 } 1151 }
1111 1152
1112 if (session->stats.nr_unprocessable_samples != 0) { 1153 if (stats->nr_unprocessable_samples != 0) {
1113 ui__warning("%u unprocessable samples recorded.\n" 1154 ui__warning("%u unprocessable samples recorded.\n"
1114 "Do you have a KVM guest running and not using 'perf kvm'?\n", 1155 "Do you have a KVM guest running and not using 'perf kvm'?\n",
1115 session->stats.nr_unprocessable_samples); 1156 stats->nr_unprocessable_samples);
1116 } 1157 }
1117 1158
1118 if (session->stats.nr_unordered_events != 0) 1159 if (stats->nr_unordered_events != 0)
1119 ui__warning("%u out of order events recorded.\n", session->stats.nr_unordered_events); 1160 ui__warning("%u out of order events recorded.\n", stats->nr_unordered_events);
1120} 1161}
1121 1162
1122volatile int session_done; 1163volatile int session_done;
1123 1164
1124static int __perf_session__process_pipe_events(struct perf_session *session, 1165static int __perf_session__process_pipe_events(struct perf_session *session)
1125 struct perf_tool *tool)
1126{ 1166{
1167 struct ordered_events *oe = &session->ordered_events;
1168 struct perf_tool *tool = oe->tool;
1127 int fd = perf_data_file__fd(session->file); 1169 int fd = perf_data_file__fd(session->file);
1128 union perf_event *event; 1170 union perf_event *event;
1129 uint32_t size, cur_size = 0; 1171 uint32_t size, cur_size = 0;
@@ -1187,7 +1229,7 @@ more:
1187 } 1229 }
1188 } 1230 }
1189 1231
1190 if ((skip = perf_session__process_event(session, event, tool, head)) < 0) { 1232 if ((skip = perf_session__process_event(session, event, head)) < 0) {
1191 pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n", 1233 pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n",
1192 head, event->header.size, event->header.type); 1234 head, event->header.size, event->header.type);
1193 err = -EINVAL; 1235 err = -EINVAL;
@@ -1203,10 +1245,10 @@ more:
1203 goto more; 1245 goto more;
1204done: 1246done:
1205 /* do the final flush for ordered samples */ 1247 /* do the final flush for ordered samples */
1206 err = ordered_events__flush(session, tool, OE_FLUSH__FINAL); 1248 err = ordered_events__flush(oe, OE_FLUSH__FINAL);
1207out_err: 1249out_err:
1208 free(buf); 1250 free(buf);
1209 perf_session__warn_about_errors(session, tool); 1251 perf_tool__warn_about_errors(tool, &session->evlist->stats);
1210 ordered_events__free(&session->ordered_events); 1252 ordered_events__free(&session->ordered_events);
1211 return err; 1253 return err;
1212} 1254}
@@ -1253,8 +1295,10 @@ fetch_mmaped_event(struct perf_session *session,
1253 1295
1254static int __perf_session__process_events(struct perf_session *session, 1296static int __perf_session__process_events(struct perf_session *session,
1255 u64 data_offset, u64 data_size, 1297 u64 data_offset, u64 data_size,
1256 u64 file_size, struct perf_tool *tool) 1298 u64 file_size)
1257{ 1299{
1300 struct ordered_events *oe = &session->ordered_events;
1301 struct perf_tool *tool = oe->tool;
1258 int fd = perf_data_file__fd(session->file); 1302 int fd = perf_data_file__fd(session->file);
1259 u64 head, page_offset, file_offset, file_pos, size; 1303 u64 head, page_offset, file_offset, file_pos, size;
1260 int err, mmap_prot, mmap_flags, map_idx = 0; 1304 int err, mmap_prot, mmap_flags, map_idx = 0;
@@ -1323,8 +1367,7 @@ more:
1323 size = event->header.size; 1367 size = event->header.size;
1324 1368
1325 if (size < sizeof(struct perf_event_header) || 1369 if (size < sizeof(struct perf_event_header) ||
1326 (skip = perf_session__process_event(session, event, tool, file_pos)) 1370 (skip = perf_session__process_event(session, event, file_pos)) < 0) {
1327 < 0) {
1328 pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n", 1371 pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n",
1329 file_offset + head, event->header.size, 1372 file_offset + head, event->header.size,
1330 event->header.type); 1373 event->header.type);
@@ -1348,17 +1391,16 @@ more:
1348 1391
1349out: 1392out:
1350 /* do the final flush for ordered samples */ 1393 /* do the final flush for ordered samples */
1351 err = ordered_events__flush(session, tool, OE_FLUSH__FINAL); 1394 err = ordered_events__flush(oe, OE_FLUSH__FINAL);
1352out_err: 1395out_err:
1353 ui_progress__finish(); 1396 ui_progress__finish();
1354 perf_session__warn_about_errors(session, tool); 1397 perf_tool__warn_about_errors(tool, &session->evlist->stats);
1355 ordered_events__free(&session->ordered_events); 1398 ordered_events__free(&session->ordered_events);
1356 session->one_mmap = false; 1399 session->one_mmap = false;
1357 return err; 1400 return err;
1358} 1401}
1359 1402
1360int perf_session__process_events(struct perf_session *session, 1403int perf_session__process_events(struct perf_session *session)
1361 struct perf_tool *tool)
1362{ 1404{
1363 u64 size = perf_data_file__size(session->file); 1405 u64 size = perf_data_file__size(session->file);
1364 int err; 1406 int err;
@@ -1369,10 +1411,9 @@ int perf_session__process_events(struct perf_session *session,
1369 if (!perf_data_file__is_pipe(session->file)) 1411 if (!perf_data_file__is_pipe(session->file))
1370 err = __perf_session__process_events(session, 1412 err = __perf_session__process_events(session,
1371 session->header.data_offset, 1413 session->header.data_offset,
1372 session->header.data_size, 1414 session->header.data_size, size);
1373 size, tool);
1374 else 1415 else
1375 err = __perf_session__process_pipe_events(session, tool); 1416 err = __perf_session__process_pipe_events(session);
1376 1417
1377 return err; 1418 return err;
1378} 1419}
@@ -1436,7 +1477,7 @@ size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp)
1436{ 1477{
1437 size_t ret = fprintf(fp, "Aggregated stats:\n"); 1478 size_t ret = fprintf(fp, "Aggregated stats:\n");
1438 1479
1439 ret += events_stats__fprintf(&session->stats, fp); 1480 ret += events_stats__fprintf(&session->evlist->stats, fp);
1440 return ret; 1481 return ret;
1441} 1482}
1442 1483
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 6d663dc76404..1310998f8318 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -20,7 +20,6 @@ struct perf_session {
20 struct machines machines; 20 struct machines machines;
21 struct perf_evlist *evlist; 21 struct perf_evlist *evlist;
22 struct trace_event tevent; 22 struct trace_event tevent;
23 struct events_stats stats;
24 bool repipe; 23 bool repipe;
25 bool one_mmap; 24 bool one_mmap;
26 void *one_mmap_addr; 25 void *one_mmap_addr;
@@ -49,20 +48,13 @@ int perf_session__peek_event(struct perf_session *session, off_t file_offset,
49 union perf_event **event_ptr, 48 union perf_event **event_ptr,
50 struct perf_sample *sample); 49 struct perf_sample *sample);
51 50
52int perf_session__process_events(struct perf_session *session, 51int perf_session__process_events(struct perf_session *session);
53 struct perf_tool *tool);
54 52
55int perf_session_queue_event(struct perf_session *s, union perf_event *event, 53int perf_session__queue_event(struct perf_session *s, union perf_event *event,
56 struct perf_tool *tool, struct perf_sample *sample, 54 struct perf_sample *sample, u64 file_offset);
57 u64 file_offset);
58 55
59void perf_tool__fill_defaults(struct perf_tool *tool); 56void perf_tool__fill_defaults(struct perf_tool *tool);
60 57
61int perf_session__deliver_event(struct perf_session *session,
62 union perf_event *event,
63 struct perf_sample *sample,
64 struct perf_tool *tool, u64 file_offset);
65
66int perf_session__resolve_callchain(struct perf_session *session, 58int perf_session__resolve_callchain(struct perf_session *session,
67 struct perf_evsel *evsel, 59 struct perf_evsel *evsel,
68 struct thread *thread, 60 struct thread *thread,
@@ -126,8 +118,7 @@ extern volatile int session_done;
126 118
127int perf_session__deliver_synth_event(struct perf_session *session, 119int perf_session__deliver_synth_event(struct perf_session *session,
128 union perf_event *event, 120 union perf_event *event,
129 struct perf_sample *sample, 121 struct perf_sample *sample);
130 struct perf_tool *tool);
131 122
132int perf_event__process_id_index(struct perf_tool *tool, 123int perf_event__process_id_index(struct perf_tool *tool,
133 union perf_event *event, 124 union perf_event *event,
diff --git a/tools/perf/util/setup.py b/tools/perf/util/setup.py
index d0aee4b9dfd4..1833103768cb 100644
--- a/tools/perf/util/setup.py
+++ b/tools/perf/util/setup.py
@@ -25,7 +25,7 @@ cflags += ['-fno-strict-aliasing', '-Wno-write-strings', '-Wno-unused-parameter'
25build_lib = getenv('PYTHON_EXTBUILD_LIB') 25build_lib = getenv('PYTHON_EXTBUILD_LIB')
26build_tmp = getenv('PYTHON_EXTBUILD_TMP') 26build_tmp = getenv('PYTHON_EXTBUILD_TMP')
27libtraceevent = getenv('LIBTRACEEVENT') 27libtraceevent = getenv('LIBTRACEEVENT')
28libapikfs = getenv('LIBAPIKFS') 28libapikfs = getenv('LIBAPI')
29 29
30ext_sources = [f.strip() for f in file('util/python-ext-sources') 30ext_sources = [f.strip() for f in file('util/python-ext-sources')
31 if len(f.strip()) > 0 and f[0] != '#'] 31 if len(f.strip()) > 0 and f[0] != '#']
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 7a39c1ed8d37..4593f36ecc4c 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -1463,6 +1463,15 @@ int sort_dimension__add(const char *tok)
1463 sort__has_parent = 1; 1463 sort__has_parent = 1;
1464 } else if (sd->entry == &sort_sym) { 1464 } else if (sd->entry == &sort_sym) {
1465 sort__has_sym = 1; 1465 sort__has_sym = 1;
1466 /*
1467 * perf diff displays the performance difference amongst
1468 * two or more perf.data files. Those files could come
1469 * from different binaries. So we should not compare
1470 * their ips, but the name of symbol.
1471 */
1472 if (sort__mode == SORT_MODE__DIFF)
1473 sd->entry->se_collapse = sort__sym_sort;
1474
1466 } else if (sd->entry == &sort_dso) { 1475 } else if (sd->entry == &sort_dso) {
1467 sort__has_dso = 1; 1476 sort__has_dso = 1;
1468 } 1477 }
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index c03e4ff8beff..846036a921dc 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -44,6 +44,7 @@ extern struct sort_entry sort_dso_to;
44extern struct sort_entry sort_sym_from; 44extern struct sort_entry sort_sym_from;
45extern struct sort_entry sort_sym_to; 45extern struct sort_entry sort_sym_to;
46extern enum sort_type sort__first_dimension; 46extern enum sort_type sort__first_dimension;
47extern const char default_mem_sort_order[];
47 48
48struct he_stat { 49struct he_stat {
49 u64 period; 50 u64 period;
@@ -102,7 +103,6 @@ struct hist_entry {
102 103
103 bool init_have_children; 104 bool init_have_children;
104 char level; 105 char level;
105 bool used;
106 u8 filtered; 106 u8 filtered;
107 char *srcline; 107 char *srcline;
108 struct symbol *parent; 108 struct symbol *parent;
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 33b7a2aef713..476268c99431 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -74,6 +74,10 @@ static inline uint8_t elf_sym__type(const GElf_Sym *sym)
74 return GELF_ST_TYPE(sym->st_info); 74 return GELF_ST_TYPE(sym->st_info);
75} 75}
76 76
77#ifndef STT_GNU_IFUNC
78#define STT_GNU_IFUNC 10
79#endif
80
77static inline int elf_sym__is_function(const GElf_Sym *sym) 81static inline int elf_sym__is_function(const GElf_Sym *sym)
78{ 82{
79 return (elf_sym__type(sym) == STT_FUNC || 83 return (elf_sym__type(sym) == STT_FUNC ||
@@ -575,32 +579,37 @@ static int dso__swap_init(struct dso *dso, unsigned char eidata)
575static int decompress_kmodule(struct dso *dso, const char *name, 579static int decompress_kmodule(struct dso *dso, const char *name,
576 enum dso_binary_type type) 580 enum dso_binary_type type)
577{ 581{
578 int fd; 582 int fd = -1;
579 const char *ext = strrchr(name, '.');
580 char tmpbuf[] = "/tmp/perf-kmod-XXXXXX"; 583 char tmpbuf[] = "/tmp/perf-kmod-XXXXXX";
584 struct kmod_path m;
581 585
582 if (type != DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP && 586 if (type != DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP &&
583 type != DSO_BINARY_TYPE__GUEST_KMODULE_COMP && 587 type != DSO_BINARY_TYPE__GUEST_KMODULE_COMP &&
584 type != DSO_BINARY_TYPE__BUILD_ID_CACHE) 588 type != DSO_BINARY_TYPE__BUILD_ID_CACHE)
585 return -1; 589 return -1;
586 590
587 if (!ext || !is_supported_compression(ext + 1)) { 591 if (type == DSO_BINARY_TYPE__BUILD_ID_CACHE)
588 ext = strrchr(dso->name, '.'); 592 name = dso->long_name;
589 if (!ext || !is_supported_compression(ext + 1))
590 return -1;
591 }
592 593
593 fd = mkstemp(tmpbuf); 594 if (kmod_path__parse_ext(&m, name) || !m.comp)
594 if (fd < 0)
595 return -1; 595 return -1;
596 596
597 if (!decompress_to_file(ext + 1, name, fd)) { 597 fd = mkstemp(tmpbuf);
598 if (fd < 0) {
599 dso->load_errno = errno;
600 goto out;
601 }
602
603 if (!decompress_to_file(m.ext, name, fd)) {
604 dso->load_errno = DSO_LOAD_ERRNO__DECOMPRESSION_FAILURE;
598 close(fd); 605 close(fd);
599 fd = -1; 606 fd = -1;
600 } 607 }
601 608
602 unlink(tmpbuf); 609 unlink(tmpbuf);
603 610
611out:
612 free(m.ext);
604 return fd; 613 return fd;
605} 614}
606 615
@@ -629,37 +638,49 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
629 Elf *elf; 638 Elf *elf;
630 int fd; 639 int fd;
631 640
632 if (dso__needs_decompress(dso)) 641 if (dso__needs_decompress(dso)) {
633 fd = decompress_kmodule(dso, name, type); 642 fd = decompress_kmodule(dso, name, type);
634 else 643 if (fd < 0)
644 return -1;
645 } else {
635 fd = open(name, O_RDONLY); 646 fd = open(name, O_RDONLY);
636 647 if (fd < 0) {
637 if (fd < 0) 648 dso->load_errno = errno;
638 return -1; 649 return -1;
650 }
651 }
639 652
640 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); 653 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
641 if (elf == NULL) { 654 if (elf == NULL) {
642 pr_debug("%s: cannot read %s ELF file.\n", __func__, name); 655 pr_debug("%s: cannot read %s ELF file.\n", __func__, name);
656 dso->load_errno = DSO_LOAD_ERRNO__INVALID_ELF;
643 goto out_close; 657 goto out_close;
644 } 658 }
645 659
646 if (gelf_getehdr(elf, &ehdr) == NULL) { 660 if (gelf_getehdr(elf, &ehdr) == NULL) {
661 dso->load_errno = DSO_LOAD_ERRNO__INVALID_ELF;
647 pr_debug("%s: cannot get elf header.\n", __func__); 662 pr_debug("%s: cannot get elf header.\n", __func__);
648 goto out_elf_end; 663 goto out_elf_end;
649 } 664 }
650 665
651 if (dso__swap_init(dso, ehdr.e_ident[EI_DATA])) 666 if (dso__swap_init(dso, ehdr.e_ident[EI_DATA])) {
667 dso->load_errno = DSO_LOAD_ERRNO__INTERNAL_ERROR;
652 goto out_elf_end; 668 goto out_elf_end;
669 }
653 670
654 /* Always reject images with a mismatched build-id: */ 671 /* Always reject images with a mismatched build-id: */
655 if (dso->has_build_id) { 672 if (dso->has_build_id) {
656 u8 build_id[BUILD_ID_SIZE]; 673 u8 build_id[BUILD_ID_SIZE];
657 674
658 if (elf_read_build_id(elf, build_id, BUILD_ID_SIZE) < 0) 675 if (elf_read_build_id(elf, build_id, BUILD_ID_SIZE) < 0) {
676 dso->load_errno = DSO_LOAD_ERRNO__CANNOT_READ_BUILDID;
659 goto out_elf_end; 677 goto out_elf_end;
678 }
660 679
661 if (!dso__build_id_equal(dso, build_id)) 680 if (!dso__build_id_equal(dso, build_id)) {
681 dso->load_errno = DSO_LOAD_ERRNO__MISMATCHING_BUILDID;
662 goto out_elf_end; 682 goto out_elf_end;
683 }
663 } 684 }
664 685
665 ss->is_64_bit = (gelf_getclass(elf) == ELFCLASS64); 686 ss->is_64_bit = (gelf_getclass(elf) == ELFCLASS64);
@@ -695,8 +716,10 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
695 } 716 }
696 717
697 ss->name = strdup(name); 718 ss->name = strdup(name);
698 if (!ss->name) 719 if (!ss->name) {
720 dso->load_errno = errno;
699 goto out_elf_end; 721 goto out_elf_end;
722 }
700 723
701 ss->elf = elf; 724 ss->elf = elf;
702 ss->fd = fd; 725 ss->fd = fd;
@@ -864,10 +887,9 @@ int dso__load_sym(struct dso *dso, struct map *map,
864 /* Reject ARM ELF "mapping symbols": these aren't unique and 887 /* Reject ARM ELF "mapping symbols": these aren't unique and
865 * don't identify functions, so will confuse the profile 888 * don't identify functions, so will confuse the profile
866 * output: */ 889 * output: */
867 if (ehdr.e_machine == EM_ARM) { 890 if (ehdr.e_machine == EM_ARM || ehdr.e_machine == EM_AARCH64) {
868 if (!strcmp(elf_name, "$a") || 891 if (elf_name[0] == '$' && strchr("adtx", elf_name[1])
869 !strcmp(elf_name, "$d") || 892 && (elf_name[2] == '\0' || elf_name[2] == '.'))
870 !strcmp(elf_name, "$t"))
871 continue; 893 continue;
872 } 894 }
873 895
@@ -1045,7 +1067,8 @@ new_symbol:
1045 * For misannotated, zeroed, ASM function sizes. 1067 * For misannotated, zeroed, ASM function sizes.
1046 */ 1068 */
1047 if (nr > 0) { 1069 if (nr > 0) {
1048 symbols__fixup_duplicate(&dso->symbols[map->type]); 1070 if (!symbol_conf.allow_aliases)
1071 symbols__fixup_duplicate(&dso->symbols[map->type]);
1049 symbols__fixup_end(&dso->symbols[map->type]); 1072 symbols__fixup_end(&dso->symbols[map->type]);
1050 if (kmap) { 1073 if (kmap) {
1051 /* 1074 /*
diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c
index d7efb03b3f9a..fd8477cacf88 100644
--- a/tools/perf/util/symbol-minimal.c
+++ b/tools/perf/util/symbol-minimal.c
@@ -246,13 +246,12 @@ out:
246 return ret; 246 return ret;
247} 247}
248 248
249int symsrc__init(struct symsrc *ss, struct dso *dso __maybe_unused, 249int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
250 const char *name,
251 enum dso_binary_type type) 250 enum dso_binary_type type)
252{ 251{
253 int fd = open(name, O_RDONLY); 252 int fd = open(name, O_RDONLY);
254 if (fd < 0) 253 if (fd < 0)
255 return -1; 254 goto out_errno;
256 255
257 ss->name = strdup(name); 256 ss->name = strdup(name);
258 if (!ss->name) 257 if (!ss->name)
@@ -264,6 +263,8 @@ int symsrc__init(struct symsrc *ss, struct dso *dso __maybe_unused,
264 return 0; 263 return 0;
265out_close: 264out_close:
266 close(fd); 265 close(fd);
266out_errno:
267 dso->load_errno = errno;
267 return -1; 268 return -1;
268} 269}
269 270
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index a69066865a55..fddeb9073039 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -15,6 +15,7 @@
15#include "machine.h" 15#include "machine.h"
16#include "symbol.h" 16#include "symbol.h"
17#include "strlist.h" 17#include "strlist.h"
18#include "intlist.h"
18#include "header.h" 19#include "header.h"
19 20
20#include <elf.h> 21#include <elf.h>
@@ -1859,6 +1860,20 @@ int setup_list(struct strlist **list, const char *list_str,
1859 return 0; 1860 return 0;
1860} 1861}
1861 1862
1863int setup_intlist(struct intlist **list, const char *list_str,
1864 const char *list_name)
1865{
1866 if (list_str == NULL)
1867 return 0;
1868
1869 *list = intlist__new(list_str);
1870 if (!*list) {
1871 pr_err("problems parsing %s list\n", list_name);
1872 return -1;
1873 }
1874 return 0;
1875}
1876
1862static bool symbol__read_kptr_restrict(void) 1877static bool symbol__read_kptr_restrict(void)
1863{ 1878{
1864 bool value = false; 1879 bool value = false;
@@ -1909,9 +1924,17 @@ int symbol__init(struct perf_session_env *env)
1909 symbol_conf.comm_list_str, "comm") < 0) 1924 symbol_conf.comm_list_str, "comm") < 0)
1910 goto out_free_dso_list; 1925 goto out_free_dso_list;
1911 1926
1927 if (setup_intlist(&symbol_conf.pid_list,
1928 symbol_conf.pid_list_str, "pid") < 0)
1929 goto out_free_comm_list;
1930
1931 if (setup_intlist(&symbol_conf.tid_list,
1932 symbol_conf.tid_list_str, "tid") < 0)
1933 goto out_free_pid_list;
1934
1912 if (setup_list(&symbol_conf.sym_list, 1935 if (setup_list(&symbol_conf.sym_list,
1913 symbol_conf.sym_list_str, "symbol") < 0) 1936 symbol_conf.sym_list_str, "symbol") < 0)
1914 goto out_free_comm_list; 1937 goto out_free_tid_list;
1915 1938
1916 /* 1939 /*
1917 * A path to symbols of "/" is identical to "" 1940 * A path to symbols of "/" is identical to ""
@@ -1930,6 +1953,10 @@ int symbol__init(struct perf_session_env *env)
1930 symbol_conf.initialized = true; 1953 symbol_conf.initialized = true;
1931 return 0; 1954 return 0;
1932 1955
1956out_free_tid_list:
1957 intlist__delete(symbol_conf.tid_list);
1958out_free_pid_list:
1959 intlist__delete(symbol_conf.pid_list);
1933out_free_comm_list: 1960out_free_comm_list:
1934 strlist__delete(symbol_conf.comm_list); 1961 strlist__delete(symbol_conf.comm_list);
1935out_free_dso_list: 1962out_free_dso_list:
@@ -1944,6 +1971,8 @@ void symbol__exit(void)
1944 strlist__delete(symbol_conf.sym_list); 1971 strlist__delete(symbol_conf.sym_list);
1945 strlist__delete(symbol_conf.dso_list); 1972 strlist__delete(symbol_conf.dso_list);
1946 strlist__delete(symbol_conf.comm_list); 1973 strlist__delete(symbol_conf.comm_list);
1974 intlist__delete(symbol_conf.tid_list);
1975 intlist__delete(symbol_conf.pid_list);
1947 vmlinux_path__exit(); 1976 vmlinux_path__exit();
1948 symbol_conf.sym_list = symbol_conf.dso_list = symbol_conf.comm_list = NULL; 1977 symbol_conf.sym_list = symbol_conf.dso_list = symbol_conf.comm_list = NULL;
1949 symbol_conf.initialized = false; 1978 symbol_conf.initialized = false;
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 1650dcb3a67b..09561500164a 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -78,6 +78,7 @@ static inline size_t symbol__size(const struct symbol *sym)
78} 78}
79 79
80struct strlist; 80struct strlist;
81struct intlist;
81 82
82struct symbol_conf { 83struct symbol_conf {
83 unsigned short priv_size; 84 unsigned short priv_size;
@@ -87,6 +88,7 @@ struct symbol_conf {
87 ignore_vmlinux_buildid, 88 ignore_vmlinux_buildid,
88 show_kernel_path, 89 show_kernel_path,
89 use_modules, 90 use_modules,
91 allow_aliases,
90 sort_by_name, 92 sort_by_name,
91 show_nr_samples, 93 show_nr_samples,
92 show_total_period, 94 show_total_period,
@@ -114,6 +116,8 @@ struct symbol_conf {
114 const char *guestmount; 116 const char *guestmount;
115 const char *dso_list_str, 117 const char *dso_list_str,
116 *comm_list_str, 118 *comm_list_str,
119 *pid_list_str,
120 *tid_list_str,
117 *sym_list_str, 121 *sym_list_str,
118 *col_width_list_str; 122 *col_width_list_str;
119 struct strlist *dso_list, 123 struct strlist *dso_list,
@@ -123,6 +127,8 @@ struct symbol_conf {
123 *dso_to_list, 127 *dso_to_list,
124 *sym_from_list, 128 *sym_from_list,
125 *sym_to_list; 129 *sym_to_list;
130 struct intlist *pid_list,
131 *tid_list;
126 const char *symfs; 132 const char *symfs;
127}; 133};
128 134
@@ -294,5 +300,7 @@ int compare_proc_modules(const char *from, const char *to);
294 300
295int setup_list(struct strlist **list, const char *list_str, 301int setup_list(struct strlist **list, const char *list_str,
296 const char *list_name); 302 const char *list_name);
303int setup_intlist(struct intlist **list, const char *list_str,
304 const char *list_name);
297 305
298#endif /* __PERF_SYMBOL */ 306#endif /* __PERF_SYMBOL */
diff --git a/tools/perf/util/target.c b/tools/perf/util/target.c
index e74c5963dc7a..a53603b27e52 100644
--- a/tools/perf/util/target.c
+++ b/tools/perf/util/target.c
@@ -123,11 +123,8 @@ int target__strerror(struct target *target, int errnum,
123 if (errnum >= 0) { 123 if (errnum >= 0) {
124 const char *err = strerror_r(errnum, buf, buflen); 124 const char *err = strerror_r(errnum, buf, buflen);
125 125
126 if (err != buf) { 126 if (err != buf)
127 size_t len = strlen(err); 127 scnprintf(buf, buflen, "%s", err);
128 memcpy(buf, err, min(buflen - 1, len));
129 *(buf + min(buflen - 1, len)) = '\0';
130 }
131 128
132 return 0; 129 return 0;
133 } 130 }
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 9ebc8b1f9be5..1c8fbc9588c5 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -82,6 +82,20 @@ void thread__delete(struct thread *thread)
82 free(thread); 82 free(thread);
83} 83}
84 84
85struct thread *thread__get(struct thread *thread)
86{
87 ++thread->refcnt;
88 return thread;
89}
90
91void thread__put(struct thread *thread)
92{
93 if (thread && --thread->refcnt == 0) {
94 list_del_init(&thread->node);
95 thread__delete(thread);
96 }
97}
98
85struct comm *thread__comm(const struct thread *thread) 99struct comm *thread__comm(const struct thread *thread)
86{ 100{
87 if (list_empty(&thread->comm_list)) 101 if (list_empty(&thread->comm_list))
@@ -192,7 +206,6 @@ int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp)
192 err = thread__set_comm(thread, comm, timestamp); 206 err = thread__set_comm(thread, comm, timestamp);
193 if (err) 207 if (err)
194 return err; 208 return err;
195 thread->comm_set = true;
196 } 209 }
197 210
198 thread->ppid = parent->tid; 211 thread->ppid = parent->tid;
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 160fd066a7d1..9b8a54dc34a8 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -7,6 +7,7 @@
7#include <sys/types.h> 7#include <sys/types.h>
8#include "symbol.h" 8#include "symbol.h"
9#include <strlist.h> 9#include <strlist.h>
10#include <intlist.h>
10 11
11struct thread_stack; 12struct thread_stack;
12 13
@@ -20,6 +21,7 @@ struct thread {
20 pid_t tid; 21 pid_t tid;
21 pid_t ppid; 22 pid_t ppid;
22 int cpu; 23 int cpu;
24 int refcnt;
23 char shortname[3]; 25 char shortname[3];
24 bool comm_set; 26 bool comm_set;
25 bool dead; /* if set thread has exited */ 27 bool dead; /* if set thread has exited */
@@ -37,6 +39,18 @@ struct comm;
37struct thread *thread__new(pid_t pid, pid_t tid); 39struct thread *thread__new(pid_t pid, pid_t tid);
38int thread__init_map_groups(struct thread *thread, struct machine *machine); 40int thread__init_map_groups(struct thread *thread, struct machine *machine);
39void thread__delete(struct thread *thread); 41void thread__delete(struct thread *thread);
42
43struct thread *thread__get(struct thread *thread);
44void thread__put(struct thread *thread);
45
46static inline void __thread__zput(struct thread **thread)
47{
48 thread__put(*thread);
49 *thread = NULL;
50}
51
52#define thread__zput(thread) __thread__zput(&thread)
53
40static inline void thread__exited(struct thread *thread) 54static inline void thread__exited(struct thread *thread)
41{ 55{
42 thread->dead = true; 56 thread->dead = true;
@@ -87,6 +101,16 @@ static inline bool thread__is_filtered(struct thread *thread)
87 return true; 101 return true;
88 } 102 }
89 103
104 if (symbol_conf.pid_list &&
105 !intlist__has_entry(symbol_conf.pid_list, thread->pid_)) {
106 return true;
107 }
108
109 if (symbol_conf.tid_list &&
110 !intlist__has_entry(symbol_conf.tid_list, thread->tid)) {
111 return true;
112 }
113
90 return false; 114 return false;
91} 115}
92 116
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index bb2708bbfaca..51d9e56c0f84 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -10,6 +10,7 @@ struct perf_evsel;
10struct perf_sample; 10struct perf_sample;
11struct perf_tool; 11struct perf_tool;
12struct machine; 12struct machine;
13struct ordered_events;
13 14
14typedef int (*event_sample)(struct perf_tool *tool, union perf_event *event, 15typedef int (*event_sample)(struct perf_tool *tool, union perf_event *event,
15 struct perf_sample *sample, 16 struct perf_sample *sample,
@@ -25,6 +26,9 @@ typedef int (*event_attr_op)(struct perf_tool *tool,
25typedef int (*event_op2)(struct perf_tool *tool, union perf_event *event, 26typedef int (*event_op2)(struct perf_tool *tool, union perf_event *event,
26 struct perf_session *session); 27 struct perf_session *session);
27 28
29typedef int (*event_oe)(struct perf_tool *tool, union perf_event *event,
30 struct ordered_events *oe);
31
28struct perf_tool { 32struct perf_tool {
29 event_sample sample, 33 event_sample sample,
30 read; 34 read;
@@ -38,8 +42,8 @@ struct perf_tool {
38 unthrottle; 42 unthrottle;
39 event_attr_op attr; 43 event_attr_op attr;
40 event_op2 tracing_data; 44 event_op2 tracing_data;
41 event_op2 finished_round, 45 event_oe finished_round;
42 build_id, 46 event_op2 build_id,
43 id_index; 47 id_index;
44 bool ordered_events; 48 bool ordered_events;
45 bool ordering_requires_timestamps; 49 bool ordering_requires_timestamps;
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index c36636fd825b..25d6c737be3e 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -112,8 +112,8 @@ unsigned long long read_size(struct event_format *event, void *ptr, int size)
112 return pevent_read_number(event->pevent, ptr, size); 112 return pevent_read_number(event->pevent, ptr, size);
113} 113}
114 114
115void event_format__print(struct event_format *event, 115void event_format__fprintf(struct event_format *event,
116 int cpu, void *data, int size) 116 int cpu, void *data, int size, FILE *fp)
117{ 117{
118 struct pevent_record record; 118 struct pevent_record record;
119 struct trace_seq s; 119 struct trace_seq s;
@@ -125,10 +125,16 @@ void event_format__print(struct event_format *event,
125 125
126 trace_seq_init(&s); 126 trace_seq_init(&s);
127 pevent_event_info(&s, event, &record); 127 pevent_event_info(&s, event, &record);
128 trace_seq_do_printf(&s); 128 trace_seq_do_fprintf(&s, fp);
129 trace_seq_destroy(&s); 129 trace_seq_destroy(&s);
130} 130}
131 131
132void event_format__print(struct event_format *event,
133 int cpu, void *data, int size)
134{
135 return event_format__fprintf(event, cpu, data, size, stdout);
136}
137
132void parse_proc_kallsyms(struct pevent *pevent, 138void parse_proc_kallsyms(struct pevent *pevent,
133 char *file, unsigned int size __maybe_unused) 139 char *file, unsigned int size __maybe_unused)
134{ 140{
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index 52aaa19e1eb1..356629a30ca9 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -23,6 +23,9 @@ trace_event__tp_format(const char *sys, const char *name);
23 23
24int bigendian(void); 24int bigendian(void);
25 25
26void event_format__fprintf(struct event_format *event,
27 int cpu, void *data, int size, FILE *fp);
28
26void event_format__print(struct event_format *event, 29void event_format__print(struct event_format *event,
27 int cpu, void *data, int size); 30 int cpu, void *data, int size);
28 31
diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-libunwind.c
index e3c40a520a25..7b09a443a280 100644
--- a/tools/perf/util/unwind-libunwind.c
+++ b/tools/perf/util/unwind-libunwind.c
@@ -266,7 +266,7 @@ static int read_unwind_spec_eh_frame(struct dso *dso, struct machine *machine,
266 u64 *fde_count) 266 u64 *fde_count)
267{ 267{
268 int ret = -EINVAL, fd; 268 int ret = -EINVAL, fd;
269 u64 offset = dso->data.frame_offset; 269 u64 offset = dso->data.eh_frame_hdr_offset;
270 270
271 if (offset == 0) { 271 if (offset == 0) {
272 fd = dso__data_fd(dso, machine); 272 fd = dso__data_fd(dso, machine);
@@ -275,7 +275,7 @@ static int read_unwind_spec_eh_frame(struct dso *dso, struct machine *machine,
275 275
276 /* Check the .eh_frame section for unwinding info */ 276 /* Check the .eh_frame section for unwinding info */
277 offset = elf_section_offset(fd, ".eh_frame_hdr"); 277 offset = elf_section_offset(fd, ".eh_frame_hdr");
278 dso->data.frame_offset = offset; 278 dso->data.eh_frame_hdr_offset = offset;
279 } 279 }
280 280
281 if (offset) 281 if (offset)
@@ -291,7 +291,7 @@ static int read_unwind_spec_debug_frame(struct dso *dso,
291 struct machine *machine, u64 *offset) 291 struct machine *machine, u64 *offset)
292{ 292{
293 int fd; 293 int fd;
294 u64 ofs = dso->data.frame_offset; 294 u64 ofs = dso->data.debug_frame_offset;
295 295
296 if (ofs == 0) { 296 if (ofs == 0) {
297 fd = dso__data_fd(dso, machine); 297 fd = dso__data_fd(dso, machine);
@@ -300,7 +300,7 @@ static int read_unwind_spec_debug_frame(struct dso *dso,
300 300
301 /* Check the .debug_frame section for unwinding info */ 301 /* Check the .debug_frame section for unwinding info */
302 ofs = elf_section_offset(fd, ".debug_frame"); 302 ofs = elf_section_offset(fd, ".debug_frame");
303 dso->data.frame_offset = ofs; 303 dso->data.debug_frame_offset = ofs;
304 } 304 }
305 305
306 *offset = ofs; 306 *offset = ofs;
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index b86744f29eef..4ee6d0d4c993 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -269,6 +269,13 @@ void dump_stack(void)
269void dump_stack(void) {} 269void dump_stack(void) {}
270#endif 270#endif
271 271
272void sighandler_dump_stack(int sig)
273{
274 psignal(sig, "perf");
275 dump_stack();
276 exit(sig);
277}
278
272void get_term_dimensions(struct winsize *ws) 279void get_term_dimensions(struct winsize *ws)
273{ 280{
274 char *s = getenv("LINES"); 281 char *s = getenv("LINES");
@@ -303,13 +310,26 @@ void set_term_quiet_input(struct termios *old)
303 tcsetattr(0, TCSANOW, &tc); 310 tcsetattr(0, TCSANOW, &tc);
304} 311}
305 312
306static void set_tracing_events_path(const char *mountpoint) 313static void set_tracing_events_path(const char *tracing, const char *mountpoint)
307{ 314{
308 snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s", 315 snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s%s",
309 mountpoint, "tracing/events"); 316 mountpoint, tracing, "events");
310} 317}
311 318
312const char *perf_debugfs_mount(const char *mountpoint) 319static const char *__perf_tracefs_mount(const char *mountpoint)
320{
321 const char *mnt;
322
323 mnt = tracefs_mount(mountpoint);
324 if (!mnt)
325 return NULL;
326
327 set_tracing_events_path("", mnt);
328
329 return mnt;
330}
331
332static const char *__perf_debugfs_mount(const char *mountpoint)
313{ 333{
314 const char *mnt; 334 const char *mnt;
315 335
@@ -317,7 +337,20 @@ const char *perf_debugfs_mount(const char *mountpoint)
317 if (!mnt) 337 if (!mnt)
318 return NULL; 338 return NULL;
319 339
320 set_tracing_events_path(mnt); 340 set_tracing_events_path("tracing/", mnt);
341
342 return mnt;
343}
344
345const char *perf_debugfs_mount(const char *mountpoint)
346{
347 const char *mnt;
348
349 mnt = __perf_tracefs_mount(mountpoint);
350 if (mnt)
351 return mnt;
352
353 mnt = __perf_debugfs_mount(mountpoint);
321 354
322 return mnt; 355 return mnt;
323} 356}
@@ -325,12 +358,19 @@ const char *perf_debugfs_mount(const char *mountpoint)
325void perf_debugfs_set_path(const char *mntpt) 358void perf_debugfs_set_path(const char *mntpt)
326{ 359{
327 snprintf(debugfs_mountpoint, strlen(debugfs_mountpoint), "%s", mntpt); 360 snprintf(debugfs_mountpoint, strlen(debugfs_mountpoint), "%s", mntpt);
328 set_tracing_events_path(mntpt); 361 set_tracing_events_path("tracing/", mntpt);
362}
363
364static const char *find_tracefs(void)
365{
366 const char *path = __perf_tracefs_mount(NULL);
367
368 return path;
329} 369}
330 370
331static const char *find_debugfs(void) 371static const char *find_debugfs(void)
332{ 372{
333 const char *path = perf_debugfs_mount(NULL); 373 const char *path = __perf_debugfs_mount(NULL);
334 374
335 if (!path) 375 if (!path)
336 fprintf(stderr, "Your kernel does not support the debugfs filesystem"); 376 fprintf(stderr, "Your kernel does not support the debugfs filesystem");
@@ -344,6 +384,7 @@ static const char *find_debugfs(void)
344 */ 384 */
345const char *find_tracing_dir(void) 385const char *find_tracing_dir(void)
346{ 386{
387 const char *tracing_dir = "";
347 static char *tracing; 388 static char *tracing;
348 static int tracing_found; 389 static int tracing_found;
349 const char *debugfs; 390 const char *debugfs;
@@ -351,11 +392,15 @@ const char *find_tracing_dir(void)
351 if (tracing_found) 392 if (tracing_found)
352 return tracing; 393 return tracing;
353 394
354 debugfs = find_debugfs(); 395 debugfs = find_tracefs();
355 if (!debugfs) 396 if (!debugfs) {
356 return NULL; 397 tracing_dir = "/tracing";
398 debugfs = find_debugfs();
399 if (!debugfs)
400 return NULL;
401 }
357 402
358 if (asprintf(&tracing, "%s/tracing", debugfs) < 0) 403 if (asprintf(&tracing, "%s%s", debugfs, tracing_dir) < 0)
359 return NULL; 404 return NULL;
360 405
361 tracing_found = 1; 406 tracing_found = 1;
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 027a5153495c..1ff23e04ad27 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -75,6 +75,7 @@
75#include <linux/types.h> 75#include <linux/types.h>
76#include <sys/ttydefaults.h> 76#include <sys/ttydefaults.h>
77#include <api/fs/debugfs.h> 77#include <api/fs/debugfs.h>
78#include <api/fs/tracefs.h>
78#include <termios.h> 79#include <termios.h>
79#include <linux/bitops.h> 80#include <linux/bitops.h>
80#include <termios.h> 81#include <termios.h>
@@ -276,6 +277,7 @@ char *ltrim(char *s);
276char *rtrim(char *s); 277char *rtrim(char *s);
277 278
278void dump_stack(void); 279void dump_stack(void);
280void sighandler_dump_stack(int sig);
279 281
280extern unsigned int page_size; 282extern unsigned int page_size;
281extern int cacheline_size; 283extern int cacheline_size;
@@ -327,4 +329,8 @@ bool find_process(const char *name);
327int gzip_decompress_to_file(const char *input, int output_fd); 329int gzip_decompress_to_file(const char *input, int output_fd);
328#endif 330#endif
329 331
332#ifdef HAVE_LZMA_SUPPORT
333int lzma_decompress_to_file(const char *input, int output_fd);
334#endif
335
330#endif /* GIT_COMPAT_UTIL_H */ 336#endif /* GIT_COMPAT_UTIL_H */