aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf')
-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.txt12
-rw-r--r--tools/perf/Documentation/perf-list.txt7
-rw-r--r--tools/perf/Documentation/perf-probe.txt16
-rw-r--r--tools/perf/Documentation/perf-record.txt30
-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/bench/mem-memcpy-x86-64-asm-def.h6
-rw-r--r--tools/perf/bench/mem-memcpy-x86-64-asm.S2
-rw-r--r--tools/perf/bench/mem-memcpy.c128
-rw-r--r--tools/perf/bench/mem-memset-x86-64-asm-def.h6
-rw-r--r--tools/perf/bench/mem-memset-x86-64-asm.S2
-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.c123
-rw-r--r--tools/perf/builtin-diff.c6
-rw-r--r--tools/perf/builtin-evlist.c2
-rw-r--r--tools/perf/builtin-help.c17
-rw-r--r--tools/perf/builtin-inject.c16
-rw-r--r--tools/perf/builtin-kmem.c538
-rw-r--r--tools/perf/builtin-kvm.c15
-rw-r--r--tools/perf/builtin-list.c28
-rw-r--r--tools/perf/builtin-lock.c7
-rw-r--r--tools/perf/builtin-mem.c7
-rw-r--r--tools/perf/builtin-probe.c19
-rw-r--r--tools/perf/builtin-record.c108
-rw-r--r--tools/perf/builtin-report.c16
-rw-r--r--tools/perf/builtin-sched.c101
-rw-r--r--tools/perf/builtin-script.c34
-rw-r--r--tools/perf/builtin-stat.c98
-rw-r--r--tools/perf/builtin-timechart.c12
-rw-r--r--tools/perf/builtin-top.c10
-rw-r--r--tools/perf/builtin-trace.c281
-rw-r--r--tools/perf/builtin.h1
-rw-r--r--tools/perf/command-list.txt1
-rw-r--r--tools/perf/config/Makefile293
-rw-r--r--tools/perf/config/Makefile.arch29
-rw-r--r--tools/perf/config/feature-checks/.gitignore2
-rw-r--r--tools/perf/config/feature-checks/Makefile155
-rw-r--r--tools/perf/config/feature-checks/test-all.c131
-rw-r--r--tools/perf/config/feature-checks/test-backtrace.c13
-rw-r--r--tools/perf/config/feature-checks/test-bionic.c6
-rw-r--r--tools/perf/config/feature-checks/test-compile.c4
-rw-r--r--tools/perf/config/feature-checks/test-cplus-demangle.c14
-rw-r--r--tools/perf/config/feature-checks/test-dwarf.c10
-rw-r--r--tools/perf/config/feature-checks/test-fortify-source.c6
-rw-r--r--tools/perf/config/feature-checks/test-glibc.c8
-rw-r--r--tools/perf/config/feature-checks/test-gtk2-infobar.c11
-rw-r--r--tools/perf/config/feature-checks/test-gtk2.c10
-rw-r--r--tools/perf/config/feature-checks/test-hello.c6
-rw-r--r--tools/perf/config/feature-checks/test-libaudit.c10
-rw-r--r--tools/perf/config/feature-checks/test-libbfd.c15
-rw-r--r--tools/perf/config/feature-checks/test-libdw-dwarf-unwind.c13
-rw-r--r--tools/perf/config/feature-checks/test-libelf-getphdrnum.c8
-rw-r--r--tools/perf/config/feature-checks/test-libelf-mmap.c8
-rw-r--r--tools/perf/config/feature-checks/test-libelf.c8
-rw-r--r--tools/perf/config/feature-checks/test-libnuma.c9
-rw-r--r--tools/perf/config/feature-checks/test-libperl.c9
-rw-r--r--tools/perf/config/feature-checks/test-libpython-version.c10
-rw-r--r--tools/perf/config/feature-checks/test-libpython.c8
-rw-r--r--tools/perf/config/feature-checks/test-libslang.c6
-rw-r--r--tools/perf/config/feature-checks/test-libunwind-debug-frame.c16
-rw-r--r--tools/perf/config/feature-checks/test-libunwind.c27
-rw-r--r--tools/perf/config/feature-checks/test-pthread-attr-setaffinity-np.c15
-rw-r--r--tools/perf/config/feature-checks/test-stackprotector-all.c6
-rw-r--r--tools/perf/config/feature-checks/test-sync-compare-and-swap.c14
-rw-r--r--tools/perf/config/feature-checks/test-timerfd.c18
-rw-r--r--tools/perf/config/feature-checks/test-zlib.c9
-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.h5
-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/attr/base-record2
-rw-r--r--tools/perf/tests/attr/base-stat2
-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.c53
-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.c34
-rw-r--r--tools/perf/util/build-id.c209
-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.c857
-rw-r--r--tools/perf/util/data-convert-bt.h8
-rw-r--r--tools/perf/util/db-export.c4
-rw-r--r--tools/perf/util/db-export.h3
-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.c29
-rw-r--r--tools/perf/util/dwarf-aux.h3
-rw-r--r--tools/perf/util/event.c190
-rw-r--r--tools/perf/util/event.h1
-rw-r--r--tools/perf/util/evlist.c49
-rw-r--r--tools/perf/util/evlist.h14
-rw-r--r--tools/perf/util/evsel.c354
-rw-r--r--tools/perf/util/evsel.h11
-rw-r--r--tools/perf/util/header.c35
-rw-r--r--tools/perf/util/hist.c11
-rw-r--r--tools/perf/util/hist.h11
-rw-r--r--tools/perf/util/include/asm/alternative-asm.h1
-rw-r--r--tools/perf/util/kvm-stat.h1
-rw-r--r--tools/perf/util/lzma.c95
-rw-r--r--tools/perf/util/machine.c332
-rw-r--r--tools/perf/util/machine.h2
-rw-r--r--tools/perf/util/map.c20
-rw-r--r--tools/perf/util/map.h6
-rw-r--r--tools/perf/util/ordered-events.c65
-rw-r--r--tools/perf/util/ordered-events.h19
-rw-r--r--tools/perf/util/parse-events.c242
-rw-r--r--tools/perf/util/parse-events.h13
-rw-r--r--tools/perf/util/parse-events.l2
-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.c425
-rw-r--r--tools/perf/util/probe-event.h6
-rw-r--r--tools/perf/util/probe-finder.c100
-rw-r--r--tools/perf/util/probe-finder.h4
-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.c10
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c21
-rw-r--r--tools/perf/util/session.c320
-rw-r--r--tools/perf/util/session.h18
-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.c87
-rw-r--r--tools/perf/util/symbol-minimal.c7
-rw-r--r--tools/perf/util/symbol.c65
-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-scripting.c1
-rw-r--r--tools/perf/util/trace-event.h6
-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
197 files changed, 5566 insertions, 2785 deletions
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..23219c65c16f 100644
--- a/tools/perf/Documentation/perf-kmem.txt
+++ b/tools/perf/Documentation/perf-kmem.txt
@@ -3,7 +3,7 @@ perf-kmem(1)
3 3
4NAME 4NAME
5---- 5----
6perf-kmem - Tool to trace/measure kernel memory(slab) properties 6perf-kmem - Tool to trace/measure kernel memory properties
7 7
8SYNOPSIS 8SYNOPSIS
9-------- 9--------
@@ -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
@@ -42,6 +46,12 @@ OPTIONS
42--raw-ip:: 46--raw-ip::
43 Print raw ip instead of symbol 47 Print raw ip instead of symbol
44 48
49--slab::
50 Analyze SLAB allocator events.
51
52--page::
53 Analyze page allocator events
54
45SEE ALSO 55SEE ALSO
46-------- 56--------
47linkperf:perf-record[1] 57linkperf:perf-record[1]
diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt
index 3e2aec94f806..bada8933fdd4 100644
--- a/tools/perf/Documentation/perf-list.txt
+++ b/tools/perf/Documentation/perf-list.txt
@@ -26,6 +26,7 @@ counted. The following modifiers exist:
26 u - user-space counting 26 u - user-space counting
27 k - kernel counting 27 k - kernel counting
28 h - hypervisor counting 28 h - hypervisor counting
29 I - non idle counting
29 G - guest counting (in KVM guests) 30 G - guest counting (in KVM guests)
30 H - host counting (not in KVM guests) 31 H - host counting (not in KVM guests)
31 p - precise level 32 p - precise level
@@ -127,6 +128,12 @@ To limit the list use:
127One or more types can be used at the same time, listing the events for the 128One or more types can be used at the same time, listing the events for the
128types specified. 129types specified.
129 130
131Support raw format:
132
133. '--raw-dump', shows the raw-dump of all the events.
134. '--raw-dump [hw|sw|cache|tracepoint|pmu|event_glob]', shows the raw-dump of
135 a certain kind of events.
136
130SEE ALSO 137SEE ALSO
131-------- 138--------
132linkperf:perf-stat[1], linkperf:perf-top[1], 139linkperf: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..4847a793de65 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,16 @@ 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
253-k::
254--clockid::
255Sets the clock id to use for the various time fields in the perf_event_type
256records. See clock_gettime(). In particular CLOCK_MONOTONIC and
257CLOCK_MONOTONIC_RAW are supported, some events might also allow
258CLOCK_BOOTTIME, CLOCK_REALTIME and CLOCK_TAI.
259
238SEE ALSO 260SEE ALSO
239-------- 261--------
240linkperf:perf-stat[1], linkperf:perf-list[1] 262linkperf: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..c43a20517591 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 LIBBABELTRACE if you DO 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/bench/mem-memcpy-x86-64-asm-def.h b/tools/perf/bench/mem-memcpy-x86-64-asm-def.h
index d66ab799b35f..8c0c1a2770c8 100644
--- a/tools/perf/bench/mem-memcpy-x86-64-asm-def.h
+++ b/tools/perf/bench/mem-memcpy-x86-64-asm-def.h
@@ -1,12 +1,12 @@
1 1
2MEMCPY_FN(__memcpy, 2MEMCPY_FN(memcpy_orig,
3 "x86-64-unrolled", 3 "x86-64-unrolled",
4 "unrolled memcpy() in arch/x86/lib/memcpy_64.S") 4 "unrolled memcpy() in arch/x86/lib/memcpy_64.S")
5 5
6MEMCPY_FN(memcpy_c, 6MEMCPY_FN(__memcpy,
7 "x86-64-movsq", 7 "x86-64-movsq",
8 "movsq-based memcpy() in arch/x86/lib/memcpy_64.S") 8 "movsq-based memcpy() in arch/x86/lib/memcpy_64.S")
9 9
10MEMCPY_FN(memcpy_c_e, 10MEMCPY_FN(memcpy_erms,
11 "x86-64-movsb", 11 "x86-64-movsb",
12 "movsb-based memcpy() in arch/x86/lib/memcpy_64.S") 12 "movsb-based memcpy() in arch/x86/lib/memcpy_64.S")
diff --git a/tools/perf/bench/mem-memcpy-x86-64-asm.S b/tools/perf/bench/mem-memcpy-x86-64-asm.S
index fcd9cf00600a..e4c2c30143b9 100644
--- a/tools/perf/bench/mem-memcpy-x86-64-asm.S
+++ b/tools/perf/bench/mem-memcpy-x86-64-asm.S
@@ -1,8 +1,6 @@
1#define memcpy MEMCPY /* don't hide glibc's memcpy() */ 1#define memcpy MEMCPY /* don't hide glibc's memcpy() */
2#define altinstr_replacement text 2#define altinstr_replacement text
3#define globl p2align 4; .globl 3#define globl p2align 4; .globl
4#define Lmemcpy_c globl memcpy_c; memcpy_c
5#define Lmemcpy_c_e globl memcpy_c_e; memcpy_c_e
6#include "../../../arch/x86/lib/memcpy_64.S" 4#include "../../../arch/x86/lib/memcpy_64.S"
7/* 5/*
8 * We need to provide note.GNU-stack section, saying that we want 6 * We need to provide note.GNU-stack section, saying that we want
diff --git a/tools/perf/bench/mem-memcpy.c b/tools/perf/bench/mem-memcpy.c
index db1d3a29d97f..d3dfb7936dcd 100644
--- a/tools/perf/bench/mem-memcpy.c
+++ b/tools/perf/bench/mem-memcpy.c
@@ -36,7 +36,7 @@ static const struct option options[] = {
36 "Specify length of memory to copy. " 36 "Specify length of memory to copy. "
37 "Available units: B, KB, MB, GB and TB (upper and lower)"), 37 "Available units: B, KB, MB, GB and TB (upper and lower)"),
38 OPT_STRING('r', "routine", &routine, "default", 38 OPT_STRING('r', "routine", &routine, "default",
39 "Specify routine to copy"), 39 "Specify routine to copy, \"all\" runs all available routines"),
40 OPT_INTEGER('i', "iterations", &iterations, 40 OPT_INTEGER('i', "iterations", &iterations,
41 "repeat memcpy() invocation this number of times"), 41 "repeat memcpy() invocation this number of times"),
42 OPT_BOOLEAN('c', "cycle", &use_cycle, 42 OPT_BOOLEAN('c', "cycle", &use_cycle,
@@ -135,55 +135,16 @@ struct bench_mem_info {
135 const char *const *usage; 135 const char *const *usage;
136}; 136};
137 137
138static int bench_mem_common(int argc, const char **argv, 138static void __bench_mem_routine(struct bench_mem_info *info, int r_idx, size_t len, double totallen)
139 const char *prefix __maybe_unused,
140 struct bench_mem_info *info)
141{ 139{
142 int i; 140 const struct routine *r = &info->routines[r_idx];
143 size_t len;
144 double totallen;
145 double result_bps[2]; 141 double result_bps[2];
146 u64 result_cycle[2]; 142 u64 result_cycle[2];
147 143
148 argc = parse_options(argc, argv, options,
149 info->usage, 0);
150
151 if (no_prefault && only_prefault) {
152 fprintf(stderr, "Invalid options: -o and -n are mutually exclusive\n");
153 return 1;
154 }
155
156 if (use_cycle)
157 init_cycle();
158
159 len = (size_t)perf_atoll((char *)length_str);
160 totallen = (double)len * iterations;
161
162 result_cycle[0] = result_cycle[1] = 0ULL; 144 result_cycle[0] = result_cycle[1] = 0ULL;
163 result_bps[0] = result_bps[1] = 0.0; 145 result_bps[0] = result_bps[1] = 0.0;
164 146
165 if ((s64)len <= 0) { 147 printf("Routine %s (%s)\n", r->name, r->desc);
166 fprintf(stderr, "Invalid length:%s\n", length_str);
167 return 1;
168 }
169
170 /* same to without specifying either of prefault and no-prefault */
171 if (only_prefault && no_prefault)
172 only_prefault = no_prefault = false;
173
174 for (i = 0; info->routines[i].name; i++) {
175 if (!strcmp(info->routines[i].name, routine))
176 break;
177 }
178 if (!info->routines[i].name) {
179 printf("Unknown routine:%s\n", routine);
180 printf("Available routines...\n");
181 for (i = 0; info->routines[i].name; i++) {
182 printf("\t%s ... %s\n",
183 info->routines[i].name, info->routines[i].desc);
184 }
185 return 1;
186 }
187 148
188 if (bench_format == BENCH_FORMAT_DEFAULT) 149 if (bench_format == BENCH_FORMAT_DEFAULT)
189 printf("# Copying %s Bytes ...\n\n", length_str); 150 printf("# Copying %s Bytes ...\n\n", length_str);
@@ -191,28 +152,17 @@ static int bench_mem_common(int argc, const char **argv,
191 if (!only_prefault && !no_prefault) { 152 if (!only_prefault && !no_prefault) {
192 /* show both of results */ 153 /* show both of results */
193 if (use_cycle) { 154 if (use_cycle) {
194 result_cycle[0] = 155 result_cycle[0] = info->do_cycle(r, len, false);
195 info->do_cycle(&info->routines[i], len, false); 156 result_cycle[1] = info->do_cycle(r, len, true);
196 result_cycle[1] =
197 info->do_cycle(&info->routines[i], len, true);
198 } else { 157 } else {
199 result_bps[0] = 158 result_bps[0] = info->do_gettimeofday(r, len, false);
200 info->do_gettimeofday(&info->routines[i], 159 result_bps[1] = info->do_gettimeofday(r, len, true);
201 len, false);
202 result_bps[1] =
203 info->do_gettimeofday(&info->routines[i],
204 len, true);
205 } 160 }
206 } else { 161 } else {
207 if (use_cycle) { 162 if (use_cycle)
208 result_cycle[pf] = 163 result_cycle[pf] = info->do_cycle(r, len, only_prefault);
209 info->do_cycle(&info->routines[i], 164 else
210 len, only_prefault); 165 result_bps[pf] = info->do_gettimeofday(r, len, only_prefault);
211 } else {
212 result_bps[pf] =
213 info->do_gettimeofday(&info->routines[i],
214 len, only_prefault);
215 }
216 } 166 }
217 167
218 switch (bench_format) { 168 switch (bench_format) {
@@ -265,6 +215,60 @@ static int bench_mem_common(int argc, const char **argv,
265 die("unknown format: %d\n", bench_format); 215 die("unknown format: %d\n", bench_format);
266 break; 216 break;
267 } 217 }
218}
219
220static int bench_mem_common(int argc, const char **argv,
221 const char *prefix __maybe_unused,
222 struct bench_mem_info *info)
223{
224 int i;
225 size_t len;
226 double totallen;
227
228 argc = parse_options(argc, argv, options,
229 info->usage, 0);
230
231 if (no_prefault && only_prefault) {
232 fprintf(stderr, "Invalid options: -o and -n are mutually exclusive\n");
233 return 1;
234 }
235
236 if (use_cycle)
237 init_cycle();
238
239 len = (size_t)perf_atoll((char *)length_str);
240 totallen = (double)len * iterations;
241
242 if ((s64)len <= 0) {
243 fprintf(stderr, "Invalid length:%s\n", length_str);
244 return 1;
245 }
246
247 /* same to without specifying either of prefault and no-prefault */
248 if (only_prefault && no_prefault)
249 only_prefault = no_prefault = false;
250
251 if (!strncmp(routine, "all", 3)) {
252 for (i = 0; info->routines[i].name; i++)
253 __bench_mem_routine(info, i, len, totallen);
254 return 0;
255 }
256
257 for (i = 0; info->routines[i].name; i++) {
258 if (!strcmp(info->routines[i].name, routine))
259 break;
260 }
261 if (!info->routines[i].name) {
262 printf("Unknown routine:%s\n", routine);
263 printf("Available routines...\n");
264 for (i = 0; info->routines[i].name; i++) {
265 printf("\t%s ... %s\n",
266 info->routines[i].name, info->routines[i].desc);
267 }
268 return 1;
269 }
270
271 __bench_mem_routine(info, i, len, totallen);
268 272
269 return 0; 273 return 0;
270} 274}
diff --git a/tools/perf/bench/mem-memset-x86-64-asm-def.h b/tools/perf/bench/mem-memset-x86-64-asm-def.h
index a71dff97c1f5..f02d028771d9 100644
--- a/tools/perf/bench/mem-memset-x86-64-asm-def.h
+++ b/tools/perf/bench/mem-memset-x86-64-asm-def.h
@@ -1,12 +1,12 @@
1 1
2MEMSET_FN(__memset, 2MEMSET_FN(memset_orig,
3 "x86-64-unrolled", 3 "x86-64-unrolled",
4 "unrolled memset() in arch/x86/lib/memset_64.S") 4 "unrolled memset() in arch/x86/lib/memset_64.S")
5 5
6MEMSET_FN(memset_c, 6MEMSET_FN(__memset,
7 "x86-64-stosq", 7 "x86-64-stosq",
8 "movsq-based memset() in arch/x86/lib/memset_64.S") 8 "movsq-based memset() in arch/x86/lib/memset_64.S")
9 9
10MEMSET_FN(memset_c_e, 10MEMSET_FN(memset_erms,
11 "x86-64-stosb", 11 "x86-64-stosb",
12 "movsb-based memset() in arch/x86/lib/memset_64.S") 12 "movsb-based memset() in arch/x86/lib/memset_64.S")
diff --git a/tools/perf/bench/mem-memset-x86-64-asm.S b/tools/perf/bench/mem-memset-x86-64-asm.S
index 9e5af89ed13a..de278784c866 100644
--- a/tools/perf/bench/mem-memset-x86-64-asm.S
+++ b/tools/perf/bench/mem-memset-x86-64-asm.S
@@ -1,8 +1,6 @@
1#define memset MEMSET /* don't hide glibc's memset() */ 1#define memset MEMSET /* don't hide glibc's memset() */
2#define altinstr_replacement text 2#define altinstr_replacement text
3#define globl p2align 4; .globl 3#define globl p2align 4; .globl
4#define Lmemset_c globl memset_c; memset_c
5#define Lmemset_c_e globl memset_c_e; memset_c_e
6#include "../../../arch/x86/lib/memset_64.S" 4#include "../../../arch/x86/lib/memset_64.S"
7 5
8/* 6/*
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..d6525bc54d13
--- /dev/null
+++ b/tools/perf/builtin-data.c
@@ -0,0 +1,123 @@
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 bool force = false;
57 const struct option options[] = {
58 OPT_INCR('v', "verbose", &verbose, "be more verbose"),
59 OPT_STRING('i', "input", &input_name, "file", "input file name"),
60#ifdef HAVE_LIBBABELTRACE_SUPPORT
61 OPT_STRING(0, "to-ctf", &to_ctf, NULL, "Convert to CTF format"),
62#endif
63 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
64 OPT_END()
65 };
66
67#ifndef HAVE_LIBBABELTRACE_SUPPORT
68 pr_err("No conversion support compiled in.\n");
69 return -1;
70#endif
71
72 argc = parse_options(argc, argv, options,
73 data_convert_usage, 0);
74 if (argc) {
75 usage_with_options(data_convert_usage, options);
76 return -1;
77 }
78
79 if (to_ctf) {
80#ifdef HAVE_LIBBABELTRACE_SUPPORT
81 return bt_convert__perf2ctf(input_name, to_ctf, force);
82#else
83 pr_err("The libbabeltrace support is not compiled in.\n");
84 return -1;
85#endif
86 }
87
88 return 0;
89}
90
91static struct data_cmd data_cmds[] = {
92 { "convert", "converts data file between formats", cmd_data_convert },
93 { .name = NULL, },
94};
95
96int cmd_data(int argc, const char **argv, const char *prefix)
97{
98 struct data_cmd *cmd;
99 const char *cmdstr;
100
101 /* No command specified. */
102 if (argc < 2)
103 goto usage;
104
105 argc = parse_options_subcommand(argc, argv, data_options, data_subcommands, data_usage,
106 PARSE_OPT_STOP_AT_NON_OPTION);
107 if (argc < 1)
108 goto usage;
109
110 cmdstr = argv[0];
111
112 for_each_cmd(cmd) {
113 if (strcmp(cmd->name, cmdstr))
114 continue;
115
116 return cmd->fn(argc, argv, prefix);
117 }
118
119 pr_err("Unknown command: %s\n", cmdstr);
120usage:
121 print_usage();
122 return -1;
123}
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-evlist.c b/tools/perf/builtin-evlist.c
index 0f93f859b782..695ec5a50cf2 100644
--- a/tools/perf/builtin-evlist.c
+++ b/tools/perf/builtin-evlist.c
@@ -24,6 +24,7 @@ static int __cmd_evlist(const char *file_name, struct perf_attr_details *details
24 struct perf_data_file file = { 24 struct perf_data_file file = {
25 .path = file_name, 25 .path = file_name,
26 .mode = PERF_DATA_MODE_READ, 26 .mode = PERF_DATA_MODE_READ,
27 .force = details->force,
27 }; 28 };
28 29
29 session = perf_session__new(&file, 0, NULL); 30 session = perf_session__new(&file, 0, NULL);
@@ -47,6 +48,7 @@ int cmd_evlist(int argc, const char **argv, const char *prefix __maybe_unused)
47 "Show all event attr details"), 48 "Show all event attr details"),
48 OPT_BOOLEAN('g', "group", &details.event_group, 49 OPT_BOOLEAN('g', "group", &details.event_group,
49 "Show event group information"), 50 "Show event group information"),
51 OPT_BOOLEAN('f', "force", &details.force, "don't complain, do it"),
50 OPT_END() 52 OPT_END()
51 }; 53 };
52 const char * const evlist_usage[] = { 54 const char * const evlist_usage[] = {
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..40a33d7334cc 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 },
@@ -438,6 +443,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
438 "be more verbose (show build ids, etc)"), 443 "be more verbose (show build ids, etc)"),
439 OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, "file", 444 OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, "file",
440 "kallsyms pathname"), 445 "kallsyms pathname"),
446 OPT_BOOLEAN('f', "force", &file.force, "don't complain, do it"),
441 OPT_END() 447 OPT_END()
442 }; 448 };
443 const char * const inject_usage[] = { 449 const char * const inject_usage[] = {
@@ -458,6 +464,8 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
458 return -1; 464 return -1;
459 } 465 }
460 466
467 inject.tool.ordered_events = inject.sched_stat;
468
461 file.path = inject.input_name; 469 file.path = inject.input_name;
462 inject.session = perf_session__new(&file, true, &inject.tool); 470 inject.session = perf_session__new(&file, true, &inject.tool);
463 if (inject.session == NULL) 471 if (inject.session == NULL)
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index f295141025bc..63ea01349b6e 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -20,6 +20,12 @@
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>
24
25static int kmem_slab;
26static int kmem_page;
27
28static long kmem_page_size;
23 29
24struct alloc_stat; 30struct alloc_stat;
25typedef int (*sort_fn_t)(struct alloc_stat *, struct alloc_stat *); 31typedef int (*sort_fn_t)(struct alloc_stat *, struct alloc_stat *);
@@ -225,6 +231,244 @@ static int perf_evsel__process_free_event(struct perf_evsel *evsel,
225 return 0; 231 return 0;
226} 232}
227 233
234static u64 total_page_alloc_bytes;
235static u64 total_page_free_bytes;
236static u64 total_page_nomatch_bytes;
237static u64 total_page_fail_bytes;
238static unsigned long nr_page_allocs;
239static unsigned long nr_page_frees;
240static unsigned long nr_page_fails;
241static unsigned long nr_page_nomatch;
242
243static bool use_pfn;
244
245#define MAX_MIGRATE_TYPES 6
246#define MAX_PAGE_ORDER 11
247
248static int order_stats[MAX_PAGE_ORDER][MAX_MIGRATE_TYPES];
249
250struct page_stat {
251 struct rb_node node;
252 u64 page;
253 int order;
254 unsigned gfp_flags;
255 unsigned migrate_type;
256 u64 alloc_bytes;
257 u64 free_bytes;
258 int nr_alloc;
259 int nr_free;
260};
261
262static struct rb_root page_tree;
263static struct rb_root page_alloc_tree;
264static struct rb_root page_alloc_sorted;
265
266static struct page_stat *search_page(unsigned long page, bool create)
267{
268 struct rb_node **node = &page_tree.rb_node;
269 struct rb_node *parent = NULL;
270 struct page_stat *data;
271
272 while (*node) {
273 s64 cmp;
274
275 parent = *node;
276 data = rb_entry(*node, struct page_stat, node);
277
278 cmp = data->page - page;
279 if (cmp < 0)
280 node = &parent->rb_left;
281 else if (cmp > 0)
282 node = &parent->rb_right;
283 else
284 return data;
285 }
286
287 if (!create)
288 return NULL;
289
290 data = zalloc(sizeof(*data));
291 if (data != NULL) {
292 data->page = page;
293
294 rb_link_node(&data->node, parent, node);
295 rb_insert_color(&data->node, &page_tree);
296 }
297
298 return data;
299}
300
301static int page_stat_cmp(struct page_stat *a, struct page_stat *b)
302{
303 if (a->page > b->page)
304 return -1;
305 if (a->page < b->page)
306 return 1;
307 if (a->order > b->order)
308 return -1;
309 if (a->order < b->order)
310 return 1;
311 if (a->migrate_type > b->migrate_type)
312 return -1;
313 if (a->migrate_type < b->migrate_type)
314 return 1;
315 if (a->gfp_flags > b->gfp_flags)
316 return -1;
317 if (a->gfp_flags < b->gfp_flags)
318 return 1;
319 return 0;
320}
321
322static struct page_stat *search_page_alloc_stat(struct page_stat *stat, bool create)
323{
324 struct rb_node **node = &page_alloc_tree.rb_node;
325 struct rb_node *parent = NULL;
326 struct page_stat *data;
327
328 while (*node) {
329 s64 cmp;
330
331 parent = *node;
332 data = rb_entry(*node, struct page_stat, node);
333
334 cmp = page_stat_cmp(data, stat);
335 if (cmp < 0)
336 node = &parent->rb_left;
337 else if (cmp > 0)
338 node = &parent->rb_right;
339 else
340 return data;
341 }
342
343 if (!create)
344 return NULL;
345
346 data = zalloc(sizeof(*data));
347 if (data != NULL) {
348 data->page = stat->page;
349 data->order = stat->order;
350 data->gfp_flags = stat->gfp_flags;
351 data->migrate_type = stat->migrate_type;
352
353 rb_link_node(&data->node, parent, node);
354 rb_insert_color(&data->node, &page_alloc_tree);
355 }
356
357 return data;
358}
359
360static bool valid_page(u64 pfn_or_page)
361{
362 if (use_pfn && pfn_or_page == -1UL)
363 return false;
364 if (!use_pfn && pfn_or_page == 0)
365 return false;
366 return true;
367}
368
369static int perf_evsel__process_page_alloc_event(struct perf_evsel *evsel,
370 struct perf_sample *sample)
371{
372 u64 page;
373 unsigned int order = perf_evsel__intval(evsel, sample, "order");
374 unsigned int gfp_flags = perf_evsel__intval(evsel, sample, "gfp_flags");
375 unsigned int migrate_type = perf_evsel__intval(evsel, sample,
376 "migratetype");
377 u64 bytes = kmem_page_size << order;
378 struct page_stat *stat;
379 struct page_stat this = {
380 .order = order,
381 .gfp_flags = gfp_flags,
382 .migrate_type = migrate_type,
383 };
384
385 if (use_pfn)
386 page = perf_evsel__intval(evsel, sample, "pfn");
387 else
388 page = perf_evsel__intval(evsel, sample, "page");
389
390 nr_page_allocs++;
391 total_page_alloc_bytes += bytes;
392
393 if (!valid_page(page)) {
394 nr_page_fails++;
395 total_page_fail_bytes += bytes;
396
397 return 0;
398 }
399
400 /*
401 * This is to find the current page (with correct gfp flags and
402 * migrate type) at free event.
403 */
404 stat = search_page(page, true);
405 if (stat == NULL)
406 return -ENOMEM;
407
408 stat->order = order;
409 stat->gfp_flags = gfp_flags;
410 stat->migrate_type = migrate_type;
411
412 this.page = page;
413 stat = search_page_alloc_stat(&this, true);
414 if (stat == NULL)
415 return -ENOMEM;
416
417 stat->nr_alloc++;
418 stat->alloc_bytes += bytes;
419
420 order_stats[order][migrate_type]++;
421
422 return 0;
423}
424
425static int perf_evsel__process_page_free_event(struct perf_evsel *evsel,
426 struct perf_sample *sample)
427{
428 u64 page;
429 unsigned int order = perf_evsel__intval(evsel, sample, "order");
430 u64 bytes = kmem_page_size << order;
431 struct page_stat *stat;
432 struct page_stat this = {
433 .order = order,
434 };
435
436 if (use_pfn)
437 page = perf_evsel__intval(evsel, sample, "pfn");
438 else
439 page = perf_evsel__intval(evsel, sample, "page");
440
441 nr_page_frees++;
442 total_page_free_bytes += bytes;
443
444 stat = search_page(page, false);
445 if (stat == NULL) {
446 pr_debug2("missing free at page %"PRIx64" (order: %d)\n",
447 page, order);
448
449 nr_page_nomatch++;
450 total_page_nomatch_bytes += bytes;
451
452 return 0;
453 }
454
455 this.page = page;
456 this.gfp_flags = stat->gfp_flags;
457 this.migrate_type = stat->migrate_type;
458
459 rb_erase(&stat->node, &page_tree);
460 free(stat);
461
462 stat = search_page_alloc_stat(&this, false);
463 if (stat == NULL)
464 return -ENOENT;
465
466 stat->nr_free++;
467 stat->free_bytes += bytes;
468
469 return 0;
470}
471
228typedef int (*tracepoint_handler)(struct perf_evsel *evsel, 472typedef int (*tracepoint_handler)(struct perf_evsel *evsel,
229 struct perf_sample *sample); 473 struct perf_sample *sample);
230 474
@@ -269,16 +513,17 @@ static double fragmentation(unsigned long n_req, unsigned long n_alloc)
269 return 100.0 - (100.0 * n_req / n_alloc); 513 return 100.0 - (100.0 * n_req / n_alloc);
270} 514}
271 515
272static void __print_result(struct rb_root *root, struct perf_session *session, 516static void __print_slab_result(struct rb_root *root,
273 int n_lines, int is_caller) 517 struct perf_session *session,
518 int n_lines, int is_caller)
274{ 519{
275 struct rb_node *next; 520 struct rb_node *next;
276 struct machine *machine = &session->machines.host; 521 struct machine *machine = &session->machines.host;
277 522
278 printf("%.102s\n", graph_dotted_line); 523 printf("%.105s\n", graph_dotted_line);
279 printf(" %-34s |", is_caller ? "Callsite": "Alloc Ptr"); 524 printf(" %-34s |", is_caller ? "Callsite": "Alloc Ptr");
280 printf(" Total_alloc/Per | Total_req/Per | Hit | Ping-pong | Frag\n"); 525 printf(" Total_alloc/Per | Total_req/Per | Hit | Ping-pong | Frag\n");
281 printf("%.102s\n", graph_dotted_line); 526 printf("%.105s\n", graph_dotted_line);
282 527
283 next = rb_first(root); 528 next = rb_first(root);
284 529
@@ -304,7 +549,7 @@ static void __print_result(struct rb_root *root, struct perf_session *session,
304 snprintf(buf, sizeof(buf), "%#" PRIx64 "", addr); 549 snprintf(buf, sizeof(buf), "%#" PRIx64 "", addr);
305 printf(" %-34s |", buf); 550 printf(" %-34s |", buf);
306 551
307 printf(" %9llu/%-5lu | %9llu/%-5lu | %8lu | %8lu | %6.3f%%\n", 552 printf(" %9llu/%-5lu | %9llu/%-5lu | %8lu | %9lu | %6.3f%%\n",
308 (unsigned long long)data->bytes_alloc, 553 (unsigned long long)data->bytes_alloc,
309 (unsigned long)data->bytes_alloc / data->hit, 554 (unsigned long)data->bytes_alloc / data->hit,
310 (unsigned long long)data->bytes_req, 555 (unsigned long long)data->bytes_req,
@@ -317,30 +562,137 @@ static void __print_result(struct rb_root *root, struct perf_session *session,
317 } 562 }
318 563
319 if (n_lines == -1) 564 if (n_lines == -1)
320 printf(" ... | ... | ... | ... | ... | ... \n"); 565 printf(" ... | ... | ... | ... | ... | ... \n");
321 566
322 printf("%.102s\n", graph_dotted_line); 567 printf("%.105s\n", graph_dotted_line);
323} 568}
324 569
325static void print_summary(void) 570static const char * const migrate_type_str[] = {
571 "UNMOVABL",
572 "RECLAIM",
573 "MOVABLE",
574 "RESERVED",
575 "CMA/ISLT",
576 "UNKNOWN",
577};
578
579static void __print_page_result(struct rb_root *root,
580 struct perf_session *session __maybe_unused,
581 int n_lines)
326{ 582{
327 printf("\nSUMMARY\n=======\n"); 583 struct rb_node *next = rb_first(root);
328 printf("Total bytes requested: %lu\n", total_requested); 584 const char *format;
329 printf("Total bytes allocated: %lu\n", total_allocated); 585
330 printf("Total bytes wasted on internal fragmentation: %lu\n", 586 printf("\n%.80s\n", graph_dotted_line);
587 printf(" %-16s | Total alloc (KB) | Hits | Order | Mig.type | GFP flags\n",
588 use_pfn ? "PFN" : "Page");
589 printf("%.80s\n", graph_dotted_line);
590
591 if (use_pfn)
592 format = " %16llu | %'16llu | %'9d | %5d | %8s | %08lx\n";
593 else
594 format = " %016llx | %'16llu | %'9d | %5d | %8s | %08lx\n";
595
596 while (next && n_lines--) {
597 struct page_stat *data;
598
599 data = rb_entry(next, struct page_stat, node);
600
601 printf(format, (unsigned long long)data->page,
602 (unsigned long long)data->alloc_bytes / 1024,
603 data->nr_alloc, data->order,
604 migrate_type_str[data->migrate_type],
605 (unsigned long)data->gfp_flags);
606
607 next = rb_next(next);
608 }
609
610 if (n_lines == -1)
611 printf(" ... | ... | ... | ... | ... | ... \n");
612
613 printf("%.80s\n", graph_dotted_line);
614}
615
616static void print_slab_summary(void)
617{
618 printf("\nSUMMARY (SLAB allocator)");
619 printf("\n========================\n");
620 printf("Total bytes requested: %'lu\n", total_requested);
621 printf("Total bytes allocated: %'lu\n", total_allocated);
622 printf("Total bytes wasted on internal fragmentation: %'lu\n",
331 total_allocated - total_requested); 623 total_allocated - total_requested);
332 printf("Internal fragmentation: %f%%\n", 624 printf("Internal fragmentation: %f%%\n",
333 fragmentation(total_requested, total_allocated)); 625 fragmentation(total_requested, total_allocated));
334 printf("Cross CPU allocations: %lu/%lu\n", nr_cross_allocs, nr_allocs); 626 printf("Cross CPU allocations: %'lu/%'lu\n", nr_cross_allocs, nr_allocs);
335} 627}
336 628
337static void print_result(struct perf_session *session) 629static void print_page_summary(void)
630{
631 int o, m;
632 u64 nr_alloc_freed = nr_page_frees - nr_page_nomatch;
633 u64 total_alloc_freed_bytes = total_page_free_bytes - total_page_nomatch_bytes;
634
635 printf("\nSUMMARY (page allocator)");
636 printf("\n========================\n");
637 printf("%-30s: %'16lu [ %'16"PRIu64" KB ]\n", "Total allocation requests",
638 nr_page_allocs, total_page_alloc_bytes / 1024);
639 printf("%-30s: %'16lu [ %'16"PRIu64" KB ]\n", "Total free requests",
640 nr_page_frees, total_page_free_bytes / 1024);
641 printf("\n");
642
643 printf("%-30s: %'16lu [ %'16"PRIu64" KB ]\n", "Total alloc+freed requests",
644 nr_alloc_freed, (total_alloc_freed_bytes) / 1024);
645 printf("%-30s: %'16lu [ %'16"PRIu64" KB ]\n", "Total alloc-only requests",
646 nr_page_allocs - nr_alloc_freed,
647 (total_page_alloc_bytes - total_alloc_freed_bytes) / 1024);
648 printf("%-30s: %'16lu [ %'16"PRIu64" KB ]\n", "Total free-only requests",
649 nr_page_nomatch, total_page_nomatch_bytes / 1024);
650 printf("\n");
651
652 printf("%-30s: %'16lu [ %'16"PRIu64" KB ]\n", "Total allocation failures",
653 nr_page_fails, total_page_fail_bytes / 1024);
654 printf("\n");
655
656 printf("%5s %12s %12s %12s %12s %12s\n", "Order", "Unmovable",
657 "Reclaimable", "Movable", "Reserved", "CMA/Isolated");
658 printf("%.5s %.12s %.12s %.12s %.12s %.12s\n", graph_dotted_line,
659 graph_dotted_line, graph_dotted_line, graph_dotted_line,
660 graph_dotted_line, graph_dotted_line);
661
662 for (o = 0; o < MAX_PAGE_ORDER; o++) {
663 printf("%5d", o);
664 for (m = 0; m < MAX_MIGRATE_TYPES - 1; m++) {
665 if (order_stats[o][m])
666 printf(" %'12d", order_stats[o][m]);
667 else
668 printf(" %12c", '.');
669 }
670 printf("\n");
671 }
672}
673
674static void print_slab_result(struct perf_session *session)
338{ 675{
339 if (caller_flag) 676 if (caller_flag)
340 __print_result(&root_caller_sorted, session, caller_lines, 1); 677 __print_slab_result(&root_caller_sorted, session, caller_lines, 1);
341 if (alloc_flag) 678 if (alloc_flag)
342 __print_result(&root_alloc_sorted, session, alloc_lines, 0); 679 __print_slab_result(&root_alloc_sorted, session, alloc_lines, 0);
343 print_summary(); 680 print_slab_summary();
681}
682
683static void print_page_result(struct perf_session *session)
684{
685 if (alloc_flag)
686 __print_page_result(&page_alloc_sorted, session, alloc_lines);
687 print_page_summary();
688}
689
690static void print_result(struct perf_session *session)
691{
692 if (kmem_slab)
693 print_slab_result(session);
694 if (kmem_page)
695 print_page_result(session);
344} 696}
345 697
346struct sort_dimension { 698struct sort_dimension {
@@ -352,8 +704,8 @@ struct sort_dimension {
352static LIST_HEAD(caller_sort); 704static LIST_HEAD(caller_sort);
353static LIST_HEAD(alloc_sort); 705static LIST_HEAD(alloc_sort);
354 706
355static void sort_insert(struct rb_root *root, struct alloc_stat *data, 707static void sort_slab_insert(struct rb_root *root, struct alloc_stat *data,
356 struct list_head *sort_list) 708 struct list_head *sort_list)
357{ 709{
358 struct rb_node **new = &(root->rb_node); 710 struct rb_node **new = &(root->rb_node);
359 struct rb_node *parent = NULL; 711 struct rb_node *parent = NULL;
@@ -382,8 +734,8 @@ static void sort_insert(struct rb_root *root, struct alloc_stat *data,
382 rb_insert_color(&data->node, root); 734 rb_insert_color(&data->node, root);
383} 735}
384 736
385static void __sort_result(struct rb_root *root, struct rb_root *root_sorted, 737static void __sort_slab_result(struct rb_root *root, struct rb_root *root_sorted,
386 struct list_head *sort_list) 738 struct list_head *sort_list)
387{ 739{
388 struct rb_node *node; 740 struct rb_node *node;
389 struct alloc_stat *data; 741 struct alloc_stat *data;
@@ -395,26 +747,79 @@ static void __sort_result(struct rb_root *root, struct rb_root *root_sorted,
395 747
396 rb_erase(node, root); 748 rb_erase(node, root);
397 data = rb_entry(node, struct alloc_stat, node); 749 data = rb_entry(node, struct alloc_stat, node);
398 sort_insert(root_sorted, data, sort_list); 750 sort_slab_insert(root_sorted, data, sort_list);
751 }
752}
753
754static void sort_page_insert(struct rb_root *root, struct page_stat *data)
755{
756 struct rb_node **new = &root->rb_node;
757 struct rb_node *parent = NULL;
758
759 while (*new) {
760 struct page_stat *this;
761 int cmp = 0;
762
763 this = rb_entry(*new, struct page_stat, node);
764 parent = *new;
765
766 /* TODO: support more sort key */
767 cmp = data->alloc_bytes - this->alloc_bytes;
768
769 if (cmp > 0)
770 new = &parent->rb_left;
771 else
772 new = &parent->rb_right;
773 }
774
775 rb_link_node(&data->node, parent, new);
776 rb_insert_color(&data->node, root);
777}
778
779static void __sort_page_result(struct rb_root *root, struct rb_root *root_sorted)
780{
781 struct rb_node *node;
782 struct page_stat *data;
783
784 for (;;) {
785 node = rb_first(root);
786 if (!node)
787 break;
788
789 rb_erase(node, root);
790 data = rb_entry(node, struct page_stat, node);
791 sort_page_insert(root_sorted, data);
399 } 792 }
400} 793}
401 794
402static void sort_result(void) 795static void sort_result(void)
403{ 796{
404 __sort_result(&root_alloc_stat, &root_alloc_sorted, &alloc_sort); 797 if (kmem_slab) {
405 __sort_result(&root_caller_stat, &root_caller_sorted, &caller_sort); 798 __sort_slab_result(&root_alloc_stat, &root_alloc_sorted,
799 &alloc_sort);
800 __sort_slab_result(&root_caller_stat, &root_caller_sorted,
801 &caller_sort);
802 }
803 if (kmem_page) {
804 __sort_page_result(&page_alloc_tree, &page_alloc_sorted);
805 }
406} 806}
407 807
408static int __cmd_kmem(struct perf_session *session) 808static int __cmd_kmem(struct perf_session *session)
409{ 809{
410 int err = -EINVAL; 810 int err = -EINVAL;
811 struct perf_evsel *evsel;
411 const struct perf_evsel_str_handler kmem_tracepoints[] = { 812 const struct perf_evsel_str_handler kmem_tracepoints[] = {
813 /* slab allocator */
412 { "kmem:kmalloc", perf_evsel__process_alloc_event, }, 814 { "kmem:kmalloc", perf_evsel__process_alloc_event, },
413 { "kmem:kmem_cache_alloc", perf_evsel__process_alloc_event, }, 815 { "kmem:kmem_cache_alloc", perf_evsel__process_alloc_event, },
414 { "kmem:kmalloc_node", perf_evsel__process_alloc_node_event, }, 816 { "kmem:kmalloc_node", perf_evsel__process_alloc_node_event, },
415 { "kmem:kmem_cache_alloc_node", perf_evsel__process_alloc_node_event, }, 817 { "kmem:kmem_cache_alloc_node", perf_evsel__process_alloc_node_event, },
416 { "kmem:kfree", perf_evsel__process_free_event, }, 818 { "kmem:kfree", perf_evsel__process_free_event, },
417 { "kmem:kmem_cache_free", perf_evsel__process_free_event, }, 819 { "kmem:kmem_cache_free", perf_evsel__process_free_event, },
820 /* page allocator */
821 { "kmem:mm_page_alloc", perf_evsel__process_page_alloc_event, },
822 { "kmem:mm_page_free", perf_evsel__process_page_free_event, },
418 }; 823 };
419 824
420 if (!perf_session__has_traces(session, "kmem record")) 825 if (!perf_session__has_traces(session, "kmem record"))
@@ -425,10 +830,20 @@ static int __cmd_kmem(struct perf_session *session)
425 goto out; 830 goto out;
426 } 831 }
427 832
833 evlist__for_each(session->evlist, evsel) {
834 if (!strcmp(perf_evsel__name(evsel), "kmem:mm_page_alloc") &&
835 perf_evsel__field(evsel, "pfn")) {
836 use_pfn = true;
837 break;
838 }
839 }
840
428 setup_pager(); 841 setup_pager();
429 err = perf_session__process_events(session, &perf_kmem); 842 err = perf_session__process_events(session);
430 if (err != 0) 843 if (err != 0) {
844 pr_err("error during process events: %d\n", err);
431 goto out; 845 goto out;
846 }
432 sort_result(); 847 sort_result();
433 print_result(session); 848 print_result(session);
434out: 849out:
@@ -559,6 +974,7 @@ static int setup_sorting(struct list_head *sort_list, const char *arg)
559{ 974{
560 char *tok; 975 char *tok;
561 char *str = strdup(arg); 976 char *str = strdup(arg);
977 char *pos = str;
562 978
563 if (!str) { 979 if (!str) {
564 pr_err("%s: strdup failed\n", __func__); 980 pr_err("%s: strdup failed\n", __func__);
@@ -566,7 +982,7 @@ static int setup_sorting(struct list_head *sort_list, const char *arg)
566 } 982 }
567 983
568 while (true) { 984 while (true) {
569 tok = strsep(&str, ","); 985 tok = strsep(&pos, ",");
570 if (!tok) 986 if (!tok)
571 break; 987 break;
572 if (sort_dimension__add(tok, sort_list) < 0) { 988 if (sort_dimension__add(tok, sort_list) < 0) {
@@ -610,6 +1026,22 @@ static int parse_alloc_opt(const struct option *opt __maybe_unused,
610 return 0; 1026 return 0;
611} 1027}
612 1028
1029static int parse_slab_opt(const struct option *opt __maybe_unused,
1030 const char *arg __maybe_unused,
1031 int unset __maybe_unused)
1032{
1033 kmem_slab = (kmem_page + 1);
1034 return 0;
1035}
1036
1037static int parse_page_opt(const struct option *opt __maybe_unused,
1038 const char *arg __maybe_unused,
1039 int unset __maybe_unused)
1040{
1041 kmem_page = (kmem_slab + 1);
1042 return 0;
1043}
1044
613static int parse_line_opt(const struct option *opt __maybe_unused, 1045static int parse_line_opt(const struct option *opt __maybe_unused,
614 const char *arg, int unset __maybe_unused) 1046 const char *arg, int unset __maybe_unused)
615{ 1047{
@@ -632,6 +1064,8 @@ static int __cmd_record(int argc, const char **argv)
632{ 1064{
633 const char * const record_args[] = { 1065 const char * const record_args[] = {
634 "record", "-a", "-R", "-c", "1", 1066 "record", "-a", "-R", "-c", "1",
1067 };
1068 const char * const slab_events[] = {
635 "-e", "kmem:kmalloc", 1069 "-e", "kmem:kmalloc",
636 "-e", "kmem:kmalloc_node", 1070 "-e", "kmem:kmalloc_node",
637 "-e", "kmem:kfree", 1071 "-e", "kmem:kfree",
@@ -639,10 +1073,19 @@ static int __cmd_record(int argc, const char **argv)
639 "-e", "kmem:kmem_cache_alloc_node", 1073 "-e", "kmem:kmem_cache_alloc_node",
640 "-e", "kmem:kmem_cache_free", 1074 "-e", "kmem:kmem_cache_free",
641 }; 1075 };
1076 const char * const page_events[] = {
1077 "-e", "kmem:mm_page_alloc",
1078 "-e", "kmem:mm_page_free",
1079 };
642 unsigned int rec_argc, i, j; 1080 unsigned int rec_argc, i, j;
643 const char **rec_argv; 1081 const char **rec_argv;
644 1082
645 rec_argc = ARRAY_SIZE(record_args) + argc - 1; 1083 rec_argc = ARRAY_SIZE(record_args) + argc - 1;
1084 if (kmem_slab)
1085 rec_argc += ARRAY_SIZE(slab_events);
1086 if (kmem_page)
1087 rec_argc += ARRAY_SIZE(page_events);
1088
646 rec_argv = calloc(rec_argc + 1, sizeof(char *)); 1089 rec_argv = calloc(rec_argc + 1, sizeof(char *));
647 1090
648 if (rec_argv == NULL) 1091 if (rec_argv == NULL)
@@ -651,6 +1094,15 @@ static int __cmd_record(int argc, const char **argv)
651 for (i = 0; i < ARRAY_SIZE(record_args); i++) 1094 for (i = 0; i < ARRAY_SIZE(record_args); i++)
652 rec_argv[i] = strdup(record_args[i]); 1095 rec_argv[i] = strdup(record_args[i]);
653 1096
1097 if (kmem_slab) {
1098 for (j = 0; j < ARRAY_SIZE(slab_events); j++, i++)
1099 rec_argv[i] = strdup(slab_events[j]);
1100 }
1101 if (kmem_page) {
1102 for (j = 0; j < ARRAY_SIZE(page_events); j++, i++)
1103 rec_argv[i] = strdup(page_events[j]);
1104 }
1105
654 for (j = 1; j < (unsigned int)argc; j++, i++) 1106 for (j = 1; j < (unsigned int)argc; j++, i++)
655 rec_argv[i] = argv[j]; 1107 rec_argv[i] = argv[j];
656 1108
@@ -660,8 +1112,13 @@ static int __cmd_record(int argc, const char **argv)
660int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused) 1112int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
661{ 1113{
662 const char * const default_sort_order = "frag,hit,bytes"; 1114 const char * const default_sort_order = "frag,hit,bytes";
1115 struct perf_data_file file = {
1116 .mode = PERF_DATA_MODE_READ,
1117 };
663 const struct option kmem_options[] = { 1118 const struct option kmem_options[] = {
664 OPT_STRING('i', "input", &input_name, "file", "input file name"), 1119 OPT_STRING('i', "input", &input_name, "file", "input file name"),
1120 OPT_INCR('v', "verbose", &verbose,
1121 "be more verbose (show symbol address, etc)"),
665 OPT_CALLBACK_NOOPT(0, "caller", NULL, NULL, 1122 OPT_CALLBACK_NOOPT(0, "caller", NULL, NULL,
666 "show per-callsite statistics", parse_caller_opt), 1123 "show per-callsite statistics", parse_caller_opt),
667 OPT_CALLBACK_NOOPT(0, "alloc", NULL, NULL, 1124 OPT_CALLBACK_NOOPT(0, "alloc", NULL, NULL,
@@ -671,6 +1128,11 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
671 parse_sort_opt), 1128 parse_sort_opt),
672 OPT_CALLBACK('l', "line", NULL, "num", "show n lines", parse_line_opt), 1129 OPT_CALLBACK('l', "line", NULL, "num", "show n lines", parse_line_opt),
673 OPT_BOOLEAN(0, "raw-ip", &raw_ip, "show raw ip instead of symbol"), 1130 OPT_BOOLEAN(0, "raw-ip", &raw_ip, "show raw ip instead of symbol"),
1131 OPT_BOOLEAN('f', "force", &file.force, "don't complain, do it"),
1132 OPT_CALLBACK_NOOPT(0, "slab", NULL, NULL, "Analyze slab allocator",
1133 parse_slab_opt),
1134 OPT_CALLBACK_NOOPT(0, "page", NULL, NULL, "Analyze page allocator",
1135 parse_page_opt),
674 OPT_END() 1136 OPT_END()
675 }; 1137 };
676 const char *const kmem_subcommands[] = { "record", "stat", NULL }; 1138 const char *const kmem_subcommands[] = { "record", "stat", NULL };
@@ -679,10 +1141,6 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
679 NULL 1141 NULL
680 }; 1142 };
681 struct perf_session *session; 1143 struct perf_session *session;
682 struct perf_data_file file = {
683 .path = input_name,
684 .mode = PERF_DATA_MODE_READ,
685 };
686 int ret = -1; 1144 int ret = -1;
687 1145
688 argc = parse_options_subcommand(argc, argv, kmem_options, 1146 argc = parse_options_subcommand(argc, argv, kmem_options,
@@ -691,18 +1149,36 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
691 if (!argc) 1149 if (!argc)
692 usage_with_options(kmem_usage, kmem_options); 1150 usage_with_options(kmem_usage, kmem_options);
693 1151
1152 if (kmem_slab == 0 && kmem_page == 0)
1153 kmem_slab = 1; /* for backward compatibility */
1154
694 if (!strncmp(argv[0], "rec", 3)) { 1155 if (!strncmp(argv[0], "rec", 3)) {
695 symbol__init(NULL); 1156 symbol__init(NULL);
696 return __cmd_record(argc, argv); 1157 return __cmd_record(argc, argv);
697 } 1158 }
698 1159
1160 file.path = input_name;
1161
699 session = perf_session__new(&file, false, &perf_kmem); 1162 session = perf_session__new(&file, false, &perf_kmem);
700 if (session == NULL) 1163 if (session == NULL)
701 return -1; 1164 return -1;
702 1165
1166 if (kmem_page) {
1167 struct perf_evsel *evsel = perf_evlist__first(session->evlist);
1168
1169 if (evsel == NULL || evsel->tp_format == NULL) {
1170 pr_err("invalid event found.. aborting\n");
1171 return -1;
1172 }
1173
1174 kmem_page_size = pevent_get_page_size(evsel->tp_format->pevent);
1175 }
1176
703 symbol__init(&session->header.env); 1177 symbol__init(&session->header.env);
704 1178
705 if (!strcmp(argv[0], "stat")) { 1179 if (!strcmp(argv[0], "stat")) {
1180 setlocale(LC_ALL, "");
1181
706 if (cpu__setup_cpunode_map()) 1182 if (cpu__setup_cpunode_map())
707 goto out_delete; 1183 goto out_delete;
708 1184
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 0894a817f67e..1f9338f6109c 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",
@@ -1044,6 +1047,7 @@ static int read_events(struct perf_kvm_stat *kvm)
1044 struct perf_data_file file = { 1047 struct perf_data_file file = {
1045 .path = kvm->file_name, 1048 .path = kvm->file_name,
1046 .mode = PERF_DATA_MODE_READ, 1049 .mode = PERF_DATA_MODE_READ,
1050 .force = kvm->force,
1047 }; 1051 };
1048 1052
1049 kvm->tool = eops; 1053 kvm->tool = eops;
@@ -1066,7 +1070,7 @@ static int read_events(struct perf_kvm_stat *kvm)
1066 if (ret < 0) 1070 if (ret < 0)
1067 return ret; 1071 return ret;
1068 1072
1069 return perf_session__process_events(kvm->session, &kvm->tool); 1073 return perf_session__process_events(kvm->session);
1070} 1074}
1071 1075
1072static int parse_target_str(struct perf_kvm_stat *kvm) 1076static int parse_target_str(struct perf_kvm_stat *kvm)
@@ -1201,6 +1205,7 @@ kvm_events_report(struct perf_kvm_stat *kvm, int argc, const char **argv)
1201 " time (sort by avg time)"), 1205 " time (sort by avg time)"),
1202 OPT_STRING('p', "pid", &kvm->opts.target.pid, "pid", 1206 OPT_STRING('p', "pid", &kvm->opts.target.pid, "pid",
1203 "analyze events only for given process id(s)"), 1207 "analyze events only for given process id(s)"),
1208 OPT_BOOLEAN('f', "force", &kvm->force, "don't complain, do it"),
1204 OPT_END() 1209 OPT_END()
1205 }; 1210 };
1206 1211
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..d49c2ab85fc2 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -846,6 +846,8 @@ static const struct perf_evsel_str_handler lock_tracepoints[] = {
846 { "lock:lock_release", perf_evsel__process_lock_release, }, /* CONFIG_LOCKDEP */ 846 { "lock:lock_release", perf_evsel__process_lock_release, }, /* CONFIG_LOCKDEP */
847}; 847};
848 848
849static bool force;
850
849static int __cmd_report(bool display_info) 851static int __cmd_report(bool display_info)
850{ 852{
851 int err = -EINVAL; 853 int err = -EINVAL;
@@ -857,6 +859,7 @@ static int __cmd_report(bool display_info)
857 struct perf_data_file file = { 859 struct perf_data_file file = {
858 .path = input_name, 860 .path = input_name,
859 .mode = PERF_DATA_MODE_READ, 861 .mode = PERF_DATA_MODE_READ,
862 .force = force,
860 }; 863 };
861 864
862 session = perf_session__new(&file, false, &eops); 865 session = perf_session__new(&file, false, &eops);
@@ -878,7 +881,7 @@ static int __cmd_report(bool display_info)
878 if (select_key()) 881 if (select_key())
879 goto out_delete; 882 goto out_delete;
880 883
881 err = perf_session__process_events(session, &eops); 884 err = perf_session__process_events(session);
882 if (err) 885 if (err)
883 goto out_delete; 886 goto out_delete;
884 887
@@ -945,6 +948,7 @@ int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused)
945 "dump thread list in perf.data"), 948 "dump thread list in perf.data"),
946 OPT_BOOLEAN('m', "map", &info_map, 949 OPT_BOOLEAN('m', "map", &info_map,
947 "map of lock instances (address:name table)"), 950 "map of lock instances (address:name table)"),
951 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
948 OPT_END() 952 OPT_END()
949 }; 953 };
950 const struct option lock_options[] = { 954 const struct option lock_options[] = {
@@ -956,6 +960,7 @@ int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused)
956 const struct option report_options[] = { 960 const struct option report_options[] = {
957 OPT_STRING('k', "key", &sort_key, "acquired", 961 OPT_STRING('k', "key", &sort_key, "acquired",
958 "key for sorting (acquired / contended / avg_wait / wait_total / wait_max / wait_min)"), 962 "key for sorting (acquired / contended / avg_wait / wait_total / wait_max / wait_min)"),
963 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
959 /* TODO: type */ 964 /* TODO: type */
960 OPT_END() 965 OPT_END()
961 }; 966 };
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
index 9b5663950a4d..675216e08bfc 100644
--- a/tools/perf/builtin-mem.c
+++ b/tools/perf/builtin-mem.c
@@ -15,6 +15,7 @@ struct perf_mem {
15 char const *input_name; 15 char const *input_name;
16 bool hide_unresolved; 16 bool hide_unresolved;
17 bool dump_raw; 17 bool dump_raw;
18 bool force;
18 int operation; 19 int operation;
19 const char *cpu_list; 20 const char *cpu_list;
20 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); 21 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
@@ -120,6 +121,7 @@ static int report_raw_events(struct perf_mem *mem)
120 struct perf_data_file file = { 121 struct perf_data_file file = {
121 .path = input_name, 122 .path = input_name,
122 .mode = PERF_DATA_MODE_READ, 123 .mode = PERF_DATA_MODE_READ,
124 .force = mem->force,
123 }; 125 };
124 int err = -EINVAL; 126 int err = -EINVAL;
125 int ret; 127 int ret;
@@ -141,7 +143,7 @@ static int report_raw_events(struct perf_mem *mem)
141 143
142 printf("# PID, TID, IP, ADDR, LOCAL WEIGHT, DSRC, SYMBOL\n"); 144 printf("# PID, TID, IP, ADDR, LOCAL WEIGHT, DSRC, SYMBOL\n");
143 145
144 err = perf_session__process_events(session, &mem->tool); 146 err = perf_session__process_events(session);
145 if (err) 147 if (err)
146 return err; 148 return err;
147 149
@@ -286,10 +288,11 @@ int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused)
286 "input file name"), 288 "input file name"),
287 OPT_STRING('C', "cpu", &mem.cpu_list, "cpu", 289 OPT_STRING('C', "cpu", &mem.cpu_list, "cpu",
288 "list of cpus to profile"), 290 "list of cpus to profile"),
289 OPT_STRING('x', "field-separator", &symbol_conf.field_sep, 291 OPT_STRING_NOEMPTY('x', "field-separator", &symbol_conf.field_sep,
290 "separator", 292 "separator",
291 "separator for columns, no spaces will be added" 293 "separator for columns, no spaces will be added"
292 " between columns '.' is reserved."), 294 " between columns '.' is reserved."),
295 OPT_BOOLEAN('f', "force", &mem.force, "don't complain, do it"),
293 OPT_END() 296 OPT_END()
294 }; 297 };
295 const char *const mem_subcommands[] = { "record", "report", NULL }; 298 const char *const mem_subcommands[] = { "record", "report", NULL };
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 921bb6942503..f7b1af67e9f6 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -56,6 +56,7 @@ static struct {
56 bool mod_events; 56 bool mod_events;
57 bool uprobes; 57 bool uprobes;
58 bool quiet; 58 bool quiet;
59 bool target_used;
59 int nevents; 60 int nevents;
60 struct perf_probe_event events[MAX_PROBES]; 61 struct perf_probe_event events[MAX_PROBES];
61 struct strlist *dellist; 62 struct strlist *dellist;
@@ -78,6 +79,12 @@ static int parse_probe_event(const char *str)
78 } 79 }
79 80
80 pev->uprobes = params.uprobes; 81 pev->uprobes = params.uprobes;
82 if (params.target) {
83 pev->target = strdup(params.target);
84 if (!pev->target)
85 return -ENOMEM;
86 params.target_used = true;
87 }
81 88
82 /* Parse a perf-probe command into event */ 89 /* Parse a perf-probe command into event */
83 ret = parse_perf_probe_command(str, pev); 90 ret = parse_perf_probe_command(str, pev);
@@ -102,6 +109,7 @@ static int set_target(const char *ptr)
102 params.target = strdup(ptr); 109 params.target = strdup(ptr);
103 if (!params.target) 110 if (!params.target)
104 return -ENOMEM; 111 return -ENOMEM;
112 params.target_used = false;
105 113
106 found = 1; 114 found = 1;
107 buf = ptr + (strlen(ptr) - 3); 115 buf = ptr + (strlen(ptr) - 3);
@@ -178,7 +186,7 @@ static int opt_set_target(const struct option *opt, const char *str,
178 int ret = -ENOENT; 186 int ret = -ENOENT;
179 char *tmp; 187 char *tmp;
180 188
181 if (str && !params.target) { 189 if (str) {
182 if (!strcmp(opt->long_name, "exec")) 190 if (!strcmp(opt->long_name, "exec"))
183 params.uprobes = true; 191 params.uprobes = true;
184#ifdef HAVE_DWARF_SUPPORT 192#ifdef HAVE_DWARF_SUPPORT
@@ -200,7 +208,9 @@ static int opt_set_target(const struct option *opt, const char *str,
200 if (!tmp) 208 if (!tmp)
201 return -ENOMEM; 209 return -ENOMEM;
202 } 210 }
211 free(params.target);
203 params.target = tmp; 212 params.target = tmp;
213 params.target_used = false;
204 ret = 0; 214 ret = 0;
205 } 215 }
206 216
@@ -485,9 +495,14 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
485 } 495 }
486 496
487 if (params.nevents) { 497 if (params.nevents) {
498 /* Ensure the last given target is used */
499 if (params.target && !params.target_used) {
500 pr_warning(" Error: -x/-m must follow the probe definitions.\n");
501 usage_with_options(probe_usage, options);
502 }
503
488 ret = add_perf_probe_events(params.events, params.nevents, 504 ret = add_perf_probe_events(params.events, params.nevents,
489 params.max_probe_points, 505 params.max_probe_points,
490 params.target,
491 params.force_add); 506 params.force_add);
492 if (ret < 0) { 507 if (ret < 0) {
493 pr_err_with_code(" Error: Failed to add events.", ret); 508 pr_err_with_code(" Error: Failed to add events.", ret);
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 404ab3434052..c3efdfb630b5 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -70,8 +70,8 @@ static int process_synthesized_event(struct perf_tool *tool,
70static int record__mmap_read(struct record *rec, int idx) 70static int record__mmap_read(struct record *rec, int idx)
71{ 71{
72 struct perf_mmap *md = &rec->evlist->mmap[idx]; 72 struct perf_mmap *md = &rec->evlist->mmap[idx];
73 unsigned int head = perf_mmap__read_head(md); 73 u64 head = perf_mmap__read_head(md);
74 unsigned int old = md->prev; 74 u64 old = md->prev;
75 unsigned char *data = md->base + page_size; 75 unsigned char *data = md->base + page_size;
76 unsigned long size; 76 unsigned long size;
77 void *buf; 77 void *buf;
@@ -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
@@ -710,6 +711,90 @@ static int perf_record_config(const char *var, const char *value, void *cb)
710 return perf_default_config(var, value, cb); 711 return perf_default_config(var, value, cb);
711} 712}
712 713
714struct clockid_map {
715 const char *name;
716 int clockid;
717};
718
719#define CLOCKID_MAP(n, c) \
720 { .name = n, .clockid = (c), }
721
722#define CLOCKID_END { .name = NULL, }
723
724
725/*
726 * Add the missing ones, we need to build on many distros...
727 */
728#ifndef CLOCK_MONOTONIC_RAW
729#define CLOCK_MONOTONIC_RAW 4
730#endif
731#ifndef CLOCK_BOOTTIME
732#define CLOCK_BOOTTIME 7
733#endif
734#ifndef CLOCK_TAI
735#define CLOCK_TAI 11
736#endif
737
738static const struct clockid_map clockids[] = {
739 /* available for all events, NMI safe */
740 CLOCKID_MAP("monotonic", CLOCK_MONOTONIC),
741 CLOCKID_MAP("monotonic_raw", CLOCK_MONOTONIC_RAW),
742
743 /* available for some events */
744 CLOCKID_MAP("realtime", CLOCK_REALTIME),
745 CLOCKID_MAP("boottime", CLOCK_BOOTTIME),
746 CLOCKID_MAP("tai", CLOCK_TAI),
747
748 /* available for the lazy */
749 CLOCKID_MAP("mono", CLOCK_MONOTONIC),
750 CLOCKID_MAP("raw", CLOCK_MONOTONIC_RAW),
751 CLOCKID_MAP("real", CLOCK_REALTIME),
752 CLOCKID_MAP("boot", CLOCK_BOOTTIME),
753
754 CLOCKID_END,
755};
756
757static int parse_clockid(const struct option *opt, const char *str, int unset)
758{
759 struct record_opts *opts = (struct record_opts *)opt->value;
760 const struct clockid_map *cm;
761 const char *ostr = str;
762
763 if (unset) {
764 opts->use_clockid = 0;
765 return 0;
766 }
767
768 /* no arg passed */
769 if (!str)
770 return 0;
771
772 /* no setting it twice */
773 if (opts->use_clockid)
774 return -1;
775
776 opts->use_clockid = true;
777
778 /* if its a number, we're done */
779 if (sscanf(str, "%d", &opts->clockid) == 1)
780 return 0;
781
782 /* allow a "CLOCK_" prefix to the name */
783 if (!strncasecmp(str, "CLOCK_", 6))
784 str += 6;
785
786 for (cm = clockids; cm->name; cm++) {
787 if (!strcasecmp(str, cm->name)) {
788 opts->clockid = cm->clockid;
789 return 0;
790 }
791 }
792
793 opts->use_clockid = false;
794 ui__warning("unknown clockid %s, check man page\n", ostr);
795 return -1;
796}
797
713static const char * const __record_usage[] = { 798static const char * const __record_usage[] = {
714 "perf record [<options>] [<command>]", 799 "perf record [<options>] [<command>]",
715 "perf record [<options>] -- <command> [<options>]", 800 "perf record [<options>] -- <command> [<options>]",
@@ -751,9 +836,9 @@ static struct record record = {
751#define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace) recording: " 836#define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace) recording: "
752 837
753#ifdef HAVE_DWARF_UNWIND_SUPPORT 838#ifdef HAVE_DWARF_UNWIND_SUPPORT
754const char record_callchain_help[] = CALLCHAIN_HELP "fp dwarf"; 839const char record_callchain_help[] = CALLCHAIN_HELP "fp dwarf lbr";
755#else 840#else
756const char record_callchain_help[] = CALLCHAIN_HELP "fp"; 841const char record_callchain_help[] = CALLCHAIN_HELP "fp lbr";
757#endif 842#endif
758 843
759/* 844/*
@@ -839,6 +924,11 @@ struct option __record_options[] = {
839 "use per-thread mmaps"), 924 "use per-thread mmaps"),
840 OPT_BOOLEAN('I', "intr-regs", &record.opts.sample_intr_regs, 925 OPT_BOOLEAN('I', "intr-regs", &record.opts.sample_intr_regs,
841 "Sample machine registers on interrupt"), 926 "Sample machine registers on interrupt"),
927 OPT_BOOLEAN(0, "running-time", &record.opts.running_time,
928 "Record running/enabled time of read (:S) events"),
929 OPT_CALLBACK('k', "clockid", &record.opts,
930 "clockid", "clockid to use for events, see clock_gettime()",
931 parse_clockid),
842 OPT_END() 932 OPT_END()
843}; 933};
844 934
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 2f91094e228b..476cdf7afcca 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");
@@ -345,7 +347,7 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
345static void report__warn_kptr_restrict(const struct report *rep) 347static void report__warn_kptr_restrict(const struct report *rep)
346{ 348{
347 struct map *kernel_map = rep->session->machines.host.vmlinux_maps[MAP__FUNCTION]; 349 struct map *kernel_map = rep->session->machines.host.vmlinux_maps[MAP__FUNCTION];
348 struct kmap *kernel_kmap = map__kmap(kernel_map); 350 struct kmap *kernel_kmap = kernel_map ? map__kmap(kernel_map) : NULL;
349 351
350 if (kernel_map == NULL || 352 if (kernel_map == NULL ||
351 (kernel_map->dso->hit && 353 (kernel_map->dso->hit &&
@@ -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..5275bab70313 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -23,12 +23,13 @@
23#include <semaphore.h> 23#include <semaphore.h>
24#include <pthread.h> 24#include <pthread.h>
25#include <math.h> 25#include <math.h>
26#include <api/fs/fs.h>
26 27
27#define PR_SET_NAME 15 /* Set process name */ 28#define PR_SET_NAME 15 /* Set process name */
28#define MAX_CPUS 4096 29#define MAX_CPUS 4096
29#define COMM_LEN 20 30#define COMM_LEN 20
30#define SYM_LEN 129 31#define SYM_LEN 129
31#define MAX_PID 65536 32#define MAX_PID 1024000
32 33
33struct sched_atom; 34struct sched_atom;
34 35
@@ -124,7 +125,7 @@ struct perf_sched {
124 struct perf_tool tool; 125 struct perf_tool tool;
125 const char *sort_order; 126 const char *sort_order;
126 unsigned long nr_tasks; 127 unsigned long nr_tasks;
127 struct task_desc *pid_to_task[MAX_PID]; 128 struct task_desc **pid_to_task;
128 struct task_desc **tasks; 129 struct task_desc **tasks;
129 const struct trace_sched_handler *tp_handler; 130 const struct trace_sched_handler *tp_handler;
130 pthread_mutex_t start_work_mutex; 131 pthread_mutex_t start_work_mutex;
@@ -169,6 +170,7 @@ struct perf_sched {
169 u64 cpu_last_switched[MAX_CPUS]; 170 u64 cpu_last_switched[MAX_CPUS];
170 struct rb_root atom_root, sorted_atom_root; 171 struct rb_root atom_root, sorted_atom_root;
171 struct list_head sort_list, cmp_pid; 172 struct list_head sort_list, cmp_pid;
173 bool force;
172}; 174};
173 175
174static u64 get_nsecs(void) 176static u64 get_nsecs(void)
@@ -326,8 +328,19 @@ static struct task_desc *register_pid(struct perf_sched *sched,
326 unsigned long pid, const char *comm) 328 unsigned long pid, const char *comm)
327{ 329{
328 struct task_desc *task; 330 struct task_desc *task;
331 static int pid_max;
329 332
330 BUG_ON(pid >= MAX_PID); 333 if (sched->pid_to_task == NULL) {
334 if (sysctl__read_int("kernel/pid_max", &pid_max) < 0)
335 pid_max = MAX_PID;
336 BUG_ON((sched->pid_to_task = calloc(pid_max, sizeof(struct task_desc *))) == NULL);
337 }
338 if (pid >= (unsigned long)pid_max) {
339 BUG_ON((sched->pid_to_task = realloc(sched->pid_to_task, (pid + 1) *
340 sizeof(struct task_desc *))) == NULL);
341 while (pid >= (unsigned long)pid_max)
342 sched->pid_to_task[pid_max++] = NULL;
343 }
331 344
332 task = sched->pid_to_task[pid]; 345 task = sched->pid_to_task[pid];
333 346
@@ -346,7 +359,7 @@ static struct task_desc *register_pid(struct perf_sched *sched,
346 359
347 sched->pid_to_task[pid] = task; 360 sched->pid_to_task[pid] = task;
348 sched->nr_tasks++; 361 sched->nr_tasks++;
349 sched->tasks = realloc(sched->tasks, sched->nr_tasks * sizeof(struct task_task *)); 362 sched->tasks = realloc(sched->tasks, sched->nr_tasks * sizeof(struct task_desc *));
350 BUG_ON(!sched->tasks); 363 BUG_ON(!sched->tasks);
351 sched->tasks[task->nr] = task; 364 sched->tasks[task->nr] = task;
352 365
@@ -425,24 +438,45 @@ static u64 get_cpu_usage_nsec_parent(void)
425 return sum; 438 return sum;
426} 439}
427 440
428static int self_open_counters(void) 441static int self_open_counters(struct perf_sched *sched, unsigned long cur_task)
429{ 442{
430 struct perf_event_attr attr; 443 struct perf_event_attr attr;
431 char sbuf[STRERR_BUFSIZE]; 444 char sbuf[STRERR_BUFSIZE], info[STRERR_BUFSIZE];
432 int fd; 445 int fd;
446 struct rlimit limit;
447 bool need_privilege = false;
433 448
434 memset(&attr, 0, sizeof(attr)); 449 memset(&attr, 0, sizeof(attr));
435 450
436 attr.type = PERF_TYPE_SOFTWARE; 451 attr.type = PERF_TYPE_SOFTWARE;
437 attr.config = PERF_COUNT_SW_TASK_CLOCK; 452 attr.config = PERF_COUNT_SW_TASK_CLOCK;
438 453
454force_again:
439 fd = sys_perf_event_open(&attr, 0, -1, -1, 455 fd = sys_perf_event_open(&attr, 0, -1, -1,
440 perf_event_open_cloexec_flag()); 456 perf_event_open_cloexec_flag());
441 457
442 if (fd < 0) 458 if (fd < 0) {
459 if (errno == EMFILE) {
460 if (sched->force) {
461 BUG_ON(getrlimit(RLIMIT_NOFILE, &limit) == -1);
462 limit.rlim_cur += sched->nr_tasks - cur_task;
463 if (limit.rlim_cur > limit.rlim_max) {
464 limit.rlim_max = limit.rlim_cur;
465 need_privilege = true;
466 }
467 if (setrlimit(RLIMIT_NOFILE, &limit) == -1) {
468 if (need_privilege && errno == EPERM)
469 strcpy(info, "Need privilege\n");
470 } else
471 goto force_again;
472 } else
473 strcpy(info, "Have a try with -f option\n");
474 }
443 pr_err("Error: sys_perf_event_open() syscall returned " 475 pr_err("Error: sys_perf_event_open() syscall returned "
444 "with %d (%s)\n", fd, 476 "with %d (%s)\n%s", fd,
445 strerror_r(errno, sbuf, sizeof(sbuf))); 477 strerror_r(errno, sbuf, sizeof(sbuf)), info);
478 exit(EXIT_FAILURE);
479 }
446 return fd; 480 return fd;
447} 481}
448 482
@@ -460,6 +494,7 @@ static u64 get_cpu_usage_nsec_self(int fd)
460struct sched_thread_parms { 494struct sched_thread_parms {
461 struct task_desc *task; 495 struct task_desc *task;
462 struct perf_sched *sched; 496 struct perf_sched *sched;
497 int fd;
463}; 498};
464 499
465static void *thread_func(void *ctx) 500static void *thread_func(void *ctx)
@@ -470,13 +505,12 @@ static void *thread_func(void *ctx)
470 u64 cpu_usage_0, cpu_usage_1; 505 u64 cpu_usage_0, cpu_usage_1;
471 unsigned long i, ret; 506 unsigned long i, ret;
472 char comm2[22]; 507 char comm2[22];
473 int fd; 508 int fd = parms->fd;
474 509
475 zfree(&parms); 510 zfree(&parms);
476 511
477 sprintf(comm2, ":%s", this_task->comm); 512 sprintf(comm2, ":%s", this_task->comm);
478 prctl(PR_SET_NAME, comm2); 513 prctl(PR_SET_NAME, comm2);
479 fd = self_open_counters();
480 if (fd < 0) 514 if (fd < 0)
481 return NULL; 515 return NULL;
482again: 516again:
@@ -528,6 +562,7 @@ static void create_tasks(struct perf_sched *sched)
528 BUG_ON(parms == NULL); 562 BUG_ON(parms == NULL);
529 parms->task = task = sched->tasks[i]; 563 parms->task = task = sched->tasks[i];
530 parms->sched = sched; 564 parms->sched = sched;
565 parms->fd = self_open_counters(sched, i);
531 sem_init(&task->sleep_sem, 0, 0); 566 sem_init(&task->sleep_sem, 0, 0);
532 sem_init(&task->ready_for_work, 0, 0); 567 sem_init(&task->ready_for_work, 0, 0);
533 sem_init(&task->work_done_sem, 0, 0); 568 sem_init(&task->work_done_sem, 0, 0);
@@ -572,13 +607,13 @@ static void wait_for_tasks(struct perf_sched *sched)
572 cpu_usage_1 = get_cpu_usage_nsec_parent(); 607 cpu_usage_1 = get_cpu_usage_nsec_parent();
573 if (!sched->runavg_cpu_usage) 608 if (!sched->runavg_cpu_usage)
574 sched->runavg_cpu_usage = sched->cpu_usage; 609 sched->runavg_cpu_usage = sched->cpu_usage;
575 sched->runavg_cpu_usage = (sched->runavg_cpu_usage * 9 + sched->cpu_usage) / 10; 610 sched->runavg_cpu_usage = (sched->runavg_cpu_usage * (sched->replay_repeat - 1) + sched->cpu_usage) / sched->replay_repeat;
576 611
577 sched->parent_cpu_usage = cpu_usage_1 - cpu_usage_0; 612 sched->parent_cpu_usage = cpu_usage_1 - cpu_usage_0;
578 if (!sched->runavg_parent_cpu_usage) 613 if (!sched->runavg_parent_cpu_usage)
579 sched->runavg_parent_cpu_usage = sched->parent_cpu_usage; 614 sched->runavg_parent_cpu_usage = sched->parent_cpu_usage;
580 sched->runavg_parent_cpu_usage = (sched->runavg_parent_cpu_usage * 9 + 615 sched->runavg_parent_cpu_usage = (sched->runavg_parent_cpu_usage * (sched->replay_repeat - 1) +
581 sched->parent_cpu_usage)/10; 616 sched->parent_cpu_usage)/sched->replay_repeat;
582 617
583 ret = pthread_mutex_lock(&sched->start_work_mutex); 618 ret = pthread_mutex_lock(&sched->start_work_mutex);
584 BUG_ON(ret); 619 BUG_ON(ret);
@@ -610,7 +645,7 @@ static void run_one_test(struct perf_sched *sched)
610 sched->sum_fluct += fluct; 645 sched->sum_fluct += fluct;
611 if (!sched->run_avg) 646 if (!sched->run_avg)
612 sched->run_avg = delta; 647 sched->run_avg = delta;
613 sched->run_avg = (sched->run_avg * 9 + delta) / 10; 648 sched->run_avg = (sched->run_avg * (sched->replay_repeat - 1) + delta) / sched->replay_repeat;
614 649
615 printf("#%-3ld: %0.3f, ", sched->nr_runs, (double)delta / 1000000.0); 650 printf("#%-3ld: %0.3f, ", sched->nr_runs, (double)delta / 1000000.0);
616 651
@@ -831,7 +866,7 @@ static int thread_atoms_insert(struct perf_sched *sched, struct thread *thread)
831 return -1; 866 return -1;
832 } 867 }
833 868
834 atoms->thread = thread; 869 atoms->thread = thread__get(thread);
835 INIT_LIST_HEAD(&atoms->work_list); 870 INIT_LIST_HEAD(&atoms->work_list);
836 __thread_latency_insert(&sched->atom_root, atoms, &sched->cmp_pid); 871 __thread_latency_insert(&sched->atom_root, atoms, &sched->cmp_pid);
837 return 0; 872 return 0;
@@ -1439,8 +1474,7 @@ static int perf_sched__process_tracepoint_sample(struct perf_tool *tool __maybe_
1439 return err; 1474 return err;
1440} 1475}
1441 1476
1442static int perf_sched__read_events(struct perf_sched *sched, 1477static int perf_sched__read_events(struct perf_sched *sched)
1443 struct perf_session **psession)
1444{ 1478{
1445 const struct perf_evsel_str_handler handlers[] = { 1479 const struct perf_evsel_str_handler handlers[] = {
1446 { "sched:sched_switch", process_sched_switch_event, }, 1480 { "sched:sched_switch", process_sched_switch_event, },
@@ -1453,7 +1487,9 @@ static int perf_sched__read_events(struct perf_sched *sched,
1453 struct perf_data_file file = { 1487 struct perf_data_file file = {
1454 .path = input_name, 1488 .path = input_name,
1455 .mode = PERF_DATA_MODE_READ, 1489 .mode = PERF_DATA_MODE_READ,
1490 .force = sched->force,
1456 }; 1491 };
1492 int rc = -1;
1457 1493
1458 session = perf_session__new(&file, false, &sched->tool); 1494 session = perf_session__new(&file, false, &sched->tool);
1459 if (session == NULL) { 1495 if (session == NULL) {
@@ -1467,27 +1503,21 @@ static int perf_sched__read_events(struct perf_sched *sched,
1467 goto out_delete; 1503 goto out_delete;
1468 1504
1469 if (perf_session__has_traces(session, "record -R")) { 1505 if (perf_session__has_traces(session, "record -R")) {
1470 int err = perf_session__process_events(session, &sched->tool); 1506 int err = perf_session__process_events(session);
1471 if (err) { 1507 if (err) {
1472 pr_err("Failed to process events, error %d", err); 1508 pr_err("Failed to process events, error %d", err);
1473 goto out_delete; 1509 goto out_delete;
1474 } 1510 }
1475 1511
1476 sched->nr_events = session->stats.nr_events[0]; 1512 sched->nr_events = session->evlist->stats.nr_events[0];
1477 sched->nr_lost_events = session->stats.total_lost; 1513 sched->nr_lost_events = session->evlist->stats.total_lost;
1478 sched->nr_lost_chunks = session->stats.nr_events[PERF_RECORD_LOST]; 1514 sched->nr_lost_chunks = session->evlist->stats.nr_events[PERF_RECORD_LOST];
1479 } 1515 }
1480 1516
1481 if (psession) 1517 rc = 0;
1482 *psession = session;
1483 else
1484 perf_session__delete(session);
1485
1486 return 0;
1487
1488out_delete: 1518out_delete:
1489 perf_session__delete(session); 1519 perf_session__delete(session);
1490 return -1; 1520 return rc;
1491} 1521}
1492 1522
1493static void print_bad_events(struct perf_sched *sched) 1523static void print_bad_events(struct perf_sched *sched)
@@ -1515,12 +1545,10 @@ static void print_bad_events(struct perf_sched *sched)
1515static int perf_sched__lat(struct perf_sched *sched) 1545static int perf_sched__lat(struct perf_sched *sched)
1516{ 1546{
1517 struct rb_node *next; 1547 struct rb_node *next;
1518 struct perf_session *session;
1519 1548
1520 setup_pager(); 1549 setup_pager();
1521 1550
1522 /* save session -- references to threads are held in work_list */ 1551 if (perf_sched__read_events(sched))
1523 if (perf_sched__read_events(sched, &session))
1524 return -1; 1552 return -1;
1525 1553
1526 perf_sched__sort_lat(sched); 1554 perf_sched__sort_lat(sched);
@@ -1537,6 +1565,7 @@ static int perf_sched__lat(struct perf_sched *sched)
1537 work_list = rb_entry(next, struct work_atoms, node); 1565 work_list = rb_entry(next, struct work_atoms, node);
1538 output_lat_thread(sched, work_list); 1566 output_lat_thread(sched, work_list);
1539 next = rb_next(next); 1567 next = rb_next(next);
1568 thread__zput(work_list->thread);
1540 } 1569 }
1541 1570
1542 printf(" -----------------------------------------------------------------------------------------------------------------\n"); 1571 printf(" -----------------------------------------------------------------------------------------------------------------\n");
@@ -1548,7 +1577,6 @@ static int perf_sched__lat(struct perf_sched *sched)
1548 print_bad_events(sched); 1577 print_bad_events(sched);
1549 printf("\n"); 1578 printf("\n");
1550 1579
1551 perf_session__delete(session);
1552 return 0; 1580 return 0;
1553} 1581}
1554 1582
@@ -1557,7 +1585,7 @@ static int perf_sched__map(struct perf_sched *sched)
1557 sched->max_cpu = sysconf(_SC_NPROCESSORS_CONF); 1585 sched->max_cpu = sysconf(_SC_NPROCESSORS_CONF);
1558 1586
1559 setup_pager(); 1587 setup_pager();
1560 if (perf_sched__read_events(sched, NULL)) 1588 if (perf_sched__read_events(sched))
1561 return -1; 1589 return -1;
1562 print_bad_events(sched); 1590 print_bad_events(sched);
1563 return 0; 1591 return 0;
@@ -1572,7 +1600,7 @@ static int perf_sched__replay(struct perf_sched *sched)
1572 1600
1573 test_calibrations(sched); 1601 test_calibrations(sched);
1574 1602
1575 if (perf_sched__read_events(sched, NULL)) 1603 if (perf_sched__read_events(sched))
1576 return -1; 1604 return -1;
1577 1605
1578 printf("nr_run_events: %ld\n", sched->nr_run_events); 1606 printf("nr_run_events: %ld\n", sched->nr_run_events);
@@ -1693,6 +1721,7 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
1693 "be more verbose (show symbol address, etc)"), 1721 "be more verbose (show symbol address, etc)"),
1694 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 1722 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
1695 "dump raw trace in ASCII"), 1723 "dump raw trace in ASCII"),
1724 OPT_BOOLEAN('f', "force", &sched.force, "don't complain, do it"),
1696 OPT_END() 1725 OPT_END()
1697 }; 1726 };
1698 const struct option sched_options[] = { 1727 const struct option sched_options[] = {
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index ce304dfd962a..58f10b8e6ff2 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -446,9 +446,9 @@ static void print_sample_bts(union perf_event *event,
446} 446}
447 447
448static void process_event(union perf_event *event, struct perf_sample *sample, 448static void process_event(union perf_event *event, struct perf_sample *sample,
449 struct perf_evsel *evsel, struct thread *thread, 449 struct perf_evsel *evsel, struct addr_location *al)
450 struct addr_location *al)
451{ 450{
451 struct thread *thread = al->thread;
452 struct perf_event_attr *attr = &evsel->attr; 452 struct perf_event_attr *attr = &evsel->attr;
453 453
454 if (output[attr->type].fields == 0) 454 if (output[attr->type].fields == 0)
@@ -549,14 +549,6 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
549 struct machine *machine) 549 struct machine *machine)
550{ 550{
551 struct addr_location al; 551 struct addr_location al;
552 struct thread *thread = machine__findnew_thread(machine, sample->pid,
553 sample->tid);
554
555 if (thread == NULL) {
556 pr_debug("problem processing %d event, skipping it.\n",
557 event->header.type);
558 return -1;
559 }
560 552
561 if (debug_mode) { 553 if (debug_mode) {
562 if (sample->time < last_timestamp) { 554 if (sample->time < last_timestamp) {
@@ -581,7 +573,7 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
581 if (cpu_list && !test_bit(sample->cpu, cpu_bitmap)) 573 if (cpu_list && !test_bit(sample->cpu, cpu_bitmap))
582 return 0; 574 return 0;
583 575
584 scripting_ops->process_event(event, sample, evsel, thread, &al); 576 scripting_ops->process_event(event, sample, evsel, &al);
585 577
586 return 0; 578 return 0;
587} 579}
@@ -800,7 +792,7 @@ static int __cmd_script(struct perf_script *script)
800 script->tool.mmap2 = process_mmap2_event; 792 script->tool.mmap2 = process_mmap2_event;
801 } 793 }
802 794
803 ret = perf_session__process_events(script->session, &script->tool); 795 ret = perf_session__process_events(script->session);
804 796
805 if (debug_mode) 797 if (debug_mode)
806 pr_err("Misordered timestamps: %" PRIu64 "\n", nr_unordered); 798 pr_err("Misordered timestamps: %" PRIu64 "\n", nr_unordered);
@@ -1523,6 +1515,9 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1523 .ordering_requires_timestamps = true, 1515 .ordering_requires_timestamps = true,
1524 }, 1516 },
1525 }; 1517 };
1518 struct perf_data_file file = {
1519 .mode = PERF_DATA_MODE_READ,
1520 };
1526 const struct option options[] = { 1521 const struct option options[] = {
1527 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 1522 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
1528 "dump raw trace in ASCII"), 1523 "dump raw trace in ASCII"),
@@ -1550,7 +1545,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1550 "When printing symbols do not display call chain"), 1545 "When printing symbols do not display call chain"),
1551 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", 1546 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
1552 "Look for files with symbols relative to this directory"), 1547 "Look for files with symbols relative to this directory"),
1553 OPT_CALLBACK('f', "fields", NULL, "str", 1548 OPT_CALLBACK('F', "fields", NULL, "str",
1554 "comma separated output fields prepend with 'type:'. " 1549 "comma separated output fields prepend with 'type:'. "
1555 "Valid types: hw,sw,trace,raw. " 1550 "Valid types: hw,sw,trace,raw. "
1556 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso," 1551 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
@@ -1562,6 +1557,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"), 1557 OPT_STRING('C', "cpu", &cpu_list, "cpu", "list of cpus to profile"),
1563 OPT_STRING('c', "comms", &symbol_conf.comm_list_str, "comm[,comm...]", 1558 OPT_STRING('c', "comms", &symbol_conf.comm_list_str, "comm[,comm...]",
1564 "only display events for these comms"), 1559 "only display events for these comms"),
1560 OPT_STRING(0, "pid", &symbol_conf.pid_list_str, "pid[,pid...]",
1561 "only consider symbols in these pids"),
1562 OPT_STRING(0, "tid", &symbol_conf.tid_list_str, "tid[,tid...]",
1563 "only consider symbols in these tids"),
1565 OPT_BOOLEAN('I', "show-info", &show_full_info, 1564 OPT_BOOLEAN('I', "show-info", &show_full_info,
1566 "display extended information from perf.data file"), 1565 "display extended information from perf.data file"),
1567 OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path, 1566 OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path,
@@ -1570,9 +1569,11 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1570 "Show the fork/comm/exit events"), 1569 "Show the fork/comm/exit events"),
1571 OPT_BOOLEAN('\0', "show-mmap-events", &script.show_mmap_events, 1570 OPT_BOOLEAN('\0', "show-mmap-events", &script.show_mmap_events,
1572 "Show the mmap events"), 1571 "Show the mmap events"),
1572 OPT_BOOLEAN('f', "force", &file.force, "don't complain, do it"),
1573 OPT_END() 1573 OPT_END()
1574 }; 1574 };
1575 const char * const script_usage[] = { 1575 const char * const script_subcommands[] = { "record", "report", NULL };
1576 const char *script_usage[] = {
1576 "perf script [<options>]", 1577 "perf script [<options>]",
1577 "perf script [<options>] record <script> [<record-options>] <command>", 1578 "perf script [<options>] record <script> [<record-options>] <command>",
1578 "perf script [<options>] report <script> [script-args]", 1579 "perf script [<options>] report <script> [script-args]",
@@ -1580,13 +1581,10 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1580 "perf script [<options>] <top-script> [script-args]", 1581 "perf script [<options>] <top-script> [script-args]",
1581 NULL 1582 NULL
1582 }; 1583 };
1583 struct perf_data_file file = {
1584 .mode = PERF_DATA_MODE_READ,
1585 };
1586 1584
1587 setup_scripting(); 1585 setup_scripting();
1588 1586
1589 argc = parse_options(argc, argv, options, script_usage, 1587 argc = parse_options_subcommand(argc, argv, options, script_subcommands, script_usage,
1590 PARSE_OPT_STOP_AT_NON_OPTION); 1588 PARSE_OPT_STOP_AT_NON_OPTION);
1591 1589
1592 file.path = input_name; 1590 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..e50fe1187b0b 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -67,6 +67,7 @@ struct timechart {
67 skip_eagain; 67 skip_eagain;
68 u64 min_time, 68 u64 min_time,
69 merge_dist; 69 merge_dist;
70 bool force;
70}; 71};
71 72
72struct per_pidcomm; 73struct per_pidcomm;
@@ -1598,6 +1599,7 @@ static int __cmd_timechart(struct timechart *tchart, const char *output_name)
1598 struct perf_data_file file = { 1599 struct perf_data_file file = {
1599 .path = input_name, 1600 .path = input_name,
1600 .mode = PERF_DATA_MODE_READ, 1601 .mode = PERF_DATA_MODE_READ,
1602 .force = tchart->force,
1601 }; 1603 };
1602 1604
1603 struct perf_session *session = perf_session__new(&file, false, 1605 struct perf_session *session = perf_session__new(&file, false,
@@ -1623,7 +1625,7 @@ static int __cmd_timechart(struct timechart *tchart, const char *output_name)
1623 goto out_delete; 1625 goto out_delete;
1624 } 1626 }
1625 1627
1626 ret = perf_session__process_events(session, &tchart->tool); 1628 ret = perf_session__process_events(session);
1627 if (ret) 1629 if (ret)
1628 goto out_delete; 1630 goto out_delete;
1629 1631
@@ -1956,9 +1958,11 @@ int cmd_timechart(int argc, const char **argv,
1956 OPT_CALLBACK(0, "io-merge-dist", &tchart.merge_dist, "time", 1958 OPT_CALLBACK(0, "io-merge-dist", &tchart.merge_dist, "time",
1957 "merge events that are merge-dist us apart", 1959 "merge events that are merge-dist us apart",
1958 parse_time), 1960 parse_time),
1961 OPT_BOOLEAN('f', "force", &tchart.force, "don't complain, do it"),
1959 OPT_END() 1962 OPT_END()
1960 }; 1963 };
1961 const char * const timechart_usage[] = { 1964 const char * const timechart_subcommands[] = { "record", NULL };
1965 const char *timechart_usage[] = {
1962 "perf timechart [<options>] {record}", 1966 "perf timechart [<options>] {record}",
1963 NULL 1967 NULL
1964 }; 1968 };
@@ -1976,8 +1980,8 @@ int cmd_timechart(int argc, const char **argv,
1976 "perf timechart record [<options>]", 1980 "perf timechart record [<options>]",
1977 NULL 1981 NULL
1978 }; 1982 };
1979 argc = parse_options(argc, argv, timechart_options, timechart_usage, 1983 argc = parse_options_subcommand(argc, argv, timechart_options, timechart_subcommands,
1980 PARSE_OPT_STOP_AT_NON_OPTION); 1984 timechart_usage, PARSE_OPT_STOP_AT_NON_OPTION);
1981 1985
1982 if (tchart.power_only && tchart.tasks_only) { 1986 if (tchart.power_only && tchart.tasks_only) {
1983 pr_err("-P and -T options cannot be used at the same time.\n"); 1987 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..e124741be187 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 {
@@ -1243,6 +1254,7 @@ struct trace {
1243 bool show_comm; 1254 bool show_comm;
1244 bool show_tool_stats; 1255 bool show_tool_stats;
1245 bool trace_syscalls; 1256 bool trace_syscalls;
1257 bool force;
1246 int trace_pgfaults; 1258 int trace_pgfaults;
1247}; 1259};
1248 1260
@@ -1433,14 +1445,14 @@ static int syscall__set_arg_fmts(struct syscall *sc)
1433 struct format_field *field; 1445 struct format_field *field;
1434 int idx = 0; 1446 int idx = 0;
1435 1447
1436 sc->arg_scnprintf = calloc(sc->tp_format->format.nr_fields - 1, sizeof(void *)); 1448 sc->arg_scnprintf = calloc(sc->nr_args, sizeof(void *));
1437 if (sc->arg_scnprintf == NULL) 1449 if (sc->arg_scnprintf == NULL)
1438 return -1; 1450 return -1;
1439 1451
1440 if (sc->fmt) 1452 if (sc->fmt)
1441 sc->arg_parm = sc->fmt->arg_parm; 1453 sc->arg_parm = sc->fmt->arg_parm;
1442 1454
1443 for (field = sc->tp_format->format.fields->next; field; field = field->next) { 1455 for (field = sc->args; field; field = field->next) {
1444 if (sc->fmt && sc->fmt->arg_scnprintf[idx]) 1456 if (sc->fmt && sc->fmt->arg_scnprintf[idx])
1445 sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx]; 1457 sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx];
1446 else if (field->flags & FIELD_IS_POINTER) 1458 else if (field->flags & FIELD_IS_POINTER)
@@ -1506,18 +1518,37 @@ static int trace__read_syscall_info(struct trace *trace, int id)
1506 if (sc->tp_format == NULL) 1518 if (sc->tp_format == NULL)
1507 return -1; 1519 return -1;
1508 1520
1521 sc->args = sc->tp_format->format.fields;
1522 sc->nr_args = sc->tp_format->format.nr_fields;
1523 /* drop nr field - not relevant here; does not exist on older kernels */
1524 if (sc->args && strcmp(sc->args->name, "nr") == 0) {
1525 sc->args = sc->args->next;
1526 --sc->nr_args;
1527 }
1528
1509 sc->is_exit = !strcmp(name, "exit_group") || !strcmp(name, "exit"); 1529 sc->is_exit = !strcmp(name, "exit_group") || !strcmp(name, "exit");
1510 1530
1511 return syscall__set_arg_fmts(sc); 1531 return syscall__set_arg_fmts(sc);
1512} 1532}
1513 1533
1534/*
1535 * args is to be interpreted as a series of longs but we need to handle
1536 * 8-byte unaligned accesses. args points to raw_data within the event
1537 * and raw_data is guaranteed to be 8-byte unaligned because it is
1538 * preceded by raw_size which is a u32. So we need to copy args to a temp
1539 * variable to read it. Most notably this avoids extended load instructions
1540 * on unaligned addresses
1541 */
1542
1514static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size, 1543static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
1515 unsigned long *args, struct trace *trace, 1544 unsigned char *args, struct trace *trace,
1516 struct thread *thread) 1545 struct thread *thread)
1517{ 1546{
1518 size_t printed = 0; 1547 size_t printed = 0;
1548 unsigned char *p;
1549 unsigned long val;
1519 1550
1520 if (sc->tp_format != NULL) { 1551 if (sc->args != NULL) {
1521 struct format_field *field; 1552 struct format_field *field;
1522 u8 bit = 1; 1553 u8 bit = 1;
1523 struct syscall_arg arg = { 1554 struct syscall_arg arg = {
@@ -1527,16 +1558,21 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
1527 .thread = thread, 1558 .thread = thread,
1528 }; 1559 };
1529 1560
1530 for (field = sc->tp_format->format.fields->next; field; 1561 for (field = sc->args; field;
1531 field = field->next, ++arg.idx, bit <<= 1) { 1562 field = field->next, ++arg.idx, bit <<= 1) {
1532 if (arg.mask & bit) 1563 if (arg.mask & bit)
1533 continue; 1564 continue;
1565
1566 /* special care for unaligned accesses */
1567 p = args + sizeof(unsigned long) * arg.idx;
1568 memcpy(&val, p, sizeof(val));
1569
1534 /* 1570 /*
1535 * Suppress this argument if its value is zero and 1571 * Suppress this argument if its value is zero and
1536 * and we don't have a string associated in an 1572 * and we don't have a string associated in an
1537 * strarray for it. 1573 * strarray for it.
1538 */ 1574 */
1539 if (args[arg.idx] == 0 && 1575 if (val == 0 &&
1540 !(sc->arg_scnprintf && 1576 !(sc->arg_scnprintf &&
1541 sc->arg_scnprintf[arg.idx] == SCA_STRARRAY && 1577 sc->arg_scnprintf[arg.idx] == SCA_STRARRAY &&
1542 sc->arg_parm[arg.idx])) 1578 sc->arg_parm[arg.idx]))
@@ -1545,23 +1581,26 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
1545 printed += scnprintf(bf + printed, size - printed, 1581 printed += scnprintf(bf + printed, size - printed,
1546 "%s%s: ", printed ? ", " : "", field->name); 1582 "%s%s: ", printed ? ", " : "", field->name);
1547 if (sc->arg_scnprintf && sc->arg_scnprintf[arg.idx]) { 1583 if (sc->arg_scnprintf && sc->arg_scnprintf[arg.idx]) {
1548 arg.val = args[arg.idx]; 1584 arg.val = val;
1549 if (sc->arg_parm) 1585 if (sc->arg_parm)
1550 arg.parm = sc->arg_parm[arg.idx]; 1586 arg.parm = sc->arg_parm[arg.idx];
1551 printed += sc->arg_scnprintf[arg.idx](bf + printed, 1587 printed += sc->arg_scnprintf[arg.idx](bf + printed,
1552 size - printed, &arg); 1588 size - printed, &arg);
1553 } else { 1589 } else {
1554 printed += scnprintf(bf + printed, size - printed, 1590 printed += scnprintf(bf + printed, size - printed,
1555 "%ld", args[arg.idx]); 1591 "%ld", val);
1556 } 1592 }
1557 } 1593 }
1558 } else { 1594 } else {
1559 int i = 0; 1595 int i = 0;
1560 1596
1561 while (i < 6) { 1597 while (i < 6) {
1598 /* special care for unaligned accesses */
1599 p = args + sizeof(unsigned long) * i;
1600 memcpy(&val, p, sizeof(val));
1562 printed += scnprintf(bf + printed, size - printed, 1601 printed += scnprintf(bf + printed, size - printed,
1563 "%sarg%d: %ld", 1602 "%sarg%d: %ld",
1564 printed ? ", " : "", i, args[i]); 1603 printed ? ", " : "", i, val);
1565 ++i; 1604 ++i;
1566 } 1605 }
1567 } 1606 }
@@ -1642,6 +1681,29 @@ static void thread__update_stats(struct thread_trace *ttrace,
1642 update_stats(stats, duration); 1681 update_stats(stats, duration);
1643} 1682}
1644 1683
1684static int trace__printf_interrupted_entry(struct trace *trace, struct perf_sample *sample)
1685{
1686 struct thread_trace *ttrace;
1687 u64 duration;
1688 size_t printed;
1689
1690 if (trace->current == NULL)
1691 return 0;
1692
1693 ttrace = thread__priv(trace->current);
1694
1695 if (!ttrace->entry_pending)
1696 return 0;
1697
1698 duration = sample->time - ttrace->entry_time;
1699
1700 printed = trace__fprintf_entry_head(trace, trace->current, duration, sample->time, trace->output);
1701 printed += fprintf(trace->output, "%-70s) ...\n", ttrace->entry_str);
1702 ttrace->entry_pending = false;
1703
1704 return printed;
1705}
1706
1645static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel, 1707static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
1646 union perf_event *event __maybe_unused, 1708 union perf_event *event __maybe_unused,
1647 struct perf_sample *sample) 1709 struct perf_sample *sample)
@@ -1673,6 +1735,9 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
1673 return -1; 1735 return -1;
1674 } 1736 }
1675 1737
1738 if (!trace->summary_only)
1739 trace__printf_interrupted_entry(trace, sample);
1740
1676 ttrace->entry_time = sample->time; 1741 ttrace->entry_time = sample->time;
1677 msg = ttrace->entry_str; 1742 msg = ttrace->entry_str;
1678 printed += scnprintf(msg + printed, 1024 - printed, "%s(", sc->name); 1743 printed += scnprintf(msg + printed, 1024 - printed, "%s(", sc->name);
@@ -1688,6 +1753,11 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
1688 } else 1753 } else
1689 ttrace->entry_pending = true; 1754 ttrace->entry_pending = true;
1690 1755
1756 if (trace->current != thread) {
1757 thread__put(trace->current);
1758 trace->current = thread__get(thread);
1759 }
1760
1691 return 0; 1761 return 0;
1692} 1762}
1693 1763
@@ -1805,6 +1875,28 @@ out_dump:
1805 return 0; 1875 return 0;
1806} 1876}
1807 1877
1878static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
1879 union perf_event *event __maybe_unused,
1880 struct perf_sample *sample)
1881{
1882 trace__printf_interrupted_entry(trace, sample);
1883 trace__fprintf_tstamp(trace, sample->time, trace->output);
1884
1885 if (trace->trace_syscalls)
1886 fprintf(trace->output, "( ): ");
1887
1888 fprintf(trace->output, "%s:", evsel->name);
1889
1890 if (evsel->tp_format) {
1891 event_format__fprintf(evsel->tp_format, sample->cpu,
1892 sample->raw_data, sample->raw_size,
1893 trace->output);
1894 }
1895
1896 fprintf(trace->output, ")\n");
1897 return 0;
1898}
1899
1808static void print_location(FILE *f, struct perf_sample *sample, 1900static void print_location(FILE *f, struct perf_sample *sample,
1809 struct addr_location *al, 1901 struct addr_location *al,
1810 bool print_dso, bool print_sym) 1902 bool print_dso, bool print_sym)
@@ -2037,10 +2129,39 @@ static int perf_evlist__add_pgfault(struct perf_evlist *evlist,
2037 return 0; 2129 return 0;
2038} 2130}
2039 2131
2040static int trace__run(struct trace *trace, int argc, const char **argv) 2132static void trace__handle_event(struct trace *trace, union perf_event *event, struct perf_sample *sample)
2041{ 2133{
2042 struct perf_evlist *evlist = perf_evlist__new(); 2134 const u32 type = event->header.type;
2043 struct perf_evsel *evsel; 2135 struct perf_evsel *evsel;
2136
2137 if (!trace->full_time && trace->base_time == 0)
2138 trace->base_time = sample->time;
2139
2140 if (type != PERF_RECORD_SAMPLE) {
2141 trace__process_event(trace, trace->host, event, sample);
2142 return;
2143 }
2144
2145 evsel = perf_evlist__id2evsel(trace->evlist, sample->id);
2146 if (evsel == NULL) {
2147 fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...\n", sample->id);
2148 return;
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 } else {
2157 tracepoint_handler handler = evsel->handler;
2158 handler(trace, evsel, event, sample);
2159 }
2160}
2161
2162static int trace__run(struct trace *trace, int argc, const char **argv)
2163{
2164 struct perf_evlist *evlist = trace->evlist;
2044 int err = -1, i; 2165 int err = -1, i;
2045 unsigned long before; 2166 unsigned long before;
2046 const bool forks = argc > 0; 2167 const bool forks = argc > 0;
@@ -2048,11 +2169,6 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
2048 2169
2049 trace->live = true; 2170 trace->live = true;
2050 2171
2051 if (evlist == NULL) {
2052 fprintf(trace->output, "Not enough memory to run!\n");
2053 goto out;
2054 }
2055
2056 if (trace->trace_syscalls && 2172 if (trace->trace_syscalls &&
2057 perf_evlist__add_syscall_newtp(evlist, trace__sys_enter, 2173 perf_evlist__add_syscall_newtp(evlist, trace__sys_enter,
2058 trace__sys_exit)) 2174 trace__sys_exit))
@@ -2105,16 +2221,34 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
2105 if (err < 0) 2221 if (err < 0)
2106 goto out_error_open; 2222 goto out_error_open;
2107 2223
2224 /*
2225 * Better not use !target__has_task() here because we need to cover the
2226 * case where no threads were specified in the command line, but a
2227 * workload was, and in that case we will fill in the thread_map when
2228 * we fork the workload in perf_evlist__prepare_workload.
2229 */
2230 if (trace->filter_pids.nr > 0)
2231 err = perf_evlist__set_filter_pids(evlist, trace->filter_pids.nr, trace->filter_pids.entries);
2232 else if (evlist->threads->map[0] == -1)
2233 err = perf_evlist__set_filter_pid(evlist, getpid());
2234
2235 if (err < 0) {
2236 printf("err=%d,%s\n", -err, strerror(-err));
2237 exit(1);
2238 }
2239
2108 err = perf_evlist__mmap(evlist, trace->opts.mmap_pages, false); 2240 err = perf_evlist__mmap(evlist, trace->opts.mmap_pages, false);
2109 if (err < 0) 2241 if (err < 0)
2110 goto out_error_mmap; 2242 goto out_error_mmap;
2111 2243
2112 perf_evlist__enable(evlist);
2113
2114 if (forks) 2244 if (forks)
2115 perf_evlist__start_workload(evlist); 2245 perf_evlist__start_workload(evlist);
2246 else
2247 perf_evlist__enable(evlist);
2116 2248
2117 trace->multiple_threads = evlist->threads->map[0] == -1 || evlist->threads->nr > 1; 2249 trace->multiple_threads = evlist->threads->map[0] == -1 ||
2250 evlist->threads->nr > 1 ||
2251 perf_evlist__first(evlist)->attr.inherit;
2118again: 2252again:
2119 before = trace->nr_events; 2253 before = trace->nr_events;
2120 2254
@@ -2122,8 +2256,6 @@ again:
2122 union perf_event *event; 2256 union perf_event *event;
2123 2257
2124 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { 2258 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; 2259 struct perf_sample sample;
2128 2260
2129 ++trace->nr_events; 2261 ++trace->nr_events;
@@ -2134,30 +2266,7 @@ again:
2134 goto next_event; 2266 goto next_event;
2135 } 2267 }
2136 2268
2137 if (!trace->full_time && trace->base_time == 0) 2269 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: 2270next_event:
2162 perf_evlist__mmap_consume(evlist, i); 2271 perf_evlist__mmap_consume(evlist, i);
2163 2272
@@ -2180,6 +2289,8 @@ next_event:
2180 } 2289 }
2181 2290
2182out_disable: 2291out_disable:
2292 thread__zput(trace->current);
2293
2183 perf_evlist__disable(evlist); 2294 perf_evlist__disable(evlist);
2184 2295
2185 if (!err) { 2296 if (!err) {
@@ -2197,7 +2308,7 @@ out_disable:
2197 2308
2198out_delete_evlist: 2309out_delete_evlist:
2199 perf_evlist__delete(evlist); 2310 perf_evlist__delete(evlist);
2200out: 2311 trace->evlist = NULL;
2201 trace->live = false; 2312 trace->live = false;
2202 return err; 2313 return err;
2203{ 2314{
@@ -2235,6 +2346,7 @@ static int trace__replay(struct trace *trace)
2235 struct perf_data_file file = { 2346 struct perf_data_file file = {
2236 .path = input_name, 2347 .path = input_name,
2237 .mode = PERF_DATA_MODE_READ, 2348 .mode = PERF_DATA_MODE_READ,
2349 .force = trace->force,
2238 }; 2350 };
2239 struct perf_session *session; 2351 struct perf_session *session;
2240 struct perf_evsel *evsel; 2352 struct perf_evsel *evsel;
@@ -2309,7 +2421,7 @@ static int trace__replay(struct trace *trace)
2309 2421
2310 setup_pager(); 2422 setup_pager();
2311 2423
2312 err = perf_session__process_events(session, &trace->tool); 2424 err = perf_session__process_events(session);
2313 if (err) 2425 if (err)
2314 pr_err("Failed to process events, error %d", err); 2426 pr_err("Failed to process events, error %d", err);
2315 2427
@@ -2434,6 +2546,38 @@ static int trace__set_duration(const struct option *opt, const char *str,
2434 return 0; 2546 return 0;
2435} 2547}
2436 2548
2549static int trace__set_filter_pids(const struct option *opt, const char *str,
2550 int unset __maybe_unused)
2551{
2552 int ret = -1;
2553 size_t i;
2554 struct trace *trace = opt->value;
2555 /*
2556 * FIXME: introduce a intarray class, plain parse csv and create a
2557 * { int nr, int entries[] } struct...
2558 */
2559 struct intlist *list = intlist__new(str);
2560
2561 if (list == NULL)
2562 return -1;
2563
2564 i = trace->filter_pids.nr = intlist__nr_entries(list) + 1;
2565 trace->filter_pids.entries = calloc(i, sizeof(pid_t));
2566
2567 if (trace->filter_pids.entries == NULL)
2568 goto out;
2569
2570 trace->filter_pids.entries[0] = getpid();
2571
2572 for (i = 1; i < trace->filter_pids.nr; ++i)
2573 trace->filter_pids.entries[i] = intlist__entry(list, i - 1)->i;
2574
2575 intlist__delete(list);
2576 ret = 0;
2577out:
2578 return ret;
2579}
2580
2437static int trace__open_output(struct trace *trace, const char *filename) 2581static int trace__open_output(struct trace *trace, const char *filename)
2438{ 2582{
2439 struct stat st; 2583 struct stat st;
@@ -2468,9 +2612,17 @@ static int parse_pagefaults(const struct option *opt, const char *str,
2468 return 0; 2612 return 0;
2469} 2613}
2470 2614
2615static void evlist__set_evsel_handler(struct perf_evlist *evlist, void *handler)
2616{
2617 struct perf_evsel *evsel;
2618
2619 evlist__for_each(evlist, evsel)
2620 evsel->handler = handler;
2621}
2622
2471int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) 2623int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
2472{ 2624{
2473 const char * const trace_usage[] = { 2625 const char *trace_usage[] = {
2474 "perf trace [<options>] [<command>]", 2626 "perf trace [<options>] [<command>]",
2475 "perf trace [<options>] -- <command> [<options>]", 2627 "perf trace [<options>] -- <command> [<options>]",
2476 "perf trace record [<options>] [<command>]", 2628 "perf trace record [<options>] [<command>]",
@@ -2502,6 +2654,9 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
2502 const char *output_name = NULL; 2654 const char *output_name = NULL;
2503 const char *ev_qualifier_str = NULL; 2655 const char *ev_qualifier_str = NULL;
2504 const struct option trace_options[] = { 2656 const struct option trace_options[] = {
2657 OPT_CALLBACK(0, "event", &trace.evlist, "event",
2658 "event selector. use 'perf list' to list available events",
2659 parse_events_option),
2505 OPT_BOOLEAN(0, "comm", &trace.show_comm, 2660 OPT_BOOLEAN(0, "comm", &trace.show_comm,
2506 "show the thread COMM next to its id"), 2661 "show the thread COMM next to its id"),
2507 OPT_BOOLEAN(0, "tool_stats", &trace.show_tool_stats, "show tool stats"), 2662 OPT_BOOLEAN(0, "tool_stats", &trace.show_tool_stats, "show tool stats"),
@@ -2513,6 +2668,8 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
2513 "trace events on existing process id"), 2668 "trace events on existing process id"),
2514 OPT_STRING('t', "tid", &trace.opts.target.tid, "tid", 2669 OPT_STRING('t', "tid", &trace.opts.target.tid, "tid",
2515 "trace events on existing thread id"), 2670 "trace events on existing thread id"),
2671 OPT_CALLBACK(0, "filter-pids", &trace, "float",
2672 "show only events with duration > N.M ms", trace__set_filter_pids),
2516 OPT_BOOLEAN('a', "all-cpus", &trace.opts.target.system_wide, 2673 OPT_BOOLEAN('a', "all-cpus", &trace.opts.target.system_wide,
2517 "system-wide collection from all CPUs"), 2674 "system-wide collection from all CPUs"),
2518 OPT_STRING('C', "cpu", &trace.opts.target.cpu_list, "cpu", 2675 OPT_STRING('C', "cpu", &trace.opts.target.cpu_list, "cpu",
@@ -2538,19 +2695,36 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
2538 OPT_CALLBACK_DEFAULT('F', "pf", &trace.trace_pgfaults, "all|maj|min", 2695 OPT_CALLBACK_DEFAULT('F', "pf", &trace.trace_pgfaults, "all|maj|min",
2539 "Trace pagefaults", parse_pagefaults, "maj"), 2696 "Trace pagefaults", parse_pagefaults, "maj"),
2540 OPT_BOOLEAN(0, "syscalls", &trace.trace_syscalls, "Trace syscalls"), 2697 OPT_BOOLEAN(0, "syscalls", &trace.trace_syscalls, "Trace syscalls"),
2698 OPT_BOOLEAN('f', "force", &trace.force, "don't complain, do it"),
2541 OPT_END() 2699 OPT_END()
2542 }; 2700 };
2701 const char * const trace_subcommands[] = { "record", NULL };
2543 int err; 2702 int err;
2544 char bf[BUFSIZ]; 2703 char bf[BUFSIZ];
2545 2704
2546 argc = parse_options(argc, argv, trace_options, trace_usage, 2705 signal(SIGSEGV, sighandler_dump_stack);
2547 PARSE_OPT_STOP_AT_NON_OPTION); 2706 signal(SIGFPE, sighandler_dump_stack);
2707
2708 trace.evlist = perf_evlist__new();
2709 if (trace.evlist == NULL)
2710 return -ENOMEM;
2711
2712 if (trace.evlist == NULL) {
2713 pr_err("Not enough memory to run!\n");
2714 goto out;
2715 }
2716
2717 argc = parse_options_subcommand(argc, argv, trace_options, trace_subcommands,
2718 trace_usage, PARSE_OPT_STOP_AT_NON_OPTION);
2548 2719
2549 if (trace.trace_pgfaults) { 2720 if (trace.trace_pgfaults) {
2550 trace.opts.sample_address = true; 2721 trace.opts.sample_address = true;
2551 trace.opts.sample_time = true; 2722 trace.opts.sample_time = true;
2552 } 2723 }
2553 2724
2725 if (trace.evlist->nr_entries > 0)
2726 evlist__set_evsel_handler(trace.evlist, trace__event_handler);
2727
2554 if ((argc >= 1) && (strcmp(argv[0], "record") == 0)) 2728 if ((argc >= 1) && (strcmp(argv[0], "record") == 0))
2555 return trace__record(&trace, argc-1, &argv[1]); 2729 return trace__record(&trace, argc-1, &argv[1]);
2556 2730
@@ -2558,7 +2732,8 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
2558 if (trace.summary_only) 2732 if (trace.summary_only)
2559 trace.summary = trace.summary_only; 2733 trace.summary = trace.summary_only;
2560 2734
2561 if (!trace.trace_syscalls && !trace.trace_pgfaults) { 2735 if (!trace.trace_syscalls && !trace.trace_pgfaults &&
2736 trace.evlist->nr_entries == 0 /* Was --events used? */) {
2562 pr_err("Please specify something to trace.\n"); 2737 pr_err("Please specify something to trace.\n");
2563 return -1; 2738 return -1;
2564 } 2739 }
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..59a98c643240 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
98ifdef 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,18 @@ else
667 NO_PERF_READ_VDSOX32 := 1 598 NO_PERF_READ_VDSOX32 := 1
668endif 599endif
669 600
601ifdef 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 endif
611endif
612
670# Among the variables below, these: 613# Among the variables below, these:
671# perfexecdir 614# perfexecdir
672# template_dir 615# template_dir
@@ -699,7 +642,7 @@ sysconfdir = $(prefix)/etc
699ETC_PERFCONFIG = etc/perfconfig 642ETC_PERFCONFIG = etc/perfconfig
700endif 643endif
701ifndef lib 644ifndef lib
702ifeq ($(IS_X86_64),1) 645ifeq ($(ARCH)$(IS_64_BIT), x861)
703lib = lib64 646lib = lib64
704else 647else
705lib = lib 648lib = lib
@@ -735,83 +678,33 @@ plugindir=$(libdir)/traceevent/plugins
735plugindir_SQ= $(subst ','\'',$(plugindir)) 678plugindir_SQ= $(subst ','\'',$(plugindir))
736endif 679endif
737 680
738# 681print_var = $(eval $(print_var_code)) $(info $(MSG))
739# Print the result of the feature test: 682define 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))) 683 MSG = $(shell printf '...%30s: %s' $(1) $($(1)))
754endef 684endef
755 685
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) 686ifeq ($(VF),1)
790 display_lib := 1 687 $(call print_var,prefix)
791 display_vf := 1 688 $(call print_var,bindir)
792endif 689 $(call print_var,libdir)
793 690 $(call print_var,sysconfdir)
794ifeq ($(display_lib),1) 691 $(call print_var,LIBUNWIND_DIR)
692 $(call print_var,LIBDW_DIR)
795 $(info ) 693 $(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 694endif
814 695
815ifeq ($(display_lib),1) 696$(call detected_var,bindir_SQ)
816 $(info ) 697$(call detected_var,PYTHON_WORD)
817endif 698ifneq ($(OUTPUT),)
699$(call detected_var,OUTPUT)
700endif
701$(call detected_var,htmldir_SQ)
702$(call detected_var,infodir_SQ)
703$(call detected_var,mandir_SQ)
704$(call detected_var,ETC_PERFCONFIG_SQ)
705$(call detected_var,prefix_SQ)
706$(call detected_var,perfexecdir_SQ)
707$(call detected_var,LIBDIR)
708$(call detected_var,GTK_CFLAGS)
709$(call detected_var,PERL_EMBED_CCOPTS)
710$(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/feature-checks/.gitignore b/tools/perf/config/feature-checks/.gitignore
deleted file mode 100644
index 80f3da0c3515..000000000000
--- a/tools/perf/config/feature-checks/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
1*.d
2*.bin
diff --git a/tools/perf/config/feature-checks/Makefile b/tools/perf/config/feature-checks/Makefile
deleted file mode 100644
index b32ff3372514..000000000000
--- a/tools/perf/config/feature-checks/Makefile
+++ /dev/null
@@ -1,155 +0,0 @@
1
2FILES= \
3 test-all.bin \
4 test-backtrace.bin \
5 test-bionic.bin \
6 test-dwarf.bin \
7 test-fortify-source.bin \
8 test-sync-compare-and-swap.bin \
9 test-glibc.bin \
10 test-gtk2.bin \
11 test-gtk2-infobar.bin \
12 test-hello.bin \
13 test-libaudit.bin \
14 test-libbfd.bin \
15 test-liberty.bin \
16 test-liberty-z.bin \
17 test-cplus-demangle.bin \
18 test-libelf.bin \
19 test-libelf-getphdrnum.bin \
20 test-libelf-mmap.bin \
21 test-libnuma.bin \
22 test-libperl.bin \
23 test-libpython.bin \
24 test-libpython-version.bin \
25 test-libslang.bin \
26 test-libunwind.bin \
27 test-libunwind-debug-frame.bin \
28 test-pthread-attr-setaffinity-np.bin \
29 test-stackprotector-all.bin \
30 test-timerfd.bin \
31 test-libdw-dwarf-unwind.bin \
32 test-compile-32.bin \
33 test-compile-x32.bin \
34 test-zlib.bin
35
36CC := $(CROSS_COMPILE)gcc -MD
37PKG_CONFIG := $(CROSS_COMPILE)pkg-config
38
39all: $(FILES)
40
41BUILD = $(CC) $(CFLAGS) -o $(OUTPUT)$@ $(patsubst %.bin,%.c,$@) $(LDFLAGS)
42
43###############################
44
45test-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
47
48test-hello.bin:
49 $(BUILD)
50
51test-pthread-attr-setaffinity-np.bin:
52 $(BUILD) -D_GNU_SOURCE -Werror -lpthread
53
54test-stackprotector-all.bin:
55 $(BUILD) -Werror -fstack-protector-all
56
57test-fortify-source.bin:
58 $(BUILD) -O2 -Werror -D_FORTIFY_SOURCE=2
59
60test-bionic.bin:
61 $(BUILD)
62
63test-libelf.bin:
64 $(BUILD) -lelf
65
66test-glibc.bin:
67 $(BUILD)
68
69test-dwarf.bin:
70 $(BUILD) -ldw
71
72test-libelf-mmap.bin:
73 $(BUILD) -lelf
74
75test-libelf-getphdrnum.bin:
76 $(BUILD) -lelf
77
78test-libnuma.bin:
79 $(BUILD) -lnuma
80
81test-libunwind.bin:
82 $(BUILD) -lelf
83
84test-libunwind-debug-frame.bin:
85 $(BUILD) -lelf
86
87test-libaudit.bin:
88 $(BUILD) -laudit
89
90test-libslang.bin:
91 $(BUILD) -I/usr/include/slang -lslang
92
93test-gtk2.bin:
94 $(BUILD) $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null)
95
96test-gtk2-infobar.bin:
97 $(BUILD) $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null)
98
99grep-libs = $(filter -l%,$(1))
100strip-libs = $(filter-out -l%,$(1))
101
102PERL_EMBED_LDOPTS = $(shell perl -MExtUtils::Embed -e ldopts 2>/dev/null)
103PERL_EMBED_LDFLAGS = $(call strip-libs,$(PERL_EMBED_LDOPTS))
104PERL_EMBED_LIBADD = $(call grep-libs,$(PERL_EMBED_LDOPTS))
105PERL_EMBED_CCOPTS = `perl -MExtUtils::Embed -e ccopts 2>/dev/null`
106FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS)
107
108test-libperl.bin:
109 $(BUILD) $(FLAGS_PERL_EMBED)
110
111test-libpython.bin:
112 $(BUILD)
113
114test-libpython-version.bin:
115 $(BUILD)
116
117test-libbfd.bin:
118 $(BUILD) -DPACKAGE='"perf"' -lbfd -lz -liberty -ldl
119
120test-liberty.bin:
121 $(CC) -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty
122
123test-liberty-z.bin:
124 $(CC) -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty -lz
125
126test-cplus-demangle.bin:
127 $(BUILD) -liberty
128
129test-backtrace.bin:
130 $(BUILD)
131
132test-timerfd.bin:
133 $(BUILD)
134
135test-libdw-dwarf-unwind.bin:
136 $(BUILD)
137
138test-sync-compare-and-swap.bin:
139 $(BUILD) -Werror
140
141test-compile-32.bin:
142 $(CC) -m32 -o $(OUTPUT)$@ test-compile.c
143
144test-compile-x32.bin:
145 $(CC) -mx32 -o $(OUTPUT)$@ test-compile.c
146
147test-zlib.bin:
148 $(BUILD) -lz
149
150-include *.d
151
152###############################
153
154clean:
155 rm -f $(FILES) *.d
diff --git a/tools/perf/config/feature-checks/test-all.c b/tools/perf/config/feature-checks/test-all.c
deleted file mode 100644
index 6d4d09323922..000000000000
--- a/tools/perf/config/feature-checks/test-all.c
+++ /dev/null
@@ -1,131 +0,0 @@
1/*
2 * test-all.c: Try to build all the main testcases at once.
3 *
4 * A well-configured system will have all the prereqs installed, so we can speed
5 * up auto-detection on such systems.
6 */
7
8/*
9 * Quirk: Python and Perl headers cannot be in arbitrary places, so keep
10 * these 3 testcases at the top:
11 */
12#define main main_test_libpython
13# include "test-libpython.c"
14#undef main
15
16#define main main_test_libpython_version
17# include "test-libpython-version.c"
18#undef main
19
20#define main main_test_libperl
21# include "test-libperl.c"
22#undef main
23
24#define main main_test_hello
25# include "test-hello.c"
26#undef main
27
28#define main main_test_libelf
29# include "test-libelf.c"
30#undef main
31
32#define main main_test_libelf_mmap
33# include "test-libelf-mmap.c"
34#undef main
35
36#define main main_test_glibc
37# include "test-glibc.c"
38#undef main
39
40#define main main_test_dwarf
41# include "test-dwarf.c"
42#undef main
43
44#define main main_test_libelf_getphdrnum
45# include "test-libelf-getphdrnum.c"
46#undef main
47
48#define main main_test_libunwind
49# include "test-libunwind.c"
50#undef main
51
52#define main main_test_libaudit
53# include "test-libaudit.c"
54#undef main
55
56#define main main_test_libslang
57# include "test-libslang.c"
58#undef main
59
60#define main main_test_gtk2
61# include "test-gtk2.c"
62#undef main
63
64#define main main_test_gtk2_infobar
65# include "test-gtk2-infobar.c"
66#undef main
67
68#define main main_test_libbfd
69# include "test-libbfd.c"
70#undef main
71
72#define main main_test_backtrace
73# include "test-backtrace.c"
74#undef main
75
76#define main main_test_libnuma
77# include "test-libnuma.c"
78#undef main
79
80#define main main_test_timerfd
81# include "test-timerfd.c"
82#undef main
83
84#define main main_test_stackprotector_all
85# include "test-stackprotector-all.c"
86#undef main
87
88#define main main_test_libdw_dwarf_unwind
89# include "test-libdw-dwarf-unwind.c"
90#undef main
91
92#define main main_test_sync_compare_and_swap
93# include "test-sync-compare-and-swap.c"
94#undef main
95
96#define main main_test_zlib
97# include "test-zlib.c"
98#undef main
99
100#define main main_test_pthread_attr_setaffinity_np
101# include "test-pthread_attr_setaffinity_np.c"
102#undef main
103
104int main(int argc, char *argv[])
105{
106 main_test_libpython();
107 main_test_libpython_version();
108 main_test_libperl();
109 main_test_hello();
110 main_test_libelf();
111 main_test_libelf_mmap();
112 main_test_glibc();
113 main_test_dwarf();
114 main_test_libelf_getphdrnum();
115 main_test_libunwind();
116 main_test_libaudit();
117 main_test_libslang();
118 main_test_gtk2(argc, argv);
119 main_test_gtk2_infobar(argc, argv);
120 main_test_libbfd();
121 main_test_backtrace();
122 main_test_libnuma();
123 main_test_timerfd();
124 main_test_stackprotector_all();
125 main_test_libdw_dwarf_unwind();
126 main_test_sync_compare_and_swap(argc, argv);
127 main_test_zlib();
128 main_test_pthread_attr_setaffinity_np();
129
130 return 0;
131}
diff --git a/tools/perf/config/feature-checks/test-backtrace.c b/tools/perf/config/feature-checks/test-backtrace.c
deleted file mode 100644
index 7124aa1dc8fb..000000000000
--- a/tools/perf/config/feature-checks/test-backtrace.c
+++ /dev/null
@@ -1,13 +0,0 @@
1#include <execinfo.h>
2#include <stdio.h>
3
4int main(void)
5{
6 void *backtrace_fns[10];
7 size_t entries;
8
9 entries = backtrace(backtrace_fns, 10);
10 backtrace_symbols_fd(backtrace_fns, entries, 1);
11
12 return 0;
13}
diff --git a/tools/perf/config/feature-checks/test-bionic.c b/tools/perf/config/feature-checks/test-bionic.c
deleted file mode 100644
index eac24e9513eb..000000000000
--- a/tools/perf/config/feature-checks/test-bionic.c
+++ /dev/null
@@ -1,6 +0,0 @@
1#include <android/api-level.h>
2
3int main(void)
4{
5 return __ANDROID_API__;
6}
diff --git a/tools/perf/config/feature-checks/test-compile.c b/tools/perf/config/feature-checks/test-compile.c
deleted file mode 100644
index 31dbf45bf99c..000000000000
--- a/tools/perf/config/feature-checks/test-compile.c
+++ /dev/null
@@ -1,4 +0,0 @@
1int main(void)
2{
3 return 0;
4}
diff --git a/tools/perf/config/feature-checks/test-cplus-demangle.c b/tools/perf/config/feature-checks/test-cplus-demangle.c
deleted file mode 100644
index 610c686e0009..000000000000
--- a/tools/perf/config/feature-checks/test-cplus-demangle.c
+++ /dev/null
@@ -1,14 +0,0 @@
1extern int printf(const char *format, ...);
2extern char *cplus_demangle(const char *, int);
3
4int main(void)
5{
6 char symbol[4096] = "FieldName__9ClassNameFd";
7 char *tmp;
8
9 tmp = cplus_demangle(symbol, 0);
10
11 printf("demangled symbol: {%s}\n", tmp);
12
13 return 0;
14}
diff --git a/tools/perf/config/feature-checks/test-dwarf.c b/tools/perf/config/feature-checks/test-dwarf.c
deleted file mode 100644
index 3fc1801ce4a9..000000000000
--- a/tools/perf/config/feature-checks/test-dwarf.c
+++ /dev/null
@@ -1,10 +0,0 @@
1#include <dwarf.h>
2#include <elfutils/libdw.h>
3#include <elfutils/version.h>
4
5int main(void)
6{
7 Dwarf *dbg = dwarf_begin(0, DWARF_C_READ);
8
9 return (long)dbg;
10}
diff --git a/tools/perf/config/feature-checks/test-fortify-source.c b/tools/perf/config/feature-checks/test-fortify-source.c
deleted file mode 100644
index c9f398d87868..000000000000
--- a/tools/perf/config/feature-checks/test-fortify-source.c
+++ /dev/null
@@ -1,6 +0,0 @@
1#include <stdio.h>
2
3int main(void)
4{
5 return puts("hi");
6}
diff --git a/tools/perf/config/feature-checks/test-glibc.c b/tools/perf/config/feature-checks/test-glibc.c
deleted file mode 100644
index b0820345cd98..000000000000
--- a/tools/perf/config/feature-checks/test-glibc.c
+++ /dev/null
@@ -1,8 +0,0 @@
1#include <gnu/libc-version.h>
2
3int main(void)
4{
5 const char *version = gnu_get_libc_version();
6
7 return (long)version;
8}
diff --git a/tools/perf/config/feature-checks/test-gtk2-infobar.c b/tools/perf/config/feature-checks/test-gtk2-infobar.c
deleted file mode 100644
index 397b4646d066..000000000000
--- a/tools/perf/config/feature-checks/test-gtk2-infobar.c
+++ /dev/null
@@ -1,11 +0,0 @@
1#pragma GCC diagnostic ignored "-Wstrict-prototypes"
2#include <gtk/gtk.h>
3#pragma GCC diagnostic error "-Wstrict-prototypes"
4
5int main(int argc, char *argv[])
6{
7 gtk_init(&argc, &argv);
8 gtk_info_bar_new();
9
10 return 0;
11}
diff --git a/tools/perf/config/feature-checks/test-gtk2.c b/tools/perf/config/feature-checks/test-gtk2.c
deleted file mode 100644
index 6bd80e509439..000000000000
--- a/tools/perf/config/feature-checks/test-gtk2.c
+++ /dev/null
@@ -1,10 +0,0 @@
1#pragma GCC diagnostic ignored "-Wstrict-prototypes"
2#include <gtk/gtk.h>
3#pragma GCC diagnostic error "-Wstrict-prototypes"
4
5int main(int argc, char *argv[])
6{
7 gtk_init(&argc, &argv);
8
9 return 0;
10}
diff --git a/tools/perf/config/feature-checks/test-hello.c b/tools/perf/config/feature-checks/test-hello.c
deleted file mode 100644
index c9f398d87868..000000000000
--- a/tools/perf/config/feature-checks/test-hello.c
+++ /dev/null
@@ -1,6 +0,0 @@
1#include <stdio.h>
2
3int main(void)
4{
5 return puts("hi");
6}
diff --git a/tools/perf/config/feature-checks/test-libaudit.c b/tools/perf/config/feature-checks/test-libaudit.c
deleted file mode 100644
index afc019f08641..000000000000
--- a/tools/perf/config/feature-checks/test-libaudit.c
+++ /dev/null
@@ -1,10 +0,0 @@
1#include <libaudit.h>
2
3extern int printf(const char *format, ...);
4
5int main(void)
6{
7 printf("error message: %s\n", audit_errno_to_name(0));
8
9 return audit_open();
10}
diff --git a/tools/perf/config/feature-checks/test-libbfd.c b/tools/perf/config/feature-checks/test-libbfd.c
deleted file mode 100644
index 24059907e990..000000000000
--- a/tools/perf/config/feature-checks/test-libbfd.c
+++ /dev/null
@@ -1,15 +0,0 @@
1#include <bfd.h>
2
3extern int printf(const char *format, ...);
4
5int main(void)
6{
7 char symbol[4096] = "FieldName__9ClassNameFd";
8 char *tmp;
9
10 tmp = bfd_demangle(0, symbol, 0);
11
12 printf("demangled symbol: {%s}\n", tmp);
13
14 return 0;
15}
diff --git a/tools/perf/config/feature-checks/test-libdw-dwarf-unwind.c b/tools/perf/config/feature-checks/test-libdw-dwarf-unwind.c
deleted file mode 100644
index f676a3ff442a..000000000000
--- a/tools/perf/config/feature-checks/test-libdw-dwarf-unwind.c
+++ /dev/null
@@ -1,13 +0,0 @@
1
2#include <elfutils/libdwfl.h>
3
4int main(void)
5{
6 /*
7 * This function is guarded via: __nonnull_attribute__ (1, 2).
8 * Passing '1' as arguments value. This code is never executed,
9 * only compiled.
10 */
11 dwfl_thread_getframes((void *) 1, (void *) 1, NULL);
12 return 0;
13}
diff --git a/tools/perf/config/feature-checks/test-libelf-getphdrnum.c b/tools/perf/config/feature-checks/test-libelf-getphdrnum.c
deleted file mode 100644
index d710459306c3..000000000000
--- a/tools/perf/config/feature-checks/test-libelf-getphdrnum.c
+++ /dev/null
@@ -1,8 +0,0 @@
1#include <libelf.h>
2
3int main(void)
4{
5 size_t dst;
6
7 return elf_getphdrnum(0, &dst);
8}
diff --git a/tools/perf/config/feature-checks/test-libelf-mmap.c b/tools/perf/config/feature-checks/test-libelf-mmap.c
deleted file mode 100644
index 564427d7ef18..000000000000
--- a/tools/perf/config/feature-checks/test-libelf-mmap.c
+++ /dev/null
@@ -1,8 +0,0 @@
1#include <libelf.h>
2
3int main(void)
4{
5 Elf *elf = elf_begin(0, ELF_C_READ_MMAP, 0);
6
7 return (long)elf;
8}
diff --git a/tools/perf/config/feature-checks/test-libelf.c b/tools/perf/config/feature-checks/test-libelf.c
deleted file mode 100644
index 08db322d8957..000000000000
--- a/tools/perf/config/feature-checks/test-libelf.c
+++ /dev/null
@@ -1,8 +0,0 @@
1#include <libelf.h>
2
3int main(void)
4{
5 Elf *elf = elf_begin(0, ELF_C_READ, 0);
6
7 return (long)elf;
8}
diff --git a/tools/perf/config/feature-checks/test-libnuma.c b/tools/perf/config/feature-checks/test-libnuma.c
deleted file mode 100644
index 4763d9cd587d..000000000000
--- a/tools/perf/config/feature-checks/test-libnuma.c
+++ /dev/null
@@ -1,9 +0,0 @@
1#include <numa.h>
2#include <numaif.h>
3
4int main(void)
5{
6 numa_available();
7
8 return 0;
9}
diff --git a/tools/perf/config/feature-checks/test-libperl.c b/tools/perf/config/feature-checks/test-libperl.c
deleted file mode 100644
index 8871f6a0fdb4..000000000000
--- a/tools/perf/config/feature-checks/test-libperl.c
+++ /dev/null
@@ -1,9 +0,0 @@
1#include <EXTERN.h>
2#include <perl.h>
3
4int main(void)
5{
6 perl_alloc();
7
8 return 0;
9}
diff --git a/tools/perf/config/feature-checks/test-libpython-version.c b/tools/perf/config/feature-checks/test-libpython-version.c
deleted file mode 100644
index facea122d812..000000000000
--- a/tools/perf/config/feature-checks/test-libpython-version.c
+++ /dev/null
@@ -1,10 +0,0 @@
1#include <Python.h>
2
3#if PY_VERSION_HEX >= 0x03000000
4 #error
5#endif
6
7int main(void)
8{
9 return 0;
10}
diff --git a/tools/perf/config/feature-checks/test-libpython.c b/tools/perf/config/feature-checks/test-libpython.c
deleted file mode 100644
index b24b28ad6324..000000000000
--- a/tools/perf/config/feature-checks/test-libpython.c
+++ /dev/null
@@ -1,8 +0,0 @@
1#include <Python.h>
2
3int main(void)
4{
5 Py_Initialize();
6
7 return 0;
8}
diff --git a/tools/perf/config/feature-checks/test-libslang.c b/tools/perf/config/feature-checks/test-libslang.c
deleted file mode 100644
index 22ff22ed94d1..000000000000
--- a/tools/perf/config/feature-checks/test-libslang.c
+++ /dev/null
@@ -1,6 +0,0 @@
1#include <slang.h>
2
3int main(void)
4{
5 return SLsmg_init_smg();
6}
diff --git a/tools/perf/config/feature-checks/test-libunwind-debug-frame.c b/tools/perf/config/feature-checks/test-libunwind-debug-frame.c
deleted file mode 100644
index 0ef8087a104a..000000000000
--- a/tools/perf/config/feature-checks/test-libunwind-debug-frame.c
+++ /dev/null
@@ -1,16 +0,0 @@
1#include <libunwind.h>
2#include <stdlib.h>
3
4extern int
5UNW_OBJ(dwarf_find_debug_frame) (int found, unw_dyn_info_t *di_debug,
6 unw_word_t ip, unw_word_t segbase,
7 const char *obj_name, unw_word_t start,
8 unw_word_t end);
9
10#define dwarf_find_debug_frame UNW_OBJ(dwarf_find_debug_frame)
11
12int main(void)
13{
14 dwarf_find_debug_frame(0, NULL, 0, 0, NULL, 0, 0);
15 return 0;
16}
diff --git a/tools/perf/config/feature-checks/test-libunwind.c b/tools/perf/config/feature-checks/test-libunwind.c
deleted file mode 100644
index 43b9369bcab7..000000000000
--- a/tools/perf/config/feature-checks/test-libunwind.c
+++ /dev/null
@@ -1,27 +0,0 @@
1#include <libunwind.h>
2#include <stdlib.h>
3
4extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
5 unw_word_t ip,
6 unw_dyn_info_t *di,
7 unw_proc_info_t *pi,
8 int need_unwind_info, void *arg);
9
10
11#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table)
12
13static unw_accessors_t accessors;
14
15int main(void)
16{
17 unw_addr_space_t addr_space;
18
19 addr_space = unw_create_addr_space(&accessors, 0);
20 if (addr_space)
21 return 0;
22
23 unw_init_remote(NULL, addr_space, NULL);
24 dwarf_search_unwind_table(addr_space, 0, NULL, NULL, 0, NULL);
25
26 return 0;
27}
diff --git a/tools/perf/config/feature-checks/test-pthread-attr-setaffinity-np.c b/tools/perf/config/feature-checks/test-pthread-attr-setaffinity-np.c
deleted file mode 100644
index 2b81b72eca23..000000000000
--- a/tools/perf/config/feature-checks/test-pthread-attr-setaffinity-np.c
+++ /dev/null
@@ -1,15 +0,0 @@
1#include <stdint.h>
2#include <pthread.h>
3
4int main(void)
5{
6 int ret = 0;
7 pthread_attr_t thread_attr;
8 cpu_set_t cs;
9
10 pthread_attr_init(&thread_attr);
11 /* don't care abt exact args, just the API itself in libpthread */
12 ret = pthread_attr_setaffinity_np(&thread_attr, sizeof(cs), &cs);
13
14 return ret;
15}
diff --git a/tools/perf/config/feature-checks/test-stackprotector-all.c b/tools/perf/config/feature-checks/test-stackprotector-all.c
deleted file mode 100644
index c9f398d87868..000000000000
--- a/tools/perf/config/feature-checks/test-stackprotector-all.c
+++ /dev/null
@@ -1,6 +0,0 @@
1#include <stdio.h>
2
3int main(void)
4{
5 return puts("hi");
6}
diff --git a/tools/perf/config/feature-checks/test-sync-compare-and-swap.c b/tools/perf/config/feature-checks/test-sync-compare-and-swap.c
deleted file mode 100644
index c34d4ca4af56..000000000000
--- a/tools/perf/config/feature-checks/test-sync-compare-and-swap.c
+++ /dev/null
@@ -1,14 +0,0 @@
1#include <stdint.h>
2
3volatile uint64_t x;
4
5int main(int argc, char *argv[])
6{
7 uint64_t old, new = argc;
8
9 argv = argv;
10 do {
11 old = __sync_val_compare_and_swap(&x, 0, 0);
12 } while (!__sync_bool_compare_and_swap(&x, old, new));
13 return old == new;
14}
diff --git a/tools/perf/config/feature-checks/test-timerfd.c b/tools/perf/config/feature-checks/test-timerfd.c
deleted file mode 100644
index 8c5c083b4d3c..000000000000
--- a/tools/perf/config/feature-checks/test-timerfd.c
+++ /dev/null
@@ -1,18 +0,0 @@
1/*
2 * test for timerfd functions used by perf-kvm-stat-live
3 */
4#include <sys/timerfd.h>
5
6int main(void)
7{
8 struct itimerspec new_value;
9
10 int fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
11 if (fd < 0)
12 return 1;
13
14 if (timerfd_settime(fd, 0, &new_value, NULL) != 0)
15 return 1;
16
17 return 0;
18}
diff --git a/tools/perf/config/feature-checks/test-zlib.c b/tools/perf/config/feature-checks/test-zlib.c
deleted file mode 100644
index e111fff6240e..000000000000
--- a/tools/perf/config/feature-checks/test-zlib.c
+++ /dev/null
@@ -1,9 +0,0 @@
1#include <zlib.h>
2
3int main(void)
4{
5 z_stream zs;
6
7 inflateInit(&zs);
8 return 0;
9}
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..e14bb637255c 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;
@@ -61,6 +62,8 @@ struct record_opts {
61 u64 user_interval; 62 u64 user_interval;
62 bool sample_transaction; 63 bool sample_transaction;
63 unsigned initial_delay; 64 unsigned initial_delay;
65 bool use_clockid;
66 clockid_t clockid;
64}; 67};
65 68
66struct option; 69struct option;
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/attr/base-record b/tools/perf/tests/attr/base-record
index d3095dafed36..7e6d74946e04 100644
--- a/tools/perf/tests/attr/base-record
+++ b/tools/perf/tests/attr/base-record
@@ -5,7 +5,7 @@ group_fd=-1
5flags=0|8 5flags=0|8
6cpu=* 6cpu=*
7type=0|1 7type=0|1
8size=104 8size=112
9config=0 9config=0
10sample_period=4000 10sample_period=4000
11sample_type=263 11sample_type=263
diff --git a/tools/perf/tests/attr/base-stat b/tools/perf/tests/attr/base-stat
index 872ed7e24c7c..f4cf148f14cb 100644
--- a/tools/perf/tests/attr/base-stat
+++ b/tools/perf/tests/attr/base-stat
@@ -5,7 +5,7 @@ group_fd=-1
5flags=0|8 5flags=0|8
6cpu=* 6cpu=*
7type=0 7type=0
8size=104 8size=112
9config=0 9config=0
10sample_period=0 10sample_period=0
11sample_type=0 11sample_type=0
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..3de744961739 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"
@@ -294,6 +295,36 @@ static int test__checkevent_genhw_modifier(struct perf_evlist *evlist)
294 return test__checkevent_genhw(evlist); 295 return test__checkevent_genhw(evlist);
295} 296}
296 297
298static int test__checkevent_exclude_idle_modifier(struct perf_evlist *evlist)
299{
300 struct perf_evsel *evsel = perf_evlist__first(evlist);
301
302 TEST_ASSERT_VAL("wrong exclude idle", evsel->attr.exclude_idle);
303 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
304 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
305 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
306 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
307 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
308 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
309
310 return test__checkevent_symbolic_name(evlist);
311}
312
313static int test__checkevent_exclude_idle_modifier_1(struct perf_evlist *evlist)
314{
315 struct perf_evsel *evsel = perf_evlist__first(evlist);
316
317 TEST_ASSERT_VAL("wrong exclude idle", evsel->attr.exclude_idle);
318 TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
319 TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
320 TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
321 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
322 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
323 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
324
325 return test__checkevent_symbolic_name(evlist);
326}
327
297static int test__checkevent_breakpoint_modifier(struct perf_evlist *evlist) 328static int test__checkevent_breakpoint_modifier(struct perf_evlist *evlist)
298{ 329{
299 struct perf_evsel *evsel = perf_evlist__first(evlist); 330 struct perf_evsel *evsel = perf_evlist__first(evlist);
@@ -1192,11 +1223,19 @@ static int count_tracepoints(void)
1192{ 1223{
1193 char events_path[PATH_MAX]; 1224 char events_path[PATH_MAX];
1194 struct dirent *events_ent; 1225 struct dirent *events_ent;
1226 const char *mountpoint;
1195 DIR *events_dir; 1227 DIR *events_dir;
1196 int cnt = 0; 1228 int cnt = 0;
1197 1229
1198 scnprintf(events_path, PATH_MAX, "%s/tracing/events", 1230 mountpoint = tracefs_find_mountpoint();
1199 debugfs_find_mountpoint()); 1231 if (mountpoint) {
1232 scnprintf(events_path, PATH_MAX, "%s/events",
1233 mountpoint);
1234 } else {
1235 mountpoint = debugfs_find_mountpoint();
1236 scnprintf(events_path, PATH_MAX, "%s/tracing/events",
1237 mountpoint);
1238 }
1200 1239
1201 events_dir = opendir(events_path); 1240 events_dir = opendir(events_path);
1202 1241
@@ -1485,6 +1524,16 @@ static struct evlist_test test__events[] = {
1485 .id = 100, 1524 .id = 100,
1486 }, 1525 },
1487#endif 1526#endif
1527 {
1528 .name = "instructions:I",
1529 .check = test__checkevent_exclude_idle_modifier,
1530 .id = 45,
1531 },
1532 {
1533 .name = "instructions:kIG",
1534 .check = test__checkevent_exclude_idle_modifier_1,
1535 .id = 46,
1536 },
1488}; 1537};
1489 1538
1490static struct evlist_test test__events_pmu[] = { 1539static struct evlist_test test__events_pmu[] = {
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 61bf9128e1f2..7f5bdfc9bc87 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -30,6 +30,8 @@ static int disasm_line__parse(char *line, char **namep, char **rawp);
30 30
31static void ins__delete(struct ins_operands *ops) 31static void ins__delete(struct ins_operands *ops)
32{ 32{
33 if (ops == NULL)
34 return;
33 zfree(&ops->source.raw); 35 zfree(&ops->source.raw);
34 zfree(&ops->source.name); 36 zfree(&ops->source.name);
35 zfree(&ops->target.raw); 37 zfree(&ops->target.raw);
@@ -1008,6 +1010,32 @@ fallback:
1008 } 1010 }
1009 filename = symfs_filename; 1011 filename = symfs_filename;
1010 } 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);
1011 } 1039 }
1012 1040
1013 snprintf(command, sizeof(command), 1041 snprintf(command, sizeof(command),
@@ -1027,7 +1055,7 @@ fallback:
1027 1055
1028 file = popen(command, "r"); 1056 file = popen(command, "r");
1029 if (!file) 1057 if (!file)
1030 goto out_free_filename; 1058 goto out_remove_tmp;
1031 1059
1032 while (!feof(file)) 1060 while (!feof(file))
1033 if (symbol__parse_objdump_line(sym, map, file, privsize, 1061 if (symbol__parse_objdump_line(sym, map, file, privsize,
@@ -1042,6 +1070,10 @@ fallback:
1042 delete_last_nop(sym); 1070 delete_last_nop(sym);
1043 1071
1044 pclose(file); 1072 pclose(file);
1073
1074out_remove_tmp:
1075 if (dso__needs_decompress(dso))
1076 unlink(symfs_filename);
1045out_free_filename: 1077out_free_filename:
1046 if (delete_extract) 1078 if (delete_extract)
1047 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..61867dff5d5a 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -59,11 +59,8 @@ static int perf_event__exit_del_thread(struct perf_tool *tool __maybe_unused,
59 dump_printf("(%d:%d):(%d:%d)\n", event->fork.pid, event->fork.tid, 59 dump_printf("(%d:%d):(%d:%d)\n", event->fork.pid, event->fork.tid,
60 event->fork.ppid, event->fork.ptid); 60 event->fork.ppid, event->fork.ptid);
61 61
62 if (thread) { 62 if (thread)
63 rb_erase(&thread->rb_node, &machine->threads); 63 machine__remove_thread(machine, thread);
64 machine->last_match = NULL;
65 thread__delete(thread);
66 }
67 64
68 return 0; 65 return 0;
69} 66}
@@ -93,6 +90,35 @@ int build_id__sprintf(const u8 *build_id, int len, char *bf)
93 return raw - build_id; 90 return raw - build_id;
94} 91}
95 92
93/* asnprintf consolidates asprintf and snprintf */
94static int asnprintf(char **strp, size_t size, const char *fmt, ...)
95{
96 va_list ap;
97 int ret;
98
99 if (!strp)
100 return -EINVAL;
101
102 va_start(ap, fmt);
103 if (*strp)
104 ret = vsnprintf(*strp, size, fmt, ap);
105 else
106 ret = vasprintf(strp, fmt, ap);
107 va_end(ap);
108
109 return ret;
110}
111
112static char *build_id__filename(const char *sbuild_id, char *bf, size_t size)
113{
114 char *tmp = bf;
115 int ret = asnprintf(&bf, size, "%s/.build-id/%.2s/%s", buildid_dir,
116 sbuild_id, sbuild_id + 2);
117 if (ret < 0 || (tmp && size < (unsigned int)ret))
118 return NULL;
119 return bf;
120}
121
96char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size) 122char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size)
97{ 123{
98 char build_id_hex[BUILD_ID_SIZE * 2 + 1]; 124 char build_id_hex[BUILD_ID_SIZE * 2 + 1];
@@ -101,14 +127,7 @@ char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size)
101 return NULL; 127 return NULL;
102 128
103 build_id__sprintf(dso->build_id, sizeof(dso->build_id), build_id_hex); 129 build_id__sprintf(dso->build_id, sizeof(dso->build_id), build_id_hex);
104 if (bf == NULL) { 130 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} 131}
113 132
114#define dsos__for_each_with_build_id(pos, head) \ 133#define dsos__for_each_with_build_id(pos, head) \
@@ -259,52 +278,113 @@ void disable_buildid_cache(void)
259 no_buildid_cache = true; 278 no_buildid_cache = true;
260} 279}
261 280
262int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, 281static char *build_id_cache__dirname_from_path(const char *name,
263 const char *name, bool is_kallsyms, bool is_vdso) 282 bool is_kallsyms, bool is_vdso)
264{ 283{
265 const size_t size = PATH_MAX; 284 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; 285 bool slash = is_kallsyms || is_vdso;
270 286
271 if (is_kallsyms) { 287 if (!slash) {
272 if (symbol_conf.kptr_restrict) {
273 pr_debug("Not caching a kptr_restrict'ed /proc/kallsyms\n");
274 err = 0;
275 goto out_free;
276 }
277 realname = (char *) name;
278 } else
279 realname = realpath(name, NULL); 288 realname = realpath(name, NULL);
289 if (!realname)
290 return NULL;
291 }
280 292
281 if (realname == NULL || filename == NULL || linkname == NULL) 293 if (asprintf(&filename, "%s%s%s", buildid_dir, slash ? "/" : "",
294 is_vdso ? DSO__NAME_VDSO : realname) < 0)
295 filename = NULL;
296
297 if (!slash)
298 free(realname);
299
300 return filename;
301}
302
303int build_id_cache__list_build_ids(const char *pathname,
304 struct strlist **result)
305{
306 struct strlist *list;
307 char *dir_name;
308 DIR *dir;
309 struct dirent *d;
310 int ret = 0;
311
312 list = strlist__new(true, NULL);
313 dir_name = build_id_cache__dirname_from_path(pathname, false, false);
314 if (!list || !dir_name) {
315 ret = -ENOMEM;
316 goto out;
317 }
318
319 /* List up all dirents */
320 dir = opendir(dir_name);
321 if (!dir) {
322 ret = -errno;
323 goto out;
324 }
325
326 while ((d = readdir(dir)) != NULL) {
327 if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
328 continue;
329 strlist__add(list, d->d_name);
330 }
331 closedir(dir);
332
333out:
334 free(dir_name);
335 if (ret)
336 strlist__delete(list);
337 else
338 *result = list;
339
340 return ret;
341}
342
343int build_id_cache__add_s(const char *sbuild_id, const char *name,
344 bool is_kallsyms, bool is_vdso)
345{
346 const size_t size = PATH_MAX;
347 char *realname = NULL, *filename = NULL, *dir_name = NULL,
348 *linkname = zalloc(size), *targetname, *tmp;
349 int err = -1;
350
351 if (!is_kallsyms) {
352 realname = realpath(name, NULL);
353 if (!realname)
354 goto out_free;
355 }
356
357 dir_name = build_id_cache__dirname_from_path(name, is_kallsyms, is_vdso);
358 if (!dir_name)
282 goto out_free; 359 goto out_free;
283 360
284 len = scnprintf(filename, size, "%s%s%s", 361 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; 362 goto out_free;
289 363
290 snprintf(filename + len, size - len, "/%s", sbuild_id); 364 if (asprintf(&filename, "%s/%s", dir_name, sbuild_id) < 0) {
365 filename = NULL;
366 goto out_free;
367 }
291 368
292 if (access(filename, F_OK)) { 369 if (access(filename, F_OK)) {
293 if (is_kallsyms) { 370 if (is_kallsyms) {
294 if (copyfile("/proc/kallsyms", filename)) 371 if (copyfile("/proc/kallsyms", filename))
295 goto out_free; 372 goto out_free;
296 } else if (link(realname, filename) && copyfile(name, filename)) 373 } else if (link(realname, filename) && errno != EEXIST &&
374 copyfile(name, filename))
297 goto out_free; 375 goto out_free;
298 } 376 }
299 377
300 len = scnprintf(linkname, size, "%s/.build-id/%.2s", 378 if (!build_id__filename(sbuild_id, linkname, size))
301 debugdir, sbuild_id); 379 goto out_free;
380 tmp = strrchr(linkname, '/');
381 *tmp = '\0';
302 382
303 if (access(linkname, X_OK) && mkdir_p(linkname, 0755)) 383 if (access(linkname, X_OK) && mkdir_p(linkname, 0755))
304 goto out_free; 384 goto out_free;
305 385
306 snprintf(linkname + len, size - len, "/%s", sbuild_id + 2); 386 *tmp = '/';
307 targetname = filename + strlen(debugdir) - 5; 387 targetname = filename + strlen(buildid_dir) - 5;
308 memcpy(targetname, "../..", 5); 388 memcpy(targetname, "../..", 5);
309 389
310 if (symlink(targetname, linkname) == 0) 390 if (symlink(targetname, linkname) == 0)
@@ -313,34 +393,46 @@ out_free:
313 if (!is_kallsyms) 393 if (!is_kallsyms)
314 free(realname); 394 free(realname);
315 free(filename); 395 free(filename);
396 free(dir_name);
316 free(linkname); 397 free(linkname);
317 return err; 398 return err;
318} 399}
319 400
320static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size, 401static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size,
321 const char *name, const char *debugdir, 402 const char *name, bool is_kallsyms,
322 bool is_kallsyms, bool is_vdso) 403 bool is_vdso)
323{ 404{
324 char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 405 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
325 406
326 build_id__sprintf(build_id, build_id_size, sbuild_id); 407 build_id__sprintf(build_id, build_id_size, sbuild_id);
327 408
328 return build_id_cache__add_s(sbuild_id, debugdir, name, 409 return build_id_cache__add_s(sbuild_id, name, is_kallsyms, is_vdso);
329 is_kallsyms, is_vdso); 410}
411
412bool build_id_cache__cached(const char *sbuild_id)
413{
414 bool ret = false;
415 char *filename = build_id__filename(sbuild_id, NULL, 0);
416
417 if (filename && !access(filename, F_OK))
418 ret = true;
419 free(filename);
420
421 return ret;
330} 422}
331 423
332int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir) 424int build_id_cache__remove_s(const char *sbuild_id)
333{ 425{
334 const size_t size = PATH_MAX; 426 const size_t size = PATH_MAX;
335 char *filename = zalloc(size), 427 char *filename = zalloc(size),
336 *linkname = zalloc(size); 428 *linkname = zalloc(size), *tmp;
337 int err = -1; 429 int err = -1;
338 430
339 if (filename == NULL || linkname == NULL) 431 if (filename == NULL || linkname == NULL)
340 goto out_free; 432 goto out_free;
341 433
342 snprintf(linkname, size, "%s/.build-id/%.2s/%s", 434 if (!build_id__filename(sbuild_id, linkname, size))
343 debugdir, sbuild_id, sbuild_id + 2); 435 goto out_free;
344 436
345 if (access(linkname, F_OK)) 437 if (access(linkname, F_OK))
346 goto out_free; 438 goto out_free;
@@ -354,8 +446,8 @@ int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir)
354 /* 446 /*
355 * Since the link is relative, we must make it absolute: 447 * Since the link is relative, we must make it absolute:
356 */ 448 */
357 snprintf(linkname, size, "%s/.build-id/%.2s/%s", 449 tmp = strrchr(linkname, '/') + 1;
358 debugdir, sbuild_id, filename); 450 snprintf(tmp, size - (tmp - linkname), "%s", filename);
359 451
360 if (unlink(linkname)) 452 if (unlink(linkname))
361 goto out_free; 453 goto out_free;
@@ -367,8 +459,7 @@ out_free:
367 return err; 459 return err;
368} 460}
369 461
370static int dso__cache_build_id(struct dso *dso, struct machine *machine, 462static int dso__cache_build_id(struct dso *dso, struct machine *machine)
371 const char *debugdir)
372{ 463{
373 bool is_kallsyms = dso->kernel && dso->long_name[0] != '/'; 464 bool is_kallsyms = dso->kernel && dso->long_name[0] != '/';
374 bool is_vdso = dso__is_vdso(dso); 465 bool is_vdso = dso__is_vdso(dso);
@@ -381,28 +472,26 @@ static int dso__cache_build_id(struct dso *dso, struct machine *machine,
381 name = nm; 472 name = nm;
382 } 473 }
383 return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id), name, 474 return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id), name,
384 debugdir, is_kallsyms, is_vdso); 475 is_kallsyms, is_vdso);
385} 476}
386 477
387static int __dsos__cache_build_ids(struct list_head *head, 478static int __dsos__cache_build_ids(struct list_head *head,
388 struct machine *machine, const char *debugdir) 479 struct machine *machine)
389{ 480{
390 struct dso *pos; 481 struct dso *pos;
391 int err = 0; 482 int err = 0;
392 483
393 dsos__for_each_with_build_id(pos, head) 484 dsos__for_each_with_build_id(pos, head)
394 if (dso__cache_build_id(pos, machine, debugdir)) 485 if (dso__cache_build_id(pos, machine))
395 err = -1; 486 err = -1;
396 487
397 return err; 488 return err;
398} 489}
399 490
400static int machine__cache_build_ids(struct machine *machine, const char *debugdir) 491static int machine__cache_build_ids(struct machine *machine)
401{ 492{
402 int ret = __dsos__cache_build_ids(&machine->kernel_dsos.head, machine, 493 int ret = __dsos__cache_build_ids(&machine->kernel_dsos.head, machine);
403 debugdir); 494 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; 495 return ret;
407} 496}
408 497
@@ -417,11 +506,11 @@ int perf_session__cache_build_ids(struct perf_session *session)
417 if (mkdir(buildid_dir, 0755) != 0 && errno != EEXIST) 506 if (mkdir(buildid_dir, 0755) != 0 && errno != EEXIST)
418 return -1; 507 return -1;
419 508
420 ret = machine__cache_build_ids(&session->machines.host, buildid_dir); 509 ret = machine__cache_build_ids(&session->machines.host);
421 510
422 for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) { 511 for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
423 struct machine *pos = rb_entry(nd, struct machine, rb_node); 512 struct machine *pos = rb_entry(nd, struct machine, rb_node);
424 ret |= machine__cache_build_ids(pos, buildid_dir); 513 ret |= machine__cache_build_ids(pos);
425 } 514 }
426 return ret ? -1 : 0; 515 return ret ? -1 : 0;
427} 516}
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..dd17c9a32fbc
--- /dev/null
+++ b/tools/perf/util/data-convert-bt.c
@@ -0,0 +1,857 @@
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, bool force)
795{
796 struct perf_session *session;
797 struct perf_data_file file = {
798 .path = input,
799 .mode = PERF_DATA_MODE_READ,
800 .force = force,
801 };
802 struct convert c = {
803 .tool = {
804 .sample = process_sample_event,
805 .mmap = perf_event__process_mmap,
806 .mmap2 = perf_event__process_mmap2,
807 .comm = perf_event__process_comm,
808 .exit = perf_event__process_exit,
809 .fork = perf_event__process_fork,
810 .lost = perf_event__process_lost,
811 .tracing_data = perf_event__process_tracing_data,
812 .build_id = perf_event__process_build_id,
813 .ordered_events = true,
814 .ordering_requires_timestamps = true,
815 },
816 };
817 struct ctf_writer *cw = &c.writer;
818 int err = -1;
819
820 /* CTF writer */
821 if (ctf_writer__init(cw, path))
822 return -1;
823
824 /* perf.data session */
825 session = perf_session__new(&file, 0, &c.tool);
826 if (!session)
827 goto free_writer;
828
829 /* CTF writer env/clock setup */
830 if (ctf_writer__setup_env(cw, session))
831 goto free_session;
832
833 /* CTF events setup */
834 if (setup_events(cw, session))
835 goto free_session;
836
837 err = perf_session__process_events(session);
838 if (!err)
839 err = bt_ctf_stream_flush(cw->stream);
840
841 fprintf(stderr,
842 "[ perf data convert: Converted '%s' into CTF data '%s' ]\n",
843 file.path, path);
844
845 fprintf(stderr,
846 "[ perf data convert: Converted and wrote %.3f MB (%" PRIu64 " samples) ]\n",
847 (double) c.events_size / 1024.0 / 1024.0,
848 c.events_count);
849
850 /* its all good */
851free_session:
852 perf_session__delete(session);
853
854free_writer:
855 ctf_writer__cleanup(cw);
856 return err;
857}
diff --git a/tools/perf/util/data-convert-bt.h b/tools/perf/util/data-convert-bt.h
new file mode 100644
index 000000000000..4c204342a9d8
--- /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, bool force);
6
7#endif /* HAVE_LIBBABELTRACE_SUPPORT */
8#endif /* __DATA_CONVERT_BT_H */
diff --git a/tools/perf/util/db-export.c b/tools/perf/util/db-export.c
index c81dae399763..bb39a3ffc70b 100644
--- a/tools/perf/util/db-export.c
+++ b/tools/perf/util/db-export.c
@@ -282,13 +282,13 @@ int db_export__branch_type(struct db_export *dbe, u32 branch_type,
282 282
283int db_export__sample(struct db_export *dbe, union perf_event *event, 283int db_export__sample(struct db_export *dbe, union perf_event *event,
284 struct perf_sample *sample, struct perf_evsel *evsel, 284 struct perf_sample *sample, struct perf_evsel *evsel,
285 struct thread *thread, struct addr_location *al) 285 struct addr_location *al)
286{ 286{
287 struct thread* thread = al->thread;
287 struct export_sample es = { 288 struct export_sample es = {
288 .event = event, 289 .event = event,
289 .sample = sample, 290 .sample = sample,
290 .evsel = evsel, 291 .evsel = evsel,
291 .thread = thread,
292 .al = al, 292 .al = al,
293 }; 293 };
294 struct thread *main_thread; 294 struct thread *main_thread;
diff --git a/tools/perf/util/db-export.h b/tools/perf/util/db-export.h
index adbd22d66798..25e22fd76aca 100644
--- a/tools/perf/util/db-export.h
+++ b/tools/perf/util/db-export.h
@@ -34,7 +34,6 @@ struct export_sample {
34 union perf_event *event; 34 union perf_event *event;
35 struct perf_sample *sample; 35 struct perf_sample *sample;
36 struct perf_evsel *evsel; 36 struct perf_evsel *evsel;
37 struct thread *thread;
38 struct addr_location *al; 37 struct addr_location *al;
39 u64 db_id; 38 u64 db_id;
40 u64 comm_db_id; 39 u64 comm_db_id;
@@ -97,7 +96,7 @@ int db_export__branch_type(struct db_export *dbe, u32 branch_type,
97 const char *name); 96 const char *name);
98int db_export__sample(struct db_export *dbe, union perf_event *event, 97int db_export__sample(struct db_export *dbe, union perf_event *event,
99 struct perf_sample *sample, struct perf_evsel *evsel, 98 struct perf_sample *sample, struct perf_evsel *evsel,
100 struct thread *thread, struct addr_location *al); 99 struct addr_location *al);
101 100
102int db_export__branch_types(struct db_export *dbe); 101int db_export__branch_types(struct db_export *dbe);
103 102
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..c34e024020c7 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
@@ -786,10 +801,16 @@ static int __die_find_member_cb(Dwarf_Die *die_mem, void *data)
786{ 801{
787 const char *name = data; 802 const char *name = data;
788 803
789 if ((dwarf_tag(die_mem) == DW_TAG_member) && 804 if (dwarf_tag(die_mem) == DW_TAG_member) {
790 die_compare_name(die_mem, name)) 805 if (die_compare_name(die_mem, name))
791 return DIE_FIND_CB_END; 806 return DIE_FIND_CB_END;
792 807 else if (!dwarf_diename(die_mem)) { /* Unnamed structure */
808 Dwarf_Die type_die, tmp_die;
809 if (die_get_type(die_mem, &type_die) &&
810 die_find_member(&type_die, name, &tmp_die))
811 return DIE_FIND_CB_END;
812 }
813 }
793 return DIE_FIND_CB_SIBLING; 814 return DIE_FIND_CB_SIBLING;
794} 815}
795 816
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..ff866c4d2e2f 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -49,72 +49,103 @@ static struct perf_sample synth_sample = {
49 .period = 1, 49 .period = 1,
50}; 50};
51 51
52static pid_t perf_event__get_comm_tgid(pid_t pid, char *comm, size_t len) 52/*
53 * Assumes that the first 4095 bytes of /proc/pid/stat contains
54 * the comm, tgid and ppid.
55 */
56static int perf_event__get_comm_ids(pid_t pid, char *comm, size_t len,
57 pid_t *tgid, pid_t *ppid)
53{ 58{
54 char filename[PATH_MAX]; 59 char filename[PATH_MAX];
55 char bf[BUFSIZ]; 60 char bf[4096];
56 FILE *fp; 61 int fd;
57 size_t size = 0; 62 size_t size = 0, n;
58 pid_t tgid = -1; 63 char *nl, *name, *tgids, *ppids;
64
65 *tgid = -1;
66 *ppid = -1;
59 67
60 snprintf(filename, sizeof(filename), "/proc/%d/status", pid); 68 snprintf(filename, sizeof(filename), "/proc/%d/status", pid);
61 69
62 fp = fopen(filename, "r"); 70 fd = open(filename, O_RDONLY);
63 if (fp == NULL) { 71 if (fd < 0) {
64 pr_debug("couldn't open %s\n", filename); 72 pr_debug("couldn't open %s\n", filename);
65 return 0; 73 return -1;
66 } 74 }
67 75
68 while (!comm[0] || (tgid < 0)) { 76 n = read(fd, bf, sizeof(bf) - 1);
69 if (fgets(bf, sizeof(bf), fp) == NULL) { 77 close(fd);
70 pr_warning("couldn't get COMM and pgid, malformed %s\n", 78 if (n <= 0) {
71 filename); 79 pr_warning("Couldn't get COMM, tigd and ppid for pid %d\n",
72 break; 80 pid);
73 } 81 return -1;
82 }
83 bf[n] = '\0';
74 84
75 if (memcmp(bf, "Name:", 5) == 0) { 85 name = strstr(bf, "Name:");
76 char *name = bf + 5; 86 tgids = strstr(bf, "Tgid:");
77 while (*name && isspace(*name)) 87 ppids = strstr(bf, "PPid:");
78 ++name; 88
79 size = strlen(name) - 1; 89 if (name) {
80 if (size >= len) 90 name += 5; /* strlen("Name:") */
81 size = len - 1; 91
82 memcpy(comm, name, size); 92 while (*name && isspace(*name))
83 comm[size] = '\0'; 93 ++name;
84 94
85 } else if (memcmp(bf, "Tgid:", 5) == 0) { 95 nl = strchr(name, '\n');
86 char *tgids = bf + 5; 96 if (nl)
87 while (*tgids && isspace(*tgids)) 97 *nl = '\0';
88 ++tgids; 98
89 tgid = atoi(tgids); 99 size = strlen(name);
90 } 100 if (size >= len)
101 size = len - 1;
102 memcpy(comm, name, size);
103 comm[size] = '\0';
104 } else {
105 pr_debug("Name: string not found for pid %d\n", pid);
91 } 106 }
92 107
93 fclose(fp); 108 if (tgids) {
109 tgids += 5; /* strlen("Tgid:") */
110 *tgid = atoi(tgids);
111 } else {
112 pr_debug("Tgid: string not found for pid %d\n", pid);
113 }
94 114
95 return tgid; 115 if (ppids) {
116 ppids += 5; /* strlen("PPid:") */
117 *ppid = atoi(ppids);
118 } else {
119 pr_debug("PPid: string not found for pid %d\n", pid);
120 }
121
122 return 0;
96} 123}
97 124
98static pid_t perf_event__synthesize_comm(struct perf_tool *tool, 125static int perf_event__prepare_comm(union perf_event *event, pid_t pid,
99 union perf_event *event, pid_t pid, 126 struct machine *machine,
100 perf_event__handler_t process, 127 pid_t *tgid, pid_t *ppid)
101 struct machine *machine)
102{ 128{
103 size_t size; 129 size_t size;
104 pid_t tgid; 130
131 *ppid = -1;
105 132
106 memset(&event->comm, 0, sizeof(event->comm)); 133 memset(&event->comm, 0, sizeof(event->comm));
107 134
108 if (machine__is_host(machine)) 135 if (machine__is_host(machine)) {
109 tgid = perf_event__get_comm_tgid(pid, event->comm.comm, 136 if (perf_event__get_comm_ids(pid, event->comm.comm,
110 sizeof(event->comm.comm)); 137 sizeof(event->comm.comm),
111 else 138 tgid, ppid) != 0) {
112 tgid = machine->pid; 139 return -1;
140 }
141 } else {
142 *tgid = machine->pid;
143 }
113 144
114 if (tgid < 0) 145 if (*tgid < 0)
115 goto out; 146 return -1;
116 147
117 event->comm.pid = tgid; 148 event->comm.pid = *tgid;
118 event->comm.header.type = PERF_RECORD_COMM; 149 event->comm.header.type = PERF_RECORD_COMM;
119 150
120 size = strlen(event->comm.comm) + 1; 151 size = strlen(event->comm.comm) + 1;
@@ -125,23 +156,45 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
125 machine->id_hdr_size); 156 machine->id_hdr_size);
126 event->comm.tid = pid; 157 event->comm.tid = pid;
127 158
159 return 0;
160}
161
162static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
163 union perf_event *event, pid_t pid,
164 perf_event__handler_t process,
165 struct machine *machine)
166{
167 pid_t tgid, ppid;
168
169 if (perf_event__prepare_comm(event, pid, machine, &tgid, &ppid) != 0)
170 return -1;
171
128 if (process(tool, event, &synth_sample, machine) != 0) 172 if (process(tool, event, &synth_sample, machine) != 0)
129 return -1; 173 return -1;
130 174
131out:
132 return tgid; 175 return tgid;
133} 176}
134 177
135static int perf_event__synthesize_fork(struct perf_tool *tool, 178static int perf_event__synthesize_fork(struct perf_tool *tool,
136 union perf_event *event, pid_t pid, 179 union perf_event *event,
137 pid_t tgid, perf_event__handler_t process, 180 pid_t pid, pid_t tgid, pid_t ppid,
181 perf_event__handler_t process,
138 struct machine *machine) 182 struct machine *machine)
139{ 183{
140 memset(&event->fork, 0, sizeof(event->fork) + machine->id_hdr_size); 184 memset(&event->fork, 0, sizeof(event->fork) + machine->id_hdr_size);
141 185
142 /* this is really a clone event but we use fork to synthesize it */ 186 /*
143 event->fork.ppid = tgid; 187 * for main thread set parent to ppid from status file. For other
144 event->fork.ptid = tgid; 188 * threads set parent pid to main thread. ie., assume main thread
189 * spawns all threads in a process
190 */
191 if (tgid == pid) {
192 event->fork.ppid = ppid;
193 event->fork.ptid = ppid;
194 } else {
195 event->fork.ppid = tgid;
196 event->fork.ptid = tgid;
197 }
145 event->fork.pid = tgid; 198 event->fork.pid = tgid;
146 event->fork.tid = pid; 199 event->fork.tid = pid;
147 event->fork.header.type = PERF_RECORD_FORK; 200 event->fork.header.type = PERF_RECORD_FORK;
@@ -333,7 +386,8 @@ static int __event__synthesize_thread(union perf_event *comm_event,
333 char filename[PATH_MAX]; 386 char filename[PATH_MAX];
334 DIR *tasks; 387 DIR *tasks;
335 struct dirent dirent, *next; 388 struct dirent dirent, *next;
336 pid_t tgid; 389 pid_t tgid, ppid;
390 int rc = 0;
337 391
338 /* special case: only send one comm event using passed in pid */ 392 /* special case: only send one comm event using passed in pid */
339 if (!full) { 393 if (!full) {
@@ -361,34 +415,38 @@ static int __event__synthesize_thread(union perf_event *comm_event,
361 415
362 while (!readdir_r(tasks, &dirent, &next) && next) { 416 while (!readdir_r(tasks, &dirent, &next) && next) {
363 char *end; 417 char *end;
364 int rc = 0;
365 pid_t _pid; 418 pid_t _pid;
366 419
367 _pid = strtol(dirent.d_name, &end, 10); 420 _pid = strtol(dirent.d_name, &end, 10);
368 if (*end) 421 if (*end)
369 continue; 422 continue;
370 423
371 tgid = perf_event__synthesize_comm(tool, comm_event, _pid, 424 rc = -1;
372 process, machine); 425 if (perf_event__prepare_comm(comm_event, _pid, machine,
373 if (tgid == -1) 426 &tgid, &ppid) != 0)
374 return -1; 427 break;
375 428
429 if (perf_event__synthesize_fork(tool, fork_event, _pid, tgid,
430 ppid, process, machine) < 0)
431 break;
432 /*
433 * Send the prepared comm event
434 */
435 if (process(tool, comm_event, &synth_sample, machine) != 0)
436 break;
437
438 rc = 0;
376 if (_pid == pid) { 439 if (_pid == pid) {
377 /* process the parent's maps too */ 440 /* process the parent's maps too */
378 rc = perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid, 441 rc = perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid,
379 process, machine, mmap_data); 442 process, machine, mmap_data);
380 } else { 443 if (rc)
381 /* only fork the tid's map, to save time */ 444 break;
382 rc = perf_event__synthesize_fork(tool, fork_event, _pid, tgid,
383 process, machine);
384 } 445 }
385
386 if (rc)
387 return rc;
388 } 446 }
389 447
390 closedir(tasks); 448 closedir(tasks);
391 return 0; 449 return rc;
392} 450}
393 451
394int perf_event__synthesize_thread_map(struct perf_tool *tool, 452int perf_event__synthesize_thread_map(struct perf_tool *tool,
@@ -615,7 +673,7 @@ size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp)
615 else 673 else
616 s = ""; 674 s = "";
617 675
618 return fprintf(fp, "%s: %s:%d\n", s, event->comm.comm, event->comm.tid); 676 return fprintf(fp, "%s: %s:%d/%d\n", s, event->comm.comm, event->comm.pid, event->comm.tid);
619} 677}
620 678
621int perf_event__process_comm(struct perf_tool *tool __maybe_unused, 679int perf_event__process_comm(struct perf_tool *tool __maybe_unused,
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index c4ffe2bd0738..09b9e8d3fcf7 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -242,7 +242,6 @@ struct events_stats {
242 u32 nr_invalid_chains; 242 u32 nr_invalid_chains;
243 u32 nr_unknown_id; 243 u32 nr_unknown_id;
244 u32 nr_unprocessable_samples; 244 u32 nr_unprocessable_samples;
245 u32 nr_unordered_events;
246}; 245};
247 246
248struct attr_event { 247struct attr_event {
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 28b8ce86bf12..080be93eea96 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"
@@ -635,8 +634,8 @@ static struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist,
635union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx) 634union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
636{ 635{
637 struct perf_mmap *md = &evlist->mmap[idx]; 636 struct perf_mmap *md = &evlist->mmap[idx];
638 unsigned int head = perf_mmap__read_head(md); 637 u64 head = perf_mmap__read_head(md);
639 unsigned int old = md->prev; 638 u64 old = md->prev;
640 unsigned char *data = md->base + page_size; 639 unsigned char *data = md->base + page_size;
641 union perf_event *event = NULL; 640 union perf_event *event = NULL;
642 641
@@ -696,7 +695,7 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
696 695
697static bool perf_mmap__empty(struct perf_mmap *md) 696static bool perf_mmap__empty(struct perf_mmap *md)
698{ 697{
699 return perf_mmap__read_head(md) != md->prev; 698 return perf_mmap__read_head(md) == md->prev;
700} 699}
701 700
702static void perf_evlist__mmap_get(struct perf_evlist *evlist, int idx) 701static void perf_evlist__mmap_get(struct perf_evlist *evlist, int idx)
@@ -717,7 +716,7 @@ void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx)
717 struct perf_mmap *md = &evlist->mmap[idx]; 716 struct perf_mmap *md = &evlist->mmap[idx];
718 717
719 if (!evlist->overwrite) { 718 if (!evlist->overwrite) {
720 unsigned int old = md->prev; 719 u64 old = md->prev;
721 720
722 perf_mmap__write_tail(md, old); 721 perf_mmap__write_tail(md, old);
723 } 722 }
@@ -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..b5cce95d644e 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -27,7 +27,7 @@ struct perf_mmap {
27 void *base; 27 void *base;
28 int mask; 28 int mask;
29 int refcnt; 29 int refcnt;
30 unsigned int prev; 30 u64 prev;
31 char event_copy[PERF_SAMPLE_MAX_SIZE] __attribute__((aligned(8))); 31 char event_copy[PERF_SAMPLE_MAX_SIZE] __attribute__((aligned(8)));
32}; 32};
33 33
@@ -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);
@@ -186,16 +189,15 @@ size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp);
186int perf_evlist__strerror_open(struct perf_evlist *evlist, int err, char *buf, size_t size); 189int perf_evlist__strerror_open(struct perf_evlist *evlist, int err, char *buf, size_t size);
187int perf_evlist__strerror_mmap(struct perf_evlist *evlist, int err, char *buf, size_t size); 190int perf_evlist__strerror_mmap(struct perf_evlist *evlist, int err, char *buf, size_t size);
188 191
189static inline unsigned int perf_mmap__read_head(struct perf_mmap *mm) 192static inline u64 perf_mmap__read_head(struct perf_mmap *mm)
190{ 193{
191 struct perf_event_mmap_page *pc = mm->base; 194 struct perf_event_mmap_page *pc = mm->base;
192 int head = ACCESS_ONCE(pc->data_head); 195 u64 head = ACCESS_ONCE(pc->data_head);
193 rmb(); 196 rmb();
194 return head; 197 return head;
195} 198}
196 199
197static inline void perf_mmap__write_tail(struct perf_mmap *md, 200static inline void perf_mmap__write_tail(struct perf_mmap *md, u64 tail)
198 unsigned long tail)
199{ 201{
200 struct perf_event_mmap_page *pc = md->base; 202 struct perf_event_mmap_page *pc = md->base;
201 203
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index ea51a90e20a0..33e3fd8c2e68 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -32,8 +32,12 @@ static struct {
32 bool exclude_guest; 32 bool exclude_guest;
33 bool mmap2; 33 bool mmap2;
34 bool cloexec; 34 bool cloexec;
35 bool clockid;
36 bool clockid_wrong;
35} perf_missing_features; 37} perf_missing_features;
36 38
39static clockid_t clockid;
40
37static int perf_evsel__no_extra_init(struct perf_evsel *evsel __maybe_unused) 41static int perf_evsel__no_extra_init(struct perf_evsel *evsel __maybe_unused)
38{ 42{
39 return 0; 43 return 0;
@@ -537,13 +541,30 @@ int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size)
537} 541}
538 542
539static void 543static void
540perf_evsel__config_callgraph(struct perf_evsel *evsel) 544perf_evsel__config_callgraph(struct perf_evsel *evsel,
545 struct record_opts *opts)
541{ 546{
542 bool function = perf_evsel__is_function_event(evsel); 547 bool function = perf_evsel__is_function_event(evsel);
543 struct perf_event_attr *attr = &evsel->attr; 548 struct perf_event_attr *attr = &evsel->attr;
544 549
545 perf_evsel__set_sample_bit(evsel, CALLCHAIN); 550 perf_evsel__set_sample_bit(evsel, CALLCHAIN);
546 551
552 if (callchain_param.record_mode == CALLCHAIN_LBR) {
553 if (!opts->branch_stack) {
554 if (attr->exclude_user) {
555 pr_warning("LBR callstack option is only available "
556 "to get user callchain information. "
557 "Falling back to framepointers.\n");
558 } else {
559 perf_evsel__set_sample_bit(evsel, BRANCH_STACK);
560 attr->branch_sample_type = PERF_SAMPLE_BRANCH_USER |
561 PERF_SAMPLE_BRANCH_CALL_STACK;
562 }
563 } else
564 pr_warning("Cannot use LBR callstack with branch stack. "
565 "Falling back to framepointers.\n");
566 }
567
547 if (callchain_param.record_mode == CALLCHAIN_DWARF) { 568 if (callchain_param.record_mode == CALLCHAIN_DWARF) {
548 if (!function) { 569 if (!function) {
549 perf_evsel__set_sample_bit(evsel, REGS_USER); 570 perf_evsel__set_sample_bit(evsel, REGS_USER);
@@ -667,7 +688,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
667 evsel->attr.exclude_callchain_user = 1; 688 evsel->attr.exclude_callchain_user = 1;
668 689
669 if (callchain_param.enabled && !evsel->no_aux_samples) 690 if (callchain_param.enabled && !evsel->no_aux_samples)
670 perf_evsel__config_callgraph(evsel); 691 perf_evsel__config_callgraph(evsel, opts);
671 692
672 if (opts->sample_intr_regs) { 693 if (opts->sample_intr_regs) {
673 attr->sample_regs_intr = PERF_REGS_MASK; 694 attr->sample_regs_intr = PERF_REGS_MASK;
@@ -717,6 +738,12 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
717 if (opts->sample_transaction) 738 if (opts->sample_transaction)
718 perf_evsel__set_sample_bit(evsel, TRANSACTION); 739 perf_evsel__set_sample_bit(evsel, TRANSACTION);
719 740
741 if (opts->running_time) {
742 evsel->attr.read_format |=
743 PERF_FORMAT_TOTAL_TIME_ENABLED |
744 PERF_FORMAT_TOTAL_TIME_RUNNING;
745 }
746
720 /* 747 /*
721 * XXX see the function comment above 748 * XXX see the function comment above
722 * 749 *
@@ -738,6 +765,12 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
738 attr->disabled = 0; 765 attr->disabled = 0;
739 attr->enable_on_exec = 0; 766 attr->enable_on_exec = 0;
740 } 767 }
768
769 clockid = opts->clockid;
770 if (opts->use_clockid) {
771 attr->use_clockid = 1;
772 attr->clockid = opts->clockid;
773 }
741} 774}
742 775
743static int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) 776static int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
@@ -978,67 +1011,126 @@ static int get_group_fd(struct perf_evsel *evsel, int cpu, int thread)
978 return fd; 1011 return fd;
979} 1012}
980 1013
981#define __PRINT_ATTR(fmt, cast, field) \ 1014struct bit_names {
982 fprintf(fp, " %-19s "fmt"\n", #field, cast attr->field) 1015 int bit;
983 1016 const char *name;
984#define PRINT_ATTR_U32(field) __PRINT_ATTR("%u" , , field) 1017};
985#define PRINT_ATTR_X32(field) __PRINT_ATTR("%#x", , field) 1018
986#define PRINT_ATTR_U64(field) __PRINT_ATTR("%" PRIu64, (uint64_t), field) 1019static void __p_bits(char *buf, size_t size, u64 value, struct bit_names *bits)
987#define PRINT_ATTR_X64(field) __PRINT_ATTR("%#"PRIx64, (uint64_t), field) 1020{
988 1021 bool first_bit = true;
989#define PRINT_ATTR2N(name1, field1, name2, field2) \ 1022 int i = 0;
990 fprintf(fp, " %-19s %u %-19s %u\n", \ 1023
991 name1, attr->field1, name2, attr->field2) 1024 do {
992 1025 if (value & bits[i].bit) {
993#define PRINT_ATTR2(field1, field2) \ 1026 buf += scnprintf(buf, size, "%s%s", first_bit ? "" : "|", bits[i].name);
994 PRINT_ATTR2N(#field1, field1, #field2, field2) 1027 first_bit = false;
995 1028 }
996static size_t perf_event_attr__fprintf(struct perf_event_attr *attr, FILE *fp) 1029 } while (bits[++i].name != NULL);
997{ 1030}
998 size_t ret = 0; 1031
999 1032static void __p_sample_type(char *buf, size_t size, u64 value)
1000 ret += fprintf(fp, "%.60s\n", graph_dotted_line); 1033{
1001 ret += fprintf(fp, "perf_event_attr:\n"); 1034#define bit_name(n) { PERF_SAMPLE_##n, #n }
1002 1035 struct bit_names bits[] = {
1003 ret += PRINT_ATTR_U32(type); 1036 bit_name(IP), bit_name(TID), bit_name(TIME), bit_name(ADDR),
1004 ret += PRINT_ATTR_U32(size); 1037 bit_name(READ), bit_name(CALLCHAIN), bit_name(ID), bit_name(CPU),
1005 ret += PRINT_ATTR_X64(config); 1038 bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW),
1006 ret += PRINT_ATTR_U64(sample_period); 1039 bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER),
1007 ret += PRINT_ATTR_U64(sample_freq); 1040 bit_name(IDENTIFIER), bit_name(REGS_INTR),
1008 ret += PRINT_ATTR_X64(sample_type); 1041 { .name = NULL, }
1009 ret += PRINT_ATTR_X64(read_format); 1042 };
1010 1043#undef bit_name
1011 ret += PRINT_ATTR2(disabled, inherit); 1044 __p_bits(buf, size, value, bits);
1012 ret += PRINT_ATTR2(pinned, exclusive); 1045}
1013 ret += PRINT_ATTR2(exclude_user, exclude_kernel); 1046
1014 ret += PRINT_ATTR2(exclude_hv, exclude_idle); 1047static void __p_read_format(char *buf, size_t size, u64 value)
1015 ret += PRINT_ATTR2(mmap, comm); 1048{
1016 ret += PRINT_ATTR2(mmap2, comm_exec); 1049#define bit_name(n) { PERF_FORMAT_##n, #n }
1017 ret += PRINT_ATTR2(freq, inherit_stat); 1050 struct bit_names bits[] = {
1018 ret += PRINT_ATTR2(enable_on_exec, task); 1051 bit_name(TOTAL_TIME_ENABLED), bit_name(TOTAL_TIME_RUNNING),
1019 ret += PRINT_ATTR2(watermark, precise_ip); 1052 bit_name(ID), bit_name(GROUP),
1020 ret += PRINT_ATTR2(mmap_data, sample_id_all); 1053 { .name = NULL, }
1021 ret += PRINT_ATTR2(exclude_host, exclude_guest); 1054 };
1022 ret += PRINT_ATTR2N("excl.callchain_kern", exclude_callchain_kernel, 1055#undef bit_name
1023 "excl.callchain_user", exclude_callchain_user); 1056 __p_bits(buf, size, value, bits);
1024 1057}
1025 ret += PRINT_ATTR_U32(wakeup_events); 1058
1026 ret += PRINT_ATTR_U32(wakeup_watermark); 1059#define BUF_SIZE 1024
1027 ret += PRINT_ATTR_X32(bp_type); 1060
1028 ret += PRINT_ATTR_X64(bp_addr); 1061#define p_hex(val) snprintf(buf, BUF_SIZE, "%"PRIx64, (uint64_t)(val))
1029 ret += PRINT_ATTR_X64(config1); 1062#define p_unsigned(val) snprintf(buf, BUF_SIZE, "%"PRIu64, (uint64_t)(val))
1030 ret += PRINT_ATTR_U64(bp_len); 1063#define p_signed(val) snprintf(buf, BUF_SIZE, "%"PRId64, (int64_t)(val))
1031 ret += PRINT_ATTR_X64(config2); 1064#define p_sample_type(val) __p_sample_type(buf, BUF_SIZE, val)
1032 ret += PRINT_ATTR_X64(branch_sample_type); 1065#define p_read_format(val) __p_read_format(buf, BUF_SIZE, val)
1033 ret += PRINT_ATTR_X64(sample_regs_user); 1066
1034 ret += PRINT_ATTR_U32(sample_stack_user); 1067#define PRINT_ATTRn(_n, _f, _p) \
1035 ret += PRINT_ATTR_X64(sample_regs_intr); 1068do { \
1036 1069 if (attr->_f) { \
1037 ret += fprintf(fp, "%.60s\n", graph_dotted_line); 1070 _p(attr->_f); \
1071 ret += attr__fprintf(fp, _n, buf, priv);\
1072 } \
1073} while (0)
1074
1075#define PRINT_ATTRf(_f, _p) PRINT_ATTRn(#_f, _f, _p)
1076
1077int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr,
1078 attr__fprintf_f attr__fprintf, void *priv)
1079{
1080 char buf[BUF_SIZE];
1081 int ret = 0;
1082
1083 PRINT_ATTRf(type, p_unsigned);
1084 PRINT_ATTRf(size, p_unsigned);
1085 PRINT_ATTRf(config, p_hex);
1086 PRINT_ATTRn("{ sample_period, sample_freq }", sample_period, p_unsigned);
1087 PRINT_ATTRf(sample_type, p_sample_type);
1088 PRINT_ATTRf(read_format, p_read_format);
1089
1090 PRINT_ATTRf(disabled, p_unsigned);
1091 PRINT_ATTRf(inherit, p_unsigned);
1092 PRINT_ATTRf(pinned, p_unsigned);
1093 PRINT_ATTRf(exclusive, p_unsigned);
1094 PRINT_ATTRf(exclude_user, p_unsigned);
1095 PRINT_ATTRf(exclude_kernel, p_unsigned);
1096 PRINT_ATTRf(exclude_hv, p_unsigned);
1097 PRINT_ATTRf(exclude_idle, p_unsigned);
1098 PRINT_ATTRf(mmap, p_unsigned);
1099 PRINT_ATTRf(comm, p_unsigned);
1100 PRINT_ATTRf(freq, p_unsigned);
1101 PRINT_ATTRf(inherit_stat, p_unsigned);
1102 PRINT_ATTRf(enable_on_exec, p_unsigned);
1103 PRINT_ATTRf(task, p_unsigned);
1104 PRINT_ATTRf(watermark, p_unsigned);
1105 PRINT_ATTRf(precise_ip, p_unsigned);
1106 PRINT_ATTRf(mmap_data, p_unsigned);
1107 PRINT_ATTRf(sample_id_all, p_unsigned);
1108 PRINT_ATTRf(exclude_host, p_unsigned);
1109 PRINT_ATTRf(exclude_guest, p_unsigned);
1110 PRINT_ATTRf(exclude_callchain_kernel, p_unsigned);
1111 PRINT_ATTRf(exclude_callchain_user, p_unsigned);
1112 PRINT_ATTRf(mmap2, p_unsigned);
1113 PRINT_ATTRf(comm_exec, p_unsigned);
1114 PRINT_ATTRf(use_clockid, p_unsigned);
1115
1116 PRINT_ATTRn("{ wakeup_events, wakeup_watermark }", wakeup_events, p_unsigned);
1117 PRINT_ATTRf(bp_type, p_unsigned);
1118 PRINT_ATTRn("{ bp_addr, config1 }", bp_addr, p_hex);
1119 PRINT_ATTRn("{ bp_len, config2 }", bp_len, p_hex);
1120 PRINT_ATTRf(sample_regs_user, p_hex);
1121 PRINT_ATTRf(sample_stack_user, p_unsigned);
1122 PRINT_ATTRf(clockid, p_signed);
1123 PRINT_ATTRf(sample_regs_intr, p_hex);
1038 1124
1039 return ret; 1125 return ret;
1040} 1126}
1041 1127
1128static int __open_attr__fprintf(FILE *fp, const char *name, const char *val,
1129 void *priv __attribute__((unused)))
1130{
1131 return fprintf(fp, " %-32s %s\n", name, val);
1132}
1133
1042static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, 1134static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
1043 struct thread_map *threads) 1135 struct thread_map *threads)
1044{ 1136{
@@ -1062,6 +1154,12 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
1062 } 1154 }
1063 1155
1064fallback_missing_features: 1156fallback_missing_features:
1157 if (perf_missing_features.clockid_wrong)
1158 evsel->attr.clockid = CLOCK_MONOTONIC; /* should always work */
1159 if (perf_missing_features.clockid) {
1160 evsel->attr.use_clockid = 0;
1161 evsel->attr.clockid = 0;
1162 }
1065 if (perf_missing_features.cloexec) 1163 if (perf_missing_features.cloexec)
1066 flags &= ~(unsigned long)PERF_FLAG_FD_CLOEXEC; 1164 flags &= ~(unsigned long)PERF_FLAG_FD_CLOEXEC;
1067 if (perf_missing_features.mmap2) 1165 if (perf_missing_features.mmap2)
@@ -1072,8 +1170,12 @@ retry_sample_id:
1072 if (perf_missing_features.sample_id_all) 1170 if (perf_missing_features.sample_id_all)
1073 evsel->attr.sample_id_all = 0; 1171 evsel->attr.sample_id_all = 0;
1074 1172
1075 if (verbose >= 2) 1173 if (verbose >= 2) {
1076 perf_event_attr__fprintf(&evsel->attr, stderr); 1174 fprintf(stderr, "%.60s\n", graph_dotted_line);
1175 fprintf(stderr, "perf_event_attr:\n");
1176 perf_event_attr__fprintf(stderr, &evsel->attr, __open_attr__fprintf, NULL);
1177 fprintf(stderr, "%.60s\n", graph_dotted_line);
1178 }
1077 1179
1078 for (cpu = 0; cpu < cpus->nr; cpu++) { 1180 for (cpu = 0; cpu < cpus->nr; cpu++) {
1079 1181
@@ -1099,6 +1201,17 @@ retry_open:
1099 goto try_fallback; 1201 goto try_fallback;
1100 } 1202 }
1101 set_rlimit = NO_CHANGE; 1203 set_rlimit = NO_CHANGE;
1204
1205 /*
1206 * If we succeeded but had to kill clockid, fail and
1207 * have perf_evsel__open_strerror() print us a nice
1208 * error.
1209 */
1210 if (perf_missing_features.clockid ||
1211 perf_missing_features.clockid_wrong) {
1212 err = -EINVAL;
1213 goto out_close;
1214 }
1102 } 1215 }
1103 } 1216 }
1104 1217
@@ -1132,7 +1245,17 @@ try_fallback:
1132 if (err != -EINVAL || cpu > 0 || thread > 0) 1245 if (err != -EINVAL || cpu > 0 || thread > 0)
1133 goto out_close; 1246 goto out_close;
1134 1247
1135 if (!perf_missing_features.cloexec && (flags & PERF_FLAG_FD_CLOEXEC)) { 1248 /*
1249 * Must probe features in the order they were added to the
1250 * perf_event_attr interface.
1251 */
1252 if (!perf_missing_features.clockid_wrong && evsel->attr.use_clockid) {
1253 perf_missing_features.clockid_wrong = true;
1254 goto fallback_missing_features;
1255 } else if (!perf_missing_features.clockid && evsel->attr.use_clockid) {
1256 perf_missing_features.clockid = true;
1257 goto fallback_missing_features;
1258 } else if (!perf_missing_features.cloexec && (flags & PERF_FLAG_FD_CLOEXEC)) {
1136 perf_missing_features.cloexec = true; 1259 perf_missing_features.cloexec = true;
1137 goto fallback_missing_features; 1260 goto fallback_missing_features;
1138 } else if (!perf_missing_features.mmap2 && evsel->attr.mmap2) { 1261 } else if (!perf_missing_features.mmap2 && evsel->attr.mmap2) {
@@ -1892,7 +2015,7 @@ u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample,
1892 value = *(u32 *)ptr; 2015 value = *(u32 *)ptr;
1893 break; 2016 break;
1894 case 8: 2017 case 8:
1895 value = *(u64 *)ptr; 2018 memcpy(&value, ptr, sizeof(u64));
1896 break; 2019 break;
1897 default: 2020 default:
1898 return 0; 2021 return 0;
@@ -1933,62 +2056,9 @@ static int comma_fprintf(FILE *fp, bool *first, const char *fmt, ...)
1933 return ret; 2056 return ret;
1934} 2057}
1935 2058
1936static int __if_fprintf(FILE *fp, bool *first, const char *field, u64 value) 2059static int __print_attr__fprintf(FILE *fp, const char *name, const char *val, void *priv)
1937{
1938 if (value == 0)
1939 return 0;
1940
1941 return comma_fprintf(fp, first, " %s: %" PRIu64, field, value);
1942}
1943
1944#define if_print(field) printed += __if_fprintf(fp, &first, #field, evsel->attr.field)
1945
1946struct bit_names {
1947 int bit;
1948 const char *name;
1949};
1950
1951static int bits__fprintf(FILE *fp, const char *field, u64 value,
1952 struct bit_names *bits, bool *first)
1953{
1954 int i = 0, printed = comma_fprintf(fp, first, " %s: ", field);
1955 bool first_bit = true;
1956
1957 do {
1958 if (value & bits[i].bit) {
1959 printed += fprintf(fp, "%s%s", first_bit ? "" : "|", bits[i].name);
1960 first_bit = false;
1961 }
1962 } while (bits[++i].name != NULL);
1963
1964 return printed;
1965}
1966
1967static int sample_type__fprintf(FILE *fp, bool *first, u64 value)
1968{
1969#define bit_name(n) { PERF_SAMPLE_##n, #n }
1970 struct bit_names bits[] = {
1971 bit_name(IP), bit_name(TID), bit_name(TIME), bit_name(ADDR),
1972 bit_name(READ), bit_name(CALLCHAIN), bit_name(ID), bit_name(CPU),
1973 bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW),
1974 bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER),
1975 bit_name(IDENTIFIER), bit_name(REGS_INTR),
1976 { .name = NULL, }
1977 };
1978#undef bit_name
1979 return bits__fprintf(fp, "sample_type", value, bits, first);
1980}
1981
1982static int read_format__fprintf(FILE *fp, bool *first, u64 value)
1983{ 2060{
1984#define bit_name(n) { PERF_FORMAT_##n, #n } 2061 return comma_fprintf(fp, (bool *)priv, " %s: %s", name, val);
1985 struct bit_names bits[] = {
1986 bit_name(TOTAL_TIME_ENABLED), bit_name(TOTAL_TIME_RUNNING),
1987 bit_name(ID), bit_name(GROUP),
1988 { .name = NULL, }
1989 };
1990#undef bit_name
1991 return bits__fprintf(fp, "read_format", value, bits, first);
1992} 2062}
1993 2063
1994int perf_evsel__fprintf(struct perf_evsel *evsel, 2064int perf_evsel__fprintf(struct perf_evsel *evsel,
@@ -2017,47 +2087,13 @@ int perf_evsel__fprintf(struct perf_evsel *evsel,
2017 2087
2018 printed += fprintf(fp, "%s", perf_evsel__name(evsel)); 2088 printed += fprintf(fp, "%s", perf_evsel__name(evsel));
2019 2089
2020 if (details->verbose || details->freq) { 2090 if (details->verbose) {
2091 printed += perf_event_attr__fprintf(fp, &evsel->attr,
2092 __print_attr__fprintf, &first);
2093 } else if (details->freq) {
2021 printed += comma_fprintf(fp, &first, " sample_freq=%" PRIu64, 2094 printed += comma_fprintf(fp, &first, " sample_freq=%" PRIu64,
2022 (u64)evsel->attr.sample_freq); 2095 (u64)evsel->attr.sample_freq);
2023 } 2096 }
2024
2025 if (details->verbose) {
2026 if_print(type);
2027 if_print(config);
2028 if_print(config1);
2029 if_print(config2);
2030 if_print(size);
2031 printed += sample_type__fprintf(fp, &first, evsel->attr.sample_type);
2032 if (evsel->attr.read_format)
2033 printed += read_format__fprintf(fp, &first, evsel->attr.read_format);
2034 if_print(disabled);
2035 if_print(inherit);
2036 if_print(pinned);
2037 if_print(exclusive);
2038 if_print(exclude_user);
2039 if_print(exclude_kernel);
2040 if_print(exclude_hv);
2041 if_print(exclude_idle);
2042 if_print(mmap);
2043 if_print(mmap2);
2044 if_print(comm);
2045 if_print(comm_exec);
2046 if_print(freq);
2047 if_print(inherit_stat);
2048 if_print(enable_on_exec);
2049 if_print(task);
2050 if_print(watermark);
2051 if_print(precise_ip);
2052 if_print(mmap_data);
2053 if_print(sample_id_all);
2054 if_print(exclude_host);
2055 if_print(exclude_guest);
2056 if_print(__reserved_1);
2057 if_print(wakeup_events);
2058 if_print(bp_type);
2059 if_print(branch_sample_type);
2060 }
2061out: 2097out:
2062 fputc('\n', fp); 2098 fputc('\n', fp);
2063 return ++printed; 2099 return ++printed;
@@ -2135,6 +2171,12 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
2135 "The PMU counters are busy/taken by another profiler.\n" 2171 "The PMU counters are busy/taken by another profiler.\n"
2136 "We found oprofile daemon running, please stop it and try again."); 2172 "We found oprofile daemon running, please stop it and try again.");
2137 break; 2173 break;
2174 case EINVAL:
2175 if (perf_missing_features.clockid)
2176 return scnprintf(msg, size, "clockid feature not supported.");
2177 if (perf_missing_features.clockid_wrong)
2178 return scnprintf(msg, size, "wrong clockid (%d).", clockid);
2179 break;
2138 default: 2180 default:
2139 break; 2181 break;
2140 } 2182 }
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 38622747d130..e486151b0308 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -335,6 +335,7 @@ struct perf_attr_details {
335 bool freq; 335 bool freq;
336 bool verbose; 336 bool verbose;
337 bool event_group; 337 bool event_group;
338 bool force;
338}; 339};
339 340
340int perf_evsel__fprintf(struct perf_evsel *evsel, 341int perf_evsel__fprintf(struct perf_evsel *evsel,
@@ -355,4 +356,14 @@ for ((_evsel) = list_entry((_leader)->node.next, struct perf_evsel, node); \
355 (_evsel) && (_evsel)->leader == (_leader); \ 356 (_evsel) && (_evsel)->leader == (_leader); \
356 (_evsel) = list_entry((_evsel)->node.next, struct perf_evsel, node)) 357 (_evsel) = list_entry((_evsel)->node.next, struct perf_evsel, node))
357 358
359static inline bool has_branch_callstack(struct perf_evsel *evsel)
360{
361 return evsel->attr.branch_sample_type & PERF_SAMPLE_BRANCH_CALL_STACK;
362}
363
364typedef int (*attr__fprintf_f)(FILE *, const char *, const char *, void *);
365
366int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr,
367 attr__fprintf_f attr__fprintf, void *priv);
368
358#endif /* __PERF_EVSEL_H */ 369#endif /* __PERF_EVSEL_H */
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 1f407f7352a7..918fd8ae2d80 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -1055,6 +1055,12 @@ error:
1055 goto out; 1055 goto out;
1056} 1056}
1057 1057
1058static int __desc_attr__fprintf(FILE *fp, const char *name, const char *val,
1059 void *priv __attribute__((unused)))
1060{
1061 return fprintf(fp, ", %s = %s", name, val);
1062}
1063
1058static void print_event_desc(struct perf_header *ph, int fd, FILE *fp) 1064static void print_event_desc(struct perf_header *ph, int fd, FILE *fp)
1059{ 1065{
1060 struct perf_evsel *evsel, *events = read_event_desc(ph, fd); 1066 struct perf_evsel *evsel, *events = read_event_desc(ph, fd);
@@ -1069,26 +1075,6 @@ static void print_event_desc(struct perf_header *ph, int fd, FILE *fp)
1069 for (evsel = events; evsel->attr.size; evsel++) { 1075 for (evsel = events; evsel->attr.size; evsel++) {
1070 fprintf(fp, "# event : name = %s, ", evsel->name); 1076 fprintf(fp, "# event : name = %s, ", evsel->name);
1071 1077
1072 fprintf(fp, "type = %d, config = 0x%"PRIx64
1073 ", config1 = 0x%"PRIx64", config2 = 0x%"PRIx64,
1074 evsel->attr.type,
1075 (u64)evsel->attr.config,
1076 (u64)evsel->attr.config1,
1077 (u64)evsel->attr.config2);
1078
1079 fprintf(fp, ", excl_usr = %d, excl_kern = %d",
1080 evsel->attr.exclude_user,
1081 evsel->attr.exclude_kernel);
1082
1083 fprintf(fp, ", excl_host = %d, excl_guest = %d",
1084 evsel->attr.exclude_host,
1085 evsel->attr.exclude_guest);
1086
1087 fprintf(fp, ", precise_ip = %d", evsel->attr.precise_ip);
1088
1089 fprintf(fp, ", attr_mmap2 = %d", evsel->attr.mmap2);
1090 fprintf(fp, ", attr_mmap = %d", evsel->attr.mmap);
1091 fprintf(fp, ", attr_mmap_data = %d", evsel->attr.mmap_data);
1092 if (evsel->ids) { 1078 if (evsel->ids) {
1093 fprintf(fp, ", id = {"); 1079 fprintf(fp, ", id = {");
1094 for (j = 0, id = evsel->id; j < evsel->ids; j++, id++) { 1080 for (j = 0, id = evsel->id; j < evsel->ids; j++, id++) {
@@ -1099,6 +1085,8 @@ static void print_event_desc(struct perf_header *ph, int fd, FILE *fp)
1099 fprintf(fp, " }"); 1085 fprintf(fp, " }");
1100 } 1086 }
1101 1087
1088 perf_event_attr__fprintf(fp, &evsel->attr, __desc_attr__fprintf, NULL);
1089
1102 fputc('\n', fp); 1090 fputc('\n', fp);
1103 } 1091 }
1104 1092
@@ -1266,7 +1254,7 @@ static int __event_process_build_id(struct build_id_event *bev,
1266 1254
1267 dso__set_build_id(dso, &bev->build_id); 1255 dso__set_build_id(dso, &bev->build_id);
1268 1256
1269 if (!is_kernel_module(filename, NULL)) 1257 if (!is_kernel_module(filename))
1270 dso->kernel = dso_type; 1258 dso->kernel = dso_type;
1271 1259
1272 build_id__sprintf(dso->build_id, sizeof(dso->build_id), 1260 build_id__sprintf(dso->build_id, sizeof(dso->build_id),
@@ -2516,8 +2504,11 @@ int perf_session__read_header(struct perf_session *session)
2516 if (read_attr(fd, header, &f_attr) < 0) 2504 if (read_attr(fd, header, &f_attr) < 0)
2517 goto out_errno; 2505 goto out_errno;
2518 2506
2519 if (header->needs_swap) 2507 if (header->needs_swap) {
2508 f_attr.ids.size = bswap_64(f_attr.ids.size);
2509 f_attr.ids.offset = bswap_64(f_attr.ids.offset);
2520 perf_event__attr_swap(&f_attr.attr); 2510 perf_event__attr_swap(&f_attr.attr);
2511 }
2521 2512
2522 tmp = lseek(fd, 0, SEEK_CUR); 2513 tmp = lseek(fd, 0, SEEK_CUR);
2523 evsel = perf_evsel__new(&f_attr.attr); 2514 evsel = perf_evsel__new(&f_attr.attr);
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/include/asm/alternative-asm.h b/tools/perf/util/include/asm/alternative-asm.h
index 6789d788d494..3a3a0f16456a 100644
--- a/tools/perf/util/include/asm/alternative-asm.h
+++ b/tools/perf/util/include/asm/alternative-asm.h
@@ -4,5 +4,6 @@
4/* Just disable it so we can build arch/x86/lib/memcpy_64.S for perf bench: */ 4/* Just disable it so we can build arch/x86/lib/memcpy_64.S for perf bench: */
5 5
6#define altinstruction_entry # 6#define altinstruction_entry #
7#define ALTERNATIVE_2 #
7 8
8#endif 9#endif
diff --git a/tools/perf/util/kvm-stat.h b/tools/perf/util/kvm-stat.h
index cf1d7913783b..ae825d4ec110 100644
--- a/tools/perf/util/kvm-stat.h
+++ b/tools/perf/util/kvm-stat.h
@@ -99,6 +99,7 @@ struct perf_kvm_stat {
99 int timerfd; 99 int timerfd;
100 unsigned int display_time; 100 unsigned int display_time;
101 bool live; 101 bool live;
102 bool force;
102}; 103};
103 104
104struct kvm_reg_events_ops { 105struct kvm_reg_events_ops {
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..527e032e24f6 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -89,16 +89,6 @@ static void dsos__delete(struct dsos *dsos)
89 } 89 }
90} 90}
91 91
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) 92void machine__delete_threads(struct machine *machine)
103{ 93{
104 struct rb_node *nd = rb_first(&machine->threads); 94 struct rb_node *nd = rb_first(&machine->threads);
@@ -106,9 +96,8 @@ void machine__delete_threads(struct machine *machine)
106 while (nd) { 96 while (nd) {
107 struct thread *t = rb_entry(nd, struct thread, rb_node); 97 struct thread *t = rb_entry(nd, struct thread, rb_node);
108 98
109 rb_erase(&t->rb_node, &machine->threads);
110 nd = rb_next(nd); 99 nd = rb_next(nd);
111 thread__delete(t); 100 machine__remove_thread(machine, t);
112 } 101 }
113} 102}
114 103
@@ -361,9 +350,13 @@ static struct thread *__machine__findnew_thread(struct machine *machine,
361 * the full rbtree: 350 * the full rbtree:
362 */ 351 */
363 th = machine->last_match; 352 th = machine->last_match;
364 if (th && th->tid == tid) { 353 if (th != NULL) {
365 machine__update_thread_pid(machine, th, pid); 354 if (th->tid == tid) {
366 return th; 355 machine__update_thread_pid(machine, th, pid);
356 return th;
357 }
358
359 thread__zput(machine->last_match);
367 } 360 }
368 361
369 while (*p != NULL) { 362 while (*p != NULL) {
@@ -371,7 +364,7 @@ static struct thread *__machine__findnew_thread(struct machine *machine,
371 th = rb_entry(parent, struct thread, rb_node); 364 th = rb_entry(parent, struct thread, rb_node);
372 365
373 if (th->tid == tid) { 366 if (th->tid == tid) {
374 machine->last_match = th; 367 machine->last_match = thread__get(th);
375 machine__update_thread_pid(machine, th, pid); 368 machine__update_thread_pid(machine, th, pid);
376 return th; 369 return th;
377 } 370 }
@@ -403,8 +396,11 @@ static struct thread *__machine__findnew_thread(struct machine *machine,
403 thread__delete(th); 396 thread__delete(th);
404 return NULL; 397 return NULL;
405 } 398 }
406 399 /*
407 machine->last_match = th; 400 * It is now in the rbtree, get a ref
401 */
402 thread__get(th);
403 machine->last_match = thread__get(th);
408 } 404 }
409 405
410 return th; 406 return th;
@@ -462,30 +458,61 @@ int machine__process_lost_event(struct machine *machine __maybe_unused,
462 return 0; 458 return 0;
463} 459}
464 460
461static struct dso*
462machine__module_dso(struct machine *machine, struct kmod_path *m,
463 const char *filename)
464{
465 struct dso *dso;
466
467 dso = dsos__find(&machine->kernel_dsos, m->name, true);
468 if (!dso) {
469 dso = dsos__addnew(&machine->kernel_dsos, m->name);
470 if (dso == NULL)
471 return NULL;
472
473 if (machine__is_host(machine))
474 dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE;
475 else
476 dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE;
477
478 /* _KMODULE_COMP should be next to _KMODULE */
479 if (m->kmod && m->comp)
480 dso->symtab_type++;
481
482 dso__set_short_name(dso, strdup(m->name), true);
483 dso__set_long_name(dso, strdup(filename), true);
484 }
485
486 return dso;
487}
488
465struct map *machine__new_module(struct machine *machine, u64 start, 489struct map *machine__new_module(struct machine *machine, u64 start,
466 const char *filename) 490 const char *filename)
467{ 491{
468 struct map *map; 492 struct map *map = NULL;
469 struct dso *dso = __dsos__findnew(&machine->kernel_dsos, filename); 493 struct dso *dso;
470 bool compressed; 494 struct kmod_path m;
471 495
472 if (dso == NULL) 496 if (kmod_path__parse_name(&m, filename))
473 return NULL; 497 return NULL;
474 498
475 map = map__new2(start, dso, MAP__FUNCTION); 499 map = map_groups__find_by_name(&machine->kmaps, MAP__FUNCTION,
476 if (map == NULL) 500 m.name);
477 return NULL; 501 if (map)
502 goto out;
478 503
479 if (machine__is_host(machine)) 504 dso = machine__module_dso(machine, &m, filename);
480 dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE; 505 if (dso == NULL)
481 else 506 goto out;
482 dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE;
483 507
484 /* _KMODULE_COMP should be next to _KMODULE */ 508 map = map__new2(start, dso, MAP__FUNCTION);
485 if (is_kernel_module(filename, &compressed) && compressed) 509 if (map == NULL)
486 dso->symtab_type++; 510 goto out;
487 511
488 map_groups__insert(&machine->kmaps, map); 512 map_groups__insert(&machine->kmaps, map);
513
514out:
515 free(m.name);
489 return map; 516 return map;
490} 517}
491 518
@@ -650,6 +677,9 @@ int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel)
650 machine->vmlinux_maps[type]->unmap_ip = 677 machine->vmlinux_maps[type]->unmap_ip =
651 identity__map_ip; 678 identity__map_ip;
652 kmap = map__kmap(machine->vmlinux_maps[type]); 679 kmap = map__kmap(machine->vmlinux_maps[type]);
680 if (!kmap)
681 return -1;
682
653 kmap->kmaps = &machine->kmaps; 683 kmap->kmaps = &machine->kmaps;
654 map_groups__insert(&machine->kmaps, 684 map_groups__insert(&machine->kmaps,
655 machine->vmlinux_maps[type]); 685 machine->vmlinux_maps[type]);
@@ -671,7 +701,7 @@ void machine__destroy_kernel_maps(struct machine *machine)
671 kmap = map__kmap(machine->vmlinux_maps[type]); 701 kmap = map__kmap(machine->vmlinux_maps[type]);
672 map_groups__remove(&machine->kmaps, 702 map_groups__remove(&machine->kmaps,
673 machine->vmlinux_maps[type]); 703 machine->vmlinux_maps[type]);
674 if (kmap->ref_reloc_sym) { 704 if (kmap && kmap->ref_reloc_sym) {
675 /* 705 /*
676 * ref_reloc_sym is shared among all maps, so free just 706 * ref_reloc_sym is shared among all maps, so free just
677 * on one of them. 707 * on one of them.
@@ -827,6 +857,39 @@ static char *get_kernel_version(const char *root_dir)
827 return strdup(name); 857 return strdup(name);
828} 858}
829 859
860static bool is_kmod_dso(struct dso *dso)
861{
862 return dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE ||
863 dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE;
864}
865
866static int map_groups__set_module_path(struct map_groups *mg, const char *path,
867 struct kmod_path *m)
868{
869 struct map *map;
870 char *long_name;
871
872 map = map_groups__find_by_name(mg, MAP__FUNCTION, m->name);
873 if (map == NULL)
874 return 0;
875
876 long_name = strdup(path);
877 if (long_name == NULL)
878 return -ENOMEM;
879
880 dso__set_long_name(map->dso, long_name, true);
881 dso__kernel_module_get_build_id(map->dso, "");
882
883 /*
884 * Full name could reveal us kmod compression, so
885 * we need to update the symtab_type if needed.
886 */
887 if (m->comp && is_kmod_dso(map->dso))
888 map->dso->symtab_type++;
889
890 return 0;
891}
892
830static int map_groups__set_modules_path_dir(struct map_groups *mg, 893static int map_groups__set_modules_path_dir(struct map_groups *mg,
831 const char *dir_name, int depth) 894 const char *dir_name, int depth)
832{ 895{
@@ -865,35 +928,19 @@ static int map_groups__set_modules_path_dir(struct map_groups *mg,
865 if (ret < 0) 928 if (ret < 0)
866 goto out; 929 goto out;
867 } else { 930 } else {
868 char *dot = strrchr(dent->d_name, '.'), 931 struct kmod_path m;
869 dso_name[PATH_MAX];
870 struct map *map;
871 char *long_name;
872 932
873 if (dot == NULL) 933 ret = kmod_path__parse_name(&m, dent->d_name);
874 continue; 934 if (ret)
875 935 goto out;
876 /* On some system, modules are compressed like .ko.gz */
877 if (is_supported_compression(dot + 1) &&
878 is_kmodule_extension(dot - 2))
879 dot -= 3;
880 936
881 snprintf(dso_name, sizeof(dso_name), "[%.*s]", 937 if (m.kmod)
882 (int)(dot - dent->d_name), dent->d_name); 938 ret = map_groups__set_module_path(mg, path, &m);
883 939
884 strxfrchar(dso_name, '-', '_'); 940 free(m.name);
885 map = map_groups__find_by_name(mg, MAP__FUNCTION,
886 dso_name);
887 if (map == NULL)
888 continue;
889 941
890 long_name = strdup(path); 942 if (ret)
891 if (long_name == NULL) {
892 ret = -1;
893 goto out; 943 goto out;
894 }
895 dso__set_long_name(map->dso, long_name, true);
896 dso__kernel_module_get_build_id(map->dso, "");
897 } 944 }
898 } 945 }
899 946
@@ -1046,40 +1093,11 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
1046 strlen(kmmap_prefix) - 1) == 0; 1093 strlen(kmmap_prefix) - 1) == 0;
1047 if (event->mmap.filename[0] == '/' || 1094 if (event->mmap.filename[0] == '/' ||
1048 (!is_kernel_mmap && event->mmap.filename[0] == '[')) { 1095 (!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, 1096 map = machine__new_module(machine, event->mmap.start,
1074 event->mmap.filename); 1097 event->mmap.filename);
1075 if (map == NULL) 1098 if (map == NULL)
1076 goto out_problem; 1099 goto out_problem;
1077 1100
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; 1101 map->end = map->start + event->mmap.len;
1084 } else if (is_kernel_mmap) { 1102 } else if (is_kernel_mmap) {
1085 const char *symbol_name = (event->mmap.filename + 1103 const char *symbol_name = (event->mmap.filename +
@@ -1092,7 +1110,7 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
1092 struct dso *dso; 1110 struct dso *dso;
1093 1111
1094 list_for_each_entry(dso, &machine->kernel_dsos.head, node) { 1112 list_for_each_entry(dso, &machine->kernel_dsos.head, node) {
1095 if (is_kernel_module(dso->long_name, NULL)) 1113 if (is_kernel_module(dso->long_name))
1096 continue; 1114 continue;
1097 1115
1098 kernel = dso; 1116 kernel = dso;
@@ -1236,15 +1254,19 @@ out_problem:
1236 return 0; 1254 return 0;
1237} 1255}
1238 1256
1239static void machine__remove_thread(struct machine *machine, struct thread *th) 1257void machine__remove_thread(struct machine *machine, struct thread *th)
1240{ 1258{
1241 machine->last_match = NULL; 1259 if (machine->last_match == th)
1260 thread__zput(machine->last_match);
1261
1242 rb_erase(&th->rb_node, &machine->threads); 1262 rb_erase(&th->rb_node, &machine->threads);
1243 /* 1263 /*
1244 * We may have references to this thread, for instance in some hist_entry 1264 * Move it first to the dead_threads list, then drop the reference,
1245 * instances, so just move them to a separate list. 1265 * if this is the last reference, then the thread__delete destructor
1266 * will be called and we will remove it from the dead_threads list.
1246 */ 1267 */
1247 list_add_tail(&th->node, &machine->dead_threads); 1268 list_add_tail(&th->node, &machine->dead_threads);
1269 thread__put(th);
1248} 1270}
1249 1271
1250int machine__process_fork_event(struct machine *machine, union perf_event *event, 1272int machine__process_fork_event(struct machine *machine, union perf_event *event,
@@ -1387,29 +1409,27 @@ struct mem_info *sample__resolve_mem(struct perf_sample *sample,
1387static int add_callchain_ip(struct thread *thread, 1409static int add_callchain_ip(struct thread *thread,
1388 struct symbol **parent, 1410 struct symbol **parent,
1389 struct addr_location *root_al, 1411 struct addr_location *root_al,
1390 bool branch_history, 1412 u8 *cpumode,
1391 u64 ip) 1413 u64 ip)
1392{ 1414{
1393 struct addr_location al; 1415 struct addr_location al;
1394 1416
1395 al.filtered = 0; 1417 al.filtered = 0;
1396 al.sym = NULL; 1418 al.sym = NULL;
1397 if (branch_history) 1419 if (!cpumode) {
1398 thread__find_cpumode_addr_location(thread, MAP__FUNCTION, 1420 thread__find_cpumode_addr_location(thread, MAP__FUNCTION,
1399 ip, &al); 1421 ip, &al);
1400 else { 1422 } else {
1401 u8 cpumode = PERF_RECORD_MISC_USER;
1402
1403 if (ip >= PERF_CONTEXT_MAX) { 1423 if (ip >= PERF_CONTEXT_MAX) {
1404 switch (ip) { 1424 switch (ip) {
1405 case PERF_CONTEXT_HV: 1425 case PERF_CONTEXT_HV:
1406 cpumode = PERF_RECORD_MISC_HYPERVISOR; 1426 *cpumode = PERF_RECORD_MISC_HYPERVISOR;
1407 break; 1427 break;
1408 case PERF_CONTEXT_KERNEL: 1428 case PERF_CONTEXT_KERNEL:
1409 cpumode = PERF_RECORD_MISC_KERNEL; 1429 *cpumode = PERF_RECORD_MISC_KERNEL;
1410 break; 1430 break;
1411 case PERF_CONTEXT_USER: 1431 case PERF_CONTEXT_USER:
1412 cpumode = PERF_RECORD_MISC_USER; 1432 *cpumode = PERF_RECORD_MISC_USER;
1413 break; 1433 break;
1414 default: 1434 default:
1415 pr_debug("invalid callchain context: " 1435 pr_debug("invalid callchain context: "
@@ -1423,8 +1443,8 @@ static int add_callchain_ip(struct thread *thread,
1423 } 1443 }
1424 return 0; 1444 return 0;
1425 } 1445 }
1426 thread__find_addr_location(thread, cpumode, MAP__FUNCTION, 1446 thread__find_addr_location(thread, *cpumode, MAP__FUNCTION,
1427 ip, &al); 1447 ip, &al);
1428 } 1448 }
1429 1449
1430 if (al.sym != NULL) { 1450 if (al.sym != NULL) {
@@ -1502,18 +1522,102 @@ static int remove_loops(struct branch_entry *l, int nr)
1502 return nr; 1522 return nr;
1503} 1523}
1504 1524
1505static int thread__resolve_callchain_sample(struct thread *thread, 1525/*
1506 struct ip_callchain *chain, 1526 * Recolve LBR callstack chain sample
1507 struct branch_stack *branch, 1527 * Return:
1508 struct symbol **parent, 1528 * 1 on success get LBR callchain information
1509 struct addr_location *root_al, 1529 * 0 no available LBR callchain information, should try fp
1510 int max_stack) 1530 * negative error code on other errors.
1531 */
1532static int resolve_lbr_callchain_sample(struct thread *thread,
1533 struct perf_sample *sample,
1534 struct symbol **parent,
1535 struct addr_location *root_al,
1536 int max_stack)
1511{ 1537{
1538 struct ip_callchain *chain = sample->callchain;
1512 int chain_nr = min(max_stack, (int)chain->nr); 1539 int chain_nr = min(max_stack, (int)chain->nr);
1540 u8 cpumode = PERF_RECORD_MISC_USER;
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, &cpumode, 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;
1606 int chain_nr = min(max_stack, (int)chain->nr);
1607 u8 cpumode = PERF_RECORD_MISC_USER;
1513 int i, j, err; 1608 int i, j, err;
1514 int skip_idx = -1; 1609 int skip_idx = -1;
1515 int first_call = 0; 1610 int first_call = 0;
1516 1611
1612 callchain_cursor_reset(&callchain_cursor);
1613
1614 if (has_branch_callstack(evsel)) {
1615 err = resolve_lbr_callchain_sample(thread, sample, parent,
1616 root_al, max_stack);
1617 if (err)
1618 return (err < 0) ? err : 0;
1619 }
1620
1517 /* 1621 /*
1518 * Based on DWARF debug information, some architectures skip 1622 * Based on DWARF debug information, some architectures skip
1519 * a callchain entry saved by the kernel. 1623 * a callchain entry saved by the kernel.
@@ -1521,8 +1625,6 @@ static int thread__resolve_callchain_sample(struct thread *thread,
1521 if (chain->nr < PERF_MAX_STACK_DEPTH) 1625 if (chain->nr < PERF_MAX_STACK_DEPTH)
1522 skip_idx = arch_skip_callchain_idx(thread, chain); 1626 skip_idx = arch_skip_callchain_idx(thread, chain);
1523 1627
1524 callchain_cursor_reset(&callchain_cursor);
1525
1526 /* 1628 /*
1527 * Add branches to call stack for easier browsing. This gives 1629 * Add branches to call stack for easier browsing. This gives
1528 * more context for a sample than just the callers. 1630 * more context for a sample than just the callers.
@@ -1568,10 +1670,10 @@ static int thread__resolve_callchain_sample(struct thread *thread,
1568 1670
1569 for (i = 0; i < nr; i++) { 1671 for (i = 0; i < nr; i++) {
1570 err = add_callchain_ip(thread, parent, root_al, 1672 err = add_callchain_ip(thread, parent, root_al,
1571 true, be[i].to); 1673 NULL, be[i].to);
1572 if (!err) 1674 if (!err)
1573 err = add_callchain_ip(thread, parent, root_al, 1675 err = add_callchain_ip(thread, parent, root_al,
1574 true, be[i].from); 1676 NULL, be[i].from);
1575 if (err == -EINVAL) 1677 if (err == -EINVAL)
1576 break; 1678 break;
1577 if (err) 1679 if (err)
@@ -1600,7 +1702,7 @@ check_calls:
1600#endif 1702#endif
1601 ip = chain->ips[j]; 1703 ip = chain->ips[j];
1602 1704
1603 err = add_callchain_ip(thread, parent, root_al, false, ip); 1705 err = add_callchain_ip(thread, parent, root_al, &cpumode, ip);
1604 1706
1605 if (err) 1707 if (err)
1606 return (err < 0) ? err : 0; 1708 return (err < 0) ? err : 0;
@@ -1623,9 +1725,9 @@ int thread__resolve_callchain(struct thread *thread,
1623 struct addr_location *root_al, 1725 struct addr_location *root_al,
1624 int max_stack) 1726 int max_stack)
1625{ 1727{
1626 int ret = thread__resolve_callchain_sample(thread, sample->callchain, 1728 int ret = thread__resolve_callchain_sample(thread, evsel,
1627 sample->branch_stack, 1729 sample, parent,
1628 parent, root_al, max_stack); 1730 root_al, max_stack);
1629 if (ret) 1731 if (ret)
1630 return ret; 1732 return ret;
1631 1733
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index e8b7779a0a3f..6d64cedb9d1e 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -118,9 +118,9 @@ 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);
123void machine__remove_thread(struct machine *machine, struct thread *th);
124 124
125struct branch_info *sample__resolve_bstack(struct perf_sample *sample, 125struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
126 struct addr_location *al); 126 struct addr_location *al);
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 62ca9f2607d5..a14f08f41686 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -778,3 +778,23 @@ struct map *maps__next(struct map *map)
778 return rb_entry(next, struct map, rb_node); 778 return rb_entry(next, struct map, rb_node);
779 return NULL; 779 return NULL;
780} 780}
781
782struct kmap *map__kmap(struct map *map)
783{
784 if (!map->dso || !map->dso->kernel) {
785 pr_err("Internal error: map__kmap with a non-kernel map\n");
786 return NULL;
787 }
788 return (struct kmap *)(map + 1);
789}
790
791struct map_groups *map__kmaps(struct map *map)
792{
793 struct kmap *kmap = map__kmap(map);
794
795 if (!kmap || !kmap->kmaps) {
796 pr_err("Internal error: map__kmaps with a non-kernel map\n");
797 return NULL;
798 }
799 return kmap->kmaps;
800}
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index 0e42438b1e59..ec19c59ca38e 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -76,10 +76,8 @@ static inline struct map_groups *map_groups__get(struct map_groups *mg)
76 76
77void map_groups__put(struct map_groups *mg); 77void map_groups__put(struct map_groups *mg);
78 78
79static inline struct kmap *map__kmap(struct map *map) 79struct kmap *map__kmap(struct map *map);
80{ 80struct map_groups *map__kmaps(struct map *map);
81 return (struct kmap *)(map + 1);
82}
83 81
84static inline u64 map__map_ip(struct map *map, u64 ip) 82static inline u64 map__map_ip(struct map *map, u64 ip)
85{ 83{
diff --git a/tools/perf/util/ordered-events.c b/tools/perf/util/ordered-events.c
index fd4be94125fb..52be201b9b25 100644
--- a/tools/perf/util/ordered-events.c
+++ b/tools/perf/util/ordered-events.c
@@ -2,7 +2,6 @@
2#include <linux/compiler.h> 2#include <linux/compiler.h>
3#include <linux/string.h> 3#include <linux/string.h>
4#include "ordered-events.h" 4#include "ordered-events.h"
5#include "evlist.h"
6#include "session.h" 5#include "session.h"
7#include "asm/bug.h" 6#include "asm/bug.h"
8#include "debug.h" 7#include "debug.h"
@@ -131,8 +130,8 @@ static struct ordered_event *alloc_event(struct ordered_events *oe,
131 return new; 130 return new;
132} 131}
133 132
134struct ordered_event * 133static struct ordered_event *
135ordered_events__new(struct ordered_events *oe, u64 timestamp, 134ordered_events__new_event(struct ordered_events *oe, u64 timestamp,
136 union perf_event *event) 135 union perf_event *event)
137{ 136{
138 struct ordered_event *new; 137 struct ordered_event *new;
@@ -153,20 +152,47 @@ void ordered_events__delete(struct ordered_events *oe, struct ordered_event *eve
153 free_dup_event(oe, event->event); 152 free_dup_event(oe, event->event);
154} 153}
155 154
156static int __ordered_events__flush(struct perf_session *s, 155int ordered_events__queue(struct ordered_events *oe, union perf_event *event,
157 struct perf_tool *tool) 156 struct perf_sample *sample, u64 file_offset)
157{
158 u64 timestamp = sample->time;
159 struct ordered_event *oevent;
160
161 if (!timestamp || timestamp == ~0ULL)
162 return -ETIME;
163
164 if (timestamp < oe->last_flush) {
165 pr_oe_time(timestamp, "out of order event\n");
166 pr_oe_time(oe->last_flush, "last flush, last_flush_type %d\n",
167 oe->last_flush_type);
168
169 oe->nr_unordered_events++;
170 }
171
172 oevent = ordered_events__new_event(oe, timestamp, event);
173 if (!oevent) {
174 ordered_events__flush(oe, OE_FLUSH__HALF);
175 oevent = ordered_events__new_event(oe, timestamp, event);
176 }
177
178 if (!oevent)
179 return -ENOMEM;
180
181 oevent->file_offset = file_offset;
182 return 0;
183}
184
185static int __ordered_events__flush(struct ordered_events *oe)
158{ 186{
159 struct ordered_events *oe = &s->ordered_events;
160 struct list_head *head = &oe->events; 187 struct list_head *head = &oe->events;
161 struct ordered_event *tmp, *iter; 188 struct ordered_event *tmp, *iter;
162 struct perf_sample sample;
163 u64 limit = oe->next_flush; 189 u64 limit = oe->next_flush;
164 u64 last_ts = oe->last ? oe->last->timestamp : 0ULL; 190 u64 last_ts = oe->last ? oe->last->timestamp : 0ULL;
165 bool show_progress = limit == ULLONG_MAX; 191 bool show_progress = limit == ULLONG_MAX;
166 struct ui_progress prog; 192 struct ui_progress prog;
167 int ret; 193 int ret;
168 194
169 if (!tool->ordered_events || !limit) 195 if (!limit)
170 return 0; 196 return 0;
171 197
172 if (show_progress) 198 if (show_progress)
@@ -178,16 +204,9 @@ static int __ordered_events__flush(struct perf_session *s,
178 204
179 if (iter->timestamp > limit) 205 if (iter->timestamp > limit)
180 break; 206 break;
181 207 ret = oe->deliver(oe, iter);
182 ret = perf_evlist__parse_sample(s->evlist, iter->event, &sample);
183 if (ret) 208 if (ret)
184 pr_err("Can't parse sample, err = %d\n", ret); 209 return ret;
185 else {
186 ret = perf_session__deliver_event(s, iter->event, &sample, tool,
187 iter->file_offset);
188 if (ret)
189 return ret;
190 }
191 210
192 ordered_events__delete(oe, iter); 211 ordered_events__delete(oe, iter);
193 oe->last_flush = iter->timestamp; 212 oe->last_flush = iter->timestamp;
@@ -204,10 +223,8 @@ static int __ordered_events__flush(struct perf_session *s,
204 return 0; 223 return 0;
205} 224}
206 225
207int ordered_events__flush(struct perf_session *s, struct perf_tool *tool, 226int ordered_events__flush(struct ordered_events *oe, enum oe_flush how)
208 enum oe_flush how)
209{ 227{
210 struct ordered_events *oe = &s->ordered_events;
211 static const char * const str[] = { 228 static const char * const str[] = {
212 "NONE", 229 "NONE",
213 "FINAL", 230 "FINAL",
@@ -216,6 +233,9 @@ int ordered_events__flush(struct perf_session *s, struct perf_tool *tool,
216 }; 233 };
217 int err; 234 int err;
218 235
236 if (oe->nr_events == 0)
237 return 0;
238
219 switch (how) { 239 switch (how) {
220 case OE_FLUSH__FINAL: 240 case OE_FLUSH__FINAL:
221 oe->next_flush = ULLONG_MAX; 241 oe->next_flush = ULLONG_MAX;
@@ -248,7 +268,7 @@ int ordered_events__flush(struct perf_session *s, struct perf_tool *tool,
248 str[how], oe->nr_events); 268 str[how], oe->nr_events);
249 pr_oe_time(oe->max_timestamp, "max_timestamp\n"); 269 pr_oe_time(oe->max_timestamp, "max_timestamp\n");
250 270
251 err = __ordered_events__flush(s, tool); 271 err = __ordered_events__flush(oe);
252 272
253 if (!err) { 273 if (!err) {
254 if (how == OE_FLUSH__ROUND) 274 if (how == OE_FLUSH__ROUND)
@@ -264,13 +284,14 @@ int ordered_events__flush(struct perf_session *s, struct perf_tool *tool,
264 return err; 284 return err;
265} 285}
266 286
267void ordered_events__init(struct ordered_events *oe) 287void ordered_events__init(struct ordered_events *oe, ordered_events__deliver_t deliver)
268{ 288{
269 INIT_LIST_HEAD(&oe->events); 289 INIT_LIST_HEAD(&oe->events);
270 INIT_LIST_HEAD(&oe->cache); 290 INIT_LIST_HEAD(&oe->cache);
271 INIT_LIST_HEAD(&oe->to_free); 291 INIT_LIST_HEAD(&oe->to_free);
272 oe->max_alloc_size = (u64) -1; 292 oe->max_alloc_size = (u64) -1;
273 oe->cur_alloc_size = 0; 293 oe->cur_alloc_size = 0;
294 oe->deliver = deliver;
274} 295}
275 296
276void ordered_events__free(struct ordered_events *oe) 297void 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..f403991e3bfd 100644
--- a/tools/perf/util/ordered-events.h
+++ b/tools/perf/util/ordered-events.h
@@ -2,9 +2,8 @@
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_sample;
8 7
9struct ordered_event { 8struct ordered_event {
10 u64 timestamp; 9 u64 timestamp;
@@ -20,6 +19,11 @@ enum oe_flush {
20 OE_FLUSH__HALF, 19 OE_FLUSH__HALF,
21}; 20};
22 21
22struct ordered_events;
23
24typedef int (*ordered_events__deliver_t)(struct ordered_events *oe,
25 struct ordered_event *event);
26
23struct ordered_events { 27struct ordered_events {
24 u64 last_flush; 28 u64 last_flush;
25 u64 next_flush; 29 u64 next_flush;
@@ -31,18 +35,19 @@ struct ordered_events {
31 struct list_head to_free; 35 struct list_head to_free;
32 struct ordered_event *buffer; 36 struct ordered_event *buffer;
33 struct ordered_event *last; 37 struct ordered_event *last;
38 ordered_events__deliver_t deliver;
34 int buffer_idx; 39 int buffer_idx;
35 unsigned int nr_events; 40 unsigned int nr_events;
36 enum oe_flush last_flush_type; 41 enum oe_flush last_flush_type;
42 u32 nr_unordered_events;
37 bool copy_on_queue; 43 bool copy_on_queue;
38}; 44};
39 45
40struct ordered_event *ordered_events__new(struct ordered_events *oe, u64 timestamp, 46int ordered_events__queue(struct ordered_events *oe, union perf_event *event,
41 union perf_event *event); 47 struct perf_sample *sample, u64 file_offset);
42void ordered_events__delete(struct ordered_events *oe, struct ordered_event *event); 48void ordered_events__delete(struct ordered_events *oe, struct ordered_event *event);
43int ordered_events__flush(struct perf_session *s, struct perf_tool *tool, 49int ordered_events__flush(struct ordered_events *oe, enum oe_flush how);
44 enum oe_flush how); 50void ordered_events__init(struct ordered_events *oe, ordered_events__deliver_t deliver);
45void ordered_events__init(struct ordered_events *oe);
46void ordered_events__free(struct ordered_events *oe); 51void ordered_events__free(struct ordered_events *oe);
47 52
48static inline 53static inline
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 7f8ec6ce2823..be0655388b38 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
@@ -723,6 +709,7 @@ struct event_modifier {
723 int eh; 709 int eh;
724 int eH; 710 int eH;
725 int eG; 711 int eG;
712 int eI;
726 int precise; 713 int precise;
727 int exclude_GH; 714 int exclude_GH;
728 int sample_read; 715 int sample_read;
@@ -737,6 +724,7 @@ static int get_event_modifier(struct event_modifier *mod, char *str,
737 int eh = evsel ? evsel->attr.exclude_hv : 0; 724 int eh = evsel ? evsel->attr.exclude_hv : 0;
738 int eH = evsel ? evsel->attr.exclude_host : 0; 725 int eH = evsel ? evsel->attr.exclude_host : 0;
739 int eG = evsel ? evsel->attr.exclude_guest : 0; 726 int eG = evsel ? evsel->attr.exclude_guest : 0;
727 int eI = evsel ? evsel->attr.exclude_idle : 0;
740 int precise = evsel ? evsel->attr.precise_ip : 0; 728 int precise = evsel ? evsel->attr.precise_ip : 0;
741 int sample_read = 0; 729 int sample_read = 0;
742 int pinned = evsel ? evsel->attr.pinned : 0; 730 int pinned = evsel ? evsel->attr.pinned : 0;
@@ -767,6 +755,8 @@ static int get_event_modifier(struct event_modifier *mod, char *str,
767 if (!exclude_GH) 755 if (!exclude_GH)
768 exclude_GH = eG = eH = 1; 756 exclude_GH = eG = eH = 1;
769 eH = 0; 757 eH = 0;
758 } else if (*str == 'I') {
759 eI = 1;
770 } else if (*str == 'p') { 760 } else if (*str == 'p') {
771 precise++; 761 precise++;
772 /* use of precise requires exclude_guest */ 762 /* use of precise requires exclude_guest */
@@ -800,6 +790,7 @@ static int get_event_modifier(struct event_modifier *mod, char *str,
800 mod->eh = eh; 790 mod->eh = eh;
801 mod->eH = eH; 791 mod->eH = eH;
802 mod->eG = eG; 792 mod->eG = eG;
793 mod->eI = eI;
803 mod->precise = precise; 794 mod->precise = precise;
804 mod->exclude_GH = exclude_GH; 795 mod->exclude_GH = exclude_GH;
805 mod->sample_read = sample_read; 796 mod->sample_read = sample_read;
@@ -817,7 +808,7 @@ static int check_modifier(char *str)
817 char *p = str; 808 char *p = str;
818 809
819 /* The sizeof includes 0 byte as well. */ 810 /* The sizeof includes 0 byte as well. */
820 if (strlen(str) > (sizeof("ukhGHpppSD") - 1)) 811 if (strlen(str) > (sizeof("ukhGHpppSDI") - 1))
821 return -1; 812 return -1;
822 813
823 while (*p) { 814 while (*p) {
@@ -853,6 +844,7 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add)
853 evsel->attr.precise_ip = mod.precise; 844 evsel->attr.precise_ip = mod.precise;
854 evsel->attr.exclude_host = mod.eH; 845 evsel->attr.exclude_host = mod.eH;
855 evsel->attr.exclude_guest = mod.eG; 846 evsel->attr.exclude_guest = mod.eG;
847 evsel->attr.exclude_idle = mod.eI;
856 evsel->exclude_GH = mod.exclude_GH; 848 evsel->exclude_GH = mod.exclude_GH;
857 evsel->sample_read = mod.sample_read; 849 evsel->sample_read = mod.sample_read;
858 850
@@ -1098,6 +1090,14 @@ static const char * const event_type_descriptors[] = {
1098 "Hardware breakpoint", 1090 "Hardware breakpoint",
1099}; 1091};
1100 1092
1093static int cmp_string(const void *a, const void *b)
1094{
1095 const char * const *as = a;
1096 const char * const *bs = b;
1097
1098 return strcmp(*as, *bs);
1099}
1100
1101/* 1101/*
1102 * Print the events from <debugfs_mount_point>/tracing/events 1102 * Print the events from <debugfs_mount_point>/tracing/events
1103 */ 1103 */
@@ -1109,18 +1109,21 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
1109 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; 1109 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
1110 char evt_path[MAXPATHLEN]; 1110 char evt_path[MAXPATHLEN];
1111 char dir_path[MAXPATHLEN]; 1111 char dir_path[MAXPATHLEN];
1112 char sbuf[STRERR_BUFSIZE]; 1112 char **evt_list = NULL;
1113 1113 unsigned int evt_i = 0, evt_num = 0;
1114 if (debugfs_valid_mountpoint(tracing_events_path)) { 1114 bool evt_num_known = false;
1115 printf(" [ Tracepoints not available: %s ]\n",
1116 strerror_r(errno, sbuf, sizeof(sbuf)));
1117 return;
1118 }
1119 1115
1116restart:
1120 sys_dir = opendir(tracing_events_path); 1117 sys_dir = opendir(tracing_events_path);
1121 if (!sys_dir) 1118 if (!sys_dir)
1122 return; 1119 return;
1123 1120
1121 if (evt_num_known) {
1122 evt_list = zalloc(sizeof(char *) * evt_num);
1123 if (!evt_list)
1124 goto out_close_sys_dir;
1125 }
1126
1124 for_each_subsystem(sys_dir, sys_dirent, sys_next) { 1127 for_each_subsystem(sys_dir, sys_dirent, sys_next) {
1125 if (subsys_glob != NULL && 1128 if (subsys_glob != NULL &&
1126 !strglobmatch(sys_dirent.d_name, subsys_glob)) 1129 !strglobmatch(sys_dirent.d_name, subsys_glob))
@@ -1137,19 +1140,56 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
1137 !strglobmatch(evt_dirent.d_name, event_glob)) 1140 !strglobmatch(evt_dirent.d_name, event_glob))
1138 continue; 1141 continue;
1139 1142
1140 if (name_only) { 1143 if (!evt_num_known) {
1141 printf("%s:%s ", sys_dirent.d_name, evt_dirent.d_name); 1144 evt_num++;
1142 continue; 1145 continue;
1143 } 1146 }
1144 1147
1145 snprintf(evt_path, MAXPATHLEN, "%s:%s", 1148 snprintf(evt_path, MAXPATHLEN, "%s:%s",
1146 sys_dirent.d_name, evt_dirent.d_name); 1149 sys_dirent.d_name, evt_dirent.d_name);
1147 printf(" %-50s [%s]\n", evt_path, 1150
1148 event_type_descriptors[PERF_TYPE_TRACEPOINT]); 1151 evt_list[evt_i] = strdup(evt_path);
1152 if (evt_list[evt_i] == NULL)
1153 goto out_close_evt_dir;
1154 evt_i++;
1149 } 1155 }
1150 closedir(evt_dir); 1156 closedir(evt_dir);
1151 } 1157 }
1152 closedir(sys_dir); 1158 closedir(sys_dir);
1159
1160 if (!evt_num_known) {
1161 evt_num_known = true;
1162 goto restart;
1163 }
1164 qsort(evt_list, evt_num, sizeof(char *), cmp_string);
1165 evt_i = 0;
1166 while (evt_i < evt_num) {
1167 if (name_only) {
1168 printf("%s ", evt_list[evt_i++]);
1169 continue;
1170 }
1171 printf(" %-50s [%s]\n", evt_list[evt_i++],
1172 event_type_descriptors[PERF_TYPE_TRACEPOINT]);
1173 }
1174 if (evt_num)
1175 printf("\n");
1176
1177out_free:
1178 evt_num = evt_i;
1179 for (evt_i = 0; evt_i < evt_num; evt_i++)
1180 zfree(&evt_list[evt_i]);
1181 zfree(&evt_list);
1182 return;
1183
1184out_close_evt_dir:
1185 closedir(evt_dir);
1186out_close_sys_dir:
1187 closedir(sys_dir);
1188
1189 printf("FATAL: not enough memory to print %s\n",
1190 event_type_descriptors[PERF_TYPE_TRACEPOINT]);
1191 if (evt_list)
1192 goto out_free;
1153} 1193}
1154 1194
1155/* 1195/*
@@ -1163,9 +1203,6 @@ int is_valid_tracepoint(const char *event_string)
1163 char evt_path[MAXPATHLEN]; 1203 char evt_path[MAXPATHLEN];
1164 char dir_path[MAXPATHLEN]; 1204 char dir_path[MAXPATHLEN];
1165 1205
1166 if (debugfs_valid_mountpoint(tracing_events_path))
1167 return 0;
1168
1169 sys_dir = opendir(tracing_events_path); 1206 sys_dir = opendir(tracing_events_path);
1170 if (!sys_dir) 1207 if (!sys_dir)
1171 return 0; 1208 return 0;
@@ -1233,38 +1270,19 @@ static bool is_event_supported(u8 type, unsigned config)
1233 return ret; 1270 return ret;
1234} 1271}
1235 1272
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) 1273int print_hwcache_events(const char *event_glob, bool name_only)
1265{ 1274{
1266 unsigned int type, op, i, printed = 0; 1275 unsigned int type, op, i, evt_i = 0, evt_num = 0;
1267 char name[64]; 1276 char name[64];
1277 char **evt_list = NULL;
1278 bool evt_num_known = false;
1279
1280restart:
1281 if (evt_num_known) {
1282 evt_list = zalloc(sizeof(char *) * evt_num);
1283 if (!evt_list)
1284 goto out_enomem;
1285 }
1268 1286
1269 for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) { 1287 for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
1270 for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) { 1288 for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
@@ -1282,27 +1300,66 @@ int print_hwcache_events(const char *event_glob, bool name_only)
1282 type | (op << 8) | (i << 16))) 1300 type | (op << 8) | (i << 16)))
1283 continue; 1301 continue;
1284 1302
1285 if (name_only) 1303 if (!evt_num_known) {
1286 printf("%s ", name); 1304 evt_num++;
1287 else 1305 continue;
1288 printf(" %-50s [%s]\n", name, 1306 }
1289 event_type_descriptors[PERF_TYPE_HW_CACHE]); 1307
1290 ++printed; 1308 evt_list[evt_i] = strdup(name);
1309 if (evt_list[evt_i] == NULL)
1310 goto out_enomem;
1311 evt_i++;
1291 } 1312 }
1292 } 1313 }
1293 } 1314 }
1294 1315
1295 if (printed) 1316 if (!evt_num_known) {
1317 evt_num_known = true;
1318 goto restart;
1319 }
1320 qsort(evt_list, evt_num, sizeof(char *), cmp_string);
1321 evt_i = 0;
1322 while (evt_i < evt_num) {
1323 if (name_only) {
1324 printf("%s ", evt_list[evt_i++]);
1325 continue;
1326 }
1327 printf(" %-50s [%s]\n", evt_list[evt_i++],
1328 event_type_descriptors[PERF_TYPE_HW_CACHE]);
1329 }
1330 if (evt_num)
1296 printf("\n"); 1331 printf("\n");
1297 return printed; 1332
1333out_free:
1334 evt_num = evt_i;
1335 for (evt_i = 0; evt_i < evt_num; evt_i++)
1336 zfree(&evt_list[evt_i]);
1337 zfree(&evt_list);
1338 return evt_num;
1339
1340out_enomem:
1341 printf("FATAL: not enough memory to print %s\n", event_type_descriptors[PERF_TYPE_HW_CACHE]);
1342 if (evt_list)
1343 goto out_free;
1344 return evt_num;
1298} 1345}
1299 1346
1300static void print_symbol_events(const char *event_glob, unsigned type, 1347void print_symbol_events(const char *event_glob, unsigned type,
1301 struct event_symbol *syms, unsigned max, 1348 struct event_symbol *syms, unsigned max,
1302 bool name_only) 1349 bool name_only)
1303{ 1350{
1304 unsigned i, printed = 0; 1351 unsigned int i, evt_i = 0, evt_num = 0;
1305 char name[MAX_NAME_LEN]; 1352 char name[MAX_NAME_LEN];
1353 char **evt_list = NULL;
1354 bool evt_num_known = false;
1355
1356restart:
1357 if (evt_num_known) {
1358 evt_list = zalloc(sizeof(char *) * evt_num);
1359 if (!evt_list)
1360 goto out_enomem;
1361 syms -= max;
1362 }
1306 1363
1307 for (i = 0; i < max; i++, syms++) { 1364 for (i = 0; i < max; i++, syms++) {
1308 1365
@@ -1314,23 +1371,49 @@ static void print_symbol_events(const char *event_glob, unsigned type,
1314 if (!is_event_supported(type, i)) 1371 if (!is_event_supported(type, i))
1315 continue; 1372 continue;
1316 1373
1317 if (name_only) { 1374 if (!evt_num_known) {
1318 printf("%s ", syms->symbol); 1375 evt_num++;
1319 continue; 1376 continue;
1320 } 1377 }
1321 1378
1322 if (strlen(syms->alias)) 1379 if (!name_only && strlen(syms->alias))
1323 snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias); 1380 snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias);
1324 else 1381 else
1325 strncpy(name, syms->symbol, MAX_NAME_LEN); 1382 strncpy(name, syms->symbol, MAX_NAME_LEN);
1326 1383
1327 printf(" %-50s [%s]\n", name, event_type_descriptors[type]); 1384 evt_list[evt_i] = strdup(name);
1328 1385 if (evt_list[evt_i] == NULL)
1329 printed++; 1386 goto out_enomem;
1387 evt_i++;
1330 } 1388 }
1331 1389
1332 if (printed) 1390 if (!evt_num_known) {
1391 evt_num_known = true;
1392 goto restart;
1393 }
1394 qsort(evt_list, evt_num, sizeof(char *), cmp_string);
1395 evt_i = 0;
1396 while (evt_i < evt_num) {
1397 if (name_only) {
1398 printf("%s ", evt_list[evt_i++]);
1399 continue;
1400 }
1401 printf(" %-50s [%s]\n", evt_list[evt_i++], event_type_descriptors[type]);
1402 }
1403 if (evt_num)
1333 printf("\n"); 1404 printf("\n");
1405
1406out_free:
1407 evt_num = evt_i;
1408 for (evt_i = 0; evt_i < evt_num; evt_i++)
1409 zfree(&evt_list[evt_i]);
1410 zfree(&evt_list);
1411 return;
1412
1413out_enomem:
1414 printf("FATAL: not enough memory to print %s\n", event_type_descriptors[type]);
1415 if (evt_list)
1416 goto out_free;
1334} 1417}
1335 1418
1336/* 1419/*
@@ -1338,11 +1421,6 @@ static void print_symbol_events(const char *event_glob, unsigned type,
1338 */ 1421 */
1339void print_events(const char *event_glob, bool name_only) 1422void print_events(const char *event_glob, bool name_only)
1340{ 1423{
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, 1424 print_symbol_events(event_glob, PERF_TYPE_HARDWARE,
1347 event_symbols_hw, PERF_COUNT_HW_MAX, name_only); 1425 event_symbols_hw, PERF_COUNT_HW_MAX, name_only);
1348 1426
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-events.l b/tools/perf/util/parse-events.l
index 94eacb6c1ef7..8895cf3132ab 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -101,7 +101,7 @@ num_raw_hex [a-fA-F0-9]+
101name [a-zA-Z_*?][a-zA-Z0-9_*?]* 101name [a-zA-Z_*?][a-zA-Z0-9_*?]*
102name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?]* 102name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?]*
103/* If you add a modifier you need to update check_modifier() */ 103/* If you add a modifier you need to update check_modifier() */
104modifier_event [ukhpGHSD]+ 104modifier_event [ukhpGHSDI]+
105modifier_bp [rwx]{1,3} 105modifier_bp [rwx]{1,3}
106 106
107%% 107%%
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..d8bb616ff57c 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");
@@ -133,6 +135,8 @@ static struct ref_reloc_sym *kernel_get_ref_reloc_sym(void)
133 return NULL; 135 return NULL;
134 136
135 kmap = map__kmap(host_machine->vmlinux_maps[MAP__FUNCTION]); 137 kmap = map__kmap(host_machine->vmlinux_maps[MAP__FUNCTION]);
138 if (!kmap)
139 return NULL;
136 return kmap->ref_reloc_sym; 140 return kmap->ref_reloc_sym;
137} 141}
138 142
@@ -150,7 +154,7 @@ static u64 kernel_get_symbol_address_by_name(const char *name, bool reloc)
150 sym = __find_kernel_function_by_name(name, &map); 154 sym = __find_kernel_function_by_name(name, &map);
151 if (sym) 155 if (sym)
152 return map->unmap_ip(map, sym->start) - 156 return map->unmap_ip(map, sym->start) -
153 (reloc) ? 0 : map->reloc; 157 ((reloc) ? 0 : map->reloc);
154 } 158 }
155 return 0; 159 return 0;
156} 160}
@@ -177,6 +181,25 @@ static struct map *kernel_get_module_map(const char *module)
177 return NULL; 181 return NULL;
178} 182}
179 183
184static struct map *get_target_map(const char *target, bool user)
185{
186 /* Init maps of given executable or kernel */
187 if (user)
188 return dso__new_map(target);
189 else
190 return kernel_get_module_map(target);
191}
192
193static void put_target_map(struct map *map, bool user)
194{
195 if (map && user) {
196 /* Only the user map needs to be released */
197 dso__delete(map->dso);
198 map__delete(map);
199 }
200}
201
202
180static struct dso *kernel_get_module_dso(const char *module) 203static struct dso *kernel_get_module_dso(const char *module)
181{ 204{
182 struct dso *dso; 205 struct dso *dso;
@@ -248,6 +271,13 @@ out:
248 return ret; 271 return ret;
249} 272}
250 273
274static void clear_perf_probe_point(struct perf_probe_point *pp)
275{
276 free(pp->file);
277 free(pp->function);
278 free(pp->lazy_line);
279}
280
251static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs) 281static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs)
252{ 282{
253 int i; 283 int i;
@@ -257,6 +287,104 @@ static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs)
257} 287}
258 288
259#ifdef HAVE_DWARF_SUPPORT 289#ifdef HAVE_DWARF_SUPPORT
290/*
291 * Some binaries like glibc have special symbols which are on the symbol
292 * table, but not in the debuginfo. If we can find the address of the
293 * symbol from map, we can translate the address back to the probe point.
294 */
295static int find_alternative_probe_point(struct debuginfo *dinfo,
296 struct perf_probe_point *pp,
297 struct perf_probe_point *result,
298 const char *target, bool uprobes)
299{
300 struct map *map = NULL;
301 struct symbol *sym;
302 u64 address = 0;
303 int ret = -ENOENT;
304
305 /* This can work only for function-name based one */
306 if (!pp->function || pp->file)
307 return -ENOTSUP;
308
309 map = get_target_map(target, uprobes);
310 if (!map)
311 return -EINVAL;
312
313 /* Find the address of given function */
314 map__for_each_symbol_by_name(map, pp->function, sym) {
315 if (uprobes)
316 address = sym->start;
317 else
318 address = map->unmap_ip(map, sym->start);
319 break;
320 }
321 if (!address) {
322 ret = -ENOENT;
323 goto out;
324 }
325 pr_debug("Symbol %s address found : %" PRIx64 "\n",
326 pp->function, address);
327
328 ret = debuginfo__find_probe_point(dinfo, (unsigned long)address,
329 result);
330 if (ret <= 0)
331 ret = (!ret) ? -ENOENT : ret;
332 else {
333 result->offset += pp->offset;
334 result->line += pp->line;
335 result->retprobe = pp->retprobe;
336 ret = 0;
337 }
338
339out:
340 put_target_map(map, uprobes);
341 return ret;
342
343}
344
345static int get_alternative_probe_event(struct debuginfo *dinfo,
346 struct perf_probe_event *pev,
347 struct perf_probe_point *tmp,
348 const char *target)
349{
350 int ret;
351
352 memcpy(tmp, &pev->point, sizeof(*tmp));
353 memset(&pev->point, 0, sizeof(pev->point));
354 ret = find_alternative_probe_point(dinfo, tmp, &pev->point,
355 target, pev->uprobes);
356 if (ret < 0)
357 memcpy(&pev->point, tmp, sizeof(*tmp));
358
359 return ret;
360}
361
362static int get_alternative_line_range(struct debuginfo *dinfo,
363 struct line_range *lr,
364 const char *target, bool user)
365{
366 struct perf_probe_point pp = { .function = lr->function,
367 .file = lr->file,
368 .line = lr->start };
369 struct perf_probe_point result;
370 int ret, len = 0;
371
372 memset(&result, 0, sizeof(result));
373
374 if (lr->end != INT_MAX)
375 len = lr->end - lr->start;
376 ret = find_alternative_probe_point(dinfo, &pp, &result,
377 target, user);
378 if (!ret) {
379 lr->function = result.function;
380 lr->file = result.file;
381 lr->start = result.line;
382 if (lr->end != INT_MAX)
383 lr->end = lr->start + len;
384 clear_perf_probe_point(&pp);
385 }
386 return ret;
387}
260 388
261/* Open new debuginfo of given module */ 389/* Open new debuginfo of given module */
262static struct debuginfo *open_debuginfo(const char *module, bool silent) 390static struct debuginfo *open_debuginfo(const char *module, bool silent)
@@ -465,6 +593,7 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
465 int max_tevs, const char *target) 593 int max_tevs, const char *target)
466{ 594{
467 bool need_dwarf = perf_probe_event_need_dwarf(pev); 595 bool need_dwarf = perf_probe_event_need_dwarf(pev);
596 struct perf_probe_point tmp;
468 struct debuginfo *dinfo; 597 struct debuginfo *dinfo;
469 int ntevs, ret = 0; 598 int ntevs, ret = 0;
470 599
@@ -481,6 +610,20 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
481 /* Searching trace events corresponding to a probe event */ 610 /* Searching trace events corresponding to a probe event */
482 ntevs = debuginfo__find_trace_events(dinfo, pev, tevs, max_tevs); 611 ntevs = debuginfo__find_trace_events(dinfo, pev, tevs, max_tevs);
483 612
613 if (ntevs == 0) { /* Not found, retry with an alternative */
614 ret = get_alternative_probe_event(dinfo, pev, &tmp, target);
615 if (!ret) {
616 ntevs = debuginfo__find_trace_events(dinfo, pev,
617 tevs, max_tevs);
618 /*
619 * Write back to the original probe_event for
620 * setting appropriate (user given) event name
621 */
622 clear_perf_probe_point(&pev->point);
623 memcpy(&pev->point, &tmp, sizeof(tmp));
624 }
625 }
626
484 debuginfo__delete(dinfo); 627 debuginfo__delete(dinfo);
485 628
486 if (ntevs > 0) { /* Succeeded to find trace events */ 629 if (ntevs > 0) { /* Succeeded to find trace events */
@@ -495,11 +638,9 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
495 } 638 }
496 639
497 if (ntevs == 0) { /* No error but failed to find probe point. */ 640 if (ntevs == 0) { /* No error but failed to find probe point. */
498 pr_warning("Probe point '%s' not found in debuginfo.\n", 641 pr_warning("Probe point '%s' not found.\n",
499 synthesize_perf_probe_point(&pev->point)); 642 synthesize_perf_probe_point(&pev->point));
500 if (need_dwarf) 643 return -ENOENT;
501 return -ENOENT;
502 return 0;
503 } 644 }
504 /* Error path : ntevs < 0 */ 645 /* Error path : ntevs < 0 */
505 pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs); 646 pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs);
@@ -514,63 +655,6 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
514 return ntevs; 655 return ntevs;
515} 656}
516 657
517/*
518 * Find a src file from a DWARF tag path. Prepend optional source path prefix
519 * and chop off leading directories that do not exist. Result is passed back as
520 * a newly allocated path on success.
521 * Return 0 if file was found and readable, -errno otherwise.
522 */
523static int get_real_path(const char *raw_path, const char *comp_dir,
524 char **new_path)
525{
526 const char *prefix = symbol_conf.source_prefix;
527
528 if (!prefix) {
529 if (raw_path[0] != '/' && comp_dir)
530 /* If not an absolute path, try to use comp_dir */
531 prefix = comp_dir;
532 else {
533 if (access(raw_path, R_OK) == 0) {
534 *new_path = strdup(raw_path);
535 return 0;
536 } else
537 return -errno;
538 }
539 }
540
541 *new_path = malloc((strlen(prefix) + strlen(raw_path) + 2));
542 if (!*new_path)
543 return -ENOMEM;
544
545 for (;;) {
546 sprintf(*new_path, "%s/%s", prefix, raw_path);
547
548 if (access(*new_path, R_OK) == 0)
549 return 0;
550
551 if (!symbol_conf.source_prefix)
552 /* In case of searching comp_dir, don't retry */
553 return -errno;
554
555 switch (errno) {
556 case ENAMETOOLONG:
557 case ENOENT:
558 case EROFS:
559 case EFAULT:
560 raw_path = strchr(++raw_path, '/');
561 if (!raw_path) {
562 zfree(new_path);
563 return -ENOENT;
564 }
565 continue;
566
567 default:
568 zfree(new_path);
569 return -errno;
570 }
571 }
572}
573
574#define LINEBUF_SIZE 256 658#define LINEBUF_SIZE 256
575#define NR_ADDITIONAL_LINES 2 659#define NR_ADDITIONAL_LINES 2
576 660
@@ -622,7 +706,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 706 * Show line-range always requires debuginfo to find source file and
623 * line number. 707 * line number.
624 */ 708 */
625static int __show_line_range(struct line_range *lr, const char *module) 709static int __show_line_range(struct line_range *lr, const char *module,
710 bool user)
626{ 711{
627 int l = 1; 712 int l = 1;
628 struct int_node *ln; 713 struct int_node *ln;
@@ -638,6 +723,11 @@ static int __show_line_range(struct line_range *lr, const char *module)
638 return -ENOENT; 723 return -ENOENT;
639 724
640 ret = debuginfo__find_line_range(dinfo, lr); 725 ret = debuginfo__find_line_range(dinfo, lr);
726 if (!ret) { /* Not found, retry with an alternative */
727 ret = get_alternative_line_range(dinfo, lr, module, user);
728 if (!ret)
729 ret = debuginfo__find_line_range(dinfo, lr);
730 }
641 debuginfo__delete(dinfo); 731 debuginfo__delete(dinfo);
642 if (ret == 0 || ret == -ENOENT) { 732 if (ret == 0 || ret == -ENOENT) {
643 pr_warning("Specified source line is not found.\n"); 733 pr_warning("Specified source line is not found.\n");
@@ -650,7 +740,11 @@ static int __show_line_range(struct line_range *lr, const char *module)
650 /* Convert source file path */ 740 /* Convert source file path */
651 tmp = lr->path; 741 tmp = lr->path;
652 ret = get_real_path(tmp, lr->comp_dir, &lr->path); 742 ret = get_real_path(tmp, lr->comp_dir, &lr->path);
653 free(tmp); /* Free old path */ 743
744 /* Free old path when new path is assigned */
745 if (tmp != lr->path)
746 free(tmp);
747
654 if (ret < 0) { 748 if (ret < 0) {
655 pr_warning("Failed to find source file path.\n"); 749 pr_warning("Failed to find source file path.\n");
656 return ret; 750 return ret;
@@ -707,7 +801,7 @@ int show_line_range(struct line_range *lr, const char *module, bool user)
707 ret = init_symbol_maps(user); 801 ret = init_symbol_maps(user);
708 if (ret < 0) 802 if (ret < 0)
709 return ret; 803 return ret;
710 ret = __show_line_range(lr, module); 804 ret = __show_line_range(lr, module, user);
711 exit_symbol_maps(); 805 exit_symbol_maps();
712 806
713 return ret; 807 return ret;
@@ -716,12 +810,13 @@ int show_line_range(struct line_range *lr, const char *module, bool user)
716static int show_available_vars_at(struct debuginfo *dinfo, 810static int show_available_vars_at(struct debuginfo *dinfo,
717 struct perf_probe_event *pev, 811 struct perf_probe_event *pev,
718 int max_vls, struct strfilter *_filter, 812 int max_vls, struct strfilter *_filter,
719 bool externs) 813 bool externs, const char *target)
720{ 814{
721 char *buf; 815 char *buf;
722 int ret, i, nvars; 816 int ret, i, nvars;
723 struct str_node *node; 817 struct str_node *node;
724 struct variable_list *vls = NULL, *vl; 818 struct variable_list *vls = NULL, *vl;
819 struct perf_probe_point tmp;
725 const char *var; 820 const char *var;
726 821
727 buf = synthesize_perf_probe_point(&pev->point); 822 buf = synthesize_perf_probe_point(&pev->point);
@@ -731,6 +826,15 @@ static int show_available_vars_at(struct debuginfo *dinfo,
731 826
732 ret = debuginfo__find_available_vars_at(dinfo, pev, &vls, 827 ret = debuginfo__find_available_vars_at(dinfo, pev, &vls,
733 max_vls, externs); 828 max_vls, externs);
829 if (!ret) { /* Not found, retry with an alternative */
830 ret = get_alternative_probe_event(dinfo, pev, &tmp, target);
831 if (!ret) {
832 ret = debuginfo__find_available_vars_at(dinfo, pev,
833 &vls, max_vls, externs);
834 /* Release the old probe_point */
835 clear_perf_probe_point(&tmp);
836 }
837 }
734 if (ret <= 0) { 838 if (ret <= 0) {
735 if (ret == 0 || ret == -ENOENT) { 839 if (ret == 0 || ret == -ENOENT) {
736 pr_err("Failed to find the address of %s\n", buf); 840 pr_err("Failed to find the address of %s\n", buf);
@@ -793,7 +897,7 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
793 897
794 for (i = 0; i < npevs && ret >= 0; i++) 898 for (i = 0; i < npevs && ret >= 0; i++)
795 ret = show_available_vars_at(dinfo, &pevs[i], max_vls, _filter, 899 ret = show_available_vars_at(dinfo, &pevs[i], max_vls, _filter,
796 externs); 900 externs, module);
797 901
798 debuginfo__delete(dinfo); 902 debuginfo__delete(dinfo);
799out: 903out:
@@ -1739,15 +1843,13 @@ static int convert_to_perf_probe_event(struct probe_trace_event *tev,
1739 1843
1740void clear_perf_probe_event(struct perf_probe_event *pev) 1844void clear_perf_probe_event(struct perf_probe_event *pev)
1741{ 1845{
1742 struct perf_probe_point *pp = &pev->point;
1743 struct perf_probe_arg_field *field, *next; 1846 struct perf_probe_arg_field *field, *next;
1744 int i; 1847 int i;
1745 1848
1746 free(pev->event); 1849 free(pev->event);
1747 free(pev->group); 1850 free(pev->group);
1748 free(pp->file); 1851 free(pev->target);
1749 free(pp->function); 1852 clear_perf_probe_point(&pev->point);
1750 free(pp->lazy_line);
1751 1853
1752 for (i = 0; i < pev->nargs; i++) { 1854 for (i = 0; i < pev->nargs; i++) {
1753 free(pev->args[i].name); 1855 free(pev->args[i].name);
@@ -1805,7 +1907,7 @@ static void print_open_warning(int err, bool is_kprobe)
1805 " - please rebuild kernel with %s.\n", 1907 " - please rebuild kernel with %s.\n",
1806 is_kprobe ? 'k' : 'u', config); 1908 is_kprobe ? 'k' : 'u', config);
1807 } else if (err == -ENOTSUP) 1909 } else if (err == -ENOTSUP)
1808 pr_warning("Debugfs is not mounted.\n"); 1910 pr_warning("Tracefs or debugfs is not mounted.\n");
1809 else 1911 else
1810 pr_warning("Failed to open %cprobe_events: %s\n", 1912 pr_warning("Failed to open %cprobe_events: %s\n",
1811 is_kprobe ? 'k' : 'u', 1913 is_kprobe ? 'k' : 'u',
@@ -1816,7 +1918,7 @@ static void print_both_open_warning(int kerr, int uerr)
1816{ 1918{
1817 /* Both kprobes and uprobes are disabled, warn it. */ 1919 /* Both kprobes and uprobes are disabled, warn it. */
1818 if (kerr == -ENOTSUP && uerr == -ENOTSUP) 1920 if (kerr == -ENOTSUP && uerr == -ENOTSUP)
1819 pr_warning("Debugfs is not mounted.\n"); 1921 pr_warning("Tracefs or debugfs is not mounted.\n");
1820 else if (kerr == -ENOENT && uerr == -ENOENT) 1922 else if (kerr == -ENOENT && uerr == -ENOENT)
1821 pr_warning("Please rebuild kernel with CONFIG_KPROBE_EVENTS " 1923 pr_warning("Please rebuild kernel with CONFIG_KPROBE_EVENTS "
1822 "or/and CONFIG_UPROBE_EVENTS.\n"); 1924 "or/and CONFIG_UPROBE_EVENTS.\n");
@@ -1833,13 +1935,20 @@ static int open_probe_events(const char *trace_file, bool readwrite)
1833{ 1935{
1834 char buf[PATH_MAX]; 1936 char buf[PATH_MAX];
1835 const char *__debugfs; 1937 const char *__debugfs;
1938 const char *tracing_dir = "";
1836 int ret; 1939 int ret;
1837 1940
1838 __debugfs = debugfs_find_mountpoint(); 1941 __debugfs = tracefs_find_mountpoint();
1839 if (__debugfs == NULL) 1942 if (__debugfs == NULL) {
1840 return -ENOTSUP; 1943 tracing_dir = "tracing/";
1944
1945 __debugfs = debugfs_find_mountpoint();
1946 if (__debugfs == NULL)
1947 return -ENOTSUP;
1948 }
1841 1949
1842 ret = e_snprintf(buf, PATH_MAX, "%s/%s", __debugfs, trace_file); 1950 ret = e_snprintf(buf, PATH_MAX, "%s/%s%s",
1951 __debugfs, tracing_dir, trace_file);
1843 if (ret >= 0) { 1952 if (ret >= 0) {
1844 pr_debug("Opening %s write=%d\n", buf, readwrite); 1953 pr_debug("Opening %s write=%d\n", buf, readwrite);
1845 if (readwrite && !probe_event_dry_run) 1954 if (readwrite && !probe_event_dry_run)
@@ -1855,12 +1964,12 @@ static int open_probe_events(const char *trace_file, bool readwrite)
1855 1964
1856static int open_kprobe_events(bool readwrite) 1965static int open_kprobe_events(bool readwrite)
1857{ 1966{
1858 return open_probe_events("tracing/kprobe_events", readwrite); 1967 return open_probe_events("kprobe_events", readwrite);
1859} 1968}
1860 1969
1861static int open_uprobe_events(bool readwrite) 1970static int open_uprobe_events(bool readwrite)
1862{ 1971{
1863 return open_probe_events("tracing/uprobe_events", readwrite); 1972 return open_probe_events("uprobe_events", readwrite);
1864} 1973}
1865 1974
1866/* Get raw string list of current kprobe_events or uprobe_events */ 1975/* Get raw string list of current kprobe_events or uprobe_events */
@@ -1895,6 +2004,95 @@ static struct strlist *get_probe_trace_command_rawlist(int fd)
1895 return sl; 2004 return sl;
1896} 2005}
1897 2006
2007struct kprobe_blacklist_node {
2008 struct list_head list;
2009 unsigned long start;
2010 unsigned long end;
2011 char *symbol;
2012};
2013
2014static void kprobe_blacklist__delete(struct list_head *blacklist)
2015{
2016 struct kprobe_blacklist_node *node;
2017
2018 while (!list_empty(blacklist)) {
2019 node = list_first_entry(blacklist,
2020 struct kprobe_blacklist_node, list);
2021 list_del(&node->list);
2022 free(node->symbol);
2023 free(node);
2024 }
2025}
2026
2027static int kprobe_blacklist__load(struct list_head *blacklist)
2028{
2029 struct kprobe_blacklist_node *node;
2030 const char *__debugfs = debugfs_find_mountpoint();
2031 char buf[PATH_MAX], *p;
2032 FILE *fp;
2033 int ret;
2034
2035 if (__debugfs == NULL)
2036 return -ENOTSUP;
2037
2038 ret = e_snprintf(buf, PATH_MAX, "%s/kprobes/blacklist", __debugfs);
2039 if (ret < 0)
2040 return ret;
2041
2042 fp = fopen(buf, "r");
2043 if (!fp)
2044 return -errno;
2045
2046 ret = 0;
2047 while (fgets(buf, PATH_MAX, fp)) {
2048 node = zalloc(sizeof(*node));
2049 if (!node) {
2050 ret = -ENOMEM;
2051 break;
2052 }
2053 INIT_LIST_HEAD(&node->list);
2054 list_add_tail(&node->list, blacklist);
2055 if (sscanf(buf, "0x%lx-0x%lx", &node->start, &node->end) != 2) {
2056 ret = -EINVAL;
2057 break;
2058 }
2059 p = strchr(buf, '\t');
2060 if (p) {
2061 p++;
2062 if (p[strlen(p) - 1] == '\n')
2063 p[strlen(p) - 1] = '\0';
2064 } else
2065 p = (char *)"unknown";
2066 node->symbol = strdup(p);
2067 if (!node->symbol) {
2068 ret = -ENOMEM;
2069 break;
2070 }
2071 pr_debug2("Blacklist: 0x%lx-0x%lx, %s\n",
2072 node->start, node->end, node->symbol);
2073 ret++;
2074 }
2075 if (ret < 0)
2076 kprobe_blacklist__delete(blacklist);
2077 fclose(fp);
2078
2079 return ret;
2080}
2081
2082static struct kprobe_blacklist_node *
2083kprobe_blacklist__find_by_address(struct list_head *blacklist,
2084 unsigned long address)
2085{
2086 struct kprobe_blacklist_node *node;
2087
2088 list_for_each_entry(node, blacklist, list) {
2089 if (node->start <= address && address <= node->end)
2090 return node;
2091 }
2092
2093 return NULL;
2094}
2095
1898/* Show an event */ 2096/* Show an event */
1899static int show_perf_probe_event(struct perf_probe_event *pev, 2097static int show_perf_probe_event(struct perf_probe_event *pev,
1900 const char *module) 2098 const char *module)
@@ -2100,6 +2298,27 @@ static int get_new_event_name(char *buf, size_t len, const char *base,
2100 return ret; 2298 return ret;
2101} 2299}
2102 2300
2301/* Warn if the current kernel's uprobe implementation is old */
2302static void warn_uprobe_event_compat(struct probe_trace_event *tev)
2303{
2304 int i;
2305 char *buf = synthesize_probe_trace_command(tev);
2306
2307 /* Old uprobe event doesn't support memory dereference */
2308 if (!tev->uprobes || tev->nargs == 0 || !buf)
2309 goto out;
2310
2311 for (i = 0; i < tev->nargs; i++)
2312 if (strglobmatch(tev->args[i].value, "[$@+-]*")) {
2313 pr_warning("Please upgrade your kernel to at least "
2314 "3.14 to have access to feature %s\n",
2315 tev->args[i].value);
2316 break;
2317 }
2318out:
2319 free(buf);
2320}
2321
2103static int __add_probe_trace_events(struct perf_probe_event *pev, 2322static int __add_probe_trace_events(struct perf_probe_event *pev,
2104 struct probe_trace_event *tevs, 2323 struct probe_trace_event *tevs,
2105 int ntevs, bool allow_suffix) 2324 int ntevs, bool allow_suffix)
@@ -2109,6 +2328,8 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
2109 char buf[64]; 2328 char buf[64];
2110 const char *event, *group; 2329 const char *event, *group;
2111 struct strlist *namelist; 2330 struct strlist *namelist;
2331 LIST_HEAD(blacklist);
2332 struct kprobe_blacklist_node *node;
2112 2333
2113 if (pev->uprobes) 2334 if (pev->uprobes)
2114 fd = open_uprobe_events(true); 2335 fd = open_uprobe_events(true);
@@ -2126,11 +2347,25 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
2126 pr_debug("Failed to get current event list.\n"); 2347 pr_debug("Failed to get current event list.\n");
2127 return -EIO; 2348 return -EIO;
2128 } 2349 }
2350 /* Get kprobe blacklist if exists */
2351 if (!pev->uprobes) {
2352 ret = kprobe_blacklist__load(&blacklist);
2353 if (ret < 0)
2354 pr_debug("No kprobe blacklist support, ignored\n");
2355 }
2129 2356
2130 ret = 0; 2357 ret = 0;
2131 pr_info("Added new event%s\n", (ntevs > 1) ? "s:" : ":"); 2358 pr_info("Added new event%s\n", (ntevs > 1) ? "s:" : ":");
2132 for (i = 0; i < ntevs; i++) { 2359 for (i = 0; i < ntevs; i++) {
2133 tev = &tevs[i]; 2360 tev = &tevs[i];
2361 /* Ensure that the address is NOT blacklisted */
2362 node = kprobe_blacklist__find_by_address(&blacklist,
2363 tev->point.address);
2364 if (node) {
2365 pr_warning("Warning: Skipped probing on blacklisted function: %s\n", node->symbol);
2366 continue;
2367 }
2368
2134 if (pev->event) 2369 if (pev->event)
2135 event = pev->event; 2370 event = pev->event;
2136 else 2371 else
@@ -2180,14 +2415,18 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
2180 */ 2415 */
2181 allow_suffix = true; 2416 allow_suffix = true;
2182 } 2417 }
2418 if (ret == -EINVAL && pev->uprobes)
2419 warn_uprobe_event_compat(tev);
2183 2420
2184 if (ret >= 0) { 2421 /* Note that it is possible to skip all events because of blacklist */
2422 if (ret >= 0 && tev->event) {
2185 /* Show how to use the event. */ 2423 /* Show how to use the event. */
2186 pr_info("\nYou can now use it in all perf tools, such as:\n\n"); 2424 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, 2425 pr_info("\tperf record -e %s:%s -aR sleep 1\n\n", tev->group,
2188 tev->event); 2426 tev->event);
2189 } 2427 }
2190 2428
2429 kprobe_blacklist__delete(&blacklist);
2191 strlist__delete(namelist); 2430 strlist__delete(namelist);
2192 close(fd); 2431 close(fd);
2193 return ret; 2432 return ret;
@@ -2199,8 +2438,7 @@ static int find_probe_functions(struct map *map, char *name)
2199 struct symbol *sym; 2438 struct symbol *sym;
2200 2439
2201 map__for_each_symbol_by_name(map, name, sym) { 2440 map__for_each_symbol_by_name(map, name, sym) {
2202 if (sym->binding == STB_GLOBAL || sym->binding == STB_LOCAL) 2441 found++;
2203 found++;
2204 } 2442 }
2205 2443
2206 return found; 2444 return found;
@@ -2218,7 +2456,6 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
2218 int max_tevs, const char *target) 2456 int max_tevs, const char *target)
2219{ 2457{
2220 struct map *map = NULL; 2458 struct map *map = NULL;
2221 struct kmap *kmap = NULL;
2222 struct ref_reloc_sym *reloc_sym = NULL; 2459 struct ref_reloc_sym *reloc_sym = NULL;
2223 struct symbol *sym; 2460 struct symbol *sym;
2224 struct probe_trace_event *tev; 2461 struct probe_trace_event *tev;
@@ -2227,11 +2464,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
2227 int num_matched_functions; 2464 int num_matched_functions;
2228 int ret, i; 2465 int ret, i;
2229 2466
2230 /* Init maps of given executable or kernel */ 2467 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) { 2468 if (!map) {
2236 ret = -EINVAL; 2469 ret = -EINVAL;
2237 goto out; 2470 goto out;
@@ -2255,8 +2488,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
2255 } 2488 }
2256 2489
2257 if (!pev->uprobes && !pp->retprobe) { 2490 if (!pev->uprobes && !pp->retprobe) {
2258 kmap = map__kmap(map); 2491 reloc_sym = kernel_get_ref_reloc_sym();
2259 reloc_sym = kmap->ref_reloc_sym;
2260 if (!reloc_sym) { 2492 if (!reloc_sym) {
2261 pr_warning("Relocated base symbol is not found!\n"); 2493 pr_warning("Relocated base symbol is not found!\n");
2262 ret = -EINVAL; 2494 ret = -EINVAL;
@@ -2324,11 +2556,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
2324 } 2556 }
2325 2557
2326out: 2558out:
2327 if (map && pev->uprobes) { 2559 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; 2560 return ret;
2333 2561
2334nomem_out: 2562nomem_out:
@@ -2369,7 +2597,7 @@ struct __event_package {
2369}; 2597};
2370 2598
2371int add_perf_probe_events(struct perf_probe_event *pevs, int npevs, 2599int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
2372 int max_tevs, const char *target, bool force_add) 2600 int max_tevs, bool force_add)
2373{ 2601{
2374 int i, j, ret; 2602 int i, j, ret;
2375 struct __event_package *pkgs; 2603 struct __event_package *pkgs;
@@ -2393,7 +2621,7 @@ int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
2393 ret = convert_to_probe_trace_events(pkgs[i].pev, 2621 ret = convert_to_probe_trace_events(pkgs[i].pev,
2394 &pkgs[i].tevs, 2622 &pkgs[i].tevs,
2395 max_tevs, 2623 max_tevs,
2396 target); 2624 pkgs[i].pev->target);
2397 if (ret < 0) 2625 if (ret < 0)
2398 goto end; 2626 goto end;
2399 pkgs[i].ntevs = ret; 2627 pkgs[i].ntevs = ret;
@@ -2568,8 +2796,7 @@ static struct strfilter *available_func_filter;
2568static int filter_available_functions(struct map *map __maybe_unused, 2796static int filter_available_functions(struct map *map __maybe_unused,
2569 struct symbol *sym) 2797 struct symbol *sym)
2570{ 2798{
2571 if ((sym->binding == STB_GLOBAL || sym->binding == STB_LOCAL) && 2799 if (strfilter__compare(available_func_filter, sym->name))
2572 strfilter__compare(available_func_filter, sym->name))
2573 return 0; 2800 return 0;
2574 return 1; 2801 return 1;
2575} 2802}
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index e01e9943139f..d6b783447be9 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -73,7 +73,8 @@ struct perf_probe_event {
73 char *group; /* Group name */ 73 char *group; /* Group name */
74 struct perf_probe_point point; /* Probe point */ 74 struct perf_probe_point point; /* Probe point */
75 int nargs; /* Number of arguments */ 75 int nargs; /* Number of arguments */
76 bool uprobes; 76 bool uprobes; /* Uprobe event flag */
77 char *target; /* Target binary */
77 struct perf_probe_arg *args; /* Arguments */ 78 struct perf_probe_arg *args; /* Arguments */
78}; 79};
79 80
@@ -124,8 +125,7 @@ extern int line_range__init(struct line_range *lr);
124extern const char *kernel_get_module_path(const char *module); 125extern const char *kernel_get_module_path(const char *module);
125 126
126extern int add_perf_probe_events(struct perf_probe_event *pevs, int npevs, 127extern int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
127 int max_probe_points, const char *module, 128 int max_probe_points, bool force_add);
128 bool force_add);
129extern int del_perf_probe_events(struct strlist *dellist); 129extern int del_perf_probe_events(struct strlist *dellist);
130extern int show_perf_probe_events(void); 130extern int show_perf_probe_events(void);
131extern int show_line_range(struct line_range *lr, const char *module, 131extern int show_line_range(struct line_range *lr, const char *module,
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index b5247d777f0e..b5bf9d5efeaf 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -456,11 +456,12 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
456 return -EINVAL; 456 return -EINVAL;
457 } 457 }
458 if (field->name[0] == '[') { 458 if (field->name[0] == '[') {
459 pr_err("Semantic error: %s is not a pointor" 459 pr_err("Semantic error: %s is not a pointer"
460 " nor array.\n", varname); 460 " nor array.\n", varname);
461 return -EINVAL; 461 return -EINVAL;
462 } 462 }
463 if (field->ref) { 463 /* While prcessing unnamed field, we don't care about this */
464 if (field->ref && dwarf_diename(vr_die)) {
464 pr_err("Semantic error: %s must be referred by '.'\n", 465 pr_err("Semantic error: %s must be referred by '.'\n",
465 field->name); 466 field->name);
466 return -EINVAL; 467 return -EINVAL;
@@ -491,6 +492,11 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
491 } 492 }
492 ref->offset += (long)offs; 493 ref->offset += (long)offs;
493 494
495 /* If this member is unnamed, we need to reuse this field */
496 if (!dwarf_diename(die_mem))
497 return convert_variable_fields(die_mem, varname, field,
498 &ref, die_mem);
499
494next: 500next:
495 /* Converting next field */ 501 /* Converting next field */
496 if (field->next) 502 if (field->next)
@@ -849,11 +855,22 @@ static int probe_point_lazy_walker(const char *fname, int lineno,
849static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf) 855static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
850{ 856{
851 int ret = 0; 857 int ret = 0;
858 char *fpath;
852 859
853 if (intlist__empty(pf->lcache)) { 860 if (intlist__empty(pf->lcache)) {
861 const char *comp_dir;
862
863 comp_dir = cu_get_comp_dir(&pf->cu_die);
864 ret = get_real_path(pf->fname, comp_dir, &fpath);
865 if (ret < 0) {
866 pr_warning("Failed to find source file path.\n");
867 return ret;
868 }
869
854 /* Matching lazy line pattern */ 870 /* Matching lazy line pattern */
855 ret = find_lazy_match_lines(pf->lcache, pf->fname, 871 ret = find_lazy_match_lines(pf->lcache, fpath,
856 pf->pev->point.lazy_line); 872 pf->pev->point.lazy_line);
873 free(fpath);
857 if (ret <= 0) 874 if (ret <= 0)
858 return ret; 875 return ret;
859 } 876 }
@@ -915,17 +932,13 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
915 dwarf_decl_line(sp_die, &pf->lno); 932 dwarf_decl_line(sp_die, &pf->lno);
916 pf->lno += pp->line; 933 pf->lno += pp->line;
917 param->retval = find_probe_point_by_line(pf); 934 param->retval = find_probe_point_by_line(pf);
918 } else if (!dwarf_func_inline(sp_die)) { 935 } else if (die_is_func_instance(sp_die)) {
936 /* Instances always have the entry address */
937 dwarf_entrypc(sp_die, &pf->addr);
919 /* Real function */ 938 /* Real function */
920 if (pp->lazy_line) 939 if (pp->lazy_line)
921 param->retval = find_probe_point_lazy(sp_die, pf); 940 param->retval = find_probe_point_lazy(sp_die, pf);
922 else { 941 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; 942 pf->addr += pp->offset;
930 /* TODO: Check the address in this function */ 943 /* TODO: Check the address in this function */
931 param->retval = call_probe_finder(sp_die, pf); 944 param->retval = call_probe_finder(sp_die, pf);
@@ -1053,7 +1066,7 @@ static int debuginfo__find_probes(struct debuginfo *dbg,
1053 if (pp->function) 1066 if (pp->function)
1054 ret = find_probe_point_by_func(pf); 1067 ret = find_probe_point_by_func(pf);
1055 else if (pp->lazy_line) 1068 else if (pp->lazy_line)
1056 ret = find_probe_point_lazy(NULL, pf); 1069 ret = find_probe_point_lazy(&pf->cu_die, pf);
1057 else { 1070 else {
1058 pf->lno = pp->line; 1071 pf->lno = pp->line;
1059 ret = find_probe_point_by_line(pf); 1072 ret = find_probe_point_by_line(pf);
@@ -1349,11 +1362,8 @@ int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr,
1349 const char *fname = NULL, *func = NULL, *basefunc = NULL, *tmp; 1362 const char *fname = NULL, *func = NULL, *basefunc = NULL, *tmp;
1350 int baseline = 0, lineno = 0, ret = 0; 1363 int baseline = 0, lineno = 0, ret = 0;
1351 1364
1352 /* Adjust address with bias */
1353 addr += dbg->bias;
1354
1355 /* Find cu die */ 1365 /* Find cu die */
1356 if (!dwarf_addrdie(dbg->dbg, (Dwarf_Addr)addr - dbg->bias, &cudie)) { 1366 if (!dwarf_addrdie(dbg->dbg, (Dwarf_Addr)addr, &cudie)) {
1357 pr_warning("Failed to find debug information for address %lx\n", 1367 pr_warning("Failed to find debug information for address %lx\n",
1358 addr); 1368 addr);
1359 ret = -EINVAL; 1369 ret = -EINVAL;
@@ -1536,7 +1546,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); 1546 pr_debug("New line range: %d to %d\n", lf->lno_s, lf->lno_e);
1537 lr->start = lf->lno_s; 1547 lr->start = lf->lno_s;
1538 lr->end = lf->lno_e; 1548 lr->end = lf->lno_e;
1539 if (dwarf_func_inline(sp_die)) 1549 if (!die_is_func_instance(sp_die))
1540 param->retval = die_walk_instances(sp_die, 1550 param->retval = die_walk_instances(sp_die,
1541 line_range_inline_cb, lf); 1551 line_range_inline_cb, lf);
1542 else 1552 else
@@ -1623,3 +1633,61 @@ found:
1623 return (ret < 0) ? ret : lf.found; 1633 return (ret < 0) ? ret : lf.found;
1624} 1634}
1625 1635
1636/*
1637 * Find a src file from a DWARF tag path. Prepend optional source path prefix
1638 * and chop off leading directories that do not exist. Result is passed back as
1639 * a newly allocated path on success.
1640 * Return 0 if file was found and readable, -errno otherwise.
1641 */
1642int get_real_path(const char *raw_path, const char *comp_dir,
1643 char **new_path)
1644{
1645 const char *prefix = symbol_conf.source_prefix;
1646
1647 if (!prefix) {
1648 if (raw_path[0] != '/' && comp_dir)
1649 /* If not an absolute path, try to use comp_dir */
1650 prefix = comp_dir;
1651 else {
1652 if (access(raw_path, R_OK) == 0) {
1653 *new_path = strdup(raw_path);
1654 return *new_path ? 0 : -ENOMEM;
1655 } else
1656 return -errno;
1657 }
1658 }
1659
1660 *new_path = malloc((strlen(prefix) + strlen(raw_path) + 2));
1661 if (!*new_path)
1662 return -ENOMEM;
1663
1664 for (;;) {
1665 sprintf(*new_path, "%s/%s", prefix, raw_path);
1666
1667 if (access(*new_path, R_OK) == 0)
1668 return 0;
1669
1670 if (!symbol_conf.source_prefix) {
1671 /* In case of searching comp_dir, don't retry */
1672 zfree(new_path);
1673 return -errno;
1674 }
1675
1676 switch (errno) {
1677 case ENAMETOOLONG:
1678 case ENOENT:
1679 case EROFS:
1680 case EFAULT:
1681 raw_path = strchr(++raw_path, '/');
1682 if (!raw_path) {
1683 zfree(new_path);
1684 return -ENOENT;
1685 }
1686 continue;
1687
1688 default:
1689 zfree(new_path);
1690 return -errno;
1691 }
1692 }
1693}
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
index 92590b2c7e1c..ebf8c8c81453 100644
--- a/tools/perf/util/probe-finder.h
+++ b/tools/perf/util/probe-finder.h
@@ -55,6 +55,10 @@ extern int debuginfo__find_available_vars_at(struct debuginfo *dbg,
55 struct variable_list **vls, 55 struct variable_list **vls,
56 int max_points, bool externs); 56 int max_points, bool externs);
57 57
58/* Find a src file from a DWARF tag path */
59int get_real_path(const char *raw_path, const char *comp_dir,
60 char **new_path);
61
58struct probe_finder { 62struct probe_finder {
59 struct perf_probe_event *pev; /* Target probe event */ 63 struct perf_probe_event *pev; /* Target probe event */
60 64
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..430b5d27828e 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:
@@ -355,10 +360,9 @@ static void perl_process_event_generic(union perf_event *event,
355static void perl_process_event(union perf_event *event, 360static void perl_process_event(union perf_event *event,
356 struct perf_sample *sample, 361 struct perf_sample *sample,
357 struct perf_evsel *evsel, 362 struct perf_evsel *evsel,
358 struct thread *thread, 363 struct addr_location *al)
359 struct addr_location *al __maybe_unused)
360{ 364{
361 perl_process_tracepoint(sample, evsel, thread); 365 perl_process_tracepoint(sample, evsel, al->thread);
362 perl_process_event_generic(event, sample, evsel); 366 perl_process_event_generic(event, sample, evsel);
363} 367}
364 368
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 0c815a40a6e8..5544b8cdd1ee 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:
@@ -376,7 +381,6 @@ exit:
376 381
377static void python_process_tracepoint(struct perf_sample *sample, 382static void python_process_tracepoint(struct perf_sample *sample,
378 struct perf_evsel *evsel, 383 struct perf_evsel *evsel,
379 struct thread *thread,
380 struct addr_location *al) 384 struct addr_location *al)
381{ 385{
382 struct event_format *event = evsel->tp_format; 386 struct event_format *event = evsel->tp_format;
@@ -390,7 +394,7 @@ static void python_process_tracepoint(struct perf_sample *sample,
390 int cpu = sample->cpu; 394 int cpu = sample->cpu;
391 void *data = sample->raw_data; 395 void *data = sample->raw_data;
392 unsigned long long nsecs = sample->time; 396 unsigned long long nsecs = sample->time;
393 const char *comm = thread__comm_str(thread); 397 const char *comm = thread__comm_str(al->thread);
394 398
395 t = PyTuple_New(MAX_FIELDS); 399 t = PyTuple_New(MAX_FIELDS);
396 if (!t) 400 if (!t)
@@ -675,7 +679,7 @@ static int python_export_sample(struct db_export *dbe,
675 tuple_set_u64(t, 0, es->db_id); 679 tuple_set_u64(t, 0, es->db_id);
676 tuple_set_u64(t, 1, es->evsel->db_id); 680 tuple_set_u64(t, 1, es->evsel->db_id);
677 tuple_set_u64(t, 2, es->al->machine->db_id); 681 tuple_set_u64(t, 2, es->al->machine->db_id);
678 tuple_set_u64(t, 3, es->thread->db_id); 682 tuple_set_u64(t, 3, es->al->thread->db_id);
679 tuple_set_u64(t, 4, es->comm_db_id); 683 tuple_set_u64(t, 4, es->comm_db_id);
680 tuple_set_u64(t, 5, es->dso_db_id); 684 tuple_set_u64(t, 5, es->dso_db_id);
681 tuple_set_u64(t, 6, es->sym_db_id); 685 tuple_set_u64(t, 6, es->sym_db_id);
@@ -761,7 +765,6 @@ static int python_process_call_return(struct call_return *cr, void *data)
761 765
762static void python_process_general_event(struct perf_sample *sample, 766static void python_process_general_event(struct perf_sample *sample,
763 struct perf_evsel *evsel, 767 struct perf_evsel *evsel,
764 struct thread *thread,
765 struct addr_location *al) 768 struct addr_location *al)
766{ 769{
767 PyObject *handler, *t, *dict, *callchain, *dict_sample; 770 PyObject *handler, *t, *dict, *callchain, *dict_sample;
@@ -811,7 +814,7 @@ static void python_process_general_event(struct perf_sample *sample,
811 pydict_set_item_string_decref(dict, "raw_buf", PyString_FromStringAndSize( 814 pydict_set_item_string_decref(dict, "raw_buf", PyString_FromStringAndSize(
812 (const char *)sample->raw_data, sample->raw_size)); 815 (const char *)sample->raw_data, sample->raw_size));
813 pydict_set_item_string_decref(dict, "comm", 816 pydict_set_item_string_decref(dict, "comm",
814 PyString_FromString(thread__comm_str(thread))); 817 PyString_FromString(thread__comm_str(al->thread)));
815 if (al->map) { 818 if (al->map) {
816 pydict_set_item_string_decref(dict, "dso", 819 pydict_set_item_string_decref(dict, "dso",
817 PyString_FromString(al->map->dso->name)); 820 PyString_FromString(al->map->dso->name));
@@ -838,22 +841,20 @@ exit:
838static void python_process_event(union perf_event *event, 841static void python_process_event(union perf_event *event,
839 struct perf_sample *sample, 842 struct perf_sample *sample,
840 struct perf_evsel *evsel, 843 struct perf_evsel *evsel,
841 struct thread *thread,
842 struct addr_location *al) 844 struct addr_location *al)
843{ 845{
844 struct tables *tables = &tables_global; 846 struct tables *tables = &tables_global;
845 847
846 switch (evsel->attr.type) { 848 switch (evsel->attr.type) {
847 case PERF_TYPE_TRACEPOINT: 849 case PERF_TYPE_TRACEPOINT:
848 python_process_tracepoint(sample, evsel, thread, al); 850 python_process_tracepoint(sample, evsel, al);
849 break; 851 break;
850 /* Reserve for future process_hw/sw/raw APIs */ 852 /* Reserve for future process_hw/sw/raw APIs */
851 default: 853 default:
852 if (tables->db_export_mode) 854 if (tables->db_export_mode)
853 db_export__sample(&tables->dbe, event, sample, evsel, 855 db_export__sample(&tables->dbe, event, sample, evsel, al);
854 thread, al);
855 else 856 else
856 python_process_general_event(sample, evsel, thread, al); 857 python_process_general_event(sample, evsel, al);
857 } 858 }
858} 859}
859 860
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 0baf75f12b7c..0c74012575ac 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,23 @@ 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{
98 struct perf_sample sample;
99 struct perf_session *session = container_of(oe, struct perf_session,
100 ordered_events);
101 int ret = perf_evlist__parse_sample(session->evlist, event->event, &sample);
102
103 if (ret) {
104 pr_err("Can't parse sample, err = %d\n", ret);
105 return ret;
106 }
107
108 return machines__deliver_event(&session->machines, session->evlist, event->event,
109 &sample, session->tool, event->file_offset);
110}
111
89struct perf_session *perf_session__new(struct perf_data_file *file, 112struct perf_session *perf_session__new(struct perf_data_file *file,
90 bool repipe, struct perf_tool *tool) 113 bool repipe, struct perf_tool *tool)
91{ 114{
@@ -95,8 +118,9 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
95 goto out; 118 goto out;
96 119
97 session->repipe = repipe; 120 session->repipe = repipe;
98 ordered_events__init(&session->ordered_events); 121 session->tool = tool;
99 machines__init(&session->machines); 122 machines__init(&session->machines);
123 ordered_events__init(&session->ordered_events, ordered_events__deliver_event);
100 124
101 if (file) { 125 if (file) {
102 if (perf_data_file__open(file)) 126 if (perf_data_file__open(file))
@@ -138,11 +162,6 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
138 return NULL; 162 return NULL;
139} 163}
140 164
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) 165static void perf_session__delete_threads(struct perf_session *session)
147{ 166{
148 machine__delete_threads(&session->machines.host); 167 machine__delete_threads(&session->machines.host);
@@ -167,7 +186,6 @@ static void perf_session_env__delete(struct perf_session_env *env)
167void perf_session__delete(struct perf_session *session) 186void perf_session__delete(struct perf_session *session)
168{ 187{
169 perf_session__destroy_kernel_maps(session); 188 perf_session__destroy_kernel_maps(session);
170 perf_session__delete_dead_threads(session);
171 perf_session__delete_threads(session); 189 perf_session__delete_threads(session);
172 perf_session_env__delete(&session->header.env); 190 perf_session_env__delete(&session->header.env);
173 machines__exit(&session->machines); 191 machines__exit(&session->machines);
@@ -215,10 +233,17 @@ static int process_event_stub(struct perf_tool *tool __maybe_unused,
215 return 0; 233 return 0;
216} 234}
217 235
236static int process_build_id_stub(struct perf_tool *tool __maybe_unused,
237 union perf_event *event __maybe_unused,
238 struct perf_session *session __maybe_unused)
239{
240 dump_printf(": unhandled!\n");
241 return 0;
242}
243
218static int process_finished_round_stub(struct perf_tool *tool __maybe_unused, 244static int process_finished_round_stub(struct perf_tool *tool __maybe_unused,
219 union perf_event *event __maybe_unused, 245 union perf_event *event __maybe_unused,
220 struct perf_session *perf_session 246 struct ordered_events *oe __maybe_unused)
221 __maybe_unused)
222{ 247{
223 dump_printf(": unhandled!\n"); 248 dump_printf(": unhandled!\n");
224 return 0; 249 return 0;
@@ -226,7 +251,7 @@ static int process_finished_round_stub(struct perf_tool *tool __maybe_unused,
226 251
227static int process_finished_round(struct perf_tool *tool, 252static int process_finished_round(struct perf_tool *tool,
228 union perf_event *event, 253 union perf_event *event,
229 struct perf_session *session); 254 struct ordered_events *oe);
230 255
231static int process_id_index_stub(struct perf_tool *tool __maybe_unused, 256static int process_id_index_stub(struct perf_tool *tool __maybe_unused,
232 union perf_event *event __maybe_unused, 257 union perf_event *event __maybe_unused,
@@ -264,7 +289,7 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
264 if (tool->tracing_data == NULL) 289 if (tool->tracing_data == NULL)
265 tool->tracing_data = process_event_synth_tracing_data_stub; 290 tool->tracing_data = process_event_synth_tracing_data_stub;
266 if (tool->build_id == NULL) 291 if (tool->build_id == NULL)
267 tool->build_id = process_finished_round_stub; 292 tool->build_id = process_build_id_stub;
268 if (tool->finished_round == NULL) { 293 if (tool->finished_round == NULL) {
269 if (tool->ordered_events) 294 if (tool->ordered_events)
270 tool->finished_round = process_finished_round; 295 tool->finished_round = process_finished_round;
@@ -514,54 +539,80 @@ static perf_event__swap_op perf_event__swap_ops[] = {
514 * Flush every events below timestamp 7 539 * Flush every events below timestamp 7
515 * etc... 540 * etc...
516 */ 541 */
517static int process_finished_round(struct perf_tool *tool, 542static int process_finished_round(struct perf_tool *tool __maybe_unused,
518 union perf_event *event __maybe_unused, 543 union perf_event *event __maybe_unused,
519 struct perf_session *session) 544 struct ordered_events *oe)
520{ 545{
521 return ordered_events__flush(session, tool, OE_FLUSH__ROUND); 546 return ordered_events__flush(oe, OE_FLUSH__ROUND);
522} 547}
523 548
524int perf_session_queue_event(struct perf_session *s, union perf_event *event, 549int perf_session__queue_event(struct perf_session *s, union perf_event *event,
525 struct perf_tool *tool, struct perf_sample *sample, 550 struct perf_sample *sample, u64 file_offset)
526 u64 file_offset)
527{ 551{
528 struct ordered_events *oe = &s->ordered_events; 552 return ordered_events__queue(&s->ordered_events, event, sample, file_offset);
529 u64 timestamp = sample->time; 553}
530 struct ordered_event *new;
531
532 if (!timestamp || timestamp == ~0ULL)
533 return -ETIME;
534 554
535 if (timestamp < oe->last_flush) { 555static void callchain__lbr_callstack_printf(struct perf_sample *sample)
536 pr_oe_time(timestamp, "out of order event\n"); 556{
537 pr_oe_time(oe->last_flush, "last flush, last_flush_type %d\n", 557 struct ip_callchain *callchain = sample->callchain;
538 oe->last_flush_type); 558 struct branch_stack *lbr_stack = sample->branch_stack;
559 u64 kernel_callchain_nr = callchain->nr;
560 unsigned int i;
539 561
540 s->stats.nr_unordered_events++; 562 for (i = 0; i < kernel_callchain_nr; i++) {
563 if (callchain->ips[i] == PERF_CONTEXT_USER)
564 break;
541 } 565 }
542 566
543 new = ordered_events__new(oe, timestamp, event); 567 if ((i != kernel_callchain_nr) && lbr_stack->nr) {
544 if (!new) { 568 u64 total_nr;
545 ordered_events__flush(s, tool, OE_FLUSH__HALF); 569 /*
546 new = ordered_events__new(oe, timestamp, event); 570 * LBR callstack can only get user call chain,
547 } 571 * i is kernel call chain number,
572 * 1 is PERF_CONTEXT_USER.
573 *
574 * The user call chain is stored in LBR registers.
575 * LBR are pair registers. The caller is stored
576 * in "from" register, while the callee is stored
577 * in "to" register.
578 * For example, there is a call stack
579 * "A"->"B"->"C"->"D".
580 * The LBR registers will recorde like
581 * "C"->"D", "B"->"C", "A"->"B".
582 * So only the first "to" register and all "from"
583 * registers are needed to construct the whole stack.
584 */
585 total_nr = i + 1 + lbr_stack->nr + 1;
586 kernel_callchain_nr = i + 1;
548 587
549 if (!new) 588 printf("... LBR call chain: nr:%" PRIu64 "\n", total_nr);
550 return -ENOMEM;
551 589
552 new->file_offset = file_offset; 590 for (i = 0; i < kernel_callchain_nr; i++)
553 return 0; 591 printf("..... %2d: %016" PRIx64 "\n",
592 i, callchain->ips[i]);
593
594 printf("..... %2d: %016" PRIx64 "\n",
595 (int)(kernel_callchain_nr), lbr_stack->entries[0].to);
596 for (i = 0; i < lbr_stack->nr; i++)
597 printf("..... %2d: %016" PRIx64 "\n",
598 (int)(i + kernel_callchain_nr + 1), lbr_stack->entries[i].from);
599 }
554} 600}
555 601
556static void callchain__printf(struct perf_sample *sample) 602static void callchain__printf(struct perf_evsel *evsel,
603 struct perf_sample *sample)
557{ 604{
558 unsigned int i; 605 unsigned int i;
606 struct ip_callchain *callchain = sample->callchain;
607
608 if (has_branch_callstack(evsel))
609 callchain__lbr_callstack_printf(sample);
559 610
560 printf("... chain: nr:%" PRIu64 "\n", sample->callchain->nr); 611 printf("... FP chain: nr:%" PRIu64 "\n", callchain->nr);
561 612
562 for (i = 0; i < sample->callchain->nr; i++) 613 for (i = 0; i < callchain->nr; i++)
563 printf("..... %2d: %016" PRIx64 "\n", 614 printf("..... %2d: %016" PRIx64 "\n",
564 i, sample->callchain->ips[i]); 615 i, callchain->ips[i]);
565} 616}
566 617
567static void branch_stack__printf(struct perf_sample *sample) 618static void branch_stack__printf(struct perf_sample *sample)
@@ -636,14 +687,14 @@ static void stack_user__printf(struct stack_dump *dump)
636 dump->size, dump->offset); 687 dump->size, dump->offset);
637} 688}
638 689
639static void perf_session__print_tstamp(struct perf_session *session, 690static void perf_evlist__print_tstamp(struct perf_evlist *evlist,
640 union perf_event *event, 691 union perf_event *event,
641 struct perf_sample *sample) 692 struct perf_sample *sample)
642{ 693{
643 u64 sample_type = __perf_evlist__combined_sample_type(session->evlist); 694 u64 sample_type = __perf_evlist__combined_sample_type(evlist);
644 695
645 if (event->header.type != PERF_RECORD_SAMPLE && 696 if (event->header.type != PERF_RECORD_SAMPLE &&
646 !perf_evlist__sample_id_all(session->evlist)) { 697 !perf_evlist__sample_id_all(evlist)) {
647 fputs("-1 -1 ", stdout); 698 fputs("-1 -1 ", stdout);
648 return; 699 return;
649 } 700 }
@@ -685,7 +736,7 @@ static void sample_read__printf(struct perf_sample *sample, u64 read_format)
685 sample->read.one.id, sample->read.one.value); 736 sample->read.one.id, sample->read.one.value);
686} 737}
687 738
688static void dump_event(struct perf_session *session, union perf_event *event, 739static void dump_event(struct perf_evlist *evlist, union perf_event *event,
689 u64 file_offset, struct perf_sample *sample) 740 u64 file_offset, struct perf_sample *sample)
690{ 741{
691 if (!dump_trace) 742 if (!dump_trace)
@@ -697,7 +748,7 @@ static void dump_event(struct perf_session *session, union perf_event *event,
697 trace_event(event); 748 trace_event(event);
698 749
699 if (sample) 750 if (sample)
700 perf_session__print_tstamp(session, event, sample); 751 perf_evlist__print_tstamp(evlist, event, sample);
701 752
702 printf("%#" PRIx64 " [%#x]: PERF_RECORD_%s", file_offset, 753 printf("%#" PRIx64 " [%#x]: PERF_RECORD_%s", file_offset,
703 event->header.size, perf_event__name(event->header.type)); 754 event->header.size, perf_event__name(event->header.type));
@@ -718,9 +769,9 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event,
718 sample_type = evsel->attr.sample_type; 769 sample_type = evsel->attr.sample_type;
719 770
720 if (sample_type & PERF_SAMPLE_CALLCHAIN) 771 if (sample_type & PERF_SAMPLE_CALLCHAIN)
721 callchain__printf(sample); 772 callchain__printf(evsel, sample);
722 773
723 if (sample_type & PERF_SAMPLE_BRANCH_STACK) 774 if ((sample_type & PERF_SAMPLE_BRANCH_STACK) && !has_branch_callstack(evsel))
724 branch_stack__printf(sample); 775 branch_stack__printf(sample);
725 776
726 if (sample_type & PERF_SAMPLE_REGS_USER) 777 if (sample_type & PERF_SAMPLE_REGS_USER)
@@ -745,8 +796,7 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event,
745 sample_read__printf(sample, evsel->attr.read_format); 796 sample_read__printf(sample, evsel->attr.read_format);
746} 797}
747 798
748static struct machine * 799static 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, 800 union perf_event *event,
751 struct perf_sample *sample) 801 struct perf_sample *sample)
752{ 802{
@@ -764,26 +814,24 @@ static struct machine *
764 else 814 else
765 pid = sample->pid; 815 pid = sample->pid;
766 816
767 machine = perf_session__find_machine(session, pid); 817 machine = machines__find(machines, pid);
768 if (!machine) 818 if (!machine)
769 machine = perf_session__findnew_machine(session, 819 machine = machines__find(machines, DEFAULT_GUEST_KERNEL_ID);
770 DEFAULT_GUEST_KERNEL_ID);
771 return machine; 820 return machine;
772 } 821 }
773 822
774 return &session->machines.host; 823 return &machines->host;
775} 824}
776 825
777static int deliver_sample_value(struct perf_session *session, 826static int deliver_sample_value(struct perf_evlist *evlist,
778 struct perf_tool *tool, 827 struct perf_tool *tool,
779 union perf_event *event, 828 union perf_event *event,
780 struct perf_sample *sample, 829 struct perf_sample *sample,
781 struct sample_read_value *v, 830 struct sample_read_value *v,
782 struct machine *machine) 831 struct machine *machine)
783{ 832{
784 struct perf_sample_id *sid; 833 struct perf_sample_id *sid = perf_evlist__id2sid(evlist, v->id);
785 834
786 sid = perf_evlist__id2sid(session->evlist, v->id);
787 if (sid) { 835 if (sid) {
788 sample->id = v->id; 836 sample->id = v->id;
789 sample->period = v->value - sid->period; 837 sample->period = v->value - sid->period;
@@ -791,14 +839,14 @@ static int deliver_sample_value(struct perf_session *session,
791 } 839 }
792 840
793 if (!sid || sid->evsel == NULL) { 841 if (!sid || sid->evsel == NULL) {
794 ++session->stats.nr_unknown_id; 842 ++evlist->stats.nr_unknown_id;
795 return 0; 843 return 0;
796 } 844 }
797 845
798 return tool->sample(tool, event, sample, sid->evsel, machine); 846 return tool->sample(tool, event, sample, sid->evsel, machine);
799} 847}
800 848
801static int deliver_sample_group(struct perf_session *session, 849static int deliver_sample_group(struct perf_evlist *evlist,
802 struct perf_tool *tool, 850 struct perf_tool *tool,
803 union perf_event *event, 851 union perf_event *event,
804 struct perf_sample *sample, 852 struct perf_sample *sample,
@@ -808,7 +856,7 @@ static int deliver_sample_group(struct perf_session *session,
808 u64 i; 856 u64 i;
809 857
810 for (i = 0; i < sample->read.group.nr; i++) { 858 for (i = 0; i < sample->read.group.nr; i++) {
811 ret = deliver_sample_value(session, tool, event, sample, 859 ret = deliver_sample_value(evlist, tool, event, sample,
812 &sample->read.group.values[i], 860 &sample->read.group.values[i],
813 machine); 861 machine);
814 if (ret) 862 if (ret)
@@ -819,7 +867,7 @@ static int deliver_sample_group(struct perf_session *session,
819} 867}
820 868
821static int 869static int
822perf_session__deliver_sample(struct perf_session *session, 870 perf_evlist__deliver_sample(struct perf_evlist *evlist,
823 struct perf_tool *tool, 871 struct perf_tool *tool,
824 union perf_event *event, 872 union perf_event *event,
825 struct perf_sample *sample, 873 struct perf_sample *sample,
@@ -836,41 +884,40 @@ perf_session__deliver_sample(struct perf_session *session,
836 884
837 /* For PERF_SAMPLE_READ we have either single or group mode. */ 885 /* For PERF_SAMPLE_READ we have either single or group mode. */
838 if (read_format & PERF_FORMAT_GROUP) 886 if (read_format & PERF_FORMAT_GROUP)
839 return deliver_sample_group(session, tool, event, sample, 887 return deliver_sample_group(evlist, tool, event, sample,
840 machine); 888 machine);
841 else 889 else
842 return deliver_sample_value(session, tool, event, sample, 890 return deliver_sample_value(evlist, tool, event, sample,
843 &sample->read.one, machine); 891 &sample->read.one, machine);
844} 892}
845 893
846int perf_session__deliver_event(struct perf_session *session, 894static int machines__deliver_event(struct machines *machines,
847 union perf_event *event, 895 struct perf_evlist *evlist,
848 struct perf_sample *sample, 896 union perf_event *event,
849 struct perf_tool *tool, u64 file_offset) 897 struct perf_sample *sample,
898 struct perf_tool *tool, u64 file_offset)
850{ 899{
851 struct perf_evsel *evsel; 900 struct perf_evsel *evsel;
852 struct machine *machine; 901 struct machine *machine;
853 902
854 dump_event(session, event, file_offset, sample); 903 dump_event(evlist, event, file_offset, sample);
855 904
856 evsel = perf_evlist__id2evsel(session->evlist, sample->id); 905 evsel = perf_evlist__id2evsel(evlist, sample->id);
857 906
858 machine = perf_session__find_machine_for_cpumode(session, event, 907 machine = machines__find_for_cpumode(machines, event, sample);
859 sample);
860 908
861 switch (event->header.type) { 909 switch (event->header.type) {
862 case PERF_RECORD_SAMPLE: 910 case PERF_RECORD_SAMPLE:
863 dump_sample(evsel, event, sample); 911 dump_sample(evsel, event, sample);
864 if (evsel == NULL) { 912 if (evsel == NULL) {
865 ++session->stats.nr_unknown_id; 913 ++evlist->stats.nr_unknown_id;
866 return 0; 914 return 0;
867 } 915 }
868 if (machine == NULL) { 916 if (machine == NULL) {
869 ++session->stats.nr_unprocessable_samples; 917 ++evlist->stats.nr_unprocessable_samples;
870 return 0; 918 return 0;
871 } 919 }
872 return perf_session__deliver_sample(session, tool, event, 920 return perf_evlist__deliver_sample(evlist, tool, event, sample, evsel, machine);
873 sample, evsel, machine);
874 case PERF_RECORD_MMAP: 921 case PERF_RECORD_MMAP:
875 return tool->mmap(tool, event, sample, machine); 922 return tool->mmap(tool, event, sample, machine);
876 case PERF_RECORD_MMAP2: 923 case PERF_RECORD_MMAP2:
@@ -883,7 +930,7 @@ int perf_session__deliver_event(struct perf_session *session,
883 return tool->exit(tool, event, sample, machine); 930 return tool->exit(tool, event, sample, machine);
884 case PERF_RECORD_LOST: 931 case PERF_RECORD_LOST:
885 if (tool->lost == perf_event__process_lost) 932 if (tool->lost == perf_event__process_lost)
886 session->stats.total_lost += event->lost.lost; 933 evlist->stats.total_lost += event->lost.lost;
887 return tool->lost(tool, event, sample, machine); 934 return tool->lost(tool, event, sample, machine);
888 case PERF_RECORD_READ: 935 case PERF_RECORD_READ:
889 return tool->read(tool, event, sample, evsel, machine); 936 return tool->read(tool, event, sample, evsel, machine);
@@ -892,20 +939,21 @@ int perf_session__deliver_event(struct perf_session *session,
892 case PERF_RECORD_UNTHROTTLE: 939 case PERF_RECORD_UNTHROTTLE:
893 return tool->unthrottle(tool, event, sample, machine); 940 return tool->unthrottle(tool, event, sample, machine);
894 default: 941 default:
895 ++session->stats.nr_unknown_events; 942 ++evlist->stats.nr_unknown_events;
896 return -1; 943 return -1;
897 } 944 }
898} 945}
899 946
900static s64 perf_session__process_user_event(struct perf_session *session, 947static s64 perf_session__process_user_event(struct perf_session *session,
901 union perf_event *event, 948 union perf_event *event,
902 struct perf_tool *tool,
903 u64 file_offset) 949 u64 file_offset)
904{ 950{
951 struct ordered_events *oe = &session->ordered_events;
952 struct perf_tool *tool = session->tool;
905 int fd = perf_data_file__fd(session->file); 953 int fd = perf_data_file__fd(session->file);
906 int err; 954 int err;
907 955
908 dump_event(session, event, file_offset, NULL); 956 dump_event(session->evlist, event, file_offset, NULL);
909 957
910 /* These events are processed right away */ 958 /* These events are processed right away */
911 switch (event->header.type) { 959 switch (event->header.type) {
@@ -929,7 +977,7 @@ static s64 perf_session__process_user_event(struct perf_session *session,
929 case PERF_RECORD_HEADER_BUILD_ID: 977 case PERF_RECORD_HEADER_BUILD_ID:
930 return tool->build_id(tool, event, session); 978 return tool->build_id(tool, event, session);
931 case PERF_RECORD_FINISHED_ROUND: 979 case PERF_RECORD_FINISHED_ROUND:
932 return tool->finished_round(tool, event, session); 980 return tool->finished_round(tool, event, oe);
933 case PERF_RECORD_ID_INDEX: 981 case PERF_RECORD_ID_INDEX:
934 return tool->id_index(tool, event, session); 982 return tool->id_index(tool, event, session);
935 default: 983 default:
@@ -939,15 +987,17 @@ static s64 perf_session__process_user_event(struct perf_session *session,
939 987
940int perf_session__deliver_synth_event(struct perf_session *session, 988int perf_session__deliver_synth_event(struct perf_session *session,
941 union perf_event *event, 989 union perf_event *event,
942 struct perf_sample *sample, 990 struct perf_sample *sample)
943 struct perf_tool *tool)
944{ 991{
945 events_stats__inc(&session->stats, event->header.type); 992 struct perf_evlist *evlist = session->evlist;
993 struct perf_tool *tool = session->tool;
994
995 events_stats__inc(&evlist->stats, event->header.type);
946 996
947 if (event->header.type >= PERF_RECORD_USER_TYPE_START) 997 if (event->header.type >= PERF_RECORD_USER_TYPE_START)
948 return perf_session__process_user_event(session, event, tool, 0); 998 return perf_session__process_user_event(session, event, 0);
949 999
950 return perf_session__deliver_event(session, event, sample, tool, 0); 1000 return machines__deliver_event(&session->machines, evlist, event, sample, tool, 0);
951} 1001}
952 1002
953static void event_swap(union perf_event *event, bool sample_id_all) 1003static void event_swap(union perf_event *event, bool sample_id_all)
@@ -1015,40 +1065,39 @@ out_parse_sample:
1015} 1065}
1016 1066
1017static s64 perf_session__process_event(struct perf_session *session, 1067static s64 perf_session__process_event(struct perf_session *session,
1018 union perf_event *event, 1068 union perf_event *event, u64 file_offset)
1019 struct perf_tool *tool,
1020 u64 file_offset)
1021{ 1069{
1070 struct perf_evlist *evlist = session->evlist;
1071 struct perf_tool *tool = session->tool;
1022 struct perf_sample sample; 1072 struct perf_sample sample;
1023 int ret; 1073 int ret;
1024 1074
1025 if (session->header.needs_swap) 1075 if (session->header.needs_swap)
1026 event_swap(event, perf_evlist__sample_id_all(session->evlist)); 1076 event_swap(event, perf_evlist__sample_id_all(evlist));
1027 1077
1028 if (event->header.type >= PERF_RECORD_HEADER_MAX) 1078 if (event->header.type >= PERF_RECORD_HEADER_MAX)
1029 return -EINVAL; 1079 return -EINVAL;
1030 1080
1031 events_stats__inc(&session->stats, event->header.type); 1081 events_stats__inc(&evlist->stats, event->header.type);
1032 1082
1033 if (event->header.type >= PERF_RECORD_USER_TYPE_START) 1083 if (event->header.type >= PERF_RECORD_USER_TYPE_START)
1034 return perf_session__process_user_event(session, event, tool, file_offset); 1084 return perf_session__process_user_event(session, event, file_offset);
1035 1085
1036 /* 1086 /*
1037 * For all kernel events we get the sample data 1087 * For all kernel events we get the sample data
1038 */ 1088 */
1039 ret = perf_evlist__parse_sample(session->evlist, event, &sample); 1089 ret = perf_evlist__parse_sample(evlist, event, &sample);
1040 if (ret) 1090 if (ret)
1041 return ret; 1091 return ret;
1042 1092
1043 if (tool->ordered_events) { 1093 if (tool->ordered_events) {
1044 ret = perf_session_queue_event(session, event, tool, &sample, 1094 ret = perf_session__queue_event(session, event, &sample, file_offset);
1045 file_offset);
1046 if (ret != -ETIME) 1095 if (ret != -ETIME)
1047 return ret; 1096 return ret;
1048 } 1097 }
1049 1098
1050 return perf_session__deliver_event(session, event, &sample, tool, 1099 return machines__deliver_event(&session->machines, evlist, event,
1051 file_offset); 1100 &sample, tool, file_offset);
1052} 1101}
1053 1102
1054void perf_event_header__bswap(struct perf_event_header *hdr) 1103void perf_event_header__bswap(struct perf_event_header *hdr)
@@ -1076,54 +1125,57 @@ static struct thread *perf_session__register_idle_thread(struct perf_session *se
1076 return thread; 1125 return thread;
1077} 1126}
1078 1127
1079static void perf_session__warn_about_errors(const struct perf_session *session, 1128static void perf_session__warn_about_errors(const struct perf_session *session)
1080 const struct perf_tool *tool)
1081{ 1129{
1082 if (tool->lost == perf_event__process_lost && 1130 const struct events_stats *stats = &session->evlist->stats;
1083 session->stats.nr_events[PERF_RECORD_LOST] != 0) { 1131 const struct ordered_events *oe = &session->ordered_events;
1132
1133 if (session->tool->lost == perf_event__process_lost &&
1134 stats->nr_events[PERF_RECORD_LOST] != 0) {
1084 ui__warning("Processed %d events and lost %d chunks!\n\n" 1135 ui__warning("Processed %d events and lost %d chunks!\n\n"
1085 "Check IO/CPU overload!\n\n", 1136 "Check IO/CPU overload!\n\n",
1086 session->stats.nr_events[0], 1137 stats->nr_events[0],
1087 session->stats.nr_events[PERF_RECORD_LOST]); 1138 stats->nr_events[PERF_RECORD_LOST]);
1088 } 1139 }
1089 1140
1090 if (session->stats.nr_unknown_events != 0) { 1141 if (stats->nr_unknown_events != 0) {
1091 ui__warning("Found %u unknown events!\n\n" 1142 ui__warning("Found %u unknown events!\n\n"
1092 "Is this an older tool processing a perf.data " 1143 "Is this an older tool processing a perf.data "
1093 "file generated by a more recent tool?\n\n" 1144 "file generated by a more recent tool?\n\n"
1094 "If that is not the case, consider " 1145 "If that is not the case, consider "
1095 "reporting to linux-kernel@vger.kernel.org.\n\n", 1146 "reporting to linux-kernel@vger.kernel.org.\n\n",
1096 session->stats.nr_unknown_events); 1147 stats->nr_unknown_events);
1097 } 1148 }
1098 1149
1099 if (session->stats.nr_unknown_id != 0) { 1150 if (stats->nr_unknown_id != 0) {
1100 ui__warning("%u samples with id not present in the header\n", 1151 ui__warning("%u samples with id not present in the header\n",
1101 session->stats.nr_unknown_id); 1152 stats->nr_unknown_id);
1102 } 1153 }
1103 1154
1104 if (session->stats.nr_invalid_chains != 0) { 1155 if (stats->nr_invalid_chains != 0) {
1105 ui__warning("Found invalid callchains!\n\n" 1156 ui__warning("Found invalid callchains!\n\n"
1106 "%u out of %u events were discarded for this reason.\n\n" 1157 "%u out of %u events were discarded for this reason.\n\n"
1107 "Consider reporting to linux-kernel@vger.kernel.org.\n\n", 1158 "Consider reporting to linux-kernel@vger.kernel.org.\n\n",
1108 session->stats.nr_invalid_chains, 1159 stats->nr_invalid_chains,
1109 session->stats.nr_events[PERF_RECORD_SAMPLE]); 1160 stats->nr_events[PERF_RECORD_SAMPLE]);
1110 } 1161 }
1111 1162
1112 if (session->stats.nr_unprocessable_samples != 0) { 1163 if (stats->nr_unprocessable_samples != 0) {
1113 ui__warning("%u unprocessable samples recorded.\n" 1164 ui__warning("%u unprocessable samples recorded.\n"
1114 "Do you have a KVM guest running and not using 'perf kvm'?\n", 1165 "Do you have a KVM guest running and not using 'perf kvm'?\n",
1115 session->stats.nr_unprocessable_samples); 1166 stats->nr_unprocessable_samples);
1116 } 1167 }
1117 1168
1118 if (session->stats.nr_unordered_events != 0) 1169 if (oe->nr_unordered_events != 0)
1119 ui__warning("%u out of order events recorded.\n", session->stats.nr_unordered_events); 1170 ui__warning("%u out of order events recorded.\n", oe->nr_unordered_events);
1120} 1171}
1121 1172
1122volatile int session_done; 1173volatile int session_done;
1123 1174
1124static int __perf_session__process_pipe_events(struct perf_session *session, 1175static int __perf_session__process_pipe_events(struct perf_session *session)
1125 struct perf_tool *tool)
1126{ 1176{
1177 struct ordered_events *oe = &session->ordered_events;
1178 struct perf_tool *tool = session->tool;
1127 int fd = perf_data_file__fd(session->file); 1179 int fd = perf_data_file__fd(session->file);
1128 union perf_event *event; 1180 union perf_event *event;
1129 uint32_t size, cur_size = 0; 1181 uint32_t size, cur_size = 0;
@@ -1187,7 +1239,7 @@ more:
1187 } 1239 }
1188 } 1240 }
1189 1241
1190 if ((skip = perf_session__process_event(session, event, tool, head)) < 0) { 1242 if ((skip = perf_session__process_event(session, event, head)) < 0) {
1191 pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n", 1243 pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n",
1192 head, event->header.size, event->header.type); 1244 head, event->header.size, event->header.type);
1193 err = -EINVAL; 1245 err = -EINVAL;
@@ -1203,10 +1255,10 @@ more:
1203 goto more; 1255 goto more;
1204done: 1256done:
1205 /* do the final flush for ordered samples */ 1257 /* do the final flush for ordered samples */
1206 err = ordered_events__flush(session, tool, OE_FLUSH__FINAL); 1258 err = ordered_events__flush(oe, OE_FLUSH__FINAL);
1207out_err: 1259out_err:
1208 free(buf); 1260 free(buf);
1209 perf_session__warn_about_errors(session, tool); 1261 perf_session__warn_about_errors(session);
1210 ordered_events__free(&session->ordered_events); 1262 ordered_events__free(&session->ordered_events);
1211 return err; 1263 return err;
1212} 1264}
@@ -1253,8 +1305,10 @@ fetch_mmaped_event(struct perf_session *session,
1253 1305
1254static int __perf_session__process_events(struct perf_session *session, 1306static int __perf_session__process_events(struct perf_session *session,
1255 u64 data_offset, u64 data_size, 1307 u64 data_offset, u64 data_size,
1256 u64 file_size, struct perf_tool *tool) 1308 u64 file_size)
1257{ 1309{
1310 struct ordered_events *oe = &session->ordered_events;
1311 struct perf_tool *tool = session->tool;
1258 int fd = perf_data_file__fd(session->file); 1312 int fd = perf_data_file__fd(session->file);
1259 u64 head, page_offset, file_offset, file_pos, size; 1313 u64 head, page_offset, file_offset, file_pos, size;
1260 int err, mmap_prot, mmap_flags, map_idx = 0; 1314 int err, mmap_prot, mmap_flags, map_idx = 0;
@@ -1323,8 +1377,7 @@ more:
1323 size = event->header.size; 1377 size = event->header.size;
1324 1378
1325 if (size < sizeof(struct perf_event_header) || 1379 if (size < sizeof(struct perf_event_header) ||
1326 (skip = perf_session__process_event(session, event, tool, file_pos)) 1380 (skip = perf_session__process_event(session, event, file_pos)) < 0) {
1327 < 0) {
1328 pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n", 1381 pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n",
1329 file_offset + head, event->header.size, 1382 file_offset + head, event->header.size,
1330 event->header.type); 1383 event->header.type);
@@ -1348,17 +1401,16 @@ more:
1348 1401
1349out: 1402out:
1350 /* do the final flush for ordered samples */ 1403 /* do the final flush for ordered samples */
1351 err = ordered_events__flush(session, tool, OE_FLUSH__FINAL); 1404 err = ordered_events__flush(oe, OE_FLUSH__FINAL);
1352out_err: 1405out_err:
1353 ui_progress__finish(); 1406 ui_progress__finish();
1354 perf_session__warn_about_errors(session, tool); 1407 perf_session__warn_about_errors(session);
1355 ordered_events__free(&session->ordered_events); 1408 ordered_events__free(&session->ordered_events);
1356 session->one_mmap = false; 1409 session->one_mmap = false;
1357 return err; 1410 return err;
1358} 1411}
1359 1412
1360int perf_session__process_events(struct perf_session *session, 1413int perf_session__process_events(struct perf_session *session)
1361 struct perf_tool *tool)
1362{ 1414{
1363 u64 size = perf_data_file__size(session->file); 1415 u64 size = perf_data_file__size(session->file);
1364 int err; 1416 int err;
@@ -1369,10 +1421,9 @@ int perf_session__process_events(struct perf_session *session,
1369 if (!perf_data_file__is_pipe(session->file)) 1421 if (!perf_data_file__is_pipe(session->file))
1370 err = __perf_session__process_events(session, 1422 err = __perf_session__process_events(session,
1371 session->header.data_offset, 1423 session->header.data_offset,
1372 session->header.data_size, 1424 session->header.data_size, size);
1373 size, tool);
1374 else 1425 else
1375 err = __perf_session__process_pipe_events(session, tool); 1426 err = __perf_session__process_pipe_events(session);
1376 1427
1377 return err; 1428 return err;
1378} 1429}
@@ -1415,6 +1466,9 @@ int maps__set_kallsyms_ref_reloc_sym(struct map **maps,
1415 1466
1416 for (i = 0; i < MAP__NR_TYPES; ++i) { 1467 for (i = 0; i < MAP__NR_TYPES; ++i) {
1417 struct kmap *kmap = map__kmap(maps[i]); 1468 struct kmap *kmap = map__kmap(maps[i]);
1469
1470 if (!kmap)
1471 continue;
1418 kmap->ref_reloc_sym = ref; 1472 kmap->ref_reloc_sym = ref;
1419 } 1473 }
1420 1474
@@ -1436,7 +1490,7 @@ size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp)
1436{ 1490{
1437 size_t ret = fprintf(fp, "Aggregated stats:\n"); 1491 size_t ret = fprintf(fp, "Aggregated stats:\n");
1438 1492
1439 ret += events_stats__fprintf(&session->stats, fp); 1493 ret += events_stats__fprintf(&session->evlist->stats, fp);
1440 return ret; 1494 return ret;
1441} 1495}
1442 1496
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 6d663dc76404..d5fa7b7916ef 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -20,13 +20,13 @@ 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;
27 u64 one_mmap_offset; 26 u64 one_mmap_offset;
28 struct ordered_events ordered_events; 27 struct ordered_events ordered_events;
29 struct perf_data_file *file; 28 struct perf_data_file *file;
29 struct perf_tool *tool;
30}; 30};
31 31
32#define PRINT_IP_OPT_IP (1<<0) 32#define PRINT_IP_OPT_IP (1<<0)
@@ -49,20 +49,13 @@ int perf_session__peek_event(struct perf_session *session, off_t file_offset,
49 union perf_event **event_ptr, 49 union perf_event **event_ptr,
50 struct perf_sample *sample); 50 struct perf_sample *sample);
51 51
52int perf_session__process_events(struct perf_session *session, 52int perf_session__process_events(struct perf_session *session);
53 struct perf_tool *tool);
54 53
55int perf_session_queue_event(struct perf_session *s, union perf_event *event, 54int perf_session__queue_event(struct perf_session *s, union perf_event *event,
56 struct perf_tool *tool, struct perf_sample *sample, 55 struct perf_sample *sample, u64 file_offset);
57 u64 file_offset);
58 56
59void perf_tool__fill_defaults(struct perf_tool *tool); 57void perf_tool__fill_defaults(struct perf_tool *tool);
60 58
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, 59int perf_session__resolve_callchain(struct perf_session *session,
67 struct perf_evsel *evsel, 60 struct perf_evsel *evsel,
68 struct thread *thread, 61 struct thread *thread,
@@ -126,8 +119,7 @@ extern volatile int session_done;
126 119
127int perf_session__deliver_synth_event(struct perf_session *session, 120int perf_session__deliver_synth_event(struct perf_session *session,
128 union perf_event *event, 121 union perf_event *event,
129 struct perf_sample *sample, 122 struct perf_sample *sample);
130 struct perf_tool *tool);
131 123
132int perf_event__process_id_index(struct perf_tool *tool, 124int perf_event__process_id_index(struct perf_tool *tool,
133 union perf_event *event, 125 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..a7ab6063e038 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;
@@ -753,6 +776,7 @@ int dso__load_sym(struct dso *dso, struct map *map,
753 symbol_filter_t filter, int kmodule) 776 symbol_filter_t filter, int kmodule)
754{ 777{
755 struct kmap *kmap = dso->kernel ? map__kmap(map) : NULL; 778 struct kmap *kmap = dso->kernel ? map__kmap(map) : NULL;
779 struct map_groups *kmaps = kmap ? map__kmaps(map) : NULL;
756 struct map *curr_map = map; 780 struct map *curr_map = map;
757 struct dso *curr_dso = dso; 781 struct dso *curr_dso = dso;
758 Elf_Data *symstrs, *secstrs; 782 Elf_Data *symstrs, *secstrs;
@@ -768,6 +792,9 @@ int dso__load_sym(struct dso *dso, struct map *map,
768 int nr = 0; 792 int nr = 0;
769 bool remap_kernel = false, adjust_kernel_syms = false; 793 bool remap_kernel = false, adjust_kernel_syms = false;
770 794
795 if (kmap && !kmaps)
796 return -1;
797
771 dso->symtab_type = syms_ss->type; 798 dso->symtab_type = syms_ss->type;
772 dso->is_64_bit = syms_ss->is_64_bit; 799 dso->is_64_bit = syms_ss->is_64_bit;
773 dso->rel = syms_ss->ehdr.e_type == ET_REL; 800 dso->rel = syms_ss->ehdr.e_type == ET_REL;
@@ -864,10 +891,9 @@ int dso__load_sym(struct dso *dso, struct map *map,
864 /* Reject ARM ELF "mapping symbols": these aren't unique and 891 /* Reject ARM ELF "mapping symbols": these aren't unique and
865 * don't identify functions, so will confuse the profile 892 * don't identify functions, so will confuse the profile
866 * output: */ 893 * output: */
867 if (ehdr.e_machine == EM_ARM) { 894 if (ehdr.e_machine == EM_ARM || ehdr.e_machine == EM_AARCH64) {
868 if (!strcmp(elf_name, "$a") || 895 if (elf_name[0] == '$' && strchr("adtx", elf_name[1])
869 !strcmp(elf_name, "$d") || 896 && (elf_name[2] == '\0' || elf_name[2] == '.'))
870 !strcmp(elf_name, "$t"))
871 continue; 897 continue;
872 } 898 }
873 899
@@ -936,8 +962,10 @@ int dso__load_sym(struct dso *dso, struct map *map,
936 map->map_ip = map__map_ip; 962 map->map_ip = map__map_ip;
937 map->unmap_ip = map__unmap_ip; 963 map->unmap_ip = map__unmap_ip;
938 /* Ensure maps are correctly ordered */ 964 /* Ensure maps are correctly ordered */
939 map_groups__remove(kmap->kmaps, map); 965 if (kmaps) {
940 map_groups__insert(kmap->kmaps, map); 966 map_groups__remove(kmaps, map);
967 map_groups__insert(kmaps, map);
968 }
941 } 969 }
942 970
943 /* 971 /*
@@ -961,7 +989,7 @@ int dso__load_sym(struct dso *dso, struct map *map,
961 snprintf(dso_name, sizeof(dso_name), 989 snprintf(dso_name, sizeof(dso_name),
962 "%s%s", dso->short_name, section_name); 990 "%s%s", dso->short_name, section_name);
963 991
964 curr_map = map_groups__find_by_name(kmap->kmaps, map->type, dso_name); 992 curr_map = map_groups__find_by_name(kmaps, map->type, dso_name);
965 if (curr_map == NULL) { 993 if (curr_map == NULL) {
966 u64 start = sym.st_value; 994 u64 start = sym.st_value;
967 995
@@ -991,7 +1019,7 @@ int dso__load_sym(struct dso *dso, struct map *map,
991 curr_map->unmap_ip = identity__map_ip; 1019 curr_map->unmap_ip = identity__map_ip;
992 } 1020 }
993 curr_dso->symtab_type = dso->symtab_type; 1021 curr_dso->symtab_type = dso->symtab_type;
994 map_groups__insert(kmap->kmaps, curr_map); 1022 map_groups__insert(kmaps, curr_map);
995 /* 1023 /*
996 * The new DSO should go to the kernel DSOS 1024 * The new DSO should go to the kernel DSOS
997 */ 1025 */
@@ -1045,14 +1073,15 @@ new_symbol:
1045 * For misannotated, zeroed, ASM function sizes. 1073 * For misannotated, zeroed, ASM function sizes.
1046 */ 1074 */
1047 if (nr > 0) { 1075 if (nr > 0) {
1048 symbols__fixup_duplicate(&dso->symbols[map->type]); 1076 if (!symbol_conf.allow_aliases)
1077 symbols__fixup_duplicate(&dso->symbols[map->type]);
1049 symbols__fixup_end(&dso->symbols[map->type]); 1078 symbols__fixup_end(&dso->symbols[map->type]);
1050 if (kmap) { 1079 if (kmap) {
1051 /* 1080 /*
1052 * We need to fixup this here too because we create new 1081 * We need to fixup this here too because we create new
1053 * maps here, for things like vsyscall sections. 1082 * maps here, for things like vsyscall sections.
1054 */ 1083 */
1055 __map_groups__fixup_end(kmap->kmaps, map->type); 1084 __map_groups__fixup_end(kmaps, map->type);
1056 } 1085 }
1057 } 1086 }
1058 err = nr; 1087 err = nr;
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..201f6c4ca738 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>
@@ -629,13 +630,16 @@ static int dso__load_all_kallsyms(struct dso *dso, const char *filename,
629static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map, 630static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map,
630 symbol_filter_t filter) 631 symbol_filter_t filter)
631{ 632{
632 struct map_groups *kmaps = map__kmap(map)->kmaps; 633 struct map_groups *kmaps = map__kmaps(map);
633 struct map *curr_map; 634 struct map *curr_map;
634 struct symbol *pos; 635 struct symbol *pos;
635 int count = 0, moved = 0; 636 int count = 0, moved = 0;
636 struct rb_root *root = &dso->symbols[map->type]; 637 struct rb_root *root = &dso->symbols[map->type];
637 struct rb_node *next = rb_first(root); 638 struct rb_node *next = rb_first(root);
638 639
640 if (!kmaps)
641 return -1;
642
639 while (next) { 643 while (next) {
640 char *module; 644 char *module;
641 645
@@ -681,8 +685,8 @@ static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map,
681static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta, 685static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta,
682 symbol_filter_t filter) 686 symbol_filter_t filter)
683{ 687{
684 struct map_groups *kmaps = map__kmap(map)->kmaps; 688 struct map_groups *kmaps = map__kmaps(map);
685 struct machine *machine = kmaps->machine; 689 struct machine *machine;
686 struct map *curr_map = map; 690 struct map *curr_map = map;
687 struct symbol *pos; 691 struct symbol *pos;
688 int count = 0, moved = 0; 692 int count = 0, moved = 0;
@@ -690,6 +694,11 @@ static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta,
690 struct rb_node *next = rb_first(root); 694 struct rb_node *next = rb_first(root);
691 int kernel_range = 0; 695 int kernel_range = 0;
692 696
697 if (!kmaps)
698 return -1;
699
700 machine = kmaps->machine;
701
693 while (next) { 702 while (next) {
694 char *module; 703 char *module;
695 704
@@ -1024,9 +1033,12 @@ static bool filename_from_kallsyms_filename(char *filename,
1024static int validate_kcore_modules(const char *kallsyms_filename, 1033static int validate_kcore_modules(const char *kallsyms_filename,
1025 struct map *map) 1034 struct map *map)
1026{ 1035{
1027 struct map_groups *kmaps = map__kmap(map)->kmaps; 1036 struct map_groups *kmaps = map__kmaps(map);
1028 char modules_filename[PATH_MAX]; 1037 char modules_filename[PATH_MAX];
1029 1038
1039 if (!kmaps)
1040 return -EINVAL;
1041
1030 if (!filename_from_kallsyms_filename(modules_filename, "modules", 1042 if (!filename_from_kallsyms_filename(modules_filename, "modules",
1031 kallsyms_filename)) 1043 kallsyms_filename))
1032 return -EINVAL; 1044 return -EINVAL;
@@ -1042,6 +1054,9 @@ static int validate_kcore_addresses(const char *kallsyms_filename,
1042{ 1054{
1043 struct kmap *kmap = map__kmap(map); 1055 struct kmap *kmap = map__kmap(map);
1044 1056
1057 if (!kmap)
1058 return -EINVAL;
1059
1045 if (kmap->ref_reloc_sym && kmap->ref_reloc_sym->name) { 1060 if (kmap->ref_reloc_sym && kmap->ref_reloc_sym->name) {
1046 u64 start; 1061 u64 start;
1047 1062
@@ -1080,8 +1095,8 @@ static int kcore_mapfn(u64 start, u64 len, u64 pgoff, void *data)
1080static int dso__load_kcore(struct dso *dso, struct map *map, 1095static int dso__load_kcore(struct dso *dso, struct map *map,
1081 const char *kallsyms_filename) 1096 const char *kallsyms_filename)
1082{ 1097{
1083 struct map_groups *kmaps = map__kmap(map)->kmaps; 1098 struct map_groups *kmaps = map__kmaps(map);
1084 struct machine *machine = kmaps->machine; 1099 struct machine *machine;
1085 struct kcore_mapfn_data md; 1100 struct kcore_mapfn_data md;
1086 struct map *old_map, *new_map, *replacement_map = NULL; 1101 struct map *old_map, *new_map, *replacement_map = NULL;
1087 bool is_64_bit; 1102 bool is_64_bit;
@@ -1089,6 +1104,11 @@ static int dso__load_kcore(struct dso *dso, struct map *map,
1089 char kcore_filename[PATH_MAX]; 1104 char kcore_filename[PATH_MAX];
1090 struct symbol *sym; 1105 struct symbol *sym;
1091 1106
1107 if (!kmaps)
1108 return -EINVAL;
1109
1110 machine = kmaps->machine;
1111
1092 /* This function requires that the map is the kernel map */ 1112 /* This function requires that the map is the kernel map */
1093 if (map != machine->vmlinux_maps[map->type]) 1113 if (map != machine->vmlinux_maps[map->type])
1094 return -EINVAL; 1114 return -EINVAL;
@@ -1201,6 +1221,9 @@ static int kallsyms__delta(struct map *map, const char *filename, u64 *delta)
1201 struct kmap *kmap = map__kmap(map); 1221 struct kmap *kmap = map__kmap(map);
1202 u64 addr; 1222 u64 addr;
1203 1223
1224 if (!kmap)
1225 return -1;
1226
1204 if (!kmap->ref_reloc_sym || !kmap->ref_reloc_sym->name) 1227 if (!kmap->ref_reloc_sym || !kmap->ref_reloc_sym->name)
1205 return 0; 1228 return 0;
1206 1229
@@ -1859,6 +1882,20 @@ int setup_list(struct strlist **list, const char *list_str,
1859 return 0; 1882 return 0;
1860} 1883}
1861 1884
1885int setup_intlist(struct intlist **list, const char *list_str,
1886 const char *list_name)
1887{
1888 if (list_str == NULL)
1889 return 0;
1890
1891 *list = intlist__new(list_str);
1892 if (!*list) {
1893 pr_err("problems parsing %s list\n", list_name);
1894 return -1;
1895 }
1896 return 0;
1897}
1898
1862static bool symbol__read_kptr_restrict(void) 1899static bool symbol__read_kptr_restrict(void)
1863{ 1900{
1864 bool value = false; 1901 bool value = false;
@@ -1909,9 +1946,17 @@ int symbol__init(struct perf_session_env *env)
1909 symbol_conf.comm_list_str, "comm") < 0) 1946 symbol_conf.comm_list_str, "comm") < 0)
1910 goto out_free_dso_list; 1947 goto out_free_dso_list;
1911 1948
1949 if (setup_intlist(&symbol_conf.pid_list,
1950 symbol_conf.pid_list_str, "pid") < 0)
1951 goto out_free_comm_list;
1952
1953 if (setup_intlist(&symbol_conf.tid_list,
1954 symbol_conf.tid_list_str, "tid") < 0)
1955 goto out_free_pid_list;
1956
1912 if (setup_list(&symbol_conf.sym_list, 1957 if (setup_list(&symbol_conf.sym_list,
1913 symbol_conf.sym_list_str, "symbol") < 0) 1958 symbol_conf.sym_list_str, "symbol") < 0)
1914 goto out_free_comm_list; 1959 goto out_free_tid_list;
1915 1960
1916 /* 1961 /*
1917 * A path to symbols of "/" is identical to "" 1962 * A path to symbols of "/" is identical to ""
@@ -1930,6 +1975,10 @@ int symbol__init(struct perf_session_env *env)
1930 symbol_conf.initialized = true; 1975 symbol_conf.initialized = true;
1931 return 0; 1976 return 0;
1932 1977
1978out_free_tid_list:
1979 intlist__delete(symbol_conf.tid_list);
1980out_free_pid_list:
1981 intlist__delete(symbol_conf.pid_list);
1933out_free_comm_list: 1982out_free_comm_list:
1934 strlist__delete(symbol_conf.comm_list); 1983 strlist__delete(symbol_conf.comm_list);
1935out_free_dso_list: 1984out_free_dso_list:
@@ -1944,6 +1993,8 @@ void symbol__exit(void)
1944 strlist__delete(symbol_conf.sym_list); 1993 strlist__delete(symbol_conf.sym_list);
1945 strlist__delete(symbol_conf.dso_list); 1994 strlist__delete(symbol_conf.dso_list);
1946 strlist__delete(symbol_conf.comm_list); 1995 strlist__delete(symbol_conf.comm_list);
1996 intlist__delete(symbol_conf.tid_list);
1997 intlist__delete(symbol_conf.pid_list);
1947 vmlinux_path__exit(); 1998 vmlinux_path__exit();
1948 symbol_conf.sym_list = symbol_conf.dso_list = symbol_conf.comm_list = NULL; 1999 symbol_conf.sym_list = symbol_conf.dso_list = symbol_conf.comm_list = NULL;
1949 symbol_conf.initialized = false; 2000 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-scripting.c b/tools/perf/util/trace-event-scripting.c
index 5c9bdd1591a9..9df61059a85d 100644
--- a/tools/perf/util/trace-event-scripting.c
+++ b/tools/perf/util/trace-event-scripting.c
@@ -43,7 +43,6 @@ static int stop_script_unsupported(void)
43static void process_event_unsupported(union perf_event *event __maybe_unused, 43static void process_event_unsupported(union perf_event *event __maybe_unused,
44 struct perf_sample *sample __maybe_unused, 44 struct perf_sample *sample __maybe_unused,
45 struct perf_evsel *evsel __maybe_unused, 45 struct perf_evsel *evsel __maybe_unused,
46 struct thread *thread __maybe_unused,
47 struct addr_location *al __maybe_unused) 46 struct addr_location *al __maybe_unused)
48{ 47{
49} 48}
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index 52aaa19e1eb1..d5168f0be4ec 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
@@ -69,8 +72,7 @@ struct scripting_ops {
69 void (*process_event) (union perf_event *event, 72 void (*process_event) (union perf_event *event,
70 struct perf_sample *sample, 73 struct perf_sample *sample,
71 struct perf_evsel *evsel, 74 struct perf_evsel *evsel,
72 struct thread *thread, 75 struct addr_location *al);
73 struct addr_location *al);
74 int (*generate_script) (struct pevent *pevent, const char *outfile); 76 int (*generate_script) (struct pevent *pevent, const char *outfile);
75}; 77};
76 78
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 */