aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2011-03-19 02:38:50 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2011-03-19 02:38:50 -0400
commit97eb3f24352ec6632c2127b35d8087d2a809a9b9 (patch)
tree722948059bbd325bbca232269490124231df80d4 /tools/perf
parent439581ec07fa9cf3f519dd461a2cf41cfd3adcb4 (diff)
parentdef179c271ac9b5020deca798470521f14d11edd (diff)
Merge branch 'next' into for-linus
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/Documentation/perf-annotate.txt37
-rw-r--r--tools/perf/Documentation/perf-buildid-list.txt3
-rw-r--r--tools/perf/Documentation/perf-diff.txt21
-rw-r--r--tools/perf/Documentation/perf-kvm.txt8
-rw-r--r--tools/perf/Documentation/perf-lock.txt15
-rw-r--r--tools/perf/Documentation/perf-probe.txt4
-rw-r--r--tools/perf/Documentation/perf-record.txt25
-rw-r--r--tools/perf/Documentation/perf-report.txt55
-rw-r--r--tools/perf/Documentation/perf-sched.txt18
-rw-r--r--tools/perf/Documentation/perf-script-perl.txt (renamed from tools/perf/Documentation/perf-trace-perl.txt)28
-rw-r--r--tools/perf/Documentation/perf-script-python.txt (renamed from tools/perf/Documentation/perf-trace-python.txt)88
-rw-r--r--tools/perf/Documentation/perf-script.txt118
-rw-r--r--tools/perf/Documentation/perf-stat.txt44
-rw-r--r--tools/perf/Documentation/perf-test.txt2
-rw-r--r--tools/perf/Documentation/perf-timechart.txt2
-rw-r--r--tools/perf/Documentation/perf-top.txt28
-rw-r--r--tools/perf/Documentation/perf-trace.txt70
-rw-r--r--tools/perf/MANIFEST1
-rw-r--r--tools/perf/Makefile34
-rw-r--r--tools/perf/arch/s390/Makefile4
-rw-r--r--tools/perf/arch/s390/util/dwarf-regs.c22
-rw-r--r--tools/perf/bench/mem-memcpy-arch.h12
-rw-r--r--tools/perf/bench/mem-memcpy-x86-64-asm-def.h4
-rw-r--r--tools/perf/bench/mem-memcpy-x86-64-asm.S2
-rw-r--r--tools/perf/bench/mem-memcpy.c219
-rw-r--r--tools/perf/builtin-annotate.c16
-rw-r--r--tools/perf/builtin-buildid-list.c6
-rw-r--r--tools/perf/builtin-diff.c21
-rw-r--r--tools/perf/builtin-inject.c41
-rw-r--r--tools/perf/builtin-kmem.c31
-rw-r--r--tools/perf/builtin-lock.c29
-rw-r--r--tools/perf/builtin-probe.c5
-rw-r--r--tools/perf/builtin-record.c254
-rw-r--r--tools/perf/builtin-report.c25
-rw-r--r--tools/perf/builtin-sched.c74
-rw-r--r--tools/perf/builtin-script.c (renamed from tools/perf/builtin-trace.c)326
-rw-r--r--tools/perf/builtin-stat.c535
-rw-r--r--tools/perf/builtin-test.c244
-rw-r--r--tools/perf/builtin-timechart.c132
-rw-r--r--tools/perf/builtin-top.c255
-rw-r--r--tools/perf/builtin.h2
-rw-r--r--tools/perf/command-list.txt2
-rw-r--r--tools/perf/feature-tests.mak4
-rw-r--r--tools/perf/perf.c2
-rw-r--r--tools/perf/scripts/perl/Perf-Trace-Util/Context.c2
-rw-r--r--tools/perf/scripts/perl/Perf-Trace-Util/Context.xs4
-rw-r--r--tools/perf/scripts/perl/Perf-Trace-Util/README4
-rw-r--r--tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Context.pm2
-rw-r--r--tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Core.pm4
-rw-r--r--tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Util.pm4
-rw-r--r--tools/perf/scripts/perl/bin/failed-syscalls-record2
-rw-r--r--tools/perf/scripts/perl/bin/failed-syscalls-report2
-rw-r--r--tools/perf/scripts/perl/bin/rw-by-file-record2
-rw-r--r--tools/perf/scripts/perl/bin/rw-by-file-report5
-rw-r--r--tools/perf/scripts/perl/bin/rw-by-pid-record2
-rw-r--r--tools/perf/scripts/perl/bin/rw-by-pid-report5
-rw-r--r--tools/perf/scripts/perl/bin/rwtop-record2
-rw-r--r--tools/perf/scripts/perl/bin/rwtop-report5
-rw-r--r--tools/perf/scripts/perl/bin/wakeup-latency-record2
-rw-r--r--tools/perf/scripts/perl/bin/wakeup-latency-report5
-rw-r--r--tools/perf/scripts/perl/bin/workqueue-stats-record2
-rw-r--r--tools/perf/scripts/perl/bin/workqueue-stats-report6
-rw-r--r--tools/perf/scripts/perl/check-perf-trace.pl2
-rw-r--r--tools/perf/scripts/perl/rw-by-file.pl2
-rw-r--r--tools/perf/scripts/perl/workqueue-stats.pl2
-rw-r--r--tools/perf/scripts/python/Perf-Trace-Util/Context.c2
-rw-r--r--tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py2
-rw-r--r--tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/SchedGui.py2
-rw-r--r--tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py2
-rw-r--r--tools/perf/scripts/python/bin/failed-syscalls-by-pid-record2
-rw-r--r--tools/perf/scripts/python/bin/failed-syscalls-by-pid-report2
-rw-r--r--tools/perf/scripts/python/bin/futex-contention-record2
-rw-r--r--tools/perf/scripts/python/bin/futex-contention-report2
-rw-r--r--tools/perf/scripts/python/bin/netdev-times-record2
-rw-r--r--tools/perf/scripts/python/bin/netdev-times-report2
-rw-r--r--tools/perf/scripts/python/bin/sched-migration-record2
-rw-r--r--tools/perf/scripts/python/bin/sched-migration-report2
-rw-r--r--tools/perf/scripts/python/bin/sctop-record2
-rw-r--r--tools/perf/scripts/python/bin/sctop-report2
-rw-r--r--tools/perf/scripts/python/bin/syscall-counts-by-pid-record2
-rw-r--r--tools/perf/scripts/python/bin/syscall-counts-by-pid-report2
-rw-r--r--tools/perf/scripts/python/bin/syscall-counts-record2
-rw-r--r--tools/perf/scripts/python/bin/syscall-counts-report2
-rw-r--r--tools/perf/scripts/python/check-perf-trace.py2
-rw-r--r--tools/perf/scripts/python/failed-syscalls-by-pid.py2
-rw-r--r--tools/perf/scripts/python/sched-migration.py2
-rw-r--r--tools/perf/scripts/python/sctop.py2
-rw-r--r--tools/perf/scripts/python/syscall-counts-by-pid.py2
-rw-r--r--tools/perf/scripts/python/syscall-counts.py2
-rw-r--r--tools/perf/util/build-id.c7
-rw-r--r--tools/perf/util/cpumap.c123
-rw-r--r--tools/perf/util/cpumap.h10
-rw-r--r--tools/perf/util/debug.c42
-rw-r--r--tools/perf/util/debug.h2
-rw-r--r--tools/perf/util/event.c363
-rw-r--r--tools/perf/util/event.h30
-rw-r--r--tools/perf/util/evsel.c201
-rw-r--r--tools/perf/util/evsel.h115
-rw-r--r--tools/perf/util/header.c83
-rw-r--r--tools/perf/util/header.h5
-rw-r--r--tools/perf/util/hist.c42
-rw-r--r--tools/perf/util/hist.h2
-rw-r--r--tools/perf/util/include/asm/cpufeature.h9
-rw-r--r--tools/perf/util/include/asm/dwarf2.h11
-rw-r--r--tools/perf/util/include/linux/bitops.h6
-rw-r--r--tools/perf/util/include/linux/linkage.h13
-rw-r--r--tools/perf/util/map.c3
-rw-r--r--tools/perf/util/parse-events.c154
-rw-r--r--tools/perf/util/parse-events.h19
-rw-r--r--tools/perf/util/parse-options.h4
-rw-r--r--tools/perf/util/probe-event.c251
-rw-r--r--tools/perf/util/probe-finder.c127
-rw-r--r--tools/perf/util/probe-finder.h6
-rw-r--r--tools/perf/util/scripting-engines/trace-event-perl.c6
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c4
-rw-r--r--tools/perf/util/session.c585
-rw-r--r--tools/perf/util/session.h26
-rw-r--r--tools/perf/util/sort.c6
-rw-r--r--tools/perf/util/string.c2
-rw-r--r--tools/perf/util/svghelper.c9
-rw-r--r--tools/perf/util/symbol.c220
-rw-r--r--tools/perf/util/symbol.h6
-rw-r--r--tools/perf/util/thread.c43
-rw-r--r--tools/perf/util/thread.h15
-rw-r--r--tools/perf/util/trace-event-info.c30
-rw-r--r--tools/perf/util/trace-event.h5
-rw-r--r--tools/perf/util/types.h10
-rw-r--r--tools/perf/util/ui/browsers/hists.c2
-rw-r--r--tools/perf/util/ui/browsers/map.c5
-rw-r--r--tools/perf/util/ui/util.c19
-rw-r--r--tools/perf/util/util.c17
-rw-r--r--tools/perf/util/util.h1
-rw-r--r--tools/perf/util/values.c10
-rw-r--r--tools/perf/util/xyarray.c20
-rw-r--r--tools/perf/util/xyarray.h20
135 files changed, 3935 insertions, 1736 deletions
diff --git a/tools/perf/Documentation/perf-annotate.txt b/tools/perf/Documentation/perf-annotate.txt
index b2c63309a651..6f5a498608b2 100644
--- a/tools/perf/Documentation/perf-annotate.txt
+++ b/tools/perf/Documentation/perf-annotate.txt
@@ -24,12 +24,47 @@ OPTIONS
24--input=:: 24--input=::
25 Input file name. (default: perf.data) 25 Input file name. (default: perf.data)
26 26
27-d::
28--dsos=<dso[,dso...]>::
29 Only consider symbols in these dsos.
30-s::
31--symbol=<symbol>::
32 Symbol to annotate.
33
34-f::
35--force::
36 Don't complain, do it.
37
38-v::
39--verbose::
40 Be more verbose. (Show symbol address, etc)
41
42-D::
43--dump-raw-trace::
44 Dump raw trace in ASCII.
45
46-k::
47--vmlinux=<file>::
48 vmlinux pathname.
49
50-m::
51--modules::
52 Load module symbols. WARNING: use only with -k and LIVE kernel.
53
54-l::
55--print-line::
56 Print matching source lines (may be slow).
57
58-P::
59--full-paths::
60 Don't shorten the displayed pathnames.
61
27--stdio:: Use the stdio interface. 62--stdio:: Use the stdio interface.
28 63
29--tui:: Use the TUI interface Use of --tui requires a tty, if one is not 64--tui:: Use the TUI interface Use of --tui requires a tty, if one is not
30 present, as when piping to other commands, the stdio interface is 65 present, as when piping to other commands, the stdio interface is
31 used. This interfaces starts by centering on the line with more 66 used. This interfaces starts by centering on the line with more
32 samples, TAB/UNTAB cycles thru the lines with more samples. 67 samples, TAB/UNTAB cycles through the lines with more samples.
33 68
34SEE ALSO 69SEE ALSO
35-------- 70--------
diff --git a/tools/perf/Documentation/perf-buildid-list.txt b/tools/perf/Documentation/perf-buildid-list.txt
index 01b642c0bf8f..5eaac6f26d51 100644
--- a/tools/perf/Documentation/perf-buildid-list.txt
+++ b/tools/perf/Documentation/perf-buildid-list.txt
@@ -18,6 +18,9 @@ perf report.
18 18
19OPTIONS 19OPTIONS
20------- 20-------
21-H::
22--with-hits::
23 Show only DSOs with hits.
21-i:: 24-i::
22--input=:: 25--input=::
23 Input file name. (default: perf.data) 26 Input file name. (default: perf.data)
diff --git a/tools/perf/Documentation/perf-diff.txt b/tools/perf/Documentation/perf-diff.txt
index 20d97d84ea1c..74d7481ed7a6 100644
--- a/tools/perf/Documentation/perf-diff.txt
+++ b/tools/perf/Documentation/perf-diff.txt
@@ -19,6 +19,18 @@ If no parameters are passed it will assume perf.data.old and perf.data.
19 19
20OPTIONS 20OPTIONS
21------- 21-------
22-M::
23--displacement::
24 Show position displacement relative to baseline.
25
26-D::
27--dump-raw-trace::
28 Dump raw trace in ASCII.
29
30-m::
31--modules::
32 Load module symbols. WARNING: use only with -k and LIVE kernel
33
22-d:: 34-d::
23--dsos=:: 35--dsos=::
24 Only consider symbols in these dsos. CSV that understands 36 Only consider symbols in these dsos. CSV that understands
@@ -42,7 +54,7 @@ OPTIONS
42--field-separator=:: 54--field-separator=::
43 55
44 Use a special separator character and don't pad with spaces, replacing 56 Use a special separator character and don't pad with spaces, replacing
45 all occurances of this separator in symbol names (and other output) 57 all occurrences of this separator in symbol names (and other output)
46 with a '.' character, that thus it's the only non valid separator. 58 with a '.' character, that thus it's the only non valid separator.
47 59
48-v:: 60-v::
@@ -50,6 +62,13 @@ OPTIONS
50 Be verbose, for instance, show the raw counts in addition to the 62 Be verbose, for instance, show the raw counts in addition to the
51 diff. 63 diff.
52 64
65-f::
66--force::
67 Don't complain, do it.
68
69--symfs=<directory>::
70 Look for files with symbols relative to this directory.
71
53SEE ALSO 72SEE ALSO
54-------- 73--------
55linkperf:perf-record[1] 74linkperf:perf-record[1]
diff --git a/tools/perf/Documentation/perf-kvm.txt b/tools/perf/Documentation/perf-kvm.txt
index d004e19fe6d6..dd84cb2f0a88 100644
--- a/tools/perf/Documentation/perf-kvm.txt
+++ b/tools/perf/Documentation/perf-kvm.txt
@@ -22,7 +22,7 @@ There are a couple of variants of perf kvm:
22 a performance counter profile of guest os in realtime 22 a performance counter profile of guest os in realtime
23 of an arbitrary workload. 23 of an arbitrary workload.
24 24
25 'perf kvm record <command>' to record the performance couinter profile 25 'perf kvm record <command>' to record the performance counter profile
26 of an arbitrary workload and save it into a perf data file. If both 26 of an arbitrary workload and save it into a perf data file. If both
27 --host and --guest are input, the perf data file name is perf.data.kvm. 27 --host and --guest are input, the perf data file name is perf.data.kvm.
28 If there is no --host but --guest, the file name is perf.data.guest. 28 If there is no --host but --guest, the file name is perf.data.guest.
@@ -40,6 +40,12 @@ There are a couple of variants of perf kvm:
40 40
41OPTIONS 41OPTIONS
42------- 42-------
43-i::
44--input=::
45 Input file name.
46-o::
47--output::
48 Output file name.
43--host=:: 49--host=::
44 Collect host side performance profile. 50 Collect host side performance profile.
45--guest=:: 51--guest=::
diff --git a/tools/perf/Documentation/perf-lock.txt b/tools/perf/Documentation/perf-lock.txt
index b317102138c8..921de259ea10 100644
--- a/tools/perf/Documentation/perf-lock.txt
+++ b/tools/perf/Documentation/perf-lock.txt
@@ -24,6 +24,21 @@ and statistics with this 'perf lock' command.
24 24
25 'perf lock report' reports statistical data. 25 'perf lock report' reports statistical data.
26 26
27OPTIONS
28-------
29
30-i::
31--input=<file>::
32 Input file name.
33
34-v::
35--verbose::
36 Be more verbose (show symbol address, etc).
37
38-D::
39--dump-raw-trace::
40 Dump raw trace in ASCII.
41
27SEE ALSO 42SEE ALSO
28-------- 43--------
29linkperf:perf[1] 44linkperf:perf[1]
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index 62de1b7f4e76..86b797a35aa6 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -115,9 +115,9 @@ Each probe argument follows below syntax.
115 115
116LINE SYNTAX 116LINE SYNTAX
117----------- 117-----------
118Line range is descripted by following syntax. 118Line range is described by following syntax.
119 119
120 "FUNC[:RLN[+NUM|-RLN2]]|SRC:ALN[+NUM|-ALN2]" 120 "FUNC[:RLN[+NUM|-RLN2]]|SRC[:ALN[+NUM|-ALN2]]"
121 121
122FUNC specifies the function name of showing lines. 'RLN' is the start line 122FUNC specifies the function name of showing lines. 'RLN' is the start line
123number from function entry line, and 'RLN2' is the end line number. As same as 123number from function entry line, and 'RLN2' is the end line number. As same as
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index a91f9f9e6e5c..e032716c839b 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -39,19 +39,31 @@ OPTIONS
39 be passed as follows: '\mem:addr[:[r][w][x]]'. 39 be passed as follows: '\mem:addr[:[r][w][x]]'.
40 If you want to profile read-write accesses in 0x1000, just set 40 If you want to profile read-write accesses in 0x1000, just set
41 'mem:0x1000:rw'. 41 'mem:0x1000:rw'.
42
43--filter=<filter>::
44 Event filter.
45
42-a:: 46-a::
43 System-wide collection. 47--all-cpus::
48 System-wide collection from all CPUs.
44 49
45-l:: 50-l::
46 Scale counter values. 51 Scale counter values.
47 52
48-p:: 53-p::
49--pid=:: 54--pid=::
50 Record events on existing pid. 55 Record events on existing process ID.
56
57-t::
58--tid=::
59 Record events on existing thread ID.
51 60
52-r:: 61-r::
53--realtime=:: 62--realtime=::
54 Collect data with this RT SCHED_FIFO priority. 63 Collect data with this RT SCHED_FIFO priority.
64-D::
65--no-delay::
66 Collect data without buffering.
55-A:: 67-A::
56--append:: 68--append::
57 Append to the output file to do incremental profiling. 69 Append to the output file to do incremental profiling.
@@ -99,6 +111,11 @@ OPTIONS
99--data:: 111--data::
100 Sample addresses. 112 Sample addresses.
101 113
114-T::
115--timestamp::
116 Sample timestamps. Use it with 'perf report -D' to see the timestamps,
117 for instance.
118
102-n:: 119-n::
103--no-samples:: 120--no-samples::
104 Don't sample. 121 Don't sample.
@@ -109,8 +126,8 @@ Collect raw sample records from all opened counters (default for tracepoint coun
109 126
110-C:: 127-C::
111--cpu:: 128--cpu::
112Collect samples only on the list of cpus provided. Multiple CPUs can be provided as a 129Collect samples only on the list of CPUs provided. Multiple CPUs can be provided as a
113comma-sperated list with no space: 0,1. Ranges of CPUs are specified with -: 0-2. 130comma-separated list with no space: 0,1. Ranges of CPUs are specified with -: 0-2.
114In per-thread mode with inheritance mode on (default), samples are captured only when 131In per-thread mode with inheritance mode on (default), samples are captured only when
115the thread executes on the designated CPUs. Default is to monitor all CPUs. 132the thread executes on the designated CPUs. Default is to monitor all CPUs.
116 133
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 12052c9ed0ba..8ba03d6e5398 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -20,6 +20,11 @@ OPTIONS
20-i:: 20-i::
21--input=:: 21--input=::
22 Input file name. (default: perf.data) 22 Input file name. (default: perf.data)
23
24-v::
25--verbose::
26 Be more verbose. (show symbol address, etc)
27
23-d:: 28-d::
24--dsos=:: 29--dsos=::
25 Only consider symbols in these dsos. CSV that understands 30 Only consider symbols in these dsos. CSV that understands
@@ -27,6 +32,10 @@ OPTIONS
27-n:: 32-n::
28--show-nr-samples:: 33--show-nr-samples::
29 Show the number of samples for each symbol 34 Show the number of samples for each symbol
35
36--showcpuutilization::
37 Show sample percentage for different cpu modes.
38
30-T:: 39-T::
31--threads:: 40--threads::
32 Show per-thread event counters 41 Show per-thread event counters
@@ -39,12 +48,24 @@ OPTIONS
39 Only consider these symbols. CSV that understands 48 Only consider these symbols. CSV that understands
40 file://filename entries. 49 file://filename entries.
41 50
51-U::
52--hide-unresolved::
53 Only display entries resolved to a symbol.
54
42-s:: 55-s::
43--sort=:: 56--sort=::
44 Sort by key(s): pid, comm, dso, symbol, parent. 57 Sort by key(s): pid, comm, dso, symbol, parent.
45 58
59-p::
60--parent=<regex>::
61 regex filter to identify parent, see: '--sort parent'
62
63-x::
64--exclude-other::
65 Only display entries with parent-match.
66
46-w:: 67-w::
47--field-width=:: 68--column-widths=<width[,width...]>::
48 Force each column width to the provided list, for large terminal 69 Force each column width to the provided list, for large terminal
49 readability. 70 readability.
50 71
@@ -52,19 +73,26 @@ OPTIONS
52--field-separator=:: 73--field-separator=::
53 74
54 Use a special separator character and don't pad with spaces, replacing 75 Use a special separator character and don't pad with spaces, replacing
55 all occurances of this separator in symbol names (and other output) 76 all occurrences of this separator in symbol names (and other output)
56 with a '.' character, that thus it's the only non valid separator. 77 with a '.' character, that thus it's the only non valid separator.
57 78
79-D::
80--dump-raw-trace::
81 Dump raw trace in ASCII.
82
58-g [type,min]:: 83-g [type,min]::
59--call-graph:: 84--call-graph::
60 Display callchains using type and min percent threshold. 85 Display call chains using type and min percent threshold.
61 type can be either: 86 type can be either:
62 - flat: single column, linear exposure of callchains. 87 - flat: single column, linear exposure of call chains.
63 - graph: use a graph tree, displaying absolute overhead rates. 88 - graph: use a graph tree, displaying absolute overhead rates.
64 - fractal: like graph, but displays relative rates. Each branch of 89 - fractal: like graph, but displays relative rates. Each branch of
65 the tree is considered as a new profiled object. + 90 the tree is considered as a new profiled object. +
66 Default: fractal,0.5. 91 Default: fractal,0.5.
67 92
93--pretty=<key>::
94 Pretty printing style. key: normal, raw
95
68--stdio:: Use the stdio interface. 96--stdio:: Use the stdio interface.
69 97
70--tui:: Use the TUI interface, that is integrated with annotate and allows 98--tui:: Use the TUI interface, that is integrated with annotate and allows
@@ -72,6 +100,25 @@ OPTIONS
72 requires a tty, if one is not present, as when piping to other 100 requires a tty, if one is not present, as when piping to other
73 commands, the stdio interface is used. 101 commands, the stdio interface is used.
74 102
103-k::
104--vmlinux=<file>::
105 vmlinux pathname
106
107--kallsyms=<file>::
108 kallsyms pathname
109
110-m::
111--modules::
112 Load module symbols. WARNING: This should only be used with -k and
113 a LIVE kernel.
114
115-f::
116--force::
117 Don't complain, do it.
118
119--symfs=<directory>::
120 Look for files with symbols relative to this directory.
121
75SEE ALSO 122SEE ALSO
76-------- 123--------
77linkperf:perf-stat[1] 124linkperf:perf-stat[1]
diff --git a/tools/perf/Documentation/perf-sched.txt b/tools/perf/Documentation/perf-sched.txt
index 8417644a6166..46822d5fde1c 100644
--- a/tools/perf/Documentation/perf-sched.txt
+++ b/tools/perf/Documentation/perf-sched.txt
@@ -8,11 +8,11 @@ perf-sched - Tool to trace/measure scheduler properties (latencies)
8SYNOPSIS 8SYNOPSIS
9-------- 9--------
10[verse] 10[verse]
11'perf sched' {record|latency|replay|trace} 11'perf sched' {record|latency|map|replay|trace}
12 12
13DESCRIPTION 13DESCRIPTION
14----------- 14-----------
15There are four variants of perf sched: 15There are five variants of perf sched:
16 16
17 'perf sched record <command>' to record the scheduling events 17 'perf sched record <command>' to record the scheduling events
18 of an arbitrary workload. 18 of an arbitrary workload.
@@ -30,8 +30,22 @@ There are four variants of perf sched:
30 of the workload as it occurred when it was recorded - and can repeat 30 of the workload as it occurred when it was recorded - and can repeat
31 it a number of times, measuring its performance.) 31 it a number of times, measuring its performance.)
32 32
33 'perf sched map' to print a textual context-switching outline of
34 workload captured via perf sched record. Columns stand for
35 individual CPUs, and the two-letter shortcuts stand for tasks that
36 are running on a CPU. A '*' denotes the CPU that had the event, and
37 a dot signals an idle CPU.
38
33OPTIONS 39OPTIONS
34------- 40-------
41-i::
42--input=<file>::
43 Input file name. (default: perf.data)
44
45-v::
46--verbose::
47 Be more verbose. (show symbol address, etc)
48
35-D:: 49-D::
36--dump-raw-trace=:: 50--dump-raw-trace=::
37 Display verbose dump of the sched data. 51 Display verbose dump of the sched data.
diff --git a/tools/perf/Documentation/perf-trace-perl.txt b/tools/perf/Documentation/perf-script-perl.txt
index ee6525ee6d69..5bb41e55a3ac 100644
--- a/tools/perf/Documentation/perf-trace-perl.txt
+++ b/tools/perf/Documentation/perf-script-perl.txt
@@ -1,19 +1,19 @@
1perf-trace-perl(1) 1perf-script-perl(1)
2================== 2==================
3 3
4NAME 4NAME
5---- 5----
6perf-trace-perl - Process trace data with a Perl script 6perf-script-perl - Process trace data with a Perl script
7 7
8SYNOPSIS 8SYNOPSIS
9-------- 9--------
10[verse] 10[verse]
11'perf trace' [-s [Perl]:script[.pl] ] 11'perf script' [-s [Perl]:script[.pl] ]
12 12
13DESCRIPTION 13DESCRIPTION
14----------- 14-----------
15 15
16This perf trace option is used to process perf trace data using perf's 16This perf script option is used to process perf script data using perf's
17built-in Perl interpreter. It reads and processes the input file and 17built-in Perl interpreter. It reads and processes the input file and
18displays the results of the trace analysis implemented in the given 18displays the results of the trace analysis implemented in the given
19Perl script, if any. 19Perl script, if any.
@@ -21,7 +21,7 @@ Perl script, if any.
21STARTER SCRIPTS 21STARTER SCRIPTS
22--------------- 22---------------
23 23
24You can avoid reading the rest of this document by running 'perf trace 24You can avoid reading the rest of this document by running 'perf script
25-g perl' in the same directory as an existing perf.data trace file. 25-g perl' in the same directory as an existing perf.data trace file.
26That will generate a starter script containing a handler for each of 26That will generate a starter script containing a handler for each of
27the event types in the trace file; it simply prints every available 27the event types in the trace file; it simply prints every available
@@ -30,13 +30,13 @@ field for each event in the trace file.
30You can also look at the existing scripts in 30You can also look at the existing scripts in
31~/libexec/perf-core/scripts/perl for typical examples showing how to 31~/libexec/perf-core/scripts/perl for typical examples showing how to
32do basic things like aggregate event data, print results, etc. Also, 32do basic things like aggregate event data, print results, etc. Also,
33the check-perf-trace.pl script, while not interesting for its results, 33the check-perf-script.pl script, while not interesting for its results,
34attempts to exercise all of the main scripting features. 34attempts to exercise all of the main scripting features.
35 35
36EVENT HANDLERS 36EVENT HANDLERS
37-------------- 37--------------
38 38
39When perf trace is invoked using a trace script, a user-defined 39When perf script is invoked using a trace script, a user-defined
40'handler function' is called for each event in the trace. If there's 40'handler function' is called for each event in the trace. If there's
41no handler function defined for a given event type, the event is 41no handler function defined for a given event type, the event is
42ignored (or passed to a 'trace_handled' function, see below) and the 42ignored (or passed to a 'trace_handled' function, see below) and the
@@ -112,13 +112,13 @@ write a useful trace script. The sections below cover the rest.
112SCRIPT LAYOUT 112SCRIPT LAYOUT
113------------- 113-------------
114 114
115Every perf trace Perl script should start by setting up a Perl module 115Every perf script Perl script should start by setting up a Perl module
116search path and 'use'ing a few support modules (see module 116search path and 'use'ing a few support modules (see module
117descriptions below): 117descriptions below):
118 118
119---- 119----
120 use lib "$ENV{'PERF_EXEC_PATH'}/scripts/perl/Perf-Trace-Util/lib"; 120 use lib "$ENV{'PERF_EXEC_PATH'}/scripts/perl/perf-script-Util/lib";
121 use lib "./Perf-Trace-Util/lib"; 121 use lib "./perf-script-Util/lib";
122 use Perf::Trace::Core; 122 use Perf::Trace::Core;
123 use Perf::Trace::Context; 123 use Perf::Trace::Context;
124 use Perf::Trace::Util; 124 use Perf::Trace::Util;
@@ -162,7 +162,7 @@ sub trace_unhandled
162---- 162----
163 163
164The remaining sections provide descriptions of each of the available 164The remaining sections provide descriptions of each of the available
165built-in perf trace Perl modules and their associated functions. 165built-in perf script Perl modules and their associated functions.
166 166
167AVAILABLE MODULES AND FUNCTIONS 167AVAILABLE MODULES AND FUNCTIONS
168------------------------------- 168-------------------------------
@@ -170,7 +170,7 @@ AVAILABLE MODULES AND FUNCTIONS
170The following sections describe the functions and variables available 170The following sections describe the functions and variables available
171via the various Perf::Trace::* Perl modules. To use the functions and 171via the various Perf::Trace::* Perl modules. To use the functions and
172variables from the given module, add the corresponding 'use 172variables from the given module, add the corresponding 'use
173Perf::Trace::XXX' line to your perf trace script. 173Perf::Trace::XXX' line to your perf script script.
174 174
175Perf::Trace::Core Module 175Perf::Trace::Core Module
176~~~~~~~~~~~~~~~~~~~~~~~~ 176~~~~~~~~~~~~~~~~~~~~~~~~
@@ -204,7 +204,7 @@ argument.
204Perf::Trace::Util Module 204Perf::Trace::Util Module
205~~~~~~~~~~~~~~~~~~~~~~~~ 205~~~~~~~~~~~~~~~~~~~~~~~~
206 206
207Various utility functions for use with perf trace: 207Various utility functions for use with perf script:
208 208
209 nsecs($secs, $nsecs) - returns total nsecs given secs/nsecs pair 209 nsecs($secs, $nsecs) - returns total nsecs given secs/nsecs pair
210 nsecs_secs($nsecs) - returns whole secs portion given nsecs 210 nsecs_secs($nsecs) - returns whole secs portion given nsecs
@@ -214,4 +214,4 @@ Various utility functions for use with perf trace:
214 214
215SEE ALSO 215SEE ALSO
216-------- 216--------
217linkperf:perf-trace[1] 217linkperf:perf-script[1]
diff --git a/tools/perf/Documentation/perf-trace-python.txt b/tools/perf/Documentation/perf-script-python.txt
index 693be804dd3d..36b38277422c 100644
--- a/tools/perf/Documentation/perf-trace-python.txt
+++ b/tools/perf/Documentation/perf-script-python.txt
@@ -1,19 +1,19 @@
1perf-trace-python(1) 1perf-script-python(1)
2==================== 2====================
3 3
4NAME 4NAME
5---- 5----
6perf-trace-python - Process trace data with a Python script 6perf-script-python - Process trace data with a Python script
7 7
8SYNOPSIS 8SYNOPSIS
9-------- 9--------
10[verse] 10[verse]
11'perf trace' [-s [Python]:script[.py] ] 11'perf script' [-s [Python]:script[.py] ]
12 12
13DESCRIPTION 13DESCRIPTION
14----------- 14-----------
15 15
16This perf trace option is used to process perf trace data using perf's 16This perf script option is used to process perf script data using perf's
17built-in Python interpreter. It reads and processes the input file and 17built-in Python interpreter. It reads and processes the input file and
18displays the results of the trace analysis implemented in the given 18displays the results of the trace analysis implemented in the given
19Python script, if any. 19Python script, if any.
@@ -23,15 +23,15 @@ A QUICK EXAMPLE
23 23
24This section shows the process, start to finish, of creating a working 24This section shows the process, start to finish, of creating a working
25Python script that aggregates and extracts useful information from a 25Python script that aggregates and extracts useful information from a
26raw perf trace stream. You can avoid reading the rest of this 26raw perf script stream. You can avoid reading the rest of this
27document if an example is enough for you; the rest of the document 27document if an example is enough for you; the rest of the document
28provides more details on each step and lists the library functions 28provides more details on each step and lists the library functions
29available to script writers. 29available to script writers.
30 30
31This example actually details the steps that were used to create the 31This example actually details the steps that were used to create the
32'syscall-counts' script you see when you list the available perf trace 32'syscall-counts' script you see when you list the available perf script
33scripts via 'perf trace -l'. As such, this script also shows how to 33scripts via 'perf script -l'. As such, this script also shows how to
34integrate your script into the list of general-purpose 'perf trace' 34integrate your script into the list of general-purpose 'perf script'
35scripts listed by that command. 35scripts listed by that command.
36 36
37The syscall-counts script is a simple script, but demonstrates all the 37The syscall-counts script is a simple script, but demonstrates all the
@@ -105,31 +105,31 @@ That single stream will be recorded in a file in the current directory
105called perf.data. 105called perf.data.
106 106
107Once we have a perf.data file containing our data, we can use the -g 107Once we have a perf.data file containing our data, we can use the -g
108'perf trace' option to generate a Python script that will contain a 108'perf script' option to generate a Python script that will contain a
109callback handler for each event type found in the perf.data trace 109callback handler for each event type found in the perf.data trace
110stream (for more details, see the STARTER SCRIPTS section). 110stream (for more details, see the STARTER SCRIPTS section).
111 111
112---- 112----
113# perf trace -g python 113# perf script -g python
114generated Python script: perf-trace.py 114generated Python script: perf-script.py
115 115
116The output file created also in the current directory is named 116The output file created also in the current directory is named
117perf-trace.py. Here's the file in its entirety: 117perf-script.py. Here's the file in its entirety:
118 118
119# perf trace event handlers, generated by perf trace -g python 119# perf script event handlers, generated by perf script -g python
120# Licensed under the terms of the GNU GPL License version 2 120# Licensed under the terms of the GNU GPL License version 2
121 121
122# The common_* event handler fields are the most useful fields common to 122# The common_* event handler fields are the most useful fields common to
123# all events. They don't necessarily correspond to the 'common_*' fields 123# all events. They don't necessarily correspond to the 'common_*' fields
124# in the format files. Those fields not available as handler params can 124# in the format files. Those fields not available as handler params can
125# be retrieved using Python functions of the form common_*(context). 125# be retrieved using Python functions of the form common_*(context).
126# See the perf-trace-python Documentation for the list of available functions. 126# See the perf-script-python Documentation for the list of available functions.
127 127
128import os 128import os
129import sys 129import sys
130 130
131sys.path.append(os.environ['PERF_EXEC_PATH'] + \ 131sys.path.append(os.environ['PERF_EXEC_PATH'] + \
132 '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') 132 '/scripts/python/perf-script-Util/lib/Perf/Trace')
133 133
134from perf_trace_context import * 134from perf_trace_context import *
135from Core import * 135from Core import *
@@ -160,7 +160,7 @@ def print_header(event_name, cpu, secs, nsecs, pid, comm):
160---- 160----
161 161
162At the top is a comment block followed by some import statements and a 162At the top is a comment block followed by some import statements and a
163path append which every perf trace script should include. 163path append which every perf script script should include.
164 164
165Following that are a couple generated functions, trace_begin() and 165Following that are a couple generated functions, trace_begin() and
166trace_end(), which are called at the beginning and the end of the 166trace_end(), which are called at the beginning and the end of the
@@ -189,8 +189,8 @@ simply a utility function used for that purpose. Let's rename the
189script and run it to see the default output: 189script and run it to see the default output:
190 190
191---- 191----
192# mv perf-trace.py syscall-counts.py 192# mv perf-script.py syscall-counts.py
193# perf trace -s syscall-counts.py 193# perf script -s syscall-counts.py
194 194
195raw_syscalls__sys_enter 1 00840.847582083 7506 perf id=1, args= 195raw_syscalls__sys_enter 1 00840.847582083 7506 perf id=1, args=
196raw_syscalls__sys_enter 1 00840.847595764 7506 perf id=1, args= 196raw_syscalls__sys_enter 1 00840.847595764 7506 perf id=1, args=
@@ -216,7 +216,7 @@ import os
216import sys 216import sys
217 217
218sys.path.append(os.environ['PERF_EXEC_PATH'] + \ 218sys.path.append(os.environ['PERF_EXEC_PATH'] + \
219 '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') 219 '/scripts/python/perf-script-Util/lib/Perf/Trace')
220 220
221from perf_trace_context import * 221from perf_trace_context import *
222from Core import * 222from Core import *
@@ -279,7 +279,7 @@ import os
279import sys 279import sys
280 280
281sys.path.append(os.environ['PERF_EXEC_PATH'] + \ 281sys.path.append(os.environ['PERF_EXEC_PATH'] + \
282 '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') 282 '/scripts/python/perf-script-Util/lib/Perf/Trace')
283 283
284from perf_trace_context import * 284from perf_trace_context import *
285from Core import * 285from Core import *
@@ -315,7 +315,7 @@ def print_syscall_totals():
315 315
316The script can be run just as before: 316The script can be run just as before:
317 317
318 # perf trace -s syscall-counts.py 318 # perf script -s syscall-counts.py
319 319
320So those are the essential steps in writing and running a script. The 320So those are the essential steps in writing and running a script. The
321process can be generalized to any tracepoint or set of tracepoints 321process can be generalized to any tracepoint or set of tracepoints
@@ -324,17 +324,17 @@ interested in by looking at the list of available events shown by
324'perf list' and/or look in /sys/kernel/debug/tracing events for 324'perf list' and/or look in /sys/kernel/debug/tracing events for
325detailed event and field info, record the corresponding trace data 325detailed event and field info, record the corresponding trace data
326using 'perf record', passing it the list of interesting events, 326using 'perf record', passing it the list of interesting events,
327generate a skeleton script using 'perf trace -g python' and modify the 327generate a skeleton script using 'perf script -g python' and modify the
328code to aggregate and display it for your particular needs. 328code to aggregate and display it for your particular needs.
329 329
330After you've done that you may end up with a general-purpose script 330After you've done that you may end up with a general-purpose script
331that you want to keep around and have available for future use. By 331that you want to keep around and have available for future use. By
332writing a couple of very simple shell scripts and putting them in the 332writing a couple of very simple shell scripts and putting them in the
333right place, you can have your script listed alongside the other 333right place, you can have your script listed alongside the other
334scripts listed by the 'perf trace -l' command e.g.: 334scripts listed by the 'perf script -l' command e.g.:
335 335
336---- 336----
337root@tropicana:~# perf trace -l 337root@tropicana:~# perf script -l
338List of available trace scripts: 338List of available trace scripts:
339 workqueue-stats workqueue stats (ins/exe/create/destroy) 339 workqueue-stats workqueue stats (ins/exe/create/destroy)
340 wakeup-latency system-wide min/max/avg wakeup latency 340 wakeup-latency system-wide min/max/avg wakeup latency
@@ -365,14 +365,14 @@ perf record -a -e raw_syscalls:sys_enter
365The 'report' script is also a shell script with the same base name as 365The 'report' script is also a shell script with the same base name as
366your script, but with -report appended. It should also be located in 366your script, but with -report appended. It should also be located in
367the perf/scripts/python/bin directory. In that script, you write the 367the perf/scripts/python/bin directory. In that script, you write the
368'perf trace -s' command-line needed for running your script: 368'perf script -s' command-line needed for running your script:
369 369
370---- 370----
371# cat kernel-source/tools/perf/scripts/python/bin/syscall-counts-report 371# cat kernel-source/tools/perf/scripts/python/bin/syscall-counts-report
372 372
373#!/bin/bash 373#!/bin/bash
374# description: system-wide syscall counts 374# description: system-wide syscall counts
375perf trace -s ~/libexec/perf-core/scripts/python/syscall-counts.py 375perf script -s ~/libexec/perf-core/scripts/python/syscall-counts.py
376---- 376----
377 377
378Note that the location of the Python script given in the shell script 378Note that the location of the Python script given in the shell script
@@ -390,17 +390,17 @@ total 32
390drwxr-xr-x 4 trz trz 4096 2010-01-26 22:30 . 390drwxr-xr-x 4 trz trz 4096 2010-01-26 22:30 .
391drwxr-xr-x 4 trz trz 4096 2010-01-26 22:29 .. 391drwxr-xr-x 4 trz trz 4096 2010-01-26 22:29 ..
392drwxr-xr-x 2 trz trz 4096 2010-01-26 22:29 bin 392drwxr-xr-x 2 trz trz 4096 2010-01-26 22:29 bin
393-rw-r--r-- 1 trz trz 2548 2010-01-26 22:29 check-perf-trace.py 393-rw-r--r-- 1 trz trz 2548 2010-01-26 22:29 check-perf-script.py
394drwxr-xr-x 3 trz trz 4096 2010-01-26 22:49 Perf-Trace-Util 394drwxr-xr-x 3 trz trz 4096 2010-01-26 22:49 perf-script-Util
395-rw-r--r-- 1 trz trz 1462 2010-01-26 22:30 syscall-counts.py 395-rw-r--r-- 1 trz trz 1462 2010-01-26 22:30 syscall-counts.py
396---- 396----
397 397
398Once you've done that (don't forget to do a new 'make install', 398Once you've done that (don't forget to do a new 'make install',
399otherwise your script won't show up at run-time), 'perf trace -l' 399otherwise your script won't show up at run-time), 'perf script -l'
400should show a new entry for your script: 400should show a new entry for your script:
401 401
402---- 402----
403root@tropicana:~# perf trace -l 403root@tropicana:~# perf script -l
404List of available trace scripts: 404List of available trace scripts:
405 workqueue-stats workqueue stats (ins/exe/create/destroy) 405 workqueue-stats workqueue stats (ins/exe/create/destroy)
406 wakeup-latency system-wide min/max/avg wakeup latency 406 wakeup-latency system-wide min/max/avg wakeup latency
@@ -409,19 +409,19 @@ List of available trace scripts:
409 syscall-counts system-wide syscall counts 409 syscall-counts system-wide syscall counts
410---- 410----
411 411
412You can now perform the record step via 'perf trace record': 412You can now perform the record step via 'perf script record':
413 413
414 # perf trace record syscall-counts 414 # perf script record syscall-counts
415 415
416and display the output using 'perf trace report': 416and display the output using 'perf script report':
417 417
418 # perf trace report syscall-counts 418 # perf script report syscall-counts
419 419
420STARTER SCRIPTS 420STARTER SCRIPTS
421--------------- 421---------------
422 422
423You can quickly get started writing a script for a particular set of 423You can quickly get started writing a script for a particular set of
424trace data by generating a skeleton script using 'perf trace -g 424trace data by generating a skeleton script using 'perf script -g
425python' in the same directory as an existing perf.data trace file. 425python' in the same directory as an existing perf.data trace file.
426That will generate a starter script containing a handler for each of 426That will generate a starter script containing a handler for each of
427the event types in the trace file; it simply prints every available 427the event types in the trace file; it simply prints every available
@@ -430,13 +430,13 @@ field for each event in the trace file.
430You can also look at the existing scripts in 430You can also look at the existing scripts in
431~/libexec/perf-core/scripts/python for typical examples showing how to 431~/libexec/perf-core/scripts/python for typical examples showing how to
432do basic things like aggregate event data, print results, etc. Also, 432do basic things like aggregate event data, print results, etc. Also,
433the check-perf-trace.py script, while not interesting for its results, 433the check-perf-script.py script, while not interesting for its results,
434attempts to exercise all of the main scripting features. 434attempts to exercise all of the main scripting features.
435 435
436EVENT HANDLERS 436EVENT HANDLERS
437-------------- 437--------------
438 438
439When perf trace is invoked using a trace script, a user-defined 439When perf script is invoked using a trace script, a user-defined
440'handler function' is called for each event in the trace. If there's 440'handler function' is called for each event in the trace. If there's
441no handler function defined for a given event type, the event is 441no handler function defined for a given event type, the event is
442ignored (or passed to a 'trace_handled' function, see below) and the 442ignored (or passed to a 'trace_handled' function, see below) and the
@@ -510,7 +510,7 @@ write a useful trace script. The sections below cover the rest.
510SCRIPT LAYOUT 510SCRIPT LAYOUT
511------------- 511-------------
512 512
513Every perf trace Python script should start by setting up a Python 513Every perf script Python script should start by setting up a Python
514module search path and 'import'ing a few support modules (see module 514module search path and 'import'ing a few support modules (see module
515descriptions below): 515descriptions below):
516 516
@@ -519,7 +519,7 @@ descriptions below):
519 import sys 519 import sys
520 520
521 sys.path.append(os.environ['PERF_EXEC_PATH'] + \ 521 sys.path.append(os.environ['PERF_EXEC_PATH'] + \
522 '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') 522 '/scripts/python/perf-script-Util/lib/Perf/Trace')
523 523
524 from perf_trace_context import * 524 from perf_trace_context import *
525 from Core import * 525 from Core import *
@@ -559,15 +559,15 @@ def trace_unhandled(event_name, context, common_cpu, common_secs,
559---- 559----
560 560
561The remaining sections provide descriptions of each of the available 561The remaining sections provide descriptions of each of the available
562built-in perf trace Python modules and their associated functions. 562built-in perf script Python modules and their associated functions.
563 563
564AVAILABLE MODULES AND FUNCTIONS 564AVAILABLE MODULES AND FUNCTIONS
565------------------------------- 565-------------------------------
566 566
567The following sections describe the functions and variables available 567The following sections describe the functions and variables available
568via the various perf trace Python modules. To use the functions and 568via the various perf script Python modules. To use the functions and
569variables from the given module, add the corresponding 'from XXXX 569variables from the given module, add the corresponding 'from XXXX
570import' line to your perf trace script. 570import' line to your perf script script.
571 571
572Core.py Module 572Core.py Module
573~~~~~~~~~~~~~~ 573~~~~~~~~~~~~~~
@@ -610,7 +610,7 @@ argument.
610Util.py Module 610Util.py Module
611~~~~~~~~~~~~~~ 611~~~~~~~~~~~~~~
612 612
613Various utility functions for use with perf trace: 613Various utility functions for use with perf script:
614 614
615 nsecs(secs, nsecs) - returns total nsecs given secs/nsecs pair 615 nsecs(secs, nsecs) - returns total nsecs given secs/nsecs pair
616 nsecs_secs(nsecs) - returns whole secs portion given nsecs 616 nsecs_secs(nsecs) - returns whole secs portion given nsecs
@@ -620,4 +620,4 @@ Various utility functions for use with perf trace:
620 620
621SEE ALSO 621SEE ALSO
622-------- 622--------
623linkperf:perf-trace[1] 623linkperf:perf-script[1]
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
new file mode 100644
index 000000000000..29ad94293cd2
--- /dev/null
+++ b/tools/perf/Documentation/perf-script.txt
@@ -0,0 +1,118 @@
1perf-script(1)
2=============
3
4NAME
5----
6perf-script - Read perf.data (created by perf record) and display trace output
7
8SYNOPSIS
9--------
10[verse]
11'perf script' [<options>]
12'perf script' [<options>] record <script> [<record-options>] <command>
13'perf script' [<options>] report <script> [script-args]
14'perf script' [<options>] <script> <required-script-args> [<record-options>] <command>
15'perf script' [<options>] <top-script> [script-args]
16
17DESCRIPTION
18-----------
19This command reads the input file and displays the trace recorded.
20
21There are several variants of perf script:
22
23 'perf script' to see a detailed trace of the workload that was
24 recorded.
25
26 You can also run a set of pre-canned scripts that aggregate and
27 summarize the raw trace data in various ways (the list of scripts is
28 available via 'perf script -l'). The following variants allow you to
29 record and run those scripts:
30
31 'perf script record <script> <command>' to record the events required
32 for 'perf script report'. <script> is the name displayed in the
33 output of 'perf script --list' i.e. the actual script name minus any
34 language extension. If <command> is not specified, the events are
35 recorded using the -a (system-wide) 'perf record' option.
36
37 'perf script report <script> [args]' to run and display the results
38 of <script>. <script> is the name displayed in the output of 'perf
39 trace --list' i.e. the actual script name minus any language
40 extension. The perf.data output from a previous run of 'perf script
41 record <script>' is used and should be present for this command to
42 succeed. [args] refers to the (mainly optional) args expected by
43 the script.
44
45 'perf script <script> <required-script-args> <command>' to both
46 record the events required for <script> and to run the <script>
47 using 'live-mode' i.e. without writing anything to disk. <script>
48 is the name displayed in the output of 'perf script --list' i.e. the
49 actual script name minus any language extension. If <command> is
50 not specified, the events are recorded using the -a (system-wide)
51 'perf record' option. If <script> has any required args, they
52 should be specified before <command>. This mode doesn't allow for
53 optional script args to be specified; if optional script args are
54 desired, they can be specified using separate 'perf script record'
55 and 'perf script report' commands, with the stdout of the record step
56 piped to the stdin of the report script, using the '-o -' and '-i -'
57 options of the corresponding commands.
58
59 'perf script <top-script>' to both record the events required for
60 <top-script> and to run the <top-script> using 'live-mode'
61 i.e. without writing anything to disk. <top-script> is the name
62 displayed in the output of 'perf script --list' i.e. the actual
63 script name minus any language extension; a <top-script> is defined
64 as any script name ending with the string 'top'.
65
66 [<record-options>] can be passed to the record steps of 'perf script
67 record' and 'live-mode' variants; this isn't possible however for
68 <top-script> 'live-mode' or 'perf script report' variants.
69
70 See the 'SEE ALSO' section for links to language-specific
71 information on how to write and run your own trace scripts.
72
73OPTIONS
74-------
75<command>...::
76 Any command you can specify in a shell.
77
78-D::
79--dump-raw-script=::
80 Display verbose dump of the trace data.
81
82-L::
83--Latency=::
84 Show latency attributes (irqs/preemption disabled, etc).
85
86-l::
87--list=::
88 Display a list of available trace scripts.
89
90-s ['lang']::
91--script=::
92 Process trace data with the given script ([lang]:script[.ext]).
93 If the string 'lang' is specified in place of a script name, a
94 list of supported languages will be displayed instead.
95
96-g::
97--gen-script=::
98 Generate perf-script.[ext] starter script for given language,
99 using current perf.data.
100
101-a::
102 Force system-wide collection. Scripts run without a <command>
103 normally use -a by default, while scripts run with a <command>
104 normally don't - this option allows the latter to be run in
105 system-wide mode.
106
107-i::
108--input=::
109 Input file name.
110
111-d::
112--debug-mode::
113 Do various checks like samples ordering and lost events.
114
115SEE ALSO
116--------
117linkperf:perf-record[1], linkperf:perf-script-perl[1],
118linkperf:perf-script-python[1]
diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index 4b3a2d46b437..b6da7affbbee 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -8,8 +8,8 @@ perf-stat - Run a command and gather performance counter statistics
8SYNOPSIS 8SYNOPSIS
9-------- 9--------
10[verse] 10[verse]
11'perf stat' [-e <EVENT> | --event=EVENT] [-S] [-a] <command> 11'perf stat' [-e <EVENT> | --event=EVENT] [-a] <command>
12'perf stat' [-e <EVENT> | --event=EVENT] [-S] [-a] -- <command> [<options>] 12'perf stat' [-e <EVENT> | --event=EVENT] [-a] -- <command> [<options>]
13 13
14DESCRIPTION 14DESCRIPTION
15----------- 15-----------
@@ -35,24 +35,54 @@ OPTIONS
35 child tasks do not inherit counters 35 child tasks do not inherit counters
36-p:: 36-p::
37--pid=<pid>:: 37--pid=<pid>::
38 stat events on existing pid 38 stat events on existing process id
39
40-t::
41--tid=<tid>::
42 stat events on existing thread id
43
39 44
40-a:: 45-a::
41 system-wide collection 46--all-cpus::
47 system-wide collection from all CPUs
42 48
43-c:: 49-c::
44 scale counter values 50--scale::
51 scale/normalize counter values
52
53-r::
54--repeat=<n>::
55 repeat command and print average + stddev (max: 100)
45 56
46-B:: 57-B::
58--big-num::
47 print large numbers with thousands' separators according to locale 59 print large numbers with thousands' separators according to locale
48 60
49-C:: 61-C::
50--cpu=:: 62--cpu=::
51Count only on the list of cpus provided. Multiple CPUs can be provided as a 63Count only on the list of CPUs provided. Multiple CPUs can be provided as a
52comma-sperated list with no space: 0,1. Ranges of CPUs are specified with -: 0-2. 64comma-separated list with no space: 0,1. Ranges of CPUs are specified with -: 0-2.
53In per-thread mode, this option is ignored. The -a option is still necessary 65In per-thread mode, this option is ignored. The -a option is still necessary
54to activate system-wide monitoring. Default is to count on all CPUs. 66to activate system-wide monitoring. Default is to count on all CPUs.
55 67
68-A::
69--no-aggr::
70Do not aggregate counts across all monitored CPUs in system-wide mode (-a).
71This option is only valid in system-wide mode.
72
73-n::
74--null::
75 null run - don't start any counters
76
77-v::
78--verbose::
79 be more verbose (show counter open errors, etc)
80
81-x SEP::
82--field-separator SEP::
83print counts using a CSV-style output to make it easy to import directly into
84spreadsheets. Columns are separated by the string specified in SEP.
85
56EXAMPLES 86EXAMPLES
57-------- 87--------
58 88
diff --git a/tools/perf/Documentation/perf-test.txt b/tools/perf/Documentation/perf-test.txt
index 1c4b5f5b7f71..2c3b462f64b0 100644
--- a/tools/perf/Documentation/perf-test.txt
+++ b/tools/perf/Documentation/perf-test.txt
@@ -12,7 +12,7 @@ SYNOPSIS
12 12
13DESCRIPTION 13DESCRIPTION
14----------- 14-----------
15This command does assorted sanity tests, initially thru linked routines but 15This command does assorted sanity tests, initially through linked routines but
16also will look for a directory with more tests in the form of scripts. 16also will look for a directory with more tests in the form of scripts.
17 17
18OPTIONS 18OPTIONS
diff --git a/tools/perf/Documentation/perf-timechart.txt b/tools/perf/Documentation/perf-timechart.txt
index 4b1788355eca..d7b79e2ba2ad 100644
--- a/tools/perf/Documentation/perf-timechart.txt
+++ b/tools/perf/Documentation/perf-timechart.txt
@@ -38,6 +38,8 @@ OPTIONS
38--process:: 38--process::
39 Select the processes to display, by name or PID 39 Select the processes to display, by name or PID
40 40
41--symfs=<directory>::
42 Look for files with symbols relative to this directory.
41 43
42SEE ALSO 44SEE ALSO
43-------- 45--------
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt
index 1f9687663f2a..f6eb1cdafb77 100644
--- a/tools/perf/Documentation/perf-top.txt
+++ b/tools/perf/Documentation/perf-top.txt
@@ -12,7 +12,7 @@ SYNOPSIS
12 12
13DESCRIPTION 13DESCRIPTION
14----------- 14-----------
15This command generates and displays a performance counter profile in realtime. 15This command generates and displays a performance counter profile in real time.
16 16
17 17
18OPTIONS 18OPTIONS
@@ -27,8 +27,8 @@ OPTIONS
27 27
28-C <cpu-list>:: 28-C <cpu-list>::
29--cpu=<cpu>:: 29--cpu=<cpu>::
30Monitor only on the list of cpus provided. Multiple CPUs can be provided as a 30Monitor only on the list of CPUs provided. Multiple CPUs can be provided as a
31comma-sperated list with no space: 0,1. Ranges of CPUs are specified with -: 0-2. 31comma-separated list with no space: 0,1. Ranges of CPUs are specified with -: 0-2.
32Default is to monitor all CPUS. 32Default is to monitor all CPUS.
33 33
34-d <seconds>:: 34-d <seconds>::
@@ -50,6 +50,10 @@ Default is to monitor all CPUS.
50--count-filter=<count>:: 50--count-filter=<count>::
51 Only display functions with more events than this. 51 Only display functions with more events than this.
52 52
53-g::
54--group::
55 Put the counters into a counter group.
56
53-F <freq>:: 57-F <freq>::
54--freq=<freq>:: 58--freq=<freq>::
55 Profile at this frequency. 59 Profile at this frequency.
@@ -68,7 +72,11 @@ Default is to monitor all CPUS.
68 72
69-p <pid>:: 73-p <pid>::
70--pid=<pid>:: 74--pid=<pid>::
71 Profile events on existing pid. 75 Profile events on existing Process ID.
76
77-t <tid>::
78--tid=<tid>::
79 Profile events on existing thread ID.
72 80
73-r <priority>:: 81-r <priority>::
74--realtime=<priority>:: 82--realtime=<priority>::
@@ -78,6 +86,18 @@ Default is to monitor all CPUS.
78--sym-annotate=<symbol>:: 86--sym-annotate=<symbol>::
79 Annotate this symbol. 87 Annotate this symbol.
80 88
89-K::
90--hide_kernel_symbols::
91 Hide kernel symbols.
92
93-U::
94--hide_user_symbols::
95 Hide user symbols.
96
97-D::
98--dump-symtab::
99 Dump the symbol table used for profiling.
100
81-v:: 101-v::
82--verbose:: 102--verbose::
83 Be more verbose (show counter open errors, etc). 103 Be more verbose (show counter open errors, etc).
diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt
deleted file mode 100644
index 122ec9dc4853..000000000000
--- a/tools/perf/Documentation/perf-trace.txt
+++ /dev/null
@@ -1,70 +0,0 @@
1perf-trace(1)
2=============
3
4NAME
5----
6perf-trace - Read perf.data (created by perf record) and display trace output
7
8SYNOPSIS
9--------
10[verse]
11'perf trace' {record <script> | report <script> [args] }
12
13DESCRIPTION
14-----------
15This command reads the input file and displays the trace recorded.
16
17There are several variants of perf trace:
18
19 'perf trace' to see a detailed trace of the workload that was
20 recorded.
21
22 You can also run a set of pre-canned scripts that aggregate and
23 summarize the raw trace data in various ways (the list of scripts is
24 available via 'perf trace -l'). The following variants allow you to
25 record and run those scripts:
26
27 'perf trace record <script>' to record the events required for 'perf
28 trace report'. <script> is the name displayed in the output of
29 'perf trace --list' i.e. the actual script name minus any language
30 extension.
31
32 'perf trace report <script>' to run and display the results of
33 <script>. <script> is the name displayed in the output of 'perf
34 trace --list' i.e. the actual script name minus any language
35 extension. The perf.data output from a previous run of 'perf trace
36 record <script>' is used and should be present for this command to
37 succeed.
38
39 See the 'SEE ALSO' section for links to language-specific
40 information on how to write and run your own trace scripts.
41
42OPTIONS
43-------
44-D::
45--dump-raw-trace=::
46 Display verbose dump of the trace data.
47
48-L::
49--Latency=::
50 Show latency attributes (irqs/preemption disabled, etc).
51
52-l::
53--list=::
54 Display a list of available trace scripts.
55
56-s ['lang']::
57--script=::
58 Process trace data with the given script ([lang]:script[.ext]).
59 If the string 'lang' is specified in place of a script name, a
60 list of supported languages will be displayed instead.
61
62-g::
63--gen-script=::
64 Generate perf-trace.[ext] starter script for given language,
65 using current perf.data.
66
67SEE ALSO
68--------
69linkperf:perf-record[1], linkperf:perf-trace-perl[1],
70linkperf:perf-trace-python[1]
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST
index 8c7fc0c8f0b8..c12659d8cb26 100644
--- a/tools/perf/MANIFEST
+++ b/tools/perf/MANIFEST
@@ -7,6 +7,7 @@ include/linux/stringify.h
7lib/rbtree.c 7lib/rbtree.c
8include/linux/swab.h 8include/linux/swab.h
9arch/*/include/asm/unistd*.h 9arch/*/include/asm/unistd*.h
10arch/*/lib/memcpy*.S
10include/linux/poison.h 11include/linux/poison.h
11include/linux/magic.h 12include/linux/magic.h
12include/linux/hw_breakpoint.h 13include/linux/hw_breakpoint.h
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index d1db0f676a4b..7141c42e1469 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -185,7 +185,10 @@ ifeq ($(ARCH),i386)
185 ARCH := x86 185 ARCH := x86
186endif 186endif
187ifeq ($(ARCH),x86_64) 187ifeq ($(ARCH),x86_64)
188 RAW_ARCH := x86_64
188 ARCH := x86 189 ARCH := x86
190 ARCH_CFLAGS := -DARCH_X86_64
191 ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S
189endif 192endif
190 193
191# CFLAGS and LDFLAGS are for the users to override from the command line. 194# CFLAGS and LDFLAGS are for the users to override from the command line.
@@ -201,13 +204,11 @@ EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wshadow
201EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Winit-self 204EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Winit-self
202EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wpacked 205EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wpacked
203EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wredundant-decls 206EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wredundant-decls
204EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wstack-protector
205EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wstrict-aliasing=3 207EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wstrict-aliasing=3
206EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wswitch-default 208EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wswitch-default
207EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wswitch-enum 209EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wswitch-enum
208EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wno-system-headers 210EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wno-system-headers
209EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wundef 211EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wundef
210EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wvolatile-register-var
211EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wwrite-strings 212EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wwrite-strings
212EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wbad-function-cast 213EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wbad-function-cast
213EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wmissing-declarations 214EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wmissing-declarations
@@ -224,7 +225,7 @@ ifndef PERF_DEBUG
224 CFLAGS_OPTIMIZE = -O6 225 CFLAGS_OPTIMIZE = -O6
225endif 226endif
226 227
227CFLAGS = -ggdb3 -Wall -Wextra -std=gnu99 -Werror $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) 228CFLAGS = -fno-omit-frame-pointer -ggdb3 -Wall -Wextra -std=gnu99 -Werror $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
228EXTLIBS = -lpthread -lrt -lelf -lm 229EXTLIBS = -lpthread -lrt -lelf -lm
229ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 230ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
230ALL_LDFLAGS = $(LDFLAGS) 231ALL_LDFLAGS = $(LDFLAGS)
@@ -291,6 +292,13 @@ ifeq ($(call try-cc,$(SOURCE_HELLO),-Werror -fstack-protector-all),y)
291 CFLAGS := $(CFLAGS) -fstack-protector-all 292 CFLAGS := $(CFLAGS) -fstack-protector-all
292endif 293endif
293 294
295ifeq ($(call try-cc,$(SOURCE_HELLO),-Werror -Wstack-protector),y)
296 CFLAGS := $(CFLAGS) -Wstack-protector
297endif
298
299ifeq ($(call try-cc,$(SOURCE_HELLO),-Werror -Wvolatile-register-var),y)
300 CFLAGS := $(CFLAGS) -Wvolatile-register-var
301endif
294 302
295### --- END CONFIGURATION SECTION --- 303### --- END CONFIGURATION SECTION ---
296 304
@@ -375,6 +383,7 @@ LIB_H += util/include/linux/prefetch.h
375LIB_H += util/include/linux/rbtree.h 383LIB_H += util/include/linux/rbtree.h
376LIB_H += util/include/linux/string.h 384LIB_H += util/include/linux/string.h
377LIB_H += util/include/linux/types.h 385LIB_H += util/include/linux/types.h
386LIB_H += util/include/linux/linkage.h
378LIB_H += util/include/asm/asm-offsets.h 387LIB_H += util/include/asm/asm-offsets.h
379LIB_H += util/include/asm/bug.h 388LIB_H += util/include/asm/bug.h
380LIB_H += util/include/asm/byteorder.h 389LIB_H += util/include/asm/byteorder.h
@@ -383,6 +392,8 @@ LIB_H += util/include/asm/swab.h
383LIB_H += util/include/asm/system.h 392LIB_H += util/include/asm/system.h
384LIB_H += util/include/asm/uaccess.h 393LIB_H += util/include/asm/uaccess.h
385LIB_H += util/include/dwarf-regs.h 394LIB_H += util/include/dwarf-regs.h
395LIB_H += util/include/asm/dwarf2.h
396LIB_H += util/include/asm/cpufeature.h
386LIB_H += perf.h 397LIB_H += perf.h
387LIB_H += util/cache.h 398LIB_H += util/cache.h
388LIB_H += util/callchain.h 399LIB_H += util/callchain.h
@@ -390,6 +401,7 @@ LIB_H += util/build-id.h
390LIB_H += util/debug.h 401LIB_H += util/debug.h
391LIB_H += util/debugfs.h 402LIB_H += util/debugfs.h
392LIB_H += util/event.h 403LIB_H += util/event.h
404LIB_H += util/evsel.h
393LIB_H += util/exec_cmd.h 405LIB_H += util/exec_cmd.h
394LIB_H += util/types.h 406LIB_H += util/types.h
395LIB_H += util/levenshtein.h 407LIB_H += util/levenshtein.h
@@ -398,6 +410,7 @@ LIB_H += util/parse-options.h
398LIB_H += util/parse-events.h 410LIB_H += util/parse-events.h
399LIB_H += util/quote.h 411LIB_H += util/quote.h
400LIB_H += util/util.h 412LIB_H += util/util.h
413LIB_H += util/xyarray.h
401LIB_H += util/header.h 414LIB_H += util/header.h
402LIB_H += util/help.h 415LIB_H += util/help.h
403LIB_H += util/session.h 416LIB_H += util/session.h
@@ -417,6 +430,7 @@ LIB_H += util/probe-finder.h
417LIB_H += util/probe-event.h 430LIB_H += util/probe-event.h
418LIB_H += util/pstack.h 431LIB_H += util/pstack.h
419LIB_H += util/cpumap.h 432LIB_H += util/cpumap.h
433LIB_H += $(ARCH_INCLUDE)
420 434
421LIB_OBJS += $(OUTPUT)util/abspath.o 435LIB_OBJS += $(OUTPUT)util/abspath.o
422LIB_OBJS += $(OUTPUT)util/alias.o 436LIB_OBJS += $(OUTPUT)util/alias.o
@@ -426,6 +440,7 @@ LIB_OBJS += $(OUTPUT)util/ctype.o
426LIB_OBJS += $(OUTPUT)util/debugfs.o 440LIB_OBJS += $(OUTPUT)util/debugfs.o
427LIB_OBJS += $(OUTPUT)util/environment.o 441LIB_OBJS += $(OUTPUT)util/environment.o
428LIB_OBJS += $(OUTPUT)util/event.o 442LIB_OBJS += $(OUTPUT)util/event.o
443LIB_OBJS += $(OUTPUT)util/evsel.o
429LIB_OBJS += $(OUTPUT)util/exec_cmd.o 444LIB_OBJS += $(OUTPUT)util/exec_cmd.o
430LIB_OBJS += $(OUTPUT)util/help.o 445LIB_OBJS += $(OUTPUT)util/help.o
431LIB_OBJS += $(OUTPUT)util/levenshtein.o 446LIB_OBJS += $(OUTPUT)util/levenshtein.o
@@ -463,6 +478,7 @@ LIB_OBJS += $(OUTPUT)util/sort.o
463LIB_OBJS += $(OUTPUT)util/hist.o 478LIB_OBJS += $(OUTPUT)util/hist.o
464LIB_OBJS += $(OUTPUT)util/probe-event.o 479LIB_OBJS += $(OUTPUT)util/probe-event.o
465LIB_OBJS += $(OUTPUT)util/util.o 480LIB_OBJS += $(OUTPUT)util/util.o
481LIB_OBJS += $(OUTPUT)util/xyarray.o
466LIB_OBJS += $(OUTPUT)util/cpumap.o 482LIB_OBJS += $(OUTPUT)util/cpumap.o
467 483
468BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o 484BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
@@ -472,6 +488,9 @@ BUILTIN_OBJS += $(OUTPUT)builtin-bench.o
472# Benchmark modules 488# Benchmark modules
473BUILTIN_OBJS += $(OUTPUT)bench/sched-messaging.o 489BUILTIN_OBJS += $(OUTPUT)bench/sched-messaging.o
474BUILTIN_OBJS += $(OUTPUT)bench/sched-pipe.o 490BUILTIN_OBJS += $(OUTPUT)bench/sched-pipe.o
491ifeq ($(RAW_ARCH),x86_64)
492BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy-x86-64-asm.o
493endif
475BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o 494BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o
476 495
477BUILTIN_OBJS += $(OUTPUT)builtin-diff.o 496BUILTIN_OBJS += $(OUTPUT)builtin-diff.o
@@ -485,7 +504,7 @@ BUILTIN_OBJS += $(OUTPUT)builtin-report.o
485BUILTIN_OBJS += $(OUTPUT)builtin-stat.o 504BUILTIN_OBJS += $(OUTPUT)builtin-stat.o
486BUILTIN_OBJS += $(OUTPUT)builtin-timechart.o 505BUILTIN_OBJS += $(OUTPUT)builtin-timechart.o
487BUILTIN_OBJS += $(OUTPUT)builtin-top.o 506BUILTIN_OBJS += $(OUTPUT)builtin-top.o
488BUILTIN_OBJS += $(OUTPUT)builtin-trace.o 507BUILTIN_OBJS += $(OUTPUT)builtin-script.o
489BUILTIN_OBJS += $(OUTPUT)builtin-probe.o 508BUILTIN_OBJS += $(OUTPUT)builtin-probe.o
490BUILTIN_OBJS += $(OUTPUT)builtin-kmem.o 509BUILTIN_OBJS += $(OUTPUT)builtin-kmem.o
491BUILTIN_OBJS += $(OUTPUT)builtin-lock.o 510BUILTIN_OBJS += $(OUTPUT)builtin-lock.o
@@ -507,7 +526,7 @@ PERFLIBS = $(LIB_FILE)
507-include config.mak 526-include config.mak
508 527
509ifndef NO_DWARF 528ifndef NO_DWARF
510FLAGS_DWARF=$(ALL_CFLAGS) -I/usr/include/elfutils -ldw -lelf $(ALL_LDFLAGS) $(EXTLIBS) 529FLAGS_DWARF=$(ALL_CFLAGS) -ldw -lelf $(ALL_LDFLAGS) $(EXTLIBS)
511ifneq ($(call try-cc,$(SOURCE_DWARF),$(FLAGS_DWARF)),y) 530ifneq ($(call try-cc,$(SOURCE_DWARF),$(FLAGS_DWARF)),y)
512 msg := $(warning No libdw.h found or old libdw.h found or elfutils is older than 0.138, disables dwarf support. Please install new elfutils-devel/libdw-dev); 531 msg := $(warning No libdw.h found or old libdw.h found or elfutils is older than 0.138, disables dwarf support. Please install new elfutils-devel/libdw-dev);
513 NO_DWARF := 1 532 NO_DWARF := 1
@@ -554,7 +573,7 @@ ifndef NO_DWARF
554ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined) 573ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined)
555 msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled); 574 msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled);
556else 575else
557 BASIC_CFLAGS += -I/usr/include/elfutils -DDWARF_SUPPORT 576 BASIC_CFLAGS += -DDWARF_SUPPORT
558 EXTLIBS += -lelf -ldw 577 EXTLIBS += -lelf -ldw
559 LIB_OBJS += $(OUTPUT)util/probe-finder.o 578 LIB_OBJS += $(OUTPUT)util/probe-finder.o
560endif # PERF_HAVE_DWARF_REGS 579endif # PERF_HAVE_DWARF_REGS
@@ -891,13 +910,14 @@ prefix_SQ = $(subst ','\'',$(prefix))
891SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH)) 910SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH))
892PERL_PATH_SQ = $(subst ','\'',$(PERL_PATH)) 911PERL_PATH_SQ = $(subst ','\'',$(PERL_PATH))
893 912
894LIBS = $(PERFLIBS) $(EXTLIBS) 913LIBS = -Wl,--whole-archive $(PERFLIBS) -Wl,--no-whole-archive $(EXTLIBS)
895 914
896BASIC_CFLAGS += -DSHA1_HEADER='$(SHA1_HEADER_SQ)' \ 915BASIC_CFLAGS += -DSHA1_HEADER='$(SHA1_HEADER_SQ)' \
897 $(COMPAT_CFLAGS) 916 $(COMPAT_CFLAGS)
898LIB_OBJS += $(COMPAT_OBJS) 917LIB_OBJS += $(COMPAT_OBJS)
899 918
900ALL_CFLAGS += $(BASIC_CFLAGS) 919ALL_CFLAGS += $(BASIC_CFLAGS)
920ALL_CFLAGS += $(ARCH_CFLAGS)
901ALL_LDFLAGS += $(BASIC_LDFLAGS) 921ALL_LDFLAGS += $(BASIC_LDFLAGS)
902 922
903export TAR INSTALL DESTDIR SHELL_PATH 923export TAR INSTALL DESTDIR SHELL_PATH
diff --git a/tools/perf/arch/s390/Makefile b/tools/perf/arch/s390/Makefile
new file mode 100644
index 000000000000..15130b50dfe3
--- /dev/null
+++ b/tools/perf/arch/s390/Makefile
@@ -0,0 +1,4 @@
1ifndef NO_DWARF
2PERF_HAVE_DWARF_REGS := 1
3LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
4endif
diff --git a/tools/perf/arch/s390/util/dwarf-regs.c b/tools/perf/arch/s390/util/dwarf-regs.c
new file mode 100644
index 000000000000..e19653e025fa
--- /dev/null
+++ b/tools/perf/arch/s390/util/dwarf-regs.c
@@ -0,0 +1,22 @@
1/*
2 * Mapping of DWARF debug register numbers into register names.
3 *
4 * Copyright IBM Corp. 2010
5 * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>,
6 *
7 */
8
9#include <libio.h>
10#include <dwarf-regs.h>
11
12#define NUM_GPRS 16
13
14static const char *gpr_names[NUM_GPRS] = {
15 "%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7",
16 "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",
17};
18
19const char *get_arch_regstr(unsigned int n)
20{
21 return (n >= NUM_GPRS) ? NULL : gpr_names[n];
22}
diff --git a/tools/perf/bench/mem-memcpy-arch.h b/tools/perf/bench/mem-memcpy-arch.h
new file mode 100644
index 000000000000..a72e36cb5394
--- /dev/null
+++ b/tools/perf/bench/mem-memcpy-arch.h
@@ -0,0 +1,12 @@
1
2#ifdef ARCH_X86_64
3
4#define MEMCPY_FN(fn, name, desc) \
5 extern void *fn(void *, const void *, size_t);
6
7#include "mem-memcpy-x86-64-asm-def.h"
8
9#undef MEMCPY_FN
10
11#endif
12
diff --git a/tools/perf/bench/mem-memcpy-x86-64-asm-def.h b/tools/perf/bench/mem-memcpy-x86-64-asm-def.h
new file mode 100644
index 000000000000..d588b87696fc
--- /dev/null
+++ b/tools/perf/bench/mem-memcpy-x86-64-asm-def.h
@@ -0,0 +1,4 @@
1
2MEMCPY_FN(__memcpy,
3 "x86-64-unrolled",
4 "unrolled 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
new file mode 100644
index 000000000000..a57b66e853c2
--- /dev/null
+++ b/tools/perf/bench/mem-memcpy-x86-64-asm.S
@@ -0,0 +1,2 @@
1
2#include "../../../arch/x86/lib/memcpy_64.S"
diff --git a/tools/perf/bench/mem-memcpy.c b/tools/perf/bench/mem-memcpy.c
index 38dae7465142..db82021f4b91 100644
--- a/tools/perf/bench/mem-memcpy.c
+++ b/tools/perf/bench/mem-memcpy.c
@@ -12,6 +12,7 @@
12#include "../util/parse-options.h" 12#include "../util/parse-options.h"
13#include "../util/header.h" 13#include "../util/header.h"
14#include "bench.h" 14#include "bench.h"
15#include "mem-memcpy-arch.h"
15 16
16#include <stdio.h> 17#include <stdio.h>
17#include <stdlib.h> 18#include <stdlib.h>
@@ -23,8 +24,10 @@
23 24
24static const char *length_str = "1MB"; 25static const char *length_str = "1MB";
25static const char *routine = "default"; 26static const char *routine = "default";
26static bool use_clock = false; 27static bool use_clock;
27static int clock_fd; 28static int clock_fd;
29static bool only_prefault;
30static bool no_prefault;
28 31
29static const struct option options[] = { 32static const struct option options[] = {
30 OPT_STRING('l', "length", &length_str, "1MB", 33 OPT_STRING('l', "length", &length_str, "1MB",
@@ -34,19 +37,33 @@ static const struct option options[] = {
34 "Specify routine to copy"), 37 "Specify routine to copy"),
35 OPT_BOOLEAN('c', "clock", &use_clock, 38 OPT_BOOLEAN('c', "clock", &use_clock,
36 "Use CPU clock for measuring"), 39 "Use CPU clock for measuring"),
40 OPT_BOOLEAN('o', "only-prefault", &only_prefault,
41 "Show only the result with page faults before memcpy()"),
42 OPT_BOOLEAN('n', "no-prefault", &no_prefault,
43 "Show only the result without page faults before memcpy()"),
37 OPT_END() 44 OPT_END()
38}; 45};
39 46
47typedef void *(*memcpy_t)(void *, const void *, size_t);
48
40struct routine { 49struct routine {
41 const char *name; 50 const char *name;
42 const char *desc; 51 const char *desc;
43 void * (*fn)(void *dst, const void *src, size_t len); 52 memcpy_t fn;
44}; 53};
45 54
46struct routine routines[] = { 55struct routine routines[] = {
47 { "default", 56 { "default",
48 "Default memcpy() provided by glibc", 57 "Default memcpy() provided by glibc",
49 memcpy }, 58 memcpy },
59#ifdef ARCH_X86_64
60
61#define MEMCPY_FN(fn, name, desc) { name, desc, fn },
62#include "mem-memcpy-x86-64-asm-def.h"
63#undef MEMCPY_FN
64
65#endif
66
50 { NULL, 67 { NULL,
51 NULL, 68 NULL,
52 NULL } 69 NULL }
@@ -89,29 +106,98 @@ static double timeval2double(struct timeval *ts)
89 (double)ts->tv_usec / (double)1000000; 106 (double)ts->tv_usec / (double)1000000;
90} 107}
91 108
109static void alloc_mem(void **dst, void **src, size_t length)
110{
111 *dst = zalloc(length);
112 if (!dst)
113 die("memory allocation failed - maybe length is too large?\n");
114
115 *src = zalloc(length);
116 if (!src)
117 die("memory allocation failed - maybe length is too large?\n");
118}
119
120static u64 do_memcpy_clock(memcpy_t fn, size_t len, bool prefault)
121{
122 u64 clock_start = 0ULL, clock_end = 0ULL;
123 void *src = NULL, *dst = NULL;
124
125 alloc_mem(&src, &dst, len);
126
127 if (prefault)
128 fn(dst, src, len);
129
130 clock_start = get_clock();
131 fn(dst, src, len);
132 clock_end = get_clock();
133
134 free(src);
135 free(dst);
136 return clock_end - clock_start;
137}
138
139static double do_memcpy_gettimeofday(memcpy_t fn, size_t len, bool prefault)
140{
141 struct timeval tv_start, tv_end, tv_diff;
142 void *src = NULL, *dst = NULL;
143
144 alloc_mem(&src, &dst, len);
145
146 if (prefault)
147 fn(dst, src, len);
148
149 BUG_ON(gettimeofday(&tv_start, NULL));
150 fn(dst, src, len);
151 BUG_ON(gettimeofday(&tv_end, NULL));
152
153 timersub(&tv_end, &tv_start, &tv_diff);
154
155 free(src);
156 free(dst);
157 return (double)((double)len / timeval2double(&tv_diff));
158}
159
160#define pf (no_prefault ? 0 : 1)
161
162#define print_bps(x) do { \
163 if (x < K) \
164 printf(" %14lf B/Sec", x); \
165 else if (x < K * K) \
166 printf(" %14lfd KB/Sec", x / K); \
167 else if (x < K * K * K) \
168 printf(" %14lf MB/Sec", x / K / K); \
169 else \
170 printf(" %14lf GB/Sec", x / K / K / K); \
171 } while (0)
172
92int bench_mem_memcpy(int argc, const char **argv, 173int bench_mem_memcpy(int argc, const char **argv,
93 const char *prefix __used) 174 const char *prefix __used)
94{ 175{
95 int i; 176 int i;
96 void *dst, *src; 177 size_t len;
97 size_t length; 178 double result_bps[2];
98 double bps = 0.0; 179 u64 result_clock[2];
99 struct timeval tv_start, tv_end, tv_diff;
100 u64 clock_start, clock_end, clock_diff;
101 180
102 clock_start = clock_end = clock_diff = 0ULL;
103 argc = parse_options(argc, argv, options, 181 argc = parse_options(argc, argv, options,
104 bench_mem_memcpy_usage, 0); 182 bench_mem_memcpy_usage, 0);
105 183
106 tv_diff.tv_sec = 0; 184 if (use_clock)
107 tv_diff.tv_usec = 0; 185 init_clock();
108 length = (size_t)perf_atoll((char *)length_str); 186
187 len = (size_t)perf_atoll((char *)length_str);
109 188
110 if ((s64)length <= 0) { 189 result_clock[0] = result_clock[1] = 0ULL;
190 result_bps[0] = result_bps[1] = 0.0;
191
192 if ((s64)len <= 0) {
111 fprintf(stderr, "Invalid length:%s\n", length_str); 193 fprintf(stderr, "Invalid length:%s\n", length_str);
112 return 1; 194 return 1;
113 } 195 }
114 196
197 /* same to without specifying either of prefault and no-prefault */
198 if (only_prefault && no_prefault)
199 only_prefault = no_prefault = false;
200
115 for (i = 0; routines[i].name; i++) { 201 for (i = 0; routines[i].name; i++) {
116 if (!strcmp(routines[i].name, routine)) 202 if (!strcmp(routines[i].name, routine))
117 break; 203 break;
@@ -126,61 +212,80 @@ int bench_mem_memcpy(int argc, const char **argv,
126 return 1; 212 return 1;
127 } 213 }
128 214
129 dst = zalloc(length); 215 if (bench_format == BENCH_FORMAT_DEFAULT)
130 if (!dst) 216 printf("# Copying %s Bytes ...\n\n", length_str);
131 die("memory allocation failed - maybe length is too large?\n");
132
133 src = zalloc(length);
134 if (!src)
135 die("memory allocation failed - maybe length is too large?\n");
136
137 if (bench_format == BENCH_FORMAT_DEFAULT) {
138 printf("# Copying %s Bytes from %p to %p ...\n\n",
139 length_str, src, dst);
140 }
141
142 if (use_clock) {
143 init_clock();
144 clock_start = get_clock();
145 } else {
146 BUG_ON(gettimeofday(&tv_start, NULL));
147 }
148
149 routines[i].fn(dst, src, length);
150 217
151 if (use_clock) { 218 if (!only_prefault && !no_prefault) {
152 clock_end = get_clock(); 219 /* show both of results */
153 clock_diff = clock_end - clock_start; 220 if (use_clock) {
221 result_clock[0] =
222 do_memcpy_clock(routines[i].fn, len, false);
223 result_clock[1] =
224 do_memcpy_clock(routines[i].fn, len, true);
225 } else {
226 result_bps[0] =
227 do_memcpy_gettimeofday(routines[i].fn,
228 len, false);
229 result_bps[1] =
230 do_memcpy_gettimeofday(routines[i].fn,
231 len, true);
232 }
154 } else { 233 } else {
155 BUG_ON(gettimeofday(&tv_end, NULL)); 234 if (use_clock) {
156 timersub(&tv_end, &tv_start, &tv_diff); 235 result_clock[pf] =
157 bps = (double)((double)length / timeval2double(&tv_diff)); 236 do_memcpy_clock(routines[i].fn,
237 len, only_prefault);
238 } else {
239 result_bps[pf] =
240 do_memcpy_gettimeofday(routines[i].fn,
241 len, only_prefault);
242 }
158 } 243 }
159 244
160 switch (bench_format) { 245 switch (bench_format) {
161 case BENCH_FORMAT_DEFAULT: 246 case BENCH_FORMAT_DEFAULT:
162 if (use_clock) { 247 if (!only_prefault && !no_prefault) {
163 printf(" %14lf Clock/Byte\n", 248 if (use_clock) {
164 (double)clock_diff / (double)length); 249 printf(" %14lf Clock/Byte\n",
165 } else { 250 (double)result_clock[0]
166 if (bps < K) 251 / (double)len);
167 printf(" %14lf B/Sec\n", bps); 252 printf(" %14lf Clock/Byte (with prefault)\n",
168 else if (bps < K * K) 253 (double)result_clock[1]
169 printf(" %14lfd KB/Sec\n", bps / 1024); 254 / (double)len);
170 else if (bps < K * K * K) 255 } else {
171 printf(" %14lf MB/Sec\n", bps / 1024 / 1024); 256 print_bps(result_bps[0]);
172 else { 257 printf("\n");
173 printf(" %14lf GB/Sec\n", 258 print_bps(result_bps[1]);
174 bps / 1024 / 1024 / 1024); 259 printf(" (with prefault)\n");
175 } 260 }
261 } else {
262 if (use_clock) {
263 printf(" %14lf Clock/Byte",
264 (double)result_clock[pf]
265 / (double)len);
266 } else
267 print_bps(result_bps[pf]);
268
269 printf("%s\n", only_prefault ? " (with prefault)" : "");
176 } 270 }
177 break; 271 break;
178 case BENCH_FORMAT_SIMPLE: 272 case BENCH_FORMAT_SIMPLE:
179 if (use_clock) { 273 if (!only_prefault && !no_prefault) {
180 printf("%14lf\n", 274 if (use_clock) {
181 (double)clock_diff / (double)length); 275 printf("%lf %lf\n",
182 } else 276 (double)result_clock[0] / (double)len,
183 printf("%lf\n", bps); 277 (double)result_clock[1] / (double)len);
278 } else {
279 printf("%lf %lf\n",
280 result_bps[0], result_bps[1]);
281 }
282 } else {
283 if (use_clock) {
284 printf("%lf\n", (double)result_clock[pf]
285 / (double)len);
286 } else
287 printf("%lf\n", result_bps[pf]);
288 }
184 break; 289 break;
185 default: 290 default:
186 /* reaching this means there's some disaster: */ 291 /* reaching this means there's some disaster: */
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 6d5604d8df95..8879463807e4 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -58,12 +58,12 @@ static int hists__add_entry(struct hists *self, struct addr_location *al)
58 return hist_entry__inc_addr_samples(he, al->addr); 58 return hist_entry__inc_addr_samples(he, al->addr);
59} 59}
60 60
61static int process_sample_event(event_t *event, struct perf_session *session) 61static int process_sample_event(event_t *event, struct sample_data *sample,
62 struct perf_session *session)
62{ 63{
63 struct addr_location al; 64 struct addr_location al;
64 struct sample_data data;
65 65
66 if (event__preprocess_sample(event, session, &al, &data, NULL) < 0) { 66 if (event__preprocess_sample(event, session, &al, sample, NULL) < 0) {
67 pr_warning("problem processing %d event, skipping it.\n", 67 pr_warning("problem processing %d event, skipping it.\n",
68 event->header.type); 68 event->header.type);
69 return -1; 69 return -1;
@@ -212,7 +212,7 @@ get_source_line(struct hist_entry *he, int len, const char *filename)
212 continue; 212 continue;
213 213
214 offset = start + i; 214 offset = start + i;
215 sprintf(cmd, "addr2line -e %s %016llx", filename, offset); 215 sprintf(cmd, "addr2line -e %s %016" PRIx64, filename, offset);
216 fp = popen(cmd, "r"); 216 fp = popen(cmd, "r");
217 if (!fp) 217 if (!fp)
218 continue; 218 continue;
@@ -270,9 +270,9 @@ static void hist_entry__print_hits(struct hist_entry *self)
270 270
271 for (offset = 0; offset < len; ++offset) 271 for (offset = 0; offset < len; ++offset)
272 if (h->ip[offset] != 0) 272 if (h->ip[offset] != 0)
273 printf("%*Lx: %Lu\n", BITS_PER_LONG / 2, 273 printf("%*" PRIx64 ": %" PRIu64 "\n", BITS_PER_LONG / 2,
274 sym->start + offset, h->ip[offset]); 274 sym->start + offset, h->ip[offset]);
275 printf("%*s: %Lu\n", BITS_PER_LONG / 2, "h->sum", h->sum); 275 printf("%*s: %" PRIu64 "\n", BITS_PER_LONG / 2, "h->sum", h->sum);
276} 276}
277 277
278static int hist_entry__tty_annotate(struct hist_entry *he) 278static int hist_entry__tty_annotate(struct hist_entry *he)
@@ -375,6 +375,8 @@ static struct perf_event_ops event_ops = {
375 .mmap = event__process_mmap, 375 .mmap = event__process_mmap,
376 .comm = event__process_comm, 376 .comm = event__process_comm,
377 .fork = event__process_task, 377 .fork = event__process_task,
378 .ordered_samples = true,
379 .ordering_requires_timestamps = true,
378}; 380};
379 381
380static int __cmd_annotate(void) 382static int __cmd_annotate(void)
@@ -382,7 +384,7 @@ static int __cmd_annotate(void)
382 int ret; 384 int ret;
383 struct perf_session *session; 385 struct perf_session *session;
384 386
385 session = perf_session__new(input_name, O_RDONLY, force, false); 387 session = perf_session__new(input_name, O_RDONLY, force, false, &event_ops);
386 if (session == NULL) 388 if (session == NULL)
387 return -ENOMEM; 389 return -ENOMEM;
388 390
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index 44a47e13bd67..5af32ae9031e 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -36,10 +36,10 @@ static const struct option options[] = {
36 36
37static int __cmd_buildid_list(void) 37static int __cmd_buildid_list(void)
38{ 38{
39 int err = -1;
40 struct perf_session *session; 39 struct perf_session *session;
41 40
42 session = perf_session__new(input_name, O_RDONLY, force, false); 41 session = perf_session__new(input_name, O_RDONLY, force, false,
42 &build_id__mark_dso_hit_ops);
43 if (session == NULL) 43 if (session == NULL)
44 return -1; 44 return -1;
45 45
@@ -49,7 +49,7 @@ static int __cmd_buildid_list(void)
49 perf_session__fprintf_dsos_buildid(session, stdout, with_hits); 49 perf_session__fprintf_dsos_buildid(session, stdout, with_hits);
50 50
51 perf_session__delete(session); 51 perf_session__delete(session);
52 return err; 52 return 0;
53} 53}
54 54
55int cmd_buildid_list(int argc, const char **argv, const char *prefix __used) 55int cmd_buildid_list(int argc, const char **argv, const char *prefix __used)
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index fca1d4402910..3153e492dbcc 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -30,12 +30,13 @@ static int hists__add_entry(struct hists *self,
30 return -ENOMEM; 30 return -ENOMEM;
31} 31}
32 32
33static int diff__process_sample_event(event_t *event, struct perf_session *session) 33static int diff__process_sample_event(event_t *event,
34 struct sample_data *sample,
35 struct perf_session *session)
34{ 36{
35 struct addr_location al; 37 struct addr_location al;
36 struct sample_data data = { .period = 1, };
37 38
38 if (event__preprocess_sample(event, session, &al, &data, NULL) < 0) { 39 if (event__preprocess_sample(event, session, &al, sample, NULL) < 0) {
39 pr_warning("problem processing %d event, skipping it.\n", 40 pr_warning("problem processing %d event, skipping it.\n",
40 event->header.type); 41 event->header.type);
41 return -1; 42 return -1;
@@ -44,12 +45,12 @@ static int diff__process_sample_event(event_t *event, struct perf_session *sessi
44 if (al.filtered || al.sym == NULL) 45 if (al.filtered || al.sym == NULL)
45 return 0; 46 return 0;
46 47
47 if (hists__add_entry(&session->hists, &al, data.period)) { 48 if (hists__add_entry(&session->hists, &al, sample->period)) {
48 pr_warning("problem incrementing symbol period, skipping event\n"); 49 pr_warning("problem incrementing symbol period, skipping event\n");
49 return -1; 50 return -1;
50 } 51 }
51 52
52 session->hists.stats.total_period += data.period; 53 session->hists.stats.total_period += sample->period;
53 return 0; 54 return 0;
54} 55}
55 56
@@ -60,6 +61,8 @@ static struct perf_event_ops event_ops = {
60 .exit = event__process_task, 61 .exit = event__process_task,
61 .fork = event__process_task, 62 .fork = event__process_task,
62 .lost = event__process_lost, 63 .lost = event__process_lost,
64 .ordered_samples = true,
65 .ordering_requires_timestamps = true,
63}; 66};
64 67
65static void perf_session__insert_hist_entry_by_name(struct rb_root *root, 68static void perf_session__insert_hist_entry_by_name(struct rb_root *root,
@@ -141,8 +144,8 @@ static int __cmd_diff(void)
141 int ret, i; 144 int ret, i;
142 struct perf_session *session[2]; 145 struct perf_session *session[2];
143 146
144 session[0] = perf_session__new(input_old, O_RDONLY, force, false); 147 session[0] = perf_session__new(input_old, O_RDONLY, force, false, &event_ops);
145 session[1] = perf_session__new(input_new, O_RDONLY, force, false); 148 session[1] = perf_session__new(input_new, O_RDONLY, force, false, &event_ops);
146 if (session[0] == NULL || session[1] == NULL) 149 if (session[0] == NULL || session[1] == NULL)
147 return -ENOMEM; 150 return -ENOMEM;
148 151
@@ -173,7 +176,7 @@ static const char * const diff_usage[] = {
173static const struct option options[] = { 176static const struct option options[] = {
174 OPT_INCR('v', "verbose", &verbose, 177 OPT_INCR('v', "verbose", &verbose,
175 "be more verbose (show symbol address, etc)"), 178 "be more verbose (show symbol address, etc)"),
176 OPT_BOOLEAN('m', "displacement", &show_displacement, 179 OPT_BOOLEAN('M', "displacement", &show_displacement,
177 "Show position displacement relative to baseline"), 180 "Show position displacement relative to baseline"),
178 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 181 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
179 "dump raw trace in ASCII"), 182 "dump raw trace in ASCII"),
@@ -191,6 +194,8 @@ static const struct option options[] = {
191 OPT_STRING('t', "field-separator", &symbol_conf.field_sep, "separator", 194 OPT_STRING('t', "field-separator", &symbol_conf.field_sep, "separator",
192 "separator for columns, no spaces will be added between " 195 "separator for columns, no spaces will be added between "
193 "columns '.' is reserved."), 196 "columns '.' is reserved."),
197 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
198 "Look for files with symbols relative to this directory"),
194 OPT_END() 199 OPT_END()
195}; 200};
196 201
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 8e3e47b064ce..0c78ffa7bf67 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -16,8 +16,8 @@
16static char const *input_name = "-"; 16static char const *input_name = "-";
17static bool inject_build_ids; 17static bool inject_build_ids;
18 18
19static int event__repipe(event_t *event __used, 19static int event__repipe_synth(event_t *event,
20 struct perf_session *session __used) 20 struct perf_session *session __used)
21{ 21{
22 uint32_t size; 22 uint32_t size;
23 void *buf = event; 23 void *buf = event;
@@ -36,22 +36,30 @@ static int event__repipe(event_t *event __used,
36 return 0; 36 return 0;
37} 37}
38 38
39static int event__repipe_mmap(event_t *self, struct perf_session *session) 39static int event__repipe(event_t *event, struct sample_data *sample __used,
40 struct perf_session *session)
41{
42 return event__repipe_synth(event, session);
43}
44
45static int event__repipe_mmap(event_t *self, struct sample_data *sample,
46 struct perf_session *session)
40{ 47{
41 int err; 48 int err;
42 49
43 err = event__process_mmap(self, session); 50 err = event__process_mmap(self, sample, session);
44 event__repipe(self, session); 51 event__repipe(self, sample, session);
45 52
46 return err; 53 return err;
47} 54}
48 55
49static int event__repipe_task(event_t *self, struct perf_session *session) 56static int event__repipe_task(event_t *self, struct sample_data *sample,
57 struct perf_session *session)
50{ 58{
51 int err; 59 int err;
52 60
53 err = event__process_task(self, session); 61 err = event__process_task(self, sample, session);
54 event__repipe(self, session); 62 event__repipe(self, sample, session);
55 63
56 return err; 64 return err;
57} 65}
@@ -61,7 +69,7 @@ static int event__repipe_tracing_data(event_t *self,
61{ 69{
62 int err; 70 int err;
63 71
64 event__repipe(self, session); 72 event__repipe_synth(self, session);
65 err = event__process_tracing_data(self, session); 73 err = event__process_tracing_data(self, session);
66 74
67 return err; 75 return err;
@@ -111,7 +119,8 @@ static int dso__inject_build_id(struct dso *self, struct perf_session *session)
111 return 0; 119 return 0;
112} 120}
113 121
114static int event__inject_buildid(event_t *event, struct perf_session *session) 122static int event__inject_buildid(event_t *event, struct sample_data *sample,
123 struct perf_session *session)
115{ 124{
116 struct addr_location al; 125 struct addr_location al;
117 struct thread *thread; 126 struct thread *thread;
@@ -146,7 +155,7 @@ static int event__inject_buildid(event_t *event, struct perf_session *session)
146 } 155 }
147 156
148repipe: 157repipe:
149 event__repipe(event, session); 158 event__repipe(event, sample, session);
150 return 0; 159 return 0;
151} 160}
152 161
@@ -160,10 +169,10 @@ struct perf_event_ops inject_ops = {
160 .read = event__repipe, 169 .read = event__repipe,
161 .throttle = event__repipe, 170 .throttle = event__repipe,
162 .unthrottle = event__repipe, 171 .unthrottle = event__repipe,
163 .attr = event__repipe, 172 .attr = event__repipe_synth,
164 .event_type = event__repipe, 173 .event_type = event__repipe_synth,
165 .tracing_data = event__repipe, 174 .tracing_data = event__repipe_synth,
166 .build_id = event__repipe, 175 .build_id = event__repipe_synth,
167}; 176};
168 177
169extern volatile int session_done; 178extern volatile int session_done;
@@ -187,7 +196,7 @@ static int __cmd_inject(void)
187 inject_ops.tracing_data = event__repipe_tracing_data; 196 inject_ops.tracing_data = event__repipe_tracing_data;
188 } 197 }
189 198
190 session = perf_session__new(input_name, O_RDONLY, false, true); 199 session = perf_session__new(input_name, O_RDONLY, false, true, &inject_ops);
191 if (session == NULL) 200 if (session == NULL)
192 return -ENOMEM; 201 return -ENOMEM;
193 202
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index 31f60a2535e0..d97256d65980 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -304,22 +304,11 @@ process_raw_event(event_t *raw_event __used, void *data,
304 } 304 }
305} 305}
306 306
307static int process_sample_event(event_t *event, struct perf_session *session) 307static int process_sample_event(event_t *event, struct sample_data *sample,
308 struct perf_session *session)
308{ 309{
309 struct sample_data data; 310 struct thread *thread = perf_session__findnew(session, event->ip.pid);
310 struct thread *thread;
311 311
312 memset(&data, 0, sizeof(data));
313 data.time = -1;
314 data.cpu = -1;
315 data.period = 1;
316
317 event__parse_sample(event, session->sample_type, &data);
318
319 dump_printf("(IP, %d): %d/%d: %#Lx period: %Ld\n", event->header.misc,
320 data.pid, data.tid, data.ip, data.period);
321
322 thread = perf_session__findnew(session, event->ip.pid);
323 if (thread == NULL) { 312 if (thread == NULL) {
324 pr_debug("problem processing %d event, skipping it.\n", 313 pr_debug("problem processing %d event, skipping it.\n",
325 event->header.type); 314 event->header.type);
@@ -328,8 +317,8 @@ static int process_sample_event(event_t *event, struct perf_session *session)
328 317
329 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); 318 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
330 319
331 process_raw_event(event, data.raw_data, data.cpu, 320 process_raw_event(event, sample->raw_data, sample->cpu,
332 data.time, thread); 321 sample->time, thread);
333 322
334 return 0; 323 return 0;
335} 324}
@@ -382,10 +371,10 @@ static void __print_result(struct rb_root *root, struct perf_session *session,
382 addr = data->ptr; 371 addr = data->ptr;
383 372
384 if (sym != NULL) 373 if (sym != NULL)
385 snprintf(buf, sizeof(buf), "%s+%Lx", sym->name, 374 snprintf(buf, sizeof(buf), "%s+%" PRIx64 "", sym->name,
386 addr - map->unmap_ip(map, sym->start)); 375 addr - map->unmap_ip(map, sym->start));
387 else 376 else
388 snprintf(buf, sizeof(buf), "%#Lx", addr); 377 snprintf(buf, sizeof(buf), "%#" PRIx64 "", addr);
389 printf(" %-34s |", buf); 378 printf(" %-34s |", buf);
390 379
391 printf(" %9llu/%-5lu | %9llu/%-5lu | %8lu | %8lu | %6.3f%%\n", 380 printf(" %9llu/%-5lu | %9llu/%-5lu | %8lu | %8lu | %6.3f%%\n",
@@ -492,7 +481,8 @@ static void sort_result(void)
492static int __cmd_kmem(void) 481static int __cmd_kmem(void)
493{ 482{
494 int err = -EINVAL; 483 int err = -EINVAL;
495 struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0, false); 484 struct perf_session *session = perf_session__new(input_name, O_RDONLY,
485 0, false, &event_ops);
496 if (session == NULL) 486 if (session == NULL)
497 return -ENOMEM; 487 return -ENOMEM;
498 488
@@ -747,6 +737,9 @@ static int __cmd_record(int argc, const char **argv)
747 rec_argc = ARRAY_SIZE(record_args) + argc - 1; 737 rec_argc = ARRAY_SIZE(record_args) + argc - 1;
748 rec_argv = calloc(rec_argc + 1, sizeof(char *)); 738 rec_argv = calloc(rec_argc + 1, sizeof(char *));
749 739
740 if (rec_argv == NULL)
741 return -ENOMEM;
742
750 for (i = 0; i < ARRAY_SIZE(record_args); i++) 743 for (i = 0; i < ARRAY_SIZE(record_args); i++)
751 rec_argv[i] = strdup(record_args[i]); 744 rec_argv[i] = strdup(record_args[i]);
752 745
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index 821c1586a22b..2b36defc5d73 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -782,9 +782,9 @@ static void print_result(void)
782 pr_info("%10u ", st->nr_acquired); 782 pr_info("%10u ", st->nr_acquired);
783 pr_info("%10u ", st->nr_contended); 783 pr_info("%10u ", st->nr_contended);
784 784
785 pr_info("%15llu ", st->wait_time_total); 785 pr_info("%15" PRIu64 " ", st->wait_time_total);
786 pr_info("%15llu ", st->wait_time_max); 786 pr_info("%15" PRIu64 " ", st->wait_time_max);
787 pr_info("%15llu ", st->wait_time_min == ULLONG_MAX ? 787 pr_info("%15" PRIu64 " ", st->wait_time_min == ULLONG_MAX ?
788 0 : st->wait_time_min); 788 0 : st->wait_time_min);
789 pr_info("\n"); 789 pr_info("\n");
790 } 790 }
@@ -834,22 +834,18 @@ static void dump_info(void)
834 die("Unknown type of information\n"); 834 die("Unknown type of information\n");
835} 835}
836 836
837static int process_sample_event(event_t *self, struct perf_session *s) 837static int process_sample_event(event_t *self, struct sample_data *sample,
838 struct perf_session *s)
838{ 839{
839 struct sample_data data; 840 struct thread *thread = perf_session__findnew(s, sample->tid);
840 struct thread *thread;
841 841
842 bzero(&data, sizeof(data));
843 event__parse_sample(self, s->sample_type, &data);
844
845 thread = perf_session__findnew(s, data.tid);
846 if (thread == NULL) { 842 if (thread == NULL) {
847 pr_debug("problem processing %d event, skipping it.\n", 843 pr_debug("problem processing %d event, skipping it.\n",
848 self->header.type); 844 self->header.type);
849 return -1; 845 return -1;
850 } 846 }
851 847
852 process_raw_event(data.raw_data, data.cpu, data.time, thread); 848 process_raw_event(sample->raw_data, sample->cpu, sample->time, thread);
853 849
854 return 0; 850 return 0;
855} 851}
@@ -862,7 +858,7 @@ static struct perf_event_ops eops = {
862 858
863static int read_events(void) 859static int read_events(void)
864{ 860{
865 session = perf_session__new(input_name, O_RDONLY, 0, false); 861 session = perf_session__new(input_name, O_RDONLY, 0, false, &eops);
866 if (!session) 862 if (!session)
867 die("Initializing perf session failed\n"); 863 die("Initializing perf session failed\n");
868 864
@@ -947,6 +943,9 @@ static int __cmd_record(int argc, const char **argv)
947 rec_argc = ARRAY_SIZE(record_args) + argc - 1; 943 rec_argc = ARRAY_SIZE(record_args) + argc - 1;
948 rec_argv = calloc(rec_argc + 1, sizeof(char *)); 944 rec_argv = calloc(rec_argc + 1, sizeof(char *));
949 945
946 if (rec_argv == NULL)
947 return -ENOMEM;
948
950 for (i = 0; i < ARRAY_SIZE(record_args); i++) 949 for (i = 0; i < ARRAY_SIZE(record_args); i++)
951 rec_argv[i] = strdup(record_args[i]); 950 rec_argv[i] = strdup(record_args[i]);
952 951
@@ -982,9 +981,9 @@ int cmd_lock(int argc, const char **argv, const char *prefix __used)
982 usage_with_options(report_usage, report_options); 981 usage_with_options(report_usage, report_options);
983 } 982 }
984 __cmd_report(); 983 __cmd_report();
985 } else if (!strcmp(argv[0], "trace")) { 984 } else if (!strcmp(argv[0], "script")) {
986 /* Aliased to 'perf trace' */ 985 /* Aliased to 'perf script' */
987 return cmd_trace(argc, argv, prefix); 986 return cmd_script(argc, argv, prefix);
988 } else if (!strcmp(argv[0], "info")) { 987 } else if (!strcmp(argv[0], "info")) {
989 if (argc) { 988 if (argc) {
990 argc = parse_options(argc, argv, 989 argc = parse_options(argc, argv,
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 2e000c068cc5..add163c9f0e7 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -249,6 +249,11 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
249 !params.show_lines)) 249 !params.show_lines))
250 usage_with_options(probe_usage, options); 250 usage_with_options(probe_usage, options);
251 251
252 /*
253 * Only consider the user's kernel image path if given.
254 */
255 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
256
252 if (params.list_events) { 257 if (params.list_events) {
253 if (params.mod_events) { 258 if (params.mod_events) {
254 pr_err(" Error: Don't use --list with --add/--del.\n"); 259 pr_err(" Error: Don't use --list with --add/--del.\n");
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 4e75583ddd6d..b2f729fdb317 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -18,6 +18,7 @@
18 18
19#include "util/header.h" 19#include "util/header.h"
20#include "util/event.h" 20#include "util/event.h"
21#include "util/evsel.h"
21#include "util/debug.h" 22#include "util/debug.h"
22#include "util/session.h" 23#include "util/session.h"
23#include "util/symbol.h" 24#include "util/symbol.h"
@@ -27,17 +28,18 @@
27#include <sched.h> 28#include <sched.h>
28#include <sys/mman.h> 29#include <sys/mman.h>
29 30
31#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
32
30enum write_mode_t { 33enum write_mode_t {
31 WRITE_FORCE, 34 WRITE_FORCE,
32 WRITE_APPEND 35 WRITE_APPEND
33}; 36};
34 37
35static int *fd[MAX_NR_CPUS][MAX_COUNTERS];
36
37static u64 user_interval = ULLONG_MAX; 38static u64 user_interval = ULLONG_MAX;
38static u64 default_interval = 0; 39static u64 default_interval = 0;
40static u64 sample_type;
39 41
40static int nr_cpus = 0; 42static struct cpu_map *cpus;
41static unsigned int page_size; 43static unsigned int page_size;
42static unsigned int mmap_pages = 128; 44static unsigned int mmap_pages = 128;
43static unsigned int user_freq = UINT_MAX; 45static unsigned int user_freq = UINT_MAX;
@@ -47,12 +49,13 @@ static int pipe_output = 0;
47static const char *output_name = "perf.data"; 49static const char *output_name = "perf.data";
48static int group = 0; 50static int group = 0;
49static int realtime_prio = 0; 51static int realtime_prio = 0;
52static bool nodelay = false;
50static bool raw_samples = false; 53static bool raw_samples = false;
54static bool sample_id_all_avail = true;
51static bool system_wide = false; 55static bool system_wide = false;
52static pid_t target_pid = -1; 56static pid_t target_pid = -1;
53static pid_t target_tid = -1; 57static pid_t target_tid = -1;
54static pid_t *all_tids = NULL; 58static struct thread_map *threads;
55static int thread_num = 0;
56static pid_t child_pid = -1; 59static pid_t child_pid = -1;
57static bool no_inherit = false; 60static bool no_inherit = false;
58static enum write_mode_t write_mode = WRITE_FORCE; 61static enum write_mode_t write_mode = WRITE_FORCE;
@@ -60,7 +63,9 @@ static bool call_graph = false;
60static bool inherit_stat = false; 63static bool inherit_stat = false;
61static bool no_samples = false; 64static bool no_samples = false;
62static bool sample_address = false; 65static bool sample_address = false;
66static bool sample_time = false;
63static bool no_buildid = false; 67static bool no_buildid = false;
68static bool no_buildid_cache = false;
64 69
65static long samples = 0; 70static long samples = 0;
66static u64 bytes_written = 0; 71static u64 bytes_written = 0;
@@ -77,7 +82,6 @@ static struct perf_session *session;
77static const char *cpu_list; 82static const char *cpu_list;
78 83
79struct mmap_data { 84struct mmap_data {
80 int counter;
81 void *base; 85 void *base;
82 unsigned int mask; 86 unsigned int mask;
83 unsigned int prev; 87 unsigned int prev;
@@ -128,6 +132,7 @@ static void write_output(void *buf, size_t size)
128} 132}
129 133
130static int process_synthesized_event(event_t *event, 134static int process_synthesized_event(event_t *event,
135 struct sample_data *sample __used,
131 struct perf_session *self __used) 136 struct perf_session *self __used)
132{ 137{
133 write_output(event, event->header.size); 138 write_output(event, event->header.size);
@@ -197,7 +202,7 @@ static void sig_atexit(void)
197 if (child_pid > 0) 202 if (child_pid > 0)
198 kill(child_pid, SIGTERM); 203 kill(child_pid, SIGTERM);
199 204
200 if (signr == -1) 205 if (signr == -1 || signr == SIGUSR1)
201 return; 206 return;
202 207
203 signal(signr, SIG_DFL); 208 signal(signr, SIG_DFL);
@@ -224,12 +229,12 @@ static struct perf_header_attr *get_header_attr(struct perf_event_attr *a, int n
224 return h_attr; 229 return h_attr;
225} 230}
226 231
227static void create_counter(int counter, int cpu) 232static void create_counter(struct perf_evsel *evsel, int cpu)
228{ 233{
229 char *filter = filters[counter]; 234 char *filter = evsel->filter;
230 struct perf_event_attr *attr = attrs + counter; 235 struct perf_event_attr *attr = &evsel->attr;
231 struct perf_header_attr *h_attr; 236 struct perf_header_attr *h_attr;
232 int track = !counter; /* only the first counter needs these */ 237 int track = !evsel->idx; /* only the first counter needs these */
233 int thread_index; 238 int thread_index;
234 int ret; 239 int ret;
235 struct { 240 struct {
@@ -238,6 +243,19 @@ static void create_counter(int counter, int cpu)
238 u64 time_running; 243 u64 time_running;
239 u64 id; 244 u64 id;
240 } read_data; 245 } read_data;
246 /*
247 * Check if parse_single_tracepoint_event has already asked for
248 * PERF_SAMPLE_TIME.
249 *
250 * XXX this is kludgy but short term fix for problems introduced by
251 * eac23d1c that broke 'perf script' by having different sample_types
252 * when using multiple tracepoint events when we use a perf binary
253 * that tries to use sample_id_all on an older kernel.
254 *
255 * We need to move counter creation to perf_session, support
256 * different sample_types, etc.
257 */
258 bool time_needed = attr->sample_type & PERF_SAMPLE_TIME;
241 259
242 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | 260 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
243 PERF_FORMAT_TOTAL_TIME_RUNNING | 261 PERF_FORMAT_TOTAL_TIME_RUNNING |
@@ -280,12 +298,21 @@ static void create_counter(int counter, int cpu)
280 if (system_wide) 298 if (system_wide)
281 attr->sample_type |= PERF_SAMPLE_CPU; 299 attr->sample_type |= PERF_SAMPLE_CPU;
282 300
301 if (sample_id_all_avail &&
302 (sample_time || system_wide || !no_inherit || cpu_list))
303 attr->sample_type |= PERF_SAMPLE_TIME;
304
283 if (raw_samples) { 305 if (raw_samples) {
284 attr->sample_type |= PERF_SAMPLE_TIME; 306 attr->sample_type |= PERF_SAMPLE_TIME;
285 attr->sample_type |= PERF_SAMPLE_RAW; 307 attr->sample_type |= PERF_SAMPLE_RAW;
286 attr->sample_type |= PERF_SAMPLE_CPU; 308 attr->sample_type |= PERF_SAMPLE_CPU;
287 } 309 }
288 310
311 if (nodelay) {
312 attr->watermark = 0;
313 attr->wakeup_events = 1;
314 }
315
289 attr->mmap = track; 316 attr->mmap = track;
290 attr->comm = track; 317 attr->comm = track;
291 attr->inherit = !no_inherit; 318 attr->inherit = !no_inherit;
@@ -293,13 +320,14 @@ static void create_counter(int counter, int cpu)
293 attr->disabled = 1; 320 attr->disabled = 1;
294 attr->enable_on_exec = 1; 321 attr->enable_on_exec = 1;
295 } 322 }
323retry_sample_id:
324 attr->sample_id_all = sample_id_all_avail ? 1 : 0;
296 325
297 for (thread_index = 0; thread_index < thread_num; thread_index++) { 326 for (thread_index = 0; thread_index < threads->nr; thread_index++) {
298try_again: 327try_again:
299 fd[nr_cpu][counter][thread_index] = sys_perf_event_open(attr, 328 FD(evsel, nr_cpu, thread_index) = sys_perf_event_open(attr, threads->map[thread_index], cpu, group_fd, 0);
300 all_tids[thread_index], cpu, group_fd, 0);
301 329
302 if (fd[nr_cpu][counter][thread_index] < 0) { 330 if (FD(evsel, nr_cpu, thread_index) < 0) {
303 int err = errno; 331 int err = errno;
304 332
305 if (err == EPERM || err == EACCES) 333 if (err == EPERM || err == EACCES)
@@ -309,6 +337,15 @@ try_again:
309 else if (err == ENODEV && cpu_list) { 337 else if (err == ENODEV && cpu_list) {
310 die("No such device - did you specify" 338 die("No such device - did you specify"
311 " an out-of-range profile CPU?\n"); 339 " an out-of-range profile CPU?\n");
340 } else if (err == EINVAL && sample_id_all_avail) {
341 /*
342 * Old kernel, no attr->sample_id_type_all field
343 */
344 sample_id_all_avail = false;
345 if (!sample_time && !raw_samples && !time_needed)
346 attr->sample_type &= ~PERF_SAMPLE_TIME;
347
348 goto retry_sample_id;
312 } 349 }
313 350
314 /* 351 /*
@@ -326,8 +363,8 @@ try_again:
326 goto try_again; 363 goto try_again;
327 } 364 }
328 printf("\n"); 365 printf("\n");
329 error("perfcounter syscall returned with %d (%s)\n", 366 error("sys_perf_event_open() syscall returned with %d (%s). /bin/dmesg may provide additional information.\n",
330 fd[nr_cpu][counter][thread_index], strerror(err)); 367 FD(evsel, nr_cpu, thread_index), strerror(err));
331 368
332#if defined(__i386__) || defined(__x86_64__) 369#if defined(__i386__) || defined(__x86_64__)
333 if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP) 370 if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP)
@@ -341,7 +378,7 @@ try_again:
341 exit(-1); 378 exit(-1);
342 } 379 }
343 380
344 h_attr = get_header_attr(attr, counter); 381 h_attr = get_header_attr(attr, evsel->idx);
345 if (h_attr == NULL) 382 if (h_attr == NULL)
346 die("nomem\n"); 383 die("nomem\n");
347 384
@@ -352,7 +389,7 @@ try_again:
352 } 389 }
353 } 390 }
354 391
355 if (read(fd[nr_cpu][counter][thread_index], &read_data, sizeof(read_data)) == -1) { 392 if (read(FD(evsel, nr_cpu, thread_index), &read_data, sizeof(read_data)) == -1) {
356 perror("Unable to read perf file descriptor"); 393 perror("Unable to read perf file descriptor");
357 exit(-1); 394 exit(-1);
358 } 395 }
@@ -362,43 +399,44 @@ try_again:
362 exit(-1); 399 exit(-1);
363 } 400 }
364 401
365 assert(fd[nr_cpu][counter][thread_index] >= 0); 402 assert(FD(evsel, nr_cpu, thread_index) >= 0);
366 fcntl(fd[nr_cpu][counter][thread_index], F_SETFL, O_NONBLOCK); 403 fcntl(FD(evsel, nr_cpu, thread_index), F_SETFL, O_NONBLOCK);
367 404
368 /* 405 /*
369 * First counter acts as the group leader: 406 * First counter acts as the group leader:
370 */ 407 */
371 if (group && group_fd == -1) 408 if (group && group_fd == -1)
372 group_fd = fd[nr_cpu][counter][thread_index]; 409 group_fd = FD(evsel, nr_cpu, thread_index);
373 410
374 if (counter || thread_index) { 411 if (evsel->idx || thread_index) {
375 ret = ioctl(fd[nr_cpu][counter][thread_index], 412 struct perf_evsel *first;
376 PERF_EVENT_IOC_SET_OUTPUT, 413 first = list_entry(evsel_list.next, struct perf_evsel, node);
377 fd[nr_cpu][0][0]); 414 ret = ioctl(FD(evsel, nr_cpu, thread_index),
415 PERF_EVENT_IOC_SET_OUTPUT,
416 FD(first, nr_cpu, 0));
378 if (ret) { 417 if (ret) {
379 error("failed to set output: %d (%s)\n", errno, 418 error("failed to set output: %d (%s)\n", errno,
380 strerror(errno)); 419 strerror(errno));
381 exit(-1); 420 exit(-1);
382 } 421 }
383 } else { 422 } else {
384 mmap_array[nr_cpu].counter = counter;
385 mmap_array[nr_cpu].prev = 0; 423 mmap_array[nr_cpu].prev = 0;
386 mmap_array[nr_cpu].mask = mmap_pages*page_size - 1; 424 mmap_array[nr_cpu].mask = mmap_pages*page_size - 1;
387 mmap_array[nr_cpu].base = mmap(NULL, (mmap_pages+1)*page_size, 425 mmap_array[nr_cpu].base = mmap(NULL, (mmap_pages+1)*page_size,
388 PROT_READ|PROT_WRITE, MAP_SHARED, fd[nr_cpu][counter][thread_index], 0); 426 PROT_READ | PROT_WRITE, MAP_SHARED, FD(evsel, nr_cpu, thread_index), 0);
389 if (mmap_array[nr_cpu].base == MAP_FAILED) { 427 if (mmap_array[nr_cpu].base == MAP_FAILED) {
390 error("failed to mmap with %d (%s)\n", errno, strerror(errno)); 428 error("failed to mmap with %d (%s)\n", errno, strerror(errno));
391 exit(-1); 429 exit(-1);
392 } 430 }
393 431
394 event_array[nr_poll].fd = fd[nr_cpu][counter][thread_index]; 432 event_array[nr_poll].fd = FD(evsel, nr_cpu, thread_index);
395 event_array[nr_poll].events = POLLIN; 433 event_array[nr_poll].events = POLLIN;
396 nr_poll++; 434 nr_poll++;
397 } 435 }
398 436
399 if (filter != NULL) { 437 if (filter != NULL) {
400 ret = ioctl(fd[nr_cpu][counter][thread_index], 438 ret = ioctl(FD(evsel, nr_cpu, thread_index),
401 PERF_EVENT_IOC_SET_FILTER, filter); 439 PERF_EVENT_IOC_SET_FILTER, filter);
402 if (ret) { 440 if (ret) {
403 error("failed to set filter with %d (%s)\n", errno, 441 error("failed to set filter with %d (%s)\n", errno,
404 strerror(errno)); 442 strerror(errno));
@@ -406,15 +444,19 @@ try_again:
406 } 444 }
407 } 445 }
408 } 446 }
447
448 if (!sample_type)
449 sample_type = attr->sample_type;
409} 450}
410 451
411static void open_counters(int cpu) 452static void open_counters(int cpu)
412{ 453{
413 int counter; 454 struct perf_evsel *pos;
414 455
415 group_fd = -1; 456 group_fd = -1;
416 for (counter = 0; counter < nr_counters; counter++) 457
417 create_counter(counter, cpu); 458 list_for_each_entry(pos, &evsel_list, node)
459 create_counter(pos, cpu);
418 460
419 nr_cpu++; 461 nr_cpu++;
420} 462}
@@ -437,9 +479,11 @@ static void atexit_header(void)
437 if (!pipe_output) { 479 if (!pipe_output) {
438 session->header.data_size += bytes_written; 480 session->header.data_size += bytes_written;
439 481
440 process_buildids(); 482 if (!no_buildid)
483 process_buildids();
441 perf_header__write(&session->header, output, true); 484 perf_header__write(&session->header, output, true);
442 perf_session__delete(session); 485 perf_session__delete(session);
486 perf_evsel_list__delete();
443 symbol__exit(); 487 symbol__exit();
444 } 488 }
445} 489}
@@ -500,7 +544,7 @@ static void mmap_read_all(void)
500 544
501static int __cmd_record(int argc, const char **argv) 545static int __cmd_record(int argc, const char **argv)
502{ 546{
503 int i, counter; 547 int i;
504 struct stat st; 548 struct stat st;
505 int flags; 549 int flags;
506 int err; 550 int err;
@@ -515,6 +559,7 @@ static int __cmd_record(int argc, const char **argv)
515 atexit(sig_atexit); 559 atexit(sig_atexit);
516 signal(SIGCHLD, sig_handler); 560 signal(SIGCHLD, sig_handler);
517 signal(SIGINT, sig_handler); 561 signal(SIGINT, sig_handler);
562 signal(SIGUSR1, sig_handler);
518 563
519 if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) { 564 if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) {
520 perror("failed to create pipes"); 565 perror("failed to create pipes");
@@ -551,19 +596,22 @@ static int __cmd_record(int argc, const char **argv)
551 } 596 }
552 597
553 session = perf_session__new(output_name, O_WRONLY, 598 session = perf_session__new(output_name, O_WRONLY,
554 write_mode == WRITE_FORCE, false); 599 write_mode == WRITE_FORCE, false, NULL);
555 if (session == NULL) { 600 if (session == NULL) {
556 pr_err("Not enough memory for reading perf file header\n"); 601 pr_err("Not enough memory for reading perf file header\n");
557 return -1; 602 return -1;
558 } 603 }
559 604
605 if (!no_buildid)
606 perf_header__set_feat(&session->header, HEADER_BUILD_ID);
607
560 if (!file_new) { 608 if (!file_new) {
561 err = perf_header__read(session, output); 609 err = perf_header__read(session, output);
562 if (err < 0) 610 if (err < 0)
563 goto out_delete_session; 611 goto out_delete_session;
564 } 612 }
565 613
566 if (have_tracepoints(attrs, nr_counters)) 614 if (have_tracepoints(&evsel_list))
567 perf_header__set_feat(&session->header, HEADER_TRACE_INFO); 615 perf_header__set_feat(&session->header, HEADER_TRACE_INFO);
568 616
569 /* 617 /*
@@ -606,11 +654,12 @@ static int __cmd_record(int argc, const char **argv)
606 execvp(argv[0], (char **)argv); 654 execvp(argv[0], (char **)argv);
607 655
608 perror(argv[0]); 656 perror(argv[0]);
657 kill(getppid(), SIGUSR1);
609 exit(-1); 658 exit(-1);
610 } 659 }
611 660
612 if (!system_wide && target_tid == -1 && target_pid == -1) 661 if (!system_wide && target_tid == -1 && target_pid == -1)
613 all_tids[0] = child_pid; 662 threads->map[0] = child_pid;
614 663
615 close(child_ready_pipe[1]); 664 close(child_ready_pipe[1]);
616 close(go_pipe[0]); 665 close(go_pipe[0]);
@@ -624,19 +673,15 @@ static int __cmd_record(int argc, const char **argv)
624 close(child_ready_pipe[0]); 673 close(child_ready_pipe[0]);
625 } 674 }
626 675
627 nr_cpus = read_cpu_map(cpu_list);
628 if (nr_cpus < 1) {
629 perror("failed to collect number of CPUs");
630 return -1;
631 }
632
633 if (!system_wide && no_inherit && !cpu_list) { 676 if (!system_wide && no_inherit && !cpu_list) {
634 open_counters(-1); 677 open_counters(-1);
635 } else { 678 } else {
636 for (i = 0; i < nr_cpus; i++) 679 for (i = 0; i < cpus->nr; i++)
637 open_counters(cpumap[i]); 680 open_counters(cpus->map[i]);
638 } 681 }
639 682
683 perf_session__set_sample_type(session, sample_type);
684
640 if (pipe_output) { 685 if (pipe_output) {
641 err = perf_header__write_pipe(output); 686 err = perf_header__write_pipe(output);
642 if (err < 0) 687 if (err < 0)
@@ -649,6 +694,8 @@ static int __cmd_record(int argc, const char **argv)
649 694
650 post_processing_offset = lseek(output, 0, SEEK_CUR); 695 post_processing_offset = lseek(output, 0, SEEK_CUR);
651 696
697 perf_session__set_sample_id_all(session, sample_id_all_avail);
698
652 if (pipe_output) { 699 if (pipe_output) {
653 err = event__synthesize_attrs(&session->header, 700 err = event__synthesize_attrs(&session->header,
654 process_synthesized_event, 701 process_synthesized_event,
@@ -665,7 +712,7 @@ static int __cmd_record(int argc, const char **argv)
665 return err; 712 return err;
666 } 713 }
667 714
668 if (have_tracepoints(attrs, nr_counters)) { 715 if (have_tracepoints(&evsel_list)) {
669 /* 716 /*
670 * FIXME err <= 0 here actually means that 717 * FIXME err <= 0 here actually means that
671 * there were no tracepoints so its not really 718 * there were no tracepoints so its not really
@@ -674,8 +721,7 @@ static int __cmd_record(int argc, const char **argv)
674 * return this more properly and also 721 * return this more properly and also
675 * propagate errors that now are calling die() 722 * propagate errors that now are calling die()
676 */ 723 */
677 err = event__synthesize_tracing_data(output, attrs, 724 err = event__synthesize_tracing_data(output, &evsel_list,
678 nr_counters,
679 process_synthesized_event, 725 process_synthesized_event,
680 session); 726 session);
681 if (err <= 0) { 727 if (err <= 0) {
@@ -697,17 +743,18 @@ static int __cmd_record(int argc, const char **argv)
697 if (err < 0) 743 if (err < 0)
698 err = event__synthesize_kernel_mmap(process_synthesized_event, 744 err = event__synthesize_kernel_mmap(process_synthesized_event,
699 session, machine, "_stext"); 745 session, machine, "_stext");
700 if (err < 0) { 746 if (err < 0)
701 pr_err("Couldn't record kernel reference relocation symbol.\n"); 747 pr_err("Couldn't record kernel reference relocation symbol\n"
702 return err; 748 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
703 } 749 "Check /proc/kallsyms permission or run as root.\n");
704 750
705 err = event__synthesize_modules(process_synthesized_event, 751 err = event__synthesize_modules(process_synthesized_event,
706 session, machine); 752 session, machine);
707 if (err < 0) { 753 if (err < 0)
708 pr_err("Couldn't record kernel reference relocation symbol.\n"); 754 pr_err("Couldn't record kernel module information.\n"
709 return err; 755 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
710 } 756 "Check /proc/modules permission or run as root.\n");
757
711 if (perf_guest) 758 if (perf_guest)
712 perf_session__process_machines(session, event__synthesize_guest_os); 759 perf_session__process_machines(session, event__synthesize_guest_os);
713 760
@@ -748,20 +795,20 @@ static int __cmd_record(int argc, const char **argv)
748 795
749 if (done) { 796 if (done) {
750 for (i = 0; i < nr_cpu; i++) { 797 for (i = 0; i < nr_cpu; i++) {
751 for (counter = 0; 798 struct perf_evsel *pos;
752 counter < nr_counters; 799
753 counter++) { 800 list_for_each_entry(pos, &evsel_list, node) {
754 for (thread = 0; 801 for (thread = 0;
755 thread < thread_num; 802 thread < threads->nr;
756 thread++) 803 thread++)
757 ioctl(fd[i][counter][thread], 804 ioctl(FD(pos, i, thread),
758 PERF_EVENT_IOC_DISABLE); 805 PERF_EVENT_IOC_DISABLE);
759 } 806 }
760 } 807 }
761 } 808 }
762 } 809 }
763 810
764 if (quiet) 811 if (quiet || signr == SIGUSR1)
765 return 0; 812 return 0;
766 813
767 fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 814 fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
@@ -770,7 +817,7 @@ static int __cmd_record(int argc, const char **argv)
770 * Approximate RIP event size: 24 bytes. 817 * Approximate RIP event size: 24 bytes.
771 */ 818 */
772 fprintf(stderr, 819 fprintf(stderr,
773 "[ perf record: Captured and wrote %.3f MB %s (~%lld samples) ]\n", 820 "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n",
774 (double)bytes_written / 1024.0 / 1024.0, 821 (double)bytes_written / 1024.0 / 1024.0,
775 output_name, 822 output_name,
776 bytes_written / 24); 823 bytes_written / 24);
@@ -790,7 +837,7 @@ static const char * const record_usage[] = {
790 837
791static bool force, append_file; 838static bool force, append_file;
792 839
793static const struct option options[] = { 840const struct option record_options[] = {
794 OPT_CALLBACK('e', "event", NULL, "event", 841 OPT_CALLBACK('e', "event", NULL, "event",
795 "event selector. use 'perf list' to list available events", 842 "event selector. use 'perf list' to list available events",
796 parse_events), 843 parse_events),
@@ -802,6 +849,8 @@ static const struct option options[] = {
802 "record events on existing thread id"), 849 "record events on existing thread id"),
803 OPT_INTEGER('r', "realtime", &realtime_prio, 850 OPT_INTEGER('r', "realtime", &realtime_prio,
804 "collect data with this RT SCHED_FIFO priority"), 851 "collect data with this RT SCHED_FIFO priority"),
852 OPT_BOOLEAN('D', "no-delay", &nodelay,
853 "collect data without buffering"),
805 OPT_BOOLEAN('R', "raw-samples", &raw_samples, 854 OPT_BOOLEAN('R', "raw-samples", &raw_samples,
806 "collect raw sample records from all opened counters"), 855 "collect raw sample records from all opened counters"),
807 OPT_BOOLEAN('a', "all-cpus", &system_wide, 856 OPT_BOOLEAN('a', "all-cpus", &system_wide,
@@ -828,27 +877,31 @@ static const struct option options[] = {
828 "per thread counts"), 877 "per thread counts"),
829 OPT_BOOLEAN('d', "data", &sample_address, 878 OPT_BOOLEAN('d', "data", &sample_address,
830 "Sample addresses"), 879 "Sample addresses"),
880 OPT_BOOLEAN('T', "timestamp", &sample_time, "Sample timestamps"),
831 OPT_BOOLEAN('n', "no-samples", &no_samples, 881 OPT_BOOLEAN('n', "no-samples", &no_samples,
832 "don't sample"), 882 "don't sample"),
833 OPT_BOOLEAN('N', "no-buildid-cache", &no_buildid, 883 OPT_BOOLEAN('N', "no-buildid-cache", &no_buildid_cache,
834 "do not update the buildid cache"), 884 "do not update the buildid cache"),
885 OPT_BOOLEAN('B', "no-buildid", &no_buildid,
886 "do not collect buildids in perf.data"),
835 OPT_END() 887 OPT_END()
836}; 888};
837 889
838int cmd_record(int argc, const char **argv, const char *prefix __used) 890int cmd_record(int argc, const char **argv, const char *prefix __used)
839{ 891{
840 int i, j, err = -ENOMEM; 892 int err = -ENOMEM;
893 struct perf_evsel *pos;
841 894
842 argc = parse_options(argc, argv, options, record_usage, 895 argc = parse_options(argc, argv, record_options, record_usage,
843 PARSE_OPT_STOP_AT_NON_OPTION); 896 PARSE_OPT_STOP_AT_NON_OPTION);
844 if (!argc && target_pid == -1 && target_tid == -1 && 897 if (!argc && target_pid == -1 && target_tid == -1 &&
845 !system_wide && !cpu_list) 898 !system_wide && !cpu_list)
846 usage_with_options(record_usage, options); 899 usage_with_options(record_usage, record_options);
847 900
848 if (force && append_file) { 901 if (force && append_file) {
849 fprintf(stderr, "Can't overwrite and append at the same time." 902 fprintf(stderr, "Can't overwrite and append at the same time."
850 " You need to choose between -f and -A"); 903 " You need to choose between -f and -A");
851 usage_with_options(record_usage, options); 904 usage_with_options(record_usage, record_options);
852 } else if (append_file) { 905 } else if (append_file) {
853 write_mode = WRITE_APPEND; 906 write_mode = WRITE_APPEND;
854 } else { 907 } else {
@@ -856,41 +909,38 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
856 } 909 }
857 910
858 symbol__init(); 911 symbol__init();
859 if (no_buildid) 912
913 if (no_buildid_cache || no_buildid)
860 disable_buildid_cache(); 914 disable_buildid_cache();
861 915
862 if (!nr_counters) { 916 if (list_empty(&evsel_list) && perf_evsel_list__create_default() < 0) {
863 nr_counters = 1; 917 pr_err("Not enough memory for event selector list\n");
864 attrs[0].type = PERF_TYPE_HARDWARE; 918 goto out_symbol_exit;
865 attrs[0].config = PERF_COUNT_HW_CPU_CYCLES;
866 } 919 }
867 920
868 if (target_pid != -1) { 921 if (target_pid != -1)
869 target_tid = target_pid; 922 target_tid = target_pid;
870 thread_num = find_all_tid(target_pid, &all_tids);
871 if (thread_num <= 0) {
872 fprintf(stderr, "Can't find all threads of pid %d\n",
873 target_pid);
874 usage_with_options(record_usage, options);
875 }
876 } else {
877 all_tids=malloc(sizeof(pid_t));
878 if (!all_tids)
879 goto out_symbol_exit;
880 923
881 all_tids[0] = target_tid; 924 threads = thread_map__new(target_pid, target_tid);
882 thread_num = 1; 925 if (threads == NULL) {
926 pr_err("Problems finding threads of monitor\n");
927 usage_with_options(record_usage, record_options);
883 } 928 }
884 929
885 for (i = 0; i < MAX_NR_CPUS; i++) { 930 cpus = cpu_map__new(cpu_list);
886 for (j = 0; j < MAX_COUNTERS; j++) { 931 if (cpus == NULL) {
887 fd[i][j] = malloc(sizeof(int)*thread_num); 932 perror("failed to parse CPUs map");
888 if (!fd[i][j]) 933 return -1;
889 goto out_free_fd;
890 }
891 } 934 }
892 event_array = malloc( 935
893 sizeof(struct pollfd)*MAX_NR_CPUS*MAX_COUNTERS*thread_num); 936 list_for_each_entry(pos, &evsel_list, node) {
937 if (perf_evsel__alloc_fd(pos, cpus->nr, threads->nr) < 0)
938 goto out_free_fd;
939 if (perf_header__push_event(pos->attr.config, event_name(pos)))
940 goto out_free_fd;
941 }
942 event_array = malloc((sizeof(struct pollfd) * MAX_NR_CPUS *
943 MAX_COUNTERS * threads->nr));
894 if (!event_array) 944 if (!event_array)
895 goto out_free_fd; 945 goto out_free_fd;
896 946
@@ -917,12 +967,8 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
917out_free_event_array: 967out_free_event_array:
918 free(event_array); 968 free(event_array);
919out_free_fd: 969out_free_fd:
920 for (i = 0; i < MAX_NR_CPUS; i++) { 970 thread_map__delete(threads);
921 for (j = 0; j < MAX_COUNTERS; j++) 971 threads = NULL;
922 free(fd[i][j]);
923 }
924 free(all_tids);
925 all_tids = NULL;
926out_symbol_exit: 972out_symbol_exit:
927 symbol__exit(); 973 symbol__exit();
928 return err; 974 return err;
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 5de405d45230..c27e31f289e6 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -150,13 +150,13 @@ static int add_event_total(struct perf_session *session,
150 return 0; 150 return 0;
151} 151}
152 152
153static int process_sample_event(event_t *event, struct perf_session *session) 153static int process_sample_event(event_t *event, struct sample_data *sample,
154 struct perf_session *session)
154{ 155{
155 struct sample_data data = { .period = 1, };
156 struct addr_location al; 156 struct addr_location al;
157 struct perf_event_attr *attr; 157 struct perf_event_attr *attr;
158 158
159 if (event__preprocess_sample(event, session, &al, &data, NULL) < 0) { 159 if (event__preprocess_sample(event, session, &al, sample, NULL) < 0) {
160 fprintf(stderr, "problem processing %d event, skipping it.\n", 160 fprintf(stderr, "problem processing %d event, skipping it.\n",
161 event->header.type); 161 event->header.type);
162 return -1; 162 return -1;
@@ -165,14 +165,14 @@ static int process_sample_event(event_t *event, struct perf_session *session)
165 if (al.filtered || (hide_unresolved && al.sym == NULL)) 165 if (al.filtered || (hide_unresolved && al.sym == NULL))
166 return 0; 166 return 0;
167 167
168 if (perf_session__add_hist_entry(session, &al, &data)) { 168 if (perf_session__add_hist_entry(session, &al, sample)) {
169 pr_debug("problem incrementing symbol period, skipping event\n"); 169 pr_debug("problem incrementing symbol period, skipping event\n");
170 return -1; 170 return -1;
171 } 171 }
172 172
173 attr = perf_header__find_attr(data.id, &session->header); 173 attr = perf_header__find_attr(sample->id, &session->header);
174 174
175 if (add_event_total(session, &data, attr)) { 175 if (add_event_total(session, sample, attr)) {
176 pr_debug("problem adding event period\n"); 176 pr_debug("problem adding event period\n");
177 return -1; 177 return -1;
178 } 178 }
@@ -180,7 +180,8 @@ static int process_sample_event(event_t *event, struct perf_session *session)
180 return 0; 180 return 0;
181} 181}
182 182
183static int process_read_event(event_t *event, struct perf_session *session __used) 183static int process_read_event(event_t *event, struct sample_data *sample __used,
184 struct perf_session *session __used)
184{ 185{
185 struct perf_event_attr *attr; 186 struct perf_event_attr *attr;
186 187
@@ -196,7 +197,7 @@ static int process_read_event(event_t *event, struct perf_session *session __use
196 event->read.value); 197 event->read.value);
197 } 198 }
198 199
199 dump_printf(": %d %d %s %Lu\n", event->read.pid, event->read.tid, 200 dump_printf(": %d %d %s %" PRIu64 "\n", event->read.pid, event->read.tid,
200 attr ? __event_name(attr->type, attr->config) : "FAIL", 201 attr ? __event_name(attr->type, attr->config) : "FAIL",
201 event->read.value); 202 event->read.value);
202 203
@@ -243,6 +244,8 @@ static struct perf_event_ops event_ops = {
243 .event_type = event__process_event_type, 244 .event_type = event__process_event_type,
244 .tracing_data = event__process_tracing_data, 245 .tracing_data = event__process_tracing_data,
245 .build_id = event__process_build_id, 246 .build_id = event__process_build_id,
247 .ordered_samples = true,
248 .ordering_requires_timestamps = true,
246}; 249};
247 250
248extern volatile int session_done; 251extern volatile int session_done;
@@ -307,7 +310,7 @@ static int __cmd_report(void)
307 310
308 signal(SIGINT, sig_handler); 311 signal(SIGINT, sig_handler);
309 312
310 session = perf_session__new(input_name, O_RDONLY, force, false); 313 session = perf_session__new(input_name, O_RDONLY, force, false, &event_ops);
311 if (session == NULL) 314 if (session == NULL)
312 return -ENOMEM; 315 return -ENOMEM;
313 316
@@ -442,6 +445,8 @@ static const struct option options[] = {
442 "dump raw trace in ASCII"), 445 "dump raw trace in ASCII"),
443 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, 446 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
444 "file", "vmlinux pathname"), 447 "file", "vmlinux pathname"),
448 OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name,
449 "file", "kallsyms pathname"),
445 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"), 450 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
446 OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules, 451 OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
447 "load module symbols - WARNING: use only with -k and LIVE kernel"), 452 "load module symbols - WARNING: use only with -k and LIVE kernel"),
@@ -478,6 +483,8 @@ static const struct option options[] = {
478 "columns '.' is reserved."), 483 "columns '.' is reserved."),
479 OPT_BOOLEAN('U', "hide-unresolved", &hide_unresolved, 484 OPT_BOOLEAN('U', "hide-unresolved", &hide_unresolved,
480 "Only display entries resolved to a symbol"), 485 "Only display entries resolved to a symbol"),
486 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
487 "Look for files with symbols relative to this directory"),
481 OPT_END() 488 OPT_END()
482}; 489};
483 490
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 55f3b5dcc731..29acb894e035 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -193,7 +193,7 @@ static void calibrate_run_measurement_overhead(void)
193 } 193 }
194 run_measurement_overhead = min_delta; 194 run_measurement_overhead = min_delta;
195 195
196 printf("run measurement overhead: %Ld nsecs\n", min_delta); 196 printf("run measurement overhead: %" PRIu64 " nsecs\n", min_delta);
197} 197}
198 198
199static void calibrate_sleep_measurement_overhead(void) 199static void calibrate_sleep_measurement_overhead(void)
@@ -211,7 +211,7 @@ static void calibrate_sleep_measurement_overhead(void)
211 min_delta -= 10000; 211 min_delta -= 10000;
212 sleep_measurement_overhead = min_delta; 212 sleep_measurement_overhead = min_delta;
213 213
214 printf("sleep measurement overhead: %Ld nsecs\n", min_delta); 214 printf("sleep measurement overhead: %" PRIu64 " nsecs\n", min_delta);
215} 215}
216 216
217static struct sched_atom * 217static struct sched_atom *
@@ -489,7 +489,8 @@ static void create_tasks(void)
489 489
490 err = pthread_attr_init(&attr); 490 err = pthread_attr_init(&attr);
491 BUG_ON(err); 491 BUG_ON(err);
492 err = pthread_attr_setstacksize(&attr, (size_t)(16*1024)); 492 err = pthread_attr_setstacksize(&attr,
493 (size_t) max(16 * 1024, PTHREAD_STACK_MIN));
493 BUG_ON(err); 494 BUG_ON(err);
494 err = pthread_mutex_lock(&start_work_mutex); 495 err = pthread_mutex_lock(&start_work_mutex);
495 BUG_ON(err); 496 BUG_ON(err);
@@ -616,13 +617,13 @@ static void test_calibrations(void)
616 burn_nsecs(1e6); 617 burn_nsecs(1e6);
617 T1 = get_nsecs(); 618 T1 = get_nsecs();
618 619
619 printf("the run test took %Ld nsecs\n", T1-T0); 620 printf("the run test took %" PRIu64 " nsecs\n", T1 - T0);
620 621
621 T0 = get_nsecs(); 622 T0 = get_nsecs();
622 sleep_nsecs(1e6); 623 sleep_nsecs(1e6);
623 T1 = get_nsecs(); 624 T1 = get_nsecs();
624 625
625 printf("the sleep test took %Ld nsecs\n", T1-T0); 626 printf("the sleep test took %" PRIu64 " nsecs\n", T1 - T0);
626} 627}
627 628
628#define FILL_FIELD(ptr, field, event, data) \ 629#define FILL_FIELD(ptr, field, event, data) \
@@ -815,10 +816,10 @@ replay_switch_event(struct trace_switch_event *switch_event,
815 delta = 0; 816 delta = 0;
816 817
817 if (delta < 0) 818 if (delta < 0)
818 die("hm, delta: %Ld < 0 ?\n", delta); 819 die("hm, delta: %" PRIu64 " < 0 ?\n", delta);
819 820
820 if (verbose) { 821 if (verbose) {
821 printf(" ... switch from %s/%d to %s/%d [ran %Ld nsecs]\n", 822 printf(" ... switch from %s/%d to %s/%d [ran %" PRIu64 " nsecs]\n",
822 switch_event->prev_comm, switch_event->prev_pid, 823 switch_event->prev_comm, switch_event->prev_pid,
823 switch_event->next_comm, switch_event->next_pid, 824 switch_event->next_comm, switch_event->next_pid,
824 delta); 825 delta);
@@ -1047,7 +1048,7 @@ latency_switch_event(struct trace_switch_event *switch_event,
1047 delta = 0; 1048 delta = 0;
1048 1049
1049 if (delta < 0) 1050 if (delta < 0)
1050 die("hm, delta: %Ld < 0 ?\n", delta); 1051 die("hm, delta: %" PRIu64 " < 0 ?\n", delta);
1051 1052
1052 1053
1053 sched_out = perf_session__findnew(session, switch_event->prev_pid); 1054 sched_out = perf_session__findnew(session, switch_event->prev_pid);
@@ -1220,7 +1221,7 @@ static void output_lat_thread(struct work_atoms *work_list)
1220 1221
1221 avg = work_list->total_lat / work_list->nb_atoms; 1222 avg = work_list->total_lat / work_list->nb_atoms;
1222 1223
1223 printf("|%11.3f ms |%9llu | avg:%9.3f ms | max:%9.3f ms | max at: %9.6f s\n", 1224 printf("|%11.3f ms |%9" PRIu64 " | avg:%9.3f ms | max:%9.3f ms | max at: %9.6f s\n",
1224 (double)work_list->total_runtime / 1e6, 1225 (double)work_list->total_runtime / 1e6,
1225 work_list->nb_atoms, (double)avg / 1e6, 1226 work_list->nb_atoms, (double)avg / 1e6,
1226 (double)work_list->max_lat / 1e6, 1227 (double)work_list->max_lat / 1e6,
@@ -1422,7 +1423,7 @@ map_switch_event(struct trace_switch_event *switch_event,
1422 delta = 0; 1423 delta = 0;
1423 1424
1424 if (delta < 0) 1425 if (delta < 0)
1425 die("hm, delta: %Ld < 0 ?\n", delta); 1426 die("hm, delta: %" PRIu64 " < 0 ?\n", delta);
1426 1427
1427 1428
1428 sched_out = perf_session__findnew(session, switch_event->prev_pid); 1429 sched_out = perf_session__findnew(session, switch_event->prev_pid);
@@ -1606,25 +1607,15 @@ process_raw_event(event_t *raw_event __used, struct perf_session *session,
1606 process_sched_migrate_task_event(data, session, event, cpu, timestamp, thread); 1607 process_sched_migrate_task_event(data, session, event, cpu, timestamp, thread);
1607} 1608}
1608 1609
1609static int process_sample_event(event_t *event, struct perf_session *session) 1610static int process_sample_event(event_t *event, struct sample_data *sample,
1611 struct perf_session *session)
1610{ 1612{
1611 struct sample_data data;
1612 struct thread *thread; 1613 struct thread *thread;
1613 1614
1614 if (!(session->sample_type & PERF_SAMPLE_RAW)) 1615 if (!(session->sample_type & PERF_SAMPLE_RAW))
1615 return 0; 1616 return 0;
1616 1617
1617 memset(&data, 0, sizeof(data)); 1618 thread = perf_session__findnew(session, sample->pid);
1618 data.time = -1;
1619 data.cpu = -1;
1620 data.period = -1;
1621
1622 event__parse_sample(event, session->sample_type, &data);
1623
1624 dump_printf("(IP, %d): %d/%d: %#Lx period: %Ld\n", event->header.misc,
1625 data.pid, data.tid, data.ip, data.period);
1626
1627 thread = perf_session__findnew(session, data.pid);
1628 if (thread == NULL) { 1619 if (thread == NULL) {
1629 pr_debug("problem processing %d event, skipping it.\n", 1620 pr_debug("problem processing %d event, skipping it.\n",
1630 event->header.type); 1621 event->header.type);
@@ -1633,10 +1624,11 @@ static int process_sample_event(event_t *event, struct perf_session *session)
1633 1624
1634 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); 1625 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
1635 1626
1636 if (profile_cpu != -1 && profile_cpu != (int)data.cpu) 1627 if (profile_cpu != -1 && profile_cpu != (int)sample->cpu)
1637 return 0; 1628 return 0;
1638 1629
1639 process_raw_event(event, session, data.raw_data, data.cpu, data.time, thread); 1630 process_raw_event(event, session, sample->raw_data, sample->cpu,
1631 sample->time, thread);
1640 1632
1641 return 0; 1633 return 0;
1642} 1634}
@@ -1652,7 +1644,8 @@ static struct perf_event_ops event_ops = {
1652static int read_events(void) 1644static int read_events(void)
1653{ 1645{
1654 int err = -EINVAL; 1646 int err = -EINVAL;
1655 struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0, false); 1647 struct perf_session *session = perf_session__new(input_name, O_RDONLY,
1648 0, false, &event_ops);
1656 if (session == NULL) 1649 if (session == NULL)
1657 return -ENOMEM; 1650 return -ENOMEM;
1658 1651
@@ -1720,7 +1713,7 @@ static void __cmd_lat(void)
1720 } 1713 }
1721 1714
1722 printf(" -----------------------------------------------------------------------------------------\n"); 1715 printf(" -----------------------------------------------------------------------------------------\n");
1723 printf(" TOTAL: |%11.3f ms |%9Ld |\n", 1716 printf(" TOTAL: |%11.3f ms |%9" PRIu64 " |\n",
1724 (double)all_runtime/1e6, all_count); 1717 (double)all_runtime/1e6, all_count);
1725 1718
1726 printf(" ---------------------------------------------------\n"); 1719 printf(" ---------------------------------------------------\n");
@@ -1850,15 +1843,15 @@ static const char *record_args[] = {
1850 "-f", 1843 "-f",
1851 "-m", "1024", 1844 "-m", "1024",
1852 "-c", "1", 1845 "-c", "1",
1853 "-e", "sched:sched_switch:r", 1846 "-e", "sched:sched_switch",
1854 "-e", "sched:sched_stat_wait:r", 1847 "-e", "sched:sched_stat_wait",
1855 "-e", "sched:sched_stat_sleep:r", 1848 "-e", "sched:sched_stat_sleep",
1856 "-e", "sched:sched_stat_iowait:r", 1849 "-e", "sched:sched_stat_iowait",
1857 "-e", "sched:sched_stat_runtime:r", 1850 "-e", "sched:sched_stat_runtime",
1858 "-e", "sched:sched_process_exit:r", 1851 "-e", "sched:sched_process_exit",
1859 "-e", "sched:sched_process_fork:r", 1852 "-e", "sched:sched_process_fork",
1860 "-e", "sched:sched_wakeup:r", 1853 "-e", "sched:sched_wakeup",
1861 "-e", "sched:sched_migrate_task:r", 1854 "-e", "sched:sched_migrate_task",
1862}; 1855};
1863 1856
1864static int __cmd_record(int argc, const char **argv) 1857static int __cmd_record(int argc, const char **argv)
@@ -1869,6 +1862,9 @@ static int __cmd_record(int argc, const char **argv)
1869 rec_argc = ARRAY_SIZE(record_args) + argc - 1; 1862 rec_argc = ARRAY_SIZE(record_args) + argc - 1;
1870 rec_argv = calloc(rec_argc + 1, sizeof(char *)); 1863 rec_argv = calloc(rec_argc + 1, sizeof(char *));
1871 1864
1865 if (rec_argv == NULL)
1866 return -ENOMEM;
1867
1872 for (i = 0; i < ARRAY_SIZE(record_args); i++) 1868 for (i = 0; i < ARRAY_SIZE(record_args); i++)
1873 rec_argv[i] = strdup(record_args[i]); 1869 rec_argv[i] = strdup(record_args[i]);
1874 1870
@@ -1888,10 +1884,10 @@ int cmd_sched(int argc, const char **argv, const char *prefix __used)
1888 usage_with_options(sched_usage, sched_options); 1884 usage_with_options(sched_usage, sched_options);
1889 1885
1890 /* 1886 /*
1891 * Aliased to 'perf trace' for now: 1887 * Aliased to 'perf script' for now:
1892 */ 1888 */
1893 if (!strcmp(argv[0], "trace")) 1889 if (!strcmp(argv[0], "script"))
1894 return cmd_trace(argc, argv, prefix); 1890 return cmd_script(argc, argv, prefix);
1895 1891
1896 symbol__init(); 1892 symbol__init();
1897 if (!strncmp(argv[0], "rec", 3)) { 1893 if (!strncmp(argv[0], "rec", 3)) {
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-script.c
index 2f8df45c4dcb..b766c2a9ac97 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-script.c
@@ -10,6 +10,7 @@
10#include "util/symbol.h" 10#include "util/symbol.h"
11#include "util/thread.h" 11#include "util/thread.h"
12#include "util/trace-event.h" 12#include "util/trace-event.h"
13#include "util/parse-options.h"
13#include "util/util.h" 14#include "util/util.h"
14 15
15static char const *script_name; 16static char const *script_name;
@@ -17,6 +18,7 @@ static char const *generate_script_lang;
17static bool debug_mode; 18static bool debug_mode;
18static u64 last_timestamp; 19static u64 last_timestamp;
19static u64 nr_unordered; 20static u64 nr_unordered;
21extern const struct option record_options[];
20 22
21static int default_start_script(const char *script __unused, 23static int default_start_script(const char *script __unused,
22 int argc __unused, 24 int argc __unused,
@@ -54,29 +56,18 @@ static void setup_scripting(void)
54 56
55static int cleanup_scripting(void) 57static int cleanup_scripting(void)
56{ 58{
57 pr_debug("\nperf trace script stopped\n"); 59 pr_debug("\nperf script stopped\n");
58 60
59 return scripting_ops->stop_script(); 61 return scripting_ops->stop_script();
60} 62}
61 63
62static char const *input_name = "perf.data"; 64static char const *input_name = "perf.data";
63 65
64static int process_sample_event(event_t *event, struct perf_session *session) 66static int process_sample_event(event_t *event, struct sample_data *sample,
67 struct perf_session *session)
65{ 68{
66 struct sample_data data; 69 struct thread *thread = perf_session__findnew(session, event->ip.pid);
67 struct thread *thread;
68
69 memset(&data, 0, sizeof(data));
70 data.time = -1;
71 data.cpu = -1;
72 data.period = 1;
73
74 event__parse_sample(event, session->sample_type, &data);
75
76 dump_printf("(IP, %d): %d/%d: %#Lx period: %Ld\n", event->header.misc,
77 data.pid, data.tid, data.ip, data.period);
78 70
79 thread = perf_session__findnew(session, event->ip.pid);
80 if (thread == NULL) { 71 if (thread == NULL) {
81 pr_debug("problem processing %d event, skipping it.\n", 72 pr_debug("problem processing %d event, skipping it.\n",
82 event->header.type); 73 event->header.type);
@@ -85,13 +76,13 @@ static int process_sample_event(event_t *event, struct perf_session *session)
85 76
86 if (session->sample_type & PERF_SAMPLE_RAW) { 77 if (session->sample_type & PERF_SAMPLE_RAW) {
87 if (debug_mode) { 78 if (debug_mode) {
88 if (data.time < last_timestamp) { 79 if (sample->time < last_timestamp) {
89 pr_err("Samples misordered, previous: %llu " 80 pr_err("Samples misordered, previous: %" PRIu64
90 "this: %llu\n", last_timestamp, 81 " this: %" PRIu64 "\n", last_timestamp,
91 data.time); 82 sample->time);
92 nr_unordered++; 83 nr_unordered++;
93 } 84 }
94 last_timestamp = data.time; 85 last_timestamp = sample->time;
95 return 0; 86 return 0;
96 } 87 }
97 /* 88 /*
@@ -99,21 +90,12 @@ static int process_sample_event(event_t *event, struct perf_session *session)
99 * field, although it should be the same than this perf 90 * field, although it should be the same than this perf
100 * event pid 91 * event pid
101 */ 92 */
102 scripting_ops->process_event(data.cpu, data.raw_data, 93 scripting_ops->process_event(sample->cpu, sample->raw_data,
103 data.raw_size, 94 sample->raw_size,
104 data.time, thread->comm); 95 sample->time, thread->comm);
105 } 96 }
106 97
107 session->hists.stats.total_period += data.period; 98 session->hists.stats.total_period += sample->period;
108 return 0;
109}
110
111static u64 nr_lost;
112
113static int process_lost_event(event_t *event, struct perf_session *session __used)
114{
115 nr_lost += event->lost.lost;
116
117 return 0; 99 return 0;
118} 100}
119 101
@@ -124,7 +106,7 @@ static struct perf_event_ops event_ops = {
124 .event_type = event__process_event_type, 106 .event_type = event__process_event_type,
125 .tracing_data = event__process_tracing_data, 107 .tracing_data = event__process_tracing_data,
126 .build_id = event__process_build_id, 108 .build_id = event__process_build_id,
127 .lost = process_lost_event, 109 .ordering_requires_timestamps = true,
128 .ordered_samples = true, 110 .ordered_samples = true,
129}; 111};
130 112
@@ -135,7 +117,7 @@ static void sig_handler(int sig __unused)
135 session_done = 1; 117 session_done = 1;
136} 118}
137 119
138static int __cmd_trace(struct perf_session *session) 120static int __cmd_script(struct perf_session *session)
139{ 121{
140 int ret; 122 int ret;
141 123
@@ -143,10 +125,8 @@ static int __cmd_trace(struct perf_session *session)
143 125
144 ret = perf_session__process_events(session, &event_ops); 126 ret = perf_session__process_events(session, &event_ops);
145 127
146 if (debug_mode) { 128 if (debug_mode)
147 pr_err("Misordered timestamps: %llu\n", nr_unordered); 129 pr_err("Misordered timestamps: %" PRIu64 "\n", nr_unordered);
148 pr_err("Lost events: %llu\n", nr_lost);
149 }
150 130
151 return ret; 131 return ret;
152} 132}
@@ -157,7 +137,7 @@ struct script_spec {
157 char spec[0]; 137 char spec[0];
158}; 138};
159 139
160LIST_HEAD(script_specs); 140static LIST_HEAD(script_specs);
161 141
162static struct script_spec *script_spec__new(const char *spec, 142static struct script_spec *script_spec__new(const char *spec,
163 struct scripting_ops *ops) 143 struct scripting_ops *ops)
@@ -245,7 +225,7 @@ static void list_available_languages(void)
245 225
246 fprintf(stderr, "\n"); 226 fprintf(stderr, "\n");
247 fprintf(stderr, "Scripting language extensions (used in " 227 fprintf(stderr, "Scripting language extensions (used in "
248 "perf trace -s [spec:]script.[spec]):\n\n"); 228 "perf script -s [spec:]script.[spec]):\n\n");
249 229
250 list_for_each_entry(s, &script_specs, node) 230 list_for_each_entry(s, &script_specs, node)
251 fprintf(stderr, " %-42s [%s]\n", s->spec, s->ops->name); 231 fprintf(stderr, " %-42s [%s]\n", s->spec, s->ops->name);
@@ -299,17 +279,34 @@ static int parse_scriptname(const struct option *opt __used,
299 return 0; 279 return 0;
300} 280}
301 281
302#define for_each_lang(scripts_dir, lang_dirent, lang_next) \ 282/* Helper function for filesystems that return a dent->d_type DT_UNKNOWN */
283static int is_directory(const char *base_path, const struct dirent *dent)
284{
285 char path[PATH_MAX];
286 struct stat st;
287
288 sprintf(path, "%s/%s", base_path, dent->d_name);
289 if (stat(path, &st))
290 return 0;
291
292 return S_ISDIR(st.st_mode);
293}
294
295#define for_each_lang(scripts_path, scripts_dir, lang_dirent, lang_next)\
303 while (!readdir_r(scripts_dir, &lang_dirent, &lang_next) && \ 296 while (!readdir_r(scripts_dir, &lang_dirent, &lang_next) && \
304 lang_next) \ 297 lang_next) \
305 if (lang_dirent.d_type == DT_DIR && \ 298 if ((lang_dirent.d_type == DT_DIR || \
299 (lang_dirent.d_type == DT_UNKNOWN && \
300 is_directory(scripts_path, &lang_dirent))) && \
306 (strcmp(lang_dirent.d_name, ".")) && \ 301 (strcmp(lang_dirent.d_name, ".")) && \
307 (strcmp(lang_dirent.d_name, ".."))) 302 (strcmp(lang_dirent.d_name, "..")))
308 303
309#define for_each_script(lang_dir, script_dirent, script_next) \ 304#define for_each_script(lang_path, lang_dir, script_dirent, script_next)\
310 while (!readdir_r(lang_dir, &script_dirent, &script_next) && \ 305 while (!readdir_r(lang_dir, &script_dirent, &script_next) && \
311 script_next) \ 306 script_next) \
312 if (script_dirent.d_type != DT_DIR) 307 if (script_dirent.d_type != DT_DIR && \
308 (script_dirent.d_type != DT_UNKNOWN || \
309 !is_directory(lang_path, &script_dirent)))
313 310
314 311
315#define RECORD_SUFFIX "-record" 312#define RECORD_SUFFIX "-record"
@@ -322,13 +319,13 @@ struct script_desc {
322 char *args; 319 char *args;
323}; 320};
324 321
325LIST_HEAD(script_descs); 322static LIST_HEAD(script_descs);
326 323
327static struct script_desc *script_desc__new(const char *name) 324static struct script_desc *script_desc__new(const char *name)
328{ 325{
329 struct script_desc *s = zalloc(sizeof(*s)); 326 struct script_desc *s = zalloc(sizeof(*s));
330 327
331 if (s != NULL) 328 if (s != NULL && name)
332 s->name = strdup(name); 329 s->name = strdup(name);
333 330
334 return s; 331 return s;
@@ -337,6 +334,8 @@ static struct script_desc *script_desc__new(const char *name)
337static void script_desc__delete(struct script_desc *s) 334static void script_desc__delete(struct script_desc *s)
338{ 335{
339 free(s->name); 336 free(s->name);
337 free(s->half_liner);
338 free(s->args);
340 free(s); 339 free(s);
341} 340}
342 341
@@ -376,10 +375,10 @@ out_delete_desc:
376 return NULL; 375 return NULL;
377} 376}
378 377
379static char *ends_with(char *str, const char *suffix) 378static const char *ends_with(const char *str, const char *suffix)
380{ 379{
381 size_t suffix_len = strlen(suffix); 380 size_t suffix_len = strlen(suffix);
382 char *p = str; 381 const char *p = str;
383 382
384 if (strlen(str) > suffix_len) { 383 if (strlen(str) > suffix_len) {
385 p = str + strlen(str) - suffix_len; 384 p = str + strlen(str) - suffix_len;
@@ -462,16 +461,16 @@ static int list_available_scripts(const struct option *opt __used,
462 if (!scripts_dir) 461 if (!scripts_dir)
463 return -1; 462 return -1;
464 463
465 for_each_lang(scripts_dir, lang_dirent, lang_next) { 464 for_each_lang(scripts_path, scripts_dir, lang_dirent, lang_next) {
466 snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path, 465 snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path,
467 lang_dirent.d_name); 466 lang_dirent.d_name);
468 lang_dir = opendir(lang_path); 467 lang_dir = opendir(lang_path);
469 if (!lang_dir) 468 if (!lang_dir)
470 continue; 469 continue;
471 470
472 for_each_script(lang_dir, script_dirent, script_next) { 471 for_each_script(lang_path, lang_dir, script_dirent, script_next) {
473 script_root = strdup(script_dirent.d_name); 472 script_root = strdup(script_dirent.d_name);
474 str = ends_with(script_root, REPORT_SUFFIX); 473 str = (char *)ends_with(script_root, REPORT_SUFFIX);
475 if (str) { 474 if (str) {
476 *str = '\0'; 475 *str = '\0';
477 desc = script_desc__findnew(script_root); 476 desc = script_desc__findnew(script_root);
@@ -510,16 +509,16 @@ static char *get_script_path(const char *script_root, const char *suffix)
510 if (!scripts_dir) 509 if (!scripts_dir)
511 return NULL; 510 return NULL;
512 511
513 for_each_lang(scripts_dir, lang_dirent, lang_next) { 512 for_each_lang(scripts_path, scripts_dir, lang_dirent, lang_next) {
514 snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path, 513 snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path,
515 lang_dirent.d_name); 514 lang_dirent.d_name);
516 lang_dir = opendir(lang_path); 515 lang_dir = opendir(lang_path);
517 if (!lang_dir) 516 if (!lang_dir)
518 continue; 517 continue;
519 518
520 for_each_script(lang_dir, script_dirent, script_next) { 519 for_each_script(lang_path, lang_dir, script_dirent, script_next) {
521 __script_root = strdup(script_dirent.d_name); 520 __script_root = strdup(script_dirent.d_name);
522 str = ends_with(__script_root, suffix); 521 str = (char *)ends_with(__script_root, suffix);
523 if (str) { 522 if (str) {
524 *str = '\0'; 523 *str = '\0';
525 if (strcmp(__script_root, script_root)) 524 if (strcmp(__script_root, script_root))
@@ -537,8 +536,40 @@ static char *get_script_path(const char *script_root, const char *suffix)
537 return path; 536 return path;
538} 537}
539 538
540static const char * const trace_usage[] = { 539static bool is_top_script(const char *script_path)
541 "perf trace [<options>] <command>", 540{
541 return ends_with(script_path, "top") == NULL ? false : true;
542}
543
544static int has_required_arg(char *script_path)
545{
546 struct script_desc *desc;
547 int n_args = 0;
548 char *p;
549
550 desc = script_desc__new(NULL);
551
552 if (read_script_info(desc, script_path))
553 goto out;
554
555 if (!desc->args)
556 goto out;
557
558 for (p = desc->args; *p; p++)
559 if (*p == '<')
560 n_args++;
561out:
562 script_desc__delete(desc);
563
564 return n_args;
565}
566
567static const char * const script_usage[] = {
568 "perf script [<options>]",
569 "perf script [<options>] record <script> [<record-options>] <command>",
570 "perf script [<options>] report <script> [script-args]",
571 "perf script [<options>] <script> [<record-options>] <command>",
572 "perf script [<options>] <top-script> [script-args]",
542 NULL 573 NULL
543}; 574};
544 575
@@ -555,7 +586,7 @@ static const struct option options[] = {
555 "script file name (lang:script name, script name, or *)", 586 "script file name (lang:script name, script name, or *)",
556 parse_scriptname), 587 parse_scriptname),
557 OPT_STRING('g', "gen-script", &generate_script_lang, "lang", 588 OPT_STRING('g', "gen-script", &generate_script_lang, "lang",
558 "generate perf-trace.xx script in specified language"), 589 "generate perf-script.xx script in specified language"),
559 OPT_STRING('i', "input", &input_name, "file", 590 OPT_STRING('i', "input", &input_name, "file",
560 "input file name"), 591 "input file name"),
561 OPT_BOOLEAN('d', "debug-mode", &debug_mode, 592 OPT_BOOLEAN('d', "debug-mode", &debug_mode,
@@ -564,50 +595,81 @@ static const struct option options[] = {
564 OPT_END() 595 OPT_END()
565}; 596};
566 597
567int cmd_trace(int argc, const char **argv, const char *prefix __used) 598static bool have_cmd(int argc, const char **argv)
599{
600 char **__argv = malloc(sizeof(const char *) * argc);
601
602 if (!__argv)
603 die("malloc");
604 memcpy(__argv, argv, sizeof(const char *) * argc);
605 argc = parse_options(argc, (const char **)__argv, record_options,
606 NULL, PARSE_OPT_STOP_AT_NON_OPTION);
607 free(__argv);
608
609 return argc != 0;
610}
611
612int cmd_script(int argc, const char **argv, const char *prefix __used)
568{ 613{
614 char *rec_script_path = NULL;
615 char *rep_script_path = NULL;
569 struct perf_session *session; 616 struct perf_session *session;
570 const char *suffix = NULL; 617 char *script_path = NULL;
571 const char **__argv; 618 const char **__argv;
572 char *script_path; 619 bool system_wide;
573 int i, err; 620 int i, j, err;
574 621
575 if (argc >= 2 && strncmp(argv[1], "rec", strlen("rec")) == 0) { 622 setup_scripting();
576 if (argc < 3) { 623
577 fprintf(stderr, 624 argc = parse_options(argc, argv, options, script_usage,
578 "Please specify a record script\n"); 625 PARSE_OPT_STOP_AT_NON_OPTION);
579 return -1; 626
580 } 627 if (argc > 1 && !strncmp(argv[0], "rec", strlen("rec"))) {
581 suffix = RECORD_SUFFIX; 628 rec_script_path = get_script_path(argv[1], RECORD_SUFFIX);
629 if (!rec_script_path)
630 return cmd_record(argc, argv, NULL);
582 } 631 }
583 632
584 if (argc >= 2 && strncmp(argv[1], "rep", strlen("rep")) == 0) { 633 if (argc > 1 && !strncmp(argv[0], "rep", strlen("rep"))) {
585 if (argc < 3) { 634 rep_script_path = get_script_path(argv[1], REPORT_SUFFIX);
635 if (!rep_script_path) {
586 fprintf(stderr, 636 fprintf(stderr,
587 "Please specify a report script\n"); 637 "Please specify a valid report script"
638 "(see 'perf script -l' for listing)\n");
588 return -1; 639 return -1;
589 } 640 }
590 suffix = REPORT_SUFFIX;
591 } 641 }
592 642
593 /* make sure PERF_EXEC_PATH is set for scripts */ 643 /* make sure PERF_EXEC_PATH is set for scripts */
594 perf_set_argv_exec_path(perf_exec_path()); 644 perf_set_argv_exec_path(perf_exec_path());
595 645
596 if (!suffix && argc >= 2 && strncmp(argv[1], "-", strlen("-")) != 0) { 646 if (argc && !script_name && !rec_script_path && !rep_script_path) {
597 char *record_script_path, *report_script_path;
598 int live_pipe[2]; 647 int live_pipe[2];
648 int rep_args;
599 pid_t pid; 649 pid_t pid;
600 650
601 record_script_path = get_script_path(argv[1], RECORD_SUFFIX); 651 rec_script_path = get_script_path(argv[0], RECORD_SUFFIX);
602 if (!record_script_path) { 652 rep_script_path = get_script_path(argv[0], REPORT_SUFFIX);
603 fprintf(stderr, "record script not found\n"); 653
604 return -1; 654 if (!rec_script_path && !rep_script_path) {
655 fprintf(stderr, " Couldn't find script %s\n\n See perf"
656 " script -l for available scripts.\n", argv[0]);
657 usage_with_options(script_usage, options);
605 } 658 }
606 659
607 report_script_path = get_script_path(argv[1], REPORT_SUFFIX); 660 if (is_top_script(argv[0])) {
608 if (!report_script_path) { 661 rep_args = argc - 1;
609 fprintf(stderr, "report script not found\n"); 662 } else {
610 return -1; 663 int rec_args;
664
665 rep_args = has_required_arg(rep_script_path);
666 rec_args = (argc - 1) - rep_args;
667 if (rec_args < 0) {
668 fprintf(stderr, " %s script requires options."
669 "\n\n See perf script -l for available "
670 "scripts and options.\n", argv[0]);
671 usage_with_options(script_usage, options);
672 }
611 } 673 }
612 674
613 if (pipe(live_pipe) < 0) { 675 if (pipe(live_pipe) < 0) {
@@ -622,66 +684,90 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used)
622 } 684 }
623 685
624 if (!pid) { 686 if (!pid) {
687 system_wide = true;
688 j = 0;
689
625 dup2(live_pipe[1], 1); 690 dup2(live_pipe[1], 1);
626 close(live_pipe[0]); 691 close(live_pipe[0]);
627 692
628 __argv = malloc(6 * sizeof(const char *)); 693 if (!is_top_script(argv[0]))
629 __argv[0] = "/bin/sh"; 694 system_wide = !have_cmd(argc - rep_args,
630 __argv[1] = record_script_path; 695 &argv[rep_args]);
631 __argv[2] = "-q"; 696
632 __argv[3] = "-o"; 697 __argv = malloc((argc + 6) * sizeof(const char *));
633 __argv[4] = "-"; 698 if (!__argv)
634 __argv[5] = NULL; 699 die("malloc");
700
701 __argv[j++] = "/bin/sh";
702 __argv[j++] = rec_script_path;
703 if (system_wide)
704 __argv[j++] = "-a";
705 __argv[j++] = "-q";
706 __argv[j++] = "-o";
707 __argv[j++] = "-";
708 for (i = rep_args + 1; i < argc; i++)
709 __argv[j++] = argv[i];
710 __argv[j++] = NULL;
635 711
636 execvp("/bin/sh", (char **)__argv); 712 execvp("/bin/sh", (char **)__argv);
713 free(__argv);
637 exit(-1); 714 exit(-1);
638 } 715 }
639 716
640 dup2(live_pipe[0], 0); 717 dup2(live_pipe[0], 0);
641 close(live_pipe[1]); 718 close(live_pipe[1]);
642 719
643 __argv = malloc((argc + 3) * sizeof(const char *)); 720 __argv = malloc((argc + 4) * sizeof(const char *));
644 __argv[0] = "/bin/sh"; 721 if (!__argv)
645 __argv[1] = report_script_path; 722 die("malloc");
646 for (i = 2; i < argc; i++) 723 j = 0;
647 __argv[i] = argv[i]; 724 __argv[j++] = "/bin/sh";
648 __argv[i++] = "-i"; 725 __argv[j++] = rep_script_path;
649 __argv[i++] = "-"; 726 for (i = 1; i < rep_args + 1; i++)
650 __argv[i++] = NULL; 727 __argv[j++] = argv[i];
728 __argv[j++] = "-i";
729 __argv[j++] = "-";
730 __argv[j++] = NULL;
651 731
652 execvp("/bin/sh", (char **)__argv); 732 execvp("/bin/sh", (char **)__argv);
733 free(__argv);
653 exit(-1); 734 exit(-1);
654 } 735 }
655 736
656 if (suffix) { 737 if (rec_script_path)
657 script_path = get_script_path(argv[2], suffix); 738 script_path = rec_script_path;
658 if (!script_path) { 739 if (rep_script_path)
659 fprintf(stderr, "script not found\n"); 740 script_path = rep_script_path;
660 return -1; 741
661 } 742 if (script_path) {
662 743 system_wide = false;
663 __argv = malloc((argc + 1) * sizeof(const char *)); 744 j = 0;
664 __argv[0] = "/bin/sh"; 745
665 __argv[1] = script_path; 746 if (rec_script_path)
666 for (i = 3; i < argc; i++) 747 system_wide = !have_cmd(argc - 1, &argv[1]);
667 __argv[i - 1] = argv[i]; 748
668 __argv[argc - 1] = NULL; 749 __argv = malloc((argc + 2) * sizeof(const char *));
750 if (!__argv)
751 die("malloc");
752 __argv[j++] = "/bin/sh";
753 __argv[j++] = script_path;
754 if (system_wide)
755 __argv[j++] = "-a";
756 for (i = 2; i < argc; i++)
757 __argv[j++] = argv[i];
758 __argv[j++] = NULL;
669 759
670 execvp("/bin/sh", (char **)__argv); 760 execvp("/bin/sh", (char **)__argv);
761 free(__argv);
671 exit(-1); 762 exit(-1);
672 } 763 }
673 764
674 setup_scripting();
675
676 argc = parse_options(argc, argv, options, trace_usage,
677 PARSE_OPT_STOP_AT_NON_OPTION);
678
679 if (symbol__init() < 0) 765 if (symbol__init() < 0)
680 return -1; 766 return -1;
681 if (!script_name) 767 if (!script_name)
682 setup_pager(); 768 setup_pager();
683 769
684 session = perf_session__new(input_name, O_RDONLY, 0, false); 770 session = perf_session__new(input_name, O_RDONLY, 0, false, &event_ops);
685 if (session == NULL) 771 if (session == NULL)
686 return -ENOMEM; 772 return -ENOMEM;
687 773
@@ -715,7 +801,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used)
715 return -1; 801 return -1;
716 } 802 }
717 803
718 err = scripting_ops->generate_script("perf-trace"); 804 err = scripting_ops->generate_script("perf-script");
719 goto out; 805 goto out;
720 } 806 }
721 807
@@ -723,10 +809,10 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used)
723 err = scripting_ops->start_script(script_name, argc, argv); 809 err = scripting_ops->start_script(script_name, argc, argv);
724 if (err) 810 if (err)
725 goto out; 811 goto out;
726 pr_debug("perf trace started with script %s\n\n", script_name); 812 pr_debug("perf script started with script %s\n\n", script_name);
727 } 813 }
728 814
729 err = __cmd_trace(session); 815 err = __cmd_script(session);
730 816
731 perf_session__delete(session); 817 perf_session__delete(session);
732 cleanup_scripting(); 818 cleanup_scripting();
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index a6b4d44f9502..a482a191a0ca 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -43,6 +43,7 @@
43#include "util/parse-options.h" 43#include "util/parse-options.h"
44#include "util/parse-events.h" 44#include "util/parse-events.h"
45#include "util/event.h" 45#include "util/event.h"
46#include "util/evsel.h"
46#include "util/debug.h" 47#include "util/debug.h"
47#include "util/header.h" 48#include "util/header.h"
48#include "util/cpumap.h" 49#include "util/cpumap.h"
@@ -52,6 +53,8 @@
52#include <math.h> 53#include <math.h>
53#include <locale.h> 54#include <locale.h>
54 55
56#define DEFAULT_SEPARATOR " "
57
55static struct perf_event_attr default_attrs[] = { 58static struct perf_event_attr default_attrs[] = {
56 59
57 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK }, 60 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK },
@@ -69,25 +72,23 @@ static struct perf_event_attr default_attrs[] = {
69}; 72};
70 73
71static bool system_wide = false; 74static bool system_wide = false;
72static int nr_cpus = 0; 75static struct cpu_map *cpus;
73static int run_idx = 0; 76static int run_idx = 0;
74 77
75static int run_count = 1; 78static int run_count = 1;
76static bool no_inherit = false; 79static bool no_inherit = false;
77static bool scale = true; 80static bool scale = true;
81static bool no_aggr = false;
78static pid_t target_pid = -1; 82static pid_t target_pid = -1;
79static pid_t target_tid = -1; 83static pid_t target_tid = -1;
80static pid_t *all_tids = NULL; 84static struct thread_map *threads;
81static int thread_num = 0;
82static pid_t child_pid = -1; 85static pid_t child_pid = -1;
83static bool null_run = false; 86static bool null_run = false;
84static bool big_num = false; 87static bool big_num = true;
88static int big_num_opt = -1;
85static const char *cpu_list; 89static const char *cpu_list;
86 90static const char *csv_sep = NULL;
87 91static bool csv_output = false;
88static int *fd[MAX_NR_CPUS][MAX_COUNTERS];
89
90static int event_scaled[MAX_COUNTERS];
91 92
92static volatile int done = 0; 93static volatile int done = 0;
93 94
@@ -96,6 +97,22 @@ struct stats
96 double n, mean, M2; 97 double n, mean, M2;
97}; 98};
98 99
100struct perf_stat {
101 struct stats res_stats[3];
102};
103
104static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel)
105{
106 evsel->priv = zalloc(sizeof(struct perf_stat));
107 return evsel->priv == NULL ? -ENOMEM : 0;
108}
109
110static void perf_evsel__free_stat_priv(struct perf_evsel *evsel)
111{
112 free(evsel->priv);
113 evsel->priv = NULL;
114}
115
99static void update_stats(struct stats *stats, u64 val) 116static void update_stats(struct stats *stats, u64 val)
100{ 117{
101 double delta; 118 double delta;
@@ -135,69 +152,38 @@ static double stddev_stats(struct stats *stats)
135 return sqrt(variance_mean); 152 return sqrt(variance_mean);
136} 153}
137 154
138struct stats event_res_stats[MAX_COUNTERS][3]; 155struct stats runtime_nsecs_stats[MAX_NR_CPUS];
139struct stats runtime_nsecs_stats; 156struct stats runtime_cycles_stats[MAX_NR_CPUS];
157struct stats runtime_branches_stats[MAX_NR_CPUS];
140struct stats walltime_nsecs_stats; 158struct stats walltime_nsecs_stats;
141struct stats runtime_cycles_stats;
142struct stats runtime_branches_stats;
143 159
144#define MATCH_EVENT(t, c, counter) \ 160static int create_perf_stat_counter(struct perf_evsel *evsel)
145 (attrs[counter].type == PERF_TYPE_##t && \
146 attrs[counter].config == PERF_COUNT_##c)
147
148#define ERR_PERF_OPEN \
149"Error: counter %d, sys_perf_event_open() syscall returned with %d (%s)\n"
150
151static int create_perf_stat_counter(int counter)
152{ 161{
153 struct perf_event_attr *attr = attrs + counter; 162 struct perf_event_attr *attr = &evsel->attr;
154 int thread;
155 int ncreated = 0;
156 163
157 if (scale) 164 if (scale)
158 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | 165 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
159 PERF_FORMAT_TOTAL_TIME_RUNNING; 166 PERF_FORMAT_TOTAL_TIME_RUNNING;
160 167
161 if (system_wide) { 168 if (system_wide)
162 int cpu; 169 return perf_evsel__open_per_cpu(evsel, cpus);
163 170
164 for (cpu = 0; cpu < nr_cpus; cpu++) { 171 attr->inherit = !no_inherit;
165 fd[cpu][counter][0] = sys_perf_event_open(attr, 172 if (target_pid == -1 && target_tid == -1) {
166 -1, cpumap[cpu], -1, 0); 173 attr->disabled = 1;
167 if (fd[cpu][counter][0] < 0) 174 attr->enable_on_exec = 1;
168 pr_debug(ERR_PERF_OPEN, counter,
169 fd[cpu][counter][0], strerror(errno));
170 else
171 ++ncreated;
172 }
173 } else {
174 attr->inherit = !no_inherit;
175 if (target_pid == -1 && target_tid == -1) {
176 attr->disabled = 1;
177 attr->enable_on_exec = 1;
178 }
179 for (thread = 0; thread < thread_num; thread++) {
180 fd[0][counter][thread] = sys_perf_event_open(attr,
181 all_tids[thread], -1, -1, 0);
182 if (fd[0][counter][thread] < 0)
183 pr_debug(ERR_PERF_OPEN, counter,
184 fd[0][counter][thread],
185 strerror(errno));
186 else
187 ++ncreated;
188 }
189 } 175 }
190 176
191 return ncreated; 177 return perf_evsel__open_per_thread(evsel, threads);
192} 178}
193 179
194/* 180/*
195 * Does the counter have nsecs as a unit? 181 * Does the counter have nsecs as a unit?
196 */ 182 */
197static inline int nsec_counter(int counter) 183static inline int nsec_counter(struct perf_evsel *evsel)
198{ 184{
199 if (MATCH_EVENT(SOFTWARE, SW_CPU_CLOCK, counter) || 185 if (perf_evsel__match(evsel, SOFTWARE, SW_CPU_CLOCK) ||
200 MATCH_EVENT(SOFTWARE, SW_TASK_CLOCK, counter)) 186 perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK))
201 return 1; 187 return 1;
202 188
203 return 0; 189 return 0;
@@ -205,84 +191,73 @@ static inline int nsec_counter(int counter)
205 191
206/* 192/*
207 * Read out the results of a single counter: 193 * Read out the results of a single counter:
194 * aggregate counts across CPUs in system-wide mode
208 */ 195 */
209static void read_counter(int counter) 196static int read_counter_aggr(struct perf_evsel *counter)
210{ 197{
211 u64 count[3], single_count[3]; 198 struct perf_stat *ps = counter->priv;
212 int cpu; 199 u64 *count = counter->counts->aggr.values;
213 size_t res, nv; 200 int i;
214 int scaled;
215 int i, thread;
216 201
217 count[0] = count[1] = count[2] = 0; 202 if (__perf_evsel__read(counter, cpus->nr, threads->nr, scale) < 0)
203 return -1;
218 204
219 nv = scale ? 3 : 1; 205 for (i = 0; i < 3; i++)
220 for (cpu = 0; cpu < nr_cpus; cpu++) { 206 update_stats(&ps->res_stats[i], count[i]);
221 for (thread = 0; thread < thread_num; thread++) {
222 if (fd[cpu][counter][thread] < 0)
223 continue;
224 207
225 res = read(fd[cpu][counter][thread], 208 if (verbose) {
226 single_count, nv * sizeof(u64)); 209 fprintf(stderr, "%s: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
227 assert(res == nv * sizeof(u64)); 210 event_name(counter), count[0], count[1], count[2]);
211 }
228 212
229 close(fd[cpu][counter][thread]); 213 /*
230 fd[cpu][counter][thread] = -1; 214 * Save the full runtime - to allow normalization during printout:
215 */
216 if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK))
217 update_stats(&runtime_nsecs_stats[0], count[0]);
218 if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES))
219 update_stats(&runtime_cycles_stats[0], count[0]);
220 if (perf_evsel__match(counter, HARDWARE, HW_BRANCH_INSTRUCTIONS))
221 update_stats(&runtime_branches_stats[0], count[0]);
231 222
232 count[0] += single_count[0]; 223 return 0;
233 if (scale) { 224}
234 count[1] += single_count[1];
235 count[2] += single_count[2];
236 }
237 }
238 }
239 225
240 scaled = 0; 226/*
241 if (scale) { 227 * Read out the results of a single counter:
242 if (count[2] == 0) { 228 * do not aggregate counts across CPUs in system-wide mode
243 event_scaled[counter] = -1; 229 */
244 count[0] = 0; 230static int read_counter(struct perf_evsel *counter)
245 return; 231{
246 } 232 u64 *count;
233 int cpu;
247 234
248 if (count[2] < count[1]) { 235 for (cpu = 0; cpu < cpus->nr; cpu++) {
249 event_scaled[counter] = 1; 236 if (__perf_evsel__read_on_cpu(counter, cpu, 0, scale) < 0)
250 count[0] = (unsigned long long) 237 return -1;
251 ((double)count[0] * count[1] / count[2] + 0.5);
252 }
253 }
254 238
255 for (i = 0; i < 3; i++) 239 count = counter->counts->cpu[cpu].values;
256 update_stats(&event_res_stats[counter][i], count[i]);
257 240
258 if (verbose) { 241 if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK))
259 fprintf(stderr, "%s: %Ld %Ld %Ld\n", event_name(counter), 242 update_stats(&runtime_nsecs_stats[cpu], count[0]);
260 count[0], count[1], count[2]); 243 if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES))
244 update_stats(&runtime_cycles_stats[cpu], count[0]);
245 if (perf_evsel__match(counter, HARDWARE, HW_BRANCH_INSTRUCTIONS))
246 update_stats(&runtime_branches_stats[cpu], count[0]);
261 } 247 }
262 248
263 /* 249 return 0;
264 * Save the full runtime - to allow normalization during printout:
265 */
266 if (MATCH_EVENT(SOFTWARE, SW_TASK_CLOCK, counter))
267 update_stats(&runtime_nsecs_stats, count[0]);
268 if (MATCH_EVENT(HARDWARE, HW_CPU_CYCLES, counter))
269 update_stats(&runtime_cycles_stats, count[0]);
270 if (MATCH_EVENT(HARDWARE, HW_BRANCH_INSTRUCTIONS, counter))
271 update_stats(&runtime_branches_stats, count[0]);
272} 250}
273 251
274static int run_perf_stat(int argc __used, const char **argv) 252static int run_perf_stat(int argc __used, const char **argv)
275{ 253{
276 unsigned long long t0, t1; 254 unsigned long long t0, t1;
255 struct perf_evsel *counter;
277 int status = 0; 256 int status = 0;
278 int counter, ncreated = 0;
279 int child_ready_pipe[2], go_pipe[2]; 257 int child_ready_pipe[2], go_pipe[2];
280 const bool forks = (argc > 0); 258 const bool forks = (argc > 0);
281 char buf; 259 char buf;
282 260
283 if (!system_wide)
284 nr_cpus = 1;
285
286 if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) { 261 if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) {
287 perror("failed to create pipes"); 262 perror("failed to create pipes");
288 exit(1); 263 exit(1);
@@ -322,7 +297,7 @@ static int run_perf_stat(int argc __used, const char **argv)
322 } 297 }
323 298
324 if (target_tid == -1 && target_pid == -1 && !system_wide) 299 if (target_tid == -1 && target_pid == -1 && !system_wide)
325 all_tids[0] = child_pid; 300 threads->map[0] = child_pid;
326 301
327 /* 302 /*
328 * Wait for the child to be ready to exec. 303 * Wait for the child to be ready to exec.
@@ -334,16 +309,25 @@ static int run_perf_stat(int argc __used, const char **argv)
334 close(child_ready_pipe[0]); 309 close(child_ready_pipe[0]);
335 } 310 }
336 311
337 for (counter = 0; counter < nr_counters; counter++) 312 list_for_each_entry(counter, &evsel_list, node) {
338 ncreated += create_perf_stat_counter(counter); 313 if (create_perf_stat_counter(counter) < 0) {
339 314 if (errno == -EPERM || errno == -EACCES) {
340 if (ncreated == 0) { 315 error("You may not have permission to collect %sstats.\n"
341 pr_err("No permission to collect %sstats.\n" 316 "\t Consider tweaking"
342 "Consider tweaking /proc/sys/kernel/perf_event_paranoid.\n", 317 " /proc/sys/kernel/perf_event_paranoid or running as root.",
343 system_wide ? "system-wide " : ""); 318 system_wide ? "system-wide " : "");
344 if (child_pid != -1) 319 } else if (errno == ENOENT) {
345 kill(child_pid, SIGTERM); 320 error("%s event is not supported. ", event_name(counter));
346 return -1; 321 } else {
322 error("open_counter returned with %d (%s). "
323 "/bin/dmesg may provide additional information.\n",
324 errno, strerror(errno));
325 }
326 if (child_pid != -1)
327 kill(child_pid, SIGTERM);
328 die("Not all events could be opened.\n");
329 return -1;
330 }
347 } 331 }
348 332
349 /* 333 /*
@@ -362,60 +346,97 @@ static int run_perf_stat(int argc __used, const char **argv)
362 346
363 update_stats(&walltime_nsecs_stats, t1 - t0); 347 update_stats(&walltime_nsecs_stats, t1 - t0);
364 348
365 for (counter = 0; counter < nr_counters; counter++) 349 if (no_aggr) {
366 read_counter(counter); 350 list_for_each_entry(counter, &evsel_list, node) {
351 read_counter(counter);
352 perf_evsel__close_fd(counter, cpus->nr, 1);
353 }
354 } else {
355 list_for_each_entry(counter, &evsel_list, node) {
356 read_counter_aggr(counter);
357 perf_evsel__close_fd(counter, cpus->nr, threads->nr);
358 }
359 }
367 360
368 return WEXITSTATUS(status); 361 return WEXITSTATUS(status);
369} 362}
370 363
371static void print_noise(int counter, double avg) 364static void print_noise(struct perf_evsel *evsel, double avg)
372{ 365{
366 struct perf_stat *ps;
367
373 if (run_count == 1) 368 if (run_count == 1)
374 return; 369 return;
375 370
371 ps = evsel->priv;
376 fprintf(stderr, " ( +- %7.3f%% )", 372 fprintf(stderr, " ( +- %7.3f%% )",
377 100 * stddev_stats(&event_res_stats[counter][0]) / avg); 373 100 * stddev_stats(&ps->res_stats[0]) / avg);
378} 374}
379 375
380static void nsec_printout(int counter, double avg) 376static void nsec_printout(int cpu, struct perf_evsel *evsel, double avg)
381{ 377{
382 double msecs = avg / 1e6; 378 double msecs = avg / 1e6;
379 char cpustr[16] = { '\0', };
380 const char *fmt = csv_output ? "%s%.6f%s%s" : "%s%18.6f%s%-24s";
381
382 if (no_aggr)
383 sprintf(cpustr, "CPU%*d%s",
384 csv_output ? 0 : -4,
385 cpus->map[cpu], csv_sep);
383 386
384 fprintf(stderr, " %18.6f %-24s", msecs, event_name(counter)); 387 fprintf(stderr, fmt, cpustr, msecs, csv_sep, event_name(evsel));
385 388
386 if (MATCH_EVENT(SOFTWARE, SW_TASK_CLOCK, counter)) { 389 if (csv_output)
390 return;
391
392 if (perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK))
387 fprintf(stderr, " # %10.3f CPUs ", 393 fprintf(stderr, " # %10.3f CPUs ",
388 avg / avg_stats(&walltime_nsecs_stats)); 394 avg / avg_stats(&walltime_nsecs_stats));
389 }
390} 395}
391 396
392static void abs_printout(int counter, double avg) 397static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
393{ 398{
394 double total, ratio = 0.0; 399 double total, ratio = 0.0;
400 char cpustr[16] = { '\0', };
401 const char *fmt;
395 402
396 if (big_num) 403 if (csv_output)
397 fprintf(stderr, " %'18.0f %-24s", avg, event_name(counter)); 404 fmt = "%s%.0f%s%s";
405 else if (big_num)
406 fmt = "%s%'18.0f%s%-24s";
398 else 407 else
399 fprintf(stderr, " %18.0f %-24s", avg, event_name(counter)); 408 fmt = "%s%18.0f%s%-24s";
400 409
401 if (MATCH_EVENT(HARDWARE, HW_INSTRUCTIONS, counter)) { 410 if (no_aggr)
402 total = avg_stats(&runtime_cycles_stats); 411 sprintf(cpustr, "CPU%*d%s",
412 csv_output ? 0 : -4,
413 cpus->map[cpu], csv_sep);
414 else
415 cpu = 0;
416
417 fprintf(stderr, fmt, cpustr, avg, csv_sep, event_name(evsel));
418
419 if (csv_output)
420 return;
421
422 if (perf_evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)) {
423 total = avg_stats(&runtime_cycles_stats[cpu]);
403 424
404 if (total) 425 if (total)
405 ratio = avg / total; 426 ratio = avg / total;
406 427
407 fprintf(stderr, " # %10.3f IPC ", ratio); 428 fprintf(stderr, " # %10.3f IPC ", ratio);
408 } else if (MATCH_EVENT(HARDWARE, HW_BRANCH_MISSES, counter) && 429 } else if (perf_evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES) &&
409 runtime_branches_stats.n != 0) { 430 runtime_branches_stats[cpu].n != 0) {
410 total = avg_stats(&runtime_branches_stats); 431 total = avg_stats(&runtime_branches_stats[cpu]);
411 432
412 if (total) 433 if (total)
413 ratio = avg * 100 / total; 434 ratio = avg * 100 / total;
414 435
415 fprintf(stderr, " # %10.3f %% ", ratio); 436 fprintf(stderr, " # %10.3f %% ", ratio);
416 437
417 } else if (runtime_nsecs_stats.n != 0) { 438 } else if (runtime_nsecs_stats[cpu].n != 0) {
418 total = avg_stats(&runtime_nsecs_stats); 439 total = avg_stats(&runtime_nsecs_stats[cpu]);
419 440
420 if (total) 441 if (total)
421 ratio = 1000.0 * avg / total; 442 ratio = 1000.0 * avg / total;
@@ -426,30 +447,38 @@ static void abs_printout(int counter, double avg)
426 447
427/* 448/*
428 * Print out the results of a single counter: 449 * Print out the results of a single counter:
450 * aggregated counts in system-wide mode
429 */ 451 */
430static void print_counter(int counter) 452static void print_counter_aggr(struct perf_evsel *counter)
431{ 453{
432 double avg = avg_stats(&event_res_stats[counter][0]); 454 struct perf_stat *ps = counter->priv;
433 int scaled = event_scaled[counter]; 455 double avg = avg_stats(&ps->res_stats[0]);
456 int scaled = counter->counts->scaled;
434 457
435 if (scaled == -1) { 458 if (scaled == -1) {
436 fprintf(stderr, " %18s %-24s\n", 459 fprintf(stderr, "%*s%s%-24s\n",
437 "<not counted>", event_name(counter)); 460 csv_output ? 0 : 18,
461 "<not counted>", csv_sep, event_name(counter));
438 return; 462 return;
439 } 463 }
440 464
441 if (nsec_counter(counter)) 465 if (nsec_counter(counter))
442 nsec_printout(counter, avg); 466 nsec_printout(-1, counter, avg);
443 else 467 else
444 abs_printout(counter, avg); 468 abs_printout(-1, counter, avg);
469
470 if (csv_output) {
471 fputc('\n', stderr);
472 return;
473 }
445 474
446 print_noise(counter, avg); 475 print_noise(counter, avg);
447 476
448 if (scaled) { 477 if (scaled) {
449 double avg_enabled, avg_running; 478 double avg_enabled, avg_running;
450 479
451 avg_enabled = avg_stats(&event_res_stats[counter][1]); 480 avg_enabled = avg_stats(&ps->res_stats[1]);
452 avg_running = avg_stats(&event_res_stats[counter][2]); 481 avg_running = avg_stats(&ps->res_stats[2]);
453 482
454 fprintf(stderr, " (scaled from %.2f%%)", 483 fprintf(stderr, " (scaled from %.2f%%)",
455 100 * avg_running / avg_enabled); 484 100 * avg_running / avg_enabled);
@@ -458,40 +487,92 @@ static void print_counter(int counter)
458 fprintf(stderr, "\n"); 487 fprintf(stderr, "\n");
459} 488}
460 489
490/*
491 * Print out the results of a single counter:
492 * does not use aggregated count in system-wide
493 */
494static void print_counter(struct perf_evsel *counter)
495{
496 u64 ena, run, val;
497 int cpu;
498
499 for (cpu = 0; cpu < cpus->nr; cpu++) {
500 val = counter->counts->cpu[cpu].val;
501 ena = counter->counts->cpu[cpu].ena;
502 run = counter->counts->cpu[cpu].run;
503 if (run == 0 || ena == 0) {
504 fprintf(stderr, "CPU%*d%s%*s%s%-24s",
505 csv_output ? 0 : -4,
506 cpus->map[cpu], csv_sep,
507 csv_output ? 0 : 18,
508 "<not counted>", csv_sep,
509 event_name(counter));
510
511 fprintf(stderr, "\n");
512 continue;
513 }
514
515 if (nsec_counter(counter))
516 nsec_printout(cpu, counter, val);
517 else
518 abs_printout(cpu, counter, val);
519
520 if (!csv_output) {
521 print_noise(counter, 1.0);
522
523 if (run != ena) {
524 fprintf(stderr, " (scaled from %.2f%%)",
525 100.0 * run / ena);
526 }
527 }
528 fprintf(stderr, "\n");
529 }
530}
531
461static void print_stat(int argc, const char **argv) 532static void print_stat(int argc, const char **argv)
462{ 533{
463 int i, counter; 534 struct perf_evsel *counter;
535 int i;
464 536
465 fflush(stdout); 537 fflush(stdout);
466 538
467 fprintf(stderr, "\n"); 539 if (!csv_output) {
468 fprintf(stderr, " Performance counter stats for "); 540 fprintf(stderr, "\n");
469 if(target_pid == -1 && target_tid == -1) { 541 fprintf(stderr, " Performance counter stats for ");
470 fprintf(stderr, "\'%s", argv[0]); 542 if(target_pid == -1 && target_tid == -1) {
471 for (i = 1; i < argc; i++) 543 fprintf(stderr, "\'%s", argv[0]);
472 fprintf(stderr, " %s", argv[i]); 544 for (i = 1; i < argc; i++)
473 } else if (target_pid != -1) 545 fprintf(stderr, " %s", argv[i]);
474 fprintf(stderr, "process id \'%d", target_pid); 546 } else if (target_pid != -1)
475 else 547 fprintf(stderr, "process id \'%d", target_pid);
476 fprintf(stderr, "thread id \'%d", target_tid); 548 else
477 549 fprintf(stderr, "thread id \'%d", target_tid);
478 fprintf(stderr, "\'"); 550
479 if (run_count > 1) 551 fprintf(stderr, "\'");
480 fprintf(stderr, " (%d runs)", run_count); 552 if (run_count > 1)
481 fprintf(stderr, ":\n\n"); 553 fprintf(stderr, " (%d runs)", run_count);
554 fprintf(stderr, ":\n\n");
555 }
482 556
483 for (counter = 0; counter < nr_counters; counter++) 557 if (no_aggr) {
484 print_counter(counter); 558 list_for_each_entry(counter, &evsel_list, node)
559 print_counter(counter);
560 } else {
561 list_for_each_entry(counter, &evsel_list, node)
562 print_counter_aggr(counter);
563 }
485 564
486 fprintf(stderr, "\n"); 565 if (!csv_output) {
487 fprintf(stderr, " %18.9f seconds time elapsed", 566 fprintf(stderr, "\n");
488 avg_stats(&walltime_nsecs_stats)/1e9); 567 fprintf(stderr, " %18.9f seconds time elapsed",
489 if (run_count > 1) { 568 avg_stats(&walltime_nsecs_stats)/1e9);
490 fprintf(stderr, " ( +- %7.3f%% )", 569 if (run_count > 1) {
570 fprintf(stderr, " ( +- %7.3f%% )",
491 100*stddev_stats(&walltime_nsecs_stats) / 571 100*stddev_stats(&walltime_nsecs_stats) /
492 avg_stats(&walltime_nsecs_stats)); 572 avg_stats(&walltime_nsecs_stats));
573 }
574 fprintf(stderr, "\n\n");
493 } 575 }
494 fprintf(stderr, "\n\n");
495} 576}
496 577
497static volatile int signr = -1; 578static volatile int signr = -1;
@@ -521,6 +602,13 @@ static const char * const stat_usage[] = {
521 NULL 602 NULL
522}; 603};
523 604
605static int stat__set_big_num(const struct option *opt __used,
606 const char *s __used, int unset)
607{
608 big_num_opt = unset ? 0 : 1;
609 return 0;
610}
611
524static const struct option options[] = { 612static const struct option options[] = {
525 OPT_CALLBACK('e', "event", NULL, "event", 613 OPT_CALLBACK('e', "event", NULL, "event",
526 "event selector. use 'perf list' to list available events", 614 "event selector. use 'perf list' to list available events",
@@ -541,64 +629,95 @@ static const struct option options[] = {
541 "repeat command and print average + stddev (max: 100)"), 629 "repeat command and print average + stddev (max: 100)"),
542 OPT_BOOLEAN('n', "null", &null_run, 630 OPT_BOOLEAN('n', "null", &null_run,
543 "null run - dont start any counters"), 631 "null run - dont start any counters"),
544 OPT_BOOLEAN('B', "big-num", &big_num, 632 OPT_CALLBACK_NOOPT('B', "big-num", NULL, NULL,
545 "print large numbers with thousands\' separators"), 633 "print large numbers with thousands\' separators",
634 stat__set_big_num),
546 OPT_STRING('C', "cpu", &cpu_list, "cpu", 635 OPT_STRING('C', "cpu", &cpu_list, "cpu",
547 "list of cpus to monitor in system-wide"), 636 "list of cpus to monitor in system-wide"),
637 OPT_BOOLEAN('A', "no-aggr", &no_aggr,
638 "disable CPU count aggregation"),
639 OPT_STRING('x', "field-separator", &csv_sep, "separator",
640 "print counts with custom separator"),
548 OPT_END() 641 OPT_END()
549}; 642};
550 643
551int cmd_stat(int argc, const char **argv, const char *prefix __used) 644int cmd_stat(int argc, const char **argv, const char *prefix __used)
552{ 645{
553 int status; 646 struct perf_evsel *pos;
554 int i,j; 647 int status = -ENOMEM;
555 648
556 setlocale(LC_ALL, ""); 649 setlocale(LC_ALL, "");
557 650
558 argc = parse_options(argc, argv, options, stat_usage, 651 argc = parse_options(argc, argv, options, stat_usage,
559 PARSE_OPT_STOP_AT_NON_OPTION); 652 PARSE_OPT_STOP_AT_NON_OPTION);
653
654 if (csv_sep)
655 csv_output = true;
656 else
657 csv_sep = DEFAULT_SEPARATOR;
658
659 /*
660 * let the spreadsheet do the pretty-printing
661 */
662 if (csv_output) {
663 /* User explicitely passed -B? */
664 if (big_num_opt == 1) {
665 fprintf(stderr, "-B option not supported with -x\n");
666 usage_with_options(stat_usage, options);
667 } else /* Nope, so disable big number formatting */
668 big_num = false;
669 } else if (big_num_opt == 0) /* User passed --no-big-num */
670 big_num = false;
671
560 if (!argc && target_pid == -1 && target_tid == -1) 672 if (!argc && target_pid == -1 && target_tid == -1)
561 usage_with_options(stat_usage, options); 673 usage_with_options(stat_usage, options);
562 if (run_count <= 0) 674 if (run_count <= 0)
563 usage_with_options(stat_usage, options); 675 usage_with_options(stat_usage, options);
564 676
677 /* no_aggr is for system-wide only */
678 if (no_aggr && !system_wide)
679 usage_with_options(stat_usage, options);
680
565 /* Set attrs and nr_counters if no event is selected and !null_run */ 681 /* Set attrs and nr_counters if no event is selected and !null_run */
566 if (!null_run && !nr_counters) { 682 if (!null_run && !nr_counters) {
567 memcpy(attrs, default_attrs, sizeof(default_attrs)); 683 size_t c;
684
568 nr_counters = ARRAY_SIZE(default_attrs); 685 nr_counters = ARRAY_SIZE(default_attrs);
686
687 for (c = 0; c < ARRAY_SIZE(default_attrs); ++c) {
688 pos = perf_evsel__new(&default_attrs[c],
689 nr_counters);
690 if (pos == NULL)
691 goto out;
692 list_add(&pos->node, &evsel_list);
693 }
569 } 694 }
570 695
571 if (system_wide) 696 if (target_pid != -1)
572 nr_cpus = read_cpu_map(cpu_list); 697 target_tid = target_pid;
573 else
574 nr_cpus = 1;
575 698
576 if (nr_cpus < 1) 699 threads = thread_map__new(target_pid, target_tid);
700 if (threads == NULL) {
701 pr_err("Problems finding threads of monitor\n");
577 usage_with_options(stat_usage, options); 702 usage_with_options(stat_usage, options);
703 }
578 704
579 if (target_pid != -1) { 705 if (system_wide)
580 target_tid = target_pid; 706 cpus = cpu_map__new(cpu_list);
581 thread_num = find_all_tid(target_pid, &all_tids); 707 else
582 if (thread_num <= 0) { 708 cpus = cpu_map__dummy_new();
583 fprintf(stderr, "Can't find all threads of pid %d\n",
584 target_pid);
585 usage_with_options(stat_usage, options);
586 }
587 } else {
588 all_tids=malloc(sizeof(pid_t));
589 if (!all_tids)
590 return -ENOMEM;
591 709
592 all_tids[0] = target_tid; 710 if (cpus == NULL) {
593 thread_num = 1; 711 perror("failed to parse CPUs map");
712 usage_with_options(stat_usage, options);
713 return -1;
594 } 714 }
595 715
596 for (i = 0; i < MAX_NR_CPUS; i++) { 716 list_for_each_entry(pos, &evsel_list, node) {
597 for (j = 0; j < MAX_COUNTERS; j++) { 717 if (perf_evsel__alloc_stat_priv(pos) < 0 ||
598 fd[i][j] = malloc(sizeof(int)*thread_num); 718 perf_evsel__alloc_counts(pos, cpus->nr) < 0 ||
599 if (!fd[i][j]) 719 perf_evsel__alloc_fd(pos, cpus->nr, threads->nr) < 0)
600 return -ENOMEM; 720 goto out_free_fd;
601 }
602 } 721 }
603 722
604 /* 723 /*
@@ -621,6 +740,12 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
621 740
622 if (status != -1) 741 if (status != -1)
623 print_stat(argc, argv); 742 print_stat(argc, argv);
624 743out_free_fd:
744 list_for_each_entry(pos, &evsel_list, node)
745 perf_evsel__free_stat_priv(pos);
746 perf_evsel_list__delete();
747out:
748 thread_map__delete(threads);
749 threads = NULL;
625 return status; 750 return status;
626} 751}
diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c
index 035b9fa063a9..5dcdba653d70 100644
--- a/tools/perf/builtin-test.c
+++ b/tools/perf/builtin-test.c
@@ -119,10 +119,16 @@ static int test__vmlinux_matches_kallsyms(void)
119 * end addresses too. 119 * end addresses too.
120 */ 120 */
121 for (nd = rb_first(&vmlinux_map->dso->symbols[type]); nd; nd = rb_next(nd)) { 121 for (nd = rb_first(&vmlinux_map->dso->symbols[type]); nd; nd = rb_next(nd)) {
122 struct symbol *pair; 122 struct symbol *pair, *first_pair;
123 bool backwards = true;
123 124
124 sym = rb_entry(nd, struct symbol, rb_node); 125 sym = rb_entry(nd, struct symbol, rb_node);
125 pair = machine__find_kernel_symbol(&kallsyms, type, sym->start, NULL, NULL); 126
127 if (sym->start == sym->end)
128 continue;
129
130 first_pair = machine__find_kernel_symbol(&kallsyms, type, sym->start, NULL, NULL);
131 pair = first_pair;
126 132
127 if (pair && pair->start == sym->start) { 133 if (pair && pair->start == sym->start) {
128next_pair: 134next_pair:
@@ -140,11 +146,13 @@ next_pair:
140 if (llabs(skew) < page_size) 146 if (llabs(skew) < page_size)
141 continue; 147 continue;
142 148
143 pr_debug("%#Lx: diff end addr for %s v: %#Lx k: %#Lx\n", 149 pr_debug("%#" PRIx64 ": diff end addr for %s v: %#" PRIx64 " k: %#" PRIx64 "\n",
144 sym->start, sym->name, sym->end, pair->end); 150 sym->start, sym->name, sym->end, pair->end);
145 } else { 151 } else {
146 struct rb_node *nnd = rb_prev(&pair->rb_node); 152 struct rb_node *nnd;
147 153detour:
154 nnd = backwards ? rb_prev(&pair->rb_node) :
155 rb_next(&pair->rb_node);
148 if (nnd) { 156 if (nnd) {
149 struct symbol *next = rb_entry(nnd, struct symbol, rb_node); 157 struct symbol *next = rb_entry(nnd, struct symbol, rb_node);
150 158
@@ -153,11 +161,18 @@ next_pair:
153 goto next_pair; 161 goto next_pair;
154 } 162 }
155 } 163 }
156 pr_debug("%#Lx: diff name v: %s k: %s\n", 164
165 if (backwards) {
166 backwards = false;
167 pair = first_pair;
168 goto detour;
169 }
170
171 pr_debug("%#" PRIx64 ": diff name v: %s k: %s\n",
157 sym->start, sym->name, pair->name); 172 sym->start, sym->name, pair->name);
158 } 173 }
159 } else 174 } else
160 pr_debug("%#Lx: %s not on kallsyms\n", sym->start, sym->name); 175 pr_debug("%#" PRIx64 ": %s not on kallsyms\n", sym->start, sym->name);
161 176
162 err = -1; 177 err = -1;
163 } 178 }
@@ -196,10 +211,10 @@ next_pair:
196 211
197 if (pair->start == pos->start) { 212 if (pair->start == pos->start) {
198 pair->priv = 1; 213 pair->priv = 1;
199 pr_info(" %Lx-%Lx %Lx %s in kallsyms as", 214 pr_info(" %" PRIx64 "-%" PRIx64 " %" PRIx64 " %s in kallsyms as",
200 pos->start, pos->end, pos->pgoff, pos->dso->name); 215 pos->start, pos->end, pos->pgoff, pos->dso->name);
201 if (pos->pgoff != pair->pgoff || pos->end != pair->end) 216 if (pos->pgoff != pair->pgoff || pos->end != pair->end)
202 pr_info(": \n*%Lx-%Lx %Lx", 217 pr_info(": \n*%" PRIx64 "-%" PRIx64 " %" PRIx64 "",
203 pair->start, pair->end, pair->pgoff); 218 pair->start, pair->end, pair->pgoff);
204 pr_info(" %s\n", pair->dso->name); 219 pr_info(" %s\n", pair->dso->name);
205 pair->priv = 1; 220 pair->priv = 1;
@@ -219,6 +234,209 @@ out:
219 return err; 234 return err;
220} 235}
221 236
237#include "util/cpumap.h"
238#include "util/evsel.h"
239#include <sys/types.h>
240
241static int trace_event__id(const char *event_name)
242{
243 char *filename;
244 int err = -1, fd;
245
246 if (asprintf(&filename,
247 "/sys/kernel/debug/tracing/events/syscalls/%s/id",
248 event_name) < 0)
249 return -1;
250
251 fd = open(filename, O_RDONLY);
252 if (fd >= 0) {
253 char id[16];
254 if (read(fd, id, sizeof(id)) > 0)
255 err = atoi(id);
256 close(fd);
257 }
258
259 free(filename);
260 return err;
261}
262
263static int test__open_syscall_event(void)
264{
265 int err = -1, fd;
266 struct thread_map *threads;
267 struct perf_evsel *evsel;
268 struct perf_event_attr attr;
269 unsigned int nr_open_calls = 111, i;
270 int id = trace_event__id("sys_enter_open");
271
272 if (id < 0) {
273 pr_debug("is debugfs mounted on /sys/kernel/debug?\n");
274 return -1;
275 }
276
277 threads = thread_map__new(-1, getpid());
278 if (threads == NULL) {
279 pr_debug("thread_map__new\n");
280 return -1;
281 }
282
283 memset(&attr, 0, sizeof(attr));
284 attr.type = PERF_TYPE_TRACEPOINT;
285 attr.config = id;
286 evsel = perf_evsel__new(&attr, 0);
287 if (evsel == NULL) {
288 pr_debug("perf_evsel__new\n");
289 goto out_thread_map_delete;
290 }
291
292 if (perf_evsel__open_per_thread(evsel, threads) < 0) {
293 pr_debug("failed to open counter: %s, "
294 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
295 strerror(errno));
296 goto out_evsel_delete;
297 }
298
299 for (i = 0; i < nr_open_calls; ++i) {
300 fd = open("/etc/passwd", O_RDONLY);
301 close(fd);
302 }
303
304 if (perf_evsel__read_on_cpu(evsel, 0, 0) < 0) {
305 pr_debug("perf_evsel__open_read_on_cpu\n");
306 goto out_close_fd;
307 }
308
309 if (evsel->counts->cpu[0].val != nr_open_calls) {
310 pr_debug("perf_evsel__read_on_cpu: expected to intercept %d calls, got %" PRIu64 "\n",
311 nr_open_calls, evsel->counts->cpu[0].val);
312 goto out_close_fd;
313 }
314
315 err = 0;
316out_close_fd:
317 perf_evsel__close_fd(evsel, 1, threads->nr);
318out_evsel_delete:
319 perf_evsel__delete(evsel);
320out_thread_map_delete:
321 thread_map__delete(threads);
322 return err;
323}
324
325#include <sched.h>
326
327static int test__open_syscall_event_on_all_cpus(void)
328{
329 int err = -1, fd, cpu;
330 struct thread_map *threads;
331 struct cpu_map *cpus;
332 struct perf_evsel *evsel;
333 struct perf_event_attr attr;
334 unsigned int nr_open_calls = 111, i;
335 cpu_set_t cpu_set;
336 int id = trace_event__id("sys_enter_open");
337
338 if (id < 0) {
339 pr_debug("is debugfs mounted on /sys/kernel/debug?\n");
340 return -1;
341 }
342
343 threads = thread_map__new(-1, getpid());
344 if (threads == NULL) {
345 pr_debug("thread_map__new\n");
346 return -1;
347 }
348
349 cpus = cpu_map__new(NULL);
350 if (threads == NULL) {
351 pr_debug("thread_map__new\n");
352 return -1;
353 }
354
355
356 CPU_ZERO(&cpu_set);
357
358 memset(&attr, 0, sizeof(attr));
359 attr.type = PERF_TYPE_TRACEPOINT;
360 attr.config = id;
361 evsel = perf_evsel__new(&attr, 0);
362 if (evsel == NULL) {
363 pr_debug("perf_evsel__new\n");
364 goto out_thread_map_delete;
365 }
366
367 if (perf_evsel__open(evsel, cpus, threads) < 0) {
368 pr_debug("failed to open counter: %s, "
369 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
370 strerror(errno));
371 goto out_evsel_delete;
372 }
373
374 for (cpu = 0; cpu < cpus->nr; ++cpu) {
375 unsigned int ncalls = nr_open_calls + cpu;
376 /*
377 * XXX eventually lift this restriction in a way that
378 * keeps perf building on older glibc installations
379 * without CPU_ALLOC. 1024 cpus in 2010 still seems
380 * a reasonable upper limit tho :-)
381 */
382 if (cpus->map[cpu] >= CPU_SETSIZE) {
383 pr_debug("Ignoring CPU %d\n", cpus->map[cpu]);
384 continue;
385 }
386
387 CPU_SET(cpus->map[cpu], &cpu_set);
388 if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) {
389 pr_debug("sched_setaffinity() failed on CPU %d: %s ",
390 cpus->map[cpu],
391 strerror(errno));
392 goto out_close_fd;
393 }
394 for (i = 0; i < ncalls; ++i) {
395 fd = open("/etc/passwd", O_RDONLY);
396 close(fd);
397 }
398 CPU_CLR(cpus->map[cpu], &cpu_set);
399 }
400
401 /*
402 * Here we need to explicitely preallocate the counts, as if
403 * we use the auto allocation it will allocate just for 1 cpu,
404 * as we start by cpu 0.
405 */
406 if (perf_evsel__alloc_counts(evsel, cpus->nr) < 0) {
407 pr_debug("perf_evsel__alloc_counts(ncpus=%d)\n", cpus->nr);
408 goto out_close_fd;
409 }
410
411 for (cpu = 0; cpu < cpus->nr; ++cpu) {
412 unsigned int expected;
413
414 if (cpus->map[cpu] >= CPU_SETSIZE)
415 continue;
416
417 if (perf_evsel__read_on_cpu(evsel, cpu, 0) < 0) {
418 pr_debug("perf_evsel__open_read_on_cpu\n");
419 goto out_close_fd;
420 }
421
422 expected = nr_open_calls + cpu;
423 if (evsel->counts->cpu[cpu].val != expected) {
424 pr_debug("perf_evsel__read_on_cpu: expected to intercept %d calls on cpu %d, got %" PRIu64 "\n",
425 expected, cpus->map[cpu], evsel->counts->cpu[cpu].val);
426 goto out_close_fd;
427 }
428 }
429
430 err = 0;
431out_close_fd:
432 perf_evsel__close_fd(evsel, 1, threads->nr);
433out_evsel_delete:
434 perf_evsel__delete(evsel);
435out_thread_map_delete:
436 thread_map__delete(threads);
437 return err;
438}
439
222static struct test { 440static struct test {
223 const char *desc; 441 const char *desc;
224 int (*func)(void); 442 int (*func)(void);
@@ -228,6 +446,14 @@ static struct test {
228 .func = test__vmlinux_matches_kallsyms, 446 .func = test__vmlinux_matches_kallsyms,
229 }, 447 },
230 { 448 {
449 .desc = "detect open syscall event",
450 .func = test__open_syscall_event,
451 },
452 {
453 .desc = "detect open syscall event on all cpus",
454 .func = test__open_syscall_event_on_all_cpus,
455 },
456 {
231 .func = NULL, 457 .func = NULL,
232 }, 458 },
233}; 459};
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 9bcc38f0b706..746cf03cb05d 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -32,6 +32,10 @@
32#include "util/session.h" 32#include "util/session.h"
33#include "util/svghelper.h" 33#include "util/svghelper.h"
34 34
35#define SUPPORT_OLD_POWER_EVENTS 1
36#define PWR_EVENT_EXIT -1
37
38
35static char const *input_name = "perf.data"; 39static char const *input_name = "perf.data";
36static char const *output_name = "output.svg"; 40static char const *output_name = "output.svg";
37 41
@@ -272,19 +276,22 @@ static int cpus_cstate_state[MAX_CPUS];
272static u64 cpus_pstate_start_times[MAX_CPUS]; 276static u64 cpus_pstate_start_times[MAX_CPUS];
273static u64 cpus_pstate_state[MAX_CPUS]; 277static u64 cpus_pstate_state[MAX_CPUS];
274 278
275static int process_comm_event(event_t *event, struct perf_session *session __used) 279static int process_comm_event(event_t *event, struct sample_data *sample __used,
280 struct perf_session *session __used)
276{ 281{
277 pid_set_comm(event->comm.tid, event->comm.comm); 282 pid_set_comm(event->comm.tid, event->comm.comm);
278 return 0; 283 return 0;
279} 284}
280 285
281static int process_fork_event(event_t *event, struct perf_session *session __used) 286static int process_fork_event(event_t *event, struct sample_data *sample __used,
287 struct perf_session *session __used)
282{ 288{
283 pid_fork(event->fork.pid, event->fork.ppid, event->fork.time); 289 pid_fork(event->fork.pid, event->fork.ppid, event->fork.time);
284 return 0; 290 return 0;
285} 291}
286 292
287static int process_exit_event(event_t *event, struct perf_session *session __used) 293static int process_exit_event(event_t *event, struct sample_data *sample __used,
294 struct perf_session *session __used)
288{ 295{
289 pid_exit(event->fork.pid, event->fork.time); 296 pid_exit(event->fork.pid, event->fork.time);
290 return 0; 297 return 0;
@@ -298,12 +305,21 @@ struct trace_entry {
298 int lock_depth; 305 int lock_depth;
299}; 306};
300 307
301struct power_entry { 308#ifdef SUPPORT_OLD_POWER_EVENTS
309static int use_old_power_events;
310struct power_entry_old {
302 struct trace_entry te; 311 struct trace_entry te;
303 u64 type; 312 u64 type;
304 u64 value; 313 u64 value;
305 u64 cpu_id; 314 u64 cpu_id;
306}; 315};
316#endif
317
318struct power_processor_entry {
319 struct trace_entry te;
320 u32 state;
321 u32 cpu_id;
322};
307 323
308#define TASK_COMM_LEN 16 324#define TASK_COMM_LEN 16
309struct wakeup_entry { 325struct wakeup_entry {
@@ -470,48 +486,65 @@ static void sched_switch(int cpu, u64 timestamp, struct trace_entry *te)
470} 486}
471 487
472 488
473static int process_sample_event(event_t *event, struct perf_session *session) 489static int process_sample_event(event_t *event __used,
490 struct sample_data *sample,
491 struct perf_session *session)
474{ 492{
475 struct sample_data data;
476 struct trace_entry *te; 493 struct trace_entry *te;
477 494
478 memset(&data, 0, sizeof(data));
479
480 event__parse_sample(event, session->sample_type, &data);
481
482 if (session->sample_type & PERF_SAMPLE_TIME) { 495 if (session->sample_type & PERF_SAMPLE_TIME) {
483 if (!first_time || first_time > data.time) 496 if (!first_time || first_time > sample->time)
484 first_time = data.time; 497 first_time = sample->time;
485 if (last_time < data.time) 498 if (last_time < sample->time)
486 last_time = data.time; 499 last_time = sample->time;
487 } 500 }
488 501
489 te = (void *)data.raw_data; 502 te = (void *)sample->raw_data;
490 if (session->sample_type & PERF_SAMPLE_RAW && data.raw_size > 0) { 503 if (session->sample_type & PERF_SAMPLE_RAW && sample->raw_size > 0) {
491 char *event_str; 504 char *event_str;
492 struct power_entry *pe; 505#ifdef SUPPORT_OLD_POWER_EVENTS
493 506 struct power_entry_old *peo;
494 pe = (void *)te; 507 peo = (void *)te;
495 508#endif
496 event_str = perf_header__find_event(te->type); 509 event_str = perf_header__find_event(te->type);
497 510
498 if (!event_str) 511 if (!event_str)
499 return 0; 512 return 0;
500 513
501 if (strcmp(event_str, "power:power_start") == 0) 514 if (strcmp(event_str, "power:cpu_idle") == 0) {
502 c_state_start(pe->cpu_id, data.time, pe->value); 515 struct power_processor_entry *ppe = (void *)te;
516 if (ppe->state == (u32)PWR_EVENT_EXIT)
517 c_state_end(ppe->cpu_id, sample->time);
518 else
519 c_state_start(ppe->cpu_id, sample->time,
520 ppe->state);
521 }
522 else if (strcmp(event_str, "power:cpu_frequency") == 0) {
523 struct power_processor_entry *ppe = (void *)te;
524 p_state_change(ppe->cpu_id, sample->time, ppe->state);
525 }
526
527 else if (strcmp(event_str, "sched:sched_wakeup") == 0)
528 sched_wakeup(sample->cpu, sample->time, sample->pid, te);
503 529
504 if (strcmp(event_str, "power:power_end") == 0) 530 else if (strcmp(event_str, "sched:sched_switch") == 0)
505 c_state_end(pe->cpu_id, data.time); 531 sched_switch(sample->cpu, sample->time, te);
506 532
507 if (strcmp(event_str, "power:power_frequency") == 0) 533#ifdef SUPPORT_OLD_POWER_EVENTS
508 p_state_change(pe->cpu_id, data.time, pe->value); 534 if (use_old_power_events) {
535 if (strcmp(event_str, "power:power_start") == 0)
536 c_state_start(peo->cpu_id, sample->time,
537 peo->value);
509 538
510 if (strcmp(event_str, "sched:sched_wakeup") == 0) 539 else if (strcmp(event_str, "power:power_end") == 0)
511 sched_wakeup(data.cpu, data.time, data.pid, te); 540 c_state_end(sample->cpu, sample->time);
512 541
513 if (strcmp(event_str, "sched:sched_switch") == 0) 542 else if (strcmp(event_str,
514 sched_switch(data.cpu, data.time, te); 543 "power:power_frequency") == 0)
544 p_state_change(peo->cpu_id, sample->time,
545 peo->value);
546 }
547#endif
515 } 548 }
516 return 0; 549 return 0;
517} 550}
@@ -937,7 +970,8 @@ static struct perf_event_ops event_ops = {
937 970
938static int __cmd_timechart(void) 971static int __cmd_timechart(void)
939{ 972{
940 struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0, false); 973 struct perf_session *session = perf_session__new(input_name, O_RDONLY,
974 0, false, &event_ops);
941 int ret = -EINVAL; 975 int ret = -EINVAL;
942 976
943 if (session == NULL) 977 if (session == NULL)
@@ -968,7 +1002,8 @@ static const char * const timechart_usage[] = {
968 NULL 1002 NULL
969}; 1003};
970 1004
971static const char *record_args[] = { 1005#ifdef SUPPORT_OLD_POWER_EVENTS
1006static const char * const record_old_args[] = {
972 "record", 1007 "record",
973 "-a", 1008 "-a",
974 "-R", 1009 "-R",
@@ -980,16 +1015,43 @@ static const char *record_args[] = {
980 "-e", "sched:sched_wakeup", 1015 "-e", "sched:sched_wakeup",
981 "-e", "sched:sched_switch", 1016 "-e", "sched:sched_switch",
982}; 1017};
1018#endif
1019
1020static const char * const record_new_args[] = {
1021 "record",
1022 "-a",
1023 "-R",
1024 "-f",
1025 "-c", "1",
1026 "-e", "power:cpu_frequency",
1027 "-e", "power:cpu_idle",
1028 "-e", "sched:sched_wakeup",
1029 "-e", "sched:sched_switch",
1030};
983 1031
984static int __cmd_record(int argc, const char **argv) 1032static int __cmd_record(int argc, const char **argv)
985{ 1033{
986 unsigned int rec_argc, i, j; 1034 unsigned int rec_argc, i, j;
987 const char **rec_argv; 1035 const char **rec_argv;
1036 const char * const *record_args = record_new_args;
1037 unsigned int record_elems = ARRAY_SIZE(record_new_args);
1038
1039#ifdef SUPPORT_OLD_POWER_EVENTS
1040 if (!is_valid_tracepoint("power:cpu_idle") &&
1041 is_valid_tracepoint("power:power_start")) {
1042 use_old_power_events = 1;
1043 record_args = record_old_args;
1044 record_elems = ARRAY_SIZE(record_old_args);
1045 }
1046#endif
988 1047
989 rec_argc = ARRAY_SIZE(record_args) + argc - 1; 1048 rec_argc = record_elems + argc - 1;
990 rec_argv = calloc(rec_argc + 1, sizeof(char *)); 1049 rec_argv = calloc(rec_argc + 1, sizeof(char *));
991 1050
992 for (i = 0; i < ARRAY_SIZE(record_args); i++) 1051 if (rec_argv == NULL)
1052 return -ENOMEM;
1053
1054 for (i = 0; i < record_elems; i++)
993 rec_argv[i] = strdup(record_args[i]); 1055 rec_argv[i] = strdup(record_args[i]);
994 1056
995 for (j = 1; j < (unsigned int)argc; j++, i++) 1057 for (j = 1; j < (unsigned int)argc; j++, i++)
@@ -1018,6 +1080,8 @@ static const struct option options[] = {
1018 OPT_CALLBACK('p', "process", NULL, "process", 1080 OPT_CALLBACK('p', "process", NULL, "process",
1019 "process selector. Pass a pid or process name.", 1081 "process selector. Pass a pid or process name.",
1020 parse_process), 1082 parse_process),
1083 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
1084 "Look for files with symbols relative to this directory"),
1021 OPT_END() 1085 OPT_END()
1022}; 1086};
1023 1087
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index b513e40974f4..b6998e055767 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -21,6 +21,7 @@
21#include "perf.h" 21#include "perf.h"
22 22
23#include "util/color.h" 23#include "util/color.h"
24#include "util/evsel.h"
24#include "util/session.h" 25#include "util/session.h"
25#include "util/symbol.h" 26#include "util/symbol.h"
26#include "util/thread.h" 27#include "util/thread.h"
@@ -29,6 +30,7 @@
29#include "util/parse-options.h" 30#include "util/parse-options.h"
30#include "util/parse-events.h" 31#include "util/parse-events.h"
31#include "util/cpumap.h" 32#include "util/cpumap.h"
33#include "util/xyarray.h"
32 34
33#include "util/debug.h" 35#include "util/debug.h"
34 36
@@ -38,6 +40,7 @@
38#include <stdio.h> 40#include <stdio.h>
39#include <termios.h> 41#include <termios.h>
40#include <unistd.h> 42#include <unistd.h>
43#include <inttypes.h>
41 44
42#include <errno.h> 45#include <errno.h>
43#include <time.h> 46#include <time.h>
@@ -55,7 +58,7 @@
55#include <linux/unistd.h> 58#include <linux/unistd.h>
56#include <linux/types.h> 59#include <linux/types.h>
57 60
58static int *fd[MAX_NR_CPUS][MAX_COUNTERS]; 61#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
59 62
60static bool system_wide = false; 63static bool system_wide = false;
61 64
@@ -66,11 +69,9 @@ static int print_entries;
66 69
67static int target_pid = -1; 70static int target_pid = -1;
68static int target_tid = -1; 71static int target_tid = -1;
69static pid_t *all_tids = NULL; 72static struct thread_map *threads;
70static int thread_num = 0;
71static bool inherit = false; 73static bool inherit = false;
72static int profile_cpu = -1; 74static struct cpu_map *cpus;
73static int nr_cpus = 0;
74static int realtime_prio = 0; 75static int realtime_prio = 0;
75static bool group = false; 76static bool group = false;
76static unsigned int page_size; 77static unsigned int page_size;
@@ -101,6 +102,7 @@ struct sym_entry *sym_filter_entry = NULL;
101struct sym_entry *sym_filter_entry_sched = NULL; 102struct sym_entry *sym_filter_entry_sched = NULL;
102static int sym_pcnt_filter = 5; 103static int sym_pcnt_filter = 5;
103static int sym_counter = 0; 104static int sym_counter = 0;
105static struct perf_evsel *sym_evsel = NULL;
104static int display_weighted = -1; 106static int display_weighted = -1;
105static const char *cpu_list; 107static const char *cpu_list;
106 108
@@ -213,7 +215,7 @@ static int parse_source(struct sym_entry *syme)
213 len = sym->end - sym->start; 215 len = sym->end - sym->start;
214 216
215 sprintf(command, 217 sprintf(command,
216 "objdump --start-address=%#0*Lx --stop-address=%#0*Lx -dS %s", 218 "objdump --start-address=%#0*" PRIx64 " --stop-address=%#0*" PRIx64 " -dS %s",
217 BITS_PER_LONG / 4, map__rip_2objdump(map, sym->start), 219 BITS_PER_LONG / 4, map__rip_2objdump(map, sym->start),
218 BITS_PER_LONG / 4, map__rip_2objdump(map, sym->end), path); 220 BITS_PER_LONG / 4, map__rip_2objdump(map, sym->end), path);
219 221
@@ -307,7 +309,7 @@ static void lookup_sym_source(struct sym_entry *syme)
307 struct source_line *line; 309 struct source_line *line;
308 char pattern[PATTERN_LEN + 1]; 310 char pattern[PATTERN_LEN + 1];
309 311
310 sprintf(pattern, "%0*Lx <", BITS_PER_LONG / 4, 312 sprintf(pattern, "%0*" PRIx64 " <", BITS_PER_LONG / 4,
311 map__rip_2objdump(syme->map, symbol->start)); 313 map__rip_2objdump(syme->map, symbol->start));
312 314
313 pthread_mutex_lock(&syme->src->lock); 315 pthread_mutex_lock(&syme->src->lock);
@@ -354,7 +356,7 @@ static void show_details(struct sym_entry *syme)
354 return; 356 return;
355 357
356 symbol = sym_entry__symbol(syme); 358 symbol = sym_entry__symbol(syme);
357 printf("Showing %s for %s\n", event_name(sym_counter), symbol->name); 359 printf("Showing %s for %s\n", event_name(sym_evsel), symbol->name);
358 printf(" Events Pcnt (>=%d%%)\n", sym_pcnt_filter); 360 printf(" Events Pcnt (>=%d%%)\n", sym_pcnt_filter);
359 361
360 pthread_mutex_lock(&syme->src->lock); 362 pthread_mutex_lock(&syme->src->lock);
@@ -461,7 +463,8 @@ static void rb_insert_active_sym(struct rb_root *tree, struct sym_entry *se)
461static void print_sym_table(void) 463static void print_sym_table(void)
462{ 464{
463 int printed = 0, j; 465 int printed = 0, j;
464 int counter, snap = !display_weighted ? sym_counter : 0; 466 struct perf_evsel *counter;
467 int snap = !display_weighted ? sym_counter : 0;
465 float samples_per_sec = samples/delay_secs; 468 float samples_per_sec = samples/delay_secs;
466 float ksamples_per_sec = kernel_samples/delay_secs; 469 float ksamples_per_sec = kernel_samples/delay_secs;
467 float us_samples_per_sec = (us_samples)/delay_secs; 470 float us_samples_per_sec = (us_samples)/delay_secs;
@@ -533,7 +536,9 @@ static void print_sym_table(void)
533 } 536 }
534 537
535 if (nr_counters == 1 || !display_weighted) { 538 if (nr_counters == 1 || !display_weighted) {
536 printf("%Ld", (u64)attrs[0].sample_period); 539 struct perf_evsel *first;
540 first = list_entry(evsel_list.next, struct perf_evsel, node);
541 printf("%" PRIu64, (uint64_t)first->attr.sample_period);
537 if (freq) 542 if (freq)
538 printf("Hz "); 543 printf("Hz ");
539 else 544 else
@@ -541,9 +546,9 @@ static void print_sym_table(void)
541 } 546 }
542 547
543 if (!display_weighted) 548 if (!display_weighted)
544 printf("%s", event_name(sym_counter)); 549 printf("%s", event_name(sym_evsel));
545 else for (counter = 0; counter < nr_counters; counter++) { 550 else list_for_each_entry(counter, &evsel_list, node) {
546 if (counter) 551 if (counter->idx)
547 printf("/"); 552 printf("/");
548 553
549 printf("%s", event_name(counter)); 554 printf("%s", event_name(counter));
@@ -558,13 +563,13 @@ static void print_sym_table(void)
558 else 563 else
559 printf(" (all"); 564 printf(" (all");
560 565
561 if (profile_cpu != -1) 566 if (cpu_list)
562 printf(", cpu: %d)\n", profile_cpu); 567 printf(", CPU%s: %s)\n", cpus->nr > 1 ? "s" : "", cpu_list);
563 else { 568 else {
564 if (target_tid != -1) 569 if (target_tid != -1)
565 printf(")\n"); 570 printf(")\n");
566 else 571 else
567 printf(", %d CPUs)\n", nr_cpus); 572 printf(", %d CPU%s)\n", cpus->nr, cpus->nr > 1 ? "s" : "");
568 } 573 }
569 574
570 printf("%-*.*s\n", win_width, win_width, graph_dotted_line); 575 printf("%-*.*s\n", win_width, win_width, graph_dotted_line);
@@ -636,7 +641,7 @@ static void print_sym_table(void)
636 641
637 percent_color_fprintf(stdout, "%4.1f%%", pcnt); 642 percent_color_fprintf(stdout, "%4.1f%%", pcnt);
638 if (verbose) 643 if (verbose)
639 printf(" %016llx", sym->start); 644 printf(" %016" PRIx64, sym->start);
640 printf(" %-*.*s", sym_width, sym_width, sym->name); 645 printf(" %-*.*s", sym_width, sym_width, sym->name);
641 printf(" %-*.*s\n", dso_width, dso_width, 646 printf(" %-*.*s\n", dso_width, dso_width,
642 dso_width >= syme->map->dso->long_name_len ? 647 dso_width >= syme->map->dso->long_name_len ?
@@ -740,7 +745,7 @@ static void print_mapped_keys(void)
740 fprintf(stdout, "\t[e] display entries (lines). \t(%d)\n", print_entries); 745 fprintf(stdout, "\t[e] display entries (lines). \t(%d)\n", print_entries);
741 746
742 if (nr_counters > 1) 747 if (nr_counters > 1)
743 fprintf(stdout, "\t[E] active event counter. \t(%s)\n", event_name(sym_counter)); 748 fprintf(stdout, "\t[E] active event counter. \t(%s)\n", event_name(sym_evsel));
744 749
745 fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", count_filter); 750 fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", count_filter);
746 751
@@ -827,19 +832,23 @@ static void handle_keypress(struct perf_session *session, int c)
827 break; 832 break;
828 case 'E': 833 case 'E':
829 if (nr_counters > 1) { 834 if (nr_counters > 1) {
830 int i;
831
832 fprintf(stderr, "\nAvailable events:"); 835 fprintf(stderr, "\nAvailable events:");
833 for (i = 0; i < nr_counters; i++) 836
834 fprintf(stderr, "\n\t%d %s", i, event_name(i)); 837 list_for_each_entry(sym_evsel, &evsel_list, node)
838 fprintf(stderr, "\n\t%d %s", sym_evsel->idx, event_name(sym_evsel));
835 839
836 prompt_integer(&sym_counter, "Enter details event counter"); 840 prompt_integer(&sym_counter, "Enter details event counter");
837 841
838 if (sym_counter >= nr_counters) { 842 if (sym_counter >= nr_counters) {
839 fprintf(stderr, "Sorry, no such event, using %s.\n", event_name(0)); 843 sym_evsel = list_entry(evsel_list.next, struct perf_evsel, node);
840 sym_counter = 0; 844 sym_counter = 0;
845 fprintf(stderr, "Sorry, no such event, using %s.\n", event_name(sym_evsel));
841 sleep(1); 846 sleep(1);
847 break;
842 } 848 }
849 list_for_each_entry(sym_evsel, &evsel_list, node)
850 if (sym_evsel->idx == sym_counter)
851 break;
843 } else sym_counter = 0; 852 } else sym_counter = 0;
844 break; 853 break;
845 case 'f': 854 case 'f':
@@ -978,12 +987,13 @@ static int symbol_filter(struct map *map, struct symbol *sym)
978} 987}
979 988
980static void event__process_sample(const event_t *self, 989static void event__process_sample(const event_t *self,
981 struct perf_session *session, int counter) 990 struct sample_data *sample,
991 struct perf_session *session,
992 struct perf_evsel *evsel)
982{ 993{
983 u64 ip = self->ip.ip; 994 u64 ip = self->ip.ip;
984 struct sym_entry *syme; 995 struct sym_entry *syme;
985 struct addr_location al; 996 struct addr_location al;
986 struct sample_data data;
987 struct machine *machine; 997 struct machine *machine;
988 u8 origin = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 998 u8 origin = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
989 999
@@ -1026,7 +1036,7 @@ static void event__process_sample(const event_t *self,
1026 if (self->header.misc & PERF_RECORD_MISC_EXACT_IP) 1036 if (self->header.misc & PERF_RECORD_MISC_EXACT_IP)
1027 exact_samples++; 1037 exact_samples++;
1028 1038
1029 if (event__preprocess_sample(self, session, &al, &data, 1039 if (event__preprocess_sample(self, session, &al, sample,
1030 symbol_filter) < 0 || 1040 symbol_filter) < 0 ||
1031 al.filtered) 1041 al.filtered)
1032 return; 1042 return;
@@ -1072,9 +1082,9 @@ static void event__process_sample(const event_t *self,
1072 1082
1073 syme = symbol__priv(al.sym); 1083 syme = symbol__priv(al.sym);
1074 if (!syme->skip) { 1084 if (!syme->skip) {
1075 syme->count[counter]++; 1085 syme->count[evsel->idx]++;
1076 syme->origin = origin; 1086 syme->origin = origin;
1077 record_precise_ip(syme, counter, ip); 1087 record_precise_ip(syme, evsel->idx, ip);
1078 pthread_mutex_lock(&active_symbols_lock); 1088 pthread_mutex_lock(&active_symbols_lock);
1079 if (list_empty(&syme->node) || !syme->node.next) 1089 if (list_empty(&syme->node) || !syme->node.next)
1080 __list_insert_active_sym(syme); 1090 __list_insert_active_sym(syme);
@@ -1083,12 +1093,24 @@ static void event__process_sample(const event_t *self,
1083} 1093}
1084 1094
1085struct mmap_data { 1095struct mmap_data {
1086 int counter;
1087 void *base; 1096 void *base;
1088 int mask; 1097 int mask;
1089 unsigned int prev; 1098 unsigned int prev;
1090}; 1099};
1091 1100
1101static int perf_evsel__alloc_mmap_per_thread(struct perf_evsel *evsel,
1102 int ncpus, int nthreads)
1103{
1104 evsel->priv = xyarray__new(ncpus, nthreads, sizeof(struct mmap_data));
1105 return evsel->priv != NULL ? 0 : -ENOMEM;
1106}
1107
1108static void perf_evsel__free_mmap(struct perf_evsel *evsel)
1109{
1110 xyarray__delete(evsel->priv);
1111 evsel->priv = NULL;
1112}
1113
1092static unsigned int mmap_read_head(struct mmap_data *md) 1114static unsigned int mmap_read_head(struct mmap_data *md)
1093{ 1115{
1094 struct perf_event_mmap_page *pc = md->base; 1116 struct perf_event_mmap_page *pc = md->base;
@@ -1101,11 +1123,15 @@ static unsigned int mmap_read_head(struct mmap_data *md)
1101} 1123}
1102 1124
1103static void perf_session__mmap_read_counter(struct perf_session *self, 1125static void perf_session__mmap_read_counter(struct perf_session *self,
1104 struct mmap_data *md) 1126 struct perf_evsel *evsel,
1127 int cpu, int thread_idx)
1105{ 1128{
1129 struct xyarray *mmap_array = evsel->priv;
1130 struct mmap_data *md = xyarray__entry(mmap_array, cpu, thread_idx);
1106 unsigned int head = mmap_read_head(md); 1131 unsigned int head = mmap_read_head(md);
1107 unsigned int old = md->prev; 1132 unsigned int old = md->prev;
1108 unsigned char *data = md->base + page_size; 1133 unsigned char *data = md->base + page_size;
1134 struct sample_data sample;
1109 int diff; 1135 int diff;
1110 1136
1111 /* 1137 /*
@@ -1153,10 +1179,11 @@ static void perf_session__mmap_read_counter(struct perf_session *self,
1153 event = &event_copy; 1179 event = &event_copy;
1154 } 1180 }
1155 1181
1182 event__parse_sample(event, self, &sample);
1156 if (event->header.type == PERF_RECORD_SAMPLE) 1183 if (event->header.type == PERF_RECORD_SAMPLE)
1157 event__process_sample(event, self, md->counter); 1184 event__process_sample(event, &sample, self, evsel);
1158 else 1185 else
1159 event__process(event, self); 1186 event__process(event, &sample, self);
1160 old += size; 1187 old += size;
1161 } 1188 }
1162 1189
@@ -1164,37 +1191,39 @@ static void perf_session__mmap_read_counter(struct perf_session *self,
1164} 1191}
1165 1192
1166static struct pollfd *event_array; 1193static struct pollfd *event_array;
1167static struct mmap_data *mmap_array[MAX_NR_CPUS][MAX_COUNTERS];
1168 1194
1169static void perf_session__mmap_read(struct perf_session *self) 1195static void perf_session__mmap_read(struct perf_session *self)
1170{ 1196{
1171 int i, counter, thread_index; 1197 struct perf_evsel *counter;
1198 int i, thread_index;
1172 1199
1173 for (i = 0; i < nr_cpus; i++) { 1200 for (i = 0; i < cpus->nr; i++) {
1174 for (counter = 0; counter < nr_counters; counter++) 1201 list_for_each_entry(counter, &evsel_list, node) {
1175 for (thread_index = 0; 1202 for (thread_index = 0;
1176 thread_index < thread_num; 1203 thread_index < threads->nr;
1177 thread_index++) { 1204 thread_index++) {
1178 perf_session__mmap_read_counter(self, 1205 perf_session__mmap_read_counter(self,
1179 &mmap_array[i][counter][thread_index]); 1206 counter, i, thread_index);
1180 } 1207 }
1208 }
1181 } 1209 }
1182} 1210}
1183 1211
1184int nr_poll; 1212int nr_poll;
1185int group_fd; 1213int group_fd;
1186 1214
1187static void start_counter(int i, int counter) 1215static void start_counter(int i, struct perf_evsel *evsel)
1188{ 1216{
1217 struct xyarray *mmap_array = evsel->priv;
1218 struct mmap_data *mm;
1189 struct perf_event_attr *attr; 1219 struct perf_event_attr *attr;
1190 int cpu; 1220 int cpu = -1;
1191 int thread_index; 1221 int thread_index;
1192 1222
1193 cpu = profile_cpu; 1223 if (target_tid == -1)
1194 if (target_tid == -1 && profile_cpu == -1) 1224 cpu = cpus->map[i];
1195 cpu = cpumap[i];
1196 1225
1197 attr = attrs + counter; 1226 attr = &evsel->attr;
1198 1227
1199 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID; 1228 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID;
1200 1229
@@ -1207,16 +1236,18 @@ static void start_counter(int i, int counter)
1207 attr->inherit = (cpu < 0) && inherit; 1236 attr->inherit = (cpu < 0) && inherit;
1208 attr->mmap = 1; 1237 attr->mmap = 1;
1209 1238
1210 for (thread_index = 0; thread_index < thread_num; thread_index++) { 1239 for (thread_index = 0; thread_index < threads->nr; thread_index++) {
1211try_again: 1240try_again:
1212 fd[i][counter][thread_index] = sys_perf_event_open(attr, 1241 FD(evsel, i, thread_index) = sys_perf_event_open(attr,
1213 all_tids[thread_index], cpu, group_fd, 0); 1242 threads->map[thread_index], cpu, group_fd, 0);
1214 1243
1215 if (fd[i][counter][thread_index] < 0) { 1244 if (FD(evsel, i, thread_index) < 0) {
1216 int err = errno; 1245 int err = errno;
1217 1246
1218 if (err == EPERM || err == EACCES) 1247 if (err == EPERM || err == EACCES)
1219 die("No permission - are you root?\n"); 1248 die("Permission error - are you root?\n"
1249 "\t Consider tweaking"
1250 " /proc/sys/kernel/perf_event_paranoid.\n");
1220 /* 1251 /*
1221 * If it's cycles then fall back to hrtimer 1252 * If it's cycles then fall back to hrtimer
1222 * based cpu-clock-tick sw counter, which 1253 * based cpu-clock-tick sw counter, which
@@ -1233,30 +1264,30 @@ try_again:
1233 goto try_again; 1264 goto try_again;
1234 } 1265 }
1235 printf("\n"); 1266 printf("\n");
1236 error("perfcounter syscall returned with %d (%s)\n", 1267 error("sys_perf_event_open() syscall returned with %d (%s). /bin/dmesg may provide additional information.\n",
1237 fd[i][counter][thread_index], strerror(err)); 1268 FD(evsel, i, thread_index), strerror(err));
1238 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); 1269 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
1239 exit(-1); 1270 exit(-1);
1240 } 1271 }
1241 assert(fd[i][counter][thread_index] >= 0); 1272 assert(FD(evsel, i, thread_index) >= 0);
1242 fcntl(fd[i][counter][thread_index], F_SETFL, O_NONBLOCK); 1273 fcntl(FD(evsel, i, thread_index), F_SETFL, O_NONBLOCK);
1243 1274
1244 /* 1275 /*
1245 * First counter acts as the group leader: 1276 * First counter acts as the group leader:
1246 */ 1277 */
1247 if (group && group_fd == -1) 1278 if (group && group_fd == -1)
1248 group_fd = fd[i][counter][thread_index]; 1279 group_fd = FD(evsel, i, thread_index);
1249 1280
1250 event_array[nr_poll].fd = fd[i][counter][thread_index]; 1281 event_array[nr_poll].fd = FD(evsel, i, thread_index);
1251 event_array[nr_poll].events = POLLIN; 1282 event_array[nr_poll].events = POLLIN;
1252 nr_poll++; 1283 nr_poll++;
1253 1284
1254 mmap_array[i][counter][thread_index].counter = counter; 1285 mm = xyarray__entry(mmap_array, i, thread_index);
1255 mmap_array[i][counter][thread_index].prev = 0; 1286 mm->prev = 0;
1256 mmap_array[i][counter][thread_index].mask = mmap_pages*page_size - 1; 1287 mm->mask = mmap_pages*page_size - 1;
1257 mmap_array[i][counter][thread_index].base = mmap(NULL, (mmap_pages+1)*page_size, 1288 mm->base = mmap(NULL, (mmap_pages+1)*page_size,
1258 PROT_READ, MAP_SHARED, fd[i][counter][thread_index], 0); 1289 PROT_READ, MAP_SHARED, FD(evsel, i, thread_index), 0);
1259 if (mmap_array[i][counter][thread_index].base == MAP_FAILED) 1290 if (mm->base == MAP_FAILED)
1260 die("failed to mmap with %d (%s)\n", errno, strerror(errno)); 1291 die("failed to mmap with %d (%s)\n", errno, strerror(errno));
1261 } 1292 }
1262} 1293}
@@ -1264,13 +1295,13 @@ try_again:
1264static int __cmd_top(void) 1295static int __cmd_top(void)
1265{ 1296{
1266 pthread_t thread; 1297 pthread_t thread;
1267 int i, counter; 1298 struct perf_evsel *counter;
1268 int ret; 1299 int i, ret;
1269 /* 1300 /*
1270 * FIXME: perf_session__new should allow passing a O_MMAP, so that all this 1301 * FIXME: perf_session__new should allow passing a O_MMAP, so that all this
1271 * mmap reading, etc is encapsulated in it. Use O_WRONLY for now. 1302 * mmap reading, etc is encapsulated in it. Use O_WRONLY for now.
1272 */ 1303 */
1273 struct perf_session *session = perf_session__new(NULL, O_WRONLY, false, false); 1304 struct perf_session *session = perf_session__new(NULL, O_WRONLY, false, false, NULL);
1274 if (session == NULL) 1305 if (session == NULL)
1275 return -ENOMEM; 1306 return -ENOMEM;
1276 1307
@@ -1279,9 +1310,9 @@ static int __cmd_top(void)
1279 else 1310 else
1280 event__synthesize_threads(event__process, session); 1311 event__synthesize_threads(event__process, session);
1281 1312
1282 for (i = 0; i < nr_cpus; i++) { 1313 for (i = 0; i < cpus->nr; i++) {
1283 group_fd = -1; 1314 group_fd = -1;
1284 for (counter = 0; counter < nr_counters; counter++) 1315 list_for_each_entry(counter, &evsel_list, node)
1285 start_counter(i, counter); 1316 start_counter(i, counter);
1286 } 1317 }
1287 1318
@@ -1370,8 +1401,8 @@ static const struct option options[] = {
1370 1401
1371int cmd_top(int argc, const char **argv, const char *prefix __used) 1402int cmd_top(int argc, const char **argv, const char *prefix __used)
1372{ 1403{
1373 int counter; 1404 struct perf_evsel *pos;
1374 int i,j; 1405 int status = -ENOMEM;
1375 1406
1376 page_size = sysconf(_SC_PAGE_SIZE); 1407 page_size = sysconf(_SC_PAGE_SIZE);
1377 1408
@@ -1379,34 +1410,17 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1379 if (argc) 1410 if (argc)
1380 usage_with_options(top_usage, options); 1411 usage_with_options(top_usage, options);
1381 1412
1382 if (target_pid != -1) { 1413 if (target_pid != -1)
1383 target_tid = target_pid; 1414 target_tid = target_pid;
1384 thread_num = find_all_tid(target_pid, &all_tids);
1385 if (thread_num <= 0) {
1386 fprintf(stderr, "Can't find all threads of pid %d\n",
1387 target_pid);
1388 usage_with_options(top_usage, options);
1389 }
1390 } else {
1391 all_tids=malloc(sizeof(pid_t));
1392 if (!all_tids)
1393 return -ENOMEM;
1394 1415
1395 all_tids[0] = target_tid; 1416 threads = thread_map__new(target_pid, target_tid);
1396 thread_num = 1; 1417 if (threads == NULL) {
1418 pr_err("Problems finding threads of monitor\n");
1419 usage_with_options(top_usage, options);
1397 } 1420 }
1398 1421
1399 for (i = 0; i < MAX_NR_CPUS; i++) { 1422 event_array = malloc((sizeof(struct pollfd) *
1400 for (j = 0; j < MAX_COUNTERS; j++) { 1423 MAX_NR_CPUS * MAX_COUNTERS * threads->nr));
1401 fd[i][j] = malloc(sizeof(int)*thread_num);
1402 mmap_array[i][j] = zalloc(
1403 sizeof(struct mmap_data)*thread_num);
1404 if (!fd[i][j] || !mmap_array[i][j])
1405 return -ENOMEM;
1406 }
1407 }
1408 event_array = malloc(
1409 sizeof(struct pollfd)*MAX_NR_CPUS*MAX_COUNTERS*thread_num);
1410 if (!event_array) 1424 if (!event_array)
1411 return -ENOMEM; 1425 return -ENOMEM;
1412 1426
@@ -1417,15 +1431,10 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1417 cpu_list = NULL; 1431 cpu_list = NULL;
1418 } 1432 }
1419 1433
1420 if (!nr_counters) 1434 if (!nr_counters && perf_evsel_list__create_default() < 0) {
1421 nr_counters = 1; 1435 pr_err("Not enough memory for event selector list\n");
1422 1436 return -ENOMEM;
1423 symbol_conf.priv_size = (sizeof(struct sym_entry) + 1437 }
1424 (nr_counters + 1) * sizeof(unsigned long));
1425
1426 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
1427 if (symbol__init() < 0)
1428 return -1;
1429 1438
1430 if (delay_secs < 1) 1439 if (delay_secs < 1)
1431 delay_secs = 1; 1440 delay_secs = 1;
@@ -1442,23 +1451,35 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1442 exit(EXIT_FAILURE); 1451 exit(EXIT_FAILURE);
1443 } 1452 }
1444 1453
1445 /* 1454 if (target_tid != -1)
1446 * Fill in the ones not specifically initialized via -c: 1455 cpus = cpu_map__dummy_new();
1447 */ 1456 else
1448 for (counter = 0; counter < nr_counters; counter++) { 1457 cpus = cpu_map__new(cpu_list);
1449 if (attrs[counter].sample_period) 1458
1459 if (cpus == NULL)
1460 usage_with_options(top_usage, options);
1461
1462 list_for_each_entry(pos, &evsel_list, node) {
1463 if (perf_evsel__alloc_mmap_per_thread(pos, cpus->nr, threads->nr) < 0 ||
1464 perf_evsel__alloc_fd(pos, cpus->nr, threads->nr) < 0)
1465 goto out_free_fd;
1466 /*
1467 * Fill in the ones not specifically initialized via -c:
1468 */
1469 if (pos->attr.sample_period)
1450 continue; 1470 continue;
1451 1471
1452 attrs[counter].sample_period = default_interval; 1472 pos->attr.sample_period = default_interval;
1453 } 1473 }
1454 1474
1455 if (target_tid != -1) 1475 sym_evsel = list_entry(evsel_list.next, struct perf_evsel, node);
1456 nr_cpus = 1;
1457 else
1458 nr_cpus = read_cpu_map(cpu_list);
1459 1476
1460 if (nr_cpus < 1) 1477 symbol_conf.priv_size = (sizeof(struct sym_entry) +
1461 usage_with_options(top_usage, options); 1478 (nr_counters + 1) * sizeof(unsigned long));
1479
1480 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
1481 if (symbol__init() < 0)
1482 return -1;
1462 1483
1463 get_term_dimensions(&winsize); 1484 get_term_dimensions(&winsize);
1464 if (print_entries == 0) { 1485 if (print_entries == 0) {
@@ -1466,5 +1487,11 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1466 signal(SIGWINCH, sig_winch_handler); 1487 signal(SIGWINCH, sig_winch_handler);
1467 } 1488 }
1468 1489
1469 return __cmd_top(); 1490 status = __cmd_top();
1491out_free_fd:
1492 list_for_each_entry(pos, &evsel_list, node)
1493 perf_evsel__free_mmap(pos);
1494 perf_evsel_list__delete();
1495
1496 return status;
1470} 1497}
diff --git a/tools/perf/builtin.h b/tools/perf/builtin.h
index 921245b28583..c7798c7f24ed 100644
--- a/tools/perf/builtin.h
+++ b/tools/perf/builtin.h
@@ -27,7 +27,7 @@ extern int cmd_report(int argc, const char **argv, const char *prefix);
27extern int cmd_stat(int argc, const char **argv, const char *prefix); 27extern int cmd_stat(int argc, const char **argv, const char *prefix);
28extern int cmd_timechart(int argc, const char **argv, const char *prefix); 28extern int cmd_timechart(int argc, const char **argv, const char *prefix);
29extern int cmd_top(int argc, const char **argv, const char *prefix); 29extern int cmd_top(int argc, const char **argv, const char *prefix);
30extern int cmd_trace(int argc, const char **argv, const char *prefix); 30extern int cmd_script(int argc, const char **argv, const char *prefix);
31extern int cmd_version(int argc, const char **argv, const char *prefix); 31extern int cmd_version(int argc, const char **argv, const char *prefix);
32extern int cmd_probe(int argc, const char **argv, const char *prefix); 32extern int cmd_probe(int argc, const char **argv, const char *prefix);
33extern int cmd_kmem(int argc, const char **argv, const char *prefix); 33extern int cmd_kmem(int argc, const char **argv, const char *prefix);
diff --git a/tools/perf/command-list.txt b/tools/perf/command-list.txt
index 949d77fc0b97..16b5088cf8f4 100644
--- a/tools/perf/command-list.txt
+++ b/tools/perf/command-list.txt
@@ -16,7 +16,7 @@ perf-report mainporcelain common
16perf-stat mainporcelain common 16perf-stat mainporcelain common
17perf-timechart mainporcelain common 17perf-timechart mainporcelain common
18perf-top mainporcelain common 18perf-top mainporcelain common
19perf-trace mainporcelain common 19perf-script mainporcelain common
20perf-probe mainporcelain common 20perf-probe mainporcelain common
21perf-kmem mainporcelain common 21perf-kmem mainporcelain common
22perf-lock mainporcelain common 22perf-lock mainporcelain common
diff --git a/tools/perf/feature-tests.mak b/tools/perf/feature-tests.mak
index b253db634f04..b041ca67a2cb 100644
--- a/tools/perf/feature-tests.mak
+++ b/tools/perf/feature-tests.mak
@@ -9,8 +9,8 @@ endef
9ifndef NO_DWARF 9ifndef NO_DWARF
10define SOURCE_DWARF 10define SOURCE_DWARF
11#include <dwarf.h> 11#include <dwarf.h>
12#include <libdw.h> 12#include <elfutils/libdw.h>
13#include <version.h> 13#include <elfutils/version.h>
14#ifndef _ELFUTILS_PREREQ 14#ifndef _ELFUTILS_PREREQ
15#error 15#error
16#endif 16#endif
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index cdd6c03f1e14..595d0f4a7103 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -323,7 +323,7 @@ static void handle_internal_command(int argc, const char **argv)
323 { "top", cmd_top, 0 }, 323 { "top", cmd_top, 0 },
324 { "annotate", cmd_annotate, 0 }, 324 { "annotate", cmd_annotate, 0 },
325 { "version", cmd_version, 0 }, 325 { "version", cmd_version, 0 },
326 { "trace", cmd_trace, 0 }, 326 { "script", cmd_script, 0 },
327 { "sched", cmd_sched, 0 }, 327 { "sched", cmd_sched, 0 },
328 { "probe", cmd_probe, 0 }, 328 { "probe", cmd_probe, 0 },
329 { "kmem", cmd_kmem, 0 }, 329 { "kmem", cmd_kmem, 0 },
diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/Context.c b/tools/perf/scripts/perl/Perf-Trace-Util/Context.c
index 01a64ad693f2..790ceba6ad3f 100644
--- a/tools/perf/scripts/perl/Perf-Trace-Util/Context.c
+++ b/tools/perf/scripts/perl/Perf-Trace-Util/Context.c
@@ -8,7 +8,7 @@
8 8
9#line 1 "Context.xs" 9#line 1 "Context.xs"
10/* 10/*
11 * Context.xs. XS interfaces for perf trace. 11 * Context.xs. XS interfaces for perf script.
12 * 12 *
13 * Copyright (C) 2009 Tom Zanussi <tzanussi@gmail.com> 13 * Copyright (C) 2009 Tom Zanussi <tzanussi@gmail.com>
14 * 14 *
diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/Context.xs b/tools/perf/scripts/perl/Perf-Trace-Util/Context.xs
index 549cf0467d30..c1e2ed1ed34e 100644
--- a/tools/perf/scripts/perl/Perf-Trace-Util/Context.xs
+++ b/tools/perf/scripts/perl/Perf-Trace-Util/Context.xs
@@ -1,5 +1,5 @@
1/* 1/*
2 * Context.xs. XS interfaces for perf trace. 2 * Context.xs. XS interfaces for perf script.
3 * 3 *
4 * Copyright (C) 2009 Tom Zanussi <tzanussi@gmail.com> 4 * Copyright (C) 2009 Tom Zanussi <tzanussi@gmail.com>
5 * 5 *
@@ -23,7 +23,7 @@
23#include "perl.h" 23#include "perl.h"
24#include "XSUB.h" 24#include "XSUB.h"
25#include "../../../perf.h" 25#include "../../../perf.h"
26#include "../../../util/trace-event.h" 26#include "../../../util/script-event.h"
27 27
28MODULE = Perf::Trace::Context PACKAGE = Perf::Trace::Context 28MODULE = Perf::Trace::Context PACKAGE = Perf::Trace::Context
29PROTOTYPES: ENABLE 29PROTOTYPES: ENABLE
diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/README b/tools/perf/scripts/perl/Perf-Trace-Util/README
index 9a9707630791..2f0c7f3043ee 100644
--- a/tools/perf/scripts/perl/Perf-Trace-Util/README
+++ b/tools/perf/scripts/perl/Perf-Trace-Util/README
@@ -1,7 +1,7 @@
1Perf-Trace-Util version 0.01 1Perf-Trace-Util version 0.01
2============================ 2============================
3 3
4This module contains utility functions for use with perf trace. 4This module contains utility functions for use with perf script.
5 5
6Core.pm and Util.pm are pure Perl modules; Core.pm contains routines 6Core.pm and Util.pm are pure Perl modules; Core.pm contains routines
7that the core perf support for Perl calls on and should always be 7that the core perf support for Perl calls on and should always be
@@ -33,7 +33,7 @@ After you do that:
33 33
34INSTALLATION 34INSTALLATION
35 35
36Building perf with perf trace Perl scripting should install this 36Building perf with perf script Perl scripting should install this
37module in the right place. 37module in the right place.
38 38
39You should make sure libperl and ExtUtils/Embed.pm are installed first 39You should make sure libperl and ExtUtils/Embed.pm are installed first
diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Context.pm b/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Context.pm
index 6c7f3659cb17..4e2f6039ac92 100644
--- a/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Context.pm
+++ b/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Context.pm
@@ -34,7 +34,7 @@ Perf::Trace::Context - Perl extension for accessing functions in perf.
34 34
35=head1 SEE ALSO 35=head1 SEE ALSO
36 36
37Perf (trace) documentation 37Perf (script) documentation
38 38
39=head1 AUTHOR 39=head1 AUTHOR
40 40
diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Core.pm b/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Core.pm
index 9df376a9f629..9158458d3eeb 100644
--- a/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Core.pm
+++ b/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Core.pm
@@ -163,7 +163,7 @@ sub dump_symbolic_fields
163__END__ 163__END__
164=head1 NAME 164=head1 NAME
165 165
166Perf::Trace::Core - Perl extension for perf trace 166Perf::Trace::Core - Perl extension for perf script
167 167
168=head1 SYNOPSIS 168=head1 SYNOPSIS
169 169
@@ -171,7 +171,7 @@ Perf::Trace::Core - Perl extension for perf trace
171 171
172=head1 SEE ALSO 172=head1 SEE ALSO
173 173
174Perf (trace) documentation 174Perf (script) documentation
175 175
176=head1 AUTHOR 176=head1 AUTHOR
177 177
diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Util.pm b/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Util.pm
index d94b40c8ac85..053500114625 100644
--- a/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Util.pm
+++ b/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Util.pm
@@ -65,7 +65,7 @@ sub clear_term
65__END__ 65__END__
66=head1 NAME 66=head1 NAME
67 67
68Perf::Trace::Util - Perl extension for perf trace 68Perf::Trace::Util - Perl extension for perf script
69 69
70=head1 SYNOPSIS 70=head1 SYNOPSIS
71 71
@@ -73,7 +73,7 @@ Perf::Trace::Util - Perl extension for perf trace
73 73
74=head1 SEE ALSO 74=head1 SEE ALSO
75 75
76Perf (trace) documentation 76Perf (script) documentation
77 77
78=head1 AUTHOR 78=head1 AUTHOR
79 79
diff --git a/tools/perf/scripts/perl/bin/failed-syscalls-record b/tools/perf/scripts/perl/bin/failed-syscalls-record
index eb5846bcb565..8104895a7b67 100644
--- a/tools/perf/scripts/perl/bin/failed-syscalls-record
+++ b/tools/perf/scripts/perl/bin/failed-syscalls-record
@@ -1,2 +1,2 @@
1#!/bin/bash 1#!/bin/bash
2perf record -a -e raw_syscalls:sys_exit $@ 2perf record -e raw_syscalls:sys_exit $@
diff --git a/tools/perf/scripts/perl/bin/failed-syscalls-report b/tools/perf/scripts/perl/bin/failed-syscalls-report
index 4028d92dc4ae..9f83cc1ad8ba 100644
--- a/tools/perf/scripts/perl/bin/failed-syscalls-report
+++ b/tools/perf/scripts/perl/bin/failed-syscalls-report
@@ -7,4 +7,4 @@ if [ $# -gt 0 ] ; then
7 shift 7 shift
8 fi 8 fi
9fi 9fi
10perf trace $@ -s "$PERF_EXEC_PATH"/scripts/perl/failed-syscalls.pl $comm 10perf script $@ -s "$PERF_EXEC_PATH"/scripts/perl/failed-syscalls.pl $comm
diff --git a/tools/perf/scripts/perl/bin/rw-by-file-record b/tools/perf/scripts/perl/bin/rw-by-file-record
index 5bfaae5a6cba..33efc8673aae 100644
--- a/tools/perf/scripts/perl/bin/rw-by-file-record
+++ b/tools/perf/scripts/perl/bin/rw-by-file-record
@@ -1,3 +1,3 @@
1#!/bin/bash 1#!/bin/bash
2perf record -a -e syscalls:sys_enter_read -e syscalls:sys_enter_write $@ 2perf record -e syscalls:sys_enter_read -e syscalls:sys_enter_write $@
3 3
diff --git a/tools/perf/scripts/perl/bin/rw-by-file-report b/tools/perf/scripts/perl/bin/rw-by-file-report
index ba25f4d41fb0..77200b3f3100 100644
--- a/tools/perf/scripts/perl/bin/rw-by-file-report
+++ b/tools/perf/scripts/perl/bin/rw-by-file-report
@@ -7,7 +7,4 @@ if [ $# -lt 1 ] ; then
7fi 7fi
8comm=$1 8comm=$1
9shift 9shift
10perf trace $@ -s "$PERF_EXEC_PATH"/scripts/perl/rw-by-file.pl $comm 10perf script $@ -s "$PERF_EXEC_PATH"/scripts/perl/rw-by-file.pl $comm
11
12
13
diff --git a/tools/perf/scripts/perl/bin/rw-by-pid-record b/tools/perf/scripts/perl/bin/rw-by-pid-record
index 6e0b2f7755ac..7cb9db230448 100644
--- a/tools/perf/scripts/perl/bin/rw-by-pid-record
+++ b/tools/perf/scripts/perl/bin/rw-by-pid-record
@@ -1,2 +1,2 @@
1#!/bin/bash 1#!/bin/bash
2perf record -a -e syscalls:sys_enter_read -e syscalls:sys_exit_read -e syscalls:sys_enter_write -e syscalls:sys_exit_write $@ 2perf record -e syscalls:sys_enter_read -e syscalls:sys_exit_read -e syscalls:sys_enter_write -e syscalls:sys_exit_write $@
diff --git a/tools/perf/scripts/perl/bin/rw-by-pid-report b/tools/perf/scripts/perl/bin/rw-by-pid-report
index 641a3f5d085c..a27b9f311f95 100644
--- a/tools/perf/scripts/perl/bin/rw-by-pid-report
+++ b/tools/perf/scripts/perl/bin/rw-by-pid-report
@@ -1,6 +1,3 @@
1#!/bin/bash 1#!/bin/bash
2# description: system-wide r/w activity 2# description: system-wide r/w activity
3perf trace $@ -s "$PERF_EXEC_PATH"/scripts/perl/rw-by-pid.pl 3perf script $@ -s "$PERF_EXEC_PATH"/scripts/perl/rw-by-pid.pl
4
5
6
diff --git a/tools/perf/scripts/perl/bin/rwtop-record b/tools/perf/scripts/perl/bin/rwtop-record
index 6e0b2f7755ac..7cb9db230448 100644
--- a/tools/perf/scripts/perl/bin/rwtop-record
+++ b/tools/perf/scripts/perl/bin/rwtop-record
@@ -1,2 +1,2 @@
1#!/bin/bash 1#!/bin/bash
2perf record -a -e syscalls:sys_enter_read -e syscalls:sys_exit_read -e syscalls:sys_enter_write -e syscalls:sys_exit_write $@ 2perf record -e syscalls:sys_enter_read -e syscalls:sys_exit_read -e syscalls:sys_enter_write -e syscalls:sys_exit_write $@
diff --git a/tools/perf/scripts/perl/bin/rwtop-report b/tools/perf/scripts/perl/bin/rwtop-report
index 4918dba77021..83e11ec2e190 100644
--- a/tools/perf/scripts/perl/bin/rwtop-report
+++ b/tools/perf/scripts/perl/bin/rwtop-report
@@ -17,7 +17,4 @@ if [ "$n_args" -gt 0 ] ; then
17 interval=$1 17 interval=$1
18 shift 18 shift
19fi 19fi
20perf trace $@ -s "$PERF_EXEC_PATH"/scripts/perl/rwtop.pl $interval 20perf script $@ -s "$PERF_EXEC_PATH"/scripts/perl/rwtop.pl $interval
21
22
23
diff --git a/tools/perf/scripts/perl/bin/wakeup-latency-record b/tools/perf/scripts/perl/bin/wakeup-latency-record
index 9f2acaaae9f0..464251a1bd7e 100644
--- a/tools/perf/scripts/perl/bin/wakeup-latency-record
+++ b/tools/perf/scripts/perl/bin/wakeup-latency-record
@@ -1,5 +1,5 @@
1#!/bin/bash 1#!/bin/bash
2perf record -a -e sched:sched_switch -e sched:sched_wakeup $@ 2perf record -e sched:sched_switch -e sched:sched_wakeup $@
3 3
4 4
5 5
diff --git a/tools/perf/scripts/perl/bin/wakeup-latency-report b/tools/perf/scripts/perl/bin/wakeup-latency-report
index 49052ebcb632..889e8130cca5 100644
--- a/tools/perf/scripts/perl/bin/wakeup-latency-report
+++ b/tools/perf/scripts/perl/bin/wakeup-latency-report
@@ -1,6 +1,3 @@
1#!/bin/bash 1#!/bin/bash
2# description: system-wide min/max/avg wakeup latency 2# description: system-wide min/max/avg wakeup latency
3perf trace $@ -s "$PERF_EXEC_PATH"/scripts/perl/wakeup-latency.pl 3perf script $@ -s "$PERF_EXEC_PATH"/scripts/perl/wakeup-latency.pl
4
5
6
diff --git a/tools/perf/scripts/perl/bin/workqueue-stats-record b/tools/perf/scripts/perl/bin/workqueue-stats-record
index 85301f2471ff..8edda9078d5d 100644
--- a/tools/perf/scripts/perl/bin/workqueue-stats-record
+++ b/tools/perf/scripts/perl/bin/workqueue-stats-record
@@ -1,2 +1,2 @@
1#!/bin/bash 1#!/bin/bash
2perf record -a -e workqueue:workqueue_creation -e workqueue:workqueue_destruction -e workqueue:workqueue_execution -e workqueue:workqueue_insertion $@ 2perf record -e workqueue:workqueue_creation -e workqueue:workqueue_destruction -e workqueue:workqueue_execution -e workqueue:workqueue_insertion $@
diff --git a/tools/perf/scripts/perl/bin/workqueue-stats-report b/tools/perf/scripts/perl/bin/workqueue-stats-report
index df0c65f4ca93..6d91411d248c 100644
--- a/tools/perf/scripts/perl/bin/workqueue-stats-report
+++ b/tools/perf/scripts/perl/bin/workqueue-stats-report
@@ -1,7 +1,3 @@
1#!/bin/bash 1#!/bin/bash
2# description: workqueue stats (ins/exe/create/destroy) 2# description: workqueue stats (ins/exe/create/destroy)
3perf trace $@ -s "$PERF_EXEC_PATH"/scripts/perl/workqueue-stats.pl 3perf script $@ -s "$PERF_EXEC_PATH"/scripts/perl/workqueue-stats.pl
4
5
6
7
diff --git a/tools/perf/scripts/perl/check-perf-trace.pl b/tools/perf/scripts/perl/check-perf-trace.pl
index 4e7dc0a407a5..4e7076c20616 100644
--- a/tools/perf/scripts/perl/check-perf-trace.pl
+++ b/tools/perf/scripts/perl/check-perf-trace.pl
@@ -1,4 +1,4 @@
1# perf trace event handlers, generated by perf trace -g perl 1# perf script event handlers, generated by perf script -g perl
2# (c) 2009, Tom Zanussi <tzanussi@gmail.com> 2# (c) 2009, Tom Zanussi <tzanussi@gmail.com>
3# Licensed under the terms of the GNU GPL License version 2 3# Licensed under the terms of the GNU GPL License version 2
4 4
diff --git a/tools/perf/scripts/perl/rw-by-file.pl b/tools/perf/scripts/perl/rw-by-file.pl
index 2a39097687b9..74844ee2be3e 100644
--- a/tools/perf/scripts/perl/rw-by-file.pl
+++ b/tools/perf/scripts/perl/rw-by-file.pl
@@ -18,7 +18,7 @@ use lib "./Perf-Trace-Util/lib";
18use Perf::Trace::Core; 18use Perf::Trace::Core;
19use Perf::Trace::Util; 19use Perf::Trace::Util;
20 20
21my $usage = "perf trace -s rw-by-file.pl <comm>\n"; 21my $usage = "perf script -s rw-by-file.pl <comm>\n";
22 22
23my $for_comm = shift or die $usage; 23my $for_comm = shift or die $usage;
24 24
diff --git a/tools/perf/scripts/perl/workqueue-stats.pl b/tools/perf/scripts/perl/workqueue-stats.pl
index b84b12699b70..a8eaff5119e0 100644
--- a/tools/perf/scripts/perl/workqueue-stats.pl
+++ b/tools/perf/scripts/perl/workqueue-stats.pl
@@ -10,7 +10,7 @@
10# workqueue:workqueue_destruction -e workqueue:workqueue_execution 10# workqueue:workqueue_destruction -e workqueue:workqueue_execution
11# -e workqueue:workqueue_insertion 11# -e workqueue:workqueue_insertion
12# 12#
13# perf trace -p -s tools/perf/scripts/perl/workqueue-stats.pl 13# perf script -p -s tools/perf/scripts/perl/workqueue-stats.pl
14 14
15use 5.010000; 15use 5.010000;
16use strict; 16use strict;
diff --git a/tools/perf/scripts/python/Perf-Trace-Util/Context.c b/tools/perf/scripts/python/Perf-Trace-Util/Context.c
index 957085dd5d8d..315067b8f552 100644
--- a/tools/perf/scripts/python/Perf-Trace-Util/Context.c
+++ b/tools/perf/scripts/python/Perf-Trace-Util/Context.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Context.c. Python interfaces for perf trace. 2 * Context.c. Python interfaces for perf script.
3 * 3 *
4 * Copyright (C) 2010 Tom Zanussi <tzanussi@gmail.com> 4 * Copyright (C) 2010 Tom Zanussi <tzanussi@gmail.com>
5 * 5 *
diff --git a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py
index aad7525bca1d..de7211e4fa47 100644
--- a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py
+++ b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py
@@ -1,4 +1,4 @@
1# Core.py - Python extension for perf trace, core functions 1# Core.py - Python extension for perf script, core functions
2# 2#
3# Copyright (C) 2010 by Tom Zanussi <tzanussi@gmail.com> 3# Copyright (C) 2010 by Tom Zanussi <tzanussi@gmail.com>
4# 4#
diff --git a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/SchedGui.py b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/SchedGui.py
index ae9a56e43e05..fdd92f699055 100644
--- a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/SchedGui.py
+++ b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/SchedGui.py
@@ -1,4 +1,4 @@
1# SchedGui.py - Python extension for perf trace, basic GUI code for 1# SchedGui.py - Python extension for perf script, basic GUI code for
2# traces drawing and overview. 2# traces drawing and overview.
3# 3#
4# Copyright (C) 2010 by Frederic Weisbecker <fweisbec@gmail.com> 4# Copyright (C) 2010 by Frederic Weisbecker <fweisbec@gmail.com>
diff --git a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py
index 13cc02b5893a..15c8400240fd 100644
--- a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py
+++ b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py
@@ -1,4 +1,4 @@
1# Util.py - Python extension for perf trace, miscellaneous utility code 1# Util.py - Python extension for perf script, miscellaneous utility code
2# 2#
3# Copyright (C) 2010 by Tom Zanussi <tzanussi@gmail.com> 3# Copyright (C) 2010 by Tom Zanussi <tzanussi@gmail.com>
4# 4#
diff --git a/tools/perf/scripts/python/bin/failed-syscalls-by-pid-record b/tools/perf/scripts/python/bin/failed-syscalls-by-pid-record
index eb5846bcb565..8104895a7b67 100644
--- a/tools/perf/scripts/python/bin/failed-syscalls-by-pid-record
+++ b/tools/perf/scripts/python/bin/failed-syscalls-by-pid-record
@@ -1,2 +1,2 @@
1#!/bin/bash 1#!/bin/bash
2perf record -a -e raw_syscalls:sys_exit $@ 2perf record -e raw_syscalls:sys_exit $@
diff --git a/tools/perf/scripts/python/bin/failed-syscalls-by-pid-report b/tools/perf/scripts/python/bin/failed-syscalls-by-pid-report
index 03587021463d..fda5096d0cbf 100644
--- a/tools/perf/scripts/python/bin/failed-syscalls-by-pid-report
+++ b/tools/perf/scripts/python/bin/failed-syscalls-by-pid-report
@@ -7,4 +7,4 @@ if [ $# -gt 0 ] ; then
7 shift 7 shift
8 fi 8 fi
9fi 9fi
10perf trace $@ -s "$PERF_EXEC_PATH"/scripts/python/failed-syscalls-by-pid.py $comm 10perf script $@ -s "$PERF_EXEC_PATH"/scripts/python/failed-syscalls-by-pid.py $comm
diff --git a/tools/perf/scripts/python/bin/futex-contention-record b/tools/perf/scripts/python/bin/futex-contention-record
index 5ecbb433caf4..b1495c9a9b20 100644
--- a/tools/perf/scripts/python/bin/futex-contention-record
+++ b/tools/perf/scripts/python/bin/futex-contention-record
@@ -1,2 +1,2 @@
1#!/bin/bash 1#!/bin/bash
2perf record -a -e syscalls:sys_enter_futex -e syscalls:sys_exit_futex $@ 2perf record -e syscalls:sys_enter_futex -e syscalls:sys_exit_futex $@
diff --git a/tools/perf/scripts/python/bin/futex-contention-report b/tools/perf/scripts/python/bin/futex-contention-report
index c8268138fb7e..6c44271091ab 100644
--- a/tools/perf/scripts/python/bin/futex-contention-report
+++ b/tools/perf/scripts/python/bin/futex-contention-report
@@ -1,4 +1,4 @@
1#!/bin/bash 1#!/bin/bash
2# description: futext contention measurement 2# description: futext contention measurement
3 3
4perf trace $@ -s "$PERF_EXEC_PATH"/scripts/python/futex-contention.py 4perf script $@ -s "$PERF_EXEC_PATH"/scripts/python/futex-contention.py
diff --git a/tools/perf/scripts/python/bin/netdev-times-record b/tools/perf/scripts/python/bin/netdev-times-record
index d931a828126b..558754b840a9 100644
--- a/tools/perf/scripts/python/bin/netdev-times-record
+++ b/tools/perf/scripts/python/bin/netdev-times-record
@@ -1,5 +1,5 @@
1#!/bin/bash 1#!/bin/bash
2perf record -a -e net:net_dev_xmit -e net:net_dev_queue \ 2perf record -e net:net_dev_xmit -e net:net_dev_queue \
3 -e net:netif_receive_skb -e net:netif_rx \ 3 -e net:netif_receive_skb -e net:netif_rx \
4 -e skb:consume_skb -e skb:kfree_skb \ 4 -e skb:consume_skb -e skb:kfree_skb \
5 -e skb:skb_copy_datagram_iovec -e napi:napi_poll \ 5 -e skb:skb_copy_datagram_iovec -e napi:napi_poll \
diff --git a/tools/perf/scripts/python/bin/netdev-times-report b/tools/perf/scripts/python/bin/netdev-times-report
index 4ad361b31249..8f759291da86 100644
--- a/tools/perf/scripts/python/bin/netdev-times-report
+++ b/tools/perf/scripts/python/bin/netdev-times-report
@@ -2,4 +2,4 @@
2# description: display a process of packet and processing time 2# description: display a process of packet and processing time
3# args: [tx] [rx] [dev=] [debug] 3# args: [tx] [rx] [dev=] [debug]
4 4
5perf trace -s "$PERF_EXEC_PATH"/scripts/python/netdev-times.py $@ 5perf script -s "$PERF_EXEC_PATH"/scripts/python/netdev-times.py $@
diff --git a/tools/perf/scripts/python/bin/sched-migration-record b/tools/perf/scripts/python/bin/sched-migration-record
index 17a3e9bd9e8f..7493fddbe995 100644
--- a/tools/perf/scripts/python/bin/sched-migration-record
+++ b/tools/perf/scripts/python/bin/sched-migration-record
@@ -1,2 +1,2 @@
1#!/bin/bash 1#!/bin/bash
2perf record -m 16384 -a -e sched:sched_wakeup -e sched:sched_wakeup_new -e sched:sched_switch -e sched:sched_migrate_task $@ 2perf record -m 16384 -e sched:sched_wakeup -e sched:sched_wakeup_new -e sched:sched_switch -e sched:sched_migrate_task $@
diff --git a/tools/perf/scripts/python/bin/sched-migration-report b/tools/perf/scripts/python/bin/sched-migration-report
index df1791f07c24..68b037a1849b 100644
--- a/tools/perf/scripts/python/bin/sched-migration-report
+++ b/tools/perf/scripts/python/bin/sched-migration-report
@@ -1,3 +1,3 @@
1#!/bin/bash 1#!/bin/bash
2# description: sched migration overview 2# description: sched migration overview
3perf trace $@ -s "$PERF_EXEC_PATH"/scripts/python/sched-migration.py 3perf script $@ -s "$PERF_EXEC_PATH"/scripts/python/sched-migration.py
diff --git a/tools/perf/scripts/python/bin/sctop-record b/tools/perf/scripts/python/bin/sctop-record
index 1fc5998b721d..4efbfaa7f6a5 100644
--- a/tools/perf/scripts/python/bin/sctop-record
+++ b/tools/perf/scripts/python/bin/sctop-record
@@ -1,2 +1,2 @@
1#!/bin/bash 1#!/bin/bash
2perf record -a -e raw_syscalls:sys_enter $@ 2perf record -e raw_syscalls:sys_enter $@
diff --git a/tools/perf/scripts/python/bin/sctop-report b/tools/perf/scripts/python/bin/sctop-report
index 36b409c05e50..c32db294124d 100644
--- a/tools/perf/scripts/python/bin/sctop-report
+++ b/tools/perf/scripts/python/bin/sctop-report
@@ -21,4 +21,4 @@ elif [ "$n_args" -gt 0 ] ; then
21 interval=$1 21 interval=$1
22 shift 22 shift
23fi 23fi
24perf trace $@ -s "$PERF_EXEC_PATH"/scripts/python/sctop.py $comm $interval 24perf script $@ -s "$PERF_EXEC_PATH"/scripts/python/sctop.py $comm $interval
diff --git a/tools/perf/scripts/python/bin/syscall-counts-by-pid-record b/tools/perf/scripts/python/bin/syscall-counts-by-pid-record
index 1fc5998b721d..4efbfaa7f6a5 100644
--- a/tools/perf/scripts/python/bin/syscall-counts-by-pid-record
+++ b/tools/perf/scripts/python/bin/syscall-counts-by-pid-record
@@ -1,2 +1,2 @@
1#!/bin/bash 1#!/bin/bash
2perf record -a -e raw_syscalls:sys_enter $@ 2perf record -e raw_syscalls:sys_enter $@
diff --git a/tools/perf/scripts/python/bin/syscall-counts-by-pid-report b/tools/perf/scripts/python/bin/syscall-counts-by-pid-report
index 4eb88c9fc83c..16eb8d65c543 100644
--- a/tools/perf/scripts/python/bin/syscall-counts-by-pid-report
+++ b/tools/perf/scripts/python/bin/syscall-counts-by-pid-report
@@ -7,4 +7,4 @@ if [ $# -gt 0 ] ; then
7 shift 7 shift
8 fi 8 fi
9fi 9fi
10perf trace $@ -s "$PERF_EXEC_PATH"/scripts/python/syscall-counts-by-pid.py $comm 10perf script $@ -s "$PERF_EXEC_PATH"/scripts/python/syscall-counts-by-pid.py $comm
diff --git a/tools/perf/scripts/python/bin/syscall-counts-record b/tools/perf/scripts/python/bin/syscall-counts-record
index 1fc5998b721d..4efbfaa7f6a5 100644
--- a/tools/perf/scripts/python/bin/syscall-counts-record
+++ b/tools/perf/scripts/python/bin/syscall-counts-record
@@ -1,2 +1,2 @@
1#!/bin/bash 1#!/bin/bash
2perf record -a -e raw_syscalls:sys_enter $@ 2perf record -e raw_syscalls:sys_enter $@
diff --git a/tools/perf/scripts/python/bin/syscall-counts-report b/tools/perf/scripts/python/bin/syscall-counts-report
index cb2f9c5cf17e..0f0e9d453bb4 100644
--- a/tools/perf/scripts/python/bin/syscall-counts-report
+++ b/tools/perf/scripts/python/bin/syscall-counts-report
@@ -7,4 +7,4 @@ if [ $# -gt 0 ] ; then
7 shift 7 shift
8 fi 8 fi
9fi 9fi
10perf trace $@ -s "$PERF_EXEC_PATH"/scripts/python/syscall-counts.py $comm 10perf script $@ -s "$PERF_EXEC_PATH"/scripts/python/syscall-counts.py $comm
diff --git a/tools/perf/scripts/python/check-perf-trace.py b/tools/perf/scripts/python/check-perf-trace.py
index d9f7893e315c..4647a7694cf6 100644
--- a/tools/perf/scripts/python/check-perf-trace.py
+++ b/tools/perf/scripts/python/check-perf-trace.py
@@ -1,4 +1,4 @@
1# perf trace event handlers, generated by perf trace -g python 1# perf script event handlers, generated by perf script -g python
2# (c) 2010, Tom Zanussi <tzanussi@gmail.com> 2# (c) 2010, Tom Zanussi <tzanussi@gmail.com>
3# Licensed under the terms of the GNU GPL License version 2 3# Licensed under the terms of the GNU GPL License version 2
4# 4#
diff --git a/tools/perf/scripts/python/failed-syscalls-by-pid.py b/tools/perf/scripts/python/failed-syscalls-by-pid.py
index acd7848717b3..85805fac4116 100644
--- a/tools/perf/scripts/python/failed-syscalls-by-pid.py
+++ b/tools/perf/scripts/python/failed-syscalls-by-pid.py
@@ -15,7 +15,7 @@ from perf_trace_context import *
15from Core import * 15from Core import *
16from Util import * 16from Util import *
17 17
18usage = "perf trace -s syscall-counts-by-pid.py [comm|pid]\n"; 18usage = "perf script -s syscall-counts-by-pid.py [comm|pid]\n";
19 19
20for_comm = None 20for_comm = None
21for_pid = None 21for_pid = None
diff --git a/tools/perf/scripts/python/sched-migration.py b/tools/perf/scripts/python/sched-migration.py
index b934383c3364..74d55ec08aed 100644
--- a/tools/perf/scripts/python/sched-migration.py
+++ b/tools/perf/scripts/python/sched-migration.py
@@ -4,7 +4,7 @@
4# 4#
5# Copyright (C) 2010 Frederic Weisbecker <fweisbec@gmail.com> 5# Copyright (C) 2010 Frederic Weisbecker <fweisbec@gmail.com>
6# 6#
7# perf trace event handlers have been generated by perf trace -g python 7# perf script event handlers have been generated by perf script -g python
8# 8#
9# This software is distributed under the terms of the GNU General 9# This software is distributed under the terms of the GNU General
10# Public License ("GPL") version 2 as published by the Free Software 10# Public License ("GPL") version 2 as published by the Free Software
diff --git a/tools/perf/scripts/python/sctop.py b/tools/perf/scripts/python/sctop.py
index 7a6ec2c7d8ab..42c267e292fa 100644
--- a/tools/perf/scripts/python/sctop.py
+++ b/tools/perf/scripts/python/sctop.py
@@ -17,7 +17,7 @@ from perf_trace_context import *
17from Core import * 17from Core import *
18from Util import * 18from Util import *
19 19
20usage = "perf trace -s sctop.py [comm] [interval]\n"; 20usage = "perf script -s sctop.py [comm] [interval]\n";
21 21
22for_comm = None 22for_comm = None
23default_interval = 3 23default_interval = 3
diff --git a/tools/perf/scripts/python/syscall-counts-by-pid.py b/tools/perf/scripts/python/syscall-counts-by-pid.py
index d1ee3ec10cf2..c64d1c55d745 100644
--- a/tools/perf/scripts/python/syscall-counts-by-pid.py
+++ b/tools/perf/scripts/python/syscall-counts-by-pid.py
@@ -14,7 +14,7 @@ from perf_trace_context import *
14from Core import * 14from Core import *
15from Util import syscall_name 15from Util import syscall_name
16 16
17usage = "perf trace -s syscall-counts-by-pid.py [comm]\n"; 17usage = "perf script -s syscall-counts-by-pid.py [comm]\n";
18 18
19for_comm = None 19for_comm = None
20for_pid = None 20for_pid = None
diff --git a/tools/perf/scripts/python/syscall-counts.py b/tools/perf/scripts/python/syscall-counts.py
index ea183dc82d29..b435d3f188e8 100644
--- a/tools/perf/scripts/python/syscall-counts.py
+++ b/tools/perf/scripts/python/syscall-counts.py
@@ -15,7 +15,7 @@ from perf_trace_context import *
15from Core import * 15from Core import *
16from Util import syscall_name 16from Util import syscall_name
17 17
18usage = "perf trace -s syscall-counts.py [comm]\n"; 18usage = "perf script -s syscall-counts.py [comm]\n";
19 19
20for_comm = None 20for_comm = None
21 21
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index e437edb72417..deffb8c96071 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -14,7 +14,9 @@
14#include <linux/kernel.h> 14#include <linux/kernel.h>
15#include "debug.h" 15#include "debug.h"
16 16
17static int build_id__mark_dso_hit(event_t *event, struct perf_session *session) 17static int build_id__mark_dso_hit(event_t *event,
18 struct sample_data *sample __used,
19 struct perf_session *session)
18{ 20{
19 struct addr_location al; 21 struct addr_location al;
20 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 22 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
@@ -35,7 +37,8 @@ static int build_id__mark_dso_hit(event_t *event, struct perf_session *session)
35 return 0; 37 return 0;
36} 38}
37 39
38static int event__exit_del_thread(event_t *self, struct perf_session *session) 40static int event__exit_del_thread(event_t *self, struct sample_data *sample __used,
41 struct perf_session *session)
39{ 42{
40 struct thread *thread = perf_session__findnew(session, self->fork.tid); 43 struct thread *thread = perf_session__findnew(session, self->fork.tid);
41 44
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index 0f9b8d7a7d7e..3ccaa1043383 100644
--- a/tools/perf/util/cpumap.c
+++ b/tools/perf/util/cpumap.c
@@ -4,32 +4,53 @@
4#include <assert.h> 4#include <assert.h>
5#include <stdio.h> 5#include <stdio.h>
6 6
7int cpumap[MAX_NR_CPUS]; 7static struct cpu_map *cpu_map__default_new(void)
8
9static int default_cpu_map(void)
10{ 8{
11 int nr_cpus, i; 9 struct cpu_map *cpus;
10 int nr_cpus;
12 11
13 nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); 12 nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
14 assert(nr_cpus <= MAX_NR_CPUS); 13 if (nr_cpus < 0)
15 assert((int)nr_cpus >= 0); 14 return NULL;
15
16 cpus = malloc(sizeof(*cpus) + nr_cpus * sizeof(int));
17 if (cpus != NULL) {
18 int i;
19 for (i = 0; i < nr_cpus; ++i)
20 cpus->map[i] = i;
16 21
17 for (i = 0; i < nr_cpus; ++i) 22 cpus->nr = nr_cpus;
18 cpumap[i] = i; 23 }
19 24
20 return nr_cpus; 25 return cpus;
21} 26}
22 27
23static int read_all_cpu_map(void) 28static struct cpu_map *cpu_map__trim_new(int nr_cpus, int *tmp_cpus)
24{ 29{
30 size_t payload_size = nr_cpus * sizeof(int);
31 struct cpu_map *cpus = malloc(sizeof(*cpus) + payload_size);
32
33 if (cpus != NULL) {
34 cpus->nr = nr_cpus;
35 memcpy(cpus->map, tmp_cpus, payload_size);
36 }
37
38 return cpus;
39}
40
41static struct cpu_map *cpu_map__read_all_cpu_map(void)
42{
43 struct cpu_map *cpus = NULL;
25 FILE *onlnf; 44 FILE *onlnf;
26 int nr_cpus = 0; 45 int nr_cpus = 0;
46 int *tmp_cpus = NULL, *tmp;
47 int max_entries = 0;
27 int n, cpu, prev; 48 int n, cpu, prev;
28 char sep; 49 char sep;
29 50
30 onlnf = fopen("/sys/devices/system/cpu/online", "r"); 51 onlnf = fopen("/sys/devices/system/cpu/online", "r");
31 if (!onlnf) 52 if (!onlnf)
32 return default_cpu_map(); 53 return cpu_map__default_new();
33 54
34 sep = 0; 55 sep = 0;
35 prev = -1; 56 prev = -1;
@@ -38,12 +59,28 @@ static int read_all_cpu_map(void)
38 if (n <= 0) 59 if (n <= 0)
39 break; 60 break;
40 if (prev >= 0) { 61 if (prev >= 0) {
41 assert(nr_cpus + cpu - prev - 1 < MAX_NR_CPUS); 62 int new_max = nr_cpus + cpu - prev - 1;
63
64 if (new_max >= max_entries) {
65 max_entries = new_max + MAX_NR_CPUS / 2;
66 tmp = realloc(tmp_cpus, max_entries * sizeof(int));
67 if (tmp == NULL)
68 goto out_free_tmp;
69 tmp_cpus = tmp;
70 }
71
42 while (++prev < cpu) 72 while (++prev < cpu)
43 cpumap[nr_cpus++] = prev; 73 tmp_cpus[nr_cpus++] = prev;
74 }
75 if (nr_cpus == max_entries) {
76 max_entries += MAX_NR_CPUS;
77 tmp = realloc(tmp_cpus, max_entries * sizeof(int));
78 if (tmp == NULL)
79 goto out_free_tmp;
80 tmp_cpus = tmp;
44 } 81 }
45 assert (nr_cpus < MAX_NR_CPUS); 82
46 cpumap[nr_cpus++] = cpu; 83 tmp_cpus[nr_cpus++] = cpu;
47 if (n == 2 && sep == '-') 84 if (n == 2 && sep == '-')
48 prev = cpu; 85 prev = cpu;
49 else 86 else
@@ -51,24 +88,31 @@ static int read_all_cpu_map(void)
51 if (n == 1 || sep == '\n') 88 if (n == 1 || sep == '\n')
52 break; 89 break;
53 } 90 }
54 fclose(onlnf);
55 if (nr_cpus > 0)
56 return nr_cpus;
57 91
58 return default_cpu_map(); 92 if (nr_cpus > 0)
93 cpus = cpu_map__trim_new(nr_cpus, tmp_cpus);
94 else
95 cpus = cpu_map__default_new();
96out_free_tmp:
97 free(tmp_cpus);
98 fclose(onlnf);
99 return cpus;
59} 100}
60 101
61int read_cpu_map(const char *cpu_list) 102struct cpu_map *cpu_map__new(const char *cpu_list)
62{ 103{
104 struct cpu_map *cpus = NULL;
63 unsigned long start_cpu, end_cpu = 0; 105 unsigned long start_cpu, end_cpu = 0;
64 char *p = NULL; 106 char *p = NULL;
65 int i, nr_cpus = 0; 107 int i, nr_cpus = 0;
108 int *tmp_cpus = NULL, *tmp;
109 int max_entries = 0;
66 110
67 if (!cpu_list) 111 if (!cpu_list)
68 return read_all_cpu_map(); 112 return cpu_map__read_all_cpu_map();
69 113
70 if (!isdigit(*cpu_list)) 114 if (!isdigit(*cpu_list))
71 goto invalid; 115 goto out;
72 116
73 while (isdigit(*cpu_list)) { 117 while (isdigit(*cpu_list)) {
74 p = NULL; 118 p = NULL;
@@ -94,21 +138,42 @@ int read_cpu_map(const char *cpu_list)
94 for (; start_cpu <= end_cpu; start_cpu++) { 138 for (; start_cpu <= end_cpu; start_cpu++) {
95 /* check for duplicates */ 139 /* check for duplicates */
96 for (i = 0; i < nr_cpus; i++) 140 for (i = 0; i < nr_cpus; i++)
97 if (cpumap[i] == (int)start_cpu) 141 if (tmp_cpus[i] == (int)start_cpu)
98 goto invalid; 142 goto invalid;
99 143
100 assert(nr_cpus < MAX_NR_CPUS); 144 if (nr_cpus == max_entries) {
101 cpumap[nr_cpus++] = (int)start_cpu; 145 max_entries += MAX_NR_CPUS;
146 tmp = realloc(tmp_cpus, max_entries * sizeof(int));
147 if (tmp == NULL)
148 goto invalid;
149 tmp_cpus = tmp;
150 }
151 tmp_cpus[nr_cpus++] = (int)start_cpu;
102 } 152 }
103 if (*p) 153 if (*p)
104 ++p; 154 ++p;
105 155
106 cpu_list = p; 156 cpu_list = p;
107 } 157 }
108 if (nr_cpus > 0)
109 return nr_cpus;
110 158
111 return default_cpu_map(); 159 if (nr_cpus > 0)
160 cpus = cpu_map__trim_new(nr_cpus, tmp_cpus);
161 else
162 cpus = cpu_map__default_new();
112invalid: 163invalid:
113 return -1; 164 free(tmp_cpus);
165out:
166 return cpus;
167}
168
169struct cpu_map *cpu_map__dummy_new(void)
170{
171 struct cpu_map *cpus = malloc(sizeof(*cpus) + sizeof(int));
172
173 if (cpus != NULL) {
174 cpus->nr = 1;
175 cpus->map[0] = -1;
176 }
177
178 return cpus;
114} 179}
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
index 3e60f56e490e..f7a4f42f6307 100644
--- a/tools/perf/util/cpumap.h
+++ b/tools/perf/util/cpumap.h
@@ -1,7 +1,13 @@
1#ifndef __PERF_CPUMAP_H 1#ifndef __PERF_CPUMAP_H
2#define __PERF_CPUMAP_H 2#define __PERF_CPUMAP_H
3 3
4extern int read_cpu_map(const char *cpu_list); 4struct cpu_map {
5extern int cpumap[]; 5 int nr;
6 int map[];
7};
8
9struct cpu_map *cpu_map__new(const char *cpu_list);
10struct cpu_map *cpu_map__dummy_new(void);
11void *cpu_map__delete(struct cpu_map *map);
6 12
7#endif /* __PERF_CPUMAP_H */ 13#endif /* __PERF_CPUMAP_H */
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index c8d81b00089d..01bbe8ecec3f 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -46,20 +46,16 @@ int dump_printf(const char *fmt, ...)
46 return ret; 46 return ret;
47} 47}
48 48
49static int dump_printf_color(const char *fmt, const char *color, ...) 49#ifdef NO_NEWT_SUPPORT
50void ui__warning(const char *format, ...)
50{ 51{
51 va_list args; 52 va_list args;
52 int ret = 0;
53 53
54 if (dump_trace) { 54 va_start(args, format);
55 va_start(args, color); 55 vfprintf(stderr, format, args);
56 ret = color_vfprintf(stdout, color, fmt, args); 56 va_end(args);
57 va_end(args);
58 }
59
60 return ret;
61} 57}
62 58#endif
63 59
64void trace_event(event_t *event) 60void trace_event(event_t *event)
65{ 61{
@@ -70,29 +66,29 @@ void trace_event(event_t *event)
70 if (!dump_trace) 66 if (!dump_trace)
71 return; 67 return;
72 68
73 dump_printf("."); 69 printf(".");
74 dump_printf_color("\n. ... raw event: size %d bytes\n", color, 70 color_fprintf(stdout, color, "\n. ... raw event: size %d bytes\n",
75 event->header.size); 71 event->header.size);
76 72
77 for (i = 0; i < event->header.size; i++) { 73 for (i = 0; i < event->header.size; i++) {
78 if ((i & 15) == 0) { 74 if ((i & 15) == 0) {
79 dump_printf("."); 75 printf(".");
80 dump_printf_color(" %04x: ", color, i); 76 color_fprintf(stdout, color, " %04x: ", i);
81 } 77 }
82 78
83 dump_printf_color(" %02x", color, raw_event[i]); 79 color_fprintf(stdout, color, " %02x", raw_event[i]);
84 80
85 if (((i & 15) == 15) || i == event->header.size-1) { 81 if (((i & 15) == 15) || i == event->header.size-1) {
86 dump_printf_color(" ", color); 82 color_fprintf(stdout, color, " ");
87 for (j = 0; j < 15-(i & 15); j++) 83 for (j = 0; j < 15-(i & 15); j++)
88 dump_printf_color(" ", color); 84 color_fprintf(stdout, color, " ");
89 for (j = i & ~15; j <= i; j++) { 85 for (j = i & ~15; j <= i; j++) {
90 dump_printf_color("%c", color, 86 color_fprintf(stdout, color, "%c",
91 isprint(raw_event[j]) ? 87 isprint(raw_event[j]) ?
92 raw_event[j] : '.'); 88 raw_event[j] : '.');
93 } 89 }
94 dump_printf_color("\n", color); 90 color_fprintf(stdout, color, "\n");
95 } 91 }
96 } 92 }
97 dump_printf(".\n"); 93 printf(".\n");
98} 94}
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index 7b514082bbaf..ca35fd66b5df 100644
--- a/tools/perf/util/debug.h
+++ b/tools/perf/util/debug.h
@@ -35,4 +35,6 @@ int ui_helpline__show_help(const char *format, va_list ap);
35#include "ui/progress.h" 35#include "ui/progress.h"
36#endif 36#endif
37 37
38void ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2)));
39
38#endif /* __PERF_DEBUG_H */ 40#endif /* __PERF_DEBUG_H */
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index dab9e754a281..1478ab4ee222 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -7,7 +7,7 @@
7#include "strlist.h" 7#include "strlist.h"
8#include "thread.h" 8#include "thread.h"
9 9
10const char *event__name[] = { 10static const char *event__name[] = {
11 [0] = "TOTAL", 11 [0] = "TOTAL",
12 [PERF_RECORD_MMAP] = "MMAP", 12 [PERF_RECORD_MMAP] = "MMAP",
13 [PERF_RECORD_LOST] = "LOST", 13 [PERF_RECORD_LOST] = "LOST",
@@ -22,13 +22,31 @@ const char *event__name[] = {
22 [PERF_RECORD_HEADER_EVENT_TYPE] = "EVENT_TYPE", 22 [PERF_RECORD_HEADER_EVENT_TYPE] = "EVENT_TYPE",
23 [PERF_RECORD_HEADER_TRACING_DATA] = "TRACING_DATA", 23 [PERF_RECORD_HEADER_TRACING_DATA] = "TRACING_DATA",
24 [PERF_RECORD_HEADER_BUILD_ID] = "BUILD_ID", 24 [PERF_RECORD_HEADER_BUILD_ID] = "BUILD_ID",
25 [PERF_RECORD_FINISHED_ROUND] = "FINISHED_ROUND",
25}; 26};
26 27
27static pid_t event__synthesize_comm(pid_t pid, int full, 28const char *event__get_event_name(unsigned int id)
29{
30 if (id >= ARRAY_SIZE(event__name))
31 return "INVALID";
32 if (!event__name[id])
33 return "UNKNOWN";
34 return event__name[id];
35}
36
37static struct sample_data synth_sample = {
38 .pid = -1,
39 .tid = -1,
40 .time = -1,
41 .stream_id = -1,
42 .cpu = -1,
43 .period = 1,
44};
45
46static pid_t event__synthesize_comm(event_t *event, pid_t pid, int full,
28 event__handler_t process, 47 event__handler_t process,
29 struct perf_session *session) 48 struct perf_session *session)
30{ 49{
31 event_t ev;
32 char filename[PATH_MAX]; 50 char filename[PATH_MAX];
33 char bf[BUFSIZ]; 51 char bf[BUFSIZ];
34 FILE *fp; 52 FILE *fp;
@@ -49,34 +67,39 @@ out_race:
49 return 0; 67 return 0;
50 } 68 }
51 69
52 memset(&ev.comm, 0, sizeof(ev.comm)); 70 memset(&event->comm, 0, sizeof(event->comm));
53 while (!ev.comm.comm[0] || !ev.comm.pid) { 71
54 if (fgets(bf, sizeof(bf), fp) == NULL) 72 while (!event->comm.comm[0] || !event->comm.pid) {
55 goto out_failure; 73 if (fgets(bf, sizeof(bf), fp) == NULL) {
74 pr_warning("couldn't get COMM and pgid, malformed %s\n", filename);
75 goto out;
76 }
56 77
57 if (memcmp(bf, "Name:", 5) == 0) { 78 if (memcmp(bf, "Name:", 5) == 0) {
58 char *name = bf + 5; 79 char *name = bf + 5;
59 while (*name && isspace(*name)) 80 while (*name && isspace(*name))
60 ++name; 81 ++name;
61 size = strlen(name) - 1; 82 size = strlen(name) - 1;
62 memcpy(ev.comm.comm, name, size++); 83 memcpy(event->comm.comm, name, size++);
63 } else if (memcmp(bf, "Tgid:", 5) == 0) { 84 } else if (memcmp(bf, "Tgid:", 5) == 0) {
64 char *tgids = bf + 5; 85 char *tgids = bf + 5;
65 while (*tgids && isspace(*tgids)) 86 while (*tgids && isspace(*tgids))
66 ++tgids; 87 ++tgids;
67 tgid = ev.comm.pid = atoi(tgids); 88 tgid = event->comm.pid = atoi(tgids);
68 } 89 }
69 } 90 }
70 91
71 ev.comm.header.type = PERF_RECORD_COMM; 92 event->comm.header.type = PERF_RECORD_COMM;
72 size = ALIGN(size, sizeof(u64)); 93 size = ALIGN(size, sizeof(u64));
73 ev.comm.header.size = sizeof(ev.comm) - (sizeof(ev.comm.comm) - size); 94 memset(event->comm.comm + size, 0, session->id_hdr_size);
74 95 event->comm.header.size = (sizeof(event->comm) -
96 (sizeof(event->comm.comm) - size) +
97 session->id_hdr_size);
75 if (!full) { 98 if (!full) {
76 ev.comm.tid = pid; 99 event->comm.tid = pid;
77 100
78 process(&ev, session); 101 process(event, &synth_sample, session);
79 goto out_fclose; 102 goto out;
80 } 103 }
81 104
82 snprintf(filename, sizeof(filename), "/proc/%d/task", pid); 105 snprintf(filename, sizeof(filename), "/proc/%d/task", pid);
@@ -91,22 +114,19 @@ out_race:
91 if (*end) 114 if (*end)
92 continue; 115 continue;
93 116
94 ev.comm.tid = pid; 117 event->comm.tid = pid;
95 118
96 process(&ev, session); 119 process(event, &synth_sample, session);
97 } 120 }
98 closedir(tasks);
99 121
100out_fclose: 122 closedir(tasks);
123out:
101 fclose(fp); 124 fclose(fp);
102 return tgid;
103 125
104out_failure: 126 return tgid;
105 pr_warning("couldn't get COMM and pgid, malformed %s\n", filename);
106 return -1;
107} 127}
108 128
109static int event__synthesize_mmap_events(pid_t pid, pid_t tgid, 129static int event__synthesize_mmap_events(event_t *event, pid_t pid, pid_t tgid,
110 event__handler_t process, 130 event__handler_t process,
111 struct perf_session *session) 131 struct perf_session *session)
112{ 132{
@@ -124,29 +144,25 @@ static int event__synthesize_mmap_events(pid_t pid, pid_t tgid,
124 return -1; 144 return -1;
125 } 145 }
126 146
147 event->header.type = PERF_RECORD_MMAP;
148 /*
149 * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c
150 */
151 event->header.misc = PERF_RECORD_MISC_USER;
152
127 while (1) { 153 while (1) {
128 char bf[BUFSIZ], *pbf = bf; 154 char bf[BUFSIZ], *pbf = bf;
129 event_t ev = {
130 .header = {
131 .type = PERF_RECORD_MMAP,
132 /*
133 * Just like the kernel, see __perf_event_mmap
134 * in kernel/perf_event.c
135 */
136 .misc = PERF_RECORD_MISC_USER,
137 },
138 };
139 int n; 155 int n;
140 size_t size; 156 size_t size;
141 if (fgets(bf, sizeof(bf), fp) == NULL) 157 if (fgets(bf, sizeof(bf), fp) == NULL)
142 break; 158 break;
143 159
144 /* 00400000-0040c000 r-xp 00000000 fd:01 41038 /bin/cat */ 160 /* 00400000-0040c000 r-xp 00000000 fd:01 41038 /bin/cat */
145 n = hex2u64(pbf, &ev.mmap.start); 161 n = hex2u64(pbf, &event->mmap.start);
146 if (n < 0) 162 if (n < 0)
147 continue; 163 continue;
148 pbf += n + 1; 164 pbf += n + 1;
149 n = hex2u64(pbf, &ev.mmap.len); 165 n = hex2u64(pbf, &event->mmap.len);
150 if (n < 0) 166 if (n < 0)
151 continue; 167 continue;
152 pbf += n + 3; 168 pbf += n + 3;
@@ -161,19 +177,21 @@ static int event__synthesize_mmap_events(pid_t pid, pid_t tgid,
161 continue; 177 continue;
162 178
163 pbf += 3; 179 pbf += 3;
164 n = hex2u64(pbf, &ev.mmap.pgoff); 180 n = hex2u64(pbf, &event->mmap.pgoff);
165 181
166 size = strlen(execname); 182 size = strlen(execname);
167 execname[size - 1] = '\0'; /* Remove \n */ 183 execname[size - 1] = '\0'; /* Remove \n */
168 memcpy(ev.mmap.filename, execname, size); 184 memcpy(event->mmap.filename, execname, size);
169 size = ALIGN(size, sizeof(u64)); 185 size = ALIGN(size, sizeof(u64));
170 ev.mmap.len -= ev.mmap.start; 186 event->mmap.len -= event->mmap.start;
171 ev.mmap.header.size = (sizeof(ev.mmap) - 187 event->mmap.header.size = (sizeof(event->mmap) -
172 (sizeof(ev.mmap.filename) - size)); 188 (sizeof(event->mmap.filename) - size));
173 ev.mmap.pid = tgid; 189 memset(event->mmap.filename + size, 0, session->id_hdr_size);
174 ev.mmap.tid = pid; 190 event->mmap.header.size += session->id_hdr_size;
175 191 event->mmap.pid = tgid;
176 process(&ev, session); 192 event->mmap.tid = pid;
193
194 process(event, &synth_sample, session);
177 } 195 }
178 } 196 }
179 197
@@ -187,20 +205,27 @@ int event__synthesize_modules(event__handler_t process,
187{ 205{
188 struct rb_node *nd; 206 struct rb_node *nd;
189 struct map_groups *kmaps = &machine->kmaps; 207 struct map_groups *kmaps = &machine->kmaps;
190 u16 misc; 208 event_t *event = zalloc(sizeof(event->mmap) + session->id_hdr_size);
209
210 if (event == NULL) {
211 pr_debug("Not enough memory synthesizing mmap event "
212 "for kernel modules\n");
213 return -1;
214 }
215
216 event->header.type = PERF_RECORD_MMAP;
191 217
192 /* 218 /*
193 * kernel uses 0 for user space maps, see kernel/perf_event.c 219 * kernel uses 0 for user space maps, see kernel/perf_event.c
194 * __perf_event_mmap 220 * __perf_event_mmap
195 */ 221 */
196 if (machine__is_host(machine)) 222 if (machine__is_host(machine))
197 misc = PERF_RECORD_MISC_KERNEL; 223 event->header.misc = PERF_RECORD_MISC_KERNEL;
198 else 224 else
199 misc = PERF_RECORD_MISC_GUEST_KERNEL; 225 event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL;
200 226
201 for (nd = rb_first(&kmaps->maps[MAP__FUNCTION]); 227 for (nd = rb_first(&kmaps->maps[MAP__FUNCTION]);
202 nd; nd = rb_next(nd)) { 228 nd; nd = rb_next(nd)) {
203 event_t ev;
204 size_t size; 229 size_t size;
205 struct map *pos = rb_entry(nd, struct map, rb_node); 230 struct map *pos = rb_entry(nd, struct map, rb_node);
206 231
@@ -208,39 +233,78 @@ int event__synthesize_modules(event__handler_t process,
208 continue; 233 continue;
209 234
210 size = ALIGN(pos->dso->long_name_len + 1, sizeof(u64)); 235 size = ALIGN(pos->dso->long_name_len + 1, sizeof(u64));
211 memset(&ev, 0, sizeof(ev)); 236 event->mmap.header.type = PERF_RECORD_MMAP;
212 ev.mmap.header.misc = misc; 237 event->mmap.header.size = (sizeof(event->mmap) -
213 ev.mmap.header.type = PERF_RECORD_MMAP; 238 (sizeof(event->mmap.filename) - size));
214 ev.mmap.header.size = (sizeof(ev.mmap) - 239 memset(event->mmap.filename + size, 0, session->id_hdr_size);
215 (sizeof(ev.mmap.filename) - size)); 240 event->mmap.header.size += session->id_hdr_size;
216 ev.mmap.start = pos->start; 241 event->mmap.start = pos->start;
217 ev.mmap.len = pos->end - pos->start; 242 event->mmap.len = pos->end - pos->start;
218 ev.mmap.pid = machine->pid; 243 event->mmap.pid = machine->pid;
219 244
220 memcpy(ev.mmap.filename, pos->dso->long_name, 245 memcpy(event->mmap.filename, pos->dso->long_name,
221 pos->dso->long_name_len + 1); 246 pos->dso->long_name_len + 1);
222 process(&ev, session); 247 process(event, &synth_sample, session);
223 } 248 }
224 249
250 free(event);
225 return 0; 251 return 0;
226} 252}
227 253
228int event__synthesize_thread(pid_t pid, event__handler_t process, 254static int __event__synthesize_thread(event_t *comm_event, event_t *mmap_event,
229 struct perf_session *session) 255 pid_t pid, event__handler_t process,
256 struct perf_session *session)
230{ 257{
231 pid_t tgid = event__synthesize_comm(pid, 1, process, session); 258 pid_t tgid = event__synthesize_comm(comm_event, pid, 1, process,
259 session);
232 if (tgid == -1) 260 if (tgid == -1)
233 return -1; 261 return -1;
234 return event__synthesize_mmap_events(pid, tgid, process, session); 262 return event__synthesize_mmap_events(mmap_event, pid, tgid,
263 process, session);
264}
265
266int event__synthesize_thread(pid_t pid, event__handler_t process,
267 struct perf_session *session)
268{
269 event_t *comm_event, *mmap_event;
270 int err = -1;
271
272 comm_event = malloc(sizeof(comm_event->comm) + session->id_hdr_size);
273 if (comm_event == NULL)
274 goto out;
275
276 mmap_event = malloc(sizeof(mmap_event->mmap) + session->id_hdr_size);
277 if (mmap_event == NULL)
278 goto out_free_comm;
279
280 err = __event__synthesize_thread(comm_event, mmap_event, pid,
281 process, session);
282 free(mmap_event);
283out_free_comm:
284 free(comm_event);
285out:
286 return err;
235} 287}
236 288
237void event__synthesize_threads(event__handler_t process, 289int event__synthesize_threads(event__handler_t process,
238 struct perf_session *session) 290 struct perf_session *session)
239{ 291{
240 DIR *proc; 292 DIR *proc;
241 struct dirent dirent, *next; 293 struct dirent dirent, *next;
294 event_t *comm_event, *mmap_event;
295 int err = -1;
296
297 comm_event = malloc(sizeof(comm_event->comm) + session->id_hdr_size);
298 if (comm_event == NULL)
299 goto out;
300
301 mmap_event = malloc(sizeof(mmap_event->mmap) + session->id_hdr_size);
302 if (mmap_event == NULL)
303 goto out_free_comm;
242 304
243 proc = opendir("/proc"); 305 proc = opendir("/proc");
306 if (proc == NULL)
307 goto out_free_mmap;
244 308
245 while (!readdir_r(proc, &dirent, &next) && next) { 309 while (!readdir_r(proc, &dirent, &next) && next) {
246 char *end; 310 char *end;
@@ -249,10 +313,18 @@ void event__synthesize_threads(event__handler_t process,
249 if (*end) /* only interested in proper numerical dirents */ 313 if (*end) /* only interested in proper numerical dirents */
250 continue; 314 continue;
251 315
252 event__synthesize_thread(pid, process, session); 316 __event__synthesize_thread(comm_event, mmap_event, pid,
317 process, session);
253 } 318 }
254 319
255 closedir(proc); 320 closedir(proc);
321 err = 0;
322out_free_mmap:
323 free(mmap_event);
324out_free_comm:
325 free(comm_event);
326out:
327 return err;
256} 328}
257 329
258struct process_symbol_args { 330struct process_symbol_args {
@@ -260,7 +332,8 @@ struct process_symbol_args {
260 u64 start; 332 u64 start;
261}; 333};
262 334
263static int find_symbol_cb(void *arg, const char *name, char type, u64 start) 335static int find_symbol_cb(void *arg, const char *name, char type,
336 u64 start, u64 end __used)
264{ 337{
265 struct process_symbol_args *args = arg; 338 struct process_symbol_args *args = arg;
266 339
@@ -286,18 +359,20 @@ int event__synthesize_kernel_mmap(event__handler_t process,
286 char path[PATH_MAX]; 359 char path[PATH_MAX];
287 char name_buff[PATH_MAX]; 360 char name_buff[PATH_MAX];
288 struct map *map; 361 struct map *map;
289 362 int err;
290 event_t ev = {
291 .header = {
292 .type = PERF_RECORD_MMAP,
293 },
294 };
295 /* 363 /*
296 * We should get this from /sys/kernel/sections/.text, but till that is 364 * We should get this from /sys/kernel/sections/.text, but till that is
297 * available use this, and after it is use this as a fallback for older 365 * available use this, and after it is use this as a fallback for older
298 * kernels. 366 * kernels.
299 */ 367 */
300 struct process_symbol_args args = { .name = symbol_name, }; 368 struct process_symbol_args args = { .name = symbol_name, };
369 event_t *event = zalloc(sizeof(event->mmap) + session->id_hdr_size);
370
371 if (event == NULL) {
372 pr_debug("Not enough memory synthesizing mmap event "
373 "for kernel modules\n");
374 return -1;
375 }
301 376
302 mmap_name = machine__mmap_name(machine, name_buff, sizeof(name_buff)); 377 mmap_name = machine__mmap_name(machine, name_buff, sizeof(name_buff));
303 if (machine__is_host(machine)) { 378 if (machine__is_host(machine)) {
@@ -305,10 +380,10 @@ int event__synthesize_kernel_mmap(event__handler_t process,
305 * kernel uses PERF_RECORD_MISC_USER for user space maps, 380 * kernel uses PERF_RECORD_MISC_USER for user space maps,
306 * see kernel/perf_event.c __perf_event_mmap 381 * see kernel/perf_event.c __perf_event_mmap
307 */ 382 */
308 ev.header.misc = PERF_RECORD_MISC_KERNEL; 383 event->header.misc = PERF_RECORD_MISC_KERNEL;
309 filename = "/proc/kallsyms"; 384 filename = "/proc/kallsyms";
310 } else { 385 } else {
311 ev.header.misc = PERF_RECORD_MISC_GUEST_KERNEL; 386 event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL;
312 if (machine__is_default_guest(machine)) 387 if (machine__is_default_guest(machine))
313 filename = (char *) symbol_conf.default_guest_kallsyms; 388 filename = (char *) symbol_conf.default_guest_kallsyms;
314 else { 389 else {
@@ -321,17 +396,21 @@ int event__synthesize_kernel_mmap(event__handler_t process,
321 return -ENOENT; 396 return -ENOENT;
322 397
323 map = machine->vmlinux_maps[MAP__FUNCTION]; 398 map = machine->vmlinux_maps[MAP__FUNCTION];
324 size = snprintf(ev.mmap.filename, sizeof(ev.mmap.filename), 399 size = snprintf(event->mmap.filename, sizeof(event->mmap.filename),
325 "%s%s", mmap_name, symbol_name) + 1; 400 "%s%s", mmap_name, symbol_name) + 1;
326 size = ALIGN(size, sizeof(u64)); 401 size = ALIGN(size, sizeof(u64));
327 ev.mmap.header.size = (sizeof(ev.mmap) - 402 event->mmap.header.type = PERF_RECORD_MMAP;
328 (sizeof(ev.mmap.filename) - size)); 403 event->mmap.header.size = (sizeof(event->mmap) -
329 ev.mmap.pgoff = args.start; 404 (sizeof(event->mmap.filename) - size) + session->id_hdr_size);
330 ev.mmap.start = map->start; 405 event->mmap.pgoff = args.start;
331 ev.mmap.len = map->end - ev.mmap.start; 406 event->mmap.start = map->start;
332 ev.mmap.pid = machine->pid; 407 event->mmap.len = map->end - event->mmap.start;
333 408 event->mmap.pid = machine->pid;
334 return process(&ev, session); 409
410 err = process(event, &synth_sample, session);
411 free(event);
412
413 return err;
335} 414}
336 415
337static void thread__comm_adjust(struct thread *self, struct hists *hists) 416static void thread__comm_adjust(struct thread *self, struct hists *hists)
@@ -361,7 +440,8 @@ static int thread__set_comm_adjust(struct thread *self, const char *comm,
361 return 0; 440 return 0;
362} 441}
363 442
364int event__process_comm(event_t *self, struct perf_session *session) 443int event__process_comm(event_t *self, struct sample_data *sample __used,
444 struct perf_session *session)
365{ 445{
366 struct thread *thread = perf_session__findnew(session, self->comm.tid); 446 struct thread *thread = perf_session__findnew(session, self->comm.tid);
367 447
@@ -376,9 +456,11 @@ int event__process_comm(event_t *self, struct perf_session *session)
376 return 0; 456 return 0;
377} 457}
378 458
379int event__process_lost(event_t *self, struct perf_session *session) 459int event__process_lost(event_t *self, struct sample_data *sample __used,
460 struct perf_session *session)
380{ 461{
381 dump_printf(": id:%Ld: lost:%Ld\n", self->lost.id, self->lost.lost); 462 dump_printf(": id:%" PRIu64 ": lost:%" PRIu64 "\n",
463 self->lost.id, self->lost.lost);
382 session->hists.stats.total_lost += self->lost.lost; 464 session->hists.stats.total_lost += self->lost.lost;
383 return 0; 465 return 0;
384} 466}
@@ -392,7 +474,7 @@ static void event_set_kernel_mmap_len(struct map **maps, event_t *self)
392 * a zero sized synthesized MMAP event for the kernel. 474 * a zero sized synthesized MMAP event for the kernel.
393 */ 475 */
394 if (maps[MAP__FUNCTION]->end == 0) 476 if (maps[MAP__FUNCTION]->end == 0)
395 maps[MAP__FUNCTION]->end = ~0UL; 477 maps[MAP__FUNCTION]->end = ~0ULL;
396} 478}
397 479
398static int event__process_kernel_mmap(event_t *self, 480static int event__process_kernel_mmap(event_t *self,
@@ -485,7 +567,8 @@ out_problem:
485 return -1; 567 return -1;
486} 568}
487 569
488int event__process_mmap(event_t *self, struct perf_session *session) 570int event__process_mmap(event_t *self, struct sample_data *sample __used,
571 struct perf_session *session)
489{ 572{
490 struct machine *machine; 573 struct machine *machine;
491 struct thread *thread; 574 struct thread *thread;
@@ -493,7 +576,7 @@ int event__process_mmap(event_t *self, struct perf_session *session)
493 u8 cpumode = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 576 u8 cpumode = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
494 int ret = 0; 577 int ret = 0;
495 578
496 dump_printf(" %d/%d: [%#Lx(%#Lx) @ %#Lx]: %s\n", 579 dump_printf(" %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 "]: %s\n",
497 self->mmap.pid, self->mmap.tid, self->mmap.start, 580 self->mmap.pid, self->mmap.tid, self->mmap.start,
498 self->mmap.len, self->mmap.pgoff, self->mmap.filename); 581 self->mmap.len, self->mmap.pgoff, self->mmap.filename);
499 582
@@ -526,7 +609,8 @@ out_problem:
526 return 0; 609 return 0;
527} 610}
528 611
529int event__process_task(event_t *self, struct perf_session *session) 612int event__process_task(event_t *self, struct sample_data *sample __used,
613 struct perf_session *session)
530{ 614{
531 struct thread *thread = perf_session__findnew(session, self->fork.tid); 615 struct thread *thread = perf_session__findnew(session, self->fork.tid);
532 struct thread *parent = perf_session__findnew(session, self->fork.ptid); 616 struct thread *parent = perf_session__findnew(session, self->fork.ptid);
@@ -548,18 +632,19 @@ int event__process_task(event_t *self, struct perf_session *session)
548 return 0; 632 return 0;
549} 633}
550 634
551int event__process(event_t *event, struct perf_session *session) 635int event__process(event_t *event, struct sample_data *sample,
636 struct perf_session *session)
552{ 637{
553 switch (event->header.type) { 638 switch (event->header.type) {
554 case PERF_RECORD_COMM: 639 case PERF_RECORD_COMM:
555 event__process_comm(event, session); 640 event__process_comm(event, sample, session);
556 break; 641 break;
557 case PERF_RECORD_MMAP: 642 case PERF_RECORD_MMAP:
558 event__process_mmap(event, session); 643 event__process_mmap(event, sample, session);
559 break; 644 break;
560 case PERF_RECORD_FORK: 645 case PERF_RECORD_FORK:
561 case PERF_RECORD_EXIT: 646 case PERF_RECORD_EXIT:
562 event__process_task(event, session); 647 event__process_task(event, sample, session);
563 break; 648 break;
564 default: 649 default:
565 break; 650 break;
@@ -674,32 +759,8 @@ int event__preprocess_sample(const event_t *self, struct perf_session *session,
674 symbol_filter_t filter) 759 symbol_filter_t filter)
675{ 760{
676 u8 cpumode = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 761 u8 cpumode = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
677 struct thread *thread; 762 struct thread *thread = perf_session__findnew(session, self->ip.pid);
678
679 event__parse_sample(self, session->sample_type, data);
680
681 dump_printf("(IP, %d): %d/%d: %#Lx period: %Ld cpu:%d\n",
682 self->header.misc, data->pid, data->tid, data->ip,
683 data->period, data->cpu);
684
685 if (session->sample_type & PERF_SAMPLE_CALLCHAIN) {
686 unsigned int i;
687
688 dump_printf("... chain: nr:%Lu\n", data->callchain->nr);
689 763
690 if (!ip_callchain__valid(data->callchain, self)) {
691 pr_debug("call-chain problem with event, "
692 "skipping it.\n");
693 goto out_filtered;
694 }
695
696 if (dump_trace) {
697 for (i = 0; i < data->callchain->nr; i++)
698 dump_printf("..... %2d: %016Lx\n",
699 i, data->callchain->ips[i]);
700 }
701 }
702 thread = perf_session__findnew(session, self->ip.pid);
703 if (thread == NULL) 764 if (thread == NULL)
704 return -1; 765 return -1;
705 766
@@ -766,9 +827,65 @@ out_filtered:
766 return 0; 827 return 0;
767} 828}
768 829
769int event__parse_sample(const event_t *event, u64 type, struct sample_data *data) 830static int event__parse_id_sample(const event_t *event,
831 struct perf_session *session,
832 struct sample_data *sample)
770{ 833{
771 const u64 *array = event->sample.array; 834 const u64 *array;
835 u64 type;
836
837 sample->cpu = sample->pid = sample->tid = -1;
838 sample->stream_id = sample->id = sample->time = -1ULL;
839
840 if (!session->sample_id_all)
841 return 0;
842
843 array = event->sample.array;
844 array += ((event->header.size -
845 sizeof(event->header)) / sizeof(u64)) - 1;
846 type = session->sample_type;
847
848 if (type & PERF_SAMPLE_CPU) {
849 u32 *p = (u32 *)array;
850 sample->cpu = *p;
851 array--;
852 }
853
854 if (type & PERF_SAMPLE_STREAM_ID) {
855 sample->stream_id = *array;
856 array--;
857 }
858
859 if (type & PERF_SAMPLE_ID) {
860 sample->id = *array;
861 array--;
862 }
863
864 if (type & PERF_SAMPLE_TIME) {
865 sample->time = *array;
866 array--;
867 }
868
869 if (type & PERF_SAMPLE_TID) {
870 u32 *p = (u32 *)array;
871 sample->pid = p[0];
872 sample->tid = p[1];
873 }
874
875 return 0;
876}
877
878int event__parse_sample(const event_t *event, struct perf_session *session,
879 struct sample_data *data)
880{
881 const u64 *array;
882 u64 type;
883
884 if (event->header.type != PERF_RECORD_SAMPLE)
885 return event__parse_id_sample(event, session, data);
886
887 array = event->sample.array;
888 type = session->sample_type;
772 889
773 if (type & PERF_SAMPLE_IP) { 890 if (type & PERF_SAMPLE_IP) {
774 data->ip = event->ip.ip; 891 data->ip = event->ip.ip;
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 8e790dae7026..2b7e91902f10 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -85,6 +85,7 @@ struct build_id_event {
85}; 85};
86 86
87enum perf_user_event_type { /* above any possible kernel type */ 87enum perf_user_event_type { /* above any possible kernel type */
88 PERF_RECORD_USER_TYPE_START = 64,
88 PERF_RECORD_HEADER_ATTR = 64, 89 PERF_RECORD_HEADER_ATTR = 64,
89 PERF_RECORD_HEADER_EVENT_TYPE = 65, 90 PERF_RECORD_HEADER_EVENT_TYPE = 65,
90 PERF_RECORD_HEADER_TRACING_DATA = 66, 91 PERF_RECORD_HEADER_TRACING_DATA = 66,
@@ -135,12 +136,15 @@ void event__print_totals(void);
135 136
136struct perf_session; 137struct perf_session;
137 138
138typedef int (*event__handler_t)(event_t *event, struct perf_session *session); 139typedef int (*event__handler_synth_t)(event_t *event,
140 struct perf_session *session);
141typedef int (*event__handler_t)(event_t *event, struct sample_data *sample,
142 struct perf_session *session);
139 143
140int event__synthesize_thread(pid_t pid, event__handler_t process, 144int event__synthesize_thread(pid_t pid, event__handler_t process,
141 struct perf_session *session); 145 struct perf_session *session);
142void event__synthesize_threads(event__handler_t process, 146int event__synthesize_threads(event__handler_t process,
143 struct perf_session *session); 147 struct perf_session *session);
144int event__synthesize_kernel_mmap(event__handler_t process, 148int event__synthesize_kernel_mmap(event__handler_t process,
145 struct perf_session *session, 149 struct perf_session *session,
146 struct machine *machine, 150 struct machine *machine,
@@ -150,18 +154,24 @@ int event__synthesize_modules(event__handler_t process,
150 struct perf_session *session, 154 struct perf_session *session,
151 struct machine *machine); 155 struct machine *machine);
152 156
153int event__process_comm(event_t *self, struct perf_session *session); 157int event__process_comm(event_t *self, struct sample_data *sample,
154int event__process_lost(event_t *self, struct perf_session *session); 158 struct perf_session *session);
155int event__process_mmap(event_t *self, struct perf_session *session); 159int event__process_lost(event_t *self, struct sample_data *sample,
156int event__process_task(event_t *self, struct perf_session *session); 160 struct perf_session *session);
157int event__process(event_t *event, struct perf_session *session); 161int event__process_mmap(event_t *self, struct sample_data *sample,
162 struct perf_session *session);
163int event__process_task(event_t *self, struct sample_data *sample,
164 struct perf_session *session);
165int event__process(event_t *event, struct sample_data *sample,
166 struct perf_session *session);
158 167
159struct addr_location; 168struct addr_location;
160int event__preprocess_sample(const event_t *self, struct perf_session *session, 169int event__preprocess_sample(const event_t *self, struct perf_session *session,
161 struct addr_location *al, struct sample_data *data, 170 struct addr_location *al, struct sample_data *data,
162 symbol_filter_t filter); 171 symbol_filter_t filter);
163int event__parse_sample(const event_t *event, u64 type, struct sample_data *data); 172int event__parse_sample(const event_t *event, struct perf_session *session,
173 struct sample_data *sample);
164 174
165extern const char *event__name[]; 175const char *event__get_event_name(unsigned int id);
166 176
167#endif /* __PERF_RECORD_H */ 177#endif /* __PERF_RECORD_H */
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
new file mode 100644
index 000000000000..f5cfed60af98
--- /dev/null
+++ b/tools/perf/util/evsel.c
@@ -0,0 +1,201 @@
1#include "evsel.h"
2#include "../perf.h"
3#include "util.h"
4#include "cpumap.h"
5#include "thread.h"
6
7#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
8
9struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx)
10{
11 struct perf_evsel *evsel = zalloc(sizeof(*evsel));
12
13 if (evsel != NULL) {
14 evsel->idx = idx;
15 evsel->attr = *attr;
16 INIT_LIST_HEAD(&evsel->node);
17 }
18
19 return evsel;
20}
21
22int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
23{
24 evsel->fd = xyarray__new(ncpus, nthreads, sizeof(int));
25 return evsel->fd != NULL ? 0 : -ENOMEM;
26}
27
28int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus)
29{
30 evsel->counts = zalloc((sizeof(*evsel->counts) +
31 (ncpus * sizeof(struct perf_counts_values))));
32 return evsel->counts != NULL ? 0 : -ENOMEM;
33}
34
35void perf_evsel__free_fd(struct perf_evsel *evsel)
36{
37 xyarray__delete(evsel->fd);
38 evsel->fd = NULL;
39}
40
41void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
42{
43 int cpu, thread;
44
45 for (cpu = 0; cpu < ncpus; cpu++)
46 for (thread = 0; thread < nthreads; ++thread) {
47 close(FD(evsel, cpu, thread));
48 FD(evsel, cpu, thread) = -1;
49 }
50}
51
52void perf_evsel__delete(struct perf_evsel *evsel)
53{
54 assert(list_empty(&evsel->node));
55 xyarray__delete(evsel->fd);
56 free(evsel);
57}
58
59int __perf_evsel__read_on_cpu(struct perf_evsel *evsel,
60 int cpu, int thread, bool scale)
61{
62 struct perf_counts_values count;
63 size_t nv = scale ? 3 : 1;
64
65 if (FD(evsel, cpu, thread) < 0)
66 return -EINVAL;
67
68 if (evsel->counts == NULL && perf_evsel__alloc_counts(evsel, cpu + 1) < 0)
69 return -ENOMEM;
70
71 if (readn(FD(evsel, cpu, thread), &count, nv * sizeof(u64)) < 0)
72 return -errno;
73
74 if (scale) {
75 if (count.run == 0)
76 count.val = 0;
77 else if (count.run < count.ena)
78 count.val = (u64)((double)count.val * count.ena / count.run + 0.5);
79 } else
80 count.ena = count.run = 0;
81
82 evsel->counts->cpu[cpu] = count;
83 return 0;
84}
85
86int __perf_evsel__read(struct perf_evsel *evsel,
87 int ncpus, int nthreads, bool scale)
88{
89 size_t nv = scale ? 3 : 1;
90 int cpu, thread;
91 struct perf_counts_values *aggr = &evsel->counts->aggr, count;
92
93 aggr->val = 0;
94
95 for (cpu = 0; cpu < ncpus; cpu++) {
96 for (thread = 0; thread < nthreads; thread++) {
97 if (FD(evsel, cpu, thread) < 0)
98 continue;
99
100 if (readn(FD(evsel, cpu, thread),
101 &count, nv * sizeof(u64)) < 0)
102 return -errno;
103
104 aggr->val += count.val;
105 if (scale) {
106 aggr->ena += count.ena;
107 aggr->run += count.run;
108 }
109 }
110 }
111
112 evsel->counts->scaled = 0;
113 if (scale) {
114 if (aggr->run == 0) {
115 evsel->counts->scaled = -1;
116 aggr->val = 0;
117 return 0;
118 }
119
120 if (aggr->run < aggr->ena) {
121 evsel->counts->scaled = 1;
122 aggr->val = (u64)((double)aggr->val * aggr->ena / aggr->run + 0.5);
123 }
124 } else
125 aggr->ena = aggr->run = 0;
126
127 return 0;
128}
129
130static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
131 struct thread_map *threads)
132{
133 int cpu, thread;
134
135 if (evsel->fd == NULL &&
136 perf_evsel__alloc_fd(evsel, cpus->nr, threads->nr) < 0)
137 return -1;
138
139 for (cpu = 0; cpu < cpus->nr; cpu++) {
140 for (thread = 0; thread < threads->nr; thread++) {
141 FD(evsel, cpu, thread) = sys_perf_event_open(&evsel->attr,
142 threads->map[thread],
143 cpus->map[cpu], -1, 0);
144 if (FD(evsel, cpu, thread) < 0)
145 goto out_close;
146 }
147 }
148
149 return 0;
150
151out_close:
152 do {
153 while (--thread >= 0) {
154 close(FD(evsel, cpu, thread));
155 FD(evsel, cpu, thread) = -1;
156 }
157 thread = threads->nr;
158 } while (--cpu >= 0);
159 return -1;
160}
161
162static struct {
163 struct cpu_map map;
164 int cpus[1];
165} empty_cpu_map = {
166 .map.nr = 1,
167 .cpus = { -1, },
168};
169
170static struct {
171 struct thread_map map;
172 int threads[1];
173} empty_thread_map = {
174 .map.nr = 1,
175 .threads = { -1, },
176};
177
178int perf_evsel__open(struct perf_evsel *evsel,
179 struct cpu_map *cpus, struct thread_map *threads)
180{
181
182 if (cpus == NULL) {
183 /* Work around old compiler warnings about strict aliasing */
184 cpus = &empty_cpu_map.map;
185 }
186
187 if (threads == NULL)
188 threads = &empty_thread_map.map;
189
190 return __perf_evsel__open(evsel, cpus, threads);
191}
192
193int perf_evsel__open_per_cpu(struct perf_evsel *evsel, struct cpu_map *cpus)
194{
195 return __perf_evsel__open(evsel, cpus, &empty_thread_map.map);
196}
197
198int perf_evsel__open_per_thread(struct perf_evsel *evsel, struct thread_map *threads)
199{
200 return __perf_evsel__open(evsel, &empty_cpu_map.map, threads);
201}
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
new file mode 100644
index 000000000000..b2d755fe88a5
--- /dev/null
+++ b/tools/perf/util/evsel.h
@@ -0,0 +1,115 @@
1#ifndef __PERF_EVSEL_H
2#define __PERF_EVSEL_H 1
3
4#include <linux/list.h>
5#include <stdbool.h>
6#include "../../../include/linux/perf_event.h"
7#include "types.h"
8#include "xyarray.h"
9
10struct perf_counts_values {
11 union {
12 struct {
13 u64 val;
14 u64 ena;
15 u64 run;
16 };
17 u64 values[3];
18 };
19};
20
21struct perf_counts {
22 s8 scaled;
23 struct perf_counts_values aggr;
24 struct perf_counts_values cpu[];
25};
26
27struct perf_evsel {
28 struct list_head node;
29 struct perf_event_attr attr;
30 char *filter;
31 struct xyarray *fd;
32 struct perf_counts *counts;
33 int idx;
34 void *priv;
35};
36
37struct cpu_map;
38struct thread_map;
39
40struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx);
41void perf_evsel__delete(struct perf_evsel *evsel);
42
43int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
44int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus);
45void perf_evsel__free_fd(struct perf_evsel *evsel);
46void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
47
48int perf_evsel__open_per_cpu(struct perf_evsel *evsel, struct cpu_map *cpus);
49int perf_evsel__open_per_thread(struct perf_evsel *evsel, struct thread_map *threads);
50int perf_evsel__open(struct perf_evsel *evsel,
51 struct cpu_map *cpus, struct thread_map *threads);
52
53#define perf_evsel__match(evsel, t, c) \
54 (evsel->attr.type == PERF_TYPE_##t && \
55 evsel->attr.config == PERF_COUNT_##c)
56
57int __perf_evsel__read_on_cpu(struct perf_evsel *evsel,
58 int cpu, int thread, bool scale);
59
60/**
61 * perf_evsel__read_on_cpu - Read out the results on a CPU and thread
62 *
63 * @evsel - event selector to read value
64 * @cpu - CPU of interest
65 * @thread - thread of interest
66 */
67static inline int perf_evsel__read_on_cpu(struct perf_evsel *evsel,
68 int cpu, int thread)
69{
70 return __perf_evsel__read_on_cpu(evsel, cpu, thread, false);
71}
72
73/**
74 * perf_evsel__read_on_cpu_scaled - Read out the results on a CPU and thread, scaled
75 *
76 * @evsel - event selector to read value
77 * @cpu - CPU of interest
78 * @thread - thread of interest
79 */
80static inline int perf_evsel__read_on_cpu_scaled(struct perf_evsel *evsel,
81 int cpu, int thread)
82{
83 return __perf_evsel__read_on_cpu(evsel, cpu, thread, true);
84}
85
86int __perf_evsel__read(struct perf_evsel *evsel, int ncpus, int nthreads,
87 bool scale);
88
89/**
90 * perf_evsel__read - Read the aggregate results on all CPUs
91 *
92 * @evsel - event selector to read value
93 * @ncpus - Number of cpus affected, from zero
94 * @nthreads - Number of threads affected, from zero
95 */
96static inline int perf_evsel__read(struct perf_evsel *evsel,
97 int ncpus, int nthreads)
98{
99 return __perf_evsel__read(evsel, ncpus, nthreads, false);
100}
101
102/**
103 * perf_evsel__read_scaled - Read the aggregate results on all CPUs, scaled
104 *
105 * @evsel - event selector to read value
106 * @ncpus - Number of cpus affected, from zero
107 * @nthreads - Number of threads affected, from zero
108 */
109static inline int perf_evsel__read_scaled(struct perf_evsel *evsel,
110 int ncpus, int nthreads)
111{
112 return __perf_evsel__read(evsel, ncpus, nthreads, true);
113}
114
115#endif /* __PERF_EVSEL_H */
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index d7e67b167ea3..f6a929e74981 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -152,6 +152,11 @@ void perf_header__set_feat(struct perf_header *self, int feat)
152 set_bit(feat, self->adds_features); 152 set_bit(feat, self->adds_features);
153} 153}
154 154
155void perf_header__clear_feat(struct perf_header *self, int feat)
156{
157 clear_bit(feat, self->adds_features);
158}
159
155bool perf_header__has_feat(const struct perf_header *self, int feat) 160bool perf_header__has_feat(const struct perf_header *self, int feat)
156{ 161{
157 return test_bit(feat, self->adds_features); 162 return test_bit(feat, self->adds_features);
@@ -265,15 +270,16 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
265 const char *name, bool is_kallsyms) 270 const char *name, bool is_kallsyms)
266{ 271{
267 const size_t size = PATH_MAX; 272 const size_t size = PATH_MAX;
268 char *filename = malloc(size), 273 char *realname = realpath(name, NULL),
274 *filename = malloc(size),
269 *linkname = malloc(size), *targetname; 275 *linkname = malloc(size), *targetname;
270 int len, err = -1; 276 int len, err = -1;
271 277
272 if (filename == NULL || linkname == NULL) 278 if (realname == NULL || filename == NULL || linkname == NULL)
273 goto out_free; 279 goto out_free;
274 280
275 len = snprintf(filename, size, "%s%s%s", 281 len = snprintf(filename, size, "%s%s%s",
276 debugdir, is_kallsyms ? "/" : "", name); 282 debugdir, is_kallsyms ? "/" : "", realname);
277 if (mkdir_p(filename, 0755)) 283 if (mkdir_p(filename, 0755))
278 goto out_free; 284 goto out_free;
279 285
@@ -283,7 +289,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
283 if (is_kallsyms) { 289 if (is_kallsyms) {
284 if (copyfile("/proc/kallsyms", filename)) 290 if (copyfile("/proc/kallsyms", filename))
285 goto out_free; 291 goto out_free;
286 } else if (link(name, filename) && copyfile(name, filename)) 292 } else if (link(realname, filename) && copyfile(name, filename))
287 goto out_free; 293 goto out_free;
288 } 294 }
289 295
@@ -300,6 +306,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
300 if (symlink(targetname, linkname) == 0) 306 if (symlink(targetname, linkname) == 0)
301 err = 0; 307 err = 0;
302out_free: 308out_free:
309 free(realname);
303 free(filename); 310 free(filename);
304 free(linkname); 311 free(linkname);
305 return err; 312 return err;
@@ -431,8 +438,10 @@ static int perf_header__adds_write(struct perf_header *self, int fd)
431 int idx = 0, err; 438 int idx = 0, err;
432 439
433 session = container_of(self, struct perf_session, header); 440 session = container_of(self, struct perf_session, header);
434 if (perf_session__read_build_ids(session, true)) 441
435 perf_header__set_feat(self, HEADER_BUILD_ID); 442 if (perf_header__has_feat(self, HEADER_BUILD_ID &&
443 !perf_session__read_build_ids(session, true)))
444 perf_header__clear_feat(self, HEADER_BUILD_ID);
436 445
437 nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS); 446 nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS);
438 if (!nr_sections) 447 if (!nr_sections)
@@ -454,7 +463,7 @@ static int perf_header__adds_write(struct perf_header *self, int fd)
454 463
455 /* Write trace info */ 464 /* Write trace info */
456 trace_sec->offset = lseek(fd, 0, SEEK_CUR); 465 trace_sec->offset = lseek(fd, 0, SEEK_CUR);
457 read_tracing_data(fd, attrs, nr_counters); 466 read_tracing_data(fd, &evsel_list);
458 trace_sec->size = lseek(fd, 0, SEEK_CUR) - trace_sec->offset; 467 trace_sec->size = lseek(fd, 0, SEEK_CUR) - trace_sec->offset;
459 } 468 }
460 469
@@ -597,7 +606,7 @@ int perf_header__write(struct perf_header *self, int fd, bool at_exit)
597static int perf_header__getbuffer64(struct perf_header *self, 606static int perf_header__getbuffer64(struct perf_header *self,
598 int fd, void *buf, size_t size) 607 int fd, void *buf, size_t size)
599{ 608{
600 if (do_read(fd, buf, size) <= 0) 609 if (readn(fd, buf, size) <= 0)
601 return -1; 610 return -1;
602 611
603 if (self->needs_swap) 612 if (self->needs_swap)
@@ -653,7 +662,7 @@ int perf_file_header__read(struct perf_file_header *self,
653{ 662{
654 lseek(fd, 0, SEEK_SET); 663 lseek(fd, 0, SEEK_SET);
655 664
656 if (do_read(fd, self, sizeof(*self)) <= 0 || 665 if (readn(fd, self, sizeof(*self)) <= 0 ||
657 memcmp(&self->magic, __perf_magic, sizeof(self->magic))) 666 memcmp(&self->magic, __perf_magic, sizeof(self->magic)))
658 return -1; 667 return -1;
659 668
@@ -789,8 +798,8 @@ static int perf_file_section__process(struct perf_file_section *self,
789 int feat, int fd) 798 int feat, int fd)
790{ 799{
791 if (lseek(fd, self->offset, SEEK_SET) == (off_t)-1) { 800 if (lseek(fd, self->offset, SEEK_SET) == (off_t)-1) {
792 pr_debug("Failed to lseek to %Ld offset for feature %d, " 801 pr_debug("Failed to lseek to %" PRIu64 " offset for feature "
793 "continuing...\n", self->offset, feat); 802 "%d, continuing...\n", self->offset, feat);
794 return 0; 803 return 0;
795 } 804 }
796 805
@@ -814,7 +823,7 @@ static int perf_file_header__read_pipe(struct perf_pipe_file_header *self,
814 struct perf_header *ph, int fd, 823 struct perf_header *ph, int fd,
815 bool repipe) 824 bool repipe)
816{ 825{
817 if (do_read(fd, self, sizeof(*self)) <= 0 || 826 if (readn(fd, self, sizeof(*self)) <= 0 ||
818 memcmp(&self->magic, __perf_magic, sizeof(self->magic))) 827 memcmp(&self->magic, __perf_magic, sizeof(self->magic)))
819 return -1; 828 return -1;
820 829
@@ -939,6 +948,24 @@ u64 perf_header__sample_type(struct perf_header *header)
939 return type; 948 return type;
940} 949}
941 950
951bool perf_header__sample_id_all(const struct perf_header *header)
952{
953 bool value = false, first = true;
954 int i;
955
956 for (i = 0; i < header->attrs; i++) {
957 struct perf_header_attr *attr = header->attr[i];
958
959 if (first) {
960 value = attr->attr.sample_id_all;
961 first = false;
962 } else if (value != attr->attr.sample_id_all)
963 die("non matching sample_id_all");
964 }
965
966 return value;
967}
968
942struct perf_event_attr * 969struct perf_event_attr *
943perf_header__find_attr(u64 id, struct perf_header *header) 970perf_header__find_attr(u64 id, struct perf_header *header)
944{ 971{
@@ -946,11 +973,16 @@ perf_header__find_attr(u64 id, struct perf_header *header)
946 973
947 /* 974 /*
948 * We set id to -1 if the data file doesn't contain sample 975 * We set id to -1 if the data file doesn't contain sample
949 * ids. Check for this and avoid walking through the entire 976 * ids. This can happen when the data file contains one type
950 * list of ids which may be large. 977 * of event and in that case, the header can still store the
978 * event attribute information. Check for this and avoid
979 * walking through the entire list of ids which may be large.
951 */ 980 */
952 if (id == -1ULL) 981 if (id == -1ULL) {
982 if (header->attrs > 0)
983 return &header->attr[0]->attr;
953 return NULL; 984 return NULL;
985 }
954 986
955 for (i = 0; i < header->attrs; i++) { 987 for (i = 0; i < header->attrs; i++) {
956 struct perf_header_attr *attr = header->attr[i]; 988 struct perf_header_attr *attr = header->attr[i];
@@ -980,21 +1012,23 @@ int event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id,
980 1012
981 ev = malloc(size); 1013 ev = malloc(size);
982 1014
1015 if (ev == NULL)
1016 return -ENOMEM;
1017
983 ev->attr.attr = *attr; 1018 ev->attr.attr = *attr;
984 memcpy(ev->attr.id, id, ids * sizeof(u64)); 1019 memcpy(ev->attr.id, id, ids * sizeof(u64));
985 1020
986 ev->attr.header.type = PERF_RECORD_HEADER_ATTR; 1021 ev->attr.header.type = PERF_RECORD_HEADER_ATTR;
987 ev->attr.header.size = size; 1022 ev->attr.header.size = size;
988 1023
989 err = process(ev, session); 1024 err = process(ev, NULL, session);
990 1025
991 free(ev); 1026 free(ev);
992 1027
993 return err; 1028 return err;
994} 1029}
995 1030
996int event__synthesize_attrs(struct perf_header *self, 1031int event__synthesize_attrs(struct perf_header *self, event__handler_t process,
997 event__handler_t process,
998 struct perf_session *session) 1032 struct perf_session *session)
999{ 1033{
1000 struct perf_header_attr *attr; 1034 struct perf_header_attr *attr;
@@ -1064,7 +1098,7 @@ int event__synthesize_event_type(u64 event_id, char *name,
1064 ev.event_type.header.size = sizeof(ev.event_type) - 1098 ev.event_type.header.size = sizeof(ev.event_type) -
1065 (sizeof(ev.event_type.event_type.name) - size); 1099 (sizeof(ev.event_type.event_type.name) - size);
1066 1100
1067 err = process(&ev, session); 1101 err = process(&ev, NULL, session);
1068 1102
1069 return err; 1103 return err;
1070} 1104}
@@ -1099,8 +1133,7 @@ int event__process_event_type(event_t *self,
1099 return 0; 1133 return 0;
1100} 1134}
1101 1135
1102int event__synthesize_tracing_data(int fd, struct perf_event_attr *pattrs, 1136int event__synthesize_tracing_data(int fd, struct list_head *pattrs,
1103 int nb_events,
1104 event__handler_t process, 1137 event__handler_t process,
1105 struct perf_session *session __unused) 1138 struct perf_session *session __unused)
1106{ 1139{
@@ -1111,7 +1144,7 @@ int event__synthesize_tracing_data(int fd, struct perf_event_attr *pattrs,
1111 memset(&ev, 0, sizeof(ev)); 1144 memset(&ev, 0, sizeof(ev));
1112 1145
1113 ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA; 1146 ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA;
1114 size = read_tracing_data_size(fd, pattrs, nb_events); 1147 size = read_tracing_data_size(fd, pattrs);
1115 if (size <= 0) 1148 if (size <= 0)
1116 return size; 1149 return size;
1117 aligned_size = ALIGN(size, sizeof(u64)); 1150 aligned_size = ALIGN(size, sizeof(u64));
@@ -1119,9 +1152,9 @@ int event__synthesize_tracing_data(int fd, struct perf_event_attr *pattrs,
1119 ev.tracing_data.header.size = sizeof(ev.tracing_data); 1152 ev.tracing_data.header.size = sizeof(ev.tracing_data);
1120 ev.tracing_data.size = aligned_size; 1153 ev.tracing_data.size = aligned_size;
1121 1154
1122 process(&ev, session); 1155 process(&ev, NULL, session);
1123 1156
1124 err = read_tracing_data(fd, pattrs, nb_events); 1157 err = read_tracing_data(fd, pattrs);
1125 write_padded(fd, NULL, 0, padding); 1158 write_padded(fd, NULL, 0, padding);
1126 1159
1127 return aligned_size; 1160 return aligned_size;
@@ -1179,7 +1212,7 @@ int event__synthesize_build_id(struct dso *pos, u16 misc,
1179 ev.build_id.header.size = sizeof(ev.build_id) + len; 1212 ev.build_id.header.size = sizeof(ev.build_id) + len;
1180 memcpy(&ev.build_id.filename, pos->long_name, pos->long_name_len); 1213 memcpy(&ev.build_id.filename, pos->long_name, pos->long_name_len);
1181 1214
1182 err = process(&ev, session); 1215 err = process(&ev, NULL, session);
1183 1216
1184 return err; 1217 return err;
1185} 1218}
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 402ac2454cf8..33f16be7b72f 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -81,9 +81,11 @@ void perf_header_attr__delete(struct perf_header_attr *self);
81int perf_header_attr__add_id(struct perf_header_attr *self, u64 id); 81int perf_header_attr__add_id(struct perf_header_attr *self, u64 id);
82 82
83u64 perf_header__sample_type(struct perf_header *header); 83u64 perf_header__sample_type(struct perf_header *header);
84bool perf_header__sample_id_all(const struct perf_header *header);
84struct perf_event_attr * 85struct perf_event_attr *
85perf_header__find_attr(u64 id, struct perf_header *header); 86perf_header__find_attr(u64 id, struct perf_header *header);
86void perf_header__set_feat(struct perf_header *self, int feat); 87void perf_header__set_feat(struct perf_header *self, int feat);
88void perf_header__clear_feat(struct perf_header *self, int feat);
87bool perf_header__has_feat(const struct perf_header *self, int feat); 89bool perf_header__has_feat(const struct perf_header *self, int feat);
88 90
89int perf_header__process_sections(struct perf_header *self, int fd, 91int perf_header__process_sections(struct perf_header *self, int fd,
@@ -111,8 +113,7 @@ int event__synthesize_event_types(event__handler_t process,
111int event__process_event_type(event_t *self, 113int event__process_event_type(event_t *self,
112 struct perf_session *session); 114 struct perf_session *session);
113 115
114int event__synthesize_tracing_data(int fd, struct perf_event_attr *pattrs, 116int event__synthesize_tracing_data(int fd, struct list_head *pattrs,
115 int nb_events,
116 event__handler_t process, 117 event__handler_t process,
117 struct perf_session *session); 118 struct perf_session *session);
118int event__process_tracing_data(event_t *self, 119int event__process_tracing_data(event_t *self,
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 2022e8740994..32f4f1f2f6e4 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -356,7 +356,7 @@ static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask,
356 356
357static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, 357static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain,
358 int depth, int depth_mask, int period, 358 int depth, int depth_mask, int period,
359 u64 total_samples, int hits, 359 u64 total_samples, u64 hits,
360 int left_margin) 360 int left_margin)
361{ 361{
362 int i; 362 int i;
@@ -636,13 +636,13 @@ int hist_entry__snprintf(struct hist_entry *self, char *s, size_t size,
636 } 636 }
637 } 637 }
638 } else 638 } else
639 ret = snprintf(s, size, sep ? "%lld" : "%12lld ", period); 639 ret = snprintf(s, size, sep ? "%" PRIu64 : "%12" PRIu64 " ", period);
640 640
641 if (symbol_conf.show_nr_samples) { 641 if (symbol_conf.show_nr_samples) {
642 if (sep) 642 if (sep)
643 ret += snprintf(s + ret, size - ret, "%c%lld", *sep, period); 643 ret += snprintf(s + ret, size - ret, "%c%" PRIu64, *sep, period);
644 else 644 else
645 ret += snprintf(s + ret, size - ret, "%11lld", period); 645 ret += snprintf(s + ret, size - ret, "%11" PRIu64, period);
646 } 646 }
647 647
648 if (pair_hists) { 648 if (pair_hists) {
@@ -971,7 +971,7 @@ int hist_entry__inc_addr_samples(struct hist_entry *self, u64 ip)
971 sym_size = sym->end - sym->start; 971 sym_size = sym->end - sym->start;
972 offset = ip - sym->start; 972 offset = ip - sym->start;
973 973
974 pr_debug3("%s: ip=%#Lx\n", __func__, self->ms.map->unmap_ip(self->ms.map, ip)); 974 pr_debug3("%s: ip=%#" PRIx64 "\n", __func__, self->ms.map->unmap_ip(self->ms.map, ip));
975 975
976 if (offset >= sym_size) 976 if (offset >= sym_size)
977 return 0; 977 return 0;
@@ -980,8 +980,9 @@ int hist_entry__inc_addr_samples(struct hist_entry *self, u64 ip)
980 h->sum++; 980 h->sum++;
981 h->ip[offset]++; 981 h->ip[offset]++;
982 982
983 pr_debug3("%#Lx %s: period++ [ip: %#Lx, %#Lx] => %Ld\n", self->ms.sym->start, 983 pr_debug3("%#" PRIx64 " %s: period++ [ip: %#" PRIx64 ", %#" PRIx64
984 self->ms.sym->name, ip, ip - self->ms.sym->start, h->ip[offset]); 984 "] => %" PRIu64 "\n", self->ms.sym->start, self->ms.sym->name,
985 ip, ip - self->ms.sym->start, h->ip[offset]);
985 return 0; 986 return 0;
986} 987}
987 988
@@ -1092,6 +1093,12 @@ int hist_entry__annotate(struct hist_entry *self, struct list_head *head,
1092 FILE *file; 1093 FILE *file;
1093 int err = 0; 1094 int err = 0;
1094 u64 len; 1095 u64 len;
1096 char symfs_filename[PATH_MAX];
1097
1098 if (filename) {
1099 snprintf(symfs_filename, sizeof(symfs_filename), "%s%s",
1100 symbol_conf.symfs, filename);
1101 }
1095 1102
1096 if (filename == NULL) { 1103 if (filename == NULL) {
1097 if (dso->has_build_id) { 1104 if (dso->has_build_id) {
@@ -1100,9 +1107,9 @@ int hist_entry__annotate(struct hist_entry *self, struct list_head *head,
1100 return -ENOMEM; 1107 return -ENOMEM;
1101 } 1108 }
1102 goto fallback; 1109 goto fallback;
1103 } else if (readlink(filename, command, sizeof(command)) < 0 || 1110 } else if (readlink(symfs_filename, command, sizeof(command)) < 0 ||
1104 strstr(command, "[kernel.kallsyms]") || 1111 strstr(command, "[kernel.kallsyms]") ||
1105 access(filename, R_OK)) { 1112 access(symfs_filename, R_OK)) {
1106 free(filename); 1113 free(filename);
1107fallback: 1114fallback:
1108 /* 1115 /*
@@ -1111,6 +1118,8 @@ fallback:
1111 * DSO is the same as when 'perf record' ran. 1118 * DSO is the same as when 'perf record' ran.
1112 */ 1119 */
1113 filename = dso->long_name; 1120 filename = dso->long_name;
1121 snprintf(symfs_filename, sizeof(symfs_filename), "%s%s",
1122 symbol_conf.symfs, filename);
1114 free_filename = false; 1123 free_filename = false;
1115 } 1124 }
1116 1125
@@ -1124,7 +1133,7 @@ fallback:
1124 goto out_free_filename; 1133 goto out_free_filename;
1125 } 1134 }
1126 1135
1127 pr_debug("%s: filename=%s, sym=%s, start=%#Lx, end=%#Lx\n", __func__, 1136 pr_debug("%s: filename=%s, sym=%s, start=%#" PRIx64 ", end=%#" PRIx64 "\n", __func__,
1128 filename, sym->name, map->unmap_ip(map, sym->start), 1137 filename, sym->name, map->unmap_ip(map, sym->start),
1129 map->unmap_ip(map, sym->end)); 1138 map->unmap_ip(map, sym->end));
1130 1139
@@ -1134,10 +1143,10 @@ fallback:
1134 dso, dso->long_name, sym, sym->name); 1143 dso, dso->long_name, sym, sym->name);
1135 1144
1136 snprintf(command, sizeof(command), 1145 snprintf(command, sizeof(command),
1137 "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS -C %s|grep -v %s|expand", 1146 "objdump --start-address=0x%016" PRIx64 " --stop-address=0x%016" PRIx64 " -dS -C %s|grep -v %s|expand",
1138 map__rip_2objdump(map, sym->start), 1147 map__rip_2objdump(map, sym->start),
1139 map__rip_2objdump(map, sym->end), 1148 map__rip_2objdump(map, sym->end),
1140 filename, filename); 1149 symfs_filename, filename);
1141 1150
1142 pr_debug("Executing: %s\n", command); 1151 pr_debug("Executing: %s\n", command);
1143 1152
@@ -1168,10 +1177,13 @@ size_t hists__fprintf_nr_events(struct hists *self, FILE *fp)
1168 size_t ret = 0; 1177 size_t ret = 0;
1169 1178
1170 for (i = 0; i < PERF_RECORD_HEADER_MAX; ++i) { 1179 for (i = 0; i < PERF_RECORD_HEADER_MAX; ++i) {
1171 if (!event__name[i]) 1180 const char *name = event__get_event_name(i);
1181
1182 if (!strcmp(name, "UNKNOWN"))
1172 continue; 1183 continue;
1173 ret += fprintf(fp, "%10s events: %10d\n", 1184
1174 event__name[i], self->stats.nr_events[i]); 1185 ret += fprintf(fp, "%16s events: %10d\n", name,
1186 self->stats.nr_events[i]);
1175 } 1187 }
1176 1188
1177 return ret; 1189 return ret;
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 587d375d3430..ee789856a8c9 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -52,8 +52,10 @@ struct sym_priv {
52struct events_stats { 52struct events_stats {
53 u64 total_period; 53 u64 total_period;
54 u64 total_lost; 54 u64 total_lost;
55 u64 total_invalid_chains;
55 u32 nr_events[PERF_RECORD_HEADER_MAX]; 56 u32 nr_events[PERF_RECORD_HEADER_MAX];
56 u32 nr_unknown_events; 57 u32 nr_unknown_events;
58 u32 nr_invalid_chains;
57}; 59};
58 60
59enum hist_column { 61enum hist_column {
diff --git a/tools/perf/util/include/asm/cpufeature.h b/tools/perf/util/include/asm/cpufeature.h
new file mode 100644
index 000000000000..acffd5e4d1d4
--- /dev/null
+++ b/tools/perf/util/include/asm/cpufeature.h
@@ -0,0 +1,9 @@
1
2#ifndef PERF_CPUFEATURE_H
3#define PERF_CPUFEATURE_H
4
5/* cpufeature.h ... dummy header file for including arch/x86/lib/memcpy_64.S */
6
7#define X86_FEATURE_REP_GOOD 0
8
9#endif /* PERF_CPUFEATURE_H */
diff --git a/tools/perf/util/include/asm/dwarf2.h b/tools/perf/util/include/asm/dwarf2.h
new file mode 100644
index 000000000000..bb4198e7837a
--- /dev/null
+++ b/tools/perf/util/include/asm/dwarf2.h
@@ -0,0 +1,11 @@
1
2#ifndef PERF_DWARF2_H
3#define PERF_DWARF2_H
4
5/* dwarf2.h ... dummy header file for including arch/x86/lib/memcpy_64.S */
6
7#define CFI_STARTPROC
8#define CFI_ENDPROC
9
10#endif /* PERF_DWARF2_H */
11
diff --git a/tools/perf/util/include/linux/bitops.h b/tools/perf/util/include/linux/bitops.h
index bb4ac2e05385..305c8484f200 100644
--- a/tools/perf/util/include/linux/bitops.h
+++ b/tools/perf/util/include/linux/bitops.h
@@ -2,6 +2,7 @@
2#define _PERF_LINUX_BITOPS_H_ 2#define _PERF_LINUX_BITOPS_H_
3 3
4#include <linux/kernel.h> 4#include <linux/kernel.h>
5#include <linux/compiler.h>
5#include <asm/hweight.h> 6#include <asm/hweight.h>
6 7
7#define BITS_PER_LONG __WORDSIZE 8#define BITS_PER_LONG __WORDSIZE
@@ -13,6 +14,11 @@ static inline void set_bit(int nr, unsigned long *addr)
13 addr[nr / BITS_PER_LONG] |= 1UL << (nr % BITS_PER_LONG); 14 addr[nr / BITS_PER_LONG] |= 1UL << (nr % BITS_PER_LONG);
14} 15}
15 16
17static inline void clear_bit(int nr, unsigned long *addr)
18{
19 addr[nr / BITS_PER_LONG] &= ~(1UL << (nr % BITS_PER_LONG));
20}
21
16static __always_inline int test_bit(unsigned int nr, const unsigned long *addr) 22static __always_inline int test_bit(unsigned int nr, const unsigned long *addr)
17{ 23{
18 return ((1UL << (nr % BITS_PER_LONG)) & 24 return ((1UL << (nr % BITS_PER_LONG)) &
diff --git a/tools/perf/util/include/linux/linkage.h b/tools/perf/util/include/linux/linkage.h
new file mode 100644
index 000000000000..06387cffe125
--- /dev/null
+++ b/tools/perf/util/include/linux/linkage.h
@@ -0,0 +1,13 @@
1
2#ifndef PERF_LINUX_LINKAGE_H_
3#define PERF_LINUX_LINKAGE_H_
4
5/* linkage.h ... for including arch/x86/lib/memcpy_64.S */
6
7#define ENTRY(name) \
8 .globl name; \
9 name:
10
11#define ENDPROC(name)
12
13#endif /* PERF_LINUX_LINKAGE_H_ */
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 3a7eb6ec0eec..a16ecab5229d 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -1,5 +1,6 @@
1#include "symbol.h" 1#include "symbol.h"
2#include <errno.h> 2#include <errno.h>
3#include <inttypes.h>
3#include <limits.h> 4#include <limits.h>
4#include <stdlib.h> 5#include <stdlib.h>
5#include <string.h> 6#include <string.h>
@@ -195,7 +196,7 @@ int map__overlap(struct map *l, struct map *r)
195 196
196size_t map__fprintf(struct map *self, FILE *fp) 197size_t map__fprintf(struct map *self, FILE *fp)
197{ 198{
198 return fprintf(fp, " %Lx-%Lx %Lx %s\n", 199 return fprintf(fp, " %" PRIx64 "-%" PRIx64 " %" PRIx64 " %s\n",
199 self->start, self->end, self->pgoff, self->dso->name); 200 self->start, self->end, self->pgoff, self->dso->name);
200} 201}
201 202
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 4af5bd59cfd1..135f69baf966 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -1,6 +1,7 @@
1#include "../../../include/linux/hw_breakpoint.h" 1#include "../../../include/linux/hw_breakpoint.h"
2#include "util.h" 2#include "util.h"
3#include "../perf.h" 3#include "../perf.h"
4#include "evsel.h"
4#include "parse-options.h" 5#include "parse-options.h"
5#include "parse-events.h" 6#include "parse-events.h"
6#include "exec_cmd.h" 7#include "exec_cmd.h"
@@ -12,8 +13,7 @@
12 13
13int nr_counters; 14int nr_counters;
14 15
15struct perf_event_attr attrs[MAX_COUNTERS]; 16LIST_HEAD(evsel_list);
16char *filters[MAX_COUNTERS];
17 17
18struct event_symbol { 18struct event_symbol {
19 u8 type; 19 u8 type;
@@ -266,10 +266,10 @@ static char *event_cache_name(u8 cache_type, u8 cache_op, u8 cache_result)
266 return name; 266 return name;
267} 267}
268 268
269const char *event_name(int counter) 269const char *event_name(struct perf_evsel *evsel)
270{ 270{
271 u64 config = attrs[counter].config; 271 u64 config = evsel->attr.config;
272 int type = attrs[counter].type; 272 int type = evsel->attr.type;
273 273
274 return __event_name(type, config); 274 return __event_name(type, config);
275} 275}
@@ -279,7 +279,7 @@ const char *__event_name(int type, u64 config)
279 static char buf[32]; 279 static char buf[32];
280 280
281 if (type == PERF_TYPE_RAW) { 281 if (type == PERF_TYPE_RAW) {
282 sprintf(buf, "raw 0x%llx", config); 282 sprintf(buf, "raw 0x%" PRIx64, config);
283 return buf; 283 return buf;
284 } 284 }
285 285
@@ -434,7 +434,7 @@ parse_single_tracepoint_event(char *sys_name,
434 id = atoll(id_buf); 434 id = atoll(id_buf);
435 attr->config = id; 435 attr->config = id;
436 attr->type = PERF_TYPE_TRACEPOINT; 436 attr->type = PERF_TYPE_TRACEPOINT;
437 *strp = evt_name + evt_length; 437 *strp += strlen(sys_name) + evt_length + 1; /* + 1 for the ':' */
438 438
439 attr->sample_type |= PERF_SAMPLE_RAW; 439 attr->sample_type |= PERF_SAMPLE_RAW;
440 attr->sample_type |= PERF_SAMPLE_TIME; 440 attr->sample_type |= PERF_SAMPLE_TIME;
@@ -490,12 +490,11 @@ parse_multiple_tracepoint_event(char *sys_name, const char *evt_exp,
490 return EVT_HANDLED_ALL; 490 return EVT_HANDLED_ALL;
491} 491}
492 492
493
494static enum event_result parse_tracepoint_event(const char **strp, 493static enum event_result parse_tracepoint_event(const char **strp,
495 struct perf_event_attr *attr) 494 struct perf_event_attr *attr)
496{ 495{
497 const char *evt_name; 496 const char *evt_name;
498 char *flags; 497 char *flags = NULL, *comma_loc;
499 char sys_name[MAX_EVENT_LENGTH]; 498 char sys_name[MAX_EVENT_LENGTH];
500 unsigned int sys_length, evt_length; 499 unsigned int sys_length, evt_length;
501 500
@@ -514,6 +513,11 @@ static enum event_result parse_tracepoint_event(const char **strp,
514 sys_name[sys_length] = '\0'; 513 sys_name[sys_length] = '\0';
515 evt_name = evt_name + 1; 514 evt_name = evt_name + 1;
516 515
516 comma_loc = strchr(evt_name, ',');
517 if (comma_loc) {
518 /* take the event name up to the comma */
519 evt_name = strndup(evt_name, comma_loc - evt_name);
520 }
517 flags = strchr(evt_name, ':'); 521 flags = strchr(evt_name, ':');
518 if (flags) { 522 if (flags) {
519 /* split it out: */ 523 /* split it out: */
@@ -524,14 +528,14 @@ static enum event_result parse_tracepoint_event(const char **strp,
524 evt_length = strlen(evt_name); 528 evt_length = strlen(evt_name);
525 if (evt_length >= MAX_EVENT_LENGTH) 529 if (evt_length >= MAX_EVENT_LENGTH)
526 return EVT_FAILED; 530 return EVT_FAILED;
527
528 if (strpbrk(evt_name, "*?")) { 531 if (strpbrk(evt_name, "*?")) {
529 *strp = evt_name + evt_length; 532 *strp += strlen(sys_name) + evt_length + 1; /* 1 == the ':' */
530 return parse_multiple_tracepoint_event(sys_name, evt_name, 533 return parse_multiple_tracepoint_event(sys_name, evt_name,
531 flags); 534 flags);
532 } else 535 } else {
533 return parse_single_tracepoint_event(sys_name, evt_name, 536 return parse_single_tracepoint_event(sys_name, evt_name,
534 evt_length, attr, strp); 537 evt_length, attr, strp);
538 }
535} 539}
536 540
537static enum event_result 541static enum event_result
@@ -774,45 +778,12 @@ modifier:
774 return ret; 778 return ret;
775} 779}
776 780
777static int store_event_type(const char *orgname)
778{
779 char filename[PATH_MAX], *c;
780 FILE *file;
781 int id, n;
782
783 sprintf(filename, "%s/", debugfs_path);
784 strncat(filename, orgname, strlen(orgname));
785 strcat(filename, "/id");
786
787 c = strchr(filename, ':');
788 if (c)
789 *c = '/';
790
791 file = fopen(filename, "r");
792 if (!file)
793 return 0;
794 n = fscanf(file, "%i", &id);
795 fclose(file);
796 if (n < 1) {
797 pr_err("cannot store event ID\n");
798 return -EINVAL;
799 }
800 return perf_header__push_event(id, orgname);
801}
802
803int parse_events(const struct option *opt __used, const char *str, int unset __used) 781int parse_events(const struct option *opt __used, const char *str, int unset __used)
804{ 782{
805 struct perf_event_attr attr; 783 struct perf_event_attr attr;
806 enum event_result ret; 784 enum event_result ret;
807 785
808 if (strchr(str, ':'))
809 if (store_event_type(str) < 0)
810 return -1;
811
812 for (;;) { 786 for (;;) {
813 if (nr_counters == MAX_COUNTERS)
814 return -1;
815
816 memset(&attr, 0, sizeof(attr)); 787 memset(&attr, 0, sizeof(attr));
817 ret = parse_event_symbols(&str, &attr); 788 ret = parse_event_symbols(&str, &attr);
818 if (ret == EVT_FAILED) 789 if (ret == EVT_FAILED)
@@ -822,8 +793,13 @@ int parse_events(const struct option *opt __used, const char *str, int unset __u
822 return -1; 793 return -1;
823 794
824 if (ret != EVT_HANDLED_ALL) { 795 if (ret != EVT_HANDLED_ALL) {
825 attrs[nr_counters] = attr; 796 struct perf_evsel *evsel;
826 nr_counters++; 797 evsel = perf_evsel__new(&attr,
798 nr_counters);
799 if (evsel == NULL)
800 return -1;
801 list_add_tail(&evsel->node, &evsel_list);
802 ++nr_counters;
827 } 803 }
828 804
829 if (*str == 0) 805 if (*str == 0)
@@ -840,21 +816,22 @@ int parse_events(const struct option *opt __used, const char *str, int unset __u
840int parse_filter(const struct option *opt __used, const char *str, 816int parse_filter(const struct option *opt __used, const char *str,
841 int unset __used) 817 int unset __used)
842{ 818{
843 int i = nr_counters - 1; 819 struct perf_evsel *last = NULL;
844 int len = strlen(str); 820
821 if (!list_empty(&evsel_list))
822 last = list_entry(evsel_list.prev, struct perf_evsel, node);
845 823
846 if (i < 0 || attrs[i].type != PERF_TYPE_TRACEPOINT) { 824 if (last == NULL || last->attr.type != PERF_TYPE_TRACEPOINT) {
847 fprintf(stderr, 825 fprintf(stderr,
848 "-F option should follow a -e tracepoint option\n"); 826 "-F option should follow a -e tracepoint option\n");
849 return -1; 827 return -1;
850 } 828 }
851 829
852 filters[i] = malloc(len + 1); 830 last->filter = strdup(str);
853 if (!filters[i]) { 831 if (last->filter == NULL) {
854 fprintf(stderr, "not enough memory to hold filter string\n"); 832 fprintf(stderr, "not enough memory to hold filter string\n");
855 return -1; 833 return -1;
856 } 834 }
857 strcpy(filters[i], str);
858 835
859 return 0; 836 return 0;
860} 837}
@@ -906,6 +883,47 @@ static void print_tracepoint_events(void)
906} 883}
907 884
908/* 885/*
886 * Check whether event is in <debugfs_mount_point>/tracing/events
887 */
888
889int is_valid_tracepoint(const char *event_string)
890{
891 DIR *sys_dir, *evt_dir;
892 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
893 char evt_path[MAXPATHLEN];
894 char dir_path[MAXPATHLEN];
895
896 if (debugfs_valid_mountpoint(debugfs_path))
897 return 0;
898
899 sys_dir = opendir(debugfs_path);
900 if (!sys_dir)
901 return 0;
902
903 for_each_subsystem(sys_dir, sys_dirent, sys_next) {
904
905 snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path,
906 sys_dirent.d_name);
907 evt_dir = opendir(dir_path);
908 if (!evt_dir)
909 continue;
910
911 for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
912 snprintf(evt_path, MAXPATHLEN, "%s:%s",
913 sys_dirent.d_name, evt_dirent.d_name);
914 if (!strcmp(evt_path, event_string)) {
915 closedir(evt_dir);
916 closedir(sys_dir);
917 return 1;
918 }
919 }
920 closedir(evt_dir);
921 }
922 closedir(sys_dir);
923 return 0;
924}
925
926/*
909 * Print the help text for the event symbols: 927 * Print the help text for the event symbols:
910 */ 928 */
911void print_events(void) 929void print_events(void)
@@ -963,3 +981,33 @@ void print_events(void)
963 981
964 exit(129); 982 exit(129);
965} 983}
984
985int perf_evsel_list__create_default(void)
986{
987 struct perf_evsel *evsel;
988 struct perf_event_attr attr;
989
990 memset(&attr, 0, sizeof(attr));
991 attr.type = PERF_TYPE_HARDWARE;
992 attr.config = PERF_COUNT_HW_CPU_CYCLES;
993
994 evsel = perf_evsel__new(&attr, 0);
995
996 if (evsel == NULL)
997 return -ENOMEM;
998
999 list_add(&evsel->node, &evsel_list);
1000 ++nr_counters;
1001 return 0;
1002}
1003
1004void perf_evsel_list__delete(void)
1005{
1006 struct perf_evsel *pos, *n;
1007
1008 list_for_each_entry_safe(pos, n, &evsel_list, node) {
1009 list_del_init(&pos->node);
1010 perf_evsel__delete(pos);
1011 }
1012 nr_counters = 0;
1013}
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index fc4ab3fe877a..458e3ecf17af 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -4,6 +4,16 @@
4 * Parse symbolic events/counts passed in as options: 4 * Parse symbolic events/counts passed in as options:
5 */ 5 */
6 6
7#include "../../../include/linux/perf_event.h"
8
9struct list_head;
10struct perf_evsel;
11
12extern struct list_head evsel_list;
13
14int perf_evsel_list__create_default(void);
15void perf_evsel_list__delete(void);
16
7struct option; 17struct option;
8 18
9struct tracepoint_path { 19struct tracepoint_path {
@@ -13,14 +23,11 @@ struct tracepoint_path {
13}; 23};
14 24
15extern struct tracepoint_path *tracepoint_id_to_path(u64 config); 25extern struct tracepoint_path *tracepoint_id_to_path(u64 config);
16extern bool have_tracepoints(struct perf_event_attr *pattrs, int nb_events); 26extern bool have_tracepoints(struct list_head *evlist);
17 27
18extern int nr_counters; 28extern int nr_counters;
19 29
20extern struct perf_event_attr attrs[MAX_COUNTERS]; 30const char *event_name(struct perf_evsel *event);
21extern char *filters[MAX_COUNTERS];
22
23extern const char *event_name(int ctr);
24extern const char *__event_name(int type, u64 config); 31extern const char *__event_name(int type, u64 config);
25 32
26extern int parse_events(const struct option *opt, const char *str, int unset); 33extern int parse_events(const struct option *opt, const char *str, int unset);
@@ -29,9 +36,9 @@ extern int parse_filter(const struct option *opt, const char *str, int unset);
29#define EVENTS_HELP_MAX (128*1024) 36#define EVENTS_HELP_MAX (128*1024)
30 37
31extern void print_events(void); 38extern void print_events(void);
39extern int is_valid_tracepoint(const char *event_string);
32 40
33extern char debugfs_path[]; 41extern char debugfs_path[];
34extern int valid_debugfs_mount(const char *debugfs); 42extern int valid_debugfs_mount(const char *debugfs);
35 43
36
37#endif /* __PERF_PARSE_EVENTS_H */ 44#endif /* __PERF_PARSE_EVENTS_H */
diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h
index c7d72dce54b2..abc31a1dac1a 100644
--- a/tools/perf/util/parse-options.h
+++ b/tools/perf/util/parse-options.h
@@ -119,6 +119,10 @@ struct option {
119 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f), .flags = PARSE_OPT_NOARG } 119 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f), .flags = PARSE_OPT_NOARG }
120#define OPT_CALLBACK_DEFAULT(s, l, v, a, h, f, d) \ 120#define OPT_CALLBACK_DEFAULT(s, l, v, a, h, f, d) \
121 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f), .defval = (intptr_t)d, .flags = PARSE_OPT_LASTARG_DEFAULT } 121 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f), .defval = (intptr_t)d, .flags = PARSE_OPT_LASTARG_DEFAULT }
122#define OPT_CALLBACK_DEFAULT_NOOPT(s, l, v, a, h, f, d) \
123 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l),\
124 .value = (v), (a), .help = (h), .callback = (f), .defval = (intptr_t)d,\
125 .flags = PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NOARG}
122 126
123/* parse_options() will filter out the processed options and leave the 127/* parse_options() will filter out the processed options and leave the
124 * non-option argments in argv[]. 128 * non-option argments in argv[].
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 3b6a5297bf16..6e29d9c9dccc 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -95,7 +95,7 @@ static int init_vmlinux(void)
95 goto out; 95 goto out;
96 96
97 if (machine__create_kernel_maps(&machine) < 0) { 97 if (machine__create_kernel_maps(&machine) < 0) {
98 pr_debug("machine__create_kernel_maps "); 98 pr_debug("machine__create_kernel_maps() failed.\n");
99 goto out; 99 goto out;
100 } 100 }
101out: 101out:
@@ -114,6 +114,8 @@ static struct symbol *__find_kernel_function_by_name(const char *name,
114const char *kernel_get_module_path(const char *module) 114const char *kernel_get_module_path(const char *module)
115{ 115{
116 struct dso *dso; 116 struct dso *dso;
117 struct map *map;
118 const char *vmlinux_name;
117 119
118 if (module) { 120 if (module) {
119 list_for_each_entry(dso, &machine.kernel_dsos, node) { 121 list_for_each_entry(dso, &machine.kernel_dsos, node) {
@@ -123,10 +125,17 @@ const char *kernel_get_module_path(const char *module)
123 } 125 }
124 pr_debug("Failed to find module %s.\n", module); 126 pr_debug("Failed to find module %s.\n", module);
125 return NULL; 127 return NULL;
128 }
129
130 map = machine.vmlinux_maps[MAP__FUNCTION];
131 dso = map->dso;
132
133 vmlinux_name = symbol_conf.vmlinux_name;
134 if (vmlinux_name) {
135 if (dso__load_vmlinux(dso, map, vmlinux_name, NULL) <= 0)
136 return NULL;
126 } else { 137 } else {
127 dso = machine.vmlinux_maps[MAP__FUNCTION]->dso; 138 if (dso__load_vmlinux_path(dso, map, NULL) <= 0) {
128 if (dso__load_vmlinux_path(dso,
129 machine.vmlinux_maps[MAP__FUNCTION], NULL) < 0) {
130 pr_debug("Failed to load kernel map.\n"); 139 pr_debug("Failed to load kernel map.\n");
131 return NULL; 140 return NULL;
132 } 141 }
@@ -140,7 +149,8 @@ static int open_vmlinux(const char *module)
140{ 149{
141 const char *path = kernel_get_module_path(module); 150 const char *path = kernel_get_module_path(module);
142 if (!path) { 151 if (!path) {
143 pr_err("Failed to find path of %s module", module ?: "kernel"); 152 pr_err("Failed to find path of %s module.\n",
153 module ?: "kernel");
144 return -ENOENT; 154 return -ENOENT;
145 } 155 }
146 pr_debug("Try to open %s\n", path); 156 pr_debug("Try to open %s\n", path);
@@ -162,7 +172,7 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
162 sym = __find_kernel_function_by_name(tp->symbol, &map); 172 sym = __find_kernel_function_by_name(tp->symbol, &map);
163 if (sym) { 173 if (sym) {
164 addr = map->unmap_ip(map, sym->start + tp->offset); 174 addr = map->unmap_ip(map, sym->start + tp->offset);
165 pr_debug("try to find %s+%ld@%llx\n", tp->symbol, 175 pr_debug("try to find %s+%ld@%" PRIx64 "\n", tp->symbol,
166 tp->offset, addr); 176 tp->offset, addr);
167 ret = find_perf_probe_point((unsigned long)addr, pp); 177 ret = find_perf_probe_point((unsigned long)addr, pp);
168 } 178 }
@@ -217,7 +227,7 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
217 pr_warning("Warning: No dwarf info found in the vmlinux - " 227 pr_warning("Warning: No dwarf info found in the vmlinux - "
218 "please rebuild kernel with CONFIG_DEBUG_INFO=y.\n"); 228 "please rebuild kernel with CONFIG_DEBUG_INFO=y.\n");
219 if (!need_dwarf) { 229 if (!need_dwarf) {
220 pr_debug("Trying to use symbols.\nn"); 230 pr_debug("Trying to use symbols.\n");
221 return 0; 231 return 0;
222 } 232 }
223 } 233 }
@@ -286,42 +296,49 @@ static int get_real_path(const char *raw_path, const char *comp_dir,
286#define LINEBUF_SIZE 256 296#define LINEBUF_SIZE 256
287#define NR_ADDITIONAL_LINES 2 297#define NR_ADDITIONAL_LINES 2
288 298
289static int show_one_line(FILE *fp, int l, bool skip, bool show_num) 299static int __show_one_line(FILE *fp, int l, bool skip, bool show_num)
290{ 300{
291 char buf[LINEBUF_SIZE]; 301 char buf[LINEBUF_SIZE];
292 const char *color = PERF_COLOR_BLUE; 302 const char *color = show_num ? "" : PERF_COLOR_BLUE;
293 303 const char *prefix = NULL;
294 if (fgets(buf, LINEBUF_SIZE, fp) == NULL)
295 goto error;
296 if (!skip) {
297 if (show_num)
298 fprintf(stdout, "%7d %s", l, buf);
299 else
300 color_fprintf(stdout, color, " %s", buf);
301 }
302 304
303 while (strlen(buf) == LINEBUF_SIZE - 1 && 305 do {
304 buf[LINEBUF_SIZE - 2] != '\n') {
305 if (fgets(buf, LINEBUF_SIZE, fp) == NULL) 306 if (fgets(buf, LINEBUF_SIZE, fp) == NULL)
306 goto error; 307 goto error;
307 if (!skip) { 308 if (skip)
308 if (show_num) 309 continue;
309 fprintf(stdout, "%s", buf); 310 if (!prefix) {
310 else 311 prefix = show_num ? "%7d " : " ";
311 color_fprintf(stdout, color, "%s", buf); 312 color_fprintf(stdout, color, prefix, l);
312 } 313 }
313 } 314 color_fprintf(stdout, color, "%s", buf);
314 315
315 return 0; 316 } while (strchr(buf, '\n') == NULL);
317
318 return 1;
316error: 319error:
317 if (feof(fp)) 320 if (ferror(fp)) {
318 pr_warning("Source file is shorter than expected.\n");
319 else
320 pr_warning("File read error: %s\n", strerror(errno)); 321 pr_warning("File read error: %s\n", strerror(errno));
322 return -1;
323 }
324 return 0;
325}
321 326
322 return -1; 327static int _show_one_line(FILE *fp, int l, bool skip, bool show_num)
328{
329 int rv = __show_one_line(fp, l, skip, show_num);
330 if (rv == 0) {
331 pr_warning("Source file is shorter than expected.\n");
332 rv = -1;
333 }
334 return rv;
323} 335}
324 336
337#define show_one_line_with_num(f,l) _show_one_line(f,l,false,true)
338#define show_one_line(f,l) _show_one_line(f,l,false,false)
339#define skip_one_line(f,l) _show_one_line(f,l,true,false)
340#define show_one_line_or_eof(f,l) __show_one_line(f,l,false,false)
341
325/* 342/*
326 * Show line-range always requires debuginfo to find source file and 343 * Show line-range always requires debuginfo to find source file and
327 * line number. 344 * line number.
@@ -370,7 +387,7 @@ int show_line_range(struct line_range *lr, const char *module)
370 fprintf(stdout, "<%s:%d>\n", lr->function, 387 fprintf(stdout, "<%s:%d>\n", lr->function,
371 lr->start - lr->offset); 388 lr->start - lr->offset);
372 else 389 else
373 fprintf(stdout, "<%s:%d>\n", lr->file, lr->start); 390 fprintf(stdout, "<%s:%d>\n", lr->path, lr->start);
374 391
375 fp = fopen(lr->path, "r"); 392 fp = fopen(lr->path, "r");
376 if (fp == NULL) { 393 if (fp == NULL) {
@@ -379,26 +396,30 @@ int show_line_range(struct line_range *lr, const char *module)
379 return -errno; 396 return -errno;
380 } 397 }
381 /* Skip to starting line number */ 398 /* Skip to starting line number */
382 while (l < lr->start && ret >= 0) 399 while (l < lr->start) {
383 ret = show_one_line(fp, l++, true, false); 400 ret = skip_one_line(fp, l++);
384 if (ret < 0) 401 if (ret < 0)
385 goto end; 402 goto end;
403 }
386 404
387 list_for_each_entry(ln, &lr->line_list, list) { 405 list_for_each_entry(ln, &lr->line_list, list) {
388 while (ln->line > l && ret >= 0) 406 for (; ln->line > l; l++) {
389 ret = show_one_line(fp, (l++) - lr->offset, 407 ret = show_one_line(fp, l - lr->offset);
390 false, false); 408 if (ret < 0)
391 if (ret >= 0) 409 goto end;
392 ret = show_one_line(fp, (l++) - lr->offset, 410 }
393 false, true); 411 ret = show_one_line_with_num(fp, l++ - lr->offset);
394 if (ret < 0) 412 if (ret < 0)
395 goto end; 413 goto end;
396 } 414 }
397 415
398 if (lr->end == INT_MAX) 416 if (lr->end == INT_MAX)
399 lr->end = l + NR_ADDITIONAL_LINES; 417 lr->end = l + NR_ADDITIONAL_LINES;
400 while (l <= lr->end && !feof(fp) && ret >= 0) 418 while (l <= lr->end) {
401 ret = show_one_line(fp, (l++) - lr->offset, false, false); 419 ret = show_one_line_or_eof(fp, l++ - lr->offset);
420 if (ret <= 0)
421 break;
422 }
402end: 423end:
403 fclose(fp); 424 fclose(fp);
404 return ret; 425 return ret;
@@ -457,7 +478,7 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
457 478
458 fd = open_vmlinux(module); 479 fd = open_vmlinux(module);
459 if (fd < 0) { 480 if (fd < 0) {
460 pr_warning("Failed to open debuginfo file.\n"); 481 pr_warning("Failed to open debug information file.\n");
461 return fd; 482 return fd;
462 } 483 }
463 484
@@ -517,56 +538,87 @@ int show_available_vars(struct perf_probe_event *pevs __unused,
517} 538}
518#endif 539#endif
519 540
541static int parse_line_num(char **ptr, int *val, const char *what)
542{
543 const char *start = *ptr;
544
545 errno = 0;
546 *val = strtol(*ptr, ptr, 0);
547 if (errno || *ptr == start) {
548 semantic_error("'%s' is not a valid number.\n", what);
549 return -EINVAL;
550 }
551 return 0;
552}
553
554/*
555 * Stuff 'lr' according to the line range described by 'arg'.
556 * The line range syntax is described by:
557 *
558 * SRC[:SLN[+NUM|-ELN]]
559 * FNC[:SLN[+NUM|-ELN]]
560 */
520int parse_line_range_desc(const char *arg, struct line_range *lr) 561int parse_line_range_desc(const char *arg, struct line_range *lr)
521{ 562{
522 const char *ptr; 563 char *range, *name = strdup(arg);
523 char *tmp; 564 int err;
524 /* 565
525 * <Syntax> 566 if (!name)
526 * SRC:SLN[+NUM|-ELN] 567 return -ENOMEM;
527 * FUNC[:SLN[+NUM|-ELN]] 568
528 */ 569 lr->start = 0;
529 ptr = strchr(arg, ':'); 570 lr->end = INT_MAX;
530 if (ptr) { 571
531 lr->start = (int)strtoul(ptr + 1, &tmp, 0); 572 range = strchr(name, ':');
532 if (*tmp == '+') { 573 if (range) {
533 lr->end = lr->start + (int)strtoul(tmp + 1, &tmp, 0); 574 *range++ = '\0';
534 lr->end--; /* 575
535 * Adjust the number of lines here. 576 err = parse_line_num(&range, &lr->start, "start line");
536 * If the number of lines == 1, the 577 if (err)
537 * the end of line should be equal to 578 goto err;
538 * the start of line. 579
539 */ 580 if (*range == '+' || *range == '-') {
540 } else if (*tmp == '-') 581 const char c = *range++;
541 lr->end = (int)strtoul(tmp + 1, &tmp, 0); 582
542 else 583 err = parse_line_num(&range, &lr->end, "end line");
543 lr->end = INT_MAX; 584 if (err)
585 goto err;
586
587 if (c == '+') {
588 lr->end += lr->start;
589 /*
590 * Adjust the number of lines here.
591 * If the number of lines == 1, the
592 * the end of line should be equal to
593 * the start of line.
594 */
595 lr->end--;
596 }
597 }
598
544 pr_debug("Line range is %d to %d\n", lr->start, lr->end); 599 pr_debug("Line range is %d to %d\n", lr->start, lr->end);
600
601 err = -EINVAL;
545 if (lr->start > lr->end) { 602 if (lr->start > lr->end) {
546 semantic_error("Start line must be smaller" 603 semantic_error("Start line must be smaller"
547 " than end line.\n"); 604 " than end line.\n");
548 return -EINVAL; 605 goto err;
549 } 606 }
550 if (*tmp != '\0') { 607 if (*range != '\0') {
551 semantic_error("Tailing with invalid character '%d'.\n", 608 semantic_error("Tailing with invalid str '%s'.\n", range);
552 *tmp); 609 goto err;
553 return -EINVAL;
554 } 610 }
555 tmp = strndup(arg, (ptr - arg));
556 } else {
557 tmp = strdup(arg);
558 lr->end = INT_MAX;
559 } 611 }
560 612
561 if (tmp == NULL) 613 if (strchr(name, '.'))
562 return -ENOMEM; 614 lr->file = name;
563
564 if (strchr(tmp, '.'))
565 lr->file = tmp;
566 else 615 else
567 lr->function = tmp; 616 lr->function = name;
568 617
569 return 0; 618 return 0;
619err:
620 free(name);
621 return err;
570} 622}
571 623
572/* Check the name is good for event/group */ 624/* Check the name is good for event/group */
@@ -690,39 +742,40 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
690 742
691 /* Exclusion check */ 743 /* Exclusion check */
692 if (pp->lazy_line && pp->line) { 744 if (pp->lazy_line && pp->line) {
693 semantic_error("Lazy pattern can't be used with line number."); 745 semantic_error("Lazy pattern can't be used with"
746 " line number.\n");
694 return -EINVAL; 747 return -EINVAL;
695 } 748 }
696 749
697 if (pp->lazy_line && pp->offset) { 750 if (pp->lazy_line && pp->offset) {
698 semantic_error("Lazy pattern can't be used with offset."); 751 semantic_error("Lazy pattern can't be used with offset.\n");
699 return -EINVAL; 752 return -EINVAL;
700 } 753 }
701 754
702 if (pp->line && pp->offset) { 755 if (pp->line && pp->offset) {
703 semantic_error("Offset can't be used with line number."); 756 semantic_error("Offset can't be used with line number.\n");
704 return -EINVAL; 757 return -EINVAL;
705 } 758 }
706 759
707 if (!pp->line && !pp->lazy_line && pp->file && !pp->function) { 760 if (!pp->line && !pp->lazy_line && pp->file && !pp->function) {
708 semantic_error("File always requires line number or " 761 semantic_error("File always requires line number or "
709 "lazy pattern."); 762 "lazy pattern.\n");
710 return -EINVAL; 763 return -EINVAL;
711 } 764 }
712 765
713 if (pp->offset && !pp->function) { 766 if (pp->offset && !pp->function) {
714 semantic_error("Offset requires an entry function."); 767 semantic_error("Offset requires an entry function.\n");
715 return -EINVAL; 768 return -EINVAL;
716 } 769 }
717 770
718 if (pp->retprobe && !pp->function) { 771 if (pp->retprobe && !pp->function) {
719 semantic_error("Return probe requires an entry function."); 772 semantic_error("Return probe requires an entry function.\n");
720 return -EINVAL; 773 return -EINVAL;
721 } 774 }
722 775
723 if ((pp->offset || pp->line || pp->lazy_line) && pp->retprobe) { 776 if ((pp->offset || pp->line || pp->lazy_line) && pp->retprobe) {
724 semantic_error("Offset/Line/Lazy pattern can't be used with " 777 semantic_error("Offset/Line/Lazy pattern can't be used with "
725 "return probe."); 778 "return probe.\n");
726 return -EINVAL; 779 return -EINVAL;
727 } 780 }
728 781
@@ -996,7 +1049,7 @@ int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len)
996 1049
997 return tmp - buf; 1050 return tmp - buf;
998error: 1051error:
999 pr_debug("Failed to synthesize perf probe argument: %s", 1052 pr_debug("Failed to synthesize perf probe argument: %s\n",
1000 strerror(-ret)); 1053 strerror(-ret));
1001 return ret; 1054 return ret;
1002} 1055}
@@ -1024,13 +1077,13 @@ static char *synthesize_perf_probe_point(struct perf_probe_point *pp)
1024 goto error; 1077 goto error;
1025 } 1078 }
1026 if (pp->file) { 1079 if (pp->file) {
1027 len = strlen(pp->file) - 31; 1080 tmp = pp->file;
1028 if (len < 0) 1081 len = strlen(tmp);
1029 len = 0; 1082 if (len > 30) {
1030 tmp = strchr(pp->file + len, '/'); 1083 tmp = strchr(pp->file + len - 30, '/');
1031 if (!tmp) 1084 tmp = tmp ? tmp + 1 : pp->file + len - 30;
1032 tmp = pp->file + len; 1085 }
1033 ret = e_snprintf(file, 32, "@%s", tmp + 1); 1086 ret = e_snprintf(file, 32, "@%s", tmp);
1034 if (ret <= 0) 1087 if (ret <= 0)
1035 goto error; 1088 goto error;
1036 } 1089 }
@@ -1046,7 +1099,7 @@ static char *synthesize_perf_probe_point(struct perf_probe_point *pp)
1046 1099
1047 return buf; 1100 return buf;
1048error: 1101error:
1049 pr_debug("Failed to synthesize perf probe point: %s", 1102 pr_debug("Failed to synthesize perf probe point: %s\n",
1050 strerror(-ret)); 1103 strerror(-ret));
1051 if (buf) 1104 if (buf)
1052 free(buf); 1105 free(buf);
@@ -1787,7 +1840,7 @@ static int del_trace_probe_event(int fd, const char *group,
1787 1840
1788 ret = e_snprintf(buf, 128, "%s:%s", group, event); 1841 ret = e_snprintf(buf, 128, "%s:%s", group, event);
1789 if (ret < 0) { 1842 if (ret < 0) {
1790 pr_err("Failed to copy event."); 1843 pr_err("Failed to copy event.\n");
1791 return ret; 1844 return ret;
1792 } 1845 }
1793 1846
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 3991d73d1cff..ab83b6ac5d65 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -117,28 +117,6 @@ static void line_list__free(struct list_head *head)
117} 117}
118 118
119/* Dwarf FL wrappers */ 119/* Dwarf FL wrappers */
120
121static int __linux_kernel_find_elf(Dwfl_Module *mod,
122 void **userdata,
123 const char *module_name,
124 Dwarf_Addr base,
125 char **file_name, Elf **elfp)
126{
127 int fd;
128 const char *path = kernel_get_module_path(module_name);
129
130 if (path) {
131 fd = open(path, O_RDONLY);
132 if (fd >= 0) {
133 *file_name = strdup(path);
134 return fd;
135 }
136 }
137 /* If failed, try to call standard method */
138 return dwfl_linux_kernel_find_elf(mod, userdata, module_name, base,
139 file_name, elfp);
140}
141
142static char *debuginfo_path; /* Currently dummy */ 120static char *debuginfo_path; /* Currently dummy */
143 121
144static const Dwfl_Callbacks offline_callbacks = { 122static const Dwfl_Callbacks offline_callbacks = {
@@ -151,14 +129,6 @@ static const Dwfl_Callbacks offline_callbacks = {
151 .find_elf = dwfl_build_id_find_elf, 129 .find_elf = dwfl_build_id_find_elf,
152}; 130};
153 131
154static const Dwfl_Callbacks kernel_callbacks = {
155 .find_debuginfo = dwfl_standard_find_debuginfo,
156 .debuginfo_path = &debuginfo_path,
157
158 .find_elf = __linux_kernel_find_elf,
159 .section_address = dwfl_linux_kernel_module_section_address,
160};
161
162/* Get a Dwarf from offline image */ 132/* Get a Dwarf from offline image */
163static Dwarf *dwfl_init_offline_dwarf(int fd, Dwfl **dwflp, Dwarf_Addr *bias) 133static Dwarf *dwfl_init_offline_dwarf(int fd, Dwfl **dwflp, Dwarf_Addr *bias)
164{ 134{
@@ -185,6 +155,38 @@ error:
185 return dbg; 155 return dbg;
186} 156}
187 157
158#if _ELFUTILS_PREREQ(0, 148)
159/* This method is buggy if elfutils is older than 0.148 */
160static int __linux_kernel_find_elf(Dwfl_Module *mod,
161 void **userdata,
162 const char *module_name,
163 Dwarf_Addr base,
164 char **file_name, Elf **elfp)
165{
166 int fd;
167 const char *path = kernel_get_module_path(module_name);
168
169 pr_debug2("Use file %s for %s\n", path, module_name);
170 if (path) {
171 fd = open(path, O_RDONLY);
172 if (fd >= 0) {
173 *file_name = strdup(path);
174 return fd;
175 }
176 }
177 /* If failed, try to call standard method */
178 return dwfl_linux_kernel_find_elf(mod, userdata, module_name, base,
179 file_name, elfp);
180}
181
182static const Dwfl_Callbacks kernel_callbacks = {
183 .find_debuginfo = dwfl_standard_find_debuginfo,
184 .debuginfo_path = &debuginfo_path,
185
186 .find_elf = __linux_kernel_find_elf,
187 .section_address = dwfl_linux_kernel_module_section_address,
188};
189
188/* Get a Dwarf from live kernel image */ 190/* Get a Dwarf from live kernel image */
189static Dwarf *dwfl_init_live_kernel_dwarf(Dwarf_Addr addr, Dwfl **dwflp, 191static Dwarf *dwfl_init_live_kernel_dwarf(Dwarf_Addr addr, Dwfl **dwflp,
190 Dwarf_Addr *bias) 192 Dwarf_Addr *bias)
@@ -205,11 +207,34 @@ static Dwarf *dwfl_init_live_kernel_dwarf(Dwarf_Addr addr, Dwfl **dwflp,
205 dbg = dwfl_addrdwarf(*dwflp, addr, bias); 207 dbg = dwfl_addrdwarf(*dwflp, addr, bias);
206 /* Here, check whether we could get a real dwarf */ 208 /* Here, check whether we could get a real dwarf */
207 if (!dbg) { 209 if (!dbg) {
210 pr_debug("Failed to find kernel dwarf at %lx\n",
211 (unsigned long)addr);
208 dwfl_end(*dwflp); 212 dwfl_end(*dwflp);
209 *dwflp = NULL; 213 *dwflp = NULL;
210 } 214 }
211 return dbg; 215 return dbg;
212} 216}
217#else
218/* With older elfutils, this just support kernel module... */
219static Dwarf *dwfl_init_live_kernel_dwarf(Dwarf_Addr addr __used, Dwfl **dwflp,
220 Dwarf_Addr *bias)
221{
222 int fd;
223 const char *path = kernel_get_module_path("kernel");
224
225 if (!path) {
226 pr_err("Failed to find vmlinux path\n");
227 return NULL;
228 }
229
230 pr_debug2("Use file %s for debuginfo\n", path);
231 fd = open(path, O_RDONLY);
232 if (fd < 0)
233 return NULL;
234
235 return dwfl_init_offline_dwarf(fd, dwflp, bias);
236}
237#endif
213 238
214/* Dwarf wrappers */ 239/* Dwarf wrappers */
215 240
@@ -627,8 +652,8 @@ static_var:
627 regs = get_arch_regstr(regn); 652 regs = get_arch_regstr(regn);
628 if (!regs) { 653 if (!regs) {
629 /* This should be a bug in DWARF or this tool */ 654 /* This should be a bug in DWARF or this tool */
630 pr_warning("Mapping for DWARF register number %u " 655 pr_warning("Mapping for the register number %u "
631 "missing on this architecture.", regn); 656 "missing on this architecture.\n", regn);
632 return -ERANGE; 657 return -ERANGE;
633 } 658 }
634 659
@@ -674,13 +699,14 @@ static int convert_variable_type(Dwarf_Die *vr_die,
674 if (ret != DW_TAG_pointer_type && 699 if (ret != DW_TAG_pointer_type &&
675 ret != DW_TAG_array_type) { 700 ret != DW_TAG_array_type) {
676 pr_warning("Failed to cast into string: " 701 pr_warning("Failed to cast into string: "
677 "%s(%s) is not a pointer nor array.", 702 "%s(%s) is not a pointer nor array.\n",
678 dwarf_diename(vr_die), dwarf_diename(&type)); 703 dwarf_diename(vr_die), dwarf_diename(&type));
679 return -EINVAL; 704 return -EINVAL;
680 } 705 }
681 if (ret == DW_TAG_pointer_type) { 706 if (ret == DW_TAG_pointer_type) {
682 if (die_get_real_type(&type, &type) == NULL) { 707 if (die_get_real_type(&type, &type) == NULL) {
683 pr_warning("Failed to get a type information."); 708 pr_warning("Failed to get a type"
709 " information.\n");
684 return -ENOENT; 710 return -ENOENT;
685 } 711 }
686 while (*ref_ptr) 712 while (*ref_ptr)
@@ -695,7 +721,7 @@ static int convert_variable_type(Dwarf_Die *vr_die,
695 if (!die_compare_name(&type, "char") && 721 if (!die_compare_name(&type, "char") &&
696 !die_compare_name(&type, "unsigned char")) { 722 !die_compare_name(&type, "unsigned char")) {
697 pr_warning("Failed to cast into string: " 723 pr_warning("Failed to cast into string: "
698 "%s is not (unsigned) char *.", 724 "%s is not (unsigned) char *.\n",
699 dwarf_diename(vr_die)); 725 dwarf_diename(vr_die));
700 return -EINVAL; 726 return -EINVAL;
701 } 727 }
@@ -805,8 +831,8 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
805 return -EINVAL; 831 return -EINVAL;
806 } 832 }
807 if (field->name[0] == '[') { 833 if (field->name[0] == '[') {
808 pr_err("Semantic error: %s is not a pointor nor array.", 834 pr_err("Semantic error: %s is not a pointor"
809 varname); 835 " nor array.\n", varname);
810 return -EINVAL; 836 return -EINVAL;
811 } 837 }
812 if (field->ref) { 838 if (field->ref) {
@@ -953,7 +979,7 @@ static int convert_to_trace_point(Dwarf_Die *sp_die, Dwarf_Addr paddr,
953 name = dwarf_diename(sp_die); 979 name = dwarf_diename(sp_die);
954 if (name) { 980 if (name) {
955 if (dwarf_entrypc(sp_die, &eaddr) != 0) { 981 if (dwarf_entrypc(sp_die, &eaddr) != 0) {
956 pr_warning("Failed to get entry pc of %s\n", 982 pr_warning("Failed to get entry address of %s\n",
957 dwarf_diename(sp_die)); 983 dwarf_diename(sp_die));
958 return -ENOENT; 984 return -ENOENT;
959 } 985 }
@@ -969,7 +995,7 @@ static int convert_to_trace_point(Dwarf_Die *sp_die, Dwarf_Addr paddr,
969 if (retprobe) { 995 if (retprobe) {
970 if (eaddr != paddr) { 996 if (eaddr != paddr) {
971 pr_warning("Return probe must be on the head of" 997 pr_warning("Return probe must be on the head of"
972 " a real function\n"); 998 " a real function.\n");
973 return -EINVAL; 999 return -EINVAL;
974 } 1000 }
975 tp->retprobe = true; 1001 tp->retprobe = true;
@@ -1008,7 +1034,7 @@ static int call_probe_finder(Dwarf_Die *sp_die, struct probe_finder *pf)
1008 Dwarf_Frame *frame; 1034 Dwarf_Frame *frame;
1009 if (dwarf_cfi_addrframe(pf->cfi, pf->addr, &frame) != 0 || 1035 if (dwarf_cfi_addrframe(pf->cfi, pf->addr, &frame) != 0 ||
1010 dwarf_frame_cfa(frame, &pf->fb_ops, &nops) != 0) { 1036 dwarf_frame_cfa(frame, &pf->fb_ops, &nops) != 0) {
1011 pr_warning("Failed to get CFA on 0x%jx\n", 1037 pr_warning("Failed to get call frame on 0x%jx\n",
1012 (uintmax_t)pf->addr); 1038 (uintmax_t)pf->addr);
1013 return -ENOENT; 1039 return -ENOENT;
1014 } 1040 }
@@ -1035,7 +1061,7 @@ static int find_probe_point_by_line(struct probe_finder *pf)
1035 int ret = 0; 1061 int ret = 0;
1036 1062
1037 if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) { 1063 if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) {
1038 pr_warning("No source lines found in this CU.\n"); 1064 pr_warning("No source lines found.\n");
1039 return -ENOENT; 1065 return -ENOENT;
1040 } 1066 }
1041 1067
@@ -1137,7 +1163,7 @@ static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
1137 } 1163 }
1138 1164
1139 if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) { 1165 if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) {
1140 pr_warning("No source lines found in this CU.\n"); 1166 pr_warning("No source lines found.\n");
1141 return -ENOENT; 1167 return -ENOENT;
1142 } 1168 }
1143 1169
@@ -1195,7 +1221,7 @@ static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)
1195 else { 1221 else {
1196 /* Get probe address */ 1222 /* Get probe address */
1197 if (dwarf_entrypc(in_die, &addr) != 0) { 1223 if (dwarf_entrypc(in_die, &addr) != 0) {
1198 pr_warning("Failed to get entry pc of %s.\n", 1224 pr_warning("Failed to get entry address of %s.\n",
1199 dwarf_diename(in_die)); 1225 dwarf_diename(in_die));
1200 param->retval = -ENOENT; 1226 param->retval = -ENOENT;
1201 return DWARF_CB_ABORT; 1227 return DWARF_CB_ABORT;
@@ -1236,8 +1262,8 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
1236 param->retval = find_probe_point_lazy(sp_die, pf); 1262 param->retval = find_probe_point_lazy(sp_die, pf);
1237 else { 1263 else {
1238 if (dwarf_entrypc(sp_die, &pf->addr) != 0) { 1264 if (dwarf_entrypc(sp_die, &pf->addr) != 0) {
1239 pr_warning("Failed to get entry pc of %s.\n", 1265 pr_warning("Failed to get entry address of "
1240 dwarf_diename(sp_die)); 1266 "%s.\n", dwarf_diename(sp_die));
1241 param->retval = -ENOENT; 1267 param->retval = -ENOENT;
1242 return DWARF_CB_ABORT; 1268 return DWARF_CB_ABORT;
1243 } 1269 }
@@ -1279,7 +1305,7 @@ static int find_probes(int fd, struct probe_finder *pf)
1279 1305
1280 dbg = dwfl_init_offline_dwarf(fd, &dwfl, &bias); 1306 dbg = dwfl_init_offline_dwarf(fd, &dwfl, &bias);
1281 if (!dbg) { 1307 if (!dbg) {
1282 pr_warning("No dwarf info found in the vmlinux - " 1308 pr_warning("No debug information found in the vmlinux - "
1283 "please rebuild with CONFIG_DEBUG_INFO=y.\n"); 1309 "please rebuild with CONFIG_DEBUG_INFO=y.\n");
1284 return -EBADF; 1310 return -EBADF;
1285 } 1311 }
@@ -1524,7 +1550,7 @@ int find_perf_probe_point(unsigned long addr, struct perf_probe_point *ppt)
1524 /* Open the live linux kernel */ 1550 /* Open the live linux kernel */
1525 dbg = dwfl_init_live_kernel_dwarf(addr, &dwfl, &bias); 1551 dbg = dwfl_init_live_kernel_dwarf(addr, &dwfl, &bias);
1526 if (!dbg) { 1552 if (!dbg) {
1527 pr_warning("No dwarf info found in the vmlinux - " 1553 pr_warning("No debug information found in the vmlinux - "
1528 "please rebuild with CONFIG_DEBUG_INFO=y.\n"); 1554 "please rebuild with CONFIG_DEBUG_INFO=y.\n");
1529 ret = -EINVAL; 1555 ret = -EINVAL;
1530 goto end; 1556 goto end;
@@ -1534,7 +1560,8 @@ int find_perf_probe_point(unsigned long addr, struct perf_probe_point *ppt)
1534 addr += bias; 1560 addr += bias;
1535 /* Find cu die */ 1561 /* Find cu die */
1536 if (!dwarf_addrdie(dbg, (Dwarf_Addr)addr - bias, &cudie)) { 1562 if (!dwarf_addrdie(dbg, (Dwarf_Addr)addr - bias, &cudie)) {
1537 pr_warning("No CU DIE is found at %lx\n", addr); 1563 pr_warning("Failed to find debug information for address %lx\n",
1564 addr);
1538 ret = -EINVAL; 1565 ret = -EINVAL;
1539 goto end; 1566 goto end;
1540 } 1567 }
@@ -1659,7 +1686,7 @@ static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf)
1659 1686
1660 line_list__init(&lf->lr->line_list); 1687 line_list__init(&lf->lr->line_list);
1661 if (dwarf_getsrclines(&lf->cu_die, &lines, &nlines) != 0) { 1688 if (dwarf_getsrclines(&lf->cu_die, &lines, &nlines) != 0) {
1662 pr_warning("No source lines found in this CU.\n"); 1689 pr_warning("No source lines found.\n");
1663 return -ENOENT; 1690 return -ENOENT;
1664 } 1691 }
1665 1692
@@ -1784,7 +1811,7 @@ int find_line_range(int fd, struct line_range *lr)
1784 1811
1785 dbg = dwfl_init_offline_dwarf(fd, &dwfl, &bias); 1812 dbg = dwfl_init_offline_dwarf(fd, &dwfl, &bias);
1786 if (!dbg) { 1813 if (!dbg) {
1787 pr_warning("No dwarf info found in the vmlinux - " 1814 pr_warning("No debug information found in the vmlinux - "
1788 "please rebuild with CONFIG_DEBUG_INFO=y.\n"); 1815 "please rebuild with CONFIG_DEBUG_INFO=y.\n");
1789 return -EBADF; 1816 return -EBADF;
1790 } 1817 }
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
index bba69d455699..beaefc3c1223 100644
--- a/tools/perf/util/probe-finder.h
+++ b/tools/perf/util/probe-finder.h
@@ -34,9 +34,9 @@ extern int find_available_vars_at(int fd, struct perf_probe_event *pev,
34 bool externs); 34 bool externs);
35 35
36#include <dwarf.h> 36#include <dwarf.h>
37#include <libdw.h> 37#include <elfutils/libdw.h>
38#include <libdwfl.h> 38#include <elfutils/libdwfl.h>
39#include <version.h> 39#include <elfutils/version.h>
40 40
41struct probe_finder { 41struct probe_finder {
42 struct perf_probe_event *pev; /* Target probe event */ 42 struct perf_probe_event *pev; /* Target probe event */
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index b059dc50cc2d..93680818e244 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * trace-event-perl. Feed perf trace events to an embedded Perl interpreter. 2 * trace-event-perl. Feed perf script events to an embedded Perl interpreter.
3 * 3 *
4 * Copyright (C) 2009 Tom Zanussi <tzanussi@gmail.com> 4 * Copyright (C) 2009 Tom Zanussi <tzanussi@gmail.com>
5 * 5 *
@@ -411,8 +411,8 @@ static int perl_generate_script(const char *outfile)
411 return -1; 411 return -1;
412 } 412 }
413 413
414 fprintf(ofp, "# perf trace event handlers, " 414 fprintf(ofp, "# perf script event handlers, "
415 "generated by perf trace -g perl\n"); 415 "generated by perf script -g perl\n");
416 416
417 fprintf(ofp, "# Licensed under the terms of the GNU GPL" 417 fprintf(ofp, "# Licensed under the terms of the GNU GPL"
418 " License version 2\n\n"); 418 " License version 2\n\n");
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 33a632523743..c6d99334bdfa 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -442,8 +442,8 @@ static int python_generate_script(const char *outfile)
442 fprintf(stderr, "couldn't open %s\n", fname); 442 fprintf(stderr, "couldn't open %s\n", fname);
443 return -1; 443 return -1;
444 } 444 }
445 fprintf(ofp, "# perf trace event handlers, " 445 fprintf(ofp, "# perf script event handlers, "
446 "generated by perf trace -g python\n"); 446 "generated by perf script -g python\n");
447 447
448 fprintf(ofp, "# Licensed under the terms of the GNU GPL" 448 fprintf(ofp, "# Licensed under the terms of the GNU GPL"
449 " License version 2\n\n"); 449 " License version 2\n\n");
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index fa9d652c2dc3..105f00bfd555 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -65,9 +65,49 @@ out_close:
65 return -1; 65 return -1;
66} 66}
67 67
68static void perf_session__id_header_size(struct perf_session *session)
69{
70 struct sample_data *data;
71 u64 sample_type = session->sample_type;
72 u16 size = 0;
73
74 if (!session->sample_id_all)
75 goto out;
76
77 if (sample_type & PERF_SAMPLE_TID)
78 size += sizeof(data->tid) * 2;
79
80 if (sample_type & PERF_SAMPLE_TIME)
81 size += sizeof(data->time);
82
83 if (sample_type & PERF_SAMPLE_ID)
84 size += sizeof(data->id);
85
86 if (sample_type & PERF_SAMPLE_STREAM_ID)
87 size += sizeof(data->stream_id);
88
89 if (sample_type & PERF_SAMPLE_CPU)
90 size += sizeof(data->cpu) * 2;
91out:
92 session->id_hdr_size = size;
93}
94
95void perf_session__set_sample_id_all(struct perf_session *session, bool value)
96{
97 session->sample_id_all = value;
98 perf_session__id_header_size(session);
99}
100
101void perf_session__set_sample_type(struct perf_session *session, u64 type)
102{
103 session->sample_type = type;
104}
105
68void perf_session__update_sample_type(struct perf_session *self) 106void perf_session__update_sample_type(struct perf_session *self)
69{ 107{
70 self->sample_type = perf_header__sample_type(&self->header); 108 self->sample_type = perf_header__sample_type(&self->header);
109 self->sample_id_all = perf_header__sample_id_all(&self->header);
110 perf_session__id_header_size(self);
71} 111}
72 112
73int perf_session__create_kernel_maps(struct perf_session *self) 113int perf_session__create_kernel_maps(struct perf_session *self)
@@ -85,7 +125,9 @@ static void perf_session__destroy_kernel_maps(struct perf_session *self)
85 machines__destroy_guest_kernel_maps(&self->machines); 125 machines__destroy_guest_kernel_maps(&self->machines);
86} 126}
87 127
88struct perf_session *perf_session__new(const char *filename, int mode, bool force, bool repipe) 128struct perf_session *perf_session__new(const char *filename, int mode,
129 bool force, bool repipe,
130 struct perf_event_ops *ops)
89{ 131{
90 size_t len = filename ? strlen(filename) + 1 : 0; 132 size_t len = filename ? strlen(filename) + 1 : 0;
91 struct perf_session *self = zalloc(sizeof(*self) + len); 133 struct perf_session *self = zalloc(sizeof(*self) + len);
@@ -101,10 +143,20 @@ struct perf_session *perf_session__new(const char *filename, int mode, bool forc
101 INIT_LIST_HEAD(&self->dead_threads); 143 INIT_LIST_HEAD(&self->dead_threads);
102 self->hists_tree = RB_ROOT; 144 self->hists_tree = RB_ROOT;
103 self->last_match = NULL; 145 self->last_match = NULL;
104 self->mmap_window = 32; 146 /*
147 * On 64bit we can mmap the data file in one go. No need for tiny mmap
148 * slices. On 32bit we use 32MB.
149 */
150#if BITS_PER_LONG == 64
151 self->mmap_window = ULLONG_MAX;
152#else
153 self->mmap_window = 32 * 1024 * 1024ULL;
154#endif
105 self->machines = RB_ROOT; 155 self->machines = RB_ROOT;
106 self->repipe = repipe; 156 self->repipe = repipe;
107 INIT_LIST_HEAD(&self->ordered_samples.samples_head); 157 INIT_LIST_HEAD(&self->ordered_samples.samples);
158 INIT_LIST_HEAD(&self->ordered_samples.sample_cache);
159 INIT_LIST_HEAD(&self->ordered_samples.to_free);
108 machine__init(&self->host_machine, "", HOST_KERNEL_ID); 160 machine__init(&self->host_machine, "", HOST_KERNEL_ID);
109 161
110 if (mode == O_RDONLY) { 162 if (mode == O_RDONLY) {
@@ -120,6 +172,13 @@ struct perf_session *perf_session__new(const char *filename, int mode, bool forc
120 } 172 }
121 173
122 perf_session__update_sample_type(self); 174 perf_session__update_sample_type(self);
175
176 if (ops && ops->ordering_requires_timestamps &&
177 ops->ordered_samples && !self->sample_id_all) {
178 dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n");
179 ops->ordered_samples = false;
180 }
181
123out: 182out:
124 return self; 183 return self;
125out_free: 184out_free:
@@ -230,7 +289,15 @@ struct map_symbol *perf_session__resolve_callchain(struct perf_session *self,
230 return syms; 289 return syms;
231} 290}
232 291
292static int process_event_synth_stub(event_t *event __used,
293 struct perf_session *session __used)
294{
295 dump_printf(": unhandled!\n");
296 return 0;
297}
298
233static int process_event_stub(event_t *event __used, 299static int process_event_stub(event_t *event __used,
300 struct sample_data *sample __used,
234 struct perf_session *session __used) 301 struct perf_session *session __used)
235{ 302{
236 dump_printf(": unhandled!\n"); 303 dump_printf(": unhandled!\n");
@@ -262,7 +329,7 @@ static void perf_event_ops__fill_defaults(struct perf_event_ops *handler)
262 if (handler->exit == NULL) 329 if (handler->exit == NULL)
263 handler->exit = process_event_stub; 330 handler->exit = process_event_stub;
264 if (handler->lost == NULL) 331 if (handler->lost == NULL)
265 handler->lost = process_event_stub; 332 handler->lost = event__process_lost;
266 if (handler->read == NULL) 333 if (handler->read == NULL)
267 handler->read = process_event_stub; 334 handler->read = process_event_stub;
268 if (handler->throttle == NULL) 335 if (handler->throttle == NULL)
@@ -270,13 +337,13 @@ static void perf_event_ops__fill_defaults(struct perf_event_ops *handler)
270 if (handler->unthrottle == NULL) 337 if (handler->unthrottle == NULL)
271 handler->unthrottle = process_event_stub; 338 handler->unthrottle = process_event_stub;
272 if (handler->attr == NULL) 339 if (handler->attr == NULL)
273 handler->attr = process_event_stub; 340 handler->attr = process_event_synth_stub;
274 if (handler->event_type == NULL) 341 if (handler->event_type == NULL)
275 handler->event_type = process_event_stub; 342 handler->event_type = process_event_synth_stub;
276 if (handler->tracing_data == NULL) 343 if (handler->tracing_data == NULL)
277 handler->tracing_data = process_event_stub; 344 handler->tracing_data = process_event_synth_stub;
278 if (handler->build_id == NULL) 345 if (handler->build_id == NULL)
279 handler->build_id = process_event_stub; 346 handler->build_id = process_event_synth_stub;
280 if (handler->finished_round == NULL) { 347 if (handler->finished_round == NULL) {
281 if (handler->ordered_samples) 348 if (handler->ordered_samples)
282 handler->finished_round = process_finished_round; 349 handler->finished_round = process_finished_round;
@@ -386,33 +453,61 @@ static event__swap_op event__swap_ops[] = {
386 453
387struct sample_queue { 454struct sample_queue {
388 u64 timestamp; 455 u64 timestamp;
389 struct sample_event *event; 456 u64 file_offset;
457 event_t *event;
390 struct list_head list; 458 struct list_head list;
391}; 459};
392 460
461static void perf_session_free_sample_buffers(struct perf_session *session)
462{
463 struct ordered_samples *os = &session->ordered_samples;
464
465 while (!list_empty(&os->to_free)) {
466 struct sample_queue *sq;
467
468 sq = list_entry(os->to_free.next, struct sample_queue, list);
469 list_del(&sq->list);
470 free(sq);
471 }
472}
473
474static int perf_session_deliver_event(struct perf_session *session,
475 event_t *event,
476 struct sample_data *sample,
477 struct perf_event_ops *ops,
478 u64 file_offset);
479
393static void flush_sample_queue(struct perf_session *s, 480static void flush_sample_queue(struct perf_session *s,
394 struct perf_event_ops *ops) 481 struct perf_event_ops *ops)
395{ 482{
396 struct list_head *head = &s->ordered_samples.samples_head; 483 struct ordered_samples *os = &s->ordered_samples;
397 u64 limit = s->ordered_samples.next_flush; 484 struct list_head *head = &os->samples;
398 struct sample_queue *tmp, *iter; 485 struct sample_queue *tmp, *iter;
486 struct sample_data sample;
487 u64 limit = os->next_flush;
488 u64 last_ts = os->last_sample ? os->last_sample->timestamp : 0ULL;
399 489
400 if (!ops->ordered_samples || !limit) 490 if (!ops->ordered_samples || !limit)
401 return; 491 return;
402 492
403 list_for_each_entry_safe(iter, tmp, head, list) { 493 list_for_each_entry_safe(iter, tmp, head, list) {
404 if (iter->timestamp > limit) 494 if (iter->timestamp > limit)
405 return; 495 break;
406 496
407 if (iter == s->ordered_samples.last_inserted) 497 event__parse_sample(iter->event, s, &sample);
408 s->ordered_samples.last_inserted = NULL; 498 perf_session_deliver_event(s, iter->event, &sample, ops,
499 iter->file_offset);
409 500
410 ops->sample((event_t *)iter->event, s); 501 os->last_flush = iter->timestamp;
411
412 s->ordered_samples.last_flush = iter->timestamp;
413 list_del(&iter->list); 502 list_del(&iter->list);
414 free(iter->event); 503 list_add(&iter->list, &os->sample_cache);
415 free(iter); 504 }
505
506 if (list_empty(head)) {
507 os->last_sample = NULL;
508 } else if (last_ts <= limit) {
509 os->last_sample =
510 list_entry(head->prev, struct sample_queue, list);
416 } 511 }
417} 512}
418 513
@@ -465,178 +560,267 @@ static int process_finished_round(event_t *event __used,
465 return 0; 560 return 0;
466} 561}
467 562
468static void __queue_sample_end(struct sample_queue *new, struct list_head *head)
469{
470 struct sample_queue *iter;
471
472 list_for_each_entry_reverse(iter, head, list) {
473 if (iter->timestamp < new->timestamp) {
474 list_add(&new->list, &iter->list);
475 return;
476 }
477 }
478
479 list_add(&new->list, head);
480}
481
482static void __queue_sample_before(struct sample_queue *new,
483 struct sample_queue *iter,
484 struct list_head *head)
485{
486 list_for_each_entry_continue_reverse(iter, head, list) {
487 if (iter->timestamp < new->timestamp) {
488 list_add(&new->list, &iter->list);
489 return;
490 }
491 }
492
493 list_add(&new->list, head);
494}
495
496static void __queue_sample_after(struct sample_queue *new,
497 struct sample_queue *iter,
498 struct list_head *head)
499{
500 list_for_each_entry_continue(iter, head, list) {
501 if (iter->timestamp > new->timestamp) {
502 list_add_tail(&new->list, &iter->list);
503 return;
504 }
505 }
506 list_add_tail(&new->list, head);
507}
508
509/* The queue is ordered by time */ 563/* The queue is ordered by time */
510static void __queue_sample_event(struct sample_queue *new, 564static void __queue_event(struct sample_queue *new, struct perf_session *s)
511 struct perf_session *s)
512{ 565{
513 struct sample_queue *last_inserted = s->ordered_samples.last_inserted; 566 struct ordered_samples *os = &s->ordered_samples;
514 struct list_head *head = &s->ordered_samples.samples_head; 567 struct sample_queue *sample = os->last_sample;
568 u64 timestamp = new->timestamp;
569 struct list_head *p;
515 570
571 os->last_sample = new;
516 572
517 if (!last_inserted) { 573 if (!sample) {
518 __queue_sample_end(new, head); 574 list_add(&new->list, &os->samples);
575 os->max_timestamp = timestamp;
519 return; 576 return;
520 } 577 }
521 578
522 /* 579 /*
523 * Most of the time the current event has a timestamp 580 * last_sample might point to some random place in the list as it's
524 * very close to the last event inserted, unless we just switched 581 * the last queued event. We expect that the new event is close to
525 * to another event buffer. Having a sorting based on a list and 582 * this.
526 * on the last inserted event that is close to the current one is
527 * probably more efficient than an rbtree based sorting.
528 */ 583 */
529 if (last_inserted->timestamp >= new->timestamp) 584 if (sample->timestamp <= timestamp) {
530 __queue_sample_before(new, last_inserted, head); 585 while (sample->timestamp <= timestamp) {
531 else 586 p = sample->list.next;
532 __queue_sample_after(new, last_inserted, head); 587 if (p == &os->samples) {
588 list_add_tail(&new->list, &os->samples);
589 os->max_timestamp = timestamp;
590 return;
591 }
592 sample = list_entry(p, struct sample_queue, list);
593 }
594 list_add_tail(&new->list, &sample->list);
595 } else {
596 while (sample->timestamp > timestamp) {
597 p = sample->list.prev;
598 if (p == &os->samples) {
599 list_add(&new->list, &os->samples);
600 return;
601 }
602 sample = list_entry(p, struct sample_queue, list);
603 }
604 list_add(&new->list, &sample->list);
605 }
533} 606}
534 607
535static int queue_sample_event(event_t *event, struct sample_data *data, 608#define MAX_SAMPLE_BUFFER (64 * 1024 / sizeof(struct sample_queue))
536 struct perf_session *s) 609
610static int perf_session_queue_event(struct perf_session *s, event_t *event,
611 struct sample_data *data, u64 file_offset)
537{ 612{
613 struct ordered_samples *os = &s->ordered_samples;
614 struct list_head *sc = &os->sample_cache;
538 u64 timestamp = data->time; 615 u64 timestamp = data->time;
539 struct sample_queue *new; 616 struct sample_queue *new;
540 617
618 if (!timestamp || timestamp == ~0ULL)
619 return -ETIME;
541 620
542 if (timestamp < s->ordered_samples.last_flush) { 621 if (timestamp < s->ordered_samples.last_flush) {
543 printf("Warning: Timestamp below last timeslice flush\n"); 622 printf("Warning: Timestamp below last timeslice flush\n");
544 return -EINVAL; 623 return -EINVAL;
545 } 624 }
546 625
547 new = malloc(sizeof(*new)); 626 if (!list_empty(sc)) {
548 if (!new) 627 new = list_entry(sc->next, struct sample_queue, list);
549 return -ENOMEM; 628 list_del(&new->list);
629 } else if (os->sample_buffer) {
630 new = os->sample_buffer + os->sample_buffer_idx;
631 if (++os->sample_buffer_idx == MAX_SAMPLE_BUFFER)
632 os->sample_buffer = NULL;
633 } else {
634 os->sample_buffer = malloc(MAX_SAMPLE_BUFFER * sizeof(*new));
635 if (!os->sample_buffer)
636 return -ENOMEM;
637 list_add(&os->sample_buffer->list, &os->to_free);
638 os->sample_buffer_idx = 2;
639 new = os->sample_buffer + 1;
640 }
550 641
551 new->timestamp = timestamp; 642 new->timestamp = timestamp;
643 new->file_offset = file_offset;
644 new->event = event;
552 645
553 new->event = malloc(event->header.size); 646 __queue_event(new, s);
554 if (!new->event) {
555 free(new);
556 return -ENOMEM;
557 }
558 647
559 memcpy(new->event, event, event->header.size); 648 return 0;
649}
560 650
561 __queue_sample_event(new, s); 651static void callchain__printf(struct sample_data *sample)
562 s->ordered_samples.last_inserted = new; 652{
653 unsigned int i;
563 654
564 if (new->timestamp > s->ordered_samples.max_timestamp) 655 printf("... chain: nr:%" PRIu64 "\n", sample->callchain->nr);
565 s->ordered_samples.max_timestamp = new->timestamp;
566 656
567 return 0; 657 for (i = 0; i < sample->callchain->nr; i++)
658 printf("..... %2d: %016" PRIx64 "\n",
659 i, sample->callchain->ips[i]);
568} 660}
569 661
570static int perf_session__process_sample(event_t *event, struct perf_session *s, 662static void perf_session__print_tstamp(struct perf_session *session,
571 struct perf_event_ops *ops) 663 event_t *event,
664 struct sample_data *sample)
572{ 665{
573 struct sample_data data; 666 if (event->header.type != PERF_RECORD_SAMPLE &&
667 !session->sample_id_all) {
668 fputs("-1 -1 ", stdout);
669 return;
670 }
574 671
575 if (!ops->ordered_samples) 672 if ((session->sample_type & PERF_SAMPLE_CPU))
576 return ops->sample(event, s); 673 printf("%u ", sample->cpu);
577 674
578 bzero(&data, sizeof(struct sample_data)); 675 if (session->sample_type & PERF_SAMPLE_TIME)
579 event__parse_sample(event, s->sample_type, &data); 676 printf("%" PRIu64 " ", sample->time);
677}
580 678
581 queue_sample_event(event, &data, s); 679static void dump_event(struct perf_session *session, event_t *event,
680 u64 file_offset, struct sample_data *sample)
681{
682 if (!dump_trace)
683 return;
582 684
583 return 0; 685 printf("\n%#" PRIx64 " [%#x]: event: %d\n",
686 file_offset, event->header.size, event->header.type);
687
688 trace_event(event);
689
690 if (sample)
691 perf_session__print_tstamp(session, event, sample);
692
693 printf("%#" PRIx64 " [%#x]: PERF_RECORD_%s", file_offset,
694 event->header.size, event__get_event_name(event->header.type));
584} 695}
585 696
586static int perf_session__process_event(struct perf_session *self, 697static void dump_sample(struct perf_session *session, event_t *event,
587 event_t *event, 698 struct sample_data *sample)
588 struct perf_event_ops *ops,
589 u64 offset, u64 head)
590{ 699{
591 trace_event(event); 700 if (!dump_trace)
701 return;
592 702
593 if (event->header.type < PERF_RECORD_HEADER_MAX) { 703 printf("(IP, %d): %d/%d: %#" PRIx64 " period: %" PRIu64 "\n",
594 dump_printf("%#Lx [%#x]: PERF_RECORD_%s", 704 event->header.misc, sample->pid, sample->tid, sample->ip,
595 offset + head, event->header.size, 705 sample->period);
596 event__name[event->header.type]);
597 hists__inc_nr_events(&self->hists, event->header.type);
598 }
599 706
600 if (self->header.needs_swap && event__swap_ops[event->header.type]) 707 if (session->sample_type & PERF_SAMPLE_CALLCHAIN)
601 event__swap_ops[event->header.type](event); 708 callchain__printf(sample);
709}
710
711static int perf_session_deliver_event(struct perf_session *session,
712 event_t *event,
713 struct sample_data *sample,
714 struct perf_event_ops *ops,
715 u64 file_offset)
716{
717 dump_event(session, event, file_offset, sample);
602 718
603 switch (event->header.type) { 719 switch (event->header.type) {
604 case PERF_RECORD_SAMPLE: 720 case PERF_RECORD_SAMPLE:
605 return perf_session__process_sample(event, self, ops); 721 dump_sample(session, event, sample);
722 return ops->sample(event, sample, session);
606 case PERF_RECORD_MMAP: 723 case PERF_RECORD_MMAP:
607 return ops->mmap(event, self); 724 return ops->mmap(event, sample, session);
608 case PERF_RECORD_COMM: 725 case PERF_RECORD_COMM:
609 return ops->comm(event, self); 726 return ops->comm(event, sample, session);
610 case PERF_RECORD_FORK: 727 case PERF_RECORD_FORK:
611 return ops->fork(event, self); 728 return ops->fork(event, sample, session);
612 case PERF_RECORD_EXIT: 729 case PERF_RECORD_EXIT:
613 return ops->exit(event, self); 730 return ops->exit(event, sample, session);
614 case PERF_RECORD_LOST: 731 case PERF_RECORD_LOST:
615 return ops->lost(event, self); 732 return ops->lost(event, sample, session);
616 case PERF_RECORD_READ: 733 case PERF_RECORD_READ:
617 return ops->read(event, self); 734 return ops->read(event, sample, session);
618 case PERF_RECORD_THROTTLE: 735 case PERF_RECORD_THROTTLE:
619 return ops->throttle(event, self); 736 return ops->throttle(event, sample, session);
620 case PERF_RECORD_UNTHROTTLE: 737 case PERF_RECORD_UNTHROTTLE:
621 return ops->unthrottle(event, self); 738 return ops->unthrottle(event, sample, session);
739 default:
740 ++session->hists.stats.nr_unknown_events;
741 return -1;
742 }
743}
744
745static int perf_session__preprocess_sample(struct perf_session *session,
746 event_t *event, struct sample_data *sample)
747{
748 if (event->header.type != PERF_RECORD_SAMPLE ||
749 !(session->sample_type & PERF_SAMPLE_CALLCHAIN))
750 return 0;
751
752 if (!ip_callchain__valid(sample->callchain, event)) {
753 pr_debug("call-chain problem with event, skipping it.\n");
754 ++session->hists.stats.nr_invalid_chains;
755 session->hists.stats.total_invalid_chains += sample->period;
756 return -EINVAL;
757 }
758 return 0;
759}
760
761static int perf_session__process_user_event(struct perf_session *session, event_t *event,
762 struct perf_event_ops *ops, u64 file_offset)
763{
764 dump_event(session, event, file_offset, NULL);
765
766 /* These events are processed right away */
767 switch (event->header.type) {
622 case PERF_RECORD_HEADER_ATTR: 768 case PERF_RECORD_HEADER_ATTR:
623 return ops->attr(event, self); 769 return ops->attr(event, session);
624 case PERF_RECORD_HEADER_EVENT_TYPE: 770 case PERF_RECORD_HEADER_EVENT_TYPE:
625 return ops->event_type(event, self); 771 return ops->event_type(event, session);
626 case PERF_RECORD_HEADER_TRACING_DATA: 772 case PERF_RECORD_HEADER_TRACING_DATA:
627 /* setup for reading amidst mmap */ 773 /* setup for reading amidst mmap */
628 lseek(self->fd, offset + head, SEEK_SET); 774 lseek(session->fd, file_offset, SEEK_SET);
629 return ops->tracing_data(event, self); 775 return ops->tracing_data(event, session);
630 case PERF_RECORD_HEADER_BUILD_ID: 776 case PERF_RECORD_HEADER_BUILD_ID:
631 return ops->build_id(event, self); 777 return ops->build_id(event, session);
632 case PERF_RECORD_FINISHED_ROUND: 778 case PERF_RECORD_FINISHED_ROUND:
633 return ops->finished_round(event, self, ops); 779 return ops->finished_round(event, session, ops);
634 default: 780 default:
635 ++self->hists.stats.nr_unknown_events; 781 return -EINVAL;
636 return -1;
637 } 782 }
638} 783}
639 784
785static int perf_session__process_event(struct perf_session *session,
786 event_t *event,
787 struct perf_event_ops *ops,
788 u64 file_offset)
789{
790 struct sample_data sample;
791 int ret;
792
793 if (session->header.needs_swap && event__swap_ops[event->header.type])
794 event__swap_ops[event->header.type](event);
795
796 if (event->header.type >= PERF_RECORD_HEADER_MAX)
797 return -EINVAL;
798
799 hists__inc_nr_events(&session->hists, event->header.type);
800
801 if (event->header.type >= PERF_RECORD_USER_TYPE_START)
802 return perf_session__process_user_event(session, event, ops, file_offset);
803
804 /*
805 * For all kernel events we get the sample data
806 */
807 event__parse_sample(event, session, &sample);
808
809 /* Preprocess sample records - precheck callchains */
810 if (perf_session__preprocess_sample(session, event, &sample))
811 return 0;
812
813 if (ops->ordered_samples) {
814 ret = perf_session_queue_event(session, event, &sample,
815 file_offset);
816 if (ret != -ETIME)
817 return ret;
818 }
819
820 return perf_session_deliver_event(session, event, &sample, ops,
821 file_offset);
822}
823
640void perf_event_header__bswap(struct perf_event_header *self) 824void perf_event_header__bswap(struct perf_event_header *self)
641{ 825{
642 self->type = bswap_32(self->type); 826 self->type = bswap_32(self->type);
@@ -656,21 +840,33 @@ static struct thread *perf_session__register_idle_thread(struct perf_session *se
656 return thread; 840 return thread;
657} 841}
658 842
659int do_read(int fd, void *buf, size_t size) 843static void perf_session__warn_about_errors(const struct perf_session *session,
844 const struct perf_event_ops *ops)
660{ 845{
661 void *buf_start = buf; 846 if (ops->lost == event__process_lost &&
662 847 session->hists.stats.total_lost != 0) {
663 while (size) { 848 ui__warning("Processed %" PRIu64 " events and LOST %" PRIu64
664 int ret = read(fd, buf, size); 849 "!\n\nCheck IO/CPU overload!\n\n",
665 850 session->hists.stats.total_period,
666 if (ret <= 0) 851 session->hists.stats.total_lost);
667 return ret; 852 }
668 853
669 size -= ret; 854 if (session->hists.stats.nr_unknown_events != 0) {
670 buf += ret; 855 ui__warning("Found %u unknown events!\n\n"
856 "Is this an older tool processing a perf.data "
857 "file generated by a more recent tool?\n\n"
858 "If that is not the case, consider "
859 "reporting to linux-kernel@vger.kernel.org.\n\n",
860 session->hists.stats.nr_unknown_events);
671 } 861 }
672 862
673 return buf - buf_start; 863 if (session->hists.stats.nr_invalid_chains != 0) {
864 ui__warning("Found invalid callchains!\n\n"
865 "%u out of %u events were discarded for this reason.\n\n"
866 "Consider reporting to linux-kernel@vger.kernel.org.\n\n",
867 session->hists.stats.nr_invalid_chains,
868 session->hists.stats.nr_events[PERF_RECORD_SAMPLE]);
869 }
674} 870}
675 871
676#define session_done() (*(volatile int *)(&session_done)) 872#define session_done() (*(volatile int *)(&session_done))
@@ -690,7 +886,7 @@ static int __perf_session__process_pipe_events(struct perf_session *self,
690 886
691 head = 0; 887 head = 0;
692more: 888more:
693 err = do_read(self->fd, &event, sizeof(struct perf_event_header)); 889 err = readn(self->fd, &event, sizeof(struct perf_event_header));
694 if (err <= 0) { 890 if (err <= 0) {
695 if (err == 0) 891 if (err == 0)
696 goto done; 892 goto done;
@@ -710,8 +906,7 @@ more:
710 p += sizeof(struct perf_event_header); 906 p += sizeof(struct perf_event_header);
711 907
712 if (size - sizeof(struct perf_event_header)) { 908 if (size - sizeof(struct perf_event_header)) {
713 err = do_read(self->fd, p, 909 err = readn(self->fd, p, size - sizeof(struct perf_event_header));
714 size - sizeof(struct perf_event_header));
715 if (err <= 0) { 910 if (err <= 0) {
716 if (err == 0) { 911 if (err == 0) {
717 pr_err("unexpected end of event stream\n"); 912 pr_err("unexpected end of event stream\n");
@@ -724,9 +919,8 @@ more:
724 } 919 }
725 920
726 if (size == 0 || 921 if (size == 0 ||
727 (skip = perf_session__process_event(self, &event, ops, 922 (skip = perf_session__process_event(self, &event, ops, head)) < 0) {
728 0, head)) < 0) { 923 dump_printf("%#" PRIx64 " [%#x]: skipping unknown header type: %d\n",
729 dump_printf("%#Lx [%#x]: skipping unknown header type: %d\n",
730 head, event.header.size, event.header.type); 924 head, event.header.size, event.header.type);
731 /* 925 /*
732 * assume we lost track of the stream, check alignment, and 926 * assume we lost track of the stream, check alignment, and
@@ -740,9 +934,6 @@ more:
740 934
741 head += size; 935 head += size;
742 936
743 dump_printf("\n%#Lx [%#x]: event: %d\n",
744 head, event.header.size, event.header.type);
745
746 if (skip > 0) 937 if (skip > 0)
747 head += skip; 938 head += skip;
748 939
@@ -751,82 +942,91 @@ more:
751done: 942done:
752 err = 0; 943 err = 0;
753out_err: 944out_err:
945 perf_session__warn_about_errors(self, ops);
946 perf_session_free_sample_buffers(self);
754 return err; 947 return err;
755} 948}
756 949
757int __perf_session__process_events(struct perf_session *self, 950int __perf_session__process_events(struct perf_session *session,
758 u64 data_offset, u64 data_size, 951 u64 data_offset, u64 data_size,
759 u64 file_size, struct perf_event_ops *ops) 952 u64 file_size, struct perf_event_ops *ops)
760{ 953{
761 int err, mmap_prot, mmap_flags; 954 u64 head, page_offset, file_offset, file_pos, progress_next;
762 u64 head, shift; 955 int err, mmap_prot, mmap_flags, map_idx = 0;
763 u64 offset = 0; 956 struct ui_progress *progress;
764 size_t page_size; 957 size_t page_size, mmap_size;
958 char *buf, *mmaps[8];
765 event_t *event; 959 event_t *event;
766 uint32_t size; 960 uint32_t size;
767 char *buf;
768 struct ui_progress *progress = ui_progress__new("Processing events...",
769 self->size);
770 if (progress == NULL)
771 return -1;
772 961
773 perf_event_ops__fill_defaults(ops); 962 perf_event_ops__fill_defaults(ops);
774 963
775 page_size = sysconf(_SC_PAGESIZE); 964 page_size = sysconf(_SC_PAGESIZE);
776 965
777 head = data_offset; 966 page_offset = page_size * (data_offset / page_size);
778 shift = page_size * (head / page_size); 967 file_offset = page_offset;
779 offset += shift; 968 head = data_offset - page_offset;
780 head -= shift; 969
970 if (data_offset + data_size < file_size)
971 file_size = data_offset + data_size;
972
973 progress_next = file_size / 16;
974 progress = ui_progress__new("Processing events...", file_size);
975 if (progress == NULL)
976 return -1;
977
978 mmap_size = session->mmap_window;
979 if (mmap_size > file_size)
980 mmap_size = file_size;
981
982 memset(mmaps, 0, sizeof(mmaps));
781 983
782 mmap_prot = PROT_READ; 984 mmap_prot = PROT_READ;
783 mmap_flags = MAP_SHARED; 985 mmap_flags = MAP_SHARED;
784 986
785 if (self->header.needs_swap) { 987 if (session->header.needs_swap) {
786 mmap_prot |= PROT_WRITE; 988 mmap_prot |= PROT_WRITE;
787 mmap_flags = MAP_PRIVATE; 989 mmap_flags = MAP_PRIVATE;
788 } 990 }
789remap: 991remap:
790 buf = mmap(NULL, page_size * self->mmap_window, mmap_prot, 992 buf = mmap(NULL, mmap_size, mmap_prot, mmap_flags, session->fd,
791 mmap_flags, self->fd, offset); 993 file_offset);
792 if (buf == MAP_FAILED) { 994 if (buf == MAP_FAILED) {
793 pr_err("failed to mmap file\n"); 995 pr_err("failed to mmap file\n");
794 err = -errno; 996 err = -errno;
795 goto out_err; 997 goto out_err;
796 } 998 }
999 mmaps[map_idx] = buf;
1000 map_idx = (map_idx + 1) & (ARRAY_SIZE(mmaps) - 1);
1001 file_pos = file_offset + head;
797 1002
798more: 1003more:
799 event = (event_t *)(buf + head); 1004 event = (event_t *)(buf + head);
800 ui_progress__update(progress, offset);
801 1005
802 if (self->header.needs_swap) 1006 if (session->header.needs_swap)
803 perf_event_header__bswap(&event->header); 1007 perf_event_header__bswap(&event->header);
804 size = event->header.size; 1008 size = event->header.size;
805 if (size == 0) 1009 if (size == 0)
806 size = 8; 1010 size = 8;
807 1011
808 if (head + event->header.size >= page_size * self->mmap_window) { 1012 if (head + event->header.size > mmap_size) {
809 int munmap_ret; 1013 if (mmaps[map_idx]) {
810 1014 munmap(mmaps[map_idx], mmap_size);
811 shift = page_size * (head / page_size); 1015 mmaps[map_idx] = NULL;
812 1016 }
813 munmap_ret = munmap(buf, page_size * self->mmap_window);
814 assert(munmap_ret == 0);
815 1017
816 offset += shift; 1018 page_offset = page_size * (head / page_size);
817 head -= shift; 1019 file_offset += page_offset;
1020 head -= page_offset;
818 goto remap; 1021 goto remap;
819 } 1022 }
820 1023
821 size = event->header.size; 1024 size = event->header.size;
822 1025
823 dump_printf("\n%#Lx [%#x]: event: %d\n",
824 offset + head, event->header.size, event->header.type);
825
826 if (size == 0 || 1026 if (size == 0 ||
827 perf_session__process_event(self, event, ops, offset, head) < 0) { 1027 perf_session__process_event(session, event, ops, file_pos) < 0) {
828 dump_printf("%#Lx [%#x]: skipping unknown header type: %d\n", 1028 dump_printf("%#" PRIx64 " [%#x]: skipping unknown header type: %d\n",
829 offset + head, event->header.size, 1029 file_offset + head, event->header.size,
830 event->header.type); 1030 event->header.type);
831 /* 1031 /*
832 * assume we lost track of the stream, check alignment, and 1032 * assume we lost track of the stream, check alignment, and
@@ -839,19 +1039,24 @@ more:
839 } 1039 }
840 1040
841 head += size; 1041 head += size;
1042 file_pos += size;
842 1043
843 if (offset + head >= data_offset + data_size) 1044 if (file_pos >= progress_next) {
844 goto done; 1045 progress_next += file_size / 16;
1046 ui_progress__update(progress, file_pos);
1047 }
845 1048
846 if (offset + head < file_size) 1049 if (file_pos < file_size)
847 goto more; 1050 goto more;
848done: 1051
849 err = 0; 1052 err = 0;
850 /* do the final flush for ordered samples */ 1053 /* do the final flush for ordered samples */
851 self->ordered_samples.next_flush = ULLONG_MAX; 1054 session->ordered_samples.next_flush = ULLONG_MAX;
852 flush_sample_queue(self, ops); 1055 flush_sample_queue(session, ops);
853out_err: 1056out_err:
854 ui_progress__delete(progress); 1057 ui_progress__delete(progress);
1058 perf_session__warn_about_errors(session, ops);
1059 perf_session_free_sample_buffers(session);
855 return err; 1060 return err;
856} 1061}
857 1062
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 9fa0fc2a863f..decd83f274fd 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -17,8 +17,12 @@ struct ordered_samples {
17 u64 last_flush; 17 u64 last_flush;
18 u64 next_flush; 18 u64 next_flush;
19 u64 max_timestamp; 19 u64 max_timestamp;
20 struct list_head samples_head; 20 struct list_head samples;
21 struct sample_queue *last_inserted; 21 struct list_head sample_cache;
22 struct list_head to_free;
23 struct sample_queue *sample_buffer;
24 struct sample_queue *last_sample;
25 int sample_buffer_idx;
22}; 26};
23 27
24struct perf_session { 28struct perf_session {
@@ -42,6 +46,8 @@ struct perf_session {
42 int fd; 46 int fd;
43 bool fd_pipe; 47 bool fd_pipe;
44 bool repipe; 48 bool repipe;
49 bool sample_id_all;
50 u16 id_hdr_size;
45 int cwdlen; 51 int cwdlen;
46 char *cwd; 52 char *cwd;
47 struct ordered_samples ordered_samples; 53 struct ordered_samples ordered_samples;
@@ -50,7 +56,9 @@ struct perf_session {
50 56
51struct perf_event_ops; 57struct perf_event_ops;
52 58
53typedef int (*event_op)(event_t *self, struct perf_session *session); 59typedef int (*event_op)(event_t *self, struct sample_data *sample,
60 struct perf_session *session);
61typedef int (*event_synth_op)(event_t *self, struct perf_session *session);
54typedef int (*event_op2)(event_t *self, struct perf_session *session, 62typedef int (*event_op2)(event_t *self, struct perf_session *session,
55 struct perf_event_ops *ops); 63 struct perf_event_ops *ops);
56 64
@@ -63,16 +71,19 @@ struct perf_event_ops {
63 lost, 71 lost,
64 read, 72 read,
65 throttle, 73 throttle,
66 unthrottle, 74 unthrottle;
67 attr, 75 event_synth_op attr,
68 event_type, 76 event_type,
69 tracing_data, 77 tracing_data,
70 build_id; 78 build_id;
71 event_op2 finished_round; 79 event_op2 finished_round;
72 bool ordered_samples; 80 bool ordered_samples;
81 bool ordering_requires_timestamps;
73}; 82};
74 83
75struct perf_session *perf_session__new(const char *filename, int mode, bool force, bool repipe); 84struct perf_session *perf_session__new(const char *filename, int mode,
85 bool force, bool repipe,
86 struct perf_event_ops *ops);
76void perf_session__delete(struct perf_session *self); 87void perf_session__delete(struct perf_session *self);
77 88
78void perf_event_header__bswap(struct perf_event_header *self); 89void perf_event_header__bswap(struct perf_event_header *self);
@@ -98,8 +109,9 @@ void mem_bswap_64(void *src, int byte_size);
98 109
99int perf_session__create_kernel_maps(struct perf_session *self); 110int perf_session__create_kernel_maps(struct perf_session *self);
100 111
101int do_read(int fd, void *buf, size_t size);
102void perf_session__update_sample_type(struct perf_session *self); 112void perf_session__update_sample_type(struct perf_session *self);
113void perf_session__set_sample_id_all(struct perf_session *session, bool value);
114void perf_session__set_sample_type(struct perf_session *session, u64 type);
103void perf_session__remove_thread(struct perf_session *self, struct thread *th); 115void perf_session__remove_thread(struct perf_session *self, struct thread *th);
104 116
105static inline 117static inline
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index b62a553cc67d..f44fa541d56e 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -170,7 +170,7 @@ static int hist_entry__dso_snprintf(struct hist_entry *self, char *bf,
170 return repsep_snprintf(bf, size, "%-*s", width, dso_name); 170 return repsep_snprintf(bf, size, "%-*s", width, dso_name);
171 } 171 }
172 172
173 return repsep_snprintf(bf, size, "%*Lx", width, self->ip); 173 return repsep_snprintf(bf, size, "%-*s", width, "[unknown]");
174} 174}
175 175
176/* --sort symbol */ 176/* --sort symbol */
@@ -196,7 +196,7 @@ static int hist_entry__sym_snprintf(struct hist_entry *self, char *bf,
196 196
197 if (verbose) { 197 if (verbose) {
198 char o = self->ms.map ? dso__symtab_origin(self->ms.map->dso) : '!'; 198 char o = self->ms.map ? dso__symtab_origin(self->ms.map->dso) : '!';
199 ret += repsep_snprintf(bf, size, "%*Lx %c ", 199 ret += repsep_snprintf(bf, size, "%-#*llx %c ",
200 BITS_PER_LONG / 4, self->ip, o); 200 BITS_PER_LONG / 4, self->ip, o);
201 } 201 }
202 202
@@ -205,7 +205,7 @@ static int hist_entry__sym_snprintf(struct hist_entry *self, char *bf,
205 ret += repsep_snprintf(bf + ret, size - ret, "%s", 205 ret += repsep_snprintf(bf + ret, size - ret, "%s",
206 self->ms.sym->name); 206 self->ms.sym->name);
207 else 207 else
208 ret += repsep_snprintf(bf + ret, size - ret, "%*Lx", 208 ret += repsep_snprintf(bf + ret, size - ret, "%-#*llx",
209 BITS_PER_LONG / 4, self->ip); 209 BITS_PER_LONG / 4, self->ip);
210 210
211 return ret; 211 return ret;
diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c
index 0409fc7c0058..8fc0bd3a3a4a 100644
--- a/tools/perf/util/string.c
+++ b/tools/perf/util/string.c
@@ -259,7 +259,7 @@ static bool __match_glob(const char *str, const char *pat, bool ignore_space)
259 if (!*pat) /* Tail wild card matches all */ 259 if (!*pat) /* Tail wild card matches all */
260 return true; 260 return true;
261 while (*str) 261 while (*str)
262 if (strglobmatch(str++, pat)) 262 if (__match_glob(str++, pat, ignore_space))
263 return true; 263 return true;
264 } 264 }
265 return !*str && !*pat; 265 return !*str && !*pat;
diff --git a/tools/perf/util/svghelper.c b/tools/perf/util/svghelper.c
index b3637db025a2..fb737fe9be91 100644
--- a/tools/perf/util/svghelper.c
+++ b/tools/perf/util/svghelper.c
@@ -12,6 +12,7 @@
12 * of the License. 12 * of the License.
13 */ 13 */
14 14
15#include <inttypes.h>
15#include <stdio.h> 16#include <stdio.h>
16#include <stdlib.h> 17#include <stdlib.h>
17#include <unistd.h> 18#include <unistd.h>
@@ -43,11 +44,11 @@ static double cpu2y(int cpu)
43 return cpu2slot(cpu) * SLOT_MULT; 44 return cpu2slot(cpu) * SLOT_MULT;
44} 45}
45 46
46static double time2pixels(u64 time) 47static double time2pixels(u64 __time)
47{ 48{
48 double X; 49 double X;
49 50
50 X = 1.0 * svg_page_width * (time - first_time) / (last_time - first_time); 51 X = 1.0 * svg_page_width * (__time - first_time) / (last_time - first_time);
51 return X; 52 return X;
52} 53}
53 54
@@ -94,7 +95,7 @@ void open_svg(const char *filename, int cpus, int rows, u64 start, u64 end)
94 95
95 total_height = (1 + rows + cpu2slot(cpus)) * SLOT_MULT; 96 total_height = (1 + rows + cpu2slot(cpus)) * SLOT_MULT;
96 fprintf(svgfile, "<?xml version=\"1.0\" standalone=\"no\"?> \n"); 97 fprintf(svgfile, "<?xml version=\"1.0\" standalone=\"no\"?> \n");
97 fprintf(svgfile, "<svg width=\"%i\" height=\"%llu\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n", svg_page_width, total_height); 98 fprintf(svgfile, "<svg width=\"%i\" height=\"%" PRIu64 "\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n", svg_page_width, total_height);
98 99
99 fprintf(svgfile, "<defs>\n <style type=\"text/css\">\n <![CDATA[\n"); 100 fprintf(svgfile, "<defs>\n <style type=\"text/css\">\n <![CDATA[\n");
100 101
@@ -483,7 +484,7 @@ void svg_time_grid(void)
483 color = 128; 484 color = 128;
484 } 485 }
485 486
486 fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%llu\" style=\"stroke:rgb(%i,%i,%i);stroke-width:%1.3f\"/>\n", 487 fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%" PRIu64 "\" style=\"stroke:rgb(%i,%i,%i);stroke-width:%1.3f\"/>\n",
487 time2pixels(i), SLOT_MULT/2, time2pixels(i), total_height, color, color, color, thickness); 488 time2pixels(i), SLOT_MULT/2, time2pixels(i), total_height, color, color, color, thickness);
488 489
489 i += 10000000; 490 i += 10000000;
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index b39f499e575a..7821d0e6866f 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -11,6 +11,7 @@
11#include <sys/param.h> 11#include <sys/param.h>
12#include <fcntl.h> 12#include <fcntl.h>
13#include <unistd.h> 13#include <unistd.h>
14#include <inttypes.h>
14#include "build-id.h" 15#include "build-id.h"
15#include "debug.h" 16#include "debug.h"
16#include "symbol.h" 17#include "symbol.h"
@@ -22,6 +23,10 @@
22#include <limits.h> 23#include <limits.h>
23#include <sys/utsname.h> 24#include <sys/utsname.h>
24 25
26#ifndef KSYM_NAME_LEN
27#define KSYM_NAME_LEN 128
28#endif
29
25#ifndef NT_GNU_BUILD_ID 30#ifndef NT_GNU_BUILD_ID
26#define NT_GNU_BUILD_ID 3 31#define NT_GNU_BUILD_ID 3
27#endif 32#endif
@@ -41,6 +46,7 @@ struct symbol_conf symbol_conf = {
41 .exclude_other = true, 46 .exclude_other = true,
42 .use_modules = true, 47 .use_modules = true,
43 .try_vmlinux_path = true, 48 .try_vmlinux_path = true,
49 .symfs = "",
44}; 50};
45 51
46int dso__name_len(const struct dso *self) 52int dso__name_len(const struct dso *self)
@@ -92,7 +98,7 @@ static void symbols__fixup_end(struct rb_root *self)
92 prev = curr; 98 prev = curr;
93 curr = rb_entry(nd, struct symbol, rb_node); 99 curr = rb_entry(nd, struct symbol, rb_node);
94 100
95 if (prev->end == prev->start) 101 if (prev->end == prev->start && prev->end != curr->start)
96 prev->end = curr->start - 1; 102 prev->end = curr->start - 1;
97 } 103 }
98 104
@@ -121,7 +127,7 @@ static void __map_groups__fixup_end(struct map_groups *self, enum map_type type)
121 * We still haven't the actual symbols, so guess the 127 * We still haven't the actual symbols, so guess the
122 * last map final address. 128 * last map final address.
123 */ 129 */
124 curr->end = ~0UL; 130 curr->end = ~0ULL;
125} 131}
126 132
127static void map_groups__fixup_end(struct map_groups *self) 133static void map_groups__fixup_end(struct map_groups *self)
@@ -148,7 +154,7 @@ static struct symbol *symbol__new(u64 start, u64 len, u8 binding,
148 self->binding = binding; 154 self->binding = binding;
149 self->namelen = namelen - 1; 155 self->namelen = namelen - 1;
150 156
151 pr_debug4("%s: %s %#Lx-%#Lx\n", __func__, name, start, self->end); 157 pr_debug4("%s: %s %#" PRIx64 "-%#" PRIx64 "\n", __func__, name, start, self->end);
152 158
153 memcpy(self->name, name, namelen); 159 memcpy(self->name, name, namelen);
154 160
@@ -162,7 +168,7 @@ void symbol__delete(struct symbol *self)
162 168
163static size_t symbol__fprintf(struct symbol *self, FILE *fp) 169static size_t symbol__fprintf(struct symbol *self, FILE *fp)
164{ 170{
165 return fprintf(fp, " %llx-%llx %c %s\n", 171 return fprintf(fp, " %" PRIx64 "-%" PRIx64 " %c %s\n",
166 self->start, self->end, 172 self->start, self->end,
167 self->binding == STB_GLOBAL ? 'g' : 173 self->binding == STB_GLOBAL ? 'g' :
168 self->binding == STB_LOCAL ? 'l' : 'w', 174 self->binding == STB_LOCAL ? 'l' : 'w',
@@ -295,7 +301,9 @@ static void symbols__insert_by_name(struct rb_root *self, struct symbol *sym)
295{ 301{
296 struct rb_node **p = &self->rb_node; 302 struct rb_node **p = &self->rb_node;
297 struct rb_node *parent = NULL; 303 struct rb_node *parent = NULL;
298 struct symbol_name_rb_node *symn = ((void *)sym) - sizeof(*parent), *s; 304 struct symbol_name_rb_node *symn, *s;
305
306 symn = container_of(sym, struct symbol_name_rb_node, sym);
299 307
300 while (*p != NULL) { 308 while (*p != NULL) {
301 parent = *p; 309 parent = *p;
@@ -423,16 +431,25 @@ size_t dso__fprintf(struct dso *self, enum map_type type, FILE *fp)
423 431
424int kallsyms__parse(const char *filename, void *arg, 432int kallsyms__parse(const char *filename, void *arg,
425 int (*process_symbol)(void *arg, const char *name, 433 int (*process_symbol)(void *arg, const char *name,
426 char type, u64 start)) 434 char type, u64 start, u64 end))
427{ 435{
428 char *line = NULL; 436 char *line = NULL;
429 size_t n; 437 size_t n;
430 int err = 0; 438 int err = -1;
439 u64 prev_start = 0;
440 char prev_symbol_type = 0;
441 char *prev_symbol_name;
431 FILE *file = fopen(filename, "r"); 442 FILE *file = fopen(filename, "r");
432 443
433 if (file == NULL) 444 if (file == NULL)
434 goto out_failure; 445 goto out_failure;
435 446
447 prev_symbol_name = malloc(KSYM_NAME_LEN);
448 if (prev_symbol_name == NULL)
449 goto out_close;
450
451 err = 0;
452
436 while (!feof(file)) { 453 while (!feof(file)) {
437 u64 start; 454 u64 start;
438 int line_len, len; 455 int line_len, len;
@@ -452,14 +469,33 @@ int kallsyms__parse(const char *filename, void *arg,
452 continue; 469 continue;
453 470
454 symbol_type = toupper(line[len]); 471 symbol_type = toupper(line[len]);
455 symbol_name = line + len + 2; 472 len += 2;
473 symbol_name = line + len;
474 len = line_len - len;
456 475
457 err = process_symbol(arg, symbol_name, symbol_type, start); 476 if (len >= KSYM_NAME_LEN) {
458 if (err) 477 err = -1;
459 break; 478 break;
479 }
480
481 if (prev_symbol_type) {
482 u64 end = start;
483 if (end != prev_start)
484 --end;
485 err = process_symbol(arg, prev_symbol_name,
486 prev_symbol_type, prev_start, end);
487 if (err)
488 break;
489 }
490
491 memcpy(prev_symbol_name, symbol_name, len + 1);
492 prev_symbol_type = symbol_type;
493 prev_start = start;
460 } 494 }
461 495
496 free(prev_symbol_name);
462 free(line); 497 free(line);
498out_close:
463 fclose(file); 499 fclose(file);
464 return err; 500 return err;
465 501
@@ -481,7 +517,7 @@ static u8 kallsyms2elf_type(char type)
481} 517}
482 518
483static int map__process_kallsym_symbol(void *arg, const char *name, 519static int map__process_kallsym_symbol(void *arg, const char *name,
484 char type, u64 start) 520 char type, u64 start, u64 end)
485{ 521{
486 struct symbol *sym; 522 struct symbol *sym;
487 struct process_kallsyms_args *a = arg; 523 struct process_kallsyms_args *a = arg;
@@ -490,11 +526,8 @@ static int map__process_kallsym_symbol(void *arg, const char *name,
490 if (!symbol_type__is_a(type, a->map->type)) 526 if (!symbol_type__is_a(type, a->map->type))
491 return 0; 527 return 0;
492 528
493 /* 529 sym = symbol__new(start, end - start + 1,
494 * Will fix up the end later, when we have all symbols sorted. 530 kallsyms2elf_type(type), name);
495 */
496 sym = symbol__new(start, 0, kallsyms2elf_type(type), name);
497
498 if (sym == NULL) 531 if (sym == NULL)
499 return -ENOMEM; 532 return -ENOMEM;
500 /* 533 /*
@@ -530,7 +563,7 @@ static int dso__split_kallsyms(struct dso *self, struct map *map,
530 struct machine *machine = kmaps->machine; 563 struct machine *machine = kmaps->machine;
531 struct map *curr_map = map; 564 struct map *curr_map = map;
532 struct symbol *pos; 565 struct symbol *pos;
533 int count = 0; 566 int count = 0, moved = 0;
534 struct rb_root *root = &self->symbols[map->type]; 567 struct rb_root *root = &self->symbols[map->type];
535 struct rb_node *next = rb_first(root); 568 struct rb_node *next = rb_first(root);
536 int kernel_range = 0; 569 int kernel_range = 0;
@@ -588,6 +621,11 @@ static int dso__split_kallsyms(struct dso *self, struct map *map,
588 char dso_name[PATH_MAX]; 621 char dso_name[PATH_MAX];
589 struct dso *dso; 622 struct dso *dso;
590 623
624 if (count == 0) {
625 curr_map = map;
626 goto filter_symbol;
627 }
628
591 if (self->kernel == DSO_TYPE_GUEST_KERNEL) 629 if (self->kernel == DSO_TYPE_GUEST_KERNEL)
592 snprintf(dso_name, sizeof(dso_name), 630 snprintf(dso_name, sizeof(dso_name),
593 "[guest.kernel].%d", 631 "[guest.kernel].%d",
@@ -613,7 +651,7 @@ static int dso__split_kallsyms(struct dso *self, struct map *map,
613 map_groups__insert(kmaps, curr_map); 651 map_groups__insert(kmaps, curr_map);
614 ++kernel_range; 652 ++kernel_range;
615 } 653 }
616 654filter_symbol:
617 if (filter && filter(curr_map, pos)) { 655 if (filter && filter(curr_map, pos)) {
618discard_symbol: rb_erase(&pos->rb_node, root); 656discard_symbol: rb_erase(&pos->rb_node, root);
619 symbol__delete(pos); 657 symbol__delete(pos);
@@ -621,8 +659,9 @@ discard_symbol: rb_erase(&pos->rb_node, root);
621 if (curr_map != map) { 659 if (curr_map != map) {
622 rb_erase(&pos->rb_node, root); 660 rb_erase(&pos->rb_node, root);
623 symbols__insert(&curr_map->dso->symbols[curr_map->type], pos); 661 symbols__insert(&curr_map->dso->symbols[curr_map->type], pos);
624 } 662 ++moved;
625 count++; 663 } else
664 ++count;
626 } 665 }
627 } 666 }
628 667
@@ -632,7 +671,7 @@ discard_symbol: rb_erase(&pos->rb_node, root);
632 dso__set_loaded(curr_map->dso, curr_map->type); 671 dso__set_loaded(curr_map->dso, curr_map->type);
633 } 672 }
634 673
635 return count; 674 return count + moved;
636} 675}
637 676
638int dso__load_kallsyms(struct dso *self, const char *filename, 677int dso__load_kallsyms(struct dso *self, const char *filename,
@@ -641,7 +680,6 @@ int dso__load_kallsyms(struct dso *self, const char *filename,
641 if (dso__load_all_kallsyms(self, filename, map) < 0) 680 if (dso__load_all_kallsyms(self, filename, map) < 0)
642 return -1; 681 return -1;
643 682
644 symbols__fixup_end(&self->symbols[map->type]);
645 if (self->kernel == DSO_TYPE_GUEST_KERNEL) 683 if (self->kernel == DSO_TYPE_GUEST_KERNEL)
646 self->origin = DSO__ORIG_GUEST_KERNEL; 684 self->origin = DSO__ORIG_GUEST_KERNEL;
647 else 685 else
@@ -831,8 +869,11 @@ static int dso__synthesize_plt_symbols(struct dso *self, struct map *map,
831 char sympltname[1024]; 869 char sympltname[1024];
832 Elf *elf; 870 Elf *elf;
833 int nr = 0, symidx, fd, err = 0; 871 int nr = 0, symidx, fd, err = 0;
872 char name[PATH_MAX];
834 873
835 fd = open(self->long_name, O_RDONLY); 874 snprintf(name, sizeof(name), "%s%s",
875 symbol_conf.symfs, self->long_name);
876 fd = open(name, O_RDONLY);
836 if (fd < 0) 877 if (fd < 0)
837 goto out; 878 goto out;
838 879
@@ -1121,6 +1162,13 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name,
1121 1162
1122 section_name = elf_sec__name(&shdr, secstrs); 1163 section_name = elf_sec__name(&shdr, secstrs);
1123 1164
1165 /* On ARM, symbols for thumb functions have 1 added to
1166 * the symbol address as a flag - remove it */
1167 if ((ehdr.e_machine == EM_ARM) &&
1168 (map->type == MAP__FUNCTION) &&
1169 (sym.st_value & 1))
1170 --sym.st_value;
1171
1124 if (self->kernel != DSO_TYPE_USER || kmodule) { 1172 if (self->kernel != DSO_TYPE_USER || kmodule) {
1125 char dso_name[PATH_MAX]; 1173 char dso_name[PATH_MAX];
1126 1174
@@ -1168,8 +1216,8 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name,
1168 } 1216 }
1169 1217
1170 if (curr_dso->adjust_symbols) { 1218 if (curr_dso->adjust_symbols) {
1171 pr_debug4("%s: adjusting symbol: st_value: %#Lx " 1219 pr_debug4("%s: adjusting symbol: st_value: %#" PRIx64 " "
1172 "sh_addr: %#Lx sh_offset: %#Lx\n", __func__, 1220 "sh_addr: %#" PRIx64 " sh_offset: %#" PRIx64 "\n", __func__,
1173 (u64)sym.st_value, (u64)shdr.sh_addr, 1221 (u64)sym.st_value, (u64)shdr.sh_addr,
1174 (u64)shdr.sh_offset); 1222 (u64)shdr.sh_offset);
1175 sym.st_value -= shdr.sh_addr - shdr.sh_offset; 1223 sym.st_value -= shdr.sh_addr - shdr.sh_offset;
@@ -1444,16 +1492,19 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
1444 self->origin++) { 1492 self->origin++) {
1445 switch (self->origin) { 1493 switch (self->origin) {
1446 case DSO__ORIG_BUILD_ID_CACHE: 1494 case DSO__ORIG_BUILD_ID_CACHE:
1447 if (dso__build_id_filename(self, name, size) == NULL) 1495 /* skip the locally configured cache if a symfs is given */
1496 if (symbol_conf.symfs[0] ||
1497 (dso__build_id_filename(self, name, size) == NULL)) {
1448 continue; 1498 continue;
1499 }
1449 break; 1500 break;
1450 case DSO__ORIG_FEDORA: 1501 case DSO__ORIG_FEDORA:
1451 snprintf(name, size, "/usr/lib/debug%s.debug", 1502 snprintf(name, size, "%s/usr/lib/debug%s.debug",
1452 self->long_name); 1503 symbol_conf.symfs, self->long_name);
1453 break; 1504 break;
1454 case DSO__ORIG_UBUNTU: 1505 case DSO__ORIG_UBUNTU:
1455 snprintf(name, size, "/usr/lib/debug%s", 1506 snprintf(name, size, "%s/usr/lib/debug%s",
1456 self->long_name); 1507 symbol_conf.symfs, self->long_name);
1457 break; 1508 break;
1458 case DSO__ORIG_BUILDID: { 1509 case DSO__ORIG_BUILDID: {
1459 char build_id_hex[BUILD_ID_SIZE * 2 + 1]; 1510 char build_id_hex[BUILD_ID_SIZE * 2 + 1];
@@ -1465,19 +1516,26 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
1465 sizeof(self->build_id), 1516 sizeof(self->build_id),
1466 build_id_hex); 1517 build_id_hex);
1467 snprintf(name, size, 1518 snprintf(name, size,
1468 "/usr/lib/debug/.build-id/%.2s/%s.debug", 1519 "%s/usr/lib/debug/.build-id/%.2s/%s.debug",
1469 build_id_hex, build_id_hex + 2); 1520 symbol_conf.symfs, build_id_hex, build_id_hex + 2);
1470 } 1521 }
1471 break; 1522 break;
1472 case DSO__ORIG_DSO: 1523 case DSO__ORIG_DSO:
1473 snprintf(name, size, "%s", self->long_name); 1524 snprintf(name, size, "%s%s",
1525 symbol_conf.symfs, self->long_name);
1474 break; 1526 break;
1475 case DSO__ORIG_GUEST_KMODULE: 1527 case DSO__ORIG_GUEST_KMODULE:
1476 if (map->groups && map->groups->machine) 1528 if (map->groups && map->groups->machine)
1477 root_dir = map->groups->machine->root_dir; 1529 root_dir = map->groups->machine->root_dir;
1478 else 1530 else
1479 root_dir = ""; 1531 root_dir = "";
1480 snprintf(name, size, "%s%s", root_dir, self->long_name); 1532 snprintf(name, size, "%s%s%s", symbol_conf.symfs,
1533 root_dir, self->long_name);
1534 break;
1535
1536 case DSO__ORIG_KMODULE:
1537 snprintf(name, size, "%s%s", symbol_conf.symfs,
1538 self->long_name);
1481 break; 1539 break;
1482 1540
1483 default: 1541 default:
@@ -1772,21 +1830,24 @@ out_failure:
1772 return -1; 1830 return -1;
1773} 1831}
1774 1832
1775static int dso__load_vmlinux(struct dso *self, struct map *map, 1833int dso__load_vmlinux(struct dso *self, struct map *map,
1776 const char *vmlinux, symbol_filter_t filter) 1834 const char *vmlinux, symbol_filter_t filter)
1777{ 1835{
1778 int err = -1, fd; 1836 int err = -1, fd;
1837 char symfs_vmlinux[PATH_MAX];
1779 1838
1780 fd = open(vmlinux, O_RDONLY); 1839 snprintf(symfs_vmlinux, sizeof(symfs_vmlinux), "%s/%s",
1840 symbol_conf.symfs, vmlinux);
1841 fd = open(symfs_vmlinux, O_RDONLY);
1781 if (fd < 0) 1842 if (fd < 0)
1782 return -1; 1843 return -1;
1783 1844
1784 dso__set_loaded(self, map->type); 1845 dso__set_loaded(self, map->type);
1785 err = dso__load_sym(self, map, vmlinux, fd, filter, 0, 0); 1846 err = dso__load_sym(self, map, symfs_vmlinux, fd, filter, 0, 0);
1786 close(fd); 1847 close(fd);
1787 1848
1788 if (err > 0) 1849 if (err > 0)
1789 pr_debug("Using %s for symbols\n", vmlinux); 1850 pr_debug("Using %s for symbols\n", symfs_vmlinux);
1790 1851
1791 return err; 1852 return err;
1792} 1853}
@@ -1828,8 +1889,8 @@ static int dso__load_kernel_sym(struct dso *self, struct map *map,
1828 const char *kallsyms_filename = NULL; 1889 const char *kallsyms_filename = NULL;
1829 char *kallsyms_allocated_filename = NULL; 1890 char *kallsyms_allocated_filename = NULL;
1830 /* 1891 /*
1831 * Step 1: if the user specified a vmlinux filename, use it and only 1892 * Step 1: if the user specified a kallsyms or vmlinux filename, use
1832 * it, reporting errors to the user if it cannot be used. 1893 * it and only it, reporting errors to the user if it cannot be used.
1833 * 1894 *
1834 * For instance, try to analyse an ARM perf.data file _without_ a 1895 * For instance, try to analyse an ARM perf.data file _without_ a
1835 * build-id, or if the user specifies the wrong path to the right 1896 * build-id, or if the user specifies the wrong path to the right
@@ -1842,6 +1903,11 @@ static int dso__load_kernel_sym(struct dso *self, struct map *map,
1842 * validation in dso__load_vmlinux and will bail out if they don't 1903 * validation in dso__load_vmlinux and will bail out if they don't
1843 * match. 1904 * match.
1844 */ 1905 */
1906 if (symbol_conf.kallsyms_name != NULL) {
1907 kallsyms_filename = symbol_conf.kallsyms_name;
1908 goto do_kallsyms;
1909 }
1910
1845 if (symbol_conf.vmlinux_name != NULL) { 1911 if (symbol_conf.vmlinux_name != NULL) {
1846 err = dso__load_vmlinux(self, map, 1912 err = dso__load_vmlinux(self, map,
1847 symbol_conf.vmlinux_name, filter); 1913 symbol_conf.vmlinux_name, filter);
@@ -1859,6 +1925,10 @@ static int dso__load_kernel_sym(struct dso *self, struct map *map,
1859 goto out_fixup; 1925 goto out_fixup;
1860 } 1926 }
1861 1927
1928 /* do not try local files if a symfs was given */
1929 if (symbol_conf.symfs[0] != 0)
1930 return -1;
1931
1862 /* 1932 /*
1863 * Say the kernel DSO was created when processing the build-id header table, 1933 * Say the kernel DSO was created when processing the build-id header table,
1864 * we have a build-id, so check if it is the same as the running kernel, 1934 * we have a build-id, so check if it is the same as the running kernel,
@@ -2123,14 +2193,55 @@ static struct dso *machine__create_kernel(struct machine *self)
2123 return kernel; 2193 return kernel;
2124} 2194}
2125 2195
2196struct process_args {
2197 u64 start;
2198};
2199
2200static int symbol__in_kernel(void *arg, const char *name,
2201 char type __used, u64 start, u64 end __used)
2202{
2203 struct process_args *args = arg;
2204
2205 if (strchr(name, '['))
2206 return 0;
2207
2208 args->start = start;
2209 return 1;
2210}
2211
2212/* Figure out the start address of kernel map from /proc/kallsyms */
2213static u64 machine__get_kernel_start_addr(struct machine *machine)
2214{
2215 const char *filename;
2216 char path[PATH_MAX];
2217 struct process_args args;
2218
2219 if (machine__is_host(machine)) {
2220 filename = "/proc/kallsyms";
2221 } else {
2222 if (machine__is_default_guest(machine))
2223 filename = (char *)symbol_conf.default_guest_kallsyms;
2224 else {
2225 sprintf(path, "%s/proc/kallsyms", machine->root_dir);
2226 filename = path;
2227 }
2228 }
2229
2230 if (kallsyms__parse(filename, &args, symbol__in_kernel) <= 0)
2231 return 0;
2232
2233 return args.start;
2234}
2235
2126int __machine__create_kernel_maps(struct machine *self, struct dso *kernel) 2236int __machine__create_kernel_maps(struct machine *self, struct dso *kernel)
2127{ 2237{
2128 enum map_type type; 2238 enum map_type type;
2239 u64 start = machine__get_kernel_start_addr(self);
2129 2240
2130 for (type = 0; type < MAP__NR_TYPES; ++type) { 2241 for (type = 0; type < MAP__NR_TYPES; ++type) {
2131 struct kmap *kmap; 2242 struct kmap *kmap;
2132 2243
2133 self->vmlinux_maps[type] = map__new2(0, kernel, type); 2244 self->vmlinux_maps[type] = map__new2(start, kernel, type);
2134 if (self->vmlinux_maps[type] == NULL) 2245 if (self->vmlinux_maps[type] == NULL)
2135 return -1; 2246 return -1;
2136 2247
@@ -2208,9 +2319,6 @@ static int vmlinux_path__init(void)
2208 struct utsname uts; 2319 struct utsname uts;
2209 char bf[PATH_MAX]; 2320 char bf[PATH_MAX];
2210 2321
2211 if (uname(&uts) < 0)
2212 return -1;
2213
2214 vmlinux_path = malloc(sizeof(char *) * 5); 2322 vmlinux_path = malloc(sizeof(char *) * 5);
2215 if (vmlinux_path == NULL) 2323 if (vmlinux_path == NULL)
2216 return -1; 2324 return -1;
@@ -2223,6 +2331,14 @@ static int vmlinux_path__init(void)
2223 if (vmlinux_path[vmlinux_path__nr_entries] == NULL) 2331 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
2224 goto out_fail; 2332 goto out_fail;
2225 ++vmlinux_path__nr_entries; 2333 ++vmlinux_path__nr_entries;
2334
2335 /* only try running kernel version if no symfs was given */
2336 if (symbol_conf.symfs[0] != 0)
2337 return 0;
2338
2339 if (uname(&uts) < 0)
2340 return -1;
2341
2226 snprintf(bf, sizeof(bf), "/boot/vmlinux-%s", uts.release); 2342 snprintf(bf, sizeof(bf), "/boot/vmlinux-%s", uts.release);
2227 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf); 2343 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
2228 if (vmlinux_path[vmlinux_path__nr_entries] == NULL) 2344 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
@@ -2282,6 +2398,8 @@ static int setup_list(struct strlist **list, const char *list_str,
2282 2398
2283int symbol__init(void) 2399int symbol__init(void)
2284{ 2400{
2401 const char *symfs;
2402
2285 if (symbol_conf.initialized) 2403 if (symbol_conf.initialized)
2286 return 0; 2404 return 0;
2287 2405
@@ -2310,6 +2428,18 @@ int symbol__init(void)
2310 symbol_conf.sym_list_str, "symbol") < 0) 2428 symbol_conf.sym_list_str, "symbol") < 0)
2311 goto out_free_comm_list; 2429 goto out_free_comm_list;
2312 2430
2431 /*
2432 * A path to symbols of "/" is identical to ""
2433 * reset here for simplicity.
2434 */
2435 symfs = realpath(symbol_conf.symfs, NULL);
2436 if (symfs == NULL)
2437 symfs = symbol_conf.symfs;
2438 if (strcmp(symfs, "/") == 0)
2439 symbol_conf.symfs = "";
2440 if (symfs != symbol_conf.symfs)
2441 free((void *)symfs);
2442
2313 symbol_conf.initialized = true; 2443 symbol_conf.initialized = true;
2314 return 0; 2444 return 0;
2315 2445
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 038f2201ee09..670cd1c88f54 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -72,6 +72,7 @@ struct symbol_conf {
72 show_cpu_utilization, 72 show_cpu_utilization,
73 initialized; 73 initialized;
74 const char *vmlinux_name, 74 const char *vmlinux_name,
75 *kallsyms_name,
75 *source_prefix, 76 *source_prefix,
76 *field_sep; 77 *field_sep;
77 const char *default_guest_vmlinux_name, 78 const char *default_guest_vmlinux_name,
@@ -85,6 +86,7 @@ struct symbol_conf {
85 struct strlist *dso_list, 86 struct strlist *dso_list,
86 *comm_list, 87 *comm_list,
87 *sym_list; 88 *sym_list;
89 const char *symfs;
88}; 90};
89 91
90extern struct symbol_conf symbol_conf; 92extern struct symbol_conf symbol_conf;
@@ -166,6 +168,8 @@ void dso__sort_by_name(struct dso *self, enum map_type type);
166struct dso *__dsos__findnew(struct list_head *head, const char *name); 168struct dso *__dsos__findnew(struct list_head *head, const char *name);
167 169
168int dso__load(struct dso *self, struct map *map, symbol_filter_t filter); 170int dso__load(struct dso *self, struct map *map, symbol_filter_t filter);
171int dso__load_vmlinux(struct dso *self, struct map *map,
172 const char *vmlinux, symbol_filter_t filter);
169int dso__load_vmlinux_path(struct dso *self, struct map *map, 173int dso__load_vmlinux_path(struct dso *self, struct map *map,
170 symbol_filter_t filter); 174 symbol_filter_t filter);
171int dso__load_kallsyms(struct dso *self, const char *filename, struct map *map, 175int dso__load_kallsyms(struct dso *self, const char *filename, struct map *map,
@@ -213,7 +217,7 @@ bool __dsos__read_build_ids(struct list_head *head, bool with_hits);
213int build_id__sprintf(const u8 *self, int len, char *bf); 217int build_id__sprintf(const u8 *self, int len, char *bf);
214int kallsyms__parse(const char *filename, void *arg, 218int kallsyms__parse(const char *filename, void *arg,
215 int (*process_symbol)(void *arg, const char *name, 219 int (*process_symbol)(void *arg, const char *name,
216 char type, u64 start)); 220 char type, u64 start, u64 end));
217 221
218void machine__destroy_kernel_maps(struct machine *self); 222void machine__destroy_kernel_maps(struct machine *self);
219int __machine__create_kernel_maps(struct machine *self, struct dso *kernel); 223int __machine__create_kernel_maps(struct machine *self, struct dso *kernel);
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 8c72d888e449..00f4eade2e3e 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -16,35 +16,50 @@ static int filter(const struct dirent *dir)
16 return 1; 16 return 1;
17} 17}
18 18
19int find_all_tid(int pid, pid_t ** all_tid) 19struct thread_map *thread_map__new_by_pid(pid_t pid)
20{ 20{
21 struct thread_map *threads;
21 char name[256]; 22 char name[256];
22 int items; 23 int items;
23 struct dirent **namelist = NULL; 24 struct dirent **namelist = NULL;
24 int ret = 0;
25 int i; 25 int i;
26 26
27 sprintf(name, "/proc/%d/task", pid); 27 sprintf(name, "/proc/%d/task", pid);
28 items = scandir(name, &namelist, filter, NULL); 28 items = scandir(name, &namelist, filter, NULL);
29 if (items <= 0) 29 if (items <= 0)
30 return -ENOENT; 30 return NULL;
31 *all_tid = malloc(sizeof(pid_t) * items);
32 if (!*all_tid) {
33 ret = -ENOMEM;
34 goto failure;
35 }
36
37 for (i = 0; i < items; i++)
38 (*all_tid)[i] = atoi(namelist[i]->d_name);
39 31
40 ret = items; 32 threads = malloc(sizeof(*threads) + sizeof(pid_t) * items);
33 if (threads != NULL) {
34 for (i = 0; i < items; i++)
35 threads->map[i] = atoi(namelist[i]->d_name);
36 threads->nr = items;
37 }
41 38
42failure:
43 for (i=0; i<items; i++) 39 for (i=0; i<items; i++)
44 free(namelist[i]); 40 free(namelist[i]);
45 free(namelist); 41 free(namelist);
46 42
47 return ret; 43 return threads;
44}
45
46struct thread_map *thread_map__new_by_tid(pid_t tid)
47{
48 struct thread_map *threads = malloc(sizeof(*threads) + sizeof(pid_t));
49
50 if (threads != NULL) {
51 threads->map[0] = tid;
52 threads->nr = 1;
53 }
54
55 return threads;
56}
57
58struct thread_map *thread_map__new(pid_t pid, pid_t tid)
59{
60 if (pid != -1)
61 return thread_map__new_by_pid(pid);
62 return thread_map__new_by_tid(tid);
48} 63}
49 64
50static struct thread *thread__new(pid_t pid) 65static struct thread *thread__new(pid_t pid)
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 688500ff826f..d7574101054a 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -18,11 +18,24 @@ struct thread {
18 int comm_len; 18 int comm_len;
19}; 19};
20 20
21struct thread_map {
22 int nr;
23 int map[];
24};
25
21struct perf_session; 26struct perf_session;
22 27
23void thread__delete(struct thread *self); 28void thread__delete(struct thread *self);
24 29
25int find_all_tid(int pid, pid_t ** all_tid); 30struct thread_map *thread_map__new_by_pid(pid_t pid);
31struct thread_map *thread_map__new_by_tid(pid_t tid);
32struct thread_map *thread_map__new(pid_t pid, pid_t tid);
33
34static inline void thread_map__delete(struct thread_map *threads)
35{
36 free(threads);
37}
38
26int thread__set_comm(struct thread *self, const char *comm); 39int thread__set_comm(struct thread *self, const char *comm);
27int thread__comm_len(struct thread *self); 40int thread__comm_len(struct thread *self);
28struct thread *perf_session__findnew(struct perf_session *self, pid_t pid); 41struct thread *perf_session__findnew(struct perf_session *self, pid_t pid);
diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c
index b1572601286c..35729f4c40cb 100644
--- a/tools/perf/util/trace-event-info.c
+++ b/tools/perf/util/trace-event-info.c
@@ -34,11 +34,13 @@
34#include <ctype.h> 34#include <ctype.h>
35#include <errno.h> 35#include <errno.h>
36#include <stdbool.h> 36#include <stdbool.h>
37#include <linux/list.h>
37#include <linux/kernel.h> 38#include <linux/kernel.h>
38 39
39#include "../perf.h" 40#include "../perf.h"
40#include "trace-event.h" 41#include "trace-event.h"
41#include "debugfs.h" 42#include "debugfs.h"
43#include "evsel.h"
42 44
43#define VERSION "0.5" 45#define VERSION "0.5"
44 46
@@ -469,16 +471,17 @@ out:
469} 471}
470 472
471static struct tracepoint_path * 473static struct tracepoint_path *
472get_tracepoints_path(struct perf_event_attr *pattrs, int nb_events) 474get_tracepoints_path(struct list_head *pattrs)
473{ 475{
474 struct tracepoint_path path, *ppath = &path; 476 struct tracepoint_path path, *ppath = &path;
475 int i, nr_tracepoints = 0; 477 struct perf_evsel *pos;
478 int nr_tracepoints = 0;
476 479
477 for (i = 0; i < nb_events; i++) { 480 list_for_each_entry(pos, pattrs, node) {
478 if (pattrs[i].type != PERF_TYPE_TRACEPOINT) 481 if (pos->attr.type != PERF_TYPE_TRACEPOINT)
479 continue; 482 continue;
480 ++nr_tracepoints; 483 ++nr_tracepoints;
481 ppath->next = tracepoint_id_to_path(pattrs[i].config); 484 ppath->next = tracepoint_id_to_path(pos->attr.config);
482 if (!ppath->next) 485 if (!ppath->next)
483 die("%s\n", "No memory to alloc tracepoints list"); 486 die("%s\n", "No memory to alloc tracepoints list");
484 ppath = ppath->next; 487 ppath = ppath->next;
@@ -487,21 +490,21 @@ get_tracepoints_path(struct perf_event_attr *pattrs, int nb_events)
487 return nr_tracepoints > 0 ? path.next : NULL; 490 return nr_tracepoints > 0 ? path.next : NULL;
488} 491}
489 492
490bool have_tracepoints(struct perf_event_attr *pattrs, int nb_events) 493bool have_tracepoints(struct list_head *pattrs)
491{ 494{
492 int i; 495 struct perf_evsel *pos;
493 496
494 for (i = 0; i < nb_events; i++) 497 list_for_each_entry(pos, pattrs, node)
495 if (pattrs[i].type == PERF_TYPE_TRACEPOINT) 498 if (pos->attr.type == PERF_TYPE_TRACEPOINT)
496 return true; 499 return true;
497 500
498 return false; 501 return false;
499} 502}
500 503
501int read_tracing_data(int fd, struct perf_event_attr *pattrs, int nb_events) 504int read_tracing_data(int fd, struct list_head *pattrs)
502{ 505{
503 char buf[BUFSIZ]; 506 char buf[BUFSIZ];
504 struct tracepoint_path *tps = get_tracepoints_path(pattrs, nb_events); 507 struct tracepoint_path *tps = get_tracepoints_path(pattrs);
505 508
506 /* 509 /*
507 * What? No tracepoints? No sense writing anything here, bail out. 510 * What? No tracepoints? No sense writing anything here, bail out.
@@ -545,14 +548,13 @@ int read_tracing_data(int fd, struct perf_event_attr *pattrs, int nb_events)
545 return 0; 548 return 0;
546} 549}
547 550
548ssize_t read_tracing_data_size(int fd, struct perf_event_attr *pattrs, 551ssize_t read_tracing_data_size(int fd, struct list_head *pattrs)
549 int nb_events)
550{ 552{
551 ssize_t size; 553 ssize_t size;
552 int err = 0; 554 int err = 0;
553 555
554 calc_data_size = 1; 556 calc_data_size = 1;
555 err = read_tracing_data(fd, pattrs, nb_events); 557 err = read_tracing_data(fd, pattrs);
556 size = calc_data_size - 1; 558 size = calc_data_size - 1;
557 calc_data_size = 0; 559 calc_data_size = 0;
558 560
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index b3e86b1e4444..b5f12ca24d99 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -262,9 +262,8 @@ raw_field_value(struct event *event, const char *name, void *data);
262void *raw_field_ptr(struct event *event, const char *name, void *data); 262void *raw_field_ptr(struct event *event, const char *name, void *data);
263unsigned long long eval_flag(const char *flag); 263unsigned long long eval_flag(const char *flag);
264 264
265int read_tracing_data(int fd, struct perf_event_attr *pattrs, int nb_events); 265int read_tracing_data(int fd, struct list_head *pattrs);
266ssize_t read_tracing_data_size(int fd, struct perf_event_attr *pattrs, 266ssize_t read_tracing_data_size(int fd, struct list_head *pattrs);
267 int nb_events);
268 267
269/* taken from kernel/trace/trace.h */ 268/* taken from kernel/trace/trace.h */
270enum trace_flag_type { 269enum trace_flag_type {
diff --git a/tools/perf/util/types.h b/tools/perf/util/types.h
index 7d6b8331f898..5f3689a3d085 100644
--- a/tools/perf/util/types.h
+++ b/tools/perf/util/types.h
@@ -1,12 +1,14 @@
1#ifndef __PERF_TYPES_H 1#ifndef __PERF_TYPES_H
2#define __PERF_TYPES_H 2#define __PERF_TYPES_H
3 3
4#include <stdint.h>
5
4/* 6/*
5 * We define u64 as unsigned long long for every architecture 7 * We define u64 as uint64_t for every architecture
6 * so that we can print it with %Lx without getting warnings. 8 * so that we can print it with "%"PRIx64 without getting warnings.
7 */ 9 */
8typedef unsigned long long u64; 10typedef uint64_t u64;
9typedef signed long long s64; 11typedef int64_t s64;
10typedef unsigned int u32; 12typedef unsigned int u32;
11typedef signed int s32; 13typedef signed int s32;
12typedef unsigned short u16; 14typedef unsigned short u16;
diff --git a/tools/perf/util/ui/browsers/hists.c b/tools/perf/util/ui/browsers/hists.c
index ebda8c3fde9e..60c463c16028 100644
--- a/tools/perf/util/ui/browsers/hists.c
+++ b/tools/perf/util/ui/browsers/hists.c
@@ -350,7 +350,7 @@ static char *callchain_list__sym_name(struct callchain_list *self,
350 if (self->ms.sym) 350 if (self->ms.sym)
351 return self->ms.sym->name; 351 return self->ms.sym->name;
352 352
353 snprintf(bf, bfsize, "%#Lx", self->ip); 353 snprintf(bf, bfsize, "%#" PRIx64, self->ip);
354 return bf; 354 return bf;
355} 355}
356 356
diff --git a/tools/perf/util/ui/browsers/map.c b/tools/perf/util/ui/browsers/map.c
index e35437dfa5b4..e5158369106e 100644
--- a/tools/perf/util/ui/browsers/map.c
+++ b/tools/perf/util/ui/browsers/map.c
@@ -1,5 +1,6 @@
1#include "../libslang.h" 1#include "../libslang.h"
2#include <elf.h> 2#include <elf.h>
3#include <inttypes.h>
3#include <sys/ttydefaults.h> 4#include <sys/ttydefaults.h>
4#include <ctype.h> 5#include <ctype.h>
5#include <string.h> 6#include <string.h>
@@ -57,7 +58,7 @@ static void map_browser__write(struct ui_browser *self, void *nd, int row)
57 int width; 58 int width;
58 59
59 ui_browser__set_percent_color(self, 0, current_entry); 60 ui_browser__set_percent_color(self, 0, current_entry);
60 slsmg_printf("%*llx %*llx %c ", 61 slsmg_printf("%*" PRIx64 " %*" PRIx64 " %c ",
61 mb->addrlen, sym->start, mb->addrlen, sym->end, 62 mb->addrlen, sym->start, mb->addrlen, sym->end,
62 sym->binding == STB_GLOBAL ? 'g' : 63 sym->binding == STB_GLOBAL ? 'g' :
63 sym->binding == STB_LOCAL ? 'l' : 'w'); 64 sym->binding == STB_LOCAL ? 'l' : 'w');
@@ -150,6 +151,6 @@ int map__browse(struct map *self)
150 ++mb.b.nr_entries; 151 ++mb.b.nr_entries;
151 } 152 }
152 153
153 mb.addrlen = snprintf(tmp, sizeof(tmp), "%llx", maxaddr); 154 mb.addrlen = snprintf(tmp, sizeof(tmp), "%" PRIx64, maxaddr);
154 return map_browser__run(&mb); 155 return map_browser__run(&mb);
155} 156}
diff --git a/tools/perf/util/ui/util.c b/tools/perf/util/ui/util.c
index 9706d9d40279..7b5a8926624e 100644
--- a/tools/perf/util/ui/util.c
+++ b/tools/perf/util/ui/util.c
@@ -104,9 +104,24 @@ out_destroy_form:
104 return rc; 104 return rc;
105} 105}
106 106
107static const char yes[] = "Yes", no[] = "No",
108 warning_str[] = "Warning!", ok[] = "Ok";
109
107bool ui__dialog_yesno(const char *msg) 110bool ui__dialog_yesno(const char *msg)
108{ 111{
109 /* newtWinChoice should really be accepting const char pointers... */ 112 /* newtWinChoice should really be accepting const char pointers... */
110 char yes[] = "Yes", no[] = "No"; 113 return newtWinChoice(NULL, (char *)yes, (char *)no, (char *)msg) == 1;
111 return newtWinChoice(NULL, yes, no, (char *)msg) == 1; 114}
115
116void ui__warning(const char *format, ...)
117{
118 va_list args;
119
120 va_start(args, format);
121 if (use_browser > 0)
122 newtWinMessagev((char *)warning_str, (char *)ok,
123 (char *)format, args);
124 else
125 vfprintf(stderr, format, args);
126 va_end(args);
112} 127}
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 214265674ddd..5b3ea49aa63e 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -114,3 +114,20 @@ unsigned long convert_unit(unsigned long value, char *unit)
114 114
115 return value; 115 return value;
116} 116}
117
118int readn(int fd, void *buf, size_t n)
119{
120 void *buf_start = buf;
121
122 while (n) {
123 int ret = read(fd, buf, n);
124
125 if (ret <= 0)
126 return ret;
127
128 n -= ret;
129 buf += ret;
130 }
131
132 return buf - buf_start;
133}
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 7562707ddd1c..e833f26f3bfc 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -265,6 +265,7 @@ void argv_free(char **argv);
265bool strglobmatch(const char *str, const char *pat); 265bool strglobmatch(const char *str, const char *pat);
266bool strlazymatch(const char *str, const char *pat); 266bool strlazymatch(const char *str, const char *pat);
267unsigned long convert_unit(unsigned long value, char *unit); 267unsigned long convert_unit(unsigned long value, char *unit);
268int readn(int fd, void *buf, size_t size);
268 269
269#define _STR(x) #x 270#define _STR(x) #x
270#define STR(x) _STR(x) 271#define STR(x) _STR(x)
diff --git a/tools/perf/util/values.c b/tools/perf/util/values.c
index cfa55d686e3b..bdd33470b235 100644
--- a/tools/perf/util/values.c
+++ b/tools/perf/util/values.c
@@ -150,7 +150,7 @@ static void perf_read_values__display_pretty(FILE *fp,
150 if (width > tidwidth) 150 if (width > tidwidth)
151 tidwidth = width; 151 tidwidth = width;
152 for (j = 0; j < values->counters; j++) { 152 for (j = 0; j < values->counters; j++) {
153 width = snprintf(NULL, 0, "%Lu", values->value[i][j]); 153 width = snprintf(NULL, 0, "%" PRIu64, values->value[i][j]);
154 if (width > counterwidth[j]) 154 if (width > counterwidth[j])
155 counterwidth[j] = width; 155 counterwidth[j] = width;
156 } 156 }
@@ -165,7 +165,7 @@ static void perf_read_values__display_pretty(FILE *fp,
165 fprintf(fp, " %*d %*d", pidwidth, values->pid[i], 165 fprintf(fp, " %*d %*d", pidwidth, values->pid[i],
166 tidwidth, values->tid[i]); 166 tidwidth, values->tid[i]);
167 for (j = 0; j < values->counters; j++) 167 for (j = 0; j < values->counters; j++)
168 fprintf(fp, " %*Lu", 168 fprintf(fp, " %*" PRIu64,
169 counterwidth[j], values->value[i][j]); 169 counterwidth[j], values->value[i][j]);
170 fprintf(fp, "\n"); 170 fprintf(fp, "\n");
171 } 171 }
@@ -196,13 +196,13 @@ static void perf_read_values__display_raw(FILE *fp,
196 width = strlen(values->countername[j]); 196 width = strlen(values->countername[j]);
197 if (width > namewidth) 197 if (width > namewidth)
198 namewidth = width; 198 namewidth = width;
199 width = snprintf(NULL, 0, "%llx", values->counterrawid[j]); 199 width = snprintf(NULL, 0, "%" PRIx64, values->counterrawid[j]);
200 if (width > rawwidth) 200 if (width > rawwidth)
201 rawwidth = width; 201 rawwidth = width;
202 } 202 }
203 for (i = 0; i < values->threads; i++) { 203 for (i = 0; i < values->threads; i++) {
204 for (j = 0; j < values->counters; j++) { 204 for (j = 0; j < values->counters; j++) {
205 width = snprintf(NULL, 0, "%Lu", values->value[i][j]); 205 width = snprintf(NULL, 0, "%" PRIu64, values->value[i][j]);
206 if (width > countwidth) 206 if (width > countwidth)
207 countwidth = width; 207 countwidth = width;
208 } 208 }
@@ -214,7 +214,7 @@ static void perf_read_values__display_raw(FILE *fp,
214 countwidth, "Count"); 214 countwidth, "Count");
215 for (i = 0; i < values->threads; i++) 215 for (i = 0; i < values->threads; i++)
216 for (j = 0; j < values->counters; j++) 216 for (j = 0; j < values->counters; j++)
217 fprintf(fp, " %*d %*d %*s %*llx %*Lu\n", 217 fprintf(fp, " %*d %*d %*s %*" PRIx64 " %*" PRIu64,
218 pidwidth, values->pid[i], 218 pidwidth, values->pid[i],
219 tidwidth, values->tid[i], 219 tidwidth, values->tid[i],
220 namewidth, values->countername[j], 220 namewidth, values->countername[j],
diff --git a/tools/perf/util/xyarray.c b/tools/perf/util/xyarray.c
new file mode 100644
index 000000000000..22afbf6c536a
--- /dev/null
+++ b/tools/perf/util/xyarray.c
@@ -0,0 +1,20 @@
1#include "xyarray.h"
2#include "util.h"
3
4struct xyarray *xyarray__new(int xlen, int ylen, size_t entry_size)
5{
6 size_t row_size = ylen * entry_size;
7 struct xyarray *xy = zalloc(sizeof(*xy) + xlen * row_size);
8
9 if (xy != NULL) {
10 xy->entry_size = entry_size;
11 xy->row_size = row_size;
12 }
13
14 return xy;
15}
16
17void xyarray__delete(struct xyarray *xy)
18{
19 free(xy);
20}
diff --git a/tools/perf/util/xyarray.h b/tools/perf/util/xyarray.h
new file mode 100644
index 000000000000..c488a07275dd
--- /dev/null
+++ b/tools/perf/util/xyarray.h
@@ -0,0 +1,20 @@
1#ifndef _PERF_XYARRAY_H_
2#define _PERF_XYARRAY_H_ 1
3
4#include <sys/types.h>
5
6struct xyarray {
7 size_t row_size;
8 size_t entry_size;
9 char contents[];
10};
11
12struct xyarray *xyarray__new(int xlen, int ylen, size_t entry_size);
13void xyarray__delete(struct xyarray *xy);
14
15static inline void *xyarray__entry(struct xyarray *xy, int x, int y)
16{
17 return &xy->contents[x * xy->row_size + y * xy->entry_size];
18}
19
20#endif /* _PERF_XYARRAY_H_ */