aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <m.chehab@samsung.com>2014-02-03 12:32:45 -0500
committerMauro Carvalho Chehab <m.chehab@samsung.com>2014-02-03 12:32:45 -0500
commitc29b8f3149f2916e98fc3b8d6c1df2137d003979 (patch)
treeaf6b4e876c732daaafb59781836bfce9715d21c2 /tools/perf
parent587d1b06e07b4a079453c74ba9edf17d21931049 (diff)
parent38dbfb59d1175ef458d006556061adeaa8751b72 (diff)
Merge tag 'v3.14-rc1' into patchwork
Linus 3.14-rc1 * tag 'v3.14-rc1': (11781 commits) Linus 3.14-rc1 hpfs: optimize quad buffer loading hpfs: remember free space parisc: add flexible mmap memory layout support parisc: Make EWOULDBLOCK be equal to EAGAIN on parisc parisc: convert uapi/asm/stat.h to use native types only parisc: wire up sched_setattr and sched_getattr parisc: fix cache-flushing parisc/sti_console: prefer Linux fonts over built-in ROM fonts hwmon: Fix SENSORS_TMP102 dependencies to eliminate build errors hwmon: Fix SENSORS_LM75 dependencies to eliminate build errors tools/power turbostat: introduce -s to dump counters tools/power turbostat: remove unused command line option afs: proc cells and rootcell are writeable tile: remove compat_sys_lookup_dcookie declaration to fix compile error Revert "PCI: Remove from bus_list and release resources in pci_release_dev()" ARM: multi_v7_defconfig: remove redundant entries and re-enable TI_EDMA ARM: multi_v7_defconfig: add mvebu drivers clocksource: kona: Add basic use of external clock drivers: bus: fix CCI driver kcalloc call parameters swap ...
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/Documentation/perf-archive.txt6
-rw-r--r--tools/perf/Documentation/perf-kvm.txt34
-rw-r--r--tools/perf/Documentation/perf-record.txt20
-rw-r--r--tools/perf/Documentation/perf-report.txt9
-rw-r--r--tools/perf/Documentation/perf-script.txt14
-rw-r--r--tools/perf/Documentation/perf-stat.txt2
-rw-r--r--tools/perf/Documentation/perf-timechart.txt42
-rw-r--r--tools/perf/Documentation/perf-top.txt5
-rw-r--r--tools/perf/MANIFEST6
-rw-r--r--tools/perf/Makefile13
-rw-r--r--tools/perf/Makefile.perf66
-rw-r--r--tools/perf/arch/common.c3
-rw-r--r--tools/perf/builtin-annotate.c17
-rw-r--r--tools/perf/builtin-diff.c103
-rw-r--r--tools/perf/builtin-evlist.c2
-rw-r--r--tools/perf/builtin-inject.c67
-rw-r--r--tools/perf/builtin-kvm.c25
-rw-r--r--tools/perf/builtin-mem.c5
-rw-r--r--tools/perf/builtin-probe.c67
-rw-r--r--tools/perf/builtin-record.c201
-rw-r--r--tools/perf/builtin-report.c433
-rw-r--r--tools/perf/builtin-sched.c2
-rw-r--r--tools/perf/builtin-script.c266
-rw-r--r--tools/perf/builtin-stat.c186
-rw-r--r--tools/perf/builtin-timechart.c755
-rw-r--r--tools/perf/builtin-top.c88
-rw-r--r--tools/perf/builtin-trace.c98
-rw-r--r--tools/perf/config/Makefile136
-rw-r--r--tools/perf/config/Makefile.arch22
-rw-r--r--tools/perf/config/feature-checks/.gitignore2
-rw-r--r--tools/perf/config/feature-checks/Makefile129
-rw-r--r--tools/perf/config/feature-checks/test-all.c5
-rw-r--r--tools/perf/config/feature-checks/test-stackprotector.c6
-rw-r--r--tools/perf/config/feature-checks/test-volatile-register-var.c6
-rw-r--r--tools/perf/config/utilities.mak7
-rw-r--r--tools/perf/perf-completion.sh (renamed from tools/perf/bash_completion)104
-rw-r--r--tools/perf/perf.c2
-rw-r--r--tools/perf/perf.h13
-rw-r--r--tools/perf/tests/attr/test-record-no-inherit2
-rw-r--r--tools/perf/tests/code-reading.c9
-rw-r--r--tools/perf/tests/evsel-roundtrip-name.c2
-rw-r--r--tools/perf/tests/hists_link.c4
-rw-r--r--tools/perf/tests/keep-tracking.c9
-rw-r--r--tools/perf/tests/make58
-rw-r--r--tools/perf/tests/mmap-basic.c25
-rw-r--r--tools/perf/tests/open-syscall-tp-fields.c26
-rw-r--r--tools/perf/tests/parse-events.c12
-rw-r--r--tools/perf/tests/perf-record.c29
-rwxr-xr-xtools/perf/tests/perf-targz-src-pkg21
-rw-r--r--tools/perf/tests/perf-time-to-tsc.c8
-rw-r--r--tools/perf/tests/sw-clock.c18
-rw-r--r--tools/perf/tests/task-exit.c33
-rw-r--r--tools/perf/ui/browser.c8
-rw-r--r--tools/perf/ui/browser.h2
-rw-r--r--tools/perf/ui/browsers/header.c127
-rw-r--r--tools/perf/ui/browsers/hists.c68
-rw-r--r--tools/perf/ui/browsers/scripts.c3
-rw-r--r--tools/perf/ui/gtk/hists.c2
-rw-r--r--tools/perf/ui/gtk/util.c3
-rw-r--r--tools/perf/ui/stdio/hist.c2
-rw-r--r--tools/perf/ui/tui/util.c19
-rw-r--r--tools/perf/util/alias.c6
-rw-r--r--tools/perf/util/annotate.c75
-rw-r--r--tools/perf/util/annotate.h9
-rw-r--r--tools/perf/util/build-id.c2
-rw-r--r--tools/perf/util/build-id.h2
-rw-r--r--tools/perf/util/callchain.c46
-rw-r--r--tools/perf/util/callchain.h8
-rw-r--r--tools/perf/util/cgroup.c6
-rw-r--r--tools/perf/util/color.c15
-rw-r--r--tools/perf/util/color.h1
-rw-r--r--tools/perf/util/comm.c21
-rw-r--r--tools/perf/util/comm.h2
-rw-r--r--tools/perf/util/data.c6
-rw-r--r--tools/perf/util/data.h14
-rw-r--r--tools/perf/util/debug.c31
-rw-r--r--tools/perf/util/debug.h2
-rw-r--r--tools/perf/util/dso.c134
-rw-r--r--tools/perf/util/dso.h31
-rw-r--r--tools/perf/util/event.c61
-rw-r--r--tools/perf/util/event.h7
-rw-r--r--tools/perf/util/evlist.c128
-rw-r--r--tools/perf/util/evlist.h81
-rw-r--r--tools/perf/util/evsel.c76
-rw-r--r--tools/perf/util/evsel.h7
-rw-r--r--tools/perf/util/header.c77
-rw-r--r--tools/perf/util/header.h10
-rw-r--r--tools/perf/util/help.c7
-rw-r--r--tools/perf/util/hist.c49
-rw-r--r--tools/perf/util/hist.h3
-rw-r--r--tools/perf/util/include/asm/bug.h22
-rw-r--r--tools/perf/util/include/linux/compiler.h30
-rw-r--r--tools/perf/util/machine.c36
-rw-r--r--tools/perf/util/map.c24
-rw-r--r--tools/perf/util/map.h2
-rw-r--r--tools/perf/util/parse-events.c43
-rw-r--r--tools/perf/util/parse-options.c21
-rw-r--r--tools/perf/util/parse-options.h8
-rw-r--r--tools/perf/util/pmu.c158
-rw-r--r--tools/perf/util/pmu.h3
-rw-r--r--tools/perf/util/probe-event.c258
-rw-r--r--tools/perf/util/probe-event.h7
-rw-r--r--tools/perf/util/probe-finder.c33
-rw-r--r--tools/perf/util/python-ext-sources1
-rw-r--r--tools/perf/util/python.c3
-rw-r--r--tools/perf/util/record.c52
-rw-r--r--tools/perf/util/scripting-engines/trace-event-perl.c22
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c28
-rw-r--r--tools/perf/util/session.c120
-rw-r--r--tools/perf/util/session.h10
-rw-r--r--tools/perf/util/setup.py4
-rw-r--r--tools/perf/util/sort.c22
-rw-r--r--tools/perf/util/srcline.c72
-rw-r--r--tools/perf/util/strbuf.c2
-rw-r--r--tools/perf/util/strfilter.c2
-rw-r--r--tools/perf/util/string.c2
-rw-r--r--tools/perf/util/strlist.c3
-rw-r--r--tools/perf/util/svghelper.c235
-rw-r--r--tools/perf/util/svghelper.h17
-rw-r--r--tools/perf/util/symbol-elf.c8
-rw-r--r--tools/perf/util/symbol-minimal.c4
-rw-r--r--tools/perf/util/symbol.c165
-rw-r--r--tools/perf/util/symbol.h16
-rw-r--r--tools/perf/util/target.c11
-rw-r--r--tools/perf/util/target.h17
-rw-r--r--tools/perf/util/thread.c18
-rw-r--r--tools/perf/util/thread.h12
-rw-r--r--tools/perf/util/thread_map.c20
-rw-r--r--tools/perf/util/top.c2
-rw-r--r--tools/perf/util/top.h2
-rw-r--r--tools/perf/util/trace-event-info.c12
-rw-r--r--tools/perf/util/trace-event-parse.c13
-rw-r--r--tools/perf/util/trace-event-read.c20
-rw-r--r--tools/perf/util/trace-event-scripting.c3
-rw-r--r--tools/perf/util/trace-event.c82
-rw-r--r--tools/perf/util/trace-event.h16
-rw-r--r--tools/perf/util/unwind.c28
-rw-r--r--tools/perf/util/util.c136
-rw-r--r--tools/perf/util/util.h26
-rw-r--r--tools/perf/util/values.c14
-rw-r--r--tools/perf/util/vdso.c2
141 files changed, 4067 insertions, 2174 deletions
diff --git a/tools/perf/Documentation/perf-archive.txt b/tools/perf/Documentation/perf-archive.txt
index 5032a142853e..ac6ecbb3e669 100644
--- a/tools/perf/Documentation/perf-archive.txt
+++ b/tools/perf/Documentation/perf-archive.txt
@@ -12,9 +12,9 @@ SYNOPSIS
12 12
13DESCRIPTION 13DESCRIPTION
14----------- 14-----------
15This command runs runs perf-buildid-list --with-hits, and collects the files 15This command runs perf-buildid-list --with-hits, and collects the files with the
16with the buildids found so that analysis of perf.data contents can be possible 16buildids found so that analysis of perf.data contents can be possible on another
17on another machine. 17machine.
18 18
19 19
20SEE ALSO 20SEE ALSO
diff --git a/tools/perf/Documentation/perf-kvm.txt b/tools/perf/Documentation/perf-kvm.txt
index 6a06cefe9642..52276a6d2b75 100644
--- a/tools/perf/Documentation/perf-kvm.txt
+++ b/tools/perf/Documentation/perf-kvm.txt
@@ -10,9 +10,9 @@ SYNOPSIS
10[verse] 10[verse]
11'perf kvm' [--host] [--guest] [--guestmount=<path> 11'perf kvm' [--host] [--guest] [--guestmount=<path>
12 [--guestkallsyms=<path> --guestmodules=<path> | --guestvmlinux=<path>]] 12 [--guestkallsyms=<path> --guestmodules=<path> | --guestvmlinux=<path>]]
13 {top|record|report|diff|buildid-list} 13 {top|record|report|diff|buildid-list} [<options>]
14'perf kvm' [--host] [--guest] [--guestkallsyms=<path> --guestmodules=<path> 14'perf kvm' [--host] [--guest] [--guestkallsyms=<path> --guestmodules=<path>
15 | --guestvmlinux=<path>] {top|record|report|diff|buildid-list|stat} 15 | --guestvmlinux=<path>] {top|record|report|diff|buildid-list|stat} [<options>]
16'perf kvm stat [record|report|live] [<options>] 16'perf kvm stat [record|report|live] [<options>]
17 17
18DESCRIPTION 18DESCRIPTION
@@ -24,10 +24,17 @@ There are a couple of variants of perf kvm:
24 of an arbitrary workload. 24 of an arbitrary workload.
25 25
26 'perf kvm record <command>' to record the performance counter profile 26 'perf kvm record <command>' to record the performance counter profile
27 of an arbitrary workload and save it into a perf data file. If both 27 of an arbitrary workload and save it into a perf data file. We set the
28 --host and --guest are input, the perf data file name is perf.data.kvm. 28 default behavior of perf kvm as --guest, so if neither --host nor --guest
29 If there is no --host but --guest, the file name is perf.data.guest. 29 is input, the perf data file name is perf.data.guest. If --host is input,
30 If there is no --guest but --host, the file name is perf.data.host. 30 the perf data file name is perf.data.kvm. If you want to record data into
31 perf.data.host, please input --host --no-guest. The behaviors are shown as
32 following:
33 Default('') -> perf.data.guest
34 --host -> perf.data.kvm
35 --guest -> perf.data.guest
36 --host --guest -> perf.data.kvm
37 --host --no-guest -> perf.data.host
31 38
32 'perf kvm report' to display the performance counter profile information 39 'perf kvm report' to display the performance counter profile information
33 recorded via perf kvm record. 40 recorded via perf kvm record.
@@ -37,7 +44,9 @@ There are a couple of variants of perf kvm:
37 44
38 'perf kvm buildid-list' to display the buildids found in a perf data file, 45 'perf kvm buildid-list' to display the buildids found in a perf data file,
39 so that other tools can be used to fetch packages with matching symbol tables 46 so that other tools can be used to fetch packages with matching symbol tables
40 for use by perf report. 47 for use by perf report. As buildid is read from /sys/kernel/notes in os, then
48 if you want to list the buildid for guest, please make sure your perf data file
49 was captured with --guestmount in perf kvm record.
41 50
42 'perf kvm stat <command>' to run a command and gather performance counter 51 'perf kvm stat <command>' to run a command and gather performance counter
43 statistics. 52 statistics.
@@ -58,14 +67,14 @@ There are a couple of variants of perf kvm:
58OPTIONS 67OPTIONS
59------- 68-------
60-i:: 69-i::
61--input=:: 70--input=<path>::
62 Input file name. 71 Input file name.
63-o:: 72-o::
64--output:: 73--output=<path>::
65 Output file name. 74 Output file name.
66--host=:: 75--host::
67 Collect host side performance profile. 76 Collect host side performance profile.
68--guest=:: 77--guest::
69 Collect guest side performance profile. 78 Collect guest side performance profile.
70--guestmount=<path>:: 79--guestmount=<path>::
71 Guest os root file system mount directory. Users mounts guest os 80 Guest os root file system mount directory. Users mounts guest os
@@ -84,6 +93,9 @@ OPTIONS
84 kernel module information. Users copy it out from guest os. 93 kernel module information. Users copy it out from guest os.
85--guestvmlinux=<path>:: 94--guestvmlinux=<path>::
86 Guest os kernel vmlinux. 95 Guest os kernel vmlinux.
96-v::
97--verbose::
98 Be more verbose (show counter open errors, etc).
87 99
88STAT REPORT OPTIONS 100STAT REPORT OPTIONS
89------------------- 101-------------------
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 43b42c4f4a91..c71b0f36d9e8 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -57,6 +57,8 @@ OPTIONS
57-t:: 57-t::
58--tid=:: 58--tid=::
59 Record events on existing thread ID (comma separated list). 59 Record events on existing thread ID (comma separated list).
60 This option also disables inheritance by default. Enable it by adding
61 --inherit.
60 62
61-u:: 63-u::
62--uid=:: 64--uid=::
@@ -66,8 +68,7 @@ OPTIONS
66--realtime=:: 68--realtime=::
67 Collect data with this RT SCHED_FIFO priority. 69 Collect data with this RT SCHED_FIFO priority.
68 70
69-D:: 71--no-buffering::
70--no-delay::
71 Collect data without buffering. 72 Collect data without buffering.
72 73
73-c:: 74-c::
@@ -201,11 +202,16 @@ abort events and some memory events in precise mode on modern Intel CPUs.
201--transaction:: 202--transaction::
202Record transaction flags for transaction related events. 203Record transaction flags for transaction related events.
203 204
204--force-per-cpu:: 205--per-thread::
205Force the use of per-cpu mmaps. By default, when tasks are specified (i.e. -p, 206Use per-thread mmaps. By default per-cpu mmaps are created. This option
206-t or -u options) per-thread mmaps are created. This option overrides that and 207overrides that and uses per-thread mmaps. A side-effect of that is that
207forces per-cpu mmaps. A side-effect of that is that inheritance is 208inheritance is automatically disabled. --per-thread is ignored with a warning
208automatically enabled. Add the -i option also to disable inheritance. 209if combined with -a or -C options.
210
211-D::
212--delay=::
213After starting the program, wait msecs before measuring. This is useful to
214filter out the startup phase of the program, which is often very different.
209 215
210SEE ALSO 216SEE ALSO
211-------- 217--------
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 10a279871251..8eab8a4bdeb8 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -237,6 +237,15 @@ OPTIONS
237 Do not show entries which have an overhead under that percent. 237 Do not show entries which have an overhead under that percent.
238 (Default: 0). 238 (Default: 0).
239 239
240--header::
241 Show header information in the perf.data file. This includes
242 various information like hostname, OS and perf version, cpu/mem
243 info, perf command line, event list and so on. Currently only
244 --stdio output supports this feature.
245
246--header-only::
247 Show only perf.data header (forces --stdio).
248
240SEE ALSO 249SEE ALSO
241-------- 250--------
242linkperf:perf-stat[1], linkperf:perf-annotate[1] 251linkperf:perf-stat[1], linkperf:perf-annotate[1]
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index e9cbfcddfa3f..05f9a0a6784c 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -115,7 +115,7 @@ OPTIONS
115-f:: 115-f::
116--fields:: 116--fields::
117 Comma separated list of fields to print. Options are: 117 Comma separated list of fields to print. Options are:
118 comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff. 118 comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff, srcline.
119 Field list can be prepended with the type, trace, sw or hw, 119 Field list can be prepended with the type, trace, sw or hw,
120 to indicate to which event type the field list applies. 120 to indicate to which event type the field list applies.
121 e.g., -f sw:comm,tid,time,ip,sym and -f trace:time,cpu,trace 121 e.g., -f sw:comm,tid,time,ip,sym and -f trace:time,cpu,trace
@@ -203,6 +203,18 @@ OPTIONS
203--show-kernel-path:: 203--show-kernel-path::
204 Try to resolve the path of [kernel.kallsyms] 204 Try to resolve the path of [kernel.kallsyms]
205 205
206--show-task-events
207 Display task related events (e.g. FORK, COMM, EXIT).
208
209--show-mmap-events
210 Display mmap related events (e.g. MMAP, MMAP2).
211
212--header
213 Show perf.data header.
214
215--header-only
216 Show only perf.data header.
217
206SEE ALSO 218SEE ALSO
207-------- 219--------
208linkperf:perf-record[1], linkperf:perf-script-perl[1], 220linkperf:perf-record[1], linkperf:perf-script-perl[1],
diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index 80c7da6732f2..29ee857c09c6 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -133,7 +133,7 @@ use --per-core in addition to -a. (system-wide). The output includes the
133core number and the number of online logical processors on that physical processor. 133core number and the number of online logical processors on that physical processor.
134 134
135-D msecs:: 135-D msecs::
136--initial-delay msecs:: 136--delay msecs::
137After starting the program, wait msecs before measuring. This is useful to 137After starting the program, wait msecs before measuring. This is useful to
138filter out the startup phase of the program, which is often very different. 138filter out the startup phase of the program, which is often very different.
139 139
diff --git a/tools/perf/Documentation/perf-timechart.txt b/tools/perf/Documentation/perf-timechart.txt
index 3ff8bd4f0b4d..bc5990c33dc0 100644
--- a/tools/perf/Documentation/perf-timechart.txt
+++ b/tools/perf/Documentation/perf-timechart.txt
@@ -8,8 +8,7 @@ perf-timechart - Tool to visualize total system behavior during a workload
8SYNOPSIS 8SYNOPSIS
9-------- 9--------
10[verse] 10[verse]
11'perf timechart' record <command> 11'perf timechart' [<timechart options>] {record} [<record options>]
12'perf timechart' [<options>]
13 12
14DESCRIPTION 13DESCRIPTION
15----------- 14-----------
@@ -21,8 +20,8 @@ There are two variants of perf timechart:
21 'perf timechart' to turn a trace into a Scalable Vector Graphics file, 20 'perf timechart' to turn a trace into a Scalable Vector Graphics file,
22 that can be viewed with popular SVG viewers such as 'Inkscape'. 21 that can be viewed with popular SVG viewers such as 'Inkscape'.
23 22
24OPTIONS 23TIMECHART OPTIONS
25------- 24-----------------
26-o:: 25-o::
27--output=:: 26--output=::
28 Select the output file (default: output.svg) 27 Select the output file (default: output.svg)
@@ -35,6 +34,9 @@ OPTIONS
35-P:: 34-P::
36--power-only:: 35--power-only::
37 Only output the CPU power section of the diagram 36 Only output the CPU power section of the diagram
37-T::
38--tasks-only::
39 Don't output processor state transitions
38-p:: 40-p::
39--process:: 41--process::
40 Select the processes to display, by name or PID 42 Select the processes to display, by name or PID
@@ -54,6 +56,38 @@ $ perf timechart
54 56
55 Written 10.2 seconds of trace to output.svg. 57 Written 10.2 seconds of trace to output.svg.
56 58
59Record system-wide timechart:
60
61 $ perf timechart record
62
63 then generate timechart and highlight 'gcc' tasks:
64
65 $ perf timechart --highlight gcc
66
67-n::
68--proc-num::
69 Print task info for at least given number of tasks.
70-t::
71--topology::
72 Sort CPUs according to topology.
73--highlight=<duration_nsecs|task_name>::
74 Highlight tasks (using different color) that run more than given
75 duration or tasks with given name. If number is given it's interpreted
76 as number of nanoseconds. If non-numeric string is given it's
77 interpreted as task name.
78
79RECORD OPTIONS
80--------------
81-P::
82--power-only::
83 Record only power-related events
84-T::
85--tasks-only::
86 Record only tasks-related events
87-g::
88--callchain::
89 Do call-graph (stack chain/backtrace) recording
90
57SEE ALSO 91SEE ALSO
58-------- 92--------
59linkperf:perf-record[1] 93linkperf:perf-record[1]
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt
index 7de01dd79688..cdd8d4946dba 100644
--- a/tools/perf/Documentation/perf-top.txt
+++ b/tools/perf/Documentation/perf-top.txt
@@ -50,7 +50,6 @@ 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:: 53--group::
55 Put the counters into a counter group. 54 Put the counters into a counter group.
56 55
@@ -143,12 +142,12 @@ Default is to monitor all CPUS.
143--asm-raw:: 142--asm-raw::
144 Show raw instruction encoding of assembly instructions. 143 Show raw instruction encoding of assembly instructions.
145 144
146-G:: 145-g::
147 Enables call-graph (stack chain/backtrace) recording. 146 Enables call-graph (stack chain/backtrace) recording.
148 147
149--call-graph:: 148--call-graph::
150 Setup and enable call-graph (stack chain/backtrace) recording, 149 Setup and enable call-graph (stack chain/backtrace) recording,
151 implies -G. 150 implies -g.
152 151
153--max-stack:: 152--max-stack::
154 Set the stack depth limit when parsing the callchain, anything 153 Set the stack depth limit when parsing the callchain, anything
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST
index 025de796067c..f41572d0dd76 100644
--- a/tools/perf/MANIFEST
+++ b/tools/perf/MANIFEST
@@ -1,7 +1,11 @@
1tools/perf 1tools/perf
2tools/scripts 2tools/scripts
3tools/lib/traceevent 3tools/lib/traceevent
4tools/lib/lk 4tools/lib/api
5tools/lib/symbol/kallsyms.c
6tools/lib/symbol/kallsyms.h
7tools/include/asm/bug.h
8tools/include/linux/compiler.h
5include/linux/const.h 9include/linux/const.h
6include/linux/perf_event.h 10include/linux/perf_event.h
7include/linux/rbtree.h 11include/linux/rbtree.h
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 4835618a5608..cb2e5868c8e8 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -60,8 +60,11 @@ endef
60 60
61# 61#
62# Needed if no target specified: 62# Needed if no target specified:
63# (Except for tags and TAGS targets. The reason is that the
64# Makefile does not treat tags/TAGS as targets but as files
65# and thus won't rebuilt them once they are in place.)
63# 66#
64all: 67all tags TAGS:
65 $(print_msg) 68 $(print_msg)
66 $(make) 69 $(make)
67 70
@@ -72,8 +75,16 @@ clean:
72 $(make) 75 $(make)
73 76
74# 77#
78# The build-test target is not really parallel, don't print the jobs info:
79#
80build-test:
81 @$(MAKE) -f tests/make --no-print-directory
82
83#
75# All other targets get passed through: 84# All other targets get passed through:
76# 85#
77%: 86%:
78 $(print_msg) 87 $(print_msg)
79 $(make) 88 $(make)
89
90.PHONY: tags TAGS
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 7fc8f179cae7..7257e7e9e38a 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -76,6 +76,7 @@ $(OUTPUT)PERF-VERSION-FILE: ../../.git/HEAD
76 76
77CC = $(CROSS_COMPILE)gcc 77CC = $(CROSS_COMPILE)gcc
78AR = $(CROSS_COMPILE)ar 78AR = $(CROSS_COMPILE)ar
79PKG_CONFIG = $(CROSS_COMPILE)pkg-config
79 80
80RM = rm -f 81RM = rm -f
81LN = ln -f 82LN = ln -f
@@ -86,7 +87,7 @@ FLEX = flex
86BISON = bison 87BISON = bison
87STRIP = strip 88STRIP = strip
88 89
89LK_DIR = $(srctree)/tools/lib/lk/ 90LIB_DIR = $(srctree)/tools/lib/api/
90TRACE_EVENT_DIR = $(srctree)/tools/lib/traceevent/ 91TRACE_EVENT_DIR = $(srctree)/tools/lib/traceevent/
91 92
92# include config/Makefile by default and rule out 93# include config/Makefile by default and rule out
@@ -105,7 +106,7 @@ ifeq ($(config),1)
105include config/Makefile 106include config/Makefile
106endif 107endif
107 108
108export prefix bindir sharedir sysconfdir 109export prefix bindir sharedir sysconfdir DESTDIR
109 110
110# sparse is architecture-neutral, which means that we need to tell it 111# sparse is architecture-neutral, which means that we need to tell it
111# explicitly what architecture to check for. Fix this up for yours.. 112# explicitly what architecture to check for. Fix this up for yours..
@@ -127,20 +128,20 @@ strip-libs = $(filter-out -l%,$(1))
127ifneq ($(OUTPUT),) 128ifneq ($(OUTPUT),)
128 TE_PATH=$(OUTPUT) 129 TE_PATH=$(OUTPUT)
129ifneq ($(subdir),) 130ifneq ($(subdir),)
130 LK_PATH=$(OUTPUT)/../lib/lk/ 131 LIB_PATH=$(OUTPUT)/../lib/api/
131else 132else
132 LK_PATH=$(OUTPUT) 133 LIB_PATH=$(OUTPUT)
133endif 134endif
134else 135else
135 TE_PATH=$(TRACE_EVENT_DIR) 136 TE_PATH=$(TRACE_EVENT_DIR)
136 LK_PATH=$(LK_DIR) 137 LIB_PATH=$(LIB_DIR)
137endif 138endif
138 139
139LIBTRACEEVENT = $(TE_PATH)libtraceevent.a 140LIBTRACEEVENT = $(TE_PATH)libtraceevent.a
140export LIBTRACEEVENT 141export LIBTRACEEVENT
141 142
142LIBLK = $(LK_PATH)liblk.a 143LIBAPIKFS = $(LIB_PATH)libapikfs.a
143export LIBLK 144export LIBAPIKFS
144 145
145# python extension build directories 146# python extension build directories
146PYTHON_EXTBUILD := $(OUTPUT)python_ext_build/ 147PYTHON_EXTBUILD := $(OUTPUT)python_ext_build/
@@ -151,7 +152,7 @@ export PYTHON_EXTBUILD_LIB PYTHON_EXTBUILD_TMP
151python-clean := $(call QUIET_CLEAN, python) $(RM) -r $(PYTHON_EXTBUILD) $(OUTPUT)python/perf.so 152python-clean := $(call QUIET_CLEAN, python) $(RM) -r $(PYTHON_EXTBUILD) $(OUTPUT)python/perf.so
152 153
153PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources) 154PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources)
154PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBLK) 155PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBAPIKFS)
155 156
156$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) 157$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS)
157 $(QUIET_GEN)CFLAGS='$(CFLAGS)' $(PYTHON_WORD) util/setup.py \ 158 $(QUIET_GEN)CFLAGS='$(CFLAGS)' $(PYTHON_WORD) util/setup.py \
@@ -202,6 +203,7 @@ $(OUTPUT)util/pmu.o: $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-bison.c
202 203
203LIB_FILE=$(OUTPUT)libperf.a 204LIB_FILE=$(OUTPUT)libperf.a
204 205
206LIB_H += ../lib/symbol/kallsyms.h
205LIB_H += ../../include/uapi/linux/perf_event.h 207LIB_H += ../../include/uapi/linux/perf_event.h
206LIB_H += ../../include/linux/rbtree.h 208LIB_H += ../../include/linux/rbtree.h
207LIB_H += ../../include/linux/list.h 209LIB_H += ../../include/linux/list.h
@@ -210,7 +212,7 @@ LIB_H += ../../include/linux/hash.h
210LIB_H += ../../include/linux/stringify.h 212LIB_H += ../../include/linux/stringify.h
211LIB_H += util/include/linux/bitmap.h 213LIB_H += util/include/linux/bitmap.h
212LIB_H += util/include/linux/bitops.h 214LIB_H += util/include/linux/bitops.h
213LIB_H += util/include/linux/compiler.h 215LIB_H += ../include/linux/compiler.h
214LIB_H += util/include/linux/const.h 216LIB_H += util/include/linux/const.h
215LIB_H += util/include/linux/ctype.h 217LIB_H += util/include/linux/ctype.h
216LIB_H += util/include/linux/kernel.h 218LIB_H += util/include/linux/kernel.h
@@ -225,7 +227,7 @@ LIB_H += util/include/linux/string.h
225LIB_H += util/include/linux/types.h 227LIB_H += util/include/linux/types.h
226LIB_H += util/include/linux/linkage.h 228LIB_H += util/include/linux/linkage.h
227LIB_H += util/include/asm/asm-offsets.h 229LIB_H += util/include/asm/asm-offsets.h
228LIB_H += util/include/asm/bug.h 230LIB_H += ../include/asm/bug.h
229LIB_H += util/include/asm/byteorder.h 231LIB_H += util/include/asm/byteorder.h
230LIB_H += util/include/asm/hweight.h 232LIB_H += util/include/asm/hweight.h
231LIB_H += util/include/asm/swab.h 233LIB_H += util/include/asm/swab.h
@@ -312,6 +314,7 @@ LIB_OBJS += $(OUTPUT)util/evlist.o
312LIB_OBJS += $(OUTPUT)util/evsel.o 314LIB_OBJS += $(OUTPUT)util/evsel.o
313LIB_OBJS += $(OUTPUT)util/exec_cmd.o 315LIB_OBJS += $(OUTPUT)util/exec_cmd.o
314LIB_OBJS += $(OUTPUT)util/help.o 316LIB_OBJS += $(OUTPUT)util/help.o
317LIB_OBJS += $(OUTPUT)util/kallsyms.o
315LIB_OBJS += $(OUTPUT)util/levenshtein.o 318LIB_OBJS += $(OUTPUT)util/levenshtein.o
316LIB_OBJS += $(OUTPUT)util/parse-options.o 319LIB_OBJS += $(OUTPUT)util/parse-options.o
317LIB_OBJS += $(OUTPUT)util/parse-events.o 320LIB_OBJS += $(OUTPUT)util/parse-events.o
@@ -353,6 +356,7 @@ LIB_OBJS += $(OUTPUT)util/pmu-bison.o
353LIB_OBJS += $(OUTPUT)util/trace-event-read.o 356LIB_OBJS += $(OUTPUT)util/trace-event-read.o
354LIB_OBJS += $(OUTPUT)util/trace-event-info.o 357LIB_OBJS += $(OUTPUT)util/trace-event-info.o
355LIB_OBJS += $(OUTPUT)util/trace-event-scripting.o 358LIB_OBJS += $(OUTPUT)util/trace-event-scripting.o
359LIB_OBJS += $(OUTPUT)util/trace-event.o
356LIB_OBJS += $(OUTPUT)util/svghelper.o 360LIB_OBJS += $(OUTPUT)util/svghelper.o
357LIB_OBJS += $(OUTPUT)util/sort.o 361LIB_OBJS += $(OUTPUT)util/sort.o
358LIB_OBJS += $(OUTPUT)util/hist.o 362LIB_OBJS += $(OUTPUT)util/hist.o
@@ -438,7 +442,7 @@ BUILTIN_OBJS += $(OUTPUT)builtin-inject.o
438BUILTIN_OBJS += $(OUTPUT)tests/builtin-test.o 442BUILTIN_OBJS += $(OUTPUT)tests/builtin-test.o
439BUILTIN_OBJS += $(OUTPUT)builtin-mem.o 443BUILTIN_OBJS += $(OUTPUT)builtin-mem.o
440 444
441PERFLIBS = $(LIB_FILE) $(LIBLK) $(LIBTRACEEVENT) 445PERFLIBS = $(LIB_FILE) $(LIBAPIKFS) $(LIBTRACEEVENT)
442 446
443# We choose to avoid "if .. else if .. else .. endif endif" 447# We choose to avoid "if .. else if .. else .. endif endif"
444# because maintaining the nesting to match is a pain. If 448# because maintaining the nesting to match is a pain. If
@@ -486,6 +490,7 @@ ifndef NO_SLANG
486 LIB_OBJS += $(OUTPUT)ui/browsers/hists.o 490 LIB_OBJS += $(OUTPUT)ui/browsers/hists.o
487 LIB_OBJS += $(OUTPUT)ui/browsers/map.o 491 LIB_OBJS += $(OUTPUT)ui/browsers/map.o
488 LIB_OBJS += $(OUTPUT)ui/browsers/scripts.o 492 LIB_OBJS += $(OUTPUT)ui/browsers/scripts.o
493 LIB_OBJS += $(OUTPUT)ui/browsers/header.o
489 LIB_OBJS += $(OUTPUT)ui/tui/setup.o 494 LIB_OBJS += $(OUTPUT)ui/tui/setup.o
490 LIB_OBJS += $(OUTPUT)ui/tui/util.o 495 LIB_OBJS += $(OUTPUT)ui/tui/util.o
491 LIB_OBJS += $(OUTPUT)ui/tui/helpline.o 496 LIB_OBJS += $(OUTPUT)ui/tui/helpline.o
@@ -671,6 +676,9 @@ $(OUTPUT)ui/browsers/map.o: ui/browsers/map.c $(OUTPUT)PERF-CFLAGS
671$(OUTPUT)ui/browsers/scripts.o: ui/browsers/scripts.c $(OUTPUT)PERF-CFLAGS 676$(OUTPUT)ui/browsers/scripts.o: ui/browsers/scripts.c $(OUTPUT)PERF-CFLAGS
672 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $< 677 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $<
673 678
679$(OUTPUT)util/kallsyms.o: ../lib/symbol/kallsyms.c $(OUTPUT)PERF-CFLAGS
680 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $<
681
674$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS 682$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS
675 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< 683 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
676 684
@@ -710,26 +718,33 @@ $(LIB_FILE): $(LIB_OBJS)
710# libtraceevent.a 718# libtraceevent.a
711TE_SOURCES = $(wildcard $(TRACE_EVENT_DIR)*.[ch]) 719TE_SOURCES = $(wildcard $(TRACE_EVENT_DIR)*.[ch])
712 720
713$(LIBTRACEEVENT): $(TE_SOURCES) 721LIBTRACEEVENT_FLAGS = $(QUIET_SUBDIR1) O=$(OUTPUT)
714 $(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(QUIET_SUBDIR1) O=$(OUTPUT) CFLAGS="-g -Wall $(EXTRA_CFLAGS)" libtraceevent.a 722LIBTRACEEVENT_FLAGS += CFLAGS="-g -Wall $(EXTRA_CFLAGS)"
723LIBTRACEEVENT_FLAGS += plugin_dir=$(plugindir_SQ)
724
725$(LIBTRACEEVENT): $(TE_SOURCES) $(OUTPUT)PERF-CFLAGS
726 $(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) libtraceevent.a plugins
715 727
716$(LIBTRACEEVENT)-clean: 728$(LIBTRACEEVENT)-clean:
717 $(call QUIET_CLEAN, libtraceevent) 729 $(call QUIET_CLEAN, libtraceevent)
718 @$(MAKE) -C $(TRACE_EVENT_DIR) O=$(OUTPUT) clean >/dev/null 730 @$(MAKE) -C $(TRACE_EVENT_DIR) O=$(OUTPUT) clean >/dev/null
719 731
720LIBLK_SOURCES = $(wildcard $(LK_PATH)*.[ch]) 732install-traceevent-plugins: $(LIBTRACEEVENT)
733 $(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) install_plugins
734
735LIBAPIKFS_SOURCES = $(wildcard $(LIB_PATH)fs/*.[ch])
721 736
722# if subdir is set, we've been called from above so target has been built 737# if subdir is set, we've been called from above so target has been built
723# already 738# already
724$(LIBLK): $(LIBLK_SOURCES) 739$(LIBAPIKFS): $(LIBAPIKFS_SOURCES)
725ifeq ($(subdir),) 740ifeq ($(subdir),)
726 $(QUIET_SUBDIR0)$(LK_DIR) $(QUIET_SUBDIR1) O=$(OUTPUT) liblk.a 741 $(QUIET_SUBDIR0)$(LIB_DIR) $(QUIET_SUBDIR1) O=$(OUTPUT) libapikfs.a
727endif 742endif
728 743
729$(LIBLK)-clean: 744$(LIBAPIKFS)-clean:
730ifeq ($(subdir),) 745ifeq ($(subdir),)
731 $(call QUIET_CLEAN, liblk) 746 $(call QUIET_CLEAN, libapikfs)
732 @$(MAKE) -C $(LK_DIR) O=$(OUTPUT) clean >/dev/null 747 @$(MAKE) -C $(LIB_DIR) O=$(OUTPUT) clean >/dev/null
733endif 748endif
734 749
735help: 750help:
@@ -785,7 +800,7 @@ cscope:
785 800
786### Detect prefix changes 801### Detect prefix changes
787TRACK_CFLAGS = $(subst ','\'',$(CFLAGS)):\ 802TRACK_CFLAGS = $(subst ','\'',$(CFLAGS)):\
788 $(bindir_SQ):$(perfexecdir_SQ):$(template_dir_SQ):$(prefix_SQ) 803 $(bindir_SQ):$(perfexecdir_SQ):$(template_dir_SQ):$(prefix_SQ):$(plugindir_SQ)
789 804
790$(OUTPUT)PERF-CFLAGS: .FORCE-PERF-CFLAGS 805$(OUTPUT)PERF-CFLAGS: .FORCE-PERF-CFLAGS
791 @FLAGS='$(TRACK_CFLAGS)'; \ 806 @FLAGS='$(TRACK_CFLAGS)'; \
@@ -840,16 +855,16 @@ ifndef NO_LIBPYTHON
840 $(INSTALL) scripts/python/*.py -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python'; \ 855 $(INSTALL) scripts/python/*.py -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python'; \
841 $(INSTALL) scripts/python/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin' 856 $(INSTALL) scripts/python/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin'
842endif 857endif
843 $(call QUIET_INSTALL, bash_completion-script) \ 858 $(call QUIET_INSTALL, perf_completion-script) \
844 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d'; \ 859 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d'; \
845 $(INSTALL) bash_completion '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d/perf' 860 $(INSTALL) perf-completion.sh '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d/perf'
846 $(call QUIET_INSTALL, tests) \ 861 $(call QUIET_INSTALL, tests) \
847 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'; \ 862 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'; \
848 $(INSTALL) tests/attr.py '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'; \ 863 $(INSTALL) tests/attr.py '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'; \
849 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'; \ 864 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'; \
850 $(INSTALL) tests/attr/* '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr' 865 $(INSTALL) tests/attr/* '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'
851 866
852install: install-bin try-install-man 867install: install-bin try-install-man install-traceevent-plugins
853 868
854install-python_ext: 869install-python_ext:
855 $(PYTHON_WORD) util/setup.py --quiet install --root='/$(DESTDIR_SQ)' 870 $(PYTHON_WORD) util/setup.py --quiet install --root='/$(DESTDIR_SQ)'
@@ -868,12 +883,11 @@ config-clean:
868 $(call QUIET_CLEAN, config) 883 $(call QUIET_CLEAN, config)
869 @$(MAKE) -C config/feature-checks clean >/dev/null 884 @$(MAKE) -C config/feature-checks clean >/dev/null
870 885
871clean: $(LIBTRACEEVENT)-clean $(LIBLK)-clean config-clean 886clean: $(LIBTRACEEVENT)-clean $(LIBAPIKFS)-clean config-clean
872 $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf.o $(LANG_BINDINGS) $(GTK_OBJS) 887 $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf.o $(LANG_BINDINGS) $(GTK_OBJS)
873 $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf 888 $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf
874 $(call QUIET_CLEAN, core-gen) $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex* 889 $(call QUIET_CLEAN, core-gen) $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex*
875 $(call QUIET_CLEAN, Documentation) 890 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean
876 @$(MAKE) -C Documentation O=$(OUTPUT) clean >/dev/null
877 $(python-clean) 891 $(python-clean)
878 892
879# 893#
diff --git a/tools/perf/arch/common.c b/tools/perf/arch/common.c
index aacef07ebf31..42faf369211c 100644
--- a/tools/perf/arch/common.c
+++ b/tools/perf/arch/common.c
@@ -154,8 +154,7 @@ static int perf_session_env__lookup_binutils_path(struct perf_session_env *env,
154 } 154 }
155 if (lookup_path(buf)) 155 if (lookup_path(buf))
156 goto out; 156 goto out;
157 free(buf); 157 zfree(&buf);
158 buf = NULL;
159 } 158 }
160 159
161 if (!strcmp(arch, "arm")) 160 if (!strcmp(arch, "arm"))
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 4087ab19823c..0da603b79b61 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -69,15 +69,7 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,
69 if (he == NULL) 69 if (he == NULL)
70 return -ENOMEM; 70 return -ENOMEM;
71 71
72 ret = 0; 72 ret = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
73 if (he->ms.sym != NULL) {
74 struct annotation *notes = symbol__annotation(he->ms.sym);
75 if (notes->src == NULL && symbol__alloc_hist(he->ms.sym) < 0)
76 return -ENOMEM;
77
78 ret = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
79 }
80
81 evsel->hists.stats.total_period += sample->period; 73 evsel->hists.stats.total_period += sample->period;
82 hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); 74 hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
83 return ret; 75 return ret;
@@ -188,8 +180,7 @@ find_next:
188 * symbol, free he->ms.sym->src to signal we already 180 * symbol, free he->ms.sym->src to signal we already
189 * processed this symbol. 181 * processed this symbol.
190 */ 182 */
191 free(notes->src); 183 zfree(&notes->src);
192 notes->src = NULL;
193 } 184 }
194 } 185 }
195} 186}
@@ -241,7 +232,7 @@ static int __cmd_annotate(struct perf_annotate *ann)
241 perf_session__fprintf_dsos(session, stdout); 232 perf_session__fprintf_dsos(session, stdout);
242 233
243 total_nr_samples = 0; 234 total_nr_samples = 0;
244 list_for_each_entry(pos, &session->evlist->entries, node) { 235 evlist__for_each(session->evlist, pos) {
245 struct hists *hists = &pos->hists; 236 struct hists *hists = &pos->hists;
246 u32 nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE]; 237 u32 nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE];
247 238
@@ -373,7 +364,7 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
373 364
374 if (argc) { 365 if (argc) {
375 /* 366 /*
376 * Special case: if there's an argument left then assume tha 367 * Special case: if there's an argument left then assume that
377 * it's a symbol filter: 368 * it's a symbol filter:
378 */ 369 */
379 if (argc > 1) 370 if (argc > 1)
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 3b67ea2444bd..a77e31246c00 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -356,9 +356,10 @@ static struct perf_evsel *evsel_match(struct perf_evsel *evsel,
356{ 356{
357 struct perf_evsel *e; 357 struct perf_evsel *e;
358 358
359 list_for_each_entry(e, &evlist->entries, node) 359 evlist__for_each(evlist, e) {
360 if (perf_evsel__match2(evsel, e)) 360 if (perf_evsel__match2(evsel, e))
361 return e; 361 return e;
362 }
362 363
363 return NULL; 364 return NULL;
364} 365}
@@ -367,7 +368,7 @@ static void perf_evlist__collapse_resort(struct perf_evlist *evlist)
367{ 368{
368 struct perf_evsel *evsel; 369 struct perf_evsel *evsel;
369 370
370 list_for_each_entry(evsel, &evlist->entries, node) { 371 evlist__for_each(evlist, evsel) {
371 struct hists *hists = &evsel->hists; 372 struct hists *hists = &evsel->hists;
372 373
373 hists__collapse_resort(hists, NULL); 374 hists__collapse_resort(hists, NULL);
@@ -614,7 +615,7 @@ static void data_process(void)
614 struct perf_evsel *evsel_base; 615 struct perf_evsel *evsel_base;
615 bool first = true; 616 bool first = true;
616 617
617 list_for_each_entry(evsel_base, &evlist_base->entries, node) { 618 evlist__for_each(evlist_base, evsel_base) {
618 struct data__file *d; 619 struct data__file *d;
619 int i; 620 int i;
620 621
@@ -654,7 +655,7 @@ static void data__free(struct data__file *d)
654 for (col = 0; col < PERF_HPP_DIFF__MAX_INDEX; col++) { 655 for (col = 0; col < PERF_HPP_DIFF__MAX_INDEX; col++) {
655 struct diff_hpp_fmt *fmt = &d->fmt[col]; 656 struct diff_hpp_fmt *fmt = &d->fmt[col];
656 657
657 free(fmt->header); 658 zfree(&fmt->header);
658 } 659 }
659} 660}
660 661
@@ -769,6 +770,81 @@ static int hpp__entry_baseline(struct hist_entry *he, char *buf, size_t size)
769 return ret; 770 return ret;
770} 771}
771 772
773static int __hpp__color_compare(struct perf_hpp_fmt *fmt,
774 struct perf_hpp *hpp, struct hist_entry *he,
775 int comparison_method)
776{
777 struct diff_hpp_fmt *dfmt =
778 container_of(fmt, struct diff_hpp_fmt, fmt);
779 struct hist_entry *pair = get_pair_fmt(he, dfmt);
780 double diff;
781 s64 wdiff;
782 char pfmt[20] = " ";
783
784 if (!pair)
785 goto dummy_print;
786
787 switch (comparison_method) {
788 case COMPUTE_DELTA:
789 if (pair->diff.computed)
790 diff = pair->diff.period_ratio_delta;
791 else
792 diff = compute_delta(he, pair);
793
794 if (fabs(diff) < 0.01)
795 goto dummy_print;
796 scnprintf(pfmt, 20, "%%%+d.2f%%%%", dfmt->header_width - 1);
797 return percent_color_snprintf(hpp->buf, hpp->size,
798 pfmt, diff);
799 case COMPUTE_RATIO:
800 if (he->dummy)
801 goto dummy_print;
802 if (pair->diff.computed)
803 diff = pair->diff.period_ratio;
804 else
805 diff = compute_ratio(he, pair);
806
807 scnprintf(pfmt, 20, "%%%d.6f", dfmt->header_width);
808 return value_color_snprintf(hpp->buf, hpp->size,
809 pfmt, diff);
810 case COMPUTE_WEIGHTED_DIFF:
811 if (he->dummy)
812 goto dummy_print;
813 if (pair->diff.computed)
814 wdiff = pair->diff.wdiff;
815 else
816 wdiff = compute_wdiff(he, pair);
817
818 scnprintf(pfmt, 20, "%%14ld", dfmt->header_width);
819 return color_snprintf(hpp->buf, hpp->size,
820 get_percent_color(wdiff),
821 pfmt, wdiff);
822 default:
823 BUG_ON(1);
824 }
825dummy_print:
826 return scnprintf(hpp->buf, hpp->size, "%*s",
827 dfmt->header_width, pfmt);
828}
829
830static int hpp__color_delta(struct perf_hpp_fmt *fmt,
831 struct perf_hpp *hpp, struct hist_entry *he)
832{
833 return __hpp__color_compare(fmt, hpp, he, COMPUTE_DELTA);
834}
835
836static int hpp__color_ratio(struct perf_hpp_fmt *fmt,
837 struct perf_hpp *hpp, struct hist_entry *he)
838{
839 return __hpp__color_compare(fmt, hpp, he, COMPUTE_RATIO);
840}
841
842static int hpp__color_wdiff(struct perf_hpp_fmt *fmt,
843 struct perf_hpp *hpp, struct hist_entry *he)
844{
845 return __hpp__color_compare(fmt, hpp, he, COMPUTE_WEIGHTED_DIFF);
846}
847
772static void 848static void
773hpp__entry_unpair(struct hist_entry *he, int idx, char *buf, size_t size) 849hpp__entry_unpair(struct hist_entry *he, int idx, char *buf, size_t size)
774{ 850{
@@ -940,8 +1016,22 @@ static void data__hpp_register(struct data__file *d, int idx)
940 fmt->entry = hpp__entry_global; 1016 fmt->entry = hpp__entry_global;
941 1017
942 /* TODO more colors */ 1018 /* TODO more colors */
943 if (idx == PERF_HPP_DIFF__BASELINE) 1019 switch (idx) {
1020 case PERF_HPP_DIFF__BASELINE:
944 fmt->color = hpp__color_baseline; 1021 fmt->color = hpp__color_baseline;
1022 break;
1023 case PERF_HPP_DIFF__DELTA:
1024 fmt->color = hpp__color_delta;
1025 break;
1026 case PERF_HPP_DIFF__RATIO:
1027 fmt->color = hpp__color_ratio;
1028 break;
1029 case PERF_HPP_DIFF__WEIGHTED_DIFF:
1030 fmt->color = hpp__color_wdiff;
1031 break;
1032 default:
1033 break;
1034 }
945 1035
946 init_header(d, dfmt); 1036 init_header(d, dfmt);
947 perf_hpp__column_register(fmt); 1037 perf_hpp__column_register(fmt);
@@ -1000,8 +1090,7 @@ static int data_init(int argc, const char **argv)
1000 data__files_cnt = argc; 1090 data__files_cnt = argc;
1001 use_default = false; 1091 use_default = false;
1002 } 1092 }
1003 } else if (symbol_conf.default_guest_vmlinux_name || 1093 } else if (perf_guest) {
1004 symbol_conf.default_guest_kallsyms) {
1005 defaults[0] = "perf.data.host"; 1094 defaults[0] = "perf.data.host";
1006 defaults[1] = "perf.data.guest"; 1095 defaults[1] = "perf.data.guest";
1007 } 1096 }
diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c
index 20b0f12763b0..c99e0de7e54a 100644
--- a/tools/perf/builtin-evlist.c
+++ b/tools/perf/builtin-evlist.c
@@ -29,7 +29,7 @@ static int __cmd_evlist(const char *file_name, struct perf_attr_details *details
29 if (session == NULL) 29 if (session == NULL)
30 return -ENOMEM; 30 return -ENOMEM;
31 31
32 list_for_each_entry(pos, &session->evlist->entries, node) 32 evlist__for_each(session->evlist, pos)
33 perf_evsel__fprintf(pos, details, stdout); 33 perf_evsel__fprintf(pos, details, stdout);
34 34
35 perf_session__delete(session); 35 perf_session__delete(session);
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 6a2508589460..b3466018bbd7 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -22,14 +22,13 @@
22#include <linux/list.h> 22#include <linux/list.h>
23 23
24struct perf_inject { 24struct perf_inject {
25 struct perf_tool tool; 25 struct perf_tool tool;
26 bool build_ids; 26 bool build_ids;
27 bool sched_stat; 27 bool sched_stat;
28 const char *input_name; 28 const char *input_name;
29 int pipe_output, 29 struct perf_data_file output;
30 output; 30 u64 bytes_written;
31 u64 bytes_written; 31 struct list_head samples;
32 struct list_head samples;
33}; 32};
34 33
35struct event_entry { 34struct event_entry {
@@ -42,21 +41,14 @@ static int perf_event__repipe_synth(struct perf_tool *tool,
42 union perf_event *event) 41 union perf_event *event)
43{ 42{
44 struct perf_inject *inject = container_of(tool, struct perf_inject, tool); 43 struct perf_inject *inject = container_of(tool, struct perf_inject, tool);
45 uint32_t size; 44 ssize_t size;
46 void *buf = event;
47 45
48 size = event->header.size; 46 size = perf_data_file__write(&inject->output, event,
49 47 event->header.size);
50 while (size) { 48 if (size < 0)
51 int ret = write(inject->output, buf, size); 49 return -errno;
52 if (ret < 0)
53 return -errno;
54
55 size -= ret;
56 buf += ret;
57 inject->bytes_written += ret;
58 }
59 50
51 inject->bytes_written += size;
60 return 0; 52 return 0;
61} 53}
62 54
@@ -80,7 +72,7 @@ static int perf_event__repipe_attr(struct perf_tool *tool,
80 if (ret) 72 if (ret)
81 return ret; 73 return ret;
82 74
83 if (!inject->pipe_output) 75 if (&inject->output.is_pipe)
84 return 0; 76 return 0;
85 77
86 return perf_event__repipe_synth(tool, event); 78 return perf_event__repipe_synth(tool, event);
@@ -355,6 +347,7 @@ static int __cmd_inject(struct perf_inject *inject)
355 .path = inject->input_name, 347 .path = inject->input_name,
356 .mode = PERF_DATA_MODE_READ, 348 .mode = PERF_DATA_MODE_READ,
357 }; 349 };
350 struct perf_data_file *file_out = &inject->output;
358 351
359 signal(SIGINT, sig_handler); 352 signal(SIGINT, sig_handler);
360 353
@@ -376,7 +369,7 @@ static int __cmd_inject(struct perf_inject *inject)
376 369
377 inject->tool.ordered_samples = true; 370 inject->tool.ordered_samples = true;
378 371
379 list_for_each_entry(evsel, &session->evlist->entries, node) { 372 evlist__for_each(session->evlist, evsel) {
380 const char *name = perf_evsel__name(evsel); 373 const char *name = perf_evsel__name(evsel);
381 374
382 if (!strcmp(name, "sched:sched_switch")) { 375 if (!strcmp(name, "sched:sched_switch")) {
@@ -391,14 +384,14 @@ static int __cmd_inject(struct perf_inject *inject)
391 } 384 }
392 } 385 }
393 386
394 if (!inject->pipe_output) 387 if (!file_out->is_pipe)
395 lseek(inject->output, session->header.data_offset, SEEK_SET); 388 lseek(file_out->fd, session->header.data_offset, SEEK_SET);
396 389
397 ret = perf_session__process_events(session, &inject->tool); 390 ret = perf_session__process_events(session, &inject->tool);
398 391
399 if (!inject->pipe_output) { 392 if (!file_out->is_pipe) {
400 session->header.data_size = inject->bytes_written; 393 session->header.data_size = inject->bytes_written;
401 perf_session__write_header(session, session->evlist, inject->output, true); 394 perf_session__write_header(session, session->evlist, file_out->fd, true);
402 } 395 }
403 396
404 perf_session__delete(session); 397 perf_session__delete(session);
@@ -427,14 +420,17 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
427 }, 420 },
428 .input_name = "-", 421 .input_name = "-",
429 .samples = LIST_HEAD_INIT(inject.samples), 422 .samples = LIST_HEAD_INIT(inject.samples),
423 .output = {
424 .path = "-",
425 .mode = PERF_DATA_MODE_WRITE,
426 },
430 }; 427 };
431 const char *output_name = "-";
432 const struct option options[] = { 428 const struct option options[] = {
433 OPT_BOOLEAN('b', "build-ids", &inject.build_ids, 429 OPT_BOOLEAN('b', "build-ids", &inject.build_ids,
434 "Inject build-ids into the output stream"), 430 "Inject build-ids into the output stream"),
435 OPT_STRING('i', "input", &inject.input_name, "file", 431 OPT_STRING('i', "input", &inject.input_name, "file",
436 "input file name"), 432 "input file name"),
437 OPT_STRING('o', "output", &output_name, "file", 433 OPT_STRING('o', "output", &inject.output.path, "file",
438 "output file name"), 434 "output file name"),
439 OPT_BOOLEAN('s', "sched-stat", &inject.sched_stat, 435 OPT_BOOLEAN('s', "sched-stat", &inject.sched_stat,
440 "Merge sched-stat and sched-switch for getting events " 436 "Merge sched-stat and sched-switch for getting events "
@@ -456,16 +452,9 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
456 if (argc) 452 if (argc)
457 usage_with_options(inject_usage, options); 453 usage_with_options(inject_usage, options);
458 454
459 if (!strcmp(output_name, "-")) { 455 if (perf_data_file__open(&inject.output)) {
460 inject.pipe_output = 1; 456 perror("failed to create output file");
461 inject.output = STDOUT_FILENO; 457 return -1;
462 } else {
463 inject.output = open(output_name, O_CREAT | O_WRONLY | O_TRUNC,
464 S_IRUSR | S_IWUSR);
465 if (inject.output < 0) {
466 perror("failed to create output file");
467 return -1;
468 }
469 } 458 }
470 459
471 if (symbol__init() < 0) 460 if (symbol__init() < 0)
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index f8bf5f244d77..a7350519c63f 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -13,7 +13,7 @@
13#include "util/parse-options.h" 13#include "util/parse-options.h"
14#include "util/trace-event.h" 14#include "util/trace-event.h"
15#include "util/debug.h" 15#include "util/debug.h"
16#include <lk/debugfs.h> 16#include <api/fs/debugfs.h>
17#include "util/tool.h" 17#include "util/tool.h"
18#include "util/stat.h" 18#include "util/stat.h"
19#include "util/top.h" 19#include "util/top.h"
@@ -89,7 +89,7 @@ struct exit_reasons_table {
89 89
90struct perf_kvm_stat { 90struct perf_kvm_stat {
91 struct perf_tool tool; 91 struct perf_tool tool;
92 struct perf_record_opts opts; 92 struct record_opts opts;
93 struct perf_evlist *evlist; 93 struct perf_evlist *evlist;
94 struct perf_session *session; 94 struct perf_session *session;
95 95
@@ -1158,9 +1158,7 @@ out:
1158 if (kvm->timerfd >= 0) 1158 if (kvm->timerfd >= 0)
1159 close(kvm->timerfd); 1159 close(kvm->timerfd);
1160 1160
1161 if (pollfds) 1161 free(pollfds);
1162 free(pollfds);
1163
1164 return err; 1162 return err;
1165} 1163}
1166 1164
@@ -1176,7 +1174,7 @@ static int kvm_live_open_events(struct perf_kvm_stat *kvm)
1176 * Note: exclude_{guest,host} do not apply here. 1174 * Note: exclude_{guest,host} do not apply here.
1177 * This command processes KVM tracepoints from host only 1175 * This command processes KVM tracepoints from host only
1178 */ 1176 */
1179 list_for_each_entry(pos, &evlist->entries, node) { 1177 evlist__for_each(evlist, pos) {
1180 struct perf_event_attr *attr = &pos->attr; 1178 struct perf_event_attr *attr = &pos->attr;
1181 1179
1182 /* make sure these *are* set */ 1180 /* make sure these *are* set */
@@ -1232,7 +1230,7 @@ static int read_events(struct perf_kvm_stat *kvm)
1232 .ordered_samples = true, 1230 .ordered_samples = true,
1233 }; 1231 };
1234 struct perf_data_file file = { 1232 struct perf_data_file file = {
1235 .path = input_name, 1233 .path = kvm->file_name,
1236 .mode = PERF_DATA_MODE_READ, 1234 .mode = PERF_DATA_MODE_READ,
1237 }; 1235 };
1238 1236
@@ -1558,10 +1556,8 @@ out:
1558 if (kvm->session) 1556 if (kvm->session)
1559 perf_session__delete(kvm->session); 1557 perf_session__delete(kvm->session);
1560 kvm->session = NULL; 1558 kvm->session = NULL;
1561 if (kvm->evlist) { 1559 if (kvm->evlist)
1562 perf_evlist__delete_maps(kvm->evlist);
1563 perf_evlist__delete(kvm->evlist); 1560 perf_evlist__delete(kvm->evlist);
1564 }
1565 1561
1566 return err; 1562 return err;
1567} 1563}
@@ -1690,6 +1686,8 @@ int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused)
1690 "file", "file saving guest os /proc/kallsyms"), 1686 "file", "file saving guest os /proc/kallsyms"),
1691 OPT_STRING(0, "guestmodules", &symbol_conf.default_guest_modules, 1687 OPT_STRING(0, "guestmodules", &symbol_conf.default_guest_modules,
1692 "file", "file saving guest os /proc/modules"), 1688 "file", "file saving guest os /proc/modules"),
1689 OPT_INCR('v', "verbose", &verbose,
1690 "be more verbose (show counter open errors, etc)"),
1693 OPT_END() 1691 OPT_END()
1694 }; 1692 };
1695 1693
@@ -1711,12 +1709,7 @@ int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused)
1711 perf_guest = 1; 1709 perf_guest = 1;
1712 1710
1713 if (!file_name) { 1711 if (!file_name) {
1714 if (perf_host && !perf_guest) 1712 file_name = get_filename_for_perf_kvm();
1715 file_name = strdup("perf.data.host");
1716 else if (!perf_host && perf_guest)
1717 file_name = strdup("perf.data.guest");
1718 else
1719 file_name = strdup("perf.data.kvm");
1720 1713
1721 if (!file_name) { 1714 if (!file_name) {
1722 pr_err("Failed to allocate memory for filename\n"); 1715 pr_err("Failed to allocate memory for filename\n");
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
index 31c00f186da1..2e3ade69a58e 100644
--- a/tools/perf/builtin-mem.c
+++ b/tools/perf/builtin-mem.c
@@ -62,7 +62,6 @@ static int
62dump_raw_samples(struct perf_tool *tool, 62dump_raw_samples(struct perf_tool *tool,
63 union perf_event *event, 63 union perf_event *event,
64 struct perf_sample *sample, 64 struct perf_sample *sample,
65 struct perf_evsel *evsel __maybe_unused,
66 struct machine *machine) 65 struct machine *machine)
67{ 66{
68 struct perf_mem *mem = container_of(tool, struct perf_mem, tool); 67 struct perf_mem *mem = container_of(tool, struct perf_mem, tool);
@@ -112,10 +111,10 @@ dump_raw_samples(struct perf_tool *tool,
112static int process_sample_event(struct perf_tool *tool, 111static int process_sample_event(struct perf_tool *tool,
113 union perf_event *event, 112 union perf_event *event,
114 struct perf_sample *sample, 113 struct perf_sample *sample,
115 struct perf_evsel *evsel, 114 struct perf_evsel *evsel __maybe_unused,
116 struct machine *machine) 115 struct machine *machine)
117{ 116{
118 return dump_raw_samples(tool, event, sample, evsel, machine); 117 return dump_raw_samples(tool, event, sample, machine);
119} 118}
120 119
121static int report_raw_events(struct perf_mem *mem) 120static int report_raw_events(struct perf_mem *mem)
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 6ea9e85bdc00..78948882e3de 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -37,7 +37,7 @@
37#include "util/strfilter.h" 37#include "util/strfilter.h"
38#include "util/symbol.h" 38#include "util/symbol.h"
39#include "util/debug.h" 39#include "util/debug.h"
40#include <lk/debugfs.h> 40#include <api/fs/debugfs.h>
41#include "util/parse-options.h" 41#include "util/parse-options.h"
42#include "util/probe-finder.h" 42#include "util/probe-finder.h"
43#include "util/probe-event.h" 43#include "util/probe-event.h"
@@ -59,7 +59,7 @@ static struct {
59 struct perf_probe_event events[MAX_PROBES]; 59 struct perf_probe_event events[MAX_PROBES];
60 struct strlist *dellist; 60 struct strlist *dellist;
61 struct line_range line_range; 61 struct line_range line_range;
62 const char *target; 62 char *target;
63 int max_probe_points; 63 int max_probe_points;
64 struct strfilter *filter; 64 struct strfilter *filter;
65} params; 65} params;
@@ -98,7 +98,10 @@ static int set_target(const char *ptr)
98 * short module name. 98 * short module name.
99 */ 99 */
100 if (!params.target && ptr && *ptr == '/') { 100 if (!params.target && ptr && *ptr == '/') {
101 params.target = ptr; 101 params.target = strdup(ptr);
102 if (!params.target)
103 return -ENOMEM;
104
102 found = 1; 105 found = 1;
103 buf = ptr + (strlen(ptr) - 3); 106 buf = ptr + (strlen(ptr) - 3);
104 107
@@ -116,6 +119,9 @@ static int parse_probe_event_argv(int argc, const char **argv)
116 char *buf; 119 char *buf;
117 120
118 found_target = set_target(argv[0]); 121 found_target = set_target(argv[0]);
122 if (found_target < 0)
123 return found_target;
124
119 if (found_target && argc == 1) 125 if (found_target && argc == 1)
120 return 0; 126 return 0;
121 127
@@ -169,6 +175,7 @@ static int opt_set_target(const struct option *opt, const char *str,
169 int unset __maybe_unused) 175 int unset __maybe_unused)
170{ 176{
171 int ret = -ENOENT; 177 int ret = -ENOENT;
178 char *tmp;
172 179
173 if (str && !params.target) { 180 if (str && !params.target) {
174 if (!strcmp(opt->long_name, "exec")) 181 if (!strcmp(opt->long_name, "exec"))
@@ -180,7 +187,19 @@ static int opt_set_target(const struct option *opt, const char *str,
180 else 187 else
181 return ret; 188 return ret;
182 189
183 params.target = str; 190 /* Expand given path to absolute path, except for modulename */
191 if (params.uprobes || strchr(str, '/')) {
192 tmp = realpath(str, NULL);
193 if (!tmp) {
194 pr_warning("Failed to get the absolute path of %s: %m\n", str);
195 return ret;
196 }
197 } else {
198 tmp = strdup(str);
199 if (!tmp)
200 return -ENOMEM;
201 }
202 params.target = tmp;
184 ret = 0; 203 ret = 0;
185 } 204 }
186 205
@@ -204,7 +223,6 @@ static int opt_show_lines(const struct option *opt __maybe_unused,
204 223
205 params.show_lines = true; 224 params.show_lines = true;
206 ret = parse_line_range_desc(str, &params.line_range); 225 ret = parse_line_range_desc(str, &params.line_range);
207 INIT_LIST_HEAD(&params.line_range.line_list);
208 226
209 return ret; 227 return ret;
210} 228}
@@ -250,7 +268,28 @@ static int opt_set_filter(const struct option *opt __maybe_unused,
250 return 0; 268 return 0;
251} 269}
252 270
253int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) 271static void init_params(void)
272{
273 line_range__init(&params.line_range);
274}
275
276static void cleanup_params(void)
277{
278 int i;
279
280 for (i = 0; i < params.nevents; i++)
281 clear_perf_probe_event(params.events + i);
282 if (params.dellist)
283 strlist__delete(params.dellist);
284 line_range__clear(&params.line_range);
285 free(params.target);
286 if (params.filter)
287 strfilter__delete(params.filter);
288 memset(&params, 0, sizeof(params));
289}
290
291static int
292__cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
254{ 293{
255 const char * const probe_usage[] = { 294 const char * const probe_usage[] = {
256 "perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]", 295 "perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]",
@@ -404,6 +443,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
404 ret = show_available_funcs(params.target, params.filter, 443 ret = show_available_funcs(params.target, params.filter,
405 params.uprobes); 444 params.uprobes);
406 strfilter__delete(params.filter); 445 strfilter__delete(params.filter);
446 params.filter = NULL;
407 if (ret < 0) 447 if (ret < 0)
408 pr_err(" Error: Failed to show functions." 448 pr_err(" Error: Failed to show functions."
409 " (%d)\n", ret); 449 " (%d)\n", ret);
@@ -411,7 +451,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
411 } 451 }
412 452
413#ifdef HAVE_DWARF_SUPPORT 453#ifdef HAVE_DWARF_SUPPORT
414 if (params.show_lines && !params.uprobes) { 454 if (params.show_lines) {
415 if (params.mod_events) { 455 if (params.mod_events) {
416 pr_err(" Error: Don't use --line with" 456 pr_err(" Error: Don't use --line with"
417 " --add/--del.\n"); 457 " --add/--del.\n");
@@ -443,6 +483,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
443 params.filter, 483 params.filter,
444 params.show_ext_vars); 484 params.show_ext_vars);
445 strfilter__delete(params.filter); 485 strfilter__delete(params.filter);
486 params.filter = NULL;
446 if (ret < 0) 487 if (ret < 0)
447 pr_err(" Error: Failed to show vars. (%d)\n", ret); 488 pr_err(" Error: Failed to show vars. (%d)\n", ret);
448 return ret; 489 return ret;
@@ -451,7 +492,6 @@ int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
451 492
452 if (params.dellist) { 493 if (params.dellist) {
453 ret = del_perf_probe_events(params.dellist); 494 ret = del_perf_probe_events(params.dellist);
454 strlist__delete(params.dellist);
455 if (ret < 0) { 495 if (ret < 0) {
456 pr_err(" Error: Failed to delete events. (%d)\n", ret); 496 pr_err(" Error: Failed to delete events. (%d)\n", ret);
457 return ret; 497 return ret;
@@ -470,3 +510,14 @@ int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
470 } 510 }
471 return 0; 511 return 0;
472} 512}
513
514int cmd_probe(int argc, const char **argv, const char *prefix)
515{
516 int ret;
517
518 init_params();
519 ret = __cmd_probe(argc, argv, prefix);
520 cleanup_params();
521
522 return ret;
523}
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 7c8020a32784..3c394bf16fa8 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -62,9 +62,9 @@ static void __handle_on_exit_funcs(void)
62} 62}
63#endif 63#endif
64 64
65struct perf_record { 65struct record {
66 struct perf_tool tool; 66 struct perf_tool tool;
67 struct perf_record_opts opts; 67 struct record_opts opts;
68 u64 bytes_written; 68 u64 bytes_written;
69 struct perf_data_file file; 69 struct perf_data_file file;
70 struct perf_evlist *evlist; 70 struct perf_evlist *evlist;
@@ -76,46 +76,27 @@ struct perf_record {
76 long samples; 76 long samples;
77}; 77};
78 78
79static int do_write_output(struct perf_record *rec, void *buf, size_t size) 79static int record__write(struct record *rec, void *bf, size_t size)
80{ 80{
81 struct perf_data_file *file = &rec->file; 81 if (perf_data_file__write(rec->session->file, bf, size) < 0) {
82 82 pr_err("failed to write perf data, error: %m\n");
83 while (size) { 83 return -1;
84 ssize_t ret = write(file->fd, buf, size);
85
86 if (ret < 0) {
87 pr_err("failed to write perf data, error: %m\n");
88 return -1;
89 }
90
91 size -= ret;
92 buf += ret;
93
94 rec->bytes_written += ret;
95 } 84 }
96 85
86 rec->bytes_written += size;
97 return 0; 87 return 0;
98} 88}
99 89
100static int write_output(struct perf_record *rec, void *buf, size_t size)
101{
102 return do_write_output(rec, buf, size);
103}
104
105static int process_synthesized_event(struct perf_tool *tool, 90static int process_synthesized_event(struct perf_tool *tool,
106 union perf_event *event, 91 union perf_event *event,
107 struct perf_sample *sample __maybe_unused, 92 struct perf_sample *sample __maybe_unused,
108 struct machine *machine __maybe_unused) 93 struct machine *machine __maybe_unused)
109{ 94{
110 struct perf_record *rec = container_of(tool, struct perf_record, tool); 95 struct record *rec = container_of(tool, struct record, tool);
111 if (write_output(rec, event, event->header.size) < 0) 96 return record__write(rec, event, event->header.size);
112 return -1;
113
114 return 0;
115} 97}
116 98
117static int perf_record__mmap_read(struct perf_record *rec, 99static int record__mmap_read(struct record *rec, struct perf_mmap *md)
118 struct perf_mmap *md)
119{ 100{
120 unsigned int head = perf_mmap__read_head(md); 101 unsigned int head = perf_mmap__read_head(md);
121 unsigned int old = md->prev; 102 unsigned int old = md->prev;
@@ -136,7 +117,7 @@ static int perf_record__mmap_read(struct perf_record *rec,
136 size = md->mask + 1 - (old & md->mask); 117 size = md->mask + 1 - (old & md->mask);
137 old += size; 118 old += size;
138 119
139 if (write_output(rec, buf, size) < 0) { 120 if (record__write(rec, buf, size) < 0) {
140 rc = -1; 121 rc = -1;
141 goto out; 122 goto out;
142 } 123 }
@@ -146,7 +127,7 @@ static int perf_record__mmap_read(struct perf_record *rec,
146 size = head - old; 127 size = head - old;
147 old += size; 128 old += size;
148 129
149 if (write_output(rec, buf, size) < 0) { 130 if (record__write(rec, buf, size) < 0) {
150 rc = -1; 131 rc = -1;
151 goto out; 132 goto out;
152 } 133 }
@@ -171,9 +152,9 @@ static void sig_handler(int sig)
171 signr = sig; 152 signr = sig;
172} 153}
173 154
174static void perf_record__sig_exit(int exit_status __maybe_unused, void *arg) 155static void record__sig_exit(int exit_status __maybe_unused, void *arg)
175{ 156{
176 struct perf_record *rec = arg; 157 struct record *rec = arg;
177 int status; 158 int status;
178 159
179 if (rec->evlist->workload.pid > 0) { 160 if (rec->evlist->workload.pid > 0) {
@@ -191,18 +172,18 @@ static void perf_record__sig_exit(int exit_status __maybe_unused, void *arg)
191 signal(signr, SIG_DFL); 172 signal(signr, SIG_DFL);
192} 173}
193 174
194static int perf_record__open(struct perf_record *rec) 175static int record__open(struct record *rec)
195{ 176{
196 char msg[512]; 177 char msg[512];
197 struct perf_evsel *pos; 178 struct perf_evsel *pos;
198 struct perf_evlist *evlist = rec->evlist; 179 struct perf_evlist *evlist = rec->evlist;
199 struct perf_session *session = rec->session; 180 struct perf_session *session = rec->session;
200 struct perf_record_opts *opts = &rec->opts; 181 struct record_opts *opts = &rec->opts;
201 int rc = 0; 182 int rc = 0;
202 183
203 perf_evlist__config(evlist, opts); 184 perf_evlist__config(evlist, opts);
204 185
205 list_for_each_entry(pos, &evlist->entries, node) { 186 evlist__for_each(evlist, pos) {
206try_again: 187try_again:
207 if (perf_evsel__open(pos, evlist->cpus, evlist->threads) < 0) { 188 if (perf_evsel__open(pos, evlist->cpus, evlist->threads) < 0) {
208 if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) { 189 if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) {
@@ -232,7 +213,7 @@ try_again:
232 "Consider increasing " 213 "Consider increasing "
233 "/proc/sys/kernel/perf_event_mlock_kb,\n" 214 "/proc/sys/kernel/perf_event_mlock_kb,\n"
234 "or try again with a smaller value of -m/--mmap_pages.\n" 215 "or try again with a smaller value of -m/--mmap_pages.\n"
235 "(current value: %d)\n", opts->mmap_pages); 216 "(current value: %u)\n", opts->mmap_pages);
236 rc = -errno; 217 rc = -errno;
237 } else { 218 } else {
238 pr_err("failed to mmap with %d (%s)\n", errno, strerror(errno)); 219 pr_err("failed to mmap with %d (%s)\n", errno, strerror(errno));
@@ -247,7 +228,7 @@ out:
247 return rc; 228 return rc;
248} 229}
249 230
250static int process_buildids(struct perf_record *rec) 231static int process_buildids(struct record *rec)
251{ 232{
252 struct perf_data_file *file = &rec->file; 233 struct perf_data_file *file = &rec->file;
253 struct perf_session *session = rec->session; 234 struct perf_session *session = rec->session;
@@ -262,9 +243,9 @@ static int process_buildids(struct perf_record *rec)
262 size, &build_id__mark_dso_hit_ops); 243 size, &build_id__mark_dso_hit_ops);
263} 244}
264 245
265static void perf_record__exit(int status, void *arg) 246static void record__exit(int status, void *arg)
266{ 247{
267 struct perf_record *rec = arg; 248 struct record *rec = arg;
268 struct perf_data_file *file = &rec->file; 249 struct perf_data_file *file = &rec->file;
269 250
270 if (status != 0) 251 if (status != 0)
@@ -320,14 +301,14 @@ static struct perf_event_header finished_round_event = {
320 .type = PERF_RECORD_FINISHED_ROUND, 301 .type = PERF_RECORD_FINISHED_ROUND,
321}; 302};
322 303
323static int perf_record__mmap_read_all(struct perf_record *rec) 304static int record__mmap_read_all(struct record *rec)
324{ 305{
325 int i; 306 int i;
326 int rc = 0; 307 int rc = 0;
327 308
328 for (i = 0; i < rec->evlist->nr_mmaps; i++) { 309 for (i = 0; i < rec->evlist->nr_mmaps; i++) {
329 if (rec->evlist->mmap[i].base) { 310 if (rec->evlist->mmap[i].base) {
330 if (perf_record__mmap_read(rec, &rec->evlist->mmap[i]) != 0) { 311 if (record__mmap_read(rec, &rec->evlist->mmap[i]) != 0) {
331 rc = -1; 312 rc = -1;
332 goto out; 313 goto out;
333 } 314 }
@@ -335,16 +316,14 @@ static int perf_record__mmap_read_all(struct perf_record *rec)
335 } 316 }
336 317
337 if (perf_header__has_feat(&rec->session->header, HEADER_TRACING_DATA)) 318 if (perf_header__has_feat(&rec->session->header, HEADER_TRACING_DATA))
338 rc = write_output(rec, &finished_round_event, 319 rc = record__write(rec, &finished_round_event, sizeof(finished_round_event));
339 sizeof(finished_round_event));
340 320
341out: 321out:
342 return rc; 322 return rc;
343} 323}
344 324
345static void perf_record__init_features(struct perf_record *rec) 325static void record__init_features(struct record *rec)
346{ 326{
347 struct perf_evlist *evsel_list = rec->evlist;
348 struct perf_session *session = rec->session; 327 struct perf_session *session = rec->session;
349 int feat; 328 int feat;
350 329
@@ -354,32 +333,46 @@ static void perf_record__init_features(struct perf_record *rec)
354 if (rec->no_buildid) 333 if (rec->no_buildid)
355 perf_header__clear_feat(&session->header, HEADER_BUILD_ID); 334 perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
356 335
357 if (!have_tracepoints(&evsel_list->entries)) 336 if (!have_tracepoints(&rec->evlist->entries))
358 perf_header__clear_feat(&session->header, HEADER_TRACING_DATA); 337 perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
359 338
360 if (!rec->opts.branch_stack) 339 if (!rec->opts.branch_stack)
361 perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); 340 perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
362} 341}
363 342
364static int __cmd_record(struct perf_record *rec, int argc, const char **argv) 343static volatile int workload_exec_errno;
344
345/*
346 * perf_evlist__prepare_workload will send a SIGUSR1
347 * if the fork fails, since we asked by setting its
348 * want_signal to true.
349 */
350static void workload_exec_failed_signal(int signo, siginfo_t *info,
351 void *ucontext __maybe_unused)
352{
353 workload_exec_errno = info->si_value.sival_int;
354 done = 1;
355 signr = signo;
356 child_finished = 1;
357}
358
359static int __cmd_record(struct record *rec, int argc, const char **argv)
365{ 360{
366 int err; 361 int err;
367 unsigned long waking = 0; 362 unsigned long waking = 0;
368 const bool forks = argc > 0; 363 const bool forks = argc > 0;
369 struct machine *machine; 364 struct machine *machine;
370 struct perf_tool *tool = &rec->tool; 365 struct perf_tool *tool = &rec->tool;
371 struct perf_record_opts *opts = &rec->opts; 366 struct record_opts *opts = &rec->opts;
372 struct perf_evlist *evsel_list = rec->evlist;
373 struct perf_data_file *file = &rec->file; 367 struct perf_data_file *file = &rec->file;
374 struct perf_session *session; 368 struct perf_session *session;
375 bool disabled = false; 369 bool disabled = false;
376 370
377 rec->progname = argv[0]; 371 rec->progname = argv[0];
378 372
379 on_exit(perf_record__sig_exit, rec); 373 on_exit(record__sig_exit, rec);
380 signal(SIGCHLD, sig_handler); 374 signal(SIGCHLD, sig_handler);
381 signal(SIGINT, sig_handler); 375 signal(SIGINT, sig_handler);
382 signal(SIGUSR1, sig_handler);
383 signal(SIGTERM, sig_handler); 376 signal(SIGTERM, sig_handler);
384 377
385 session = perf_session__new(file, false, NULL); 378 session = perf_session__new(file, false, NULL);
@@ -390,37 +383,37 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
390 383
391 rec->session = session; 384 rec->session = session;
392 385
393 perf_record__init_features(rec); 386 record__init_features(rec);
394 387
395 if (forks) { 388 if (forks) {
396 err = perf_evlist__prepare_workload(evsel_list, &opts->target, 389 err = perf_evlist__prepare_workload(rec->evlist, &opts->target,
397 argv, file->is_pipe, 390 argv, file->is_pipe,
398 true); 391 workload_exec_failed_signal);
399 if (err < 0) { 392 if (err < 0) {
400 pr_err("Couldn't run the workload!\n"); 393 pr_err("Couldn't run the workload!\n");
401 goto out_delete_session; 394 goto out_delete_session;
402 } 395 }
403 } 396 }
404 397
405 if (perf_record__open(rec) != 0) { 398 if (record__open(rec) != 0) {
406 err = -1; 399 err = -1;
407 goto out_delete_session; 400 goto out_delete_session;
408 } 401 }
409 402
410 if (!evsel_list->nr_groups) 403 if (!rec->evlist->nr_groups)
411 perf_header__clear_feat(&session->header, HEADER_GROUP_DESC); 404 perf_header__clear_feat(&session->header, HEADER_GROUP_DESC);
412 405
413 /* 406 /*
414 * perf_session__delete(session) will be called at perf_record__exit() 407 * perf_session__delete(session) will be called at record__exit()
415 */ 408 */
416 on_exit(perf_record__exit, rec); 409 on_exit(record__exit, rec);
417 410
418 if (file->is_pipe) { 411 if (file->is_pipe) {
419 err = perf_header__write_pipe(file->fd); 412 err = perf_header__write_pipe(file->fd);
420 if (err < 0) 413 if (err < 0)
421 goto out_delete_session; 414 goto out_delete_session;
422 } else { 415 } else {
423 err = perf_session__write_header(session, evsel_list, 416 err = perf_session__write_header(session, rec->evlist,
424 file->fd, false); 417 file->fd, false);
425 if (err < 0) 418 if (err < 0)
426 goto out_delete_session; 419 goto out_delete_session;
@@ -444,7 +437,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
444 goto out_delete_session; 437 goto out_delete_session;
445 } 438 }
446 439
447 if (have_tracepoints(&evsel_list->entries)) { 440 if (have_tracepoints(&rec->evlist->entries)) {
448 /* 441 /*
449 * FIXME err <= 0 here actually means that 442 * FIXME err <= 0 here actually means that
450 * there were no tracepoints so its not really 443 * there were no tracepoints so its not really
@@ -453,7 +446,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
453 * return this more properly and also 446 * return this more properly and also
454 * propagate errors that now are calling die() 447 * propagate errors that now are calling die()
455 */ 448 */
456 err = perf_event__synthesize_tracing_data(tool, file->fd, evsel_list, 449 err = perf_event__synthesize_tracing_data(tool, file->fd, rec->evlist,
457 process_synthesized_event); 450 process_synthesized_event);
458 if (err <= 0) { 451 if (err <= 0) {
459 pr_err("Couldn't record tracing data.\n"); 452 pr_err("Couldn't record tracing data.\n");
@@ -485,7 +478,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
485 perf_event__synthesize_guest_os, tool); 478 perf_event__synthesize_guest_os, tool);
486 } 479 }
487 480
488 err = __machine__synthesize_threads(machine, tool, &opts->target, evsel_list->threads, 481 err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads,
489 process_synthesized_event, opts->sample_address); 482 process_synthesized_event, opts->sample_address);
490 if (err != 0) 483 if (err != 0)
491 goto out_delete_session; 484 goto out_delete_session;
@@ -506,19 +499,24 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
506 * (apart from group members) have enable_on_exec=1 set, 499 * (apart from group members) have enable_on_exec=1 set,
507 * so don't spoil it by prematurely enabling them. 500 * so don't spoil it by prematurely enabling them.
508 */ 501 */
509 if (!target__none(&opts->target)) 502 if (!target__none(&opts->target) && !opts->initial_delay)
510 perf_evlist__enable(evsel_list); 503 perf_evlist__enable(rec->evlist);
511 504
512 /* 505 /*
513 * Let the child rip 506 * Let the child rip
514 */ 507 */
515 if (forks) 508 if (forks)
516 perf_evlist__start_workload(evsel_list); 509 perf_evlist__start_workload(rec->evlist);
510
511 if (opts->initial_delay) {
512 usleep(opts->initial_delay * 1000);
513 perf_evlist__enable(rec->evlist);
514 }
517 515
518 for (;;) { 516 for (;;) {
519 int hits = rec->samples; 517 int hits = rec->samples;
520 518
521 if (perf_record__mmap_read_all(rec) < 0) { 519 if (record__mmap_read_all(rec) < 0) {
522 err = -1; 520 err = -1;
523 goto out_delete_session; 521 goto out_delete_session;
524 } 522 }
@@ -526,7 +524,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
526 if (hits == rec->samples) { 524 if (hits == rec->samples) {
527 if (done) 525 if (done)
528 break; 526 break;
529 err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1); 527 err = poll(rec->evlist->pollfd, rec->evlist->nr_fds, -1);
530 waking++; 528 waking++;
531 } 529 }
532 530
@@ -536,11 +534,19 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
536 * disable events in this case. 534 * disable events in this case.
537 */ 535 */
538 if (done && !disabled && !target__none(&opts->target)) { 536 if (done && !disabled && !target__none(&opts->target)) {
539 perf_evlist__disable(evsel_list); 537 perf_evlist__disable(rec->evlist);
540 disabled = true; 538 disabled = true;
541 } 539 }
542 } 540 }
543 541
542 if (forks && workload_exec_errno) {
543 char msg[512];
544 const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg));
545 pr_err("Workload failed: %s\n", emsg);
546 err = -1;
547 goto out_delete_session;
548 }
549
544 if (quiet || signr == SIGUSR1) 550 if (quiet || signr == SIGUSR1)
545 return 0; 551 return 0;
546 552
@@ -677,7 +683,7 @@ static int get_stack_size(char *str, unsigned long *_size)
677} 683}
678#endif /* HAVE_LIBUNWIND_SUPPORT */ 684#endif /* HAVE_LIBUNWIND_SUPPORT */
679 685
680int record_parse_callchain(const char *arg, struct perf_record_opts *opts) 686int record_parse_callchain(const char *arg, struct record_opts *opts)
681{ 687{
682 char *tok, *name, *saveptr = NULL; 688 char *tok, *name, *saveptr = NULL;
683 char *buf; 689 char *buf;
@@ -733,7 +739,7 @@ int record_parse_callchain(const char *arg, struct perf_record_opts *opts)
733 return ret; 739 return ret;
734} 740}
735 741
736static void callchain_debug(struct perf_record_opts *opts) 742static void callchain_debug(struct record_opts *opts)
737{ 743{
738 pr_debug("callchain: type %d\n", opts->call_graph); 744 pr_debug("callchain: type %d\n", opts->call_graph);
739 745
@@ -746,7 +752,7 @@ int record_parse_callchain_opt(const struct option *opt,
746 const char *arg, 752 const char *arg,
747 int unset) 753 int unset)
748{ 754{
749 struct perf_record_opts *opts = opt->value; 755 struct record_opts *opts = opt->value;
750 int ret; 756 int ret;
751 757
752 /* --no-call-graph */ 758 /* --no-call-graph */
@@ -767,7 +773,7 @@ int record_callchain_opt(const struct option *opt,
767 const char *arg __maybe_unused, 773 const char *arg __maybe_unused,
768 int unset __maybe_unused) 774 int unset __maybe_unused)
769{ 775{
770 struct perf_record_opts *opts = opt->value; 776 struct record_opts *opts = opt->value;
771 777
772 if (opts->call_graph == CALLCHAIN_NONE) 778 if (opts->call_graph == CALLCHAIN_NONE)
773 opts->call_graph = CALLCHAIN_FP; 779 opts->call_graph = CALLCHAIN_FP;
@@ -783,8 +789,8 @@ static const char * const record_usage[] = {
783}; 789};
784 790
785/* 791/*
786 * XXX Ideally would be local to cmd_record() and passed to a perf_record__new 792 * XXX Ideally would be local to cmd_record() and passed to a record__new
787 * because we need to have access to it in perf_record__exit, that is called 793 * because we need to have access to it in record__exit, that is called
788 * after cmd_record() exits, but since record_options need to be accessible to 794 * after cmd_record() exits, but since record_options need to be accessible to
789 * builtin-script, leave it here. 795 * builtin-script, leave it here.
790 * 796 *
@@ -792,7 +798,7 @@ static const char * const record_usage[] = {
792 * 798 *
793 * Just say no to tons of global variables, sigh. 799 * Just say no to tons of global variables, sigh.
794 */ 800 */
795static struct perf_record record = { 801static struct record record = {
796 .opts = { 802 .opts = {
797 .mmap_pages = UINT_MAX, 803 .mmap_pages = UINT_MAX,
798 .user_freq = UINT_MAX, 804 .user_freq = UINT_MAX,
@@ -800,6 +806,7 @@ static struct perf_record record = {
800 .freq = 4000, 806 .freq = 4000,
801 .target = { 807 .target = {
802 .uses_mmap = true, 808 .uses_mmap = true,
809 .default_per_cpu = true,
803 }, 810 },
804 }, 811 },
805}; 812};
@@ -815,7 +822,7 @@ const char record_callchain_help[] = CALLCHAIN_HELP "fp";
815/* 822/*
816 * XXX Will stay a global variable till we fix builtin-script.c to stop messing 823 * XXX Will stay a global variable till we fix builtin-script.c to stop messing
817 * with it and switch to use the library functions in perf_evlist that came 824 * with it and switch to use the library functions in perf_evlist that came
818 * from builtin-record.c, i.e. use perf_record_opts, 825 * from builtin-record.c, i.e. use record_opts,
819 * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record', 826 * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record',
820 * using pipes, etc. 827 * using pipes, etc.
821 */ 828 */
@@ -831,7 +838,7 @@ const struct option record_options[] = {
831 "record events on existing thread id"), 838 "record events on existing thread id"),
832 OPT_INTEGER('r', "realtime", &record.realtime_prio, 839 OPT_INTEGER('r', "realtime", &record.realtime_prio,
833 "collect data with this RT SCHED_FIFO priority"), 840 "collect data with this RT SCHED_FIFO priority"),
834 OPT_BOOLEAN('D', "no-delay", &record.opts.no_delay, 841 OPT_BOOLEAN(0, "no-buffering", &record.opts.no_buffering,
835 "collect data without buffering"), 842 "collect data without buffering"),
836 OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples, 843 OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples,
837 "collect raw sample records from all opened counters"), 844 "collect raw sample records from all opened counters"),
@@ -842,8 +849,9 @@ const struct option record_options[] = {
842 OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), 849 OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
843 OPT_STRING('o', "output", &record.file.path, "file", 850 OPT_STRING('o', "output", &record.file.path, "file",
844 "output file name"), 851 "output file name"),
845 OPT_BOOLEAN('i', "no-inherit", &record.opts.no_inherit, 852 OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit,
846 "child tasks do not inherit counters"), 853 &record.opts.no_inherit_set,
854 "child tasks do not inherit counters"),
847 OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), 855 OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"),
848 OPT_CALLBACK('m', "mmap-pages", &record.opts.mmap_pages, "pages", 856 OPT_CALLBACK('m', "mmap-pages", &record.opts.mmap_pages, "pages",
849 "number of mmap data pages", 857 "number of mmap data pages",
@@ -874,6 +882,8 @@ const struct option record_options[] = {
874 OPT_CALLBACK('G', "cgroup", &record.evlist, "name", 882 OPT_CALLBACK('G', "cgroup", &record.evlist, "name",
875 "monitor event in cgroup name only", 883 "monitor event in cgroup name only",
876 parse_cgroups), 884 parse_cgroups),
885 OPT_UINTEGER('D', "delay", &record.opts.initial_delay,
886 "ms to wait before starting measurement after program start"),
877 OPT_STRING('u', "uid", &record.opts.target.uid_str, "user", 887 OPT_STRING('u', "uid", &record.opts.target.uid_str, "user",
878 "user to profile"), 888 "user to profile"),
879 889
@@ -888,24 +898,21 @@ const struct option record_options[] = {
888 "sample by weight (on special events only)"), 898 "sample by weight (on special events only)"),
889 OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction, 899 OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction,
890 "sample transaction flags (special events only)"), 900 "sample transaction flags (special events only)"),
891 OPT_BOOLEAN(0, "force-per-cpu", &record.opts.target.force_per_cpu, 901 OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread,
892 "force the use of per-cpu mmaps"), 902 "use per-thread mmaps"),
893 OPT_END() 903 OPT_END()
894}; 904};
895 905
896int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) 906int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
897{ 907{
898 int err = -ENOMEM; 908 int err = -ENOMEM;
899 struct perf_evlist *evsel_list; 909 struct record *rec = &record;
900 struct perf_record *rec = &record;
901 char errbuf[BUFSIZ]; 910 char errbuf[BUFSIZ];
902 911
903 evsel_list = perf_evlist__new(); 912 rec->evlist = perf_evlist__new();
904 if (evsel_list == NULL) 913 if (rec->evlist == NULL)
905 return -ENOMEM; 914 return -ENOMEM;
906 915
907 rec->evlist = evsel_list;
908
909 argc = parse_options(argc, argv, record_options, record_usage, 916 argc = parse_options(argc, argv, record_options, record_usage,
910 PARSE_OPT_STOP_AT_NON_OPTION); 917 PARSE_OPT_STOP_AT_NON_OPTION);
911 if (!argc && target__none(&rec->opts.target)) 918 if (!argc && target__none(&rec->opts.target))
@@ -932,12 +939,15 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
932 if (rec->no_buildid_cache || rec->no_buildid) 939 if (rec->no_buildid_cache || rec->no_buildid)
933 disable_buildid_cache(); 940 disable_buildid_cache();
934 941
935 if (evsel_list->nr_entries == 0 && 942 if (rec->evlist->nr_entries == 0 &&
936 perf_evlist__add_default(evsel_list) < 0) { 943 perf_evlist__add_default(rec->evlist) < 0) {
937 pr_err("Not enough memory for event selector list\n"); 944 pr_err("Not enough memory for event selector list\n");
938 goto out_symbol_exit; 945 goto out_symbol_exit;
939 } 946 }
940 947
948 if (rec->opts.target.tid && !rec->opts.no_inherit_set)
949 rec->opts.no_inherit = true;
950
941 err = target__validate(&rec->opts.target); 951 err = target__validate(&rec->opts.target);
942 if (err) { 952 if (err) {
943 target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); 953 target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
@@ -956,20 +966,15 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
956 } 966 }
957 967
958 err = -ENOMEM; 968 err = -ENOMEM;
959 if (perf_evlist__create_maps(evsel_list, &rec->opts.target) < 0) 969 if (perf_evlist__create_maps(rec->evlist, &rec->opts.target) < 0)
960 usage_with_options(record_usage, record_options); 970 usage_with_options(record_usage, record_options);
961 971
962 if (perf_record_opts__config(&rec->opts)) { 972 if (record_opts__config(&rec->opts)) {
963 err = -EINVAL; 973 err = -EINVAL;
964 goto out_free_fd; 974 goto out_symbol_exit;
965 } 975 }
966 976
967 err = __cmd_record(&record, argc, argv); 977 err = __cmd_record(&record, argc, argv);
968
969 perf_evlist__munmap(evsel_list);
970 perf_evlist__close(evsel_list);
971out_free_fd:
972 perf_evlist__delete_maps(evsel_list);
973out_symbol_exit: 978out_symbol_exit:
974 symbol__exit(); 979 symbol__exit();
975 return err; 980 return err;
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 8cf8e66ba594..3c53ec268fbc 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -39,7 +39,7 @@
39#include <dlfcn.h> 39#include <dlfcn.h>
40#include <linux/bitmap.h> 40#include <linux/bitmap.h>
41 41
42struct perf_report { 42struct report {
43 struct perf_tool tool; 43 struct perf_tool tool;
44 struct perf_session *session; 44 struct perf_session *session;
45 bool force, use_tui, use_gtk, use_stdio; 45 bool force, use_tui, use_gtk, use_stdio;
@@ -49,6 +49,8 @@ struct perf_report {
49 bool show_threads; 49 bool show_threads;
50 bool inverted_callchain; 50 bool inverted_callchain;
51 bool mem_mode; 51 bool mem_mode;
52 bool header;
53 bool header_only;
52 int max_stack; 54 int max_stack;
53 struct perf_read_values show_threads_values; 55 struct perf_read_values show_threads_values;
54 const char *pretty_printing_style; 56 const char *pretty_printing_style;
@@ -58,14 +60,14 @@ struct perf_report {
58 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); 60 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
59}; 61};
60 62
61static int perf_report_config(const char *var, const char *value, void *cb) 63static int report__config(const char *var, const char *value, void *cb)
62{ 64{
63 if (!strcmp(var, "report.group")) { 65 if (!strcmp(var, "report.group")) {
64 symbol_conf.event_group = perf_config_bool(var, value); 66 symbol_conf.event_group = perf_config_bool(var, value);
65 return 0; 67 return 0;
66 } 68 }
67 if (!strcmp(var, "report.percent-limit")) { 69 if (!strcmp(var, "report.percent-limit")) {
68 struct perf_report *rep = cb; 70 struct report *rep = cb;
69 rep->min_percent = strtof(value, NULL); 71 rep->min_percent = strtof(value, NULL);
70 return 0; 72 return 0;
71 } 73 }
@@ -73,31 +75,22 @@ static int perf_report_config(const char *var, const char *value, void *cb)
73 return perf_default_config(var, value, cb); 75 return perf_default_config(var, value, cb);
74} 76}
75 77
76static int perf_report__add_mem_hist_entry(struct perf_tool *tool, 78static int report__add_mem_hist_entry(struct perf_tool *tool, struct addr_location *al,
77 struct addr_location *al, 79 struct perf_sample *sample, struct perf_evsel *evsel,
78 struct perf_sample *sample, 80 union perf_event *event)
79 struct perf_evsel *evsel,
80 struct machine *machine,
81 union perf_event *event)
82{ 81{
83 struct perf_report *rep = container_of(tool, struct perf_report, tool); 82 struct report *rep = container_of(tool, struct report, tool);
84 struct symbol *parent = NULL; 83 struct symbol *parent = NULL;
85 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 84 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
86 int err = 0;
87 struct hist_entry *he; 85 struct hist_entry *he;
88 struct mem_info *mi, *mx; 86 struct mem_info *mi, *mx;
89 uint64_t cost; 87 uint64_t cost;
88 int err = sample__resolve_callchain(sample, &parent, evsel, al, rep->max_stack);
90 89
91 if ((sort__has_parent || symbol_conf.use_callchain) && 90 if (err)
92 sample->callchain) { 91 return err;
93 err = machine__resolve_callchain(machine, evsel, al->thread,
94 sample, &parent, al,
95 rep->max_stack);
96 if (err)
97 return err;
98 }
99 92
100 mi = machine__resolve_mem(machine, al->thread, sample, cpumode); 93 mi = machine__resolve_mem(al->machine, al->thread, sample, cpumode);
101 if (!mi) 94 if (!mi)
102 return -ENOMEM; 95 return -ENOMEM;
103 96
@@ -120,77 +113,36 @@ static int perf_report__add_mem_hist_entry(struct perf_tool *tool,
120 if (!he) 113 if (!he)
121 return -ENOMEM; 114 return -ENOMEM;
122 115
123 /* 116 err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
124 * In the TUI browser, we are doing integrated annotation, 117 if (err)
125 * so we don't allocate the extra space needed because the stdio 118 goto out;
126 * code will not use it.
127 */
128 if (sort__has_sym && he->ms.sym && use_browser > 0) {
129 struct annotation *notes = symbol__annotation(he->ms.sym);
130
131 assert(evsel != NULL);
132
133 if (notes->src == NULL && symbol__alloc_hist(he->ms.sym) < 0)
134 goto out;
135
136 err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
137 if (err)
138 goto out;
139 }
140 119
141 if (sort__has_sym && he->mem_info->daddr.sym && use_browser > 0) { 120 mx = he->mem_info;
142 struct annotation *notes; 121 err = addr_map_symbol__inc_samples(&mx->daddr, evsel->idx);
143 122 if (err)
144 mx = he->mem_info; 123 goto out;
145
146 notes = symbol__annotation(mx->daddr.sym);
147 if (notes->src == NULL && symbol__alloc_hist(mx->daddr.sym) < 0)
148 goto out;
149
150 err = symbol__inc_addr_samples(mx->daddr.sym,
151 mx->daddr.map,
152 evsel->idx,
153 mx->daddr.al_addr);
154 if (err)
155 goto out;
156 }
157 124
158 evsel->hists.stats.total_period += cost; 125 evsel->hists.stats.total_period += cost;
159 hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); 126 hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
160 err = 0; 127 err = hist_entry__append_callchain(he, sample);
161
162 if (symbol_conf.use_callchain) {
163 err = callchain_append(he->callchain,
164 &callchain_cursor,
165 sample->period);
166 }
167out: 128out:
168 return err; 129 return err;
169} 130}
170 131
171static int perf_report__add_branch_hist_entry(struct perf_tool *tool, 132static int report__add_branch_hist_entry(struct perf_tool *tool, struct addr_location *al,
172 struct addr_location *al, 133 struct perf_sample *sample, struct perf_evsel *evsel)
173 struct perf_sample *sample,
174 struct perf_evsel *evsel,
175 struct machine *machine)
176{ 134{
177 struct perf_report *rep = container_of(tool, struct perf_report, tool); 135 struct report *rep = container_of(tool, struct report, tool);
178 struct symbol *parent = NULL; 136 struct symbol *parent = NULL;
179 int err = 0;
180 unsigned i; 137 unsigned i;
181 struct hist_entry *he; 138 struct hist_entry *he;
182 struct branch_info *bi, *bx; 139 struct branch_info *bi, *bx;
140 int err = sample__resolve_callchain(sample, &parent, evsel, al, rep->max_stack);
183 141
184 if ((sort__has_parent || symbol_conf.use_callchain) 142 if (err)
185 && sample->callchain) { 143 return err;
186 err = machine__resolve_callchain(machine, evsel, al->thread,
187 sample, &parent, al,
188 rep->max_stack);
189 if (err)
190 return err;
191 }
192 144
193 bi = machine__resolve_bstack(machine, al->thread, 145 bi = machine__resolve_bstack(al->machine, al->thread,
194 sample->branch_stack); 146 sample->branch_stack);
195 if (!bi) 147 if (!bi)
196 return -ENOMEM; 148 return -ENOMEM;
@@ -212,35 +164,15 @@ static int perf_report__add_branch_hist_entry(struct perf_tool *tool,
212 he = __hists__add_entry(&evsel->hists, al, parent, &bi[i], NULL, 164 he = __hists__add_entry(&evsel->hists, al, parent, &bi[i], NULL,
213 1, 1, 0); 165 1, 1, 0);
214 if (he) { 166 if (he) {
215 struct annotation *notes;
216 bx = he->branch_info; 167 bx = he->branch_info;
217 if (bx->from.sym && use_browser == 1 && sort__has_sym) { 168 err = addr_map_symbol__inc_samples(&bx->from, evsel->idx);
218 notes = symbol__annotation(bx->from.sym); 169 if (err)
219 if (!notes->src 170 goto out;
220 && symbol__alloc_hist(bx->from.sym) < 0) 171
221 goto out; 172 err = addr_map_symbol__inc_samples(&bx->to, evsel->idx);
222 173 if (err)
223 err = symbol__inc_addr_samples(bx->from.sym, 174 goto out;
224 bx->from.map,
225 evsel->idx,
226 bx->from.al_addr);
227 if (err)
228 goto out;
229 }
230 175
231 if (bx->to.sym && use_browser == 1 && sort__has_sym) {
232 notes = symbol__annotation(bx->to.sym);
233 if (!notes->src
234 && symbol__alloc_hist(bx->to.sym) < 0)
235 goto out;
236
237 err = symbol__inc_addr_samples(bx->to.sym,
238 bx->to.map,
239 evsel->idx,
240 bx->to.al_addr);
241 if (err)
242 goto out;
243 }
244 evsel->hists.stats.total_period += 1; 176 evsel->hists.stats.total_period += 1;
245 hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); 177 hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
246 } else 178 } else
@@ -252,24 +184,16 @@ out:
252 return err; 184 return err;
253} 185}
254 186
255static int perf_evsel__add_hist_entry(struct perf_tool *tool, 187static int report__add_hist_entry(struct perf_tool *tool, struct perf_evsel *evsel,
256 struct perf_evsel *evsel, 188 struct addr_location *al, struct perf_sample *sample)
257 struct addr_location *al,
258 struct perf_sample *sample,
259 struct machine *machine)
260{ 189{
261 struct perf_report *rep = container_of(tool, struct perf_report, tool); 190 struct report *rep = container_of(tool, struct report, tool);
262 struct symbol *parent = NULL; 191 struct symbol *parent = NULL;
263 int err = 0;
264 struct hist_entry *he; 192 struct hist_entry *he;
193 int err = sample__resolve_callchain(sample, &parent, evsel, al, rep->max_stack);
265 194
266 if ((sort__has_parent || symbol_conf.use_callchain) && sample->callchain) { 195 if (err)
267 err = machine__resolve_callchain(machine, evsel, al->thread, 196 return err;
268 sample, &parent, al,
269 rep->max_stack);
270 if (err)
271 return err;
272 }
273 197
274 he = __hists__add_entry(&evsel->hists, al, parent, NULL, NULL, 198 he = __hists__add_entry(&evsel->hists, al, parent, NULL, NULL,
275 sample->period, sample->weight, 199 sample->period, sample->weight,
@@ -277,30 +201,11 @@ static int perf_evsel__add_hist_entry(struct perf_tool *tool,
277 if (he == NULL) 201 if (he == NULL)
278 return -ENOMEM; 202 return -ENOMEM;
279 203
280 if (symbol_conf.use_callchain) { 204 err = hist_entry__append_callchain(he, sample);
281 err = callchain_append(he->callchain, 205 if (err)
282 &callchain_cursor, 206 goto out;
283 sample->period);
284 if (err)
285 return err;
286 }
287 /*
288 * Only in the TUI browser we are doing integrated annotation,
289 * so we don't allocated the extra space needed because the stdio
290 * code will not use it.
291 */
292 if (he->ms.sym != NULL && use_browser == 1 && sort__has_sym) {
293 struct annotation *notes = symbol__annotation(he->ms.sym);
294
295 assert(evsel != NULL);
296
297 err = -ENOMEM;
298 if (notes->src == NULL && symbol__alloc_hist(he->ms.sym) < 0)
299 goto out;
300
301 err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
302 }
303 207
208 err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
304 evsel->hists.stats.total_period += sample->period; 209 evsel->hists.stats.total_period += sample->period;
305 hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); 210 hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
306out: 211out:
@@ -314,13 +219,13 @@ static int process_sample_event(struct perf_tool *tool,
314 struct perf_evsel *evsel, 219 struct perf_evsel *evsel,
315 struct machine *machine) 220 struct machine *machine)
316{ 221{
317 struct perf_report *rep = container_of(tool, struct perf_report, tool); 222 struct report *rep = container_of(tool, struct report, tool);
318 struct addr_location al; 223 struct addr_location al;
319 int ret; 224 int ret;
320 225
321 if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) { 226 if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) {
322 fprintf(stderr, "problem processing %d event, skipping it.\n", 227 pr_debug("problem processing %d event, skipping it.\n",
323 event->header.type); 228 event->header.type);
324 return -1; 229 return -1;
325 } 230 }
326 231
@@ -331,21 +236,18 @@ static int process_sample_event(struct perf_tool *tool,
331 return 0; 236 return 0;
332 237
333 if (sort__mode == SORT_MODE__BRANCH) { 238 if (sort__mode == SORT_MODE__BRANCH) {
334 ret = perf_report__add_branch_hist_entry(tool, &al, sample, 239 ret = report__add_branch_hist_entry(tool, &al, sample, evsel);
335 evsel, machine);
336 if (ret < 0) 240 if (ret < 0)
337 pr_debug("problem adding lbr entry, skipping event\n"); 241 pr_debug("problem adding lbr entry, skipping event\n");
338 } else if (rep->mem_mode == 1) { 242 } else if (rep->mem_mode == 1) {
339 ret = perf_report__add_mem_hist_entry(tool, &al, sample, 243 ret = report__add_mem_hist_entry(tool, &al, sample, evsel, event);
340 evsel, machine, event);
341 if (ret < 0) 244 if (ret < 0)
342 pr_debug("problem adding mem entry, skipping event\n"); 245 pr_debug("problem adding mem entry, skipping event\n");
343 } else { 246 } else {
344 if (al.map != NULL) 247 if (al.map != NULL)
345 al.map->dso->hit = 1; 248 al.map->dso->hit = 1;
346 249
347 ret = perf_evsel__add_hist_entry(tool, evsel, &al, sample, 250 ret = report__add_hist_entry(tool, evsel, &al, sample);
348 machine);
349 if (ret < 0) 251 if (ret < 0)
350 pr_debug("problem incrementing symbol period, skipping event\n"); 252 pr_debug("problem incrementing symbol period, skipping event\n");
351 } 253 }
@@ -358,7 +260,7 @@ static int process_read_event(struct perf_tool *tool,
358 struct perf_evsel *evsel, 260 struct perf_evsel *evsel,
359 struct machine *machine __maybe_unused) 261 struct machine *machine __maybe_unused)
360{ 262{
361 struct perf_report *rep = container_of(tool, struct perf_report, tool); 263 struct report *rep = container_of(tool, struct report, tool);
362 264
363 if (rep->show_threads) { 265 if (rep->show_threads) {
364 const char *name = evsel ? perf_evsel__name(evsel) : "unknown"; 266 const char *name = evsel ? perf_evsel__name(evsel) : "unknown";
@@ -377,7 +279,7 @@ static int process_read_event(struct perf_tool *tool,
377} 279}
378 280
379/* For pipe mode, sample_type is not currently set */ 281/* For pipe mode, sample_type is not currently set */
380static int perf_report__setup_sample_type(struct perf_report *rep) 282static int report__setup_sample_type(struct report *rep)
381{ 283{
382 struct perf_session *session = rep->session; 284 struct perf_session *session = rep->session;
383 u64 sample_type = perf_evlist__combined_sample_type(session->evlist); 285 u64 sample_type = perf_evlist__combined_sample_type(session->evlist);
@@ -422,8 +324,7 @@ static void sig_handler(int sig __maybe_unused)
422 session_done = 1; 324 session_done = 1;
423} 325}
424 326
425static size_t hists__fprintf_nr_sample_events(struct perf_report *rep, 327static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report *rep,
426 struct hists *hists,
427 const char *evname, FILE *fp) 328 const char *evname, FILE *fp)
428{ 329{
429 size_t ret; 330 size_t ret;
@@ -460,12 +361,12 @@ static size_t hists__fprintf_nr_sample_events(struct perf_report *rep,
460} 361}
461 362
462static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist, 363static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
463 struct perf_report *rep, 364 struct report *rep,
464 const char *help) 365 const char *help)
465{ 366{
466 struct perf_evsel *pos; 367 struct perf_evsel *pos;
467 368
468 list_for_each_entry(pos, &evlist->entries, node) { 369 evlist__for_each(evlist, pos) {
469 struct hists *hists = &pos->hists; 370 struct hists *hists = &pos->hists;
470 const char *evname = perf_evsel__name(pos); 371 const char *evname = perf_evsel__name(pos);
471 372
@@ -473,7 +374,7 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
473 !perf_evsel__is_group_leader(pos)) 374 !perf_evsel__is_group_leader(pos))
474 continue; 375 continue;
475 376
476 hists__fprintf_nr_sample_events(rep, hists, evname, stdout); 377 hists__fprintf_nr_sample_events(hists, rep, evname, stdout);
477 hists__fprintf(hists, true, 0, 0, rep->min_percent, stdout); 378 hists__fprintf(hists, true, 0, 0, rep->min_percent, stdout);
478 fprintf(stdout, "\n\n"); 379 fprintf(stdout, "\n\n");
479 } 380 }
@@ -493,43 +394,11 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
493 return 0; 394 return 0;
494} 395}
495 396
496static int __cmd_report(struct perf_report *rep) 397static void report__warn_kptr_restrict(const struct report *rep)
497{ 398{
498 int ret = -EINVAL; 399 struct map *kernel_map = rep->session->machines.host.vmlinux_maps[MAP__FUNCTION];
499 u64 nr_samples; 400 struct kmap *kernel_kmap = map__kmap(kernel_map);
500 struct perf_session *session = rep->session;
501 struct perf_evsel *pos;
502 struct map *kernel_map;
503 struct kmap *kernel_kmap;
504 const char *help = "For a higher level overview, try: perf report --sort comm,dso";
505 struct ui_progress prog;
506 struct perf_data_file *file = session->file;
507
508 signal(SIGINT, sig_handler);
509 401
510 if (rep->cpu_list) {
511 ret = perf_session__cpu_bitmap(session, rep->cpu_list,
512 rep->cpu_bitmap);
513 if (ret)
514 return ret;
515 }
516
517 if (use_browser <= 0)
518 perf_session__fprintf_info(session, stdout, rep->show_full_info);
519
520 if (rep->show_threads)
521 perf_read_values_init(&rep->show_threads_values);
522
523 ret = perf_report__setup_sample_type(rep);
524 if (ret)
525 return ret;
526
527 ret = perf_session__process_events(session, &rep->tool);
528 if (ret)
529 return ret;
530
531 kernel_map = session->machines.host.vmlinux_maps[MAP__FUNCTION];
532 kernel_kmap = map__kmap(kernel_map);
533 if (kernel_map == NULL || 402 if (kernel_map == NULL ||
534 (kernel_map->dso->hit && 403 (kernel_map->dso->hit &&
535 (kernel_kmap->ref_reloc_sym == NULL || 404 (kernel_kmap->ref_reloc_sym == NULL ||
@@ -552,26 +421,73 @@ static int __cmd_report(struct perf_report *rep)
552"Samples in kernel modules can't be resolved as well.\n\n", 421"Samples in kernel modules can't be resolved as well.\n\n",
553 desc); 422 desc);
554 } 423 }
424}
555 425
556 if (verbose > 3) 426static int report__gtk_browse_hists(struct report *rep, const char *help)
557 perf_session__fprintf(session, stdout); 427{
428 int (*hist_browser)(struct perf_evlist *evlist, const char *help,
429 struct hist_browser_timer *timer, float min_pcnt);
558 430
559 if (verbose > 2) 431 hist_browser = dlsym(perf_gtk_handle, "perf_evlist__gtk_browse_hists");
560 perf_session__fprintf_dsos(session, stdout);
561 432
562 if (dump_trace) { 433 if (hist_browser == NULL) {
563 perf_session__fprintf_nr_events(session, stdout); 434 ui__error("GTK browser not found!\n");
564 return 0; 435 return -1;
565 } 436 }
566 437
567 nr_samples = 0; 438 return hist_browser(rep->session->evlist, help, NULL, rep->min_percent);
568 list_for_each_entry(pos, &session->evlist->entries, node) 439}
440
441static int report__browse_hists(struct report *rep)
442{
443 int ret;
444 struct perf_session *session = rep->session;
445 struct perf_evlist *evlist = session->evlist;
446 const char *help = "For a higher level overview, try: perf report --sort comm,dso";
447
448 switch (use_browser) {
449 case 1:
450 ret = perf_evlist__tui_browse_hists(evlist, help, NULL,
451 rep->min_percent,
452 &session->header.env);
453 /*
454 * Usually "ret" is the last pressed key, and we only
455 * care if the key notifies us to switch data file.
456 */
457 if (ret != K_SWITCH_INPUT_DATA)
458 ret = 0;
459 break;
460 case 2:
461 ret = report__gtk_browse_hists(rep, help);
462 break;
463 default:
464 ret = perf_evlist__tty_browse_hists(evlist, rep, help);
465 break;
466 }
467
468 return ret;
469}
470
471static u64 report__collapse_hists(struct report *rep)
472{
473 struct ui_progress prog;
474 struct perf_evsel *pos;
475 u64 nr_samples = 0;
476 /*
477 * Count number of histogram entries to use when showing progress,
478 * reusing nr_samples variable.
479 */
480 evlist__for_each(rep->session->evlist, pos)
569 nr_samples += pos->hists.nr_entries; 481 nr_samples += pos->hists.nr_entries;
570 482
571 ui_progress__init(&prog, nr_samples, "Merging related events..."); 483 ui_progress__init(&prog, nr_samples, "Merging related events...");
572 484 /*
485 * Count total number of samples, will be used to check if this
486 * session had any.
487 */
573 nr_samples = 0; 488 nr_samples = 0;
574 list_for_each_entry(pos, &session->evlist->entries, node) { 489
490 evlist__for_each(rep->session->evlist, pos) {
575 struct hists *hists = &pos->hists; 491 struct hists *hists = &pos->hists;
576 492
577 if (pos->idx == 0) 493 if (pos->idx == 0)
@@ -589,8 +505,57 @@ static int __cmd_report(struct perf_report *rep)
589 hists__link(leader_hists, hists); 505 hists__link(leader_hists, hists);
590 } 506 }
591 } 507 }
508
592 ui_progress__finish(); 509 ui_progress__finish();
593 510
511 return nr_samples;
512}
513
514static int __cmd_report(struct report *rep)
515{
516 int ret;
517 u64 nr_samples;
518 struct perf_session *session = rep->session;
519 struct perf_evsel *pos;
520 struct perf_data_file *file = session->file;
521
522 signal(SIGINT, sig_handler);
523
524 if (rep->cpu_list) {
525 ret = perf_session__cpu_bitmap(session, rep->cpu_list,
526 rep->cpu_bitmap);
527 if (ret)
528 return ret;
529 }
530
531 if (rep->show_threads)
532 perf_read_values_init(&rep->show_threads_values);
533
534 ret = report__setup_sample_type(rep);
535 if (ret)
536 return ret;
537
538 ret = perf_session__process_events(session, &rep->tool);
539 if (ret)
540 return ret;
541
542 report__warn_kptr_restrict(rep);
543
544 if (use_browser == 0) {
545 if (verbose > 3)
546 perf_session__fprintf(session, stdout);
547
548 if (verbose > 2)
549 perf_session__fprintf_dsos(session, stdout);
550
551 if (dump_trace) {
552 perf_session__fprintf_nr_events(session, stdout);
553 return 0;
554 }
555 }
556
557 nr_samples = report__collapse_hists(rep);
558
594 if (session_done()) 559 if (session_done())
595 return 0; 560 return 0;
596 561
@@ -599,47 +564,16 @@ static int __cmd_report(struct perf_report *rep)
599 return 0; 564 return 0;
600 } 565 }
601 566
602 list_for_each_entry(pos, &session->evlist->entries, node) 567 evlist__for_each(session->evlist, pos)
603 hists__output_resort(&pos->hists); 568 hists__output_resort(&pos->hists);
604 569
605 if (use_browser > 0) { 570 return report__browse_hists(rep);
606 if (use_browser == 1) {
607 ret = perf_evlist__tui_browse_hists(session->evlist,
608 help, NULL,
609 rep->min_percent,
610 &session->header.env);
611 /*
612 * Usually "ret" is the last pressed key, and we only
613 * care if the key notifies us to switch data file.
614 */
615 if (ret != K_SWITCH_INPUT_DATA)
616 ret = 0;
617
618 } else if (use_browser == 2) {
619 int (*hist_browser)(struct perf_evlist *,
620 const char *,
621 struct hist_browser_timer *,
622 float min_pcnt);
623
624 hist_browser = dlsym(perf_gtk_handle,
625 "perf_evlist__gtk_browse_hists");
626 if (hist_browser == NULL) {
627 ui__error("GTK browser not found!\n");
628 return ret;
629 }
630 hist_browser(session->evlist, help, NULL,
631 rep->min_percent);
632 }
633 } else
634 perf_evlist__tty_browse_hists(session->evlist, rep, help);
635
636 return ret;
637} 571}
638 572
639static int 573static int
640parse_callchain_opt(const struct option *opt, const char *arg, int unset) 574parse_callchain_opt(const struct option *opt, const char *arg, int unset)
641{ 575{
642 struct perf_report *rep = (struct perf_report *)opt->value; 576 struct report *rep = (struct report *)opt->value;
643 char *tok, *tok2; 577 char *tok, *tok2;
644 char *endptr; 578 char *endptr;
645 579
@@ -721,7 +655,7 @@ parse_callchain_opt(const struct option *opt, const char *arg, int unset)
721 return -1; 655 return -1;
722setup: 656setup:
723 if (callchain_register_param(&callchain_param) < 0) { 657 if (callchain_register_param(&callchain_param) < 0) {
724 fprintf(stderr, "Can't register callchain params\n"); 658 pr_err("Can't register callchain params\n");
725 return -1; 659 return -1;
726 } 660 }
727 return 0; 661 return 0;
@@ -759,7 +693,7 @@ static int
759parse_percent_limit(const struct option *opt, const char *str, 693parse_percent_limit(const struct option *opt, const char *str,
760 int unset __maybe_unused) 694 int unset __maybe_unused)
761{ 695{
762 struct perf_report *rep = opt->value; 696 struct report *rep = opt->value;
763 697
764 rep->min_percent = strtof(str, NULL); 698 rep->min_percent = strtof(str, NULL);
765 return 0; 699 return 0;
@@ -777,7 +711,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
777 "perf report [<options>]", 711 "perf report [<options>]",
778 NULL 712 NULL
779 }; 713 };
780 struct perf_report report = { 714 struct report report = {
781 .tool = { 715 .tool = {
782 .sample = process_sample_event, 716 .sample = process_sample_event,
783 .mmap = perf_event__process_mmap, 717 .mmap = perf_event__process_mmap,
@@ -820,6 +754,9 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
820 OPT_BOOLEAN(0, "gtk", &report.use_gtk, "Use the GTK2 interface"), 754 OPT_BOOLEAN(0, "gtk", &report.use_gtk, "Use the GTK2 interface"),
821 OPT_BOOLEAN(0, "stdio", &report.use_stdio, 755 OPT_BOOLEAN(0, "stdio", &report.use_stdio,
822 "Use the stdio interface"), 756 "Use the stdio interface"),
757 OPT_BOOLEAN(0, "header", &report.header, "Show data header."),
758 OPT_BOOLEAN(0, "header-only", &report.header_only,
759 "Show only data header."),
823 OPT_STRING('s', "sort", &sort_order, "key[,key2...]", 760 OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
824 "sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline," 761 "sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline,"
825 " dso_to, dso_from, symbol_to, symbol_from, mispredict," 762 " dso_to, dso_from, symbol_to, symbol_from, mispredict,"
@@ -890,7 +827,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
890 .mode = PERF_DATA_MODE_READ, 827 .mode = PERF_DATA_MODE_READ,
891 }; 828 };
892 829
893 perf_config(perf_report_config, &report); 830 perf_config(report__config, &report);
894 831
895 argc = parse_options(argc, argv, options, report_usage, 0); 832 argc = parse_options(argc, argv, options, report_usage, 0);
896 833
@@ -940,7 +877,7 @@ repeat:
940 } 877 }
941 if (report.mem_mode) { 878 if (report.mem_mode) {
942 if (sort__mode == SORT_MODE__BRANCH) { 879 if (sort__mode == SORT_MODE__BRANCH) {
943 fprintf(stderr, "branch and mem mode incompatible\n"); 880 pr_err("branch and mem mode incompatible\n");
944 goto error; 881 goto error;
945 } 882 }
946 sort__mode = SORT_MODE__MEMORY; 883 sort__mode = SORT_MODE__MEMORY;
@@ -963,6 +900,10 @@ repeat:
963 goto error; 900 goto error;
964 } 901 }
965 902
903 /* Force tty output for header output. */
904 if (report.header || report.header_only)
905 use_browser = 0;
906
966 if (strcmp(input_name, "-") != 0) 907 if (strcmp(input_name, "-") != 0)
967 setup_browser(true); 908 setup_browser(true);
968 else { 909 else {
@@ -970,6 +911,16 @@ repeat:
970 perf_hpp__init(); 911 perf_hpp__init();
971 } 912 }
972 913
914 if (report.header || report.header_only) {
915 perf_session__fprintf_info(session, stdout,
916 report.show_full_info);
917 if (report.header_only)
918 return 0;
919 } else if (use_browser == 0) {
920 fputs("# To display the perf.data header info, please use --header/--header-only options.\n#\n",
921 stdout);
922 }
923
973 /* 924 /*
974 * Only in the TUI browser we are doing integrated annotation, 925 * Only in the TUI browser we are doing integrated annotation,
975 * so don't allocate extra space that won't be used in the stdio 926 * so don't allocate extra space that won't be used in the stdio
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 0f3c65518a2c..6a76a07b6789 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -469,7 +469,7 @@ static void *thread_func(void *ctx)
469 char comm2[22]; 469 char comm2[22];
470 int fd; 470 int fd;
471 471
472 free(parms); 472 zfree(&parms);
473 473
474 sprintf(comm2, ":%s", this_task->comm); 474 sprintf(comm2, ":%s", this_task->comm);
475 prctl(PR_SET_NAME, comm2); 475 prctl(PR_SET_NAME, comm2);
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index baf17989a216..9e9c91f5b7fa 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -43,6 +43,7 @@ enum perf_output_field {
43 PERF_OUTPUT_DSO = 1U << 9, 43 PERF_OUTPUT_DSO = 1U << 9,
44 PERF_OUTPUT_ADDR = 1U << 10, 44 PERF_OUTPUT_ADDR = 1U << 10,
45 PERF_OUTPUT_SYMOFFSET = 1U << 11, 45 PERF_OUTPUT_SYMOFFSET = 1U << 11,
46 PERF_OUTPUT_SRCLINE = 1U << 12,
46}; 47};
47 48
48struct output_option { 49struct output_option {
@@ -61,6 +62,7 @@ struct output_option {
61 {.str = "dso", .field = PERF_OUTPUT_DSO}, 62 {.str = "dso", .field = PERF_OUTPUT_DSO},
62 {.str = "addr", .field = PERF_OUTPUT_ADDR}, 63 {.str = "addr", .field = PERF_OUTPUT_ADDR},
63 {.str = "symoff", .field = PERF_OUTPUT_SYMOFFSET}, 64 {.str = "symoff", .field = PERF_OUTPUT_SYMOFFSET},
65 {.str = "srcline", .field = PERF_OUTPUT_SRCLINE},
64}; 66};
65 67
66/* default set to maintain compatibility with current format */ 68/* default set to maintain compatibility with current format */
@@ -210,6 +212,11 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
210 "to DSO.\n"); 212 "to DSO.\n");
211 return -EINVAL; 213 return -EINVAL;
212 } 214 }
215 if (PRINT_FIELD(SRCLINE) && !PRINT_FIELD(IP)) {
216 pr_err("Display of source line number requested but sample IP is not\n"
217 "selected. Hence, no address to lookup the source line number.\n");
218 return -EINVAL;
219 }
213 220
214 if ((PRINT_FIELD(PID) || PRINT_FIELD(TID)) && 221 if ((PRINT_FIELD(PID) || PRINT_FIELD(TID)) &&
215 perf_evsel__check_stype(evsel, PERF_SAMPLE_TID, "TID", 222 perf_evsel__check_stype(evsel, PERF_SAMPLE_TID, "TID",
@@ -245,6 +252,9 @@ static void set_print_ip_opts(struct perf_event_attr *attr)
245 252
246 if (PRINT_FIELD(SYMOFFSET)) 253 if (PRINT_FIELD(SYMOFFSET))
247 output[type].print_ip_opts |= PRINT_IP_OPT_SYMOFFSET; 254 output[type].print_ip_opts |= PRINT_IP_OPT_SYMOFFSET;
255
256 if (PRINT_FIELD(SRCLINE))
257 output[type].print_ip_opts |= PRINT_IP_OPT_SRCLINE;
248} 258}
249 259
250/* 260/*
@@ -280,6 +290,30 @@ static int perf_session__check_output_opt(struct perf_session *session)
280 set_print_ip_opts(&evsel->attr); 290 set_print_ip_opts(&evsel->attr);
281 } 291 }
282 292
293 /*
294 * set default for tracepoints to print symbols only
295 * if callchains are present
296 */
297 if (symbol_conf.use_callchain &&
298 !output[PERF_TYPE_TRACEPOINT].user_set) {
299 struct perf_event_attr *attr;
300
301 j = PERF_TYPE_TRACEPOINT;
302 evsel = perf_session__find_first_evtype(session, j);
303 if (evsel == NULL)
304 goto out;
305
306 attr = &evsel->attr;
307
308 if (attr->sample_type & PERF_SAMPLE_CALLCHAIN) {
309 output[j].fields |= PERF_OUTPUT_IP;
310 output[j].fields |= PERF_OUTPUT_SYM;
311 output[j].fields |= PERF_OUTPUT_DSO;
312 set_print_ip_opts(attr);
313 }
314 }
315
316out:
283 return 0; 317 return 0;
284} 318}
285 319
@@ -288,7 +322,6 @@ static void print_sample_start(struct perf_sample *sample,
288 struct perf_evsel *evsel) 322 struct perf_evsel *evsel)
289{ 323{
290 struct perf_event_attr *attr = &evsel->attr; 324 struct perf_event_attr *attr = &evsel->attr;
291 const char *evname = NULL;
292 unsigned long secs; 325 unsigned long secs;
293 unsigned long usecs; 326 unsigned long usecs;
294 unsigned long long nsecs; 327 unsigned long long nsecs;
@@ -323,11 +356,6 @@ static void print_sample_start(struct perf_sample *sample,
323 usecs = nsecs / NSECS_PER_USEC; 356 usecs = nsecs / NSECS_PER_USEC;
324 printf("%5lu.%06lu: ", secs, usecs); 357 printf("%5lu.%06lu: ", secs, usecs);
325 } 358 }
326
327 if (PRINT_FIELD(EVNAME)) {
328 evname = perf_evsel__name(evsel);
329 printf("%s: ", evname ? evname : "[unknown]");
330 }
331} 359}
332 360
333static bool is_bts_event(struct perf_event_attr *attr) 361static bool is_bts_event(struct perf_event_attr *attr)
@@ -395,8 +423,8 @@ static void print_sample_addr(union perf_event *event,
395static void print_sample_bts(union perf_event *event, 423static void print_sample_bts(union perf_event *event,
396 struct perf_sample *sample, 424 struct perf_sample *sample,
397 struct perf_evsel *evsel, 425 struct perf_evsel *evsel,
398 struct machine *machine, 426 struct thread *thread,
399 struct thread *thread) 427 struct addr_location *al)
400{ 428{
401 struct perf_event_attr *attr = &evsel->attr; 429 struct perf_event_attr *attr = &evsel->attr;
402 430
@@ -406,7 +434,7 @@ static void print_sample_bts(union perf_event *event,
406 printf(" "); 434 printf(" ");
407 else 435 else
408 printf("\n"); 436 printf("\n");
409 perf_evsel__print_ip(evsel, event, sample, machine, 437 perf_evsel__print_ip(evsel, sample, al,
410 output[attr->type].print_ip_opts, 438 output[attr->type].print_ip_opts,
411 PERF_MAX_STACK_DEPTH); 439 PERF_MAX_STACK_DEPTH);
412 } 440 }
@@ -417,15 +445,14 @@ static void print_sample_bts(union perf_event *event,
417 if (PRINT_FIELD(ADDR) || 445 if (PRINT_FIELD(ADDR) ||
418 ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) && 446 ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) &&
419 !output[attr->type].user_set)) 447 !output[attr->type].user_set))
420 print_sample_addr(event, sample, machine, thread, attr); 448 print_sample_addr(event, sample, al->machine, thread, attr);
421 449
422 printf("\n"); 450 printf("\n");
423} 451}
424 452
425static void process_event(union perf_event *event, struct perf_sample *sample, 453static void process_event(union perf_event *event, struct perf_sample *sample,
426 struct perf_evsel *evsel, struct machine *machine, 454 struct perf_evsel *evsel, struct thread *thread,
427 struct thread *thread, 455 struct addr_location *al)
428 struct addr_location *al __maybe_unused)
429{ 456{
430 struct perf_event_attr *attr = &evsel->attr; 457 struct perf_event_attr *attr = &evsel->attr;
431 458
@@ -434,8 +461,13 @@ static void process_event(union perf_event *event, struct perf_sample *sample,
434 461
435 print_sample_start(sample, thread, evsel); 462 print_sample_start(sample, thread, evsel);
436 463
464 if (PRINT_FIELD(EVNAME)) {
465 const char *evname = perf_evsel__name(evsel);
466 printf("%s: ", evname ? evname : "[unknown]");
467 }
468
437 if (is_bts_event(attr)) { 469 if (is_bts_event(attr)) {
438 print_sample_bts(event, sample, evsel, machine, thread); 470 print_sample_bts(event, sample, evsel, thread, al);
439 return; 471 return;
440 } 472 }
441 473
@@ -443,7 +475,7 @@ static void process_event(union perf_event *event, struct perf_sample *sample,
443 event_format__print(evsel->tp_format, sample->cpu, 475 event_format__print(evsel->tp_format, sample->cpu,
444 sample->raw_data, sample->raw_size); 476 sample->raw_data, sample->raw_size);
445 if (PRINT_FIELD(ADDR)) 477 if (PRINT_FIELD(ADDR))
446 print_sample_addr(event, sample, machine, thread, attr); 478 print_sample_addr(event, sample, al->machine, thread, attr);
447 479
448 if (PRINT_FIELD(IP)) { 480 if (PRINT_FIELD(IP)) {
449 if (!symbol_conf.use_callchain) 481 if (!symbol_conf.use_callchain)
@@ -451,7 +483,7 @@ static void process_event(union perf_event *event, struct perf_sample *sample,
451 else 483 else
452 printf("\n"); 484 printf("\n");
453 485
454 perf_evsel__print_ip(evsel, event, sample, machine, 486 perf_evsel__print_ip(evsel, sample, al,
455 output[attr->type].print_ip_opts, 487 output[attr->type].print_ip_opts,
456 PERF_MAX_STACK_DEPTH); 488 PERF_MAX_STACK_DEPTH);
457 } 489 }
@@ -540,7 +572,7 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
540 if (cpu_list && !test_bit(sample->cpu, cpu_bitmap)) 572 if (cpu_list && !test_bit(sample->cpu, cpu_bitmap))
541 return 0; 573 return 0;
542 574
543 scripting_ops->process_event(event, sample, evsel, machine, thread, &al); 575 scripting_ops->process_event(event, sample, evsel, thread, &al);
544 576
545 evsel->hists.stats.total_period += sample->period; 577 evsel->hists.stats.total_period += sample->period;
546 return 0; 578 return 0;
@@ -549,6 +581,8 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
549struct perf_script { 581struct perf_script {
550 struct perf_tool tool; 582 struct perf_tool tool;
551 struct perf_session *session; 583 struct perf_session *session;
584 bool show_task_events;
585 bool show_mmap_events;
552}; 586};
553 587
554static int process_attr(struct perf_tool *tool, union perf_event *event, 588static int process_attr(struct perf_tool *tool, union perf_event *event,
@@ -569,7 +603,7 @@ static int process_attr(struct perf_tool *tool, union perf_event *event,
569 if (evsel->attr.type >= PERF_TYPE_MAX) 603 if (evsel->attr.type >= PERF_TYPE_MAX)
570 return 0; 604 return 0;
571 605
572 list_for_each_entry(pos, &evlist->entries, node) { 606 evlist__for_each(evlist, pos) {
573 if (pos->attr.type == evsel->attr.type && pos != evsel) 607 if (pos->attr.type == evsel->attr.type && pos != evsel)
574 return 0; 608 return 0;
575 } 609 }
@@ -579,6 +613,163 @@ static int process_attr(struct perf_tool *tool, union perf_event *event,
579 return perf_evsel__check_attr(evsel, scr->session); 613 return perf_evsel__check_attr(evsel, scr->session);
580} 614}
581 615
616static int process_comm_event(struct perf_tool *tool,
617 union perf_event *event,
618 struct perf_sample *sample,
619 struct machine *machine)
620{
621 struct thread *thread;
622 struct perf_script *script = container_of(tool, struct perf_script, tool);
623 struct perf_session *session = script->session;
624 struct perf_evsel *evsel = perf_evlist__first(session->evlist);
625 int ret = -1;
626
627 thread = machine__findnew_thread(machine, event->comm.pid, event->comm.tid);
628 if (thread == NULL) {
629 pr_debug("problem processing COMM event, skipping it.\n");
630 return -1;
631 }
632
633 if (perf_event__process_comm(tool, event, sample, machine) < 0)
634 goto out;
635
636 if (!evsel->attr.sample_id_all) {
637 sample->cpu = 0;
638 sample->time = 0;
639 sample->tid = event->comm.tid;
640 sample->pid = event->comm.pid;
641 }
642 print_sample_start(sample, thread, evsel);
643 perf_event__fprintf(event, stdout);
644 ret = 0;
645
646out:
647 return ret;
648}
649
650static int process_fork_event(struct perf_tool *tool,
651 union perf_event *event,
652 struct perf_sample *sample,
653 struct machine *machine)
654{
655 struct thread *thread;
656 struct perf_script *script = container_of(tool, struct perf_script, tool);
657 struct perf_session *session = script->session;
658 struct perf_evsel *evsel = perf_evlist__first(session->evlist);
659
660 if (perf_event__process_fork(tool, event, sample, machine) < 0)
661 return -1;
662
663 thread = machine__findnew_thread(machine, event->fork.pid, event->fork.tid);
664 if (thread == NULL) {
665 pr_debug("problem processing FORK event, skipping it.\n");
666 return -1;
667 }
668
669 if (!evsel->attr.sample_id_all) {
670 sample->cpu = 0;
671 sample->time = event->fork.time;
672 sample->tid = event->fork.tid;
673 sample->pid = event->fork.pid;
674 }
675 print_sample_start(sample, thread, evsel);
676 perf_event__fprintf(event, stdout);
677
678 return 0;
679}
680static int process_exit_event(struct perf_tool *tool,
681 union perf_event *event,
682 struct perf_sample *sample,
683 struct machine *machine)
684{
685 struct thread *thread;
686 struct perf_script *script = container_of(tool, struct perf_script, tool);
687 struct perf_session *session = script->session;
688 struct perf_evsel *evsel = perf_evlist__first(session->evlist);
689
690 thread = machine__findnew_thread(machine, event->fork.pid, event->fork.tid);
691 if (thread == NULL) {
692 pr_debug("problem processing EXIT event, skipping it.\n");
693 return -1;
694 }
695
696 if (!evsel->attr.sample_id_all) {
697 sample->cpu = 0;
698 sample->time = 0;
699 sample->tid = event->comm.tid;
700 sample->pid = event->comm.pid;
701 }
702 print_sample_start(sample, thread, evsel);
703 perf_event__fprintf(event, stdout);
704
705 if (perf_event__process_exit(tool, event, sample, machine) < 0)
706 return -1;
707
708 return 0;
709}
710
711static int process_mmap_event(struct perf_tool *tool,
712 union perf_event *event,
713 struct perf_sample *sample,
714 struct machine *machine)
715{
716 struct thread *thread;
717 struct perf_script *script = container_of(tool, struct perf_script, tool);
718 struct perf_session *session = script->session;
719 struct perf_evsel *evsel = perf_evlist__first(session->evlist);
720
721 if (perf_event__process_mmap(tool, event, sample, machine) < 0)
722 return -1;
723
724 thread = machine__findnew_thread(machine, event->mmap.pid, event->mmap.tid);
725 if (thread == NULL) {
726 pr_debug("problem processing MMAP event, skipping it.\n");
727 return -1;
728 }
729
730 if (!evsel->attr.sample_id_all) {
731 sample->cpu = 0;
732 sample->time = 0;
733 sample->tid = event->mmap.tid;
734 sample->pid = event->mmap.pid;
735 }
736 print_sample_start(sample, thread, evsel);
737 perf_event__fprintf(event, stdout);
738
739 return 0;
740}
741
742static int process_mmap2_event(struct perf_tool *tool,
743 union perf_event *event,
744 struct perf_sample *sample,
745 struct machine *machine)
746{
747 struct thread *thread;
748 struct perf_script *script = container_of(tool, struct perf_script, tool);
749 struct perf_session *session = script->session;
750 struct perf_evsel *evsel = perf_evlist__first(session->evlist);
751
752 if (perf_event__process_mmap2(tool, event, sample, machine) < 0)
753 return -1;
754
755 thread = machine__findnew_thread(machine, event->mmap2.pid, event->mmap2.tid);
756 if (thread == NULL) {
757 pr_debug("problem processing MMAP2 event, skipping it.\n");
758 return -1;
759 }
760
761 if (!evsel->attr.sample_id_all) {
762 sample->cpu = 0;
763 sample->time = 0;
764 sample->tid = event->mmap2.tid;
765 sample->pid = event->mmap2.pid;
766 }
767 print_sample_start(sample, thread, evsel);
768 perf_event__fprintf(event, stdout);
769
770 return 0;
771}
772
582static void sig_handler(int sig __maybe_unused) 773static void sig_handler(int sig __maybe_unused)
583{ 774{
584 session_done = 1; 775 session_done = 1;
@@ -590,6 +781,17 @@ static int __cmd_script(struct perf_script *script)
590 781
591 signal(SIGINT, sig_handler); 782 signal(SIGINT, sig_handler);
592 783
784 /* override event processing functions */
785 if (script->show_task_events) {
786 script->tool.comm = process_comm_event;
787 script->tool.fork = process_fork_event;
788 script->tool.exit = process_exit_event;
789 }
790 if (script->show_mmap_events) {
791 script->tool.mmap = process_mmap_event;
792 script->tool.mmap2 = process_mmap2_event;
793 }
794
593 ret = perf_session__process_events(script->session, &script->tool); 795 ret = perf_session__process_events(script->session, &script->tool);
594 796
595 if (debug_mode) 797 if (debug_mode)
@@ -900,9 +1102,9 @@ static struct script_desc *script_desc__new(const char *name)
900 1102
901static void script_desc__delete(struct script_desc *s) 1103static void script_desc__delete(struct script_desc *s)
902{ 1104{
903 free(s->name); 1105 zfree(&s->name);
904 free(s->half_liner); 1106 zfree(&s->half_liner);
905 free(s->args); 1107 zfree(&s->args);
906 free(s); 1108 free(s);
907} 1109}
908 1110
@@ -1107,8 +1309,7 @@ static int check_ev_match(char *dir_name, char *scriptname,
1107 snprintf(evname, len + 1, "%s", p); 1309 snprintf(evname, len + 1, "%s", p);
1108 1310
1109 match = 0; 1311 match = 0;
1110 list_for_each_entry(pos, 1312 evlist__for_each(session->evlist, pos) {
1111 &session->evlist->entries, node) {
1112 if (!strcmp(perf_evsel__name(pos), evname)) { 1313 if (!strcmp(perf_evsel__name(pos), evname)) {
1113 match = 1; 1314 match = 1;
1114 break; 1315 break;
@@ -1290,6 +1491,8 @@ static int have_cmd(int argc, const char **argv)
1290int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) 1491int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1291{ 1492{
1292 bool show_full_info = false; 1493 bool show_full_info = false;
1494 bool header = false;
1495 bool header_only = false;
1293 char *rec_script_path = NULL; 1496 char *rec_script_path = NULL;
1294 char *rep_script_path = NULL; 1497 char *rep_script_path = NULL;
1295 struct perf_session *session; 1498 struct perf_session *session;
@@ -1328,6 +1531,8 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1328 OPT_STRING('i', "input", &input_name, "file", "input file name"), 1531 OPT_STRING('i', "input", &input_name, "file", "input file name"),
1329 OPT_BOOLEAN('d', "debug-mode", &debug_mode, 1532 OPT_BOOLEAN('d', "debug-mode", &debug_mode,
1330 "do various checks like samples ordering and lost events"), 1533 "do various checks like samples ordering and lost events"),
1534 OPT_BOOLEAN(0, "header", &header, "Show data header."),
1535 OPT_BOOLEAN(0, "header-only", &header_only, "Show only data header."),
1331 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, 1536 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
1332 "file", "vmlinux pathname"), 1537 "file", "vmlinux pathname"),
1333 OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, 1538 OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name,
@@ -1352,6 +1557,10 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1352 "display extended information from perf.data file"), 1557 "display extended information from perf.data file"),
1353 OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path, 1558 OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path,
1354 "Show the path of [kernel.kallsyms]"), 1559 "Show the path of [kernel.kallsyms]"),
1560 OPT_BOOLEAN('\0', "show-task-events", &script.show_task_events,
1561 "Show the fork/comm/exit events"),
1562 OPT_BOOLEAN('\0', "show-mmap-events", &script.show_mmap_events,
1563 "Show the mmap events"),
1355 OPT_END() 1564 OPT_END()
1356 }; 1565 };
1357 const char * const script_usage[] = { 1566 const char * const script_usage[] = {
@@ -1540,6 +1749,12 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1540 if (session == NULL) 1749 if (session == NULL)
1541 return -ENOMEM; 1750 return -ENOMEM;
1542 1751
1752 if (header || header_only) {
1753 perf_session__fprintf_info(session, stdout, show_full_info);
1754 if (header_only)
1755 return 0;
1756 }
1757
1543 script.session = session; 1758 script.session = session;
1544 1759
1545 if (cpu_list) { 1760 if (cpu_list) {
@@ -1547,9 +1762,6 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1547 return -1; 1762 return -1;
1548 } 1763 }
1549 1764
1550 if (!script_name && !generate_script_lang)
1551 perf_session__fprintf_info(session, stdout, show_full_info);
1552
1553 if (!no_callchain) 1765 if (!no_callchain)
1554 symbol_conf.use_callchain = true; 1766 symbol_conf.use_callchain = true;
1555 else 1767 else
@@ -1588,7 +1800,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1588 return -1; 1800 return -1;
1589 } 1801 }
1590 1802
1591 err = scripting_ops->generate_script(session->pevent, 1803 err = scripting_ops->generate_script(session->tevent.pevent,
1592 "perf-script"); 1804 "perf-script");
1593 goto out; 1805 goto out;
1594 } 1806 }
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index ee0d565f83e3..8b0e1c9234d9 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -138,6 +138,7 @@ static const char *post_cmd = NULL;
138static bool sync_run = false; 138static bool sync_run = false;
139static unsigned int interval = 0; 139static unsigned int interval = 0;
140static unsigned int initial_delay = 0; 140static unsigned int initial_delay = 0;
141static unsigned int unit_width = 4; /* strlen("unit") */
141static bool forever = false; 142static bool forever = false;
142static struct timespec ref_time; 143static struct timespec ref_time;
143static struct cpu_map *aggr_map; 144static struct cpu_map *aggr_map;
@@ -184,8 +185,7 @@ static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel)
184 185
185static void perf_evsel__free_stat_priv(struct perf_evsel *evsel) 186static void perf_evsel__free_stat_priv(struct perf_evsel *evsel)
186{ 187{
187 free(evsel->priv); 188 zfree(&evsel->priv);
188 evsel->priv = NULL;
189} 189}
190 190
191static int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel) 191static int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel)
@@ -207,15 +207,14 @@ static int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel)
207 207
208static void perf_evsel__free_prev_raw_counts(struct perf_evsel *evsel) 208static void perf_evsel__free_prev_raw_counts(struct perf_evsel *evsel)
209{ 209{
210 free(evsel->prev_raw_counts); 210 zfree(&evsel->prev_raw_counts);
211 evsel->prev_raw_counts = NULL;
212} 211}
213 212
214static void perf_evlist__free_stats(struct perf_evlist *evlist) 213static void perf_evlist__free_stats(struct perf_evlist *evlist)
215{ 214{
216 struct perf_evsel *evsel; 215 struct perf_evsel *evsel;
217 216
218 list_for_each_entry(evsel, &evlist->entries, node) { 217 evlist__for_each(evlist, evsel) {
219 perf_evsel__free_stat_priv(evsel); 218 perf_evsel__free_stat_priv(evsel);
220 perf_evsel__free_counts(evsel); 219 perf_evsel__free_counts(evsel);
221 perf_evsel__free_prev_raw_counts(evsel); 220 perf_evsel__free_prev_raw_counts(evsel);
@@ -226,7 +225,7 @@ static int perf_evlist__alloc_stats(struct perf_evlist *evlist, bool alloc_raw)
226{ 225{
227 struct perf_evsel *evsel; 226 struct perf_evsel *evsel;
228 227
229 list_for_each_entry(evsel, &evlist->entries, node) { 228 evlist__for_each(evlist, evsel) {
230 if (perf_evsel__alloc_stat_priv(evsel) < 0 || 229 if (perf_evsel__alloc_stat_priv(evsel) < 0 ||
231 perf_evsel__alloc_counts(evsel, perf_evsel__nr_cpus(evsel)) < 0 || 230 perf_evsel__alloc_counts(evsel, perf_evsel__nr_cpus(evsel)) < 0 ||
232 (alloc_raw && perf_evsel__alloc_prev_raw_counts(evsel) < 0)) 231 (alloc_raw && perf_evsel__alloc_prev_raw_counts(evsel) < 0))
@@ -260,7 +259,7 @@ static void perf_stat__reset_stats(struct perf_evlist *evlist)
260{ 259{
261 struct perf_evsel *evsel; 260 struct perf_evsel *evsel;
262 261
263 list_for_each_entry(evsel, &evlist->entries, node) { 262 evlist__for_each(evlist, evsel) {
264 perf_evsel__reset_stat_priv(evsel); 263 perf_evsel__reset_stat_priv(evsel);
265 perf_evsel__reset_counts(evsel, perf_evsel__nr_cpus(evsel)); 264 perf_evsel__reset_counts(evsel, perf_evsel__nr_cpus(evsel));
266 } 265 }
@@ -327,13 +326,13 @@ static struct perf_evsel *nth_evsel(int n)
327 326
328 /* Assumes this only called when evsel_list does not change anymore. */ 327 /* Assumes this only called when evsel_list does not change anymore. */
329 if (!array) { 328 if (!array) {
330 list_for_each_entry(ev, &evsel_list->entries, node) 329 evlist__for_each(evsel_list, ev)
331 array_len++; 330 array_len++;
332 array = malloc(array_len * sizeof(void *)); 331 array = malloc(array_len * sizeof(void *));
333 if (!array) 332 if (!array)
334 exit(ENOMEM); 333 exit(ENOMEM);
335 j = 0; 334 j = 0;
336 list_for_each_entry(ev, &evsel_list->entries, node) 335 evlist__for_each(evsel_list, ev)
337 array[j++] = ev; 336 array[j++] = ev;
338 } 337 }
339 if (n < array_len) 338 if (n < array_len)
@@ -441,13 +440,13 @@ static void print_interval(void)
441 char prefix[64]; 440 char prefix[64];
442 441
443 if (aggr_mode == AGGR_GLOBAL) { 442 if (aggr_mode == AGGR_GLOBAL) {
444 list_for_each_entry(counter, &evsel_list->entries, node) { 443 evlist__for_each(evsel_list, counter) {
445 ps = counter->priv; 444 ps = counter->priv;
446 memset(ps->res_stats, 0, sizeof(ps->res_stats)); 445 memset(ps->res_stats, 0, sizeof(ps->res_stats));
447 read_counter_aggr(counter); 446 read_counter_aggr(counter);
448 } 447 }
449 } else { 448 } else {
450 list_for_each_entry(counter, &evsel_list->entries, node) { 449 evlist__for_each(evsel_list, counter) {
451 ps = counter->priv; 450 ps = counter->priv;
452 memset(ps->res_stats, 0, sizeof(ps->res_stats)); 451 memset(ps->res_stats, 0, sizeof(ps->res_stats));
453 read_counter(counter); 452 read_counter(counter);
@@ -461,17 +460,17 @@ static void print_interval(void)
461 if (num_print_interval == 0 && !csv_output) { 460 if (num_print_interval == 0 && !csv_output) {
462 switch (aggr_mode) { 461 switch (aggr_mode) {
463 case AGGR_SOCKET: 462 case AGGR_SOCKET:
464 fprintf(output, "# time socket cpus counts events\n"); 463 fprintf(output, "# time socket cpus counts %*s events\n", unit_width, "unit");
465 break; 464 break;
466 case AGGR_CORE: 465 case AGGR_CORE:
467 fprintf(output, "# time core cpus counts events\n"); 466 fprintf(output, "# time core cpus counts %*s events\n", unit_width, "unit");
468 break; 467 break;
469 case AGGR_NONE: 468 case AGGR_NONE:
470 fprintf(output, "# time CPU counts events\n"); 469 fprintf(output, "# time CPU counts %*s events\n", unit_width, "unit");
471 break; 470 break;
472 case AGGR_GLOBAL: 471 case AGGR_GLOBAL:
473 default: 472 default:
474 fprintf(output, "# time counts events\n"); 473 fprintf(output, "# time counts %*s events\n", unit_width, "unit");
475 } 474 }
476 } 475 }
477 476
@@ -484,12 +483,12 @@ static void print_interval(void)
484 print_aggr(prefix); 483 print_aggr(prefix);
485 break; 484 break;
486 case AGGR_NONE: 485 case AGGR_NONE:
487 list_for_each_entry(counter, &evsel_list->entries, node) 486 evlist__for_each(evsel_list, counter)
488 print_counter(counter, prefix); 487 print_counter(counter, prefix);
489 break; 488 break;
490 case AGGR_GLOBAL: 489 case AGGR_GLOBAL:
491 default: 490 default:
492 list_for_each_entry(counter, &evsel_list->entries, node) 491 evlist__for_each(evsel_list, counter)
493 print_counter_aggr(counter, prefix); 492 print_counter_aggr(counter, prefix);
494 } 493 }
495 494
@@ -505,17 +504,31 @@ static void handle_initial_delay(void)
505 nthreads = thread_map__nr(evsel_list->threads); 504 nthreads = thread_map__nr(evsel_list->threads);
506 505
507 usleep(initial_delay * 1000); 506 usleep(initial_delay * 1000);
508 list_for_each_entry(counter, &evsel_list->entries, node) 507 evlist__for_each(evsel_list, counter)
509 perf_evsel__enable(counter, ncpus, nthreads); 508 perf_evsel__enable(counter, ncpus, nthreads);
510 } 509 }
511} 510}
512 511
512static volatile int workload_exec_errno;
513
514/*
515 * perf_evlist__prepare_workload will send a SIGUSR1
516 * if the fork fails, since we asked by setting its
517 * want_signal to true.
518 */
519static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *info,
520 void *ucontext __maybe_unused)
521{
522 workload_exec_errno = info->si_value.sival_int;
523}
524
513static int __run_perf_stat(int argc, const char **argv) 525static int __run_perf_stat(int argc, const char **argv)
514{ 526{
515 char msg[512]; 527 char msg[512];
516 unsigned long long t0, t1; 528 unsigned long long t0, t1;
517 struct perf_evsel *counter; 529 struct perf_evsel *counter;
518 struct timespec ts; 530 struct timespec ts;
531 size_t l;
519 int status = 0; 532 int status = 0;
520 const bool forks = (argc > 0); 533 const bool forks = (argc > 0);
521 534
@@ -528,8 +541,8 @@ static int __run_perf_stat(int argc, const char **argv)
528 } 541 }
529 542
530 if (forks) { 543 if (forks) {
531 if (perf_evlist__prepare_workload(evsel_list, &target, argv, 544 if (perf_evlist__prepare_workload(evsel_list, &target, argv, false,
532 false, false) < 0) { 545 workload_exec_failed_signal) < 0) {
533 perror("failed to prepare workload"); 546 perror("failed to prepare workload");
534 return -1; 547 return -1;
535 } 548 }
@@ -539,7 +552,7 @@ static int __run_perf_stat(int argc, const char **argv)
539 if (group) 552 if (group)
540 perf_evlist__set_leader(evsel_list); 553 perf_evlist__set_leader(evsel_list);
541 554
542 list_for_each_entry(counter, &evsel_list->entries, node) { 555 evlist__for_each(evsel_list, counter) {
543 if (create_perf_stat_counter(counter) < 0) { 556 if (create_perf_stat_counter(counter) < 0) {
544 /* 557 /*
545 * PPC returns ENXIO for HW counters until 2.6.37 558 * PPC returns ENXIO for HW counters until 2.6.37
@@ -565,6 +578,10 @@ static int __run_perf_stat(int argc, const char **argv)
565 return -1; 578 return -1;
566 } 579 }
567 counter->supported = true; 580 counter->supported = true;
581
582 l = strlen(counter->unit);
583 if (l > unit_width)
584 unit_width = l;
568 } 585 }
569 586
570 if (perf_evlist__apply_filters(evsel_list)) { 587 if (perf_evlist__apply_filters(evsel_list)) {
@@ -590,6 +607,13 @@ static int __run_perf_stat(int argc, const char **argv)
590 } 607 }
591 } 608 }
592 wait(&status); 609 wait(&status);
610
611 if (workload_exec_errno) {
612 const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg));
613 pr_err("Workload failed: %s\n", emsg);
614 return -1;
615 }
616
593 if (WIFSIGNALED(status)) 617 if (WIFSIGNALED(status))
594 psignal(WTERMSIG(status), argv[0]); 618 psignal(WTERMSIG(status), argv[0]);
595 } else { 619 } else {
@@ -606,13 +630,13 @@ static int __run_perf_stat(int argc, const char **argv)
606 update_stats(&walltime_nsecs_stats, t1 - t0); 630 update_stats(&walltime_nsecs_stats, t1 - t0);
607 631
608 if (aggr_mode == AGGR_GLOBAL) { 632 if (aggr_mode == AGGR_GLOBAL) {
609 list_for_each_entry(counter, &evsel_list->entries, node) { 633 evlist__for_each(evsel_list, counter) {
610 read_counter_aggr(counter); 634 read_counter_aggr(counter);
611 perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter), 635 perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter),
612 thread_map__nr(evsel_list->threads)); 636 thread_map__nr(evsel_list->threads));
613 } 637 }
614 } else { 638 } else {
615 list_for_each_entry(counter, &evsel_list->entries, node) { 639 evlist__for_each(evsel_list, counter) {
616 read_counter(counter); 640 read_counter(counter);
617 perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter), 1); 641 perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter), 1);
618 } 642 }
@@ -621,7 +645,7 @@ static int __run_perf_stat(int argc, const char **argv)
621 return WEXITSTATUS(status); 645 return WEXITSTATUS(status);
622} 646}
623 647
624static int run_perf_stat(int argc __maybe_unused, const char **argv) 648static int run_perf_stat(int argc, const char **argv)
625{ 649{
626 int ret; 650 int ret;
627 651
@@ -704,14 +728,25 @@ static void aggr_printout(struct perf_evsel *evsel, int id, int nr)
704static void nsec_printout(int cpu, int nr, struct perf_evsel *evsel, double avg) 728static void nsec_printout(int cpu, int nr, struct perf_evsel *evsel, double avg)
705{ 729{
706 double msecs = avg / 1e6; 730 double msecs = avg / 1e6;
707 const char *fmt = csv_output ? "%.6f%s%s" : "%18.6f%s%-25s"; 731 const char *fmt_v, *fmt_n;
708 char name[25]; 732 char name[25];
709 733
734 fmt_v = csv_output ? "%.6f%s" : "%18.6f%s";
735 fmt_n = csv_output ? "%s" : "%-25s";
736
710 aggr_printout(evsel, cpu, nr); 737 aggr_printout(evsel, cpu, nr);
711 738
712 scnprintf(name, sizeof(name), "%s%s", 739 scnprintf(name, sizeof(name), "%s%s",
713 perf_evsel__name(evsel), csv_output ? "" : " (msec)"); 740 perf_evsel__name(evsel), csv_output ? "" : " (msec)");
714 fprintf(output, fmt, msecs, csv_sep, name); 741
742 fprintf(output, fmt_v, msecs, csv_sep);
743
744 if (csv_output)
745 fprintf(output, "%s%s", evsel->unit, csv_sep);
746 else
747 fprintf(output, "%-*s%s", unit_width, evsel->unit, csv_sep);
748
749 fprintf(output, fmt_n, name);
715 750
716 if (evsel->cgrp) 751 if (evsel->cgrp)
717 fprintf(output, "%s%s", csv_sep, evsel->cgrp->name); 752 fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
@@ -908,21 +943,31 @@ static void print_ll_cache_misses(int cpu,
908static void abs_printout(int cpu, int nr, struct perf_evsel *evsel, double avg) 943static void abs_printout(int cpu, int nr, struct perf_evsel *evsel, double avg)
909{ 944{
910 double total, ratio = 0.0, total2; 945 double total, ratio = 0.0, total2;
946 double sc = evsel->scale;
911 const char *fmt; 947 const char *fmt;
912 948
913 if (csv_output) 949 if (csv_output) {
914 fmt = "%.0f%s%s"; 950 fmt = sc != 1.0 ? "%.2f%s" : "%.0f%s";
915 else if (big_num) 951 } else {
916 fmt = "%'18.0f%s%-25s"; 952 if (big_num)
917 else 953 fmt = sc != 1.0 ? "%'18.2f%s" : "%'18.0f%s";
918 fmt = "%18.0f%s%-25s"; 954 else
955 fmt = sc != 1.0 ? "%18.2f%s" : "%18.0f%s";
956 }
919 957
920 aggr_printout(evsel, cpu, nr); 958 aggr_printout(evsel, cpu, nr);
921 959
922 if (aggr_mode == AGGR_GLOBAL) 960 if (aggr_mode == AGGR_GLOBAL)
923 cpu = 0; 961 cpu = 0;
924 962
925 fprintf(output, fmt, avg, csv_sep, perf_evsel__name(evsel)); 963 fprintf(output, fmt, avg, csv_sep);
964
965 if (evsel->unit)
966 fprintf(output, "%-*s%s",
967 csv_output ? 0 : unit_width,
968 evsel->unit, csv_sep);
969
970 fprintf(output, "%-*s", csv_output ? 0 : 25, perf_evsel__name(evsel));
926 971
927 if (evsel->cgrp) 972 if (evsel->cgrp)
928 fprintf(output, "%s%s", csv_sep, evsel->cgrp->name); 973 fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
@@ -941,7 +986,10 @@ static void abs_printout(int cpu, int nr, struct perf_evsel *evsel, double avg)
941 986
942 if (total && avg) { 987 if (total && avg) {
943 ratio = total / avg; 988 ratio = total / avg;
944 fprintf(output, "\n # %5.2f stalled cycles per insn", ratio); 989 fprintf(output, "\n");
990 if (aggr_mode == AGGR_NONE)
991 fprintf(output, " ");
992 fprintf(output, " # %5.2f stalled cycles per insn", ratio);
945 } 993 }
946 994
947 } else if (perf_evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES) && 995 } else if (perf_evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES) &&
@@ -1061,6 +1109,7 @@ static void print_aggr(char *prefix)
1061{ 1109{
1062 struct perf_evsel *counter; 1110 struct perf_evsel *counter;
1063 int cpu, cpu2, s, s2, id, nr; 1111 int cpu, cpu2, s, s2, id, nr;
1112 double uval;
1064 u64 ena, run, val; 1113 u64 ena, run, val;
1065 1114
1066 if (!(aggr_map || aggr_get_id)) 1115 if (!(aggr_map || aggr_get_id))
@@ -1068,7 +1117,7 @@ static void print_aggr(char *prefix)
1068 1117
1069 for (s = 0; s < aggr_map->nr; s++) { 1118 for (s = 0; s < aggr_map->nr; s++) {
1070 id = aggr_map->map[s]; 1119 id = aggr_map->map[s];
1071 list_for_each_entry(counter, &evsel_list->entries, node) { 1120 evlist__for_each(evsel_list, counter) {
1072 val = ena = run = 0; 1121 val = ena = run = 0;
1073 nr = 0; 1122 nr = 0;
1074 for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) { 1123 for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
@@ -1087,11 +1136,17 @@ static void print_aggr(char *prefix)
1087 if (run == 0 || ena == 0) { 1136 if (run == 0 || ena == 0) {
1088 aggr_printout(counter, id, nr); 1137 aggr_printout(counter, id, nr);
1089 1138
1090 fprintf(output, "%*s%s%*s", 1139 fprintf(output, "%*s%s",
1091 csv_output ? 0 : 18, 1140 csv_output ? 0 : 18,
1092 counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED, 1141 counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
1093 csv_sep, 1142 csv_sep);
1094 csv_output ? 0 : -24, 1143
1144 fprintf(output, "%-*s%s",
1145 csv_output ? 0 : unit_width,
1146 counter->unit, csv_sep);
1147
1148 fprintf(output, "%*s",
1149 csv_output ? 0 : -25,
1095 perf_evsel__name(counter)); 1150 perf_evsel__name(counter));
1096 1151
1097 if (counter->cgrp) 1152 if (counter->cgrp)
@@ -1101,11 +1156,12 @@ static void print_aggr(char *prefix)
1101 fputc('\n', output); 1156 fputc('\n', output);
1102 continue; 1157 continue;
1103 } 1158 }
1159 uval = val * counter->scale;
1104 1160
1105 if (nsec_counter(counter)) 1161 if (nsec_counter(counter))
1106 nsec_printout(id, nr, counter, val); 1162 nsec_printout(id, nr, counter, uval);
1107 else 1163 else
1108 abs_printout(id, nr, counter, val); 1164 abs_printout(id, nr, counter, uval);
1109 1165
1110 if (!csv_output) { 1166 if (!csv_output) {
1111 print_noise(counter, 1.0); 1167 print_noise(counter, 1.0);
@@ -1128,16 +1184,21 @@ static void print_counter_aggr(struct perf_evsel *counter, char *prefix)
1128 struct perf_stat *ps = counter->priv; 1184 struct perf_stat *ps = counter->priv;
1129 double avg = avg_stats(&ps->res_stats[0]); 1185 double avg = avg_stats(&ps->res_stats[0]);
1130 int scaled = counter->counts->scaled; 1186 int scaled = counter->counts->scaled;
1187 double uval;
1131 1188
1132 if (prefix) 1189 if (prefix)
1133 fprintf(output, "%s", prefix); 1190 fprintf(output, "%s", prefix);
1134 1191
1135 if (scaled == -1) { 1192 if (scaled == -1) {
1136 fprintf(output, "%*s%s%*s", 1193 fprintf(output, "%*s%s",
1137 csv_output ? 0 : 18, 1194 csv_output ? 0 : 18,
1138 counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED, 1195 counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
1139 csv_sep, 1196 csv_sep);
1140 csv_output ? 0 : -24, 1197 fprintf(output, "%-*s%s",
1198 csv_output ? 0 : unit_width,
1199 counter->unit, csv_sep);
1200 fprintf(output, "%*s",
1201 csv_output ? 0 : -25,
1141 perf_evsel__name(counter)); 1202 perf_evsel__name(counter));
1142 1203
1143 if (counter->cgrp) 1204 if (counter->cgrp)
@@ -1147,10 +1208,12 @@ static void print_counter_aggr(struct perf_evsel *counter, char *prefix)
1147 return; 1208 return;
1148 } 1209 }
1149 1210
1211 uval = avg * counter->scale;
1212
1150 if (nsec_counter(counter)) 1213 if (nsec_counter(counter))
1151 nsec_printout(-1, 0, counter, avg); 1214 nsec_printout(-1, 0, counter, uval);
1152 else 1215 else
1153 abs_printout(-1, 0, counter, avg); 1216 abs_printout(-1, 0, counter, uval);
1154 1217
1155 print_noise(counter, avg); 1218 print_noise(counter, avg);
1156 1219
@@ -1177,6 +1240,7 @@ static void print_counter_aggr(struct perf_evsel *counter, char *prefix)
1177static void print_counter(struct perf_evsel *counter, char *prefix) 1240static void print_counter(struct perf_evsel *counter, char *prefix)
1178{ 1241{
1179 u64 ena, run, val; 1242 u64 ena, run, val;
1243 double uval;
1180 int cpu; 1244 int cpu;
1181 1245
1182 for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) { 1246 for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
@@ -1188,14 +1252,20 @@ static void print_counter(struct perf_evsel *counter, char *prefix)
1188 fprintf(output, "%s", prefix); 1252 fprintf(output, "%s", prefix);
1189 1253
1190 if (run == 0 || ena == 0) { 1254 if (run == 0 || ena == 0) {
1191 fprintf(output, "CPU%*d%s%*s%s%*s", 1255 fprintf(output, "CPU%*d%s%*s%s",
1192 csv_output ? 0 : -4, 1256 csv_output ? 0 : -4,
1193 perf_evsel__cpus(counter)->map[cpu], csv_sep, 1257 perf_evsel__cpus(counter)->map[cpu], csv_sep,
1194 csv_output ? 0 : 18, 1258 csv_output ? 0 : 18,
1195 counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED, 1259 counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
1196 csv_sep, 1260 csv_sep);
1197 csv_output ? 0 : -24, 1261
1198 perf_evsel__name(counter)); 1262 fprintf(output, "%-*s%s",
1263 csv_output ? 0 : unit_width,
1264 counter->unit, csv_sep);
1265
1266 fprintf(output, "%*s",
1267 csv_output ? 0 : -25,
1268 perf_evsel__name(counter));
1199 1269
1200 if (counter->cgrp) 1270 if (counter->cgrp)
1201 fprintf(output, "%s%s", 1271 fprintf(output, "%s%s",
@@ -1205,10 +1275,12 @@ static void print_counter(struct perf_evsel *counter, char *prefix)
1205 continue; 1275 continue;
1206 } 1276 }
1207 1277
1278 uval = val * counter->scale;
1279
1208 if (nsec_counter(counter)) 1280 if (nsec_counter(counter))
1209 nsec_printout(cpu, 0, counter, val); 1281 nsec_printout(cpu, 0, counter, uval);
1210 else 1282 else
1211 abs_printout(cpu, 0, counter, val); 1283 abs_printout(cpu, 0, counter, uval);
1212 1284
1213 if (!csv_output) { 1285 if (!csv_output) {
1214 print_noise(counter, 1.0); 1286 print_noise(counter, 1.0);
@@ -1256,11 +1328,11 @@ static void print_stat(int argc, const char **argv)
1256 print_aggr(NULL); 1328 print_aggr(NULL);
1257 break; 1329 break;
1258 case AGGR_GLOBAL: 1330 case AGGR_GLOBAL:
1259 list_for_each_entry(counter, &evsel_list->entries, node) 1331 evlist__for_each(evsel_list, counter)
1260 print_counter_aggr(counter, NULL); 1332 print_counter_aggr(counter, NULL);
1261 break; 1333 break;
1262 case AGGR_NONE: 1334 case AGGR_NONE:
1263 list_for_each_entry(counter, &evsel_list->entries, node) 1335 evlist__for_each(evsel_list, counter)
1264 print_counter(counter, NULL); 1336 print_counter(counter, NULL);
1265 break; 1337 break;
1266 default: 1338 default:
@@ -1710,14 +1782,14 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
1710 if (interval && interval < 100) { 1782 if (interval && interval < 100) {
1711 pr_err("print interval must be >= 100ms\n"); 1783 pr_err("print interval must be >= 100ms\n");
1712 parse_options_usage(stat_usage, options, "I", 1); 1784 parse_options_usage(stat_usage, options, "I", 1);
1713 goto out_free_maps; 1785 goto out;
1714 } 1786 }
1715 1787
1716 if (perf_evlist__alloc_stats(evsel_list, interval)) 1788 if (perf_evlist__alloc_stats(evsel_list, interval))
1717 goto out_free_maps; 1789 goto out;
1718 1790
1719 if (perf_stat_init_aggr_mode()) 1791 if (perf_stat_init_aggr_mode())
1720 goto out_free_maps; 1792 goto out;
1721 1793
1722 /* 1794 /*
1723 * We dont want to block the signals - that would cause 1795 * We dont want to block the signals - that would cause
@@ -1749,8 +1821,6 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
1749 print_stat(argc, argv); 1821 print_stat(argc, argv);
1750 1822
1751 perf_evlist__free_stats(evsel_list); 1823 perf_evlist__free_stats(evsel_list);
1752out_free_maps:
1753 perf_evlist__delete_maps(evsel_list);
1754out: 1824out:
1755 perf_evlist__delete(evsel_list); 1825 perf_evlist__delete(evsel_list);
1756 return status; 1826 return status;
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 41c9bde2fb67..25526d6eae59 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -41,25 +41,29 @@
41#define SUPPORT_OLD_POWER_EVENTS 1 41#define SUPPORT_OLD_POWER_EVENTS 1
42#define PWR_EVENT_EXIT -1 42#define PWR_EVENT_EXIT -1
43 43
44
45static unsigned int numcpus;
46static u64 min_freq; /* Lowest CPU frequency seen */
47static u64 max_freq; /* Highest CPU frequency seen */
48static u64 turbo_frequency;
49
50static u64 first_time, last_time;
51
52static bool power_only;
53
54
55struct per_pid; 44struct per_pid;
56struct per_pidcomm;
57
58struct cpu_sample;
59struct power_event; 45struct power_event;
60struct wake_event; 46struct wake_event;
61 47
62struct sample_wrapper; 48struct timechart {
49 struct perf_tool tool;
50 struct per_pid *all_data;
51 struct power_event *power_events;
52 struct wake_event *wake_events;
53 int proc_num;
54 unsigned int numcpus;
55 u64 min_freq, /* Lowest CPU frequency seen */
56 max_freq, /* Highest CPU frequency seen */
57 turbo_frequency,
58 first_time, last_time;
59 bool power_only,
60 tasks_only,
61 with_backtrace,
62 topology;
63};
64
65struct per_pidcomm;
66struct cpu_sample;
63 67
64/* 68/*
65 * Datastructure layout: 69 * Datastructure layout:
@@ -124,10 +128,9 @@ struct cpu_sample {
124 u64 end_time; 128 u64 end_time;
125 int type; 129 int type;
126 int cpu; 130 int cpu;
131 const char *backtrace;
127}; 132};
128 133
129static struct per_pid *all_data;
130
131#define CSTATE 1 134#define CSTATE 1
132#define PSTATE 2 135#define PSTATE 2
133 136
@@ -145,12 +148,9 @@ struct wake_event {
145 int waker; 148 int waker;
146 int wakee; 149 int wakee;
147 u64 time; 150 u64 time;
151 const char *backtrace;
148}; 152};
149 153
150static struct power_event *power_events;
151static struct wake_event *wake_events;
152
153struct process_filter;
154struct process_filter { 154struct process_filter {
155 char *name; 155 char *name;
156 int pid; 156 int pid;
@@ -160,9 +160,9 @@ struct process_filter {
160static struct process_filter *process_filter; 160static struct process_filter *process_filter;
161 161
162 162
163static struct per_pid *find_create_pid(int pid) 163static struct per_pid *find_create_pid(struct timechart *tchart, int pid)
164{ 164{
165 struct per_pid *cursor = all_data; 165 struct per_pid *cursor = tchart->all_data;
166 166
167 while (cursor) { 167 while (cursor) {
168 if (cursor->pid == pid) 168 if (cursor->pid == pid)
@@ -172,16 +172,16 @@ static struct per_pid *find_create_pid(int pid)
172 cursor = zalloc(sizeof(*cursor)); 172 cursor = zalloc(sizeof(*cursor));
173 assert(cursor != NULL); 173 assert(cursor != NULL);
174 cursor->pid = pid; 174 cursor->pid = pid;
175 cursor->next = all_data; 175 cursor->next = tchart->all_data;
176 all_data = cursor; 176 tchart->all_data = cursor;
177 return cursor; 177 return cursor;
178} 178}
179 179
180static void pid_set_comm(int pid, char *comm) 180static void pid_set_comm(struct timechart *tchart, int pid, char *comm)
181{ 181{
182 struct per_pid *p; 182 struct per_pid *p;
183 struct per_pidcomm *c; 183 struct per_pidcomm *c;
184 p = find_create_pid(pid); 184 p = find_create_pid(tchart, pid);
185 c = p->all; 185 c = p->all;
186 while (c) { 186 while (c) {
187 if (c->comm && strcmp(c->comm, comm) == 0) { 187 if (c->comm && strcmp(c->comm, comm) == 0) {
@@ -203,14 +203,14 @@ static void pid_set_comm(int pid, char *comm)
203 p->all = c; 203 p->all = c;
204} 204}
205 205
206static void pid_fork(int pid, int ppid, u64 timestamp) 206static void pid_fork(struct timechart *tchart, int pid, int ppid, u64 timestamp)
207{ 207{
208 struct per_pid *p, *pp; 208 struct per_pid *p, *pp;
209 p = find_create_pid(pid); 209 p = find_create_pid(tchart, pid);
210 pp = find_create_pid(ppid); 210 pp = find_create_pid(tchart, ppid);
211 p->ppid = ppid; 211 p->ppid = ppid;
212 if (pp->current && pp->current->comm && !p->current) 212 if (pp->current && pp->current->comm && !p->current)
213 pid_set_comm(pid, pp->current->comm); 213 pid_set_comm(tchart, pid, pp->current->comm);
214 214
215 p->start_time = timestamp; 215 p->start_time = timestamp;
216 if (p->current) { 216 if (p->current) {
@@ -219,23 +219,24 @@ static void pid_fork(int pid, int ppid, u64 timestamp)
219 } 219 }
220} 220}
221 221
222static void pid_exit(int pid, u64 timestamp) 222static void pid_exit(struct timechart *tchart, int pid, u64 timestamp)
223{ 223{
224 struct per_pid *p; 224 struct per_pid *p;
225 p = find_create_pid(pid); 225 p = find_create_pid(tchart, pid);
226 p->end_time = timestamp; 226 p->end_time = timestamp;
227 if (p->current) 227 if (p->current)
228 p->current->end_time = timestamp; 228 p->current->end_time = timestamp;
229} 229}
230 230
231static void 231static void pid_put_sample(struct timechart *tchart, int pid, int type,
232pid_put_sample(int pid, int type, unsigned int cpu, u64 start, u64 end) 232 unsigned int cpu, u64 start, u64 end,
233 const char *backtrace)
233{ 234{
234 struct per_pid *p; 235 struct per_pid *p;
235 struct per_pidcomm *c; 236 struct per_pidcomm *c;
236 struct cpu_sample *sample; 237 struct cpu_sample *sample;
237 238
238 p = find_create_pid(pid); 239 p = find_create_pid(tchart, pid);
239 c = p->current; 240 c = p->current;
240 if (!c) { 241 if (!c) {
241 c = zalloc(sizeof(*c)); 242 c = zalloc(sizeof(*c));
@@ -252,6 +253,7 @@ pid_put_sample(int pid, int type, unsigned int cpu, u64 start, u64 end)
252 sample->type = type; 253 sample->type = type;
253 sample->next = c->samples; 254 sample->next = c->samples;
254 sample->cpu = cpu; 255 sample->cpu = cpu;
256 sample->backtrace = backtrace;
255 c->samples = sample; 257 c->samples = sample;
256 258
257 if (sample->type == TYPE_RUNNING && end > start && start > 0) { 259 if (sample->type == TYPE_RUNNING && end > start && start > 0) {
@@ -272,84 +274,47 @@ static int cpus_cstate_state[MAX_CPUS];
272static u64 cpus_pstate_start_times[MAX_CPUS]; 274static u64 cpus_pstate_start_times[MAX_CPUS];
273static u64 cpus_pstate_state[MAX_CPUS]; 275static u64 cpus_pstate_state[MAX_CPUS];
274 276
275static int process_comm_event(struct perf_tool *tool __maybe_unused, 277static int process_comm_event(struct perf_tool *tool,
276 union perf_event *event, 278 union perf_event *event,
277 struct perf_sample *sample __maybe_unused, 279 struct perf_sample *sample __maybe_unused,
278 struct machine *machine __maybe_unused) 280 struct machine *machine __maybe_unused)
279{ 281{
280 pid_set_comm(event->comm.tid, event->comm.comm); 282 struct timechart *tchart = container_of(tool, struct timechart, tool);
283 pid_set_comm(tchart, event->comm.tid, event->comm.comm);
281 return 0; 284 return 0;
282} 285}
283 286
284static int process_fork_event(struct perf_tool *tool __maybe_unused, 287static int process_fork_event(struct perf_tool *tool,
285 union perf_event *event, 288 union perf_event *event,
286 struct perf_sample *sample __maybe_unused, 289 struct perf_sample *sample __maybe_unused,
287 struct machine *machine __maybe_unused) 290 struct machine *machine __maybe_unused)
288{ 291{
289 pid_fork(event->fork.pid, event->fork.ppid, event->fork.time); 292 struct timechart *tchart = container_of(tool, struct timechart, tool);
293 pid_fork(tchart, event->fork.pid, event->fork.ppid, event->fork.time);
290 return 0; 294 return 0;
291} 295}
292 296
293static int process_exit_event(struct perf_tool *tool __maybe_unused, 297static int process_exit_event(struct perf_tool *tool,
294 union perf_event *event, 298 union perf_event *event,
295 struct perf_sample *sample __maybe_unused, 299 struct perf_sample *sample __maybe_unused,
296 struct machine *machine __maybe_unused) 300 struct machine *machine __maybe_unused)
297{ 301{
298 pid_exit(event->fork.pid, event->fork.time); 302 struct timechart *tchart = container_of(tool, struct timechart, tool);
303 pid_exit(tchart, event->fork.pid, event->fork.time);
299 return 0; 304 return 0;
300} 305}
301 306
302struct trace_entry {
303 unsigned short type;
304 unsigned char flags;
305 unsigned char preempt_count;
306 int pid;
307 int lock_depth;
308};
309
310#ifdef SUPPORT_OLD_POWER_EVENTS 307#ifdef SUPPORT_OLD_POWER_EVENTS
311static int use_old_power_events; 308static int use_old_power_events;
312struct power_entry_old {
313 struct trace_entry te;
314 u64 type;
315 u64 value;
316 u64 cpu_id;
317};
318#endif 309#endif
319 310
320struct power_processor_entry {
321 struct trace_entry te;
322 u32 state;
323 u32 cpu_id;
324};
325
326#define TASK_COMM_LEN 16
327struct wakeup_entry {
328 struct trace_entry te;
329 char comm[TASK_COMM_LEN];
330 int pid;
331 int prio;
332 int success;
333};
334
335struct sched_switch {
336 struct trace_entry te;
337 char prev_comm[TASK_COMM_LEN];
338 int prev_pid;
339 int prev_prio;
340 long prev_state; /* Arjan weeps. */
341 char next_comm[TASK_COMM_LEN];
342 int next_pid;
343 int next_prio;
344};
345
346static void c_state_start(int cpu, u64 timestamp, int state) 311static void c_state_start(int cpu, u64 timestamp, int state)
347{ 312{
348 cpus_cstate_start_times[cpu] = timestamp; 313 cpus_cstate_start_times[cpu] = timestamp;
349 cpus_cstate_state[cpu] = state; 314 cpus_cstate_state[cpu] = state;
350} 315}
351 316
352static void c_state_end(int cpu, u64 timestamp) 317static void c_state_end(struct timechart *tchart, int cpu, u64 timestamp)
353{ 318{
354 struct power_event *pwr = zalloc(sizeof(*pwr)); 319 struct power_event *pwr = zalloc(sizeof(*pwr));
355 320
@@ -361,12 +326,12 @@ static void c_state_end(int cpu, u64 timestamp)
361 pwr->end_time = timestamp; 326 pwr->end_time = timestamp;
362 pwr->cpu = cpu; 327 pwr->cpu = cpu;
363 pwr->type = CSTATE; 328 pwr->type = CSTATE;
364 pwr->next = power_events; 329 pwr->next = tchart->power_events;
365 330
366 power_events = pwr; 331 tchart->power_events = pwr;
367} 332}
368 333
369static void p_state_change(int cpu, u64 timestamp, u64 new_freq) 334static void p_state_change(struct timechart *tchart, int cpu, u64 timestamp, u64 new_freq)
370{ 335{
371 struct power_event *pwr; 336 struct power_event *pwr;
372 337
@@ -382,73 +347,78 @@ static void p_state_change(int cpu, u64 timestamp, u64 new_freq)
382 pwr->end_time = timestamp; 347 pwr->end_time = timestamp;
383 pwr->cpu = cpu; 348 pwr->cpu = cpu;
384 pwr->type = PSTATE; 349 pwr->type = PSTATE;
385 pwr->next = power_events; 350 pwr->next = tchart->power_events;
386 351
387 if (!pwr->start_time) 352 if (!pwr->start_time)
388 pwr->start_time = first_time; 353 pwr->start_time = tchart->first_time;
389 354
390 power_events = pwr; 355 tchart->power_events = pwr;
391 356
392 cpus_pstate_state[cpu] = new_freq; 357 cpus_pstate_state[cpu] = new_freq;
393 cpus_pstate_start_times[cpu] = timestamp; 358 cpus_pstate_start_times[cpu] = timestamp;
394 359
395 if ((u64)new_freq > max_freq) 360 if ((u64)new_freq > tchart->max_freq)
396 max_freq = new_freq; 361 tchart->max_freq = new_freq;
397 362
398 if (new_freq < min_freq || min_freq == 0) 363 if (new_freq < tchart->min_freq || tchart->min_freq == 0)
399 min_freq = new_freq; 364 tchart->min_freq = new_freq;
400 365
401 if (new_freq == max_freq - 1000) 366 if (new_freq == tchart->max_freq - 1000)
402 turbo_frequency = max_freq; 367 tchart->turbo_frequency = tchart->max_freq;
403} 368}
404 369
405static void 370static void sched_wakeup(struct timechart *tchart, int cpu, u64 timestamp,
406sched_wakeup(int cpu, u64 timestamp, int pid, struct trace_entry *te) 371 int waker, int wakee, u8 flags, const char *backtrace)
407{ 372{
408 struct per_pid *p; 373 struct per_pid *p;
409 struct wakeup_entry *wake = (void *)te;
410 struct wake_event *we = zalloc(sizeof(*we)); 374 struct wake_event *we = zalloc(sizeof(*we));
411 375
412 if (!we) 376 if (!we)
413 return; 377 return;
414 378
415 we->time = timestamp; 379 we->time = timestamp;
416 we->waker = pid; 380 we->waker = waker;
381 we->backtrace = backtrace;
417 382
418 if ((te->flags & TRACE_FLAG_HARDIRQ) || (te->flags & TRACE_FLAG_SOFTIRQ)) 383 if ((flags & TRACE_FLAG_HARDIRQ) || (flags & TRACE_FLAG_SOFTIRQ))
419 we->waker = -1; 384 we->waker = -1;
420 385
421 we->wakee = wake->pid; 386 we->wakee = wakee;
422 we->next = wake_events; 387 we->next = tchart->wake_events;
423 wake_events = we; 388 tchart->wake_events = we;
424 p = find_create_pid(we->wakee); 389 p = find_create_pid(tchart, we->wakee);
425 390
426 if (p && p->current && p->current->state == TYPE_NONE) { 391 if (p && p->current && p->current->state == TYPE_NONE) {
427 p->current->state_since = timestamp; 392 p->current->state_since = timestamp;
428 p->current->state = TYPE_WAITING; 393 p->current->state = TYPE_WAITING;
429 } 394 }
430 if (p && p->current && p->current->state == TYPE_BLOCKED) { 395 if (p && p->current && p->current->state == TYPE_BLOCKED) {
431 pid_put_sample(p->pid, p->current->state, cpu, p->current->state_since, timestamp); 396 pid_put_sample(tchart, p->pid, p->current->state, cpu,
397 p->current->state_since, timestamp, NULL);
432 p->current->state_since = timestamp; 398 p->current->state_since = timestamp;
433 p->current->state = TYPE_WAITING; 399 p->current->state = TYPE_WAITING;
434 } 400 }
435} 401}
436 402
437static void sched_switch(int cpu, u64 timestamp, struct trace_entry *te) 403static void sched_switch(struct timechart *tchart, int cpu, u64 timestamp,
404 int prev_pid, int next_pid, u64 prev_state,
405 const char *backtrace)
438{ 406{
439 struct per_pid *p = NULL, *prev_p; 407 struct per_pid *p = NULL, *prev_p;
440 struct sched_switch *sw = (void *)te;
441 408
409 prev_p = find_create_pid(tchart, prev_pid);
442 410
443 prev_p = find_create_pid(sw->prev_pid); 411 p = find_create_pid(tchart, next_pid);
444
445 p = find_create_pid(sw->next_pid);
446 412
447 if (prev_p->current && prev_p->current->state != TYPE_NONE) 413 if (prev_p->current && prev_p->current->state != TYPE_NONE)
448 pid_put_sample(sw->prev_pid, TYPE_RUNNING, cpu, prev_p->current->state_since, timestamp); 414 pid_put_sample(tchart, prev_pid, TYPE_RUNNING, cpu,
415 prev_p->current->state_since, timestamp,
416 backtrace);
449 if (p && p->current) { 417 if (p && p->current) {
450 if (p->current->state != TYPE_NONE) 418 if (p->current->state != TYPE_NONE)
451 pid_put_sample(sw->next_pid, p->current->state, cpu, p->current->state_since, timestamp); 419 pid_put_sample(tchart, next_pid, p->current->state, cpu,
420 p->current->state_since, timestamp,
421 backtrace);
452 422
453 p->current->state_since = timestamp; 423 p->current->state_since = timestamp;
454 p->current->state = TYPE_RUNNING; 424 p->current->state = TYPE_RUNNING;
@@ -457,109 +427,211 @@ static void sched_switch(int cpu, u64 timestamp, struct trace_entry *te)
457 if (prev_p->current) { 427 if (prev_p->current) {
458 prev_p->current->state = TYPE_NONE; 428 prev_p->current->state = TYPE_NONE;
459 prev_p->current->state_since = timestamp; 429 prev_p->current->state_since = timestamp;
460 if (sw->prev_state & 2) 430 if (prev_state & 2)
461 prev_p->current->state = TYPE_BLOCKED; 431 prev_p->current->state = TYPE_BLOCKED;
462 if (sw->prev_state == 0) 432 if (prev_state == 0)
463 prev_p->current->state = TYPE_WAITING; 433 prev_p->current->state = TYPE_WAITING;
464 } 434 }
465} 435}
466 436
467typedef int (*tracepoint_handler)(struct perf_evsel *evsel, 437static const char *cat_backtrace(union perf_event *event,
468 struct perf_sample *sample); 438 struct perf_sample *sample,
439 struct machine *machine)
440{
441 struct addr_location al;
442 unsigned int i;
443 char *p = NULL;
444 size_t p_len;
445 u8 cpumode = PERF_RECORD_MISC_USER;
446 struct addr_location tal;
447 struct ip_callchain *chain = sample->callchain;
448 FILE *f = open_memstream(&p, &p_len);
449
450 if (!f) {
451 perror("open_memstream error");
452 return NULL;
453 }
454
455 if (!chain)
456 goto exit;
457
458 if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) {
459 fprintf(stderr, "problem processing %d event, skipping it.\n",
460 event->header.type);
461 goto exit;
462 }
463
464 for (i = 0; i < chain->nr; i++) {
465 u64 ip;
466
467 if (callchain_param.order == ORDER_CALLEE)
468 ip = chain->ips[i];
469 else
470 ip = chain->ips[chain->nr - i - 1];
471
472 if (ip >= PERF_CONTEXT_MAX) {
473 switch (ip) {
474 case PERF_CONTEXT_HV:
475 cpumode = PERF_RECORD_MISC_HYPERVISOR;
476 break;
477 case PERF_CONTEXT_KERNEL:
478 cpumode = PERF_RECORD_MISC_KERNEL;
479 break;
480 case PERF_CONTEXT_USER:
481 cpumode = PERF_RECORD_MISC_USER;
482 break;
483 default:
484 pr_debug("invalid callchain context: "
485 "%"PRId64"\n", (s64) ip);
486
487 /*
488 * It seems the callchain is corrupted.
489 * Discard all.
490 */
491 zfree(&p);
492 goto exit;
493 }
494 continue;
495 }
496
497 tal.filtered = false;
498 thread__find_addr_location(al.thread, machine, cpumode,
499 MAP__FUNCTION, ip, &tal);
500
501 if (tal.sym)
502 fprintf(f, "..... %016" PRIx64 " %s\n", ip,
503 tal.sym->name);
504 else
505 fprintf(f, "..... %016" PRIx64 "\n", ip);
506 }
507
508exit:
509 fclose(f);
510
511 return p;
512}
513
514typedef int (*tracepoint_handler)(struct timechart *tchart,
515 struct perf_evsel *evsel,
516 struct perf_sample *sample,
517 const char *backtrace);
469 518
470static int process_sample_event(struct perf_tool *tool __maybe_unused, 519static int process_sample_event(struct perf_tool *tool,
471 union perf_event *event __maybe_unused, 520 union perf_event *event,
472 struct perf_sample *sample, 521 struct perf_sample *sample,
473 struct perf_evsel *evsel, 522 struct perf_evsel *evsel,
474 struct machine *machine __maybe_unused) 523 struct machine *machine)
475{ 524{
525 struct timechart *tchart = container_of(tool, struct timechart, tool);
526
476 if (evsel->attr.sample_type & PERF_SAMPLE_TIME) { 527 if (evsel->attr.sample_type & PERF_SAMPLE_TIME) {
477 if (!first_time || first_time > sample->time) 528 if (!tchart->first_time || tchart->first_time > sample->time)
478 first_time = sample->time; 529 tchart->first_time = sample->time;
479 if (last_time < sample->time) 530 if (tchart->last_time < sample->time)
480 last_time = sample->time; 531 tchart->last_time = sample->time;
481 } 532 }
482 533
483 if (sample->cpu > numcpus)
484 numcpus = sample->cpu;
485
486 if (evsel->handler != NULL) { 534 if (evsel->handler != NULL) {
487 tracepoint_handler f = evsel->handler; 535 tracepoint_handler f = evsel->handler;
488 return f(evsel, sample); 536 return f(tchart, evsel, sample,
537 cat_backtrace(event, sample, machine));
489 } 538 }
490 539
491 return 0; 540 return 0;
492} 541}
493 542
494static int 543static int
495process_sample_cpu_idle(struct perf_evsel *evsel __maybe_unused, 544process_sample_cpu_idle(struct timechart *tchart __maybe_unused,
496 struct perf_sample *sample) 545 struct perf_evsel *evsel,
546 struct perf_sample *sample,
547 const char *backtrace __maybe_unused)
497{ 548{
498 struct power_processor_entry *ppe = sample->raw_data; 549 u32 state = perf_evsel__intval(evsel, sample, "state");
550 u32 cpu_id = perf_evsel__intval(evsel, sample, "cpu_id");
499 551
500 if (ppe->state == (u32) PWR_EVENT_EXIT) 552 if (state == (u32)PWR_EVENT_EXIT)
501 c_state_end(ppe->cpu_id, sample->time); 553 c_state_end(tchart, cpu_id, sample->time);
502 else 554 else
503 c_state_start(ppe->cpu_id, sample->time, ppe->state); 555 c_state_start(cpu_id, sample->time, state);
504 return 0; 556 return 0;
505} 557}
506 558
507static int 559static int
508process_sample_cpu_frequency(struct perf_evsel *evsel __maybe_unused, 560process_sample_cpu_frequency(struct timechart *tchart,
509 struct perf_sample *sample) 561 struct perf_evsel *evsel,
562 struct perf_sample *sample,
563 const char *backtrace __maybe_unused)
510{ 564{
511 struct power_processor_entry *ppe = sample->raw_data; 565 u32 state = perf_evsel__intval(evsel, sample, "state");
566 u32 cpu_id = perf_evsel__intval(evsel, sample, "cpu_id");
512 567
513 p_state_change(ppe->cpu_id, sample->time, ppe->state); 568 p_state_change(tchart, cpu_id, sample->time, state);
514 return 0; 569 return 0;
515} 570}
516 571
517static int 572static int
518process_sample_sched_wakeup(struct perf_evsel *evsel __maybe_unused, 573process_sample_sched_wakeup(struct timechart *tchart,
519 struct perf_sample *sample) 574 struct perf_evsel *evsel,
575 struct perf_sample *sample,
576 const char *backtrace)
520{ 577{
521 struct trace_entry *te = sample->raw_data; 578 u8 flags = perf_evsel__intval(evsel, sample, "common_flags");
579 int waker = perf_evsel__intval(evsel, sample, "common_pid");
580 int wakee = perf_evsel__intval(evsel, sample, "pid");
522 581
523 sched_wakeup(sample->cpu, sample->time, sample->pid, te); 582 sched_wakeup(tchart, sample->cpu, sample->time, waker, wakee, flags, backtrace);
524 return 0; 583 return 0;
525} 584}
526 585
527static int 586static int
528process_sample_sched_switch(struct perf_evsel *evsel __maybe_unused, 587process_sample_sched_switch(struct timechart *tchart,
529 struct perf_sample *sample) 588 struct perf_evsel *evsel,
589 struct perf_sample *sample,
590 const char *backtrace)
530{ 591{
531 struct trace_entry *te = sample->raw_data; 592 int prev_pid = perf_evsel__intval(evsel, sample, "prev_pid");
593 int next_pid = perf_evsel__intval(evsel, sample, "next_pid");
594 u64 prev_state = perf_evsel__intval(evsel, sample, "prev_state");
532 595
533 sched_switch(sample->cpu, sample->time, te); 596 sched_switch(tchart, sample->cpu, sample->time, prev_pid, next_pid,
597 prev_state, backtrace);
534 return 0; 598 return 0;
535} 599}
536 600
537#ifdef SUPPORT_OLD_POWER_EVENTS 601#ifdef SUPPORT_OLD_POWER_EVENTS
538static int 602static int
539process_sample_power_start(struct perf_evsel *evsel __maybe_unused, 603process_sample_power_start(struct timechart *tchart __maybe_unused,
540 struct perf_sample *sample) 604 struct perf_evsel *evsel,
605 struct perf_sample *sample,
606 const char *backtrace __maybe_unused)
541{ 607{
542 struct power_entry_old *peo = sample->raw_data; 608 u64 cpu_id = perf_evsel__intval(evsel, sample, "cpu_id");
609 u64 value = perf_evsel__intval(evsel, sample, "value");
543 610
544 c_state_start(peo->cpu_id, sample->time, peo->value); 611 c_state_start(cpu_id, sample->time, value);
545 return 0; 612 return 0;
546} 613}
547 614
548static int 615static int
549process_sample_power_end(struct perf_evsel *evsel __maybe_unused, 616process_sample_power_end(struct timechart *tchart,
550 struct perf_sample *sample) 617 struct perf_evsel *evsel __maybe_unused,
618 struct perf_sample *sample,
619 const char *backtrace __maybe_unused)
551{ 620{
552 c_state_end(sample->cpu, sample->time); 621 c_state_end(tchart, sample->cpu, sample->time);
553 return 0; 622 return 0;
554} 623}
555 624
556static int 625static int
557process_sample_power_frequency(struct perf_evsel *evsel __maybe_unused, 626process_sample_power_frequency(struct timechart *tchart,
558 struct perf_sample *sample) 627 struct perf_evsel *evsel,
628 struct perf_sample *sample,
629 const char *backtrace __maybe_unused)
559{ 630{
560 struct power_entry_old *peo = sample->raw_data; 631 u64 cpu_id = perf_evsel__intval(evsel, sample, "cpu_id");
632 u64 value = perf_evsel__intval(evsel, sample, "value");
561 633
562 p_state_change(peo->cpu_id, sample->time, peo->value); 634 p_state_change(tchart, cpu_id, sample->time, value);
563 return 0; 635 return 0;
564} 636}
565#endif /* SUPPORT_OLD_POWER_EVENTS */ 637#endif /* SUPPORT_OLD_POWER_EVENTS */
@@ -568,12 +640,12 @@ process_sample_power_frequency(struct perf_evsel *evsel __maybe_unused,
568 * After the last sample we need to wrap up the current C/P state 640 * After the last sample we need to wrap up the current C/P state
569 * and close out each CPU for these. 641 * and close out each CPU for these.
570 */ 642 */
571static void end_sample_processing(void) 643static void end_sample_processing(struct timechart *tchart)
572{ 644{
573 u64 cpu; 645 u64 cpu;
574 struct power_event *pwr; 646 struct power_event *pwr;
575 647
576 for (cpu = 0; cpu <= numcpus; cpu++) { 648 for (cpu = 0; cpu <= tchart->numcpus; cpu++) {
577 /* C state */ 649 /* C state */
578#if 0 650#if 0
579 pwr = zalloc(sizeof(*pwr)); 651 pwr = zalloc(sizeof(*pwr));
@@ -582,12 +654,12 @@ static void end_sample_processing(void)
582 654
583 pwr->state = cpus_cstate_state[cpu]; 655 pwr->state = cpus_cstate_state[cpu];
584 pwr->start_time = cpus_cstate_start_times[cpu]; 656 pwr->start_time = cpus_cstate_start_times[cpu];
585 pwr->end_time = last_time; 657 pwr->end_time = tchart->last_time;
586 pwr->cpu = cpu; 658 pwr->cpu = cpu;
587 pwr->type = CSTATE; 659 pwr->type = CSTATE;
588 pwr->next = power_events; 660 pwr->next = tchart->power_events;
589 661
590 power_events = pwr; 662 tchart->power_events = pwr;
591#endif 663#endif
592 /* P state */ 664 /* P state */
593 665
@@ -597,32 +669,32 @@ static void end_sample_processing(void)
597 669
598 pwr->state = cpus_pstate_state[cpu]; 670 pwr->state = cpus_pstate_state[cpu];
599 pwr->start_time = cpus_pstate_start_times[cpu]; 671 pwr->start_time = cpus_pstate_start_times[cpu];
600 pwr->end_time = last_time; 672 pwr->end_time = tchart->last_time;
601 pwr->cpu = cpu; 673 pwr->cpu = cpu;
602 pwr->type = PSTATE; 674 pwr->type = PSTATE;
603 pwr->next = power_events; 675 pwr->next = tchart->power_events;
604 676
605 if (!pwr->start_time) 677 if (!pwr->start_time)
606 pwr->start_time = first_time; 678 pwr->start_time = tchart->first_time;
607 if (!pwr->state) 679 if (!pwr->state)
608 pwr->state = min_freq; 680 pwr->state = tchart->min_freq;
609 power_events = pwr; 681 tchart->power_events = pwr;
610 } 682 }
611} 683}
612 684
613/* 685/*
614 * Sort the pid datastructure 686 * Sort the pid datastructure
615 */ 687 */
616static void sort_pids(void) 688static void sort_pids(struct timechart *tchart)
617{ 689{
618 struct per_pid *new_list, *p, *cursor, *prev; 690 struct per_pid *new_list, *p, *cursor, *prev;
619 /* sort by ppid first, then by pid, lowest to highest */ 691 /* sort by ppid first, then by pid, lowest to highest */
620 692
621 new_list = NULL; 693 new_list = NULL;
622 694
623 while (all_data) { 695 while (tchart->all_data) {
624 p = all_data; 696 p = tchart->all_data;
625 all_data = p->next; 697 tchart->all_data = p->next;
626 p->next = NULL; 698 p->next = NULL;
627 699
628 if (new_list == NULL) { 700 if (new_list == NULL) {
@@ -655,14 +727,14 @@ static void sort_pids(void)
655 prev->next = p; 727 prev->next = p;
656 } 728 }
657 } 729 }
658 all_data = new_list; 730 tchart->all_data = new_list;
659} 731}
660 732
661 733
662static void draw_c_p_states(void) 734static void draw_c_p_states(struct timechart *tchart)
663{ 735{
664 struct power_event *pwr; 736 struct power_event *pwr;
665 pwr = power_events; 737 pwr = tchart->power_events;
666 738
667 /* 739 /*
668 * two pass drawing so that the P state bars are on top of the C state blocks 740 * two pass drawing so that the P state bars are on top of the C state blocks
@@ -673,30 +745,30 @@ static void draw_c_p_states(void)
673 pwr = pwr->next; 745 pwr = pwr->next;
674 } 746 }
675 747
676 pwr = power_events; 748 pwr = tchart->power_events;
677 while (pwr) { 749 while (pwr) {
678 if (pwr->type == PSTATE) { 750 if (pwr->type == PSTATE) {
679 if (!pwr->state) 751 if (!pwr->state)
680 pwr->state = min_freq; 752 pwr->state = tchart->min_freq;
681 svg_pstate(pwr->cpu, pwr->start_time, pwr->end_time, pwr->state); 753 svg_pstate(pwr->cpu, pwr->start_time, pwr->end_time, pwr->state);
682 } 754 }
683 pwr = pwr->next; 755 pwr = pwr->next;
684 } 756 }
685} 757}
686 758
687static void draw_wakeups(void) 759static void draw_wakeups(struct timechart *tchart)
688{ 760{
689 struct wake_event *we; 761 struct wake_event *we;
690 struct per_pid *p; 762 struct per_pid *p;
691 struct per_pidcomm *c; 763 struct per_pidcomm *c;
692 764
693 we = wake_events; 765 we = tchart->wake_events;
694 while (we) { 766 while (we) {
695 int from = 0, to = 0; 767 int from = 0, to = 0;
696 char *task_from = NULL, *task_to = NULL; 768 char *task_from = NULL, *task_to = NULL;
697 769
698 /* locate the column of the waker and wakee */ 770 /* locate the column of the waker and wakee */
699 p = all_data; 771 p = tchart->all_data;
700 while (p) { 772 while (p) {
701 if (p->pid == we->waker || p->pid == we->wakee) { 773 if (p->pid == we->waker || p->pid == we->wakee) {
702 c = p->all; 774 c = p->all;
@@ -739,11 +811,12 @@ static void draw_wakeups(void)
739 } 811 }
740 812
741 if (we->waker == -1) 813 if (we->waker == -1)
742 svg_interrupt(we->time, to); 814 svg_interrupt(we->time, to, we->backtrace);
743 else if (from && to && abs(from - to) == 1) 815 else if (from && to && abs(from - to) == 1)
744 svg_wakeline(we->time, from, to); 816 svg_wakeline(we->time, from, to, we->backtrace);
745 else 817 else
746 svg_partial_wakeline(we->time, from, task_from, to, task_to); 818 svg_partial_wakeline(we->time, from, task_from, to,
819 task_to, we->backtrace);
747 we = we->next; 820 we = we->next;
748 821
749 free(task_from); 822 free(task_from);
@@ -751,19 +824,25 @@ static void draw_wakeups(void)
751 } 824 }
752} 825}
753 826
754static void draw_cpu_usage(void) 827static void draw_cpu_usage(struct timechart *tchart)
755{ 828{
756 struct per_pid *p; 829 struct per_pid *p;
757 struct per_pidcomm *c; 830 struct per_pidcomm *c;
758 struct cpu_sample *sample; 831 struct cpu_sample *sample;
759 p = all_data; 832 p = tchart->all_data;
760 while (p) { 833 while (p) {
761 c = p->all; 834 c = p->all;
762 while (c) { 835 while (c) {
763 sample = c->samples; 836 sample = c->samples;
764 while (sample) { 837 while (sample) {
765 if (sample->type == TYPE_RUNNING) 838 if (sample->type == TYPE_RUNNING) {
766 svg_process(sample->cpu, sample->start_time, sample->end_time, "sample", c->comm); 839 svg_process(sample->cpu,
840 sample->start_time,
841 sample->end_time,
842 p->pid,
843 c->comm,
844 sample->backtrace);
845 }
767 846
768 sample = sample->next; 847 sample = sample->next;
769 } 848 }
@@ -773,16 +852,16 @@ static void draw_cpu_usage(void)
773 } 852 }
774} 853}
775 854
776static void draw_process_bars(void) 855static void draw_process_bars(struct timechart *tchart)
777{ 856{
778 struct per_pid *p; 857 struct per_pid *p;
779 struct per_pidcomm *c; 858 struct per_pidcomm *c;
780 struct cpu_sample *sample; 859 struct cpu_sample *sample;
781 int Y = 0; 860 int Y = 0;
782 861
783 Y = 2 * numcpus + 2; 862 Y = 2 * tchart->numcpus + 2;
784 863
785 p = all_data; 864 p = tchart->all_data;
786 while (p) { 865 while (p) {
787 c = p->all; 866 c = p->all;
788 while (c) { 867 while (c) {
@@ -796,11 +875,20 @@ static void draw_process_bars(void)
796 sample = c->samples; 875 sample = c->samples;
797 while (sample) { 876 while (sample) {
798 if (sample->type == TYPE_RUNNING) 877 if (sample->type == TYPE_RUNNING)
799 svg_sample(Y, sample->cpu, sample->start_time, sample->end_time); 878 svg_running(Y, sample->cpu,
879 sample->start_time,
880 sample->end_time,
881 sample->backtrace);
800 if (sample->type == TYPE_BLOCKED) 882 if (sample->type == TYPE_BLOCKED)
801 svg_box(Y, sample->start_time, sample->end_time, "blocked"); 883 svg_blocked(Y, sample->cpu,
884 sample->start_time,
885 sample->end_time,
886 sample->backtrace);
802 if (sample->type == TYPE_WAITING) 887 if (sample->type == TYPE_WAITING)
803 svg_waiting(Y, sample->start_time, sample->end_time); 888 svg_waiting(Y, sample->cpu,
889 sample->start_time,
890 sample->end_time,
891 sample->backtrace);
804 sample = sample->next; 892 sample = sample->next;
805 } 893 }
806 894
@@ -853,21 +941,21 @@ static int passes_filter(struct per_pid *p, struct per_pidcomm *c)
853 return 0; 941 return 0;
854} 942}
855 943
856static int determine_display_tasks_filtered(void) 944static int determine_display_tasks_filtered(struct timechart *tchart)
857{ 945{
858 struct per_pid *p; 946 struct per_pid *p;
859 struct per_pidcomm *c; 947 struct per_pidcomm *c;
860 int count = 0; 948 int count = 0;
861 949
862 p = all_data; 950 p = tchart->all_data;
863 while (p) { 951 while (p) {
864 p->display = 0; 952 p->display = 0;
865 if (p->start_time == 1) 953 if (p->start_time == 1)
866 p->start_time = first_time; 954 p->start_time = tchart->first_time;
867 955
868 /* no exit marker, task kept running to the end */ 956 /* no exit marker, task kept running to the end */
869 if (p->end_time == 0) 957 if (p->end_time == 0)
870 p->end_time = last_time; 958 p->end_time = tchart->last_time;
871 959
872 c = p->all; 960 c = p->all;
873 961
@@ -875,7 +963,7 @@ static int determine_display_tasks_filtered(void)
875 c->display = 0; 963 c->display = 0;
876 964
877 if (c->start_time == 1) 965 if (c->start_time == 1)
878 c->start_time = first_time; 966 c->start_time = tchart->first_time;
879 967
880 if (passes_filter(p, c)) { 968 if (passes_filter(p, c)) {
881 c->display = 1; 969 c->display = 1;
@@ -884,7 +972,7 @@ static int determine_display_tasks_filtered(void)
884 } 972 }
885 973
886 if (c->end_time == 0) 974 if (c->end_time == 0)
887 c->end_time = last_time; 975 c->end_time = tchart->last_time;
888 976
889 c = c->next; 977 c = c->next;
890 } 978 }
@@ -893,25 +981,25 @@ static int determine_display_tasks_filtered(void)
893 return count; 981 return count;
894} 982}
895 983
896static int determine_display_tasks(u64 threshold) 984static int determine_display_tasks(struct timechart *tchart, u64 threshold)
897{ 985{
898 struct per_pid *p; 986 struct per_pid *p;
899 struct per_pidcomm *c; 987 struct per_pidcomm *c;
900 int count = 0; 988 int count = 0;
901 989
902 if (process_filter) 990 if (process_filter)
903 return determine_display_tasks_filtered(); 991 return determine_display_tasks_filtered(tchart);
904 992
905 p = all_data; 993 p = tchart->all_data;
906 while (p) { 994 while (p) {
907 p->display = 0; 995 p->display = 0;
908 if (p->start_time == 1) 996 if (p->start_time == 1)
909 p->start_time = first_time; 997 p->start_time = tchart->first_time;
910 998
911 /* no exit marker, task kept running to the end */ 999 /* no exit marker, task kept running to the end */
912 if (p->end_time == 0) 1000 if (p->end_time == 0)
913 p->end_time = last_time; 1001 p->end_time = tchart->last_time;
914 if (p->total_time >= threshold && !power_only) 1002 if (p->total_time >= threshold)
915 p->display = 1; 1003 p->display = 1;
916 1004
917 c = p->all; 1005 c = p->all;
@@ -920,15 +1008,15 @@ static int determine_display_tasks(u64 threshold)
920 c->display = 0; 1008 c->display = 0;
921 1009
922 if (c->start_time == 1) 1010 if (c->start_time == 1)
923 c->start_time = first_time; 1011 c->start_time = tchart->first_time;
924 1012
925 if (c->total_time >= threshold && !power_only) { 1013 if (c->total_time >= threshold) {
926 c->display = 1; 1014 c->display = 1;
927 count++; 1015 count++;
928 } 1016 }
929 1017
930 if (c->end_time == 0) 1018 if (c->end_time == 0)
931 c->end_time = last_time; 1019 c->end_time = tchart->last_time;
932 1020
933 c = c->next; 1021 c = c->next;
934 } 1022 }
@@ -941,45 +1029,77 @@ static int determine_display_tasks(u64 threshold)
941 1029
942#define TIME_THRESH 10000000 1030#define TIME_THRESH 10000000
943 1031
944static void write_svg_file(const char *filename) 1032static void write_svg_file(struct timechart *tchart, const char *filename)
945{ 1033{
946 u64 i; 1034 u64 i;
947 int count; 1035 int count;
1036 int thresh = TIME_THRESH;
948 1037
949 numcpus++; 1038 if (tchart->power_only)
1039 tchart->proc_num = 0;
950 1040
1041 /* We'd like to show at least proc_num tasks;
1042 * be less picky if we have fewer */
1043 do {
1044 count = determine_display_tasks(tchart, thresh);
1045 thresh /= 10;
1046 } while (!process_filter && thresh && count < tchart->proc_num);
951 1047
952 count = determine_display_tasks(TIME_THRESH); 1048 if (!tchart->proc_num)
1049 count = 0;
953 1050
954 /* We'd like to show at least 15 tasks; be less picky if we have fewer */ 1051 open_svg(filename, tchart->numcpus, count, tchart->first_time, tchart->last_time);
955 if (count < 15)
956 count = determine_display_tasks(TIME_THRESH / 10);
957
958 open_svg(filename, numcpus, count, first_time, last_time);
959 1052
960 svg_time_grid(); 1053 svg_time_grid();
961 svg_legenda(); 1054 svg_legenda();
962 1055
963 for (i = 0; i < numcpus; i++) 1056 for (i = 0; i < tchart->numcpus; i++)
964 svg_cpu_box(i, max_freq, turbo_frequency); 1057 svg_cpu_box(i, tchart->max_freq, tchart->turbo_frequency);
965 1058
966 draw_cpu_usage(); 1059 draw_cpu_usage(tchart);
967 draw_process_bars(); 1060 if (tchart->proc_num)
968 draw_c_p_states(); 1061 draw_process_bars(tchart);
969 draw_wakeups(); 1062 if (!tchart->tasks_only)
1063 draw_c_p_states(tchart);
1064 if (tchart->proc_num)
1065 draw_wakeups(tchart);
970 1066
971 svg_close(); 1067 svg_close();
972} 1068}
973 1069
974static int __cmd_timechart(const char *output_name) 1070static int process_header(struct perf_file_section *section __maybe_unused,
1071 struct perf_header *ph,
1072 int feat,
1073 int fd __maybe_unused,
1074 void *data)
1075{
1076 struct timechart *tchart = data;
1077
1078 switch (feat) {
1079 case HEADER_NRCPUS:
1080 tchart->numcpus = ph->env.nr_cpus_avail;
1081 break;
1082
1083 case HEADER_CPU_TOPOLOGY:
1084 if (!tchart->topology)
1085 break;
1086
1087 if (svg_build_topology_map(ph->env.sibling_cores,
1088 ph->env.nr_sibling_cores,
1089 ph->env.sibling_threads,
1090 ph->env.nr_sibling_threads))
1091 fprintf(stderr, "problem building topology\n");
1092 break;
1093
1094 default:
1095 break;
1096 }
1097
1098 return 0;
1099}
1100
1101static int __cmd_timechart(struct timechart *tchart, const char *output_name)
975{ 1102{
976 struct perf_tool perf_timechart = {
977 .comm = process_comm_event,
978 .fork = process_fork_event,
979 .exit = process_exit_event,
980 .sample = process_sample_event,
981 .ordered_samples = true,
982 };
983 const struct perf_evsel_str_handler power_tracepoints[] = { 1103 const struct perf_evsel_str_handler power_tracepoints[] = {
984 { "power:cpu_idle", process_sample_cpu_idle }, 1104 { "power:cpu_idle", process_sample_cpu_idle },
985 { "power:cpu_frequency", process_sample_cpu_frequency }, 1105 { "power:cpu_frequency", process_sample_cpu_frequency },
@@ -997,12 +1117,17 @@ static int __cmd_timechart(const char *output_name)
997 }; 1117 };
998 1118
999 struct perf_session *session = perf_session__new(&file, false, 1119 struct perf_session *session = perf_session__new(&file, false,
1000 &perf_timechart); 1120 &tchart->tool);
1001 int ret = -EINVAL; 1121 int ret = -EINVAL;
1002 1122
1003 if (session == NULL) 1123 if (session == NULL)
1004 return -ENOMEM; 1124 return -ENOMEM;
1005 1125
1126 (void)perf_header__process_sections(&session->header,
1127 perf_data_file__fd(session->file),
1128 tchart,
1129 process_header);
1130
1006 if (!perf_session__has_traces(session, "timechart record")) 1131 if (!perf_session__has_traces(session, "timechart record"))
1007 goto out_delete; 1132 goto out_delete;
1008 1133
@@ -1012,69 +1137,111 @@ static int __cmd_timechart(const char *output_name)
1012 goto out_delete; 1137 goto out_delete;
1013 } 1138 }
1014 1139
1015 ret = perf_session__process_events(session, &perf_timechart); 1140 ret = perf_session__process_events(session, &tchart->tool);
1016 if (ret) 1141 if (ret)
1017 goto out_delete; 1142 goto out_delete;
1018 1143
1019 end_sample_processing(); 1144 end_sample_processing(tchart);
1020 1145
1021 sort_pids(); 1146 sort_pids(tchart);
1022 1147
1023 write_svg_file(output_name); 1148 write_svg_file(tchart, output_name);
1024 1149
1025 pr_info("Written %2.1f seconds of trace to %s.\n", 1150 pr_info("Written %2.1f seconds of trace to %s.\n",
1026 (last_time - first_time) / 1000000000.0, output_name); 1151 (tchart->last_time - tchart->first_time) / 1000000000.0, output_name);
1027out_delete: 1152out_delete:
1028 perf_session__delete(session); 1153 perf_session__delete(session);
1029 return ret; 1154 return ret;
1030} 1155}
1031 1156
1032static int __cmd_record(int argc, const char **argv) 1157static int timechart__record(struct timechart *tchart, int argc, const char **argv)
1033{ 1158{
1034#ifdef SUPPORT_OLD_POWER_EVENTS 1159 unsigned int rec_argc, i, j;
1035 const char * const record_old_args[] = { 1160 const char **rec_argv;
1161 const char **p;
1162 unsigned int record_elems;
1163
1164 const char * const common_args[] = {
1036 "record", "-a", "-R", "-c", "1", 1165 "record", "-a", "-R", "-c", "1",
1166 };
1167 unsigned int common_args_nr = ARRAY_SIZE(common_args);
1168
1169 const char * const backtrace_args[] = {
1170 "-g",
1171 };
1172 unsigned int backtrace_args_no = ARRAY_SIZE(backtrace_args);
1173
1174 const char * const power_args[] = {
1175 "-e", "power:cpu_frequency",
1176 "-e", "power:cpu_idle",
1177 };
1178 unsigned int power_args_nr = ARRAY_SIZE(power_args);
1179
1180 const char * const old_power_args[] = {
1181#ifdef SUPPORT_OLD_POWER_EVENTS
1037 "-e", "power:power_start", 1182 "-e", "power:power_start",
1038 "-e", "power:power_end", 1183 "-e", "power:power_end",
1039 "-e", "power:power_frequency", 1184 "-e", "power:power_frequency",
1040 "-e", "sched:sched_wakeup",
1041 "-e", "sched:sched_switch",
1042 };
1043#endif 1185#endif
1044 const char * const record_new_args[] = { 1186 };
1045 "record", "-a", "-R", "-c", "1", 1187 unsigned int old_power_args_nr = ARRAY_SIZE(old_power_args);
1046 "-e", "power:cpu_frequency", 1188
1047 "-e", "power:cpu_idle", 1189 const char * const tasks_args[] = {
1048 "-e", "sched:sched_wakeup", 1190 "-e", "sched:sched_wakeup",
1049 "-e", "sched:sched_switch", 1191 "-e", "sched:sched_switch",
1050 }; 1192 };
1051 unsigned int rec_argc, i, j; 1193 unsigned int tasks_args_nr = ARRAY_SIZE(tasks_args);
1052 const char **rec_argv;
1053 const char * const *record_args = record_new_args;
1054 unsigned int record_elems = ARRAY_SIZE(record_new_args);
1055 1194
1056#ifdef SUPPORT_OLD_POWER_EVENTS 1195#ifdef SUPPORT_OLD_POWER_EVENTS
1057 if (!is_valid_tracepoint("power:cpu_idle") && 1196 if (!is_valid_tracepoint("power:cpu_idle") &&
1058 is_valid_tracepoint("power:power_start")) { 1197 is_valid_tracepoint("power:power_start")) {
1059 use_old_power_events = 1; 1198 use_old_power_events = 1;
1060 record_args = record_old_args; 1199 power_args_nr = 0;
1061 record_elems = ARRAY_SIZE(record_old_args); 1200 } else {
1201 old_power_args_nr = 0;
1062 } 1202 }
1063#endif 1203#endif
1064 1204
1065 rec_argc = record_elems + argc - 1; 1205 if (tchart->power_only)
1206 tasks_args_nr = 0;
1207
1208 if (tchart->tasks_only) {
1209 power_args_nr = 0;
1210 old_power_args_nr = 0;
1211 }
1212
1213 if (!tchart->with_backtrace)
1214 backtrace_args_no = 0;
1215
1216 record_elems = common_args_nr + tasks_args_nr +
1217 power_args_nr + old_power_args_nr + backtrace_args_no;
1218
1219 rec_argc = record_elems + argc;
1066 rec_argv = calloc(rec_argc + 1, sizeof(char *)); 1220 rec_argv = calloc(rec_argc + 1, sizeof(char *));
1067 1221
1068 if (rec_argv == NULL) 1222 if (rec_argv == NULL)
1069 return -ENOMEM; 1223 return -ENOMEM;
1070 1224
1071 for (i = 0; i < record_elems; i++) 1225 p = rec_argv;
1072 rec_argv[i] = strdup(record_args[i]); 1226 for (i = 0; i < common_args_nr; i++)
1227 *p++ = strdup(common_args[i]);
1228
1229 for (i = 0; i < backtrace_args_no; i++)
1230 *p++ = strdup(backtrace_args[i]);
1231
1232 for (i = 0; i < tasks_args_nr; i++)
1233 *p++ = strdup(tasks_args[i]);
1234
1235 for (i = 0; i < power_args_nr; i++)
1236 *p++ = strdup(power_args[i]);
1073 1237
1074 for (j = 1; j < (unsigned int)argc; j++, i++) 1238 for (i = 0; i < old_power_args_nr; i++)
1075 rec_argv[i] = argv[j]; 1239 *p++ = strdup(old_power_args[i]);
1076 1240
1077 return cmd_record(i, rec_argv, NULL); 1241 for (j = 1; j < (unsigned int)argc; j++)
1242 *p++ = argv[j];
1243
1244 return cmd_record(rec_argc, rec_argv, NULL);
1078} 1245}
1079 1246
1080static int 1247static int
@@ -1086,20 +1253,56 @@ parse_process(const struct option *opt __maybe_unused, const char *arg,
1086 return 0; 1253 return 0;
1087} 1254}
1088 1255
1256static int
1257parse_highlight(const struct option *opt __maybe_unused, const char *arg,
1258 int __maybe_unused unset)
1259{
1260 unsigned long duration = strtoul(arg, NULL, 0);
1261
1262 if (svg_highlight || svg_highlight_name)
1263 return -1;
1264
1265 if (duration)
1266 svg_highlight = duration;
1267 else
1268 svg_highlight_name = strdup(arg);
1269
1270 return 0;
1271}
1272
1089int cmd_timechart(int argc, const char **argv, 1273int cmd_timechart(int argc, const char **argv,
1090 const char *prefix __maybe_unused) 1274 const char *prefix __maybe_unused)
1091{ 1275{
1276 struct timechart tchart = {
1277 .tool = {
1278 .comm = process_comm_event,
1279 .fork = process_fork_event,
1280 .exit = process_exit_event,
1281 .sample = process_sample_event,
1282 .ordered_samples = true,
1283 },
1284 .proc_num = 15,
1285 };
1092 const char *output_name = "output.svg"; 1286 const char *output_name = "output.svg";
1093 const struct option options[] = { 1287 const struct option timechart_options[] = {
1094 OPT_STRING('i', "input", &input_name, "file", "input file name"), 1288 OPT_STRING('i', "input", &input_name, "file", "input file name"),
1095 OPT_STRING('o', "output", &output_name, "file", "output file name"), 1289 OPT_STRING('o', "output", &output_name, "file", "output file name"),
1096 OPT_INTEGER('w', "width", &svg_page_width, "page width"), 1290 OPT_INTEGER('w', "width", &svg_page_width, "page width"),
1097 OPT_BOOLEAN('P', "power-only", &power_only, "output power data only"), 1291 OPT_CALLBACK(0, "highlight", NULL, "duration or task name",
1292 "highlight tasks. Pass duration in ns or process name.",
1293 parse_highlight),
1294 OPT_BOOLEAN('P', "power-only", &tchart.power_only, "output power data only"),
1295 OPT_BOOLEAN('T', "tasks-only", &tchart.tasks_only,
1296 "output processes data only"),
1098 OPT_CALLBACK('p', "process", NULL, "process", 1297 OPT_CALLBACK('p', "process", NULL, "process",
1099 "process selector. Pass a pid or process name.", 1298 "process selector. Pass a pid or process name.",
1100 parse_process), 1299 parse_process),
1101 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", 1300 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
1102 "Look for files with symbols relative to this directory"), 1301 "Look for files with symbols relative to this directory"),
1302 OPT_INTEGER('n', "proc-num", &tchart.proc_num,
1303 "min. number of tasks to print"),
1304 OPT_BOOLEAN('t', "topology", &tchart.topology,
1305 "sort CPUs according to topology"),
1103 OPT_END() 1306 OPT_END()
1104 }; 1307 };
1105 const char * const timechart_usage[] = { 1308 const char * const timechart_usage[] = {
@@ -1107,17 +1310,41 @@ int cmd_timechart(int argc, const char **argv,
1107 NULL 1310 NULL
1108 }; 1311 };
1109 1312
1110 argc = parse_options(argc, argv, options, timechart_usage, 1313 const struct option record_options[] = {
1314 OPT_BOOLEAN('P', "power-only", &tchart.power_only, "output power data only"),
1315 OPT_BOOLEAN('T', "tasks-only", &tchart.tasks_only,
1316 "output processes data only"),
1317 OPT_BOOLEAN('g', "callchain", &tchart.with_backtrace, "record callchain"),
1318 OPT_END()
1319 };
1320 const char * const record_usage[] = {
1321 "perf timechart record [<options>]",
1322 NULL
1323 };
1324 argc = parse_options(argc, argv, timechart_options, timechart_usage,
1111 PARSE_OPT_STOP_AT_NON_OPTION); 1325 PARSE_OPT_STOP_AT_NON_OPTION);
1112 1326
1327 if (tchart.power_only && tchart.tasks_only) {
1328 pr_err("-P and -T options cannot be used at the same time.\n");
1329 return -1;
1330 }
1331
1113 symbol__init(); 1332 symbol__init();
1114 1333
1115 if (argc && !strncmp(argv[0], "rec", 3)) 1334 if (argc && !strncmp(argv[0], "rec", 3)) {
1116 return __cmd_record(argc, argv); 1335 argc = parse_options(argc, argv, record_options, record_usage,
1117 else if (argc) 1336 PARSE_OPT_STOP_AT_NON_OPTION);
1118 usage_with_options(timechart_usage, options); 1337
1338 if (tchart.power_only && tchart.tasks_only) {
1339 pr_err("-P and -T options cannot be used at the same time.\n");
1340 return -1;
1341 }
1342
1343 return timechart__record(&tchart, argc, argv);
1344 } else if (argc)
1345 usage_with_options(timechart_usage, timechart_options);
1119 1346
1120 setup_pager(); 1347 setup_pager();
1121 1348
1122 return __cmd_timechart(output_name); 1349 return __cmd_timechart(&tchart, output_name);
1123} 1350}
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 71e6402729a8..76cd510d34d0 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -189,21 +189,18 @@ static void perf_top__record_precise_ip(struct perf_top *top,
189 if (pthread_mutex_trylock(&notes->lock)) 189 if (pthread_mutex_trylock(&notes->lock))
190 return; 190 return;
191 191
192 if (notes->src == NULL && symbol__alloc_hist(sym) < 0) {
193 pthread_mutex_unlock(&notes->lock);
194 pr_err("Not enough memory for annotating '%s' symbol!\n",
195 sym->name);
196 sleep(1);
197 return;
198 }
199
200 ip = he->ms.map->map_ip(he->ms.map, ip); 192 ip = he->ms.map->map_ip(he->ms.map, ip);
201 err = symbol__inc_addr_samples(sym, he->ms.map, counter, ip); 193 err = hist_entry__inc_addr_samples(he, counter, ip);
202 194
203 pthread_mutex_unlock(&notes->lock); 195 pthread_mutex_unlock(&notes->lock);
204 196
205 if (err == -ERANGE && !he->ms.map->erange_warned) 197 if (err == -ERANGE && !he->ms.map->erange_warned)
206 ui__warn_map_erange(he->ms.map, sym, ip); 198 ui__warn_map_erange(he->ms.map, sym, ip);
199 else if (err == -ENOMEM) {
200 pr_err("Not enough memory for annotating '%s' symbol!\n",
201 sym->name);
202 sleep(1);
203 }
207} 204}
208 205
209static void perf_top__show_details(struct perf_top *top) 206static void perf_top__show_details(struct perf_top *top)
@@ -485,7 +482,7 @@ static bool perf_top__handle_keypress(struct perf_top *top, int c)
485 482
486 fprintf(stderr, "\nAvailable events:"); 483 fprintf(stderr, "\nAvailable events:");
487 484
488 list_for_each_entry(top->sym_evsel, &top->evlist->entries, node) 485 evlist__for_each(top->evlist, top->sym_evsel)
489 fprintf(stderr, "\n\t%d %s", top->sym_evsel->idx, perf_evsel__name(top->sym_evsel)); 486 fprintf(stderr, "\n\t%d %s", top->sym_evsel->idx, perf_evsel__name(top->sym_evsel));
490 487
491 prompt_integer(&counter, "Enter details event counter"); 488 prompt_integer(&counter, "Enter details event counter");
@@ -496,7 +493,7 @@ static bool perf_top__handle_keypress(struct perf_top *top, int c)
496 sleep(1); 493 sleep(1);
497 break; 494 break;
498 } 495 }
499 list_for_each_entry(top->sym_evsel, &top->evlist->entries, node) 496 evlist__for_each(top->evlist, top->sym_evsel)
500 if (top->sym_evsel->idx == counter) 497 if (top->sym_evsel->idx == counter)
501 break; 498 break;
502 } else 499 } else
@@ -578,7 +575,7 @@ static void *display_thread_tui(void *arg)
578 * Zooming in/out UIDs. For now juse use whatever the user passed 575 * Zooming in/out UIDs. For now juse use whatever the user passed
579 * via --uid. 576 * via --uid.
580 */ 577 */
581 list_for_each_entry(pos, &top->evlist->entries, node) 578 evlist__for_each(top->evlist, pos)
582 pos->hists.uid_filter_str = top->record_opts.target.uid_str; 579 pos->hists.uid_filter_str = top->record_opts.target.uid_str;
583 580
584 perf_evlist__tui_browse_hists(top->evlist, help, &hbt, top->min_percent, 581 perf_evlist__tui_browse_hists(top->evlist, help, &hbt, top->min_percent,
@@ -634,26 +631,9 @@ repeat:
634 return NULL; 631 return NULL;
635} 632}
636 633
637/* Tag samples to be skipped. */
638static const char *skip_symbols[] = {
639 "intel_idle",
640 "default_idle",
641 "native_safe_halt",
642 "cpu_idle",
643 "enter_idle",
644 "exit_idle",
645 "mwait_idle",
646 "mwait_idle_with_hints",
647 "poll_idle",
648 "ppc64_runlatch_off",
649 "pseries_dedicated_idle_sleep",
650 NULL
651};
652
653static int symbol_filter(struct map *map __maybe_unused, struct symbol *sym) 634static int symbol_filter(struct map *map __maybe_unused, struct symbol *sym)
654{ 635{
655 const char *name = sym->name; 636 const char *name = sym->name;
656 int i;
657 637
658 /* 638 /*
659 * ppc64 uses function descriptors and appends a '.' to the 639 * ppc64 uses function descriptors and appends a '.' to the
@@ -671,12 +651,8 @@ static int symbol_filter(struct map *map __maybe_unused, struct symbol *sym)
671 strstr(name, "_text_end")) 651 strstr(name, "_text_end"))
672 return 1; 652 return 1;
673 653
674 for (i = 0; skip_symbols[i]; i++) { 654 if (symbol__is_idle(sym))
675 if (!strcmp(skip_symbols[i], name)) { 655 sym->ignore = true;
676 sym->ignore = true;
677 break;
678 }
679 }
680 656
681 return 0; 657 return 0;
682} 658}
@@ -767,15 +743,10 @@ static void perf_event__process_sample(struct perf_tool *tool,
767 if (al.sym == NULL || !al.sym->ignore) { 743 if (al.sym == NULL || !al.sym->ignore) {
768 struct hist_entry *he; 744 struct hist_entry *he;
769 745
770 if ((sort__has_parent || symbol_conf.use_callchain) && 746 err = sample__resolve_callchain(sample, &parent, evsel, &al,
771 sample->callchain) { 747 top->max_stack);
772 err = machine__resolve_callchain(machine, evsel, 748 if (err)
773 al.thread, sample, 749 return;
774 &parent, &al,
775 top->max_stack);
776 if (err)
777 return;
778 }
779 750
780 he = perf_evsel__add_hist_entry(evsel, &al, sample); 751 he = perf_evsel__add_hist_entry(evsel, &al, sample);
781 if (he == NULL) { 752 if (he == NULL) {
@@ -783,12 +754,9 @@ static void perf_event__process_sample(struct perf_tool *tool,
783 return; 754 return;
784 } 755 }
785 756
786 if (symbol_conf.use_callchain) { 757 err = hist_entry__append_callchain(he, sample);
787 err = callchain_append(he->callchain, &callchain_cursor, 758 if (err)
788 sample->period); 759 return;
789 if (err)
790 return;
791 }
792 760
793 if (sort__has_sym) 761 if (sort__has_sym)
794 perf_top__record_precise_ip(top, he, evsel->idx, ip); 762 perf_top__record_precise_ip(top, he, evsel->idx, ip);
@@ -878,11 +846,11 @@ static int perf_top__start_counters(struct perf_top *top)
878 char msg[512]; 846 char msg[512];
879 struct perf_evsel *counter; 847 struct perf_evsel *counter;
880 struct perf_evlist *evlist = top->evlist; 848 struct perf_evlist *evlist = top->evlist;
881 struct perf_record_opts *opts = &top->record_opts; 849 struct record_opts *opts = &top->record_opts;
882 850
883 perf_evlist__config(evlist, opts); 851 perf_evlist__config(evlist, opts);
884 852
885 list_for_each_entry(counter, &evlist->entries, node) { 853 evlist__for_each(evlist, counter) {
886try_again: 854try_again:
887 if (perf_evsel__open(counter, top->evlist->cpus, 855 if (perf_evsel__open(counter, top->evlist->cpus,
888 top->evlist->threads) < 0) { 856 top->evlist->threads) < 0) {
@@ -930,7 +898,7 @@ static int perf_top__setup_sample_type(struct perf_top *top __maybe_unused)
930 898
931static int __cmd_top(struct perf_top *top) 899static int __cmd_top(struct perf_top *top)
932{ 900{
933 struct perf_record_opts *opts = &top->record_opts; 901 struct record_opts *opts = &top->record_opts;
934 pthread_t thread; 902 pthread_t thread;
935 int ret; 903 int ret;
936 904
@@ -1052,7 +1020,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1052 .max_stack = PERF_MAX_STACK_DEPTH, 1020 .max_stack = PERF_MAX_STACK_DEPTH,
1053 .sym_pcnt_filter = 5, 1021 .sym_pcnt_filter = 5,
1054 }; 1022 };
1055 struct perf_record_opts *opts = &top.record_opts; 1023 struct record_opts *opts = &top.record_opts;
1056 struct target *target = &opts->target; 1024 struct target *target = &opts->target;
1057 const struct option options[] = { 1025 const struct option options[] = {
1058 OPT_CALLBACK('e', "event", &top.evlist, "event", 1026 OPT_CALLBACK('e', "event", &top.evlist, "event",
@@ -1084,7 +1052,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1084 "dump the symbol table used for profiling"), 1052 "dump the symbol table used for profiling"),
1085 OPT_INTEGER('f', "count-filter", &top.count_filter, 1053 OPT_INTEGER('f', "count-filter", &top.count_filter,
1086 "only display functions with more events than this"), 1054 "only display functions with more events than this"),
1087 OPT_BOOLEAN('g', "group", &opts->group, 1055 OPT_BOOLEAN(0, "group", &opts->group,
1088 "put the counters into a counter group"), 1056 "put the counters into a counter group"),
1089 OPT_BOOLEAN('i', "no-inherit", &opts->no_inherit, 1057 OPT_BOOLEAN('i', "no-inherit", &opts->no_inherit,
1090 "child tasks do not inherit counters"), 1058 "child tasks do not inherit counters"),
@@ -1105,7 +1073,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1105 " abort, in_tx, transaction"), 1073 " abort, in_tx, transaction"),
1106 OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples, 1074 OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples,
1107 "Show a column with the number of samples"), 1075 "Show a column with the number of samples"),
1108 OPT_CALLBACK_NOOPT('G', NULL, &top.record_opts, 1076 OPT_CALLBACK_NOOPT('g', NULL, &top.record_opts,
1109 NULL, "enables call-graph recording", 1077 NULL, "enables call-graph recording",
1110 &callchain_opt), 1078 &callchain_opt),
1111 OPT_CALLBACK(0, "call-graph", &top.record_opts, 1079 OPT_CALLBACK(0, "call-graph", &top.record_opts,
@@ -1195,7 +1163,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1195 if (!top.evlist->nr_entries && 1163 if (!top.evlist->nr_entries &&
1196 perf_evlist__add_default(top.evlist) < 0) { 1164 perf_evlist__add_default(top.evlist) < 0) {
1197 ui__error("Not enough memory for event selector list\n"); 1165 ui__error("Not enough memory for event selector list\n");
1198 goto out_delete_maps; 1166 goto out_delete_evlist;
1199 } 1167 }
1200 1168
1201 symbol_conf.nr_events = top.evlist->nr_entries; 1169 symbol_conf.nr_events = top.evlist->nr_entries;
@@ -1203,9 +1171,9 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1203 if (top.delay_secs < 1) 1171 if (top.delay_secs < 1)
1204 top.delay_secs = 1; 1172 top.delay_secs = 1;
1205 1173
1206 if (perf_record_opts__config(opts)) { 1174 if (record_opts__config(opts)) {
1207 status = -EINVAL; 1175 status = -EINVAL;
1208 goto out_delete_maps; 1176 goto out_delete_evlist;
1209 } 1177 }
1210 1178
1211 top.sym_evsel = perf_evlist__first(top.evlist); 1179 top.sym_evsel = perf_evlist__first(top.evlist);
@@ -1230,8 +1198,6 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1230 1198
1231 status = __cmd_top(&top); 1199 status = __cmd_top(&top);
1232 1200
1233out_delete_maps:
1234 perf_evlist__delete_maps(top.evlist);
1235out_delete_evlist: 1201out_delete_evlist:
1236 perf_evlist__delete(top.evlist); 1202 perf_evlist__delete(top.evlist);
1237 1203
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 8be17fc462ba..896f27047ed6 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -11,6 +11,8 @@
11#include "util/intlist.h" 11#include "util/intlist.h"
12#include "util/thread_map.h" 12#include "util/thread_map.h"
13#include "util/stat.h" 13#include "util/stat.h"
14#include "trace-event.h"
15#include "util/parse-events.h"
14 16
15#include <libaudit.h> 17#include <libaudit.h>
16#include <stdlib.h> 18#include <stdlib.h>
@@ -144,8 +146,7 @@ static int perf_evsel__init_tp_ptr_field(struct perf_evsel *evsel,
144 146
145static void perf_evsel__delete_priv(struct perf_evsel *evsel) 147static void perf_evsel__delete_priv(struct perf_evsel *evsel)
146{ 148{
147 free(evsel->priv); 149 zfree(&evsel->priv);
148 evsel->priv = NULL;
149 perf_evsel__delete(evsel); 150 perf_evsel__delete(evsel);
150} 151}
151 152
@@ -163,8 +164,7 @@ static int perf_evsel__init_syscall_tp(struct perf_evsel *evsel, void *handler)
163 return -ENOMEM; 164 return -ENOMEM;
164 165
165out_delete: 166out_delete:
166 free(evsel->priv); 167 zfree(&evsel->priv);
167 evsel->priv = NULL;
168 return -ENOENT; 168 return -ENOENT;
169} 169}
170 170
@@ -172,6 +172,10 @@ static struct perf_evsel *perf_evsel__syscall_newtp(const char *direction, void
172{ 172{
173 struct perf_evsel *evsel = perf_evsel__newtp("raw_syscalls", direction); 173 struct perf_evsel *evsel = perf_evsel__newtp("raw_syscalls", direction);
174 174
175 /* older kernel (e.g., RHEL6) use syscalls:{enter,exit} */
176 if (evsel == NULL)
177 evsel = perf_evsel__newtp("syscalls", direction);
178
175 if (evsel) { 179 if (evsel) {
176 if (perf_evsel__init_syscall_tp(evsel, handler)) 180 if (perf_evsel__init_syscall_tp(evsel, handler))
177 goto out_delete; 181 goto out_delete;
@@ -1153,29 +1157,30 @@ struct trace {
1153 int max; 1157 int max;
1154 struct syscall *table; 1158 struct syscall *table;
1155 } syscalls; 1159 } syscalls;
1156 struct perf_record_opts opts; 1160 struct record_opts opts;
1157 struct machine *host; 1161 struct machine *host;
1158 u64 base_time; 1162 u64 base_time;
1159 bool full_time;
1160 FILE *output; 1163 FILE *output;
1161 unsigned long nr_events; 1164 unsigned long nr_events;
1162 struct strlist *ev_qualifier; 1165 struct strlist *ev_qualifier;
1163 bool not_ev_qualifier;
1164 bool live;
1165 const char *last_vfs_getname; 1166 const char *last_vfs_getname;
1166 struct intlist *tid_list; 1167 struct intlist *tid_list;
1167 struct intlist *pid_list; 1168 struct intlist *pid_list;
1169 double duration_filter;
1170 double runtime_ms;
1171 struct {
1172 u64 vfs_getname,
1173 proc_getname;
1174 } stats;
1175 bool not_ev_qualifier;
1176 bool live;
1177 bool full_time;
1168 bool sched; 1178 bool sched;
1169 bool multiple_threads; 1179 bool multiple_threads;
1170 bool summary; 1180 bool summary;
1171 bool summary_only; 1181 bool summary_only;
1172 bool show_comm; 1182 bool show_comm;
1173 bool show_tool_stats; 1183 bool show_tool_stats;
1174 double duration_filter;
1175 double runtime_ms;
1176 struct {
1177 u64 vfs_getname, proc_getname;
1178 } stats;
1179}; 1184};
1180 1185
1181static int trace__set_fd_pathname(struct thread *thread, int fd, const char *pathname) 1186static int trace__set_fd_pathname(struct thread *thread, int fd, const char *pathname)
@@ -1272,10 +1277,8 @@ static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
1272 size_t printed = syscall_arg__scnprintf_fd(bf, size, arg); 1277 size_t printed = syscall_arg__scnprintf_fd(bf, size, arg);
1273 struct thread_trace *ttrace = arg->thread->priv; 1278 struct thread_trace *ttrace = arg->thread->priv;
1274 1279
1275 if (ttrace && fd >= 0 && fd <= ttrace->paths.max) { 1280 if (ttrace && fd >= 0 && fd <= ttrace->paths.max)
1276 free(ttrace->paths.table[fd]); 1281 zfree(&ttrace->paths.table[fd]);
1277 ttrace->paths.table[fd] = NULL;
1278 }
1279 1282
1280 return printed; 1283 return printed;
1281} 1284}
@@ -1430,11 +1433,11 @@ static int trace__read_syscall_info(struct trace *trace, int id)
1430 sc->fmt = syscall_fmt__find(sc->name); 1433 sc->fmt = syscall_fmt__find(sc->name);
1431 1434
1432 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name); 1435 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name);
1433 sc->tp_format = event_format__new("syscalls", tp_name); 1436 sc->tp_format = trace_event__tp_format("syscalls", tp_name);
1434 1437
1435 if (sc->tp_format == NULL && sc->fmt && sc->fmt->alias) { 1438 if (sc->tp_format == NULL && sc->fmt && sc->fmt->alias) {
1436 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->fmt->alias); 1439 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->fmt->alias);
1437 sc->tp_format = event_format__new("syscalls", tp_name); 1440 sc->tp_format = trace_event__tp_format("syscalls", tp_name);
1438 } 1441 }
1439 1442
1440 if (sc->tp_format == NULL) 1443 if (sc->tp_format == NULL)
@@ -1764,8 +1767,10 @@ static int trace__process_sample(struct perf_tool *tool,
1764 if (!trace->full_time && trace->base_time == 0) 1767 if (!trace->full_time && trace->base_time == 0)
1765 trace->base_time = sample->time; 1768 trace->base_time = sample->time;
1766 1769
1767 if (handler) 1770 if (handler) {
1771 ++trace->nr_events;
1768 handler(trace, evsel, sample); 1772 handler(trace, evsel, sample);
1773 }
1769 1774
1770 return err; 1775 return err;
1771} 1776}
@@ -1800,10 +1805,11 @@ static int trace__record(int argc, const char **argv)
1800 "-R", 1805 "-R",
1801 "-m", "1024", 1806 "-m", "1024",
1802 "-c", "1", 1807 "-c", "1",
1803 "-e", "raw_syscalls:sys_enter,raw_syscalls:sys_exit", 1808 "-e",
1804 }; 1809 };
1805 1810
1806 rec_argc = ARRAY_SIZE(record_args) + argc; 1811 /* +1 is for the event string below */
1812 rec_argc = ARRAY_SIZE(record_args) + 1 + argc;
1807 rec_argv = calloc(rec_argc + 1, sizeof(char *)); 1813 rec_argv = calloc(rec_argc + 1, sizeof(char *));
1808 1814
1809 if (rec_argv == NULL) 1815 if (rec_argv == NULL)
@@ -1812,6 +1818,17 @@ static int trace__record(int argc, const char **argv)
1812 for (i = 0; i < ARRAY_SIZE(record_args); i++) 1818 for (i = 0; i < ARRAY_SIZE(record_args); i++)
1813 rec_argv[i] = record_args[i]; 1819 rec_argv[i] = record_args[i];
1814 1820
1821 /* event string may be different for older kernels - e.g., RHEL6 */
1822 if (is_valid_tracepoint("raw_syscalls:sys_enter"))
1823 rec_argv[i] = "raw_syscalls:sys_enter,raw_syscalls:sys_exit";
1824 else if (is_valid_tracepoint("syscalls:sys_enter"))
1825 rec_argv[i] = "syscalls:sys_enter,syscalls:sys_exit";
1826 else {
1827 pr_err("Neither raw_syscalls nor syscalls events exist.\n");
1828 return -1;
1829 }
1830 i++;
1831
1815 for (j = 0; j < (unsigned int)argc; j++, i++) 1832 for (j = 0; j < (unsigned int)argc; j++, i++)
1816 rec_argv[i] = argv[j]; 1833 rec_argv[i] = argv[j];
1817 1834
@@ -1869,7 +1886,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
1869 err = trace__symbols_init(trace, evlist); 1886 err = trace__symbols_init(trace, evlist);
1870 if (err < 0) { 1887 if (err < 0) {
1871 fprintf(trace->output, "Problems initializing symbol libraries!\n"); 1888 fprintf(trace->output, "Problems initializing symbol libraries!\n");
1872 goto out_delete_maps; 1889 goto out_delete_evlist;
1873 } 1890 }
1874 1891
1875 perf_evlist__config(evlist, &trace->opts); 1892 perf_evlist__config(evlist, &trace->opts);
@@ -1879,10 +1896,10 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
1879 1896
1880 if (forks) { 1897 if (forks) {
1881 err = perf_evlist__prepare_workload(evlist, &trace->opts.target, 1898 err = perf_evlist__prepare_workload(evlist, &trace->opts.target,
1882 argv, false, false); 1899 argv, false, NULL);
1883 if (err < 0) { 1900 if (err < 0) {
1884 fprintf(trace->output, "Couldn't run the workload!\n"); 1901 fprintf(trace->output, "Couldn't run the workload!\n");
1885 goto out_delete_maps; 1902 goto out_delete_evlist;
1886 } 1903 }
1887 } 1904 }
1888 1905
@@ -1890,10 +1907,10 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
1890 if (err < 0) 1907 if (err < 0)
1891 goto out_error_open; 1908 goto out_error_open;
1892 1909
1893 err = perf_evlist__mmap(evlist, UINT_MAX, false); 1910 err = perf_evlist__mmap(evlist, trace->opts.mmap_pages, false);
1894 if (err < 0) { 1911 if (err < 0) {
1895 fprintf(trace->output, "Couldn't mmap the events: %s\n", strerror(errno)); 1912 fprintf(trace->output, "Couldn't mmap the events: %s\n", strerror(errno));
1896 goto out_close_evlist; 1913 goto out_delete_evlist;
1897 } 1914 }
1898 1915
1899 perf_evlist__enable(evlist); 1916 perf_evlist__enable(evlist);
@@ -1977,11 +1994,6 @@ out_disable:
1977 } 1994 }
1978 } 1995 }
1979 1996
1980 perf_evlist__munmap(evlist);
1981out_close_evlist:
1982 perf_evlist__close(evlist);
1983out_delete_maps:
1984 perf_evlist__delete_maps(evlist);
1985out_delete_evlist: 1997out_delete_evlist:
1986 perf_evlist__delete(evlist); 1998 perf_evlist__delete(evlist);
1987out: 1999out:
@@ -2047,6 +2059,10 @@ static int trace__replay(struct trace *trace)
2047 2059
2048 evsel = perf_evlist__find_tracepoint_by_name(session->evlist, 2060 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2049 "raw_syscalls:sys_enter"); 2061 "raw_syscalls:sys_enter");
2062 /* older kernels have syscalls tp versus raw_syscalls */
2063 if (evsel == NULL)
2064 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2065 "syscalls:sys_enter");
2050 if (evsel == NULL) { 2066 if (evsel == NULL) {
2051 pr_err("Data file does not have raw_syscalls:sys_enter event\n"); 2067 pr_err("Data file does not have raw_syscalls:sys_enter event\n");
2052 goto out; 2068 goto out;
@@ -2060,6 +2076,9 @@ static int trace__replay(struct trace *trace)
2060 2076
2061 evsel = perf_evlist__find_tracepoint_by_name(session->evlist, 2077 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2062 "raw_syscalls:sys_exit"); 2078 "raw_syscalls:sys_exit");
2079 if (evsel == NULL)
2080 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2081 "syscalls:sys_exit");
2063 if (evsel == NULL) { 2082 if (evsel == NULL) {
2064 pr_err("Data file does not have raw_syscalls:sys_exit event\n"); 2083 pr_err("Data file does not have raw_syscalls:sys_exit event\n");
2065 goto out; 2084 goto out;
@@ -2158,7 +2177,6 @@ static int trace__fprintf_one_thread(struct thread *thread, void *priv)
2158 size_t printed = data->printed; 2177 size_t printed = data->printed;
2159 struct trace *trace = data->trace; 2178 struct trace *trace = data->trace;
2160 struct thread_trace *ttrace = thread->priv; 2179 struct thread_trace *ttrace = thread->priv;
2161 const char *color;
2162 double ratio; 2180 double ratio;
2163 2181
2164 if (ttrace == NULL) 2182 if (ttrace == NULL)
@@ -2166,17 +2184,9 @@ static int trace__fprintf_one_thread(struct thread *thread, void *priv)
2166 2184
2167 ratio = (double)ttrace->nr_events / trace->nr_events * 100.0; 2185 ratio = (double)ttrace->nr_events / trace->nr_events * 100.0;
2168 2186
2169 color = PERF_COLOR_NORMAL; 2187 printed += fprintf(fp, " %s (%d), ", thread__comm_str(thread), thread->tid);
2170 if (ratio > 50.0)
2171 color = PERF_COLOR_RED;
2172 else if (ratio > 25.0)
2173 color = PERF_COLOR_GREEN;
2174 else if (ratio > 5.0)
2175 color = PERF_COLOR_YELLOW;
2176
2177 printed += color_fprintf(fp, color, " %s (%d), ", thread__comm_str(thread), thread->tid);
2178 printed += fprintf(fp, "%lu events, ", ttrace->nr_events); 2188 printed += fprintf(fp, "%lu events, ", ttrace->nr_events);
2179 printed += color_fprintf(fp, color, "%.1f%%", ratio); 2189 printed += fprintf(fp, "%.1f%%", ratio);
2180 printed += fprintf(fp, ", %.3f msec\n", ttrace->runtime_ms); 2190 printed += fprintf(fp, ", %.3f msec\n", ttrace->runtime_ms);
2181 printed += thread__dump_stats(ttrace, trace, fp); 2191 printed += thread__dump_stats(ttrace, trace, fp);
2182 2192
@@ -2248,7 +2258,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
2248 }, 2258 },
2249 .user_freq = UINT_MAX, 2259 .user_freq = UINT_MAX,
2250 .user_interval = ULLONG_MAX, 2260 .user_interval = ULLONG_MAX,
2251 .no_delay = true, 2261 .no_buffering = true,
2252 .mmap_pages = 1024, 2262 .mmap_pages = 1024,
2253 }, 2263 },
2254 .output = stdout, 2264 .output = stdout,
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index f7d11a811c74..c48d44958172 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -1,28 +1,26 @@
1uname_M := $(shell uname -m 2>/dev/null || echo not)
2 1
3ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ 2ifeq ($(src-perf),)
4 -e s/arm.*/arm/ -e s/sa110/arm/ \ 3src-perf := $(srctree)/tools/perf
5 -e s/s390x/s390/ -e s/parisc64/parisc/ \ 4endif
6 -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \
7 -e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ )
8NO_PERF_REGS := 1
9CFLAGS := $(EXTRA_CFLAGS) $(EXTRA_WARNINGS)
10 5
11# Additional ARCH settings for x86 6ifeq ($(obj-perf),)
12ifeq ($(ARCH),i386) 7obj-perf := $(OUTPUT)
13 override ARCH := x86
14 NO_PERF_REGS := 0
15 LIBUNWIND_LIBS = -lunwind -lunwind-x86
16endif 8endif
17 9
18ifeq ($(ARCH),x86_64) 10ifneq ($(obj-perf),)
19 override ARCH := x86 11obj-perf := $(abspath $(obj-perf))/
20 IS_X86_64 := 0 12endif
21 ifeq (, $(findstring m32,$(CFLAGS))) 13
22 IS_X86_64 := $(shell echo __x86_64__ | ${CC} -E -x c - | tail -n 1) 14LIB_INCLUDE := $(srctree)/tools/lib/
23 endif 15CFLAGS := $(EXTRA_CFLAGS) $(EXTRA_WARNINGS)
16
17include $(src-perf)/config/Makefile.arch
18
19NO_PERF_REGS := 1
20
21# Additional ARCH settings for x86
22ifeq ($(ARCH),x86)
24 ifeq (${IS_X86_64}, 1) 23 ifeq (${IS_X86_64}, 1)
25 RAW_ARCH := x86_64
26 CFLAGS += -DHAVE_ARCH_X86_64_SUPPORT 24 CFLAGS += -DHAVE_ARCH_X86_64_SUPPORT
27 ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S 25 ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S
28 LIBUNWIND_LIBS = -lunwind -lunwind-x86_64 26 LIBUNWIND_LIBS = -lunwind -lunwind-x86_64
@@ -36,24 +34,31 @@ ifeq ($(ARCH),arm)
36 LIBUNWIND_LIBS = -lunwind -lunwind-arm 34 LIBUNWIND_LIBS = -lunwind -lunwind-arm
37endif 35endif
38 36
39ifeq ($(NO_PERF_REGS),0) 37ifeq ($(LIBUNWIND_LIBS),)
40 CFLAGS += -DHAVE_PERF_REGS_SUPPORT 38 NO_LIBUNWIND := 1
41endif 39else
42 40 #
43ifeq ($(src-perf),) 41 # For linking with debug library, run like:
44src-perf := $(srctree)/tools/perf 42 #
45endif 43 # make DEBUG=1 LIBUNWIND_DIR=/opt/libunwind/
44 #
45 ifdef LIBUNWIND_DIR
46 LIBUNWIND_CFLAGS = -I$(LIBUNWIND_DIR)/include
47 LIBUNWIND_LDFLAGS = -L$(LIBUNWIND_DIR)/lib
48 endif
49 LIBUNWIND_LDFLAGS += $(LIBUNWIND_LIBS)
46 50
47ifeq ($(obj-perf),) 51 # Set per-feature check compilation flags
48obj-perf := $(OUTPUT) 52 FEATURE_CHECK_CFLAGS-libunwind = $(LIBUNWIND_CFLAGS)
53 FEATURE_CHECK_LDFLAGS-libunwind = $(LIBUNWIND_LDFLAGS)
54 FEATURE_CHECK_CFLAGS-libunwind-debug-frame = $(LIBUNWIND_CFLAGS)
55 FEATURE_CHECK_LDFLAGS-libunwind-debug-frame = $(LIBUNWIND_LDFLAGS)
49endif 56endif
50 57
51ifneq ($(obj-perf),) 58ifeq ($(NO_PERF_REGS),0)
52obj-perf := $(abspath $(obj-perf))/ 59 CFLAGS += -DHAVE_PERF_REGS_SUPPORT
53endif 60endif
54 61
55LIB_INCLUDE := $(srctree)/tools/lib/
56
57# include ARCH specific config 62# include ARCH specific config
58-include $(src-perf)/arch/$(ARCH)/Makefile 63-include $(src-perf)/arch/$(ARCH)/Makefile
59 64
@@ -102,7 +107,7 @@ endif
102 107
103feature_check = $(eval $(feature_check_code)) 108feature_check = $(eval $(feature_check_code))
104define feature_check_code 109define feature_check_code
105 feature-$(1) := $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS)" LDFLAGS="$(LDFLAGS)" LIBUNWIND_LIBS="$(LIBUNWIND_LIBS)" -C config/feature-checks test-$1 >/dev/null 2>/dev/null && echo 1 || echo 0) 110 feature-$(1) := $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS) $(FEATURE_CHECK_CFLAGS-$(1))" LDFLAGS="$(LDFLAGS) $(FEATURE_CHECK_LDFLAGS-$(1))" -C config/feature-checks test-$1.bin >/dev/null 2>/dev/null && echo 1 || echo 0)
106endef 111endef
107 112
108feature_set = $(eval $(feature_set_code)) 113feature_set = $(eval $(feature_set_code))
@@ -141,16 +146,26 @@ CORE_FEATURE_TESTS = \
141 libslang \ 146 libslang \
142 libunwind \ 147 libunwind \
143 on-exit \ 148 on-exit \
144 stackprotector \
145 stackprotector-all \ 149 stackprotector-all \
146 timerfd 150 timerfd
147 151
152# Set FEATURE_CHECK_(C|LD)FLAGS-all for all CORE_FEATURE_TESTS features.
153# If in the future we need per-feature checks/flags for features not
154# mentioned in this list we need to refactor this ;-).
155set_test_all_flags = $(eval $(set_test_all_flags_code))
156define set_test_all_flags_code
157 FEATURE_CHECK_CFLAGS-all += $(FEATURE_CHECK_CFLAGS-$(1))
158 FEATURE_CHECK_LDFLAGS-all += $(FEATURE_CHECK_LDFLAGS-$(1))
159endef
160
161$(foreach feat,$(CORE_FEATURE_TESTS),$(call set_test_all_flags,$(feat)))
162
148# 163#
149# So here we detect whether test-all was rebuilt, to be able 164# So here we detect whether test-all was rebuilt, to be able
150# to skip the print-out of the long features list if the file 165# to skip the print-out of the long features list if the file
151# existed before and after it was built: 166# existed before and after it was built:
152# 167#
153ifeq ($(wildcard $(OUTPUT)config/feature-checks/test-all),) 168ifeq ($(wildcard $(OUTPUT)config/feature-checks/test-all.bin),)
154 test-all-failed := 1 169 test-all-failed := 1
155else 170else
156 test-all-failed := 0 171 test-all-failed := 0
@@ -180,7 +195,7 @@ ifeq ($(feature-all), 1)
180 # 195 #
181 $(foreach feat,$(CORE_FEATURE_TESTS),$(call feature_set,$(feat))) 196 $(foreach feat,$(CORE_FEATURE_TESTS),$(call feature_set,$(feat)))
182else 197else
183 $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS)" LDFLAGS=$(LDFLAGS) -i -j -C config/feature-checks $(CORE_FEATURE_TESTS) >/dev/null 2>&1) 198 $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS)" LDFLAGS=$(LDFLAGS) -i -j -C config/feature-checks $(addsuffix .bin,$(CORE_FEATURE_TESTS)) >/dev/null 2>&1)
184 $(foreach feat,$(CORE_FEATURE_TESTS),$(call feature_check,$(feat))) 199 $(foreach feat,$(CORE_FEATURE_TESTS),$(call feature_check,$(feat)))
185endif 200endif
186 201
@@ -209,10 +224,6 @@ ifeq ($(feature-stackprotector-all), 1)
209 CFLAGS += -fstack-protector-all 224 CFLAGS += -fstack-protector-all
210endif 225endif
211 226
212ifeq ($(feature-stackprotector), 1)
213 CFLAGS += -Wstack-protector
214endif
215
216ifeq ($(DEBUG),0) 227ifeq ($(DEBUG),0)
217 ifeq ($(feature-fortify-source), 1) 228 ifeq ($(feature-fortify-source), 1)
218 CFLAGS += -D_FORTIFY_SOURCE=2 229 CFLAGS += -D_FORTIFY_SOURCE=2
@@ -221,6 +232,7 @@ endif
221 232
222CFLAGS += -I$(src-perf)/util/include 233CFLAGS += -I$(src-perf)/util/include
223CFLAGS += -I$(src-perf)/arch/$(ARCH)/include 234CFLAGS += -I$(src-perf)/arch/$(ARCH)/include
235CFLAGS += -I$(srctree)/tools/include/
224CFLAGS += -I$(srctree)/arch/$(ARCH)/include/uapi 236CFLAGS += -I$(srctree)/arch/$(ARCH)/include/uapi
225CFLAGS += -I$(srctree)/arch/$(ARCH)/include 237CFLAGS += -I$(srctree)/arch/$(ARCH)/include
226CFLAGS += -I$(srctree)/include/uapi 238CFLAGS += -I$(srctree)/include/uapi
@@ -310,21 +322,7 @@ ifndef NO_LIBELF
310 endif # NO_DWARF 322 endif # NO_DWARF
311endif # NO_LIBELF 323endif # NO_LIBELF
312 324
313ifeq ($(LIBUNWIND_LIBS),)
314 NO_LIBUNWIND := 1
315endif
316
317ifndef NO_LIBUNWIND 325ifndef NO_LIBUNWIND
318 #
319 # For linking with debug library, run like:
320 #
321 # make DEBUG=1 LIBUNWIND_DIR=/opt/libunwind/
322 #
323 ifdef LIBUNWIND_DIR
324 LIBUNWIND_CFLAGS := -I$(LIBUNWIND_DIR)/include
325 LIBUNWIND_LDFLAGS := -L$(LIBUNWIND_DIR)/lib
326 endif
327
328 ifneq ($(feature-libunwind), 1) 326 ifneq ($(feature-libunwind), 1)
329 msg := $(warning No libunwind found, disabling post unwind support. Please install libunwind-dev[el] >= 1.1); 327 msg := $(warning No libunwind found, disabling post unwind support. Please install libunwind-dev[el] >= 1.1);
330 NO_LIBUNWIND := 1 328 NO_LIBUNWIND := 1
@@ -339,14 +337,12 @@ ifndef NO_LIBUNWIND
339 # non-ARM has no dwarf_find_debug_frame() function: 337 # non-ARM has no dwarf_find_debug_frame() function:
340 CFLAGS += -DNO_LIBUNWIND_DEBUG_FRAME 338 CFLAGS += -DNO_LIBUNWIND_DEBUG_FRAME
341 endif 339 endif
342 endif
343endif
344 340
345ifndef NO_LIBUNWIND 341 CFLAGS += -DHAVE_LIBUNWIND_SUPPORT
346 CFLAGS += -DHAVE_LIBUNWIND_SUPPORT 342 EXTLIBS += $(LIBUNWIND_LIBS)
347 EXTLIBS += $(LIBUNWIND_LIBS) 343 CFLAGS += $(LIBUNWIND_CFLAGS)
348 CFLAGS += $(LIBUNWIND_CFLAGS) 344 LDFLAGS += $(LIBUNWIND_LDFLAGS)
349 LDFLAGS += $(LIBUNWIND_LDFLAGS) 345 endif # ifneq ($(feature-libunwind), 1)
350endif 346endif
351 347
352ifndef NO_LIBAUDIT 348ifndef NO_LIBAUDIT
@@ -376,7 +372,7 @@ ifndef NO_SLANG
376endif 372endif
377 373
378ifndef NO_GTK2 374ifndef NO_GTK2
379 FLAGS_GTK2=$(CFLAGS) $(LDFLAGS) $(EXTLIBS) $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null) 375 FLAGS_GTK2=$(CFLAGS) $(LDFLAGS) $(EXTLIBS) $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null)
380 ifneq ($(feature-gtk2), 1) 376 ifneq ($(feature-gtk2), 1)
381 msg := $(warning GTK2 not found, disables GTK2 support. Please install gtk2-devel or libgtk2.0-dev); 377 msg := $(warning GTK2 not found, disables GTK2 support. Please install gtk2-devel or libgtk2.0-dev);
382 NO_GTK2 := 1 378 NO_GTK2 := 1
@@ -385,8 +381,8 @@ ifndef NO_GTK2
385 GTK_CFLAGS := -DHAVE_GTK_INFO_BAR_SUPPORT 381 GTK_CFLAGS := -DHAVE_GTK_INFO_BAR_SUPPORT
386 endif 382 endif
387 CFLAGS += -DHAVE_GTK2_SUPPORT 383 CFLAGS += -DHAVE_GTK2_SUPPORT
388 GTK_CFLAGS += $(shell pkg-config --cflags gtk+-2.0 2>/dev/null) 384 GTK_CFLAGS += $(shell $(PKG_CONFIG) --cflags gtk+-2.0 2>/dev/null)
389 GTK_LIBS := $(shell pkg-config --libs gtk+-2.0 2>/dev/null) 385 GTK_LIBS := $(shell $(PKG_CONFIG) --libs gtk+-2.0 2>/dev/null)
390 EXTLIBS += -ldl 386 EXTLIBS += -ldl
391 endif 387 endif
392endif 388endif
@@ -533,7 +529,7 @@ endif
533 529
534ifndef NO_LIBNUMA 530ifndef NO_LIBNUMA
535 ifeq ($(feature-libnuma), 0) 531 ifeq ($(feature-libnuma), 0)
536 msg := $(warning No numa.h found, disables 'perf bench numa mem' benchmark, please install numa-libs-devel or libnuma-dev); 532 msg := $(warning No numa.h found, disables 'perf bench numa mem' benchmark, please install numactl-devel/libnuma-devel/libnuma-dev);
537 NO_LIBNUMA := 1 533 NO_LIBNUMA := 1
538 else 534 else
539 CFLAGS += -DHAVE_LIBNUMA_SUPPORT 535 CFLAGS += -DHAVE_LIBNUMA_SUPPORT
@@ -598,3 +594,11 @@ else
598perfexec_instdir = $(prefix)/$(perfexecdir) 594perfexec_instdir = $(prefix)/$(perfexecdir)
599endif 595endif
600perfexec_instdir_SQ = $(subst ','\'',$(perfexec_instdir)) 596perfexec_instdir_SQ = $(subst ','\'',$(perfexec_instdir))
597
598# If we install to $(HOME) we keep the traceevent default:
599# $(HOME)/.traceevent/plugins
600# Otherwise we install plugins into the global $(libdir).
601ifdef DESTDIR
602plugindir=$(libdir)/traceevent/plugins
603plugindir_SQ= $(subst ','\'',$(plugindir))
604endif
diff --git a/tools/perf/config/Makefile.arch b/tools/perf/config/Makefile.arch
new file mode 100644
index 000000000000..fef8ae922800
--- /dev/null
+++ b/tools/perf/config/Makefile.arch
@@ -0,0 +1,22 @@
1
2uname_M := $(shell uname -m 2>/dev/null || echo not)
3
4ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
5 -e s/arm.*/arm/ -e s/sa110/arm/ \
6 -e s/s390x/s390/ -e s/parisc64/parisc/ \
7 -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \
8 -e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ )
9
10# Additional ARCH settings for x86
11ifeq ($(ARCH),i386)
12 override ARCH := x86
13endif
14
15ifeq ($(ARCH),x86_64)
16 override ARCH := x86
17 IS_X86_64 := 0
18 ifeq (, $(findstring m32,$(CFLAGS)))
19 IS_X86_64 := $(shell echo __x86_64__ | ${CC} -E -x c - | tail -n 1)
20 RAW_ARCH := x86_64
21 endif
22endif
diff --git a/tools/perf/config/feature-checks/.gitignore b/tools/perf/config/feature-checks/.gitignore
new file mode 100644
index 000000000000..80f3da0c3515
--- /dev/null
+++ b/tools/perf/config/feature-checks/.gitignore
@@ -0,0 +1,2 @@
1*.d
2*.bin
diff --git a/tools/perf/config/feature-checks/Makefile b/tools/perf/config/feature-checks/Makefile
index 87e790017c69..12e551346fa6 100644
--- a/tools/perf/config/feature-checks/Makefile
+++ b/tools/perf/config/feature-checks/Makefile
@@ -1,95 +1,92 @@
1 1
2FILES= \ 2FILES= \
3 test-all \ 3 test-all.bin \
4 test-backtrace \ 4 test-backtrace.bin \
5 test-bionic \ 5 test-bionic.bin \
6 test-dwarf \ 6 test-dwarf.bin \
7 test-fortify-source \ 7 test-fortify-source.bin \
8 test-glibc \ 8 test-glibc.bin \
9 test-gtk2 \ 9 test-gtk2.bin \
10 test-gtk2-infobar \ 10 test-gtk2-infobar.bin \
11 test-hello \ 11 test-hello.bin \
12 test-libaudit \ 12 test-libaudit.bin \
13 test-libbfd \ 13 test-libbfd.bin \
14 test-liberty \ 14 test-liberty.bin \
15 test-liberty-z \ 15 test-liberty-z.bin \
16 test-cplus-demangle \ 16 test-cplus-demangle.bin \
17 test-libelf \ 17 test-libelf.bin \
18 test-libelf-getphdrnum \ 18 test-libelf-getphdrnum.bin \
19 test-libelf-mmap \ 19 test-libelf-mmap.bin \
20 test-libnuma \ 20 test-libnuma.bin \
21 test-libperl \ 21 test-libperl.bin \
22 test-libpython \ 22 test-libpython.bin \
23 test-libpython-version \ 23 test-libpython-version.bin \
24 test-libslang \ 24 test-libslang.bin \
25 test-libunwind \ 25 test-libunwind.bin \
26 test-libunwind-debug-frame \ 26 test-libunwind-debug-frame.bin \
27 test-on-exit \ 27 test-on-exit.bin \
28 test-stackprotector-all \ 28 test-stackprotector-all.bin \
29 test-stackprotector \ 29 test-timerfd.bin
30 test-timerfd 30
31 31CC := $(CROSS_COMPILE)gcc -MD
32CC := $(CC) -MD 32PKG_CONFIG := $(CROSS_COMPILE)pkg-config
33 33
34all: $(FILES) 34all: $(FILES)
35 35
36BUILD = $(CC) $(CFLAGS) $(LDFLAGS) -o $(OUTPUT)$@ $@.c 36BUILD = $(CC) $(CFLAGS) -o $(OUTPUT)$@ $(patsubst %.bin,%.c,$@) $(LDFLAGS)
37 37
38############################### 38###############################
39 39
40test-all: 40test-all.bin:
41 $(BUILD) -Werror -fstack-protector -fstack-protector-all -O2 -Werror -D_FORTIFY_SOURCE=2 -ldw -lelf -lnuma $(LIBUNWIND_LIBS) -lelf -laudit -I/usr/include/slang -lslang $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null) $(FLAGS_PERL_EMBED) $(FLAGS_PYTHON_EMBED) -DPACKAGE='"perf"' -lbfd -ldl 41 $(BUILD) -Werror -fstack-protector-all -O2 -Werror -D_FORTIFY_SOURCE=2 -ldw -lelf -lnuma -lelf -laudit -I/usr/include/slang -lslang $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null) $(FLAGS_PERL_EMBED) $(FLAGS_PYTHON_EMBED) -DPACKAGE='"perf"' -lbfd -ldl
42 42
43test-hello: 43test-hello.bin:
44 $(BUILD) 44 $(BUILD)
45 45
46test-stackprotector-all: 46test-stackprotector-all.bin:
47 $(BUILD) -Werror -fstack-protector-all 47 $(BUILD) -Werror -fstack-protector-all
48 48
49test-stackprotector: 49test-fortify-source.bin:
50 $(BUILD) -Werror -fstack-protector -Wstack-protector
51
52test-fortify-source:
53 $(BUILD) -O2 -Werror -D_FORTIFY_SOURCE=2 50 $(BUILD) -O2 -Werror -D_FORTIFY_SOURCE=2
54 51
55test-bionic: 52test-bionic.bin:
56 $(BUILD) 53 $(BUILD)
57 54
58test-libelf: 55test-libelf.bin:
59 $(BUILD) -lelf 56 $(BUILD) -lelf
60 57
61test-glibc: 58test-glibc.bin:
62 $(BUILD) 59 $(BUILD)
63 60
64test-dwarf: 61test-dwarf.bin:
65 $(BUILD) -ldw 62 $(BUILD) -ldw
66 63
67test-libelf-mmap: 64test-libelf-mmap.bin:
68 $(BUILD) -lelf 65 $(BUILD) -lelf
69 66
70test-libelf-getphdrnum: 67test-libelf-getphdrnum.bin:
71 $(BUILD) -lelf 68 $(BUILD) -lelf
72 69
73test-libnuma: 70test-libnuma.bin:
74 $(BUILD) -lnuma 71 $(BUILD) -lnuma
75 72
76test-libunwind: 73test-libunwind.bin:
77 $(BUILD) $(LIBUNWIND_LIBS) -lelf 74 $(BUILD) -lelf
78 75
79test-libunwind-debug-frame: 76test-libunwind-debug-frame.bin:
80 $(BUILD) $(LIBUNWIND_LIBS) -lelf 77 $(BUILD) -lelf
81 78
82test-libaudit: 79test-libaudit.bin:
83 $(BUILD) -laudit 80 $(BUILD) -laudit
84 81
85test-libslang: 82test-libslang.bin:
86 $(BUILD) -I/usr/include/slang -lslang 83 $(BUILD) -I/usr/include/slang -lslang
87 84
88test-gtk2: 85test-gtk2.bin:
89 $(BUILD) $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null) 86 $(BUILD) $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null)
90 87
91test-gtk2-infobar: 88test-gtk2-infobar.bin:
92 $(BUILD) $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null) 89 $(BUILD) $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null)
93 90
94grep-libs = $(filter -l%,$(1)) 91grep-libs = $(filter -l%,$(1))
95strip-libs = $(filter-out -l%,$(1)) 92strip-libs = $(filter-out -l%,$(1))
@@ -100,7 +97,7 @@ PERL_EMBED_LIBADD = $(call grep-libs,$(PERL_EMBED_LDOPTS))
100PERL_EMBED_CCOPTS = `perl -MExtUtils::Embed -e ccopts 2>/dev/null` 97PERL_EMBED_CCOPTS = `perl -MExtUtils::Embed -e ccopts 2>/dev/null`
101FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS) 98FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS)
102 99
103test-libperl: 100test-libperl.bin:
104 $(BUILD) $(FLAGS_PERL_EMBED) 101 $(BUILD) $(FLAGS_PERL_EMBED)
105 102
106override PYTHON := python 103override PYTHON := python
@@ -117,31 +114,31 @@ PYTHON_EMBED_LIBADD = $(call grep-libs,$(PYTHON_EMBED_LDOPTS))
117PYTHON_EMBED_CCOPTS = $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null) 114PYTHON_EMBED_CCOPTS = $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null)
118FLAGS_PYTHON_EMBED = $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS) 115FLAGS_PYTHON_EMBED = $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS)
119 116
120test-libpython: 117test-libpython.bin:
121 $(BUILD) $(FLAGS_PYTHON_EMBED) 118 $(BUILD) $(FLAGS_PYTHON_EMBED)
122 119
123test-libpython-version: 120test-libpython-version.bin:
124 $(BUILD) $(FLAGS_PYTHON_EMBED) 121 $(BUILD) $(FLAGS_PYTHON_EMBED)
125 122
126test-libbfd: 123test-libbfd.bin:
127 $(BUILD) -DPACKAGE='"perf"' -lbfd -ldl 124 $(BUILD) -DPACKAGE='"perf"' -lbfd -ldl
128 125
129test-liberty: 126test-liberty.bin:
130 $(CC) -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty 127 $(CC) -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty
131 128
132test-liberty-z: 129test-liberty-z.bin:
133 $(CC) -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty -lz 130 $(CC) -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty -lz
134 131
135test-cplus-demangle: 132test-cplus-demangle.bin:
136 $(BUILD) -liberty 133 $(BUILD) -liberty
137 134
138test-on-exit: 135test-on-exit.bin:
139 $(BUILD) 136 $(BUILD)
140 137
141test-backtrace: 138test-backtrace.bin:
142 $(BUILD) 139 $(BUILD)
143 140
144test-timerfd: 141test-timerfd.bin:
145 $(BUILD) 142 $(BUILD)
146 143
147-include *.d 144-include *.d
diff --git a/tools/perf/config/feature-checks/test-all.c b/tools/perf/config/feature-checks/test-all.c
index 59e7a705e146..9b8a544155bb 100644
--- a/tools/perf/config/feature-checks/test-all.c
+++ b/tools/perf/config/feature-checks/test-all.c
@@ -85,6 +85,10 @@
85# include "test-timerfd.c" 85# include "test-timerfd.c"
86#undef main 86#undef main
87 87
88#define main main_test_stackprotector_all
89# include "test-stackprotector-all.c"
90#undef main
91
88int main(int argc, char *argv[]) 92int main(int argc, char *argv[])
89{ 93{
90 main_test_libpython(); 94 main_test_libpython();
@@ -106,6 +110,7 @@ int main(int argc, char *argv[])
106 main_test_backtrace(); 110 main_test_backtrace();
107 main_test_libnuma(); 111 main_test_libnuma();
108 main_test_timerfd(); 112 main_test_timerfd();
113 main_test_stackprotector_all();
109 114
110 return 0; 115 return 0;
111} 116}
diff --git a/tools/perf/config/feature-checks/test-stackprotector.c b/tools/perf/config/feature-checks/test-stackprotector.c
deleted file mode 100644
index c9f398d87868..000000000000
--- a/tools/perf/config/feature-checks/test-stackprotector.c
+++ /dev/null
@@ -1,6 +0,0 @@
1#include <stdio.h>
2
3int main(void)
4{
5 return puts("hi");
6}
diff --git a/tools/perf/config/feature-checks/test-volatile-register-var.c b/tools/perf/config/feature-checks/test-volatile-register-var.c
deleted file mode 100644
index c9f398d87868..000000000000
--- a/tools/perf/config/feature-checks/test-volatile-register-var.c
+++ /dev/null
@@ -1,6 +0,0 @@
1#include <stdio.h>
2
3int main(void)
4{
5 return puts("hi");
6}
diff --git a/tools/perf/config/utilities.mak b/tools/perf/config/utilities.mak
index f168debc5be2..4d985e0f03f5 100644
--- a/tools/perf/config/utilities.mak
+++ b/tools/perf/config/utilities.mak
@@ -178,10 +178,3 @@ endef
178_ge_attempt = $(if $(get-executable),$(get-executable),$(_gea_warn)$(call _gea_err,$(2))) 178_ge_attempt = $(if $(get-executable),$(get-executable),$(_gea_warn)$(call _gea_err,$(2)))
179_gea_warn = $(warning The path '$(1)' is not executable.) 179_gea_warn = $(warning The path '$(1)' is not executable.)
180_gea_err = $(if $(1),$(error Please set '$(1)' appropriately)) 180_gea_err = $(if $(1),$(error Please set '$(1)' appropriately))
181
182ifneq ($(findstring $(MAKEFLAGS),s),s)
183 ifneq ($(V),1)
184 QUIET_CLEAN = @printf ' CLEAN %s\n' $1;
185 QUIET_INSTALL = @printf ' INSTALL %s\n' $1;
186 endif
187endif
diff --git a/tools/perf/bash_completion b/tools/perf/perf-completion.sh
index 62e157db2e2b..496e2abb5482 100644
--- a/tools/perf/bash_completion
+++ b/tools/perf/perf-completion.sh
@@ -1,4 +1,4 @@
1# perf completion 1# perf bash and zsh completion
2 2
3# Taken from git.git's completion script. 3# Taken from git.git's completion script.
4__my_reassemble_comp_words_by_ref() 4__my_reassemble_comp_words_by_ref()
@@ -89,37 +89,117 @@ __ltrim_colon_completions()
89 fi 89 fi
90} 90}
91 91
92type perf &>/dev/null && 92__perfcomp ()
93_perf()
94{ 93{
95 local cur words cword prev cmd 94 COMPREPLY=( $( compgen -W "$1" -- "$2" ) )
95}
96 96
97 COMPREPLY=() 97__perfcomp_colon ()
98 _get_comp_words_by_ref -n =: cur words cword prev 98{
99 __perfcomp "$1" "$2"
100 __ltrim_colon_completions $cur
101}
102
103__perf_main ()
104{
105 local cmd
99 106
100 cmd=${words[0]} 107 cmd=${words[0]}
108 COMPREPLY=()
101 109
102 # List perf subcommands or long options 110 # List perf subcommands or long options
103 if [ $cword -eq 1 ]; then 111 if [ $cword -eq 1 ]; then
104 if [[ $cur == --* ]]; then 112 if [[ $cur == --* ]]; then
105 COMPREPLY=( $( compgen -W '--help --version \ 113 __perfcomp '--help --version \
106 --exec-path --html-path --paginate --no-pager \ 114 --exec-path --html-path --paginate --no-pager \
107 --perf-dir --work-tree --debugfs-dir' -- "$cur" ) ) 115 --perf-dir --work-tree --debugfs-dir' -- "$cur"
108 else 116 else
109 cmds=$($cmd --list-cmds) 117 cmds=$($cmd --list-cmds)
110 COMPREPLY=( $( compgen -W '$cmds' -- "$cur" ) ) 118 __perfcomp "$cmds" "$cur"
111 fi 119 fi
112 # List possible events for -e option 120 # List possible events for -e option
113 elif [[ $prev == "-e" && "${words[1]}" == @(record|stat|top) ]]; then 121 elif [[ $prev == "-e" && "${words[1]}" == @(record|stat|top) ]]; then
114 evts=$($cmd list --raw-dump) 122 evts=$($cmd list --raw-dump)
115 COMPREPLY=( $( compgen -W '$evts' -- "$cur" ) ) 123 __perfcomp_colon "$evts" "$cur"
116 __ltrim_colon_completions $cur 124 # List subcommands for 'perf kvm'
125 elif [[ $prev == "kvm" ]]; then
126 subcmds="top record report diff buildid-list stat"
127 __perfcomp_colon "$subcmds" "$cur"
117 # List long option names 128 # List long option names
118 elif [[ $cur == --* ]]; then 129 elif [[ $cur == --* ]]; then
119 subcmd=${words[1]} 130 subcmd=${words[1]}
120 opts=$($cmd $subcmd --list-opts) 131 opts=$($cmd $subcmd --list-opts)
121 COMPREPLY=( $( compgen -W '$opts' -- "$cur" ) ) 132 __perfcomp "$opts" "$cur"
122 fi 133 fi
134}
135
136if [[ -n ${ZSH_VERSION-} ]]; then
137 autoload -U +X compinit && compinit
138
139 __perfcomp ()
140 {
141 emulate -L zsh
142
143 local c IFS=$' \t\n'
144 local -a array
145
146 for c in ${=1}; do
147 case $c in
148 --*=*|*.) ;;
149 *) c="$c " ;;
150 esac
151 array[${#array[@]}+1]="$c"
152 done
153
154 compset -P '*[=:]'
155 compadd -Q -S '' -a -- array && _ret=0
156 }
157
158 __perfcomp_colon ()
159 {
160 emulate -L zsh
161
162 local cur_="${2-$cur}"
163 local c IFS=$' \t\n'
164 local -a array
165
166 if [[ "$cur_" == *:* ]]; then
167 local colon_word=${cur_%"${cur_##*:}"}
168 fi
169
170 for c in ${=1}; do
171 case $c in
172 --*=*|*.) ;;
173 *) c="$c " ;;
174 esac
175 array[$#array+1]=${c#"$colon_word"}
176 done
177
178 compset -P '*[=:]'
179 compadd -Q -S '' -a -- array && _ret=0
180 }
181
182 _perf ()
183 {
184 local _ret=1 cur cword prev
185 cur=${words[CURRENT]}
186 prev=${words[CURRENT-1]}
187 let cword=CURRENT-1
188 emulate ksh -c __perf_main
189 let _ret && _default && _ret=0
190 return _ret
191 }
192
193 compdef _perf perf
194 return
195fi
196
197type perf &>/dev/null &&
198_perf()
199{
200 local cur words cword prev
201 _get_comp_words_by_ref -n =: cur words cword prev
202 __perf_main
123} && 203} &&
124 204
125complete -o bashdefault -o default -o nospace -F _perf perf 2>/dev/null \ 205complete -o bashdefault -o default -o nospace -F _perf perf 2>/dev/null \
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 8b38b4e80ec2..431798a4110d 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -13,7 +13,7 @@
13#include "util/quote.h" 13#include "util/quote.h"
14#include "util/run-command.h" 14#include "util/run-command.h"
15#include "util/parse-events.h" 15#include "util/parse-events.h"
16#include <lk/debugfs.h> 16#include <api/fs/debugfs.h>
17#include <pthread.h> 17#include <pthread.h>
18 18
19const char perf_usage_string[] = 19const char perf_usage_string[] =
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index b079304bd53d..7daa806d9050 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -132,6 +132,13 @@
132#define CPUINFO_PROC "CPU" 132#define CPUINFO_PROC "CPU"
133#endif 133#endif
134 134
135#ifdef __xtensa__
136#define mb() asm volatile("memw" ::: "memory")
137#define wmb() asm volatile("memw" ::: "memory")
138#define rmb() asm volatile("" ::: "memory")
139#define CPUINFO_PROC "core ID"
140#endif
141
135#define barrier() asm volatile ("" ::: "memory") 142#define barrier() asm volatile ("" ::: "memory")
136 143
137#ifndef cpu_relax 144#ifndef cpu_relax
@@ -247,13 +254,14 @@ enum perf_call_graph_mode {
247 CALLCHAIN_DWARF 254 CALLCHAIN_DWARF
248}; 255};
249 256
250struct perf_record_opts { 257struct record_opts {
251 struct target target; 258 struct target target;
252 int call_graph; 259 int call_graph;
253 bool group; 260 bool group;
254 bool inherit_stat; 261 bool inherit_stat;
255 bool no_delay; 262 bool no_buffering;
256 bool no_inherit; 263 bool no_inherit;
264 bool no_inherit_set;
257 bool no_samples; 265 bool no_samples;
258 bool raw_samples; 266 bool raw_samples;
259 bool sample_address; 267 bool sample_address;
@@ -268,6 +276,7 @@ struct perf_record_opts {
268 u64 user_interval; 276 u64 user_interval;
269 u16 stack_dump_size; 277 u16 stack_dump_size;
270 bool sample_transaction; 278 bool sample_transaction;
279 unsigned initial_delay;
271}; 280};
272 281
273#endif 282#endif
diff --git a/tools/perf/tests/attr/test-record-no-inherit b/tools/perf/tests/attr/test-record-no-inherit
index 9079a25cd643..44edcb2edcd5 100644
--- a/tools/perf/tests/attr/test-record-no-inherit
+++ b/tools/perf/tests/attr/test-record-no-inherit
@@ -3,5 +3,5 @@ command = record
3args = -i kill >/dev/null 2>&1 3args = -i kill >/dev/null 2>&1
4 4
5[event:base-record] 5[event:base-record]
6sample_type=259 6sample_type=263
7inherit=0 7inherit=0
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c
index 85d4919dd623..653a8fe2db95 100644
--- a/tools/perf/tests/code-reading.c
+++ b/tools/perf/tests/code-reading.c
@@ -391,7 +391,7 @@ static int do_test_code_reading(bool try_kcore)
391 struct machines machines; 391 struct machines machines;
392 struct machine *machine; 392 struct machine *machine;
393 struct thread *thread; 393 struct thread *thread;
394 struct perf_record_opts opts = { 394 struct record_opts opts = {
395 .mmap_pages = UINT_MAX, 395 .mmap_pages = UINT_MAX,
396 .user_freq = UINT_MAX, 396 .user_freq = UINT_MAX,
397 .user_interval = ULLONG_MAX, 397 .user_interval = ULLONG_MAX,
@@ -540,14 +540,11 @@ static int do_test_code_reading(bool try_kcore)
540 err = TEST_CODE_READING_OK; 540 err = TEST_CODE_READING_OK;
541out_err: 541out_err:
542 if (evlist) { 542 if (evlist) {
543 perf_evlist__munmap(evlist);
544 perf_evlist__close(evlist);
545 perf_evlist__delete(evlist); 543 perf_evlist__delete(evlist);
546 } 544 } else {
547 if (cpus)
548 cpu_map__delete(cpus); 545 cpu_map__delete(cpus);
549 if (threads)
550 thread_map__delete(threads); 546 thread_map__delete(threads);
547 }
551 machines__destroy_kernel_maps(&machines); 548 machines__destroy_kernel_maps(&machines);
552 machine__delete_threads(machine); 549 machine__delete_threads(machine);
553 machines__exit(&machines); 550 machines__exit(&machines);
diff --git a/tools/perf/tests/evsel-roundtrip-name.c b/tools/perf/tests/evsel-roundtrip-name.c
index 0197bda9c461..465cdbc345cf 100644
--- a/tools/perf/tests/evsel-roundtrip-name.c
+++ b/tools/perf/tests/evsel-roundtrip-name.c
@@ -79,7 +79,7 @@ static int __perf_evsel__name_array_test(const char *names[], int nr_names)
79 } 79 }
80 80
81 err = 0; 81 err = 0;
82 list_for_each_entry(evsel, &evlist->entries, node) { 82 evlist__for_each(evlist, evsel) {
83 if (strcmp(perf_evsel__name(evsel), names[evsel->idx])) { 83 if (strcmp(perf_evsel__name(evsel), names[evsel->idx])) {
84 --err; 84 --err;
85 pr_debug("%s != %s\n", perf_evsel__name(evsel), names[evsel->idx]); 85 pr_debug("%s != %s\n", perf_evsel__name(evsel), names[evsel->idx]);
diff --git a/tools/perf/tests/hists_link.c b/tools/perf/tests/hists_link.c
index 173bf42cc03e..2b6519e0e36f 100644
--- a/tools/perf/tests/hists_link.c
+++ b/tools/perf/tests/hists_link.c
@@ -208,7 +208,7 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine)
208 * However the second evsel also has a collapsed entry for 208 * However the second evsel also has a collapsed entry for
209 * "bash [libc] malloc" so total 9 entries will be in the tree. 209 * "bash [libc] malloc" so total 9 entries will be in the tree.
210 */ 210 */
211 list_for_each_entry(evsel, &evlist->entries, node) { 211 evlist__for_each(evlist, evsel) {
212 for (k = 0; k < ARRAY_SIZE(fake_common_samples); k++) { 212 for (k = 0; k < ARRAY_SIZE(fake_common_samples); k++) {
213 const union perf_event event = { 213 const union perf_event event = {
214 .header = { 214 .header = {
@@ -466,7 +466,7 @@ int test__hists_link(void)
466 if (err < 0) 466 if (err < 0)
467 goto out; 467 goto out;
468 468
469 list_for_each_entry(evsel, &evlist->entries, node) { 469 evlist__for_each(evlist, evsel) {
470 hists__collapse_resort(&evsel->hists, NULL); 470 hists__collapse_resort(&evsel->hists, NULL);
471 471
472 if (verbose > 2) 472 if (verbose > 2)
diff --git a/tools/perf/tests/keep-tracking.c b/tools/perf/tests/keep-tracking.c
index 376c35608534..497957f269d8 100644
--- a/tools/perf/tests/keep-tracking.c
+++ b/tools/perf/tests/keep-tracking.c
@@ -51,7 +51,7 @@ static int find_comm(struct perf_evlist *evlist, const char *comm)
51 */ 51 */
52int test__keep_tracking(void) 52int test__keep_tracking(void)
53{ 53{
54 struct perf_record_opts opts = { 54 struct record_opts opts = {
55 .mmap_pages = UINT_MAX, 55 .mmap_pages = UINT_MAX,
56 .user_freq = UINT_MAX, 56 .user_freq = UINT_MAX,
57 .user_interval = ULLONG_MAX, 57 .user_interval = ULLONG_MAX,
@@ -142,14 +142,11 @@ int test__keep_tracking(void)
142out_err: 142out_err:
143 if (evlist) { 143 if (evlist) {
144 perf_evlist__disable(evlist); 144 perf_evlist__disable(evlist);
145 perf_evlist__munmap(evlist);
146 perf_evlist__close(evlist);
147 perf_evlist__delete(evlist); 145 perf_evlist__delete(evlist);
148 } 146 } else {
149 if (cpus)
150 cpu_map__delete(cpus); 147 cpu_map__delete(cpus);
151 if (threads)
152 thread_map__delete(threads); 148 thread_map__delete(threads);
149 }
153 150
154 return err; 151 return err;
155} 152}
diff --git a/tools/perf/tests/make b/tools/perf/tests/make
index 2ca0abf1b2b6..00544b8b644b 100644
--- a/tools/perf/tests/make
+++ b/tools/perf/tests/make
@@ -1,6 +1,16 @@
1PERF := . 1PERF := .
2MK := Makefile 2MK := Makefile
3 3
4include config/Makefile.arch
5
6# FIXME looks like x86 is the only arch running tests ;-)
7# we need some IS_(32/64) flag to make this generic
8ifeq ($(IS_X86_64),1)
9lib = lib64
10else
11lib = lib
12endif
13
4has = $(shell which $1 2>/dev/null) 14has = $(shell which $1 2>/dev/null)
5 15
6# standard single make variable specified 16# standard single make variable specified
@@ -106,10 +116,36 @@ test_make_python_perf_so := test -f $(PERF)/python/perf.so
106test_make_perf_o := test -f $(PERF)/perf.o 116test_make_perf_o := test -f $(PERF)/perf.o
107test_make_util_map_o := test -f $(PERF)/util/map.o 117test_make_util_map_o := test -f $(PERF)/util/map.o
108 118
109test_make_install := test -x $$TMP_DEST/bin/perf 119define test_dest_files
110test_make_install_O := $(test_make_install) 120 for file in $(1); do \
111test_make_install_bin := $(test_make_install) 121 if [ ! -x $$TMP_DEST/$$file ]; then \
112test_make_install_bin_O := $(test_make_install) 122 echo " failed to find: $$file"; \
123 fi \
124 done
125endef
126
127installed_files_bin := bin/perf
128installed_files_bin += etc/bash_completion.d/perf
129installed_files_bin += libexec/perf-core/perf-archive
130
131installed_files_plugins := $(lib)/traceevent/plugins/plugin_cfg80211.so
132installed_files_plugins += $(lib)/traceevent/plugins/plugin_scsi.so
133installed_files_plugins += $(lib)/traceevent/plugins/plugin_xen.so
134installed_files_plugins += $(lib)/traceevent/plugins/plugin_function.so
135installed_files_plugins += $(lib)/traceevent/plugins/plugin_sched_switch.so
136installed_files_plugins += $(lib)/traceevent/plugins/plugin_mac80211.so
137installed_files_plugins += $(lib)/traceevent/plugins/plugin_kvm.so
138installed_files_plugins += $(lib)/traceevent/plugins/plugin_kmem.so
139installed_files_plugins += $(lib)/traceevent/plugins/plugin_hrtimer.so
140installed_files_plugins += $(lib)/traceevent/plugins/plugin_jbd2.so
141
142installed_files_all := $(installed_files_bin)
143installed_files_all += $(installed_files_plugins)
144
145test_make_install := $(call test_dest_files,$(installed_files_all))
146test_make_install_O := $(call test_dest_files,$(installed_files_all))
147test_make_install_bin := $(call test_dest_files,$(installed_files_bin))
148test_make_install_bin_O := $(call test_dest_files,$(installed_files_bin))
113 149
114# FIXME nothing gets installed 150# FIXME nothing gets installed
115test_make_install_man := test -f $$TMP_DEST/share/man/man1/perf.1 151test_make_install_man := test -f $$TMP_DEST/share/man/man1/perf.1
@@ -162,7 +198,7 @@ $(run):
162 cmd="cd $(PERF) && make -f $(MK) DESTDIR=$$TMP_DEST $($@)"; \ 198 cmd="cd $(PERF) && make -f $(MK) DESTDIR=$$TMP_DEST $($@)"; \
163 echo "- $@: $$cmd" && echo $$cmd > $@ && \ 199 echo "- $@: $$cmd" && echo $$cmd > $@ && \
164 ( eval $$cmd ) >> $@ 2>&1; \ 200 ( eval $$cmd ) >> $@ 2>&1; \
165 echo " test: $(call test,$@)"; \ 201 echo " test: $(call test,$@)" >> $@ 2>&1; \
166 $(call test,$@) && \ 202 $(call test,$@) && \
167 rm -f $@ \ 203 rm -f $@ \
168 rm -rf $$TMP_DEST 204 rm -rf $$TMP_DEST
@@ -174,16 +210,22 @@ $(run_O):
174 cmd="cd $(PERF) && make -f $(MK) O=$$TMP_O DESTDIR=$$TMP_DEST $($(patsubst %_O,%,$@))"; \ 210 cmd="cd $(PERF) && make -f $(MK) O=$$TMP_O DESTDIR=$$TMP_DEST $($(patsubst %_O,%,$@))"; \
175 echo "- $@: $$cmd" && echo $$cmd > $@ && \ 211 echo "- $@: $$cmd" && echo $$cmd > $@ && \
176 ( eval $$cmd ) >> $@ 2>&1 && \ 212 ( eval $$cmd ) >> $@ 2>&1 && \
177 echo " test: $(call test_O,$@)"; \ 213 echo " test: $(call test_O,$@)" >> $@ 2>&1; \
178 $(call test_O,$@) && \ 214 $(call test_O,$@) && \
179 rm -f $@ && \ 215 rm -f $@ && \
180 rm -rf $$TMP_O \ 216 rm -rf $$TMP_O \
181 rm -rf $$TMP_DEST 217 rm -rf $$TMP_DEST
182 218
183all: $(run) $(run_O) 219tarpkg:
220 @cmd="$(PERF)/tests/perf-targz-src-pkg $(PERF)"; \
221 echo "- $@: $$cmd" && echo $$cmd > $@ && \
222 ( eval $$cmd ) >> $@ 2>&1
223
224
225all: $(run) $(run_O) tarpkg
184 @echo OK 226 @echo OK
185 227
186out: $(run_O) 228out: $(run_O)
187 @echo OK 229 @echo OK
188 230
189.PHONY: all $(run) $(run_O) clean 231.PHONY: all $(run) $(run_O) tarpkg clean
diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c
index d64ab79c6d35..142263492f6f 100644
--- a/tools/perf/tests/mmap-basic.c
+++ b/tools/perf/tests/mmap-basic.c
@@ -68,7 +68,7 @@ int test__basic_mmap(void)
68 evsels[i] = perf_evsel__newtp("syscalls", name); 68 evsels[i] = perf_evsel__newtp("syscalls", name);
69 if (evsels[i] == NULL) { 69 if (evsels[i] == NULL) {
70 pr_debug("perf_evsel__new\n"); 70 pr_debug("perf_evsel__new\n");
71 goto out_free_evlist; 71 goto out_delete_evlist;
72 } 72 }
73 73
74 evsels[i]->attr.wakeup_events = 1; 74 evsels[i]->attr.wakeup_events = 1;
@@ -80,7 +80,7 @@ int test__basic_mmap(void)
80 pr_debug("failed to open counter: %s, " 80 pr_debug("failed to open counter: %s, "
81 "tweak /proc/sys/kernel/perf_event_paranoid?\n", 81 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
82 strerror(errno)); 82 strerror(errno));
83 goto out_close_fd; 83 goto out_delete_evlist;
84 } 84 }
85 85
86 nr_events[i] = 0; 86 nr_events[i] = 0;
@@ -90,7 +90,7 @@ int test__basic_mmap(void)
90 if (perf_evlist__mmap(evlist, 128, true) < 0) { 90 if (perf_evlist__mmap(evlist, 128, true) < 0) {
91 pr_debug("failed to mmap events: %d (%s)\n", errno, 91 pr_debug("failed to mmap events: %d (%s)\n", errno,
92 strerror(errno)); 92 strerror(errno));
93 goto out_close_fd; 93 goto out_delete_evlist;
94 } 94 }
95 95
96 for (i = 0; i < nsyscalls; ++i) 96 for (i = 0; i < nsyscalls; ++i)
@@ -105,13 +105,13 @@ int test__basic_mmap(void)
105 if (event->header.type != PERF_RECORD_SAMPLE) { 105 if (event->header.type != PERF_RECORD_SAMPLE) {
106 pr_debug("unexpected %s event\n", 106 pr_debug("unexpected %s event\n",
107 perf_event__name(event->header.type)); 107 perf_event__name(event->header.type));
108 goto out_munmap; 108 goto out_delete_evlist;
109 } 109 }
110 110
111 err = perf_evlist__parse_sample(evlist, event, &sample); 111 err = perf_evlist__parse_sample(evlist, event, &sample);
112 if (err) { 112 if (err) {
113 pr_err("Can't parse sample, err = %d\n", err); 113 pr_err("Can't parse sample, err = %d\n", err);
114 goto out_munmap; 114 goto out_delete_evlist;
115 } 115 }
116 116
117 err = -1; 117 err = -1;
@@ -119,30 +119,27 @@ int test__basic_mmap(void)
119 if (evsel == NULL) { 119 if (evsel == NULL) {
120 pr_debug("event with id %" PRIu64 120 pr_debug("event with id %" PRIu64
121 " doesn't map to an evsel\n", sample.id); 121 " doesn't map to an evsel\n", sample.id);
122 goto out_munmap; 122 goto out_delete_evlist;
123 } 123 }
124 nr_events[evsel->idx]++; 124 nr_events[evsel->idx]++;
125 perf_evlist__mmap_consume(evlist, 0); 125 perf_evlist__mmap_consume(evlist, 0);
126 } 126 }
127 127
128 err = 0; 128 err = 0;
129 list_for_each_entry(evsel, &evlist->entries, node) { 129 evlist__for_each(evlist, evsel) {
130 if (nr_events[evsel->idx] != expected_nr_events[evsel->idx]) { 130 if (nr_events[evsel->idx] != expected_nr_events[evsel->idx]) {
131 pr_debug("expected %d %s events, got %d\n", 131 pr_debug("expected %d %s events, got %d\n",
132 expected_nr_events[evsel->idx], 132 expected_nr_events[evsel->idx],
133 perf_evsel__name(evsel), nr_events[evsel->idx]); 133 perf_evsel__name(evsel), nr_events[evsel->idx]);
134 err = -1; 134 err = -1;
135 goto out_munmap; 135 goto out_delete_evlist;
136 } 136 }
137 } 137 }
138 138
139out_munmap: 139out_delete_evlist:
140 perf_evlist__munmap(evlist);
141out_close_fd:
142 for (i = 0; i < nsyscalls; ++i)
143 perf_evsel__close_fd(evsels[i], 1, threads->nr);
144out_free_evlist:
145 perf_evlist__delete(evlist); 140 perf_evlist__delete(evlist);
141 cpus = NULL;
142 threads = NULL;
146out_free_cpus: 143out_free_cpus:
147 cpu_map__delete(cpus); 144 cpu_map__delete(cpus);
148out_free_threads: 145out_free_threads:
diff --git a/tools/perf/tests/open-syscall-tp-fields.c b/tools/perf/tests/open-syscall-tp-fields.c
index 41cc0badb74b..c505ef2af245 100644
--- a/tools/perf/tests/open-syscall-tp-fields.c
+++ b/tools/perf/tests/open-syscall-tp-fields.c
@@ -6,15 +6,15 @@
6 6
7int test__syscall_open_tp_fields(void) 7int test__syscall_open_tp_fields(void)
8{ 8{
9 struct perf_record_opts opts = { 9 struct record_opts opts = {
10 .target = { 10 .target = {
11 .uid = UINT_MAX, 11 .uid = UINT_MAX,
12 .uses_mmap = true, 12 .uses_mmap = true,
13 }, 13 },
14 .no_delay = true, 14 .no_buffering = true,
15 .freq = 1, 15 .freq = 1,
16 .mmap_pages = 256, 16 .mmap_pages = 256,
17 .raw_samples = true, 17 .raw_samples = true,
18 }; 18 };
19 const char *filename = "/etc/passwd"; 19 const char *filename = "/etc/passwd";
20 int flags = O_RDONLY | O_DIRECTORY; 20 int flags = O_RDONLY | O_DIRECTORY;
@@ -48,13 +48,13 @@ int test__syscall_open_tp_fields(void)
48 err = perf_evlist__open(evlist); 48 err = perf_evlist__open(evlist);
49 if (err < 0) { 49 if (err < 0) {
50 pr_debug("perf_evlist__open: %s\n", strerror(errno)); 50 pr_debug("perf_evlist__open: %s\n", strerror(errno));
51 goto out_delete_maps; 51 goto out_delete_evlist;
52 } 52 }
53 53
54 err = perf_evlist__mmap(evlist, UINT_MAX, false); 54 err = perf_evlist__mmap(evlist, UINT_MAX, false);
55 if (err < 0) { 55 if (err < 0) {
56 pr_debug("perf_evlist__mmap: %s\n", strerror(errno)); 56 pr_debug("perf_evlist__mmap: %s\n", strerror(errno));
57 goto out_close_evlist; 57 goto out_delete_evlist;
58 } 58 }
59 59
60 perf_evlist__enable(evlist); 60 perf_evlist__enable(evlist);
@@ -85,7 +85,7 @@ int test__syscall_open_tp_fields(void)
85 err = perf_evsel__parse_sample(evsel, event, &sample); 85 err = perf_evsel__parse_sample(evsel, event, &sample);
86 if (err) { 86 if (err) {
87 pr_err("Can't parse sample, err = %d\n", err); 87 pr_err("Can't parse sample, err = %d\n", err);
88 goto out_munmap; 88 goto out_delete_evlist;
89 } 89 }
90 90
91 tp_flags = perf_evsel__intval(evsel, &sample, "flags"); 91 tp_flags = perf_evsel__intval(evsel, &sample, "flags");
@@ -93,7 +93,7 @@ int test__syscall_open_tp_fields(void)
93 if (flags != tp_flags) { 93 if (flags != tp_flags) {
94 pr_debug("%s: Expected flags=%#x, got %#x\n", 94 pr_debug("%s: Expected flags=%#x, got %#x\n",
95 __func__, flags, tp_flags); 95 __func__, flags, tp_flags);
96 goto out_munmap; 96 goto out_delete_evlist;
97 } 97 }
98 98
99 goto out_ok; 99 goto out_ok;
@@ -105,17 +105,11 @@ int test__syscall_open_tp_fields(void)
105 105
106 if (++nr_polls > 5) { 106 if (++nr_polls > 5) {
107 pr_debug("%s: no events!\n", __func__); 107 pr_debug("%s: no events!\n", __func__);
108 goto out_munmap; 108 goto out_delete_evlist;
109 } 109 }
110 } 110 }
111out_ok: 111out_ok:
112 err = 0; 112 err = 0;
113out_munmap:
114 perf_evlist__munmap(evlist);
115out_close_evlist:
116 perf_evlist__close(evlist);
117out_delete_maps:
118 perf_evlist__delete_maps(evlist);
119out_delete_evlist: 113out_delete_evlist:
120 perf_evlist__delete(evlist); 114 perf_evlist__delete(evlist);
121out: 115out:
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c
index 3cbd10496087..4db0ae617d70 100644
--- a/tools/perf/tests/parse-events.c
+++ b/tools/perf/tests/parse-events.c
@@ -3,7 +3,7 @@
3#include "evsel.h" 3#include "evsel.h"
4#include "evlist.h" 4#include "evlist.h"
5#include "fs.h" 5#include "fs.h"
6#include <lk/debugfs.h> 6#include <api/fs/debugfs.h>
7#include "tests.h" 7#include "tests.h"
8#include <linux/hw_breakpoint.h> 8#include <linux/hw_breakpoint.h>
9 9
@@ -30,7 +30,7 @@ static int test__checkevent_tracepoint_multi(struct perf_evlist *evlist)
30 TEST_ASSERT_VAL("wrong number of entries", evlist->nr_entries > 1); 30 TEST_ASSERT_VAL("wrong number of entries", evlist->nr_entries > 1);
31 TEST_ASSERT_VAL("wrong number of groups", 0 == evlist->nr_groups); 31 TEST_ASSERT_VAL("wrong number of groups", 0 == evlist->nr_groups);
32 32
33 list_for_each_entry(evsel, &evlist->entries, node) { 33 evlist__for_each(evlist, evsel) {
34 TEST_ASSERT_VAL("wrong type", 34 TEST_ASSERT_VAL("wrong type",
35 PERF_TYPE_TRACEPOINT == evsel->attr.type); 35 PERF_TYPE_TRACEPOINT == evsel->attr.type);
36 TEST_ASSERT_VAL("wrong sample_type", 36 TEST_ASSERT_VAL("wrong sample_type",
@@ -201,7 +201,7 @@ test__checkevent_tracepoint_multi_modifier(struct perf_evlist *evlist)
201 201
202 TEST_ASSERT_VAL("wrong number of entries", evlist->nr_entries > 1); 202 TEST_ASSERT_VAL("wrong number of entries", evlist->nr_entries > 1);
203 203
204 list_for_each_entry(evsel, &evlist->entries, node) { 204 evlist__for_each(evlist, evsel) {
205 TEST_ASSERT_VAL("wrong exclude_user", 205 TEST_ASSERT_VAL("wrong exclude_user",
206 !evsel->attr.exclude_user); 206 !evsel->attr.exclude_user);
207 TEST_ASSERT_VAL("wrong exclude_kernel", 207 TEST_ASSERT_VAL("wrong exclude_kernel",
@@ -1385,10 +1385,10 @@ static int test_event(struct evlist_test *e)
1385 if (ret) { 1385 if (ret) {
1386 pr_debug("failed to parse event '%s', err %d\n", 1386 pr_debug("failed to parse event '%s', err %d\n",
1387 e->name, ret); 1387 e->name, ret);
1388 return ret; 1388 } else {
1389 ret = e->check(evlist);
1389 } 1390 }
1390 1391
1391 ret = e->check(evlist);
1392 perf_evlist__delete(evlist); 1392 perf_evlist__delete(evlist);
1393 1393
1394 return ret; 1394 return ret;
diff --git a/tools/perf/tests/perf-record.c b/tools/perf/tests/perf-record.c
index 93a62b06c3af..aca1a83dd13a 100644
--- a/tools/perf/tests/perf-record.c
+++ b/tools/perf/tests/perf-record.c
@@ -34,14 +34,14 @@ realloc:
34 34
35int test__PERF_RECORD(void) 35int test__PERF_RECORD(void)
36{ 36{
37 struct perf_record_opts opts = { 37 struct record_opts opts = {
38 .target = { 38 .target = {
39 .uid = UINT_MAX, 39 .uid = UINT_MAX,
40 .uses_mmap = true, 40 .uses_mmap = true,
41 }, 41 },
42 .no_delay = true, 42 .no_buffering = true,
43 .freq = 10, 43 .freq = 10,
44 .mmap_pages = 256, 44 .mmap_pages = 256,
45 }; 45 };
46 cpu_set_t cpu_mask; 46 cpu_set_t cpu_mask;
47 size_t cpu_mask_size = sizeof(cpu_mask); 47 size_t cpu_mask_size = sizeof(cpu_mask);
@@ -83,11 +83,10 @@ int test__PERF_RECORD(void)
83 * so that we have time to open the evlist (calling sys_perf_event_open 83 * so that we have time to open the evlist (calling sys_perf_event_open
84 * on all the fds) and then mmap them. 84 * on all the fds) and then mmap them.
85 */ 85 */
86 err = perf_evlist__prepare_workload(evlist, &opts.target, argv, 86 err = perf_evlist__prepare_workload(evlist, &opts.target, argv, false, NULL);
87 false, false);
88 if (err < 0) { 87 if (err < 0) {
89 pr_debug("Couldn't run the workload!\n"); 88 pr_debug("Couldn't run the workload!\n");
90 goto out_delete_maps; 89 goto out_delete_evlist;
91 } 90 }
92 91
93 /* 92 /*
@@ -102,7 +101,7 @@ int test__PERF_RECORD(void)
102 err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask); 101 err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask);
103 if (err < 0) { 102 if (err < 0) {
104 pr_debug("sched__get_first_possible_cpu: %s\n", strerror(errno)); 103 pr_debug("sched__get_first_possible_cpu: %s\n", strerror(errno));
105 goto out_delete_maps; 104 goto out_delete_evlist;
106 } 105 }
107 106
108 cpu = err; 107 cpu = err;
@@ -112,7 +111,7 @@ int test__PERF_RECORD(void)
112 */ 111 */
113 if (sched_setaffinity(evlist->workload.pid, cpu_mask_size, &cpu_mask) < 0) { 112 if (sched_setaffinity(evlist->workload.pid, cpu_mask_size, &cpu_mask) < 0) {
114 pr_debug("sched_setaffinity: %s\n", strerror(errno)); 113 pr_debug("sched_setaffinity: %s\n", strerror(errno));
115 goto out_delete_maps; 114 goto out_delete_evlist;
116 } 115 }
117 116
118 /* 117 /*
@@ -122,7 +121,7 @@ int test__PERF_RECORD(void)
122 err = perf_evlist__open(evlist); 121 err = perf_evlist__open(evlist);
123 if (err < 0) { 122 if (err < 0) {
124 pr_debug("perf_evlist__open: %s\n", strerror(errno)); 123 pr_debug("perf_evlist__open: %s\n", strerror(errno));
125 goto out_delete_maps; 124 goto out_delete_evlist;
126 } 125 }
127 126
128 /* 127 /*
@@ -133,7 +132,7 @@ int test__PERF_RECORD(void)
133 err = perf_evlist__mmap(evlist, opts.mmap_pages, false); 132 err = perf_evlist__mmap(evlist, opts.mmap_pages, false);
134 if (err < 0) { 133 if (err < 0) {
135 pr_debug("perf_evlist__mmap: %s\n", strerror(errno)); 134 pr_debug("perf_evlist__mmap: %s\n", strerror(errno));
136 goto out_close_evlist; 135 goto out_delete_evlist;
137 } 136 }
138 137
139 /* 138 /*
@@ -166,7 +165,7 @@ int test__PERF_RECORD(void)
166 if (verbose) 165 if (verbose)
167 perf_event__fprintf(event, stderr); 166 perf_event__fprintf(event, stderr);
168 pr_debug("Couldn't parse sample\n"); 167 pr_debug("Couldn't parse sample\n");
169 goto out_err; 168 goto out_delete_evlist;
170 } 169 }
171 170
172 if (verbose) { 171 if (verbose) {
@@ -303,12 +302,6 @@ found_exit:
303 pr_debug("PERF_RECORD_MMAP for %s missing!\n", "[vdso]"); 302 pr_debug("PERF_RECORD_MMAP for %s missing!\n", "[vdso]");
304 ++errs; 303 ++errs;
305 } 304 }
306out_err:
307 perf_evlist__munmap(evlist);
308out_close_evlist:
309 perf_evlist__close(evlist);
310out_delete_maps:
311 perf_evlist__delete_maps(evlist);
312out_delete_evlist: 305out_delete_evlist:
313 perf_evlist__delete(evlist); 306 perf_evlist__delete(evlist);
314out: 307out:
diff --git a/tools/perf/tests/perf-targz-src-pkg b/tools/perf/tests/perf-targz-src-pkg
new file mode 100755
index 000000000000..238aa3927c71
--- /dev/null
+++ b/tools/perf/tests/perf-targz-src-pkg
@@ -0,0 +1,21 @@
1#!/bin/sh
2# Test one of the main kernel Makefile targets to generate a perf sources tarball
3# suitable for build outside the full kernel sources.
4#
5# This is to test that the tools/perf/MANIFEST file lists all the files needed to
6# be in such tarball, which sometimes gets broken when we move files around,
7# like when we made some files that were in tools/perf/ available to other tools/
8# codebases by moving it to tools/include/, etc.
9
10PERF=$1
11cd ${PERF}/../..
12make perf-targz-src-pkg > /dev/null
13TARBALL=$(ls -rt perf-*.tar.gz)
14TMP_DEST=$(mktemp -d)
15tar xf ${TARBALL} -C $TMP_DEST
16rm -f ${TARBALL}
17cd - > /dev/null
18make -C $TMP_DEST/perf*/tools/perf > /dev/null 2>&1
19RC=$?
20rm -rf ${TMP_DEST}
21exit $RC
diff --git a/tools/perf/tests/perf-time-to-tsc.c b/tools/perf/tests/perf-time-to-tsc.c
index 4ca1b938f6a6..47146d388dbf 100644
--- a/tools/perf/tests/perf-time-to-tsc.c
+++ b/tools/perf/tests/perf-time-to-tsc.c
@@ -46,7 +46,7 @@ static u64 rdtsc(void)
46 */ 46 */
47int test__perf_time_to_tsc(void) 47int test__perf_time_to_tsc(void)
48{ 48{
49 struct perf_record_opts opts = { 49 struct record_opts opts = {
50 .mmap_pages = UINT_MAX, 50 .mmap_pages = UINT_MAX,
51 .user_freq = UINT_MAX, 51 .user_freq = UINT_MAX,
52 .user_interval = ULLONG_MAX, 52 .user_interval = ULLONG_MAX,
@@ -166,14 +166,8 @@ next_event:
166out_err: 166out_err:
167 if (evlist) { 167 if (evlist) {
168 perf_evlist__disable(evlist); 168 perf_evlist__disable(evlist);
169 perf_evlist__munmap(evlist);
170 perf_evlist__close(evlist);
171 perf_evlist__delete(evlist); 169 perf_evlist__delete(evlist);
172 } 170 }
173 if (cpus)
174 cpu_map__delete(cpus);
175 if (threads)
176 thread_map__delete(threads);
177 171
178 return err; 172 return err;
179} 173}
diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c
index 6664a7cd828c..983d6b8562a8 100644
--- a/tools/perf/tests/sw-clock.c
+++ b/tools/perf/tests/sw-clock.c
@@ -45,7 +45,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
45 evsel = perf_evsel__new(&attr); 45 evsel = perf_evsel__new(&attr);
46 if (evsel == NULL) { 46 if (evsel == NULL) {
47 pr_debug("perf_evsel__new\n"); 47 pr_debug("perf_evsel__new\n");
48 goto out_free_evlist; 48 goto out_delete_evlist;
49 } 49 }
50 perf_evlist__add(evlist, evsel); 50 perf_evlist__add(evlist, evsel);
51 51
@@ -54,7 +54,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
54 if (!evlist->cpus || !evlist->threads) { 54 if (!evlist->cpus || !evlist->threads) {
55 err = -ENOMEM; 55 err = -ENOMEM;
56 pr_debug("Not enough memory to create thread/cpu maps\n"); 56 pr_debug("Not enough memory to create thread/cpu maps\n");
57 goto out_delete_maps; 57 goto out_delete_evlist;
58 } 58 }
59 59
60 if (perf_evlist__open(evlist)) { 60 if (perf_evlist__open(evlist)) {
@@ -63,14 +63,14 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
63 err = -errno; 63 err = -errno;
64 pr_debug("Couldn't open evlist: %s\nHint: check %s, using %" PRIu64 " in this test.\n", 64 pr_debug("Couldn't open evlist: %s\nHint: check %s, using %" PRIu64 " in this test.\n",
65 strerror(errno), knob, (u64)attr.sample_freq); 65 strerror(errno), knob, (u64)attr.sample_freq);
66 goto out_delete_maps; 66 goto out_delete_evlist;
67 } 67 }
68 68
69 err = perf_evlist__mmap(evlist, 128, true); 69 err = perf_evlist__mmap(evlist, 128, true);
70 if (err < 0) { 70 if (err < 0) {
71 pr_debug("failed to mmap event: %d (%s)\n", errno, 71 pr_debug("failed to mmap event: %d (%s)\n", errno,
72 strerror(errno)); 72 strerror(errno));
73 goto out_close_evlist; 73 goto out_delete_evlist;
74 } 74 }
75 75
76 perf_evlist__enable(evlist); 76 perf_evlist__enable(evlist);
@@ -90,7 +90,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
90 err = perf_evlist__parse_sample(evlist, event, &sample); 90 err = perf_evlist__parse_sample(evlist, event, &sample);
91 if (err < 0) { 91 if (err < 0) {
92 pr_debug("Error during parse sample\n"); 92 pr_debug("Error during parse sample\n");
93 goto out_unmap_evlist; 93 goto out_delete_evlist;
94 } 94 }
95 95
96 total_periods += sample.period; 96 total_periods += sample.period;
@@ -105,13 +105,7 @@ next_event:
105 err = -1; 105 err = -1;
106 } 106 }
107 107
108out_unmap_evlist: 108out_delete_evlist:
109 perf_evlist__munmap(evlist);
110out_close_evlist:
111 perf_evlist__close(evlist);
112out_delete_maps:
113 perf_evlist__delete_maps(evlist);
114out_free_evlist:
115 perf_evlist__delete(evlist); 109 perf_evlist__delete(evlist);
116 return err; 110 return err;
117} 111}
diff --git a/tools/perf/tests/task-exit.c b/tools/perf/tests/task-exit.c
index d09ab579119e..5ff3db318f12 100644
--- a/tools/perf/tests/task-exit.c
+++ b/tools/perf/tests/task-exit.c
@@ -9,12 +9,21 @@
9static int exited; 9static int exited;
10static int nr_exit; 10static int nr_exit;
11 11
12static void sig_handler(int sig) 12static void sig_handler(int sig __maybe_unused)
13{ 13{
14 exited = 1; 14 exited = 1;
15}
15 16
16 if (sig == SIGUSR1) 17/*
17 nr_exit = -1; 18 * perf_evlist__prepare_workload will send a SIGUSR1 if the fork fails, since
19 * we asked by setting its exec_error to this handler.
20 */
21static void workload_exec_failed_signal(int signo __maybe_unused,
22 siginfo_t *info __maybe_unused,
23 void *ucontext __maybe_unused)
24{
25 exited = 1;
26 nr_exit = -1;
18} 27}
19 28
20/* 29/*
@@ -35,7 +44,6 @@ int test__task_exit(void)
35 const char *argv[] = { "true", NULL }; 44 const char *argv[] = { "true", NULL };
36 45
37 signal(SIGCHLD, sig_handler); 46 signal(SIGCHLD, sig_handler);
38 signal(SIGUSR1, sig_handler);
39 47
40 evlist = perf_evlist__new_default(); 48 evlist = perf_evlist__new_default();
41 if (evlist == NULL) { 49 if (evlist == NULL) {
@@ -54,13 +62,14 @@ int test__task_exit(void)
54 if (!evlist->cpus || !evlist->threads) { 62 if (!evlist->cpus || !evlist->threads) {
55 err = -ENOMEM; 63 err = -ENOMEM;
56 pr_debug("Not enough memory to create thread/cpu maps\n"); 64 pr_debug("Not enough memory to create thread/cpu maps\n");
57 goto out_delete_maps; 65 goto out_delete_evlist;
58 } 66 }
59 67
60 err = perf_evlist__prepare_workload(evlist, &target, argv, false, true); 68 err = perf_evlist__prepare_workload(evlist, &target, argv, false,
69 workload_exec_failed_signal);
61 if (err < 0) { 70 if (err < 0) {
62 pr_debug("Couldn't run the workload!\n"); 71 pr_debug("Couldn't run the workload!\n");
63 goto out_delete_maps; 72 goto out_delete_evlist;
64 } 73 }
65 74
66 evsel = perf_evlist__first(evlist); 75 evsel = perf_evlist__first(evlist);
@@ -74,13 +83,13 @@ int test__task_exit(void)
74 err = perf_evlist__open(evlist); 83 err = perf_evlist__open(evlist);
75 if (err < 0) { 84 if (err < 0) {
76 pr_debug("Couldn't open the evlist: %s\n", strerror(-err)); 85 pr_debug("Couldn't open the evlist: %s\n", strerror(-err));
77 goto out_delete_maps; 86 goto out_delete_evlist;
78 } 87 }
79 88
80 if (perf_evlist__mmap(evlist, 128, true) < 0) { 89 if (perf_evlist__mmap(evlist, 128, true) < 0) {
81 pr_debug("failed to mmap events: %d (%s)\n", errno, 90 pr_debug("failed to mmap events: %d (%s)\n", errno,
82 strerror(errno)); 91 strerror(errno));
83 goto out_close_evlist; 92 goto out_delete_evlist;
84 } 93 }
85 94
86 perf_evlist__start_workload(evlist); 95 perf_evlist__start_workload(evlist);
@@ -103,11 +112,7 @@ retry:
103 err = -1; 112 err = -1;
104 } 113 }
105 114
106 perf_evlist__munmap(evlist); 115out_delete_evlist:
107out_close_evlist:
108 perf_evlist__close(evlist);
109out_delete_maps:
110 perf_evlist__delete_maps(evlist);
111 perf_evlist__delete(evlist); 116 perf_evlist__delete(evlist);
112 return err; 117 return err;
113} 118}
diff --git a/tools/perf/ui/browser.c b/tools/perf/ui/browser.c
index cbaa7af45513..d11541d4d7d7 100644
--- a/tools/perf/ui/browser.c
+++ b/tools/perf/ui/browser.c
@@ -256,8 +256,7 @@ int ui_browser__show(struct ui_browser *browser, const char *title,
256 __ui_browser__show_title(browser, title); 256 __ui_browser__show_title(browser, title);
257 257
258 browser->title = title; 258 browser->title = title;
259 free(browser->helpline); 259 zfree(&browser->helpline);
260 browser->helpline = NULL;
261 260
262 va_start(ap, helpline); 261 va_start(ap, helpline);
263 err = vasprintf(&browser->helpline, helpline, ap); 262 err = vasprintf(&browser->helpline, helpline, ap);
@@ -268,12 +267,11 @@ int ui_browser__show(struct ui_browser *browser, const char *title,
268 return err ? 0 : -1; 267 return err ? 0 : -1;
269} 268}
270 269
271void ui_browser__hide(struct ui_browser *browser __maybe_unused) 270void ui_browser__hide(struct ui_browser *browser)
272{ 271{
273 pthread_mutex_lock(&ui__lock); 272 pthread_mutex_lock(&ui__lock);
274 ui_helpline__pop(); 273 ui_helpline__pop();
275 free(browser->helpline); 274 zfree(&browser->helpline);
276 browser->helpline = NULL;
277 pthread_mutex_unlock(&ui__lock); 275 pthread_mutex_unlock(&ui__lock);
278} 276}
279 277
diff --git a/tools/perf/ui/browser.h b/tools/perf/ui/browser.h
index 7d45d2f53601..118cca29dd26 100644
--- a/tools/perf/ui/browser.h
+++ b/tools/perf/ui/browser.h
@@ -59,6 +59,8 @@ int ui_browser__help_window(struct ui_browser *browser, const char *text);
59bool ui_browser__dialog_yesno(struct ui_browser *browser, const char *text); 59bool ui_browser__dialog_yesno(struct ui_browser *browser, const char *text);
60int ui_browser__input_window(const char *title, const char *text, char *input, 60int ui_browser__input_window(const char *title, const char *text, char *input,
61 const char *exit_msg, int delay_sec); 61 const char *exit_msg, int delay_sec);
62struct perf_session_env;
63int tui__header_window(struct perf_session_env *env);
62 64
63void ui_browser__argv_seek(struct ui_browser *browser, off_t offset, int whence); 65void ui_browser__argv_seek(struct ui_browser *browser, off_t offset, int whence);
64unsigned int ui_browser__argv_refresh(struct ui_browser *browser); 66unsigned int ui_browser__argv_refresh(struct ui_browser *browser);
diff --git a/tools/perf/ui/browsers/header.c b/tools/perf/ui/browsers/header.c
new file mode 100644
index 000000000000..89c16b988618
--- /dev/null
+++ b/tools/perf/ui/browsers/header.c
@@ -0,0 +1,127 @@
1#include "util/cache.h"
2#include "util/debug.h"
3#include "ui/browser.h"
4#include "ui/ui.h"
5#include "ui/util.h"
6#include "ui/libslang.h"
7#include "util/header.h"
8#include "util/session.h"
9
10static void ui_browser__argv_write(struct ui_browser *browser,
11 void *entry, int row)
12{
13 char **arg = entry;
14 char *str = *arg;
15 char empty[] = " ";
16 bool current_entry = ui_browser__is_current_entry(browser, row);
17 unsigned long offset = (unsigned long)browser->priv;
18
19 if (offset >= strlen(str))
20 str = empty;
21 else
22 str = str + offset;
23
24 ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED :
25 HE_COLORSET_NORMAL);
26
27 slsmg_write_nstring(str, browser->width);
28}
29
30static int list_menu__run(struct ui_browser *menu)
31{
32 int key;
33 unsigned long offset;
34 const char help[] =
35 "h/?/F1 Show this window\n"
36 "UP/DOWN/PGUP\n"
37 "PGDN/SPACE\n"
38 "LEFT/RIGHT Navigate\n"
39 "q/ESC/CTRL+C Exit browser";
40
41 if (ui_browser__show(menu, "Header information", "Press 'q' to exit") < 0)
42 return -1;
43
44 while (1) {
45 key = ui_browser__run(menu, 0);
46
47 switch (key) {
48 case K_RIGHT:
49 offset = (unsigned long)menu->priv;
50 offset += 10;
51 menu->priv = (void *)offset;
52 continue;
53 case K_LEFT:
54 offset = (unsigned long)menu->priv;
55 if (offset >= 10)
56 offset -= 10;
57 menu->priv = (void *)offset;
58 continue;
59 case K_F1:
60 case 'h':
61 case '?':
62 ui_browser__help_window(menu, help);
63 continue;
64 case K_ESC:
65 case 'q':
66 case CTRL('c'):
67 key = -1;
68 break;
69 default:
70 continue;
71 }
72
73 break;
74 }
75
76 ui_browser__hide(menu);
77 return key;
78}
79
80static int ui__list_menu(int argc, char * const argv[])
81{
82 struct ui_browser menu = {
83 .entries = (void *)argv,
84 .refresh = ui_browser__argv_refresh,
85 .seek = ui_browser__argv_seek,
86 .write = ui_browser__argv_write,
87 .nr_entries = argc,
88 };
89
90 return list_menu__run(&menu);
91}
92
93int tui__header_window(struct perf_session_env *env)
94{
95 int i, argc = 0;
96 char **argv;
97 struct perf_session *session;
98 char *ptr, *pos;
99 size_t size;
100 FILE *fp = open_memstream(&ptr, &size);
101
102 session = container_of(env, struct perf_session, header.env);
103 perf_header__fprintf_info(session, fp, true);
104 fclose(fp);
105
106 for (pos = ptr, argc = 0; (pos = strchr(pos, '\n')) != NULL; pos++)
107 argc++;
108
109 argv = calloc(argc + 1, sizeof(*argv));
110 if (argv == NULL)
111 goto out;
112
113 argv[0] = pos = ptr;
114 for (i = 1; (pos = strchr(pos, '\n')) != NULL; i++) {
115 *pos++ = '\0';
116 argv[i] = pos;
117 }
118
119 BUG_ON(i != argc + 1);
120
121 ui__list_menu(argc, argv);
122
123out:
124 free(argv);
125 free(ptr);
126 return 0;
127}
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index a440e03cd8c2..b720b92eba6e 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -1267,10 +1267,8 @@ static inline void free_popup_options(char **options, int n)
1267{ 1267{
1268 int i; 1268 int i;
1269 1269
1270 for (i = 0; i < n; ++i) { 1270 for (i = 0; i < n; ++i)
1271 free(options[i]); 1271 zfree(&options[i]);
1272 options[i] = NULL;
1273 }
1274} 1272}
1275 1273
1276/* Check whether the browser is for 'top' or 'report' */ 1274/* Check whether the browser is for 'top' or 'report' */
@@ -1329,7 +1327,7 @@ static int switch_data_file(void)
1329 1327
1330 abs_path[nr_options] = strdup(path); 1328 abs_path[nr_options] = strdup(path);
1331 if (!abs_path[nr_options]) { 1329 if (!abs_path[nr_options]) {
1332 free(options[nr_options]); 1330 zfree(&options[nr_options]);
1333 ui__warning("Can't search all data files due to memory shortage.\n"); 1331 ui__warning("Can't search all data files due to memory shortage.\n");
1334 fclose(file); 1332 fclose(file);
1335 break; 1333 break;
@@ -1400,6 +1398,36 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1400 char script_opt[64]; 1398 char script_opt[64];
1401 int delay_secs = hbt ? hbt->refresh : 0; 1399 int delay_secs = hbt ? hbt->refresh : 0;
1402 1400
1401#define HIST_BROWSER_HELP_COMMON \
1402 "h/?/F1 Show this window\n" \
1403 "UP/DOWN/PGUP\n" \
1404 "PGDN/SPACE Navigate\n" \
1405 "q/ESC/CTRL+C Exit browser\n\n" \
1406 "For multiple event sessions:\n\n" \
1407 "TAB/UNTAB Switch events\n\n" \
1408 "For symbolic views (--sort has sym):\n\n" \
1409 "-> Zoom into DSO/Threads & Annotate current symbol\n" \
1410 "<- Zoom out\n" \
1411 "a Annotate current symbol\n" \
1412 "C Collapse all callchains\n" \
1413 "d Zoom into current DSO\n" \
1414 "E Expand all callchains\n" \
1415
1416 /* help messages are sorted by lexical order of the hotkey */
1417 const char report_help[] = HIST_BROWSER_HELP_COMMON
1418 "i Show header information\n"
1419 "P Print histograms to perf.hist.N\n"
1420 "r Run available scripts\n"
1421 "s Switch to another data file in PWD\n"
1422 "t Zoom into current Thread\n"
1423 "V Verbose (DSO names in callchains, etc)\n"
1424 "/ Filter symbol by name";
1425 const char top_help[] = HIST_BROWSER_HELP_COMMON
1426 "P Print histograms to perf.hist.N\n"
1427 "t Zoom into current Thread\n"
1428 "V Verbose (DSO names in callchains, etc)\n"
1429 "/ Filter symbol by name";
1430
1403 if (browser == NULL) 1431 if (browser == NULL)
1404 return -1; 1432 return -1;
1405 1433
@@ -1484,29 +1512,16 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1484 if (is_report_browser(hbt)) 1512 if (is_report_browser(hbt))
1485 goto do_data_switch; 1513 goto do_data_switch;
1486 continue; 1514 continue;
1515 case 'i':
1516 /* env->arch is NULL for live-mode (i.e. perf top) */
1517 if (env->arch)
1518 tui__header_window(env);
1519 continue;
1487 case K_F1: 1520 case K_F1:
1488 case 'h': 1521 case 'h':
1489 case '?': 1522 case '?':
1490 ui_browser__help_window(&browser->b, 1523 ui_browser__help_window(&browser->b,
1491 "h/?/F1 Show this window\n" 1524 is_report_browser(hbt) ? report_help : top_help);
1492 "UP/DOWN/PGUP\n"
1493 "PGDN/SPACE Navigate\n"
1494 "q/ESC/CTRL+C Exit browser\n\n"
1495 "For multiple event sessions:\n\n"
1496 "TAB/UNTAB Switch events\n\n"
1497 "For symbolic views (--sort has sym):\n\n"
1498 "-> Zoom into DSO/Threads & Annotate current symbol\n"
1499 "<- Zoom out\n"
1500 "a Annotate current symbol\n"
1501 "C Collapse all callchains\n"
1502 "E Expand all callchains\n"
1503 "d Zoom into current DSO\n"
1504 "t Zoom into current Thread\n"
1505 "r Run available scripts('perf report' only)\n"
1506 "s Switch to another data file in PWD ('perf report' only)\n"
1507 "P Print histograms to perf.hist.N\n"
1508 "V Verbose (DSO names in callchains, etc)\n"
1509 "/ Filter symbol by name");
1510 continue; 1525 continue;
1511 case K_ENTER: 1526 case K_ENTER:
1512 case K_RIGHT: 1527 case K_RIGHT:
@@ -1923,7 +1938,7 @@ static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist,
1923 1938
1924 ui_helpline__push("Press ESC to exit"); 1939 ui_helpline__push("Press ESC to exit");
1925 1940
1926 list_for_each_entry(pos, &evlist->entries, node) { 1941 evlist__for_each(evlist, pos) {
1927 const char *ev_name = perf_evsel__name(pos); 1942 const char *ev_name = perf_evsel__name(pos);
1928 size_t line_len = strlen(ev_name) + 7; 1943 size_t line_len = strlen(ev_name) + 7;
1929 1944
@@ -1955,9 +1970,10 @@ single_entry:
1955 struct perf_evsel *pos; 1970 struct perf_evsel *pos;
1956 1971
1957 nr_entries = 0; 1972 nr_entries = 0;
1958 list_for_each_entry(pos, &evlist->entries, node) 1973 evlist__for_each(evlist, pos) {
1959 if (perf_evsel__is_group_leader(pos)) 1974 if (perf_evsel__is_group_leader(pos))
1960 nr_entries++; 1975 nr_entries++;
1976 }
1961 1977
1962 if (nr_entries == 1) 1978 if (nr_entries == 1)
1963 goto single_entry; 1979 goto single_entry;
diff --git a/tools/perf/ui/browsers/scripts.c b/tools/perf/ui/browsers/scripts.c
index d63c68ea02a8..402d2bd30b09 100644
--- a/tools/perf/ui/browsers/scripts.c
+++ b/tools/perf/ui/browsers/scripts.c
@@ -173,8 +173,7 @@ int script_browse(const char *script_opt)
173 if (script.b.width > AVERAGE_LINE_LEN) 173 if (script.b.width > AVERAGE_LINE_LEN)
174 script.b.width = AVERAGE_LINE_LEN; 174 script.b.width = AVERAGE_LINE_LEN;
175 175
176 if (line) 176 free(line);
177 free(line);
178 pclose(fp); 177 pclose(fp);
179 178
180 script.nr_lines = nr_entries; 179 script.nr_lines = nr_entries;
diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c
index 2ca66cc1160f..5b95c44f3435 100644
--- a/tools/perf/ui/gtk/hists.c
+++ b/tools/perf/ui/gtk/hists.c
@@ -375,7 +375,7 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist,
375 375
376 gtk_container_add(GTK_CONTAINER(window), vbox); 376 gtk_container_add(GTK_CONTAINER(window), vbox);
377 377
378 list_for_each_entry(pos, &evlist->entries, node) { 378 evlist__for_each(evlist, pos) {
379 struct hists *hists = &pos->hists; 379 struct hists *hists = &pos->hists;
380 const char *evname = perf_evsel__name(pos); 380 const char *evname = perf_evsel__name(pos);
381 GtkWidget *scrolled_window; 381 GtkWidget *scrolled_window;
diff --git a/tools/perf/ui/gtk/util.c b/tools/perf/ui/gtk/util.c
index 696c1fbe4248..52e7fc48af9f 100644
--- a/tools/perf/ui/gtk/util.c
+++ b/tools/perf/ui/gtk/util.c
@@ -23,8 +23,7 @@ int perf_gtk__deactivate_context(struct perf_gtk_context **ctx)
23 if (!perf_gtk__is_active_context(*ctx)) 23 if (!perf_gtk__is_active_context(*ctx))
24 return -1; 24 return -1;
25 25
26 free(*ctx); 26 zfree(ctx);
27 *ctx = NULL;
28 return 0; 27 return 0;
29} 28}
30 29
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index c244cb524ef2..831fbb77d1ff 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -510,7 +510,7 @@ print_entries:
510 510
511 free(line); 511 free(line);
512out: 512out:
513 free(rem_sq_bracket); 513 zfree(&rem_sq_bracket);
514 514
515 return ret; 515 return ret;
516} 516}
diff --git a/tools/perf/ui/tui/util.c b/tools/perf/ui/tui/util.c
index 092902e30cee..bf890f72fe80 100644
--- a/tools/perf/ui/tui/util.c
+++ b/tools/perf/ui/tui/util.c
@@ -92,6 +92,8 @@ int ui_browser__input_window(const char *title, const char *text, char *input,
92 t = sep + 1; 92 t = sep + 1;
93 } 93 }
94 94
95 pthread_mutex_lock(&ui__lock);
96
95 max_len += 2; 97 max_len += 2;
96 nr_lines += 8; 98 nr_lines += 8;
97 y = SLtt_Screen_Rows / 2 - nr_lines / 2; 99 y = SLtt_Screen_Rows / 2 - nr_lines / 2;
@@ -120,13 +122,19 @@ int ui_browser__input_window(const char *title, const char *text, char *input,
120 SLsmg_write_nstring((char *)exit_msg, max_len); 122 SLsmg_write_nstring((char *)exit_msg, max_len);
121 SLsmg_refresh(); 123 SLsmg_refresh();
122 124
125 pthread_mutex_unlock(&ui__lock);
126
123 x += 2; 127 x += 2;
124 len = 0; 128 len = 0;
125 key = ui__getch(delay_secs); 129 key = ui__getch(delay_secs);
126 while (key != K_TIMER && key != K_ENTER && key != K_ESC) { 130 while (key != K_TIMER && key != K_ENTER && key != K_ESC) {
131 pthread_mutex_lock(&ui__lock);
132
127 if (key == K_BKSPC) { 133 if (key == K_BKSPC) {
128 if (len == 0) 134 if (len == 0) {
135 pthread_mutex_unlock(&ui__lock);
129 goto next_key; 136 goto next_key;
137 }
130 SLsmg_gotorc(y, x + --len); 138 SLsmg_gotorc(y, x + --len);
131 SLsmg_write_char(' '); 139 SLsmg_write_char(' ');
132 } else { 140 } else {
@@ -136,6 +144,8 @@ int ui_browser__input_window(const char *title, const char *text, char *input,
136 } 144 }
137 SLsmg_refresh(); 145 SLsmg_refresh();
138 146
147 pthread_mutex_unlock(&ui__lock);
148
139 /* XXX more graceful overflow handling needed */ 149 /* XXX more graceful overflow handling needed */
140 if (len == sizeof(buf) - 1) { 150 if (len == sizeof(buf) - 1) {
141 ui_helpline__push("maximum size of symbol name reached!"); 151 ui_helpline__push("maximum size of symbol name reached!");
@@ -174,6 +184,8 @@ int ui__question_window(const char *title, const char *text,
174 t = sep + 1; 184 t = sep + 1;
175 } 185 }
176 186
187 pthread_mutex_lock(&ui__lock);
188
177 max_len += 2; 189 max_len += 2;
178 nr_lines += 4; 190 nr_lines += 4;
179 y = SLtt_Screen_Rows / 2 - nr_lines / 2, 191 y = SLtt_Screen_Rows / 2 - nr_lines / 2,
@@ -195,6 +207,9 @@ int ui__question_window(const char *title, const char *text,
195 SLsmg_gotorc(y + nr_lines - 1, x); 207 SLsmg_gotorc(y + nr_lines - 1, x);
196 SLsmg_write_nstring((char *)exit_msg, max_len); 208 SLsmg_write_nstring((char *)exit_msg, max_len);
197 SLsmg_refresh(); 209 SLsmg_refresh();
210
211 pthread_mutex_unlock(&ui__lock);
212
198 return ui__getch(delay_secs); 213 return ui__getch(delay_secs);
199} 214}
200 215
@@ -215,9 +230,7 @@ static int __ui__warning(const char *title, const char *format, va_list args)
215 if (vasprintf(&s, format, args) > 0) { 230 if (vasprintf(&s, format, args) > 0) {
216 int key; 231 int key;
217 232
218 pthread_mutex_lock(&ui__lock);
219 key = ui__question_window(title, s, "Press any key...", 0); 233 key = ui__question_window(title, s, "Press any key...", 0);
220 pthread_mutex_unlock(&ui__lock);
221 free(s); 234 free(s);
222 return key; 235 return key;
223 } 236 }
diff --git a/tools/perf/util/alias.c b/tools/perf/util/alias.c
index e6d134773d0a..c0b43ee40d95 100644
--- a/tools/perf/util/alias.c
+++ b/tools/perf/util/alias.c
@@ -55,8 +55,7 @@ int split_cmdline(char *cmdline, const char ***argv)
55 src++; 55 src++;
56 c = cmdline[src]; 56 c = cmdline[src];
57 if (!c) { 57 if (!c) {
58 free(*argv); 58 zfree(argv);
59 *argv = NULL;
60 return error("cmdline ends with \\"); 59 return error("cmdline ends with \\");
61 } 60 }
62 } 61 }
@@ -68,8 +67,7 @@ int split_cmdline(char *cmdline, const char ***argv)
68 cmdline[dst] = 0; 67 cmdline[dst] = 0;
69 68
70 if (quoted) { 69 if (quoted) {
71 free(*argv); 70 zfree(argv);
72 *argv = NULL;
73 return error("unclosed quote"); 71 return error("unclosed quote");
74 } 72 }
75 73
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index cf6242c92ee2..469eb679fb9d 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -26,10 +26,10 @@ static int disasm_line__parse(char *line, char **namep, char **rawp);
26 26
27static void ins__delete(struct ins_operands *ops) 27static void ins__delete(struct ins_operands *ops)
28{ 28{
29 free(ops->source.raw); 29 zfree(&ops->source.raw);
30 free(ops->source.name); 30 zfree(&ops->source.name);
31 free(ops->target.raw); 31 zfree(&ops->target.raw);
32 free(ops->target.name); 32 zfree(&ops->target.name);
33} 33}
34 34
35static int ins__raw_scnprintf(struct ins *ins, char *bf, size_t size, 35static int ins__raw_scnprintf(struct ins *ins, char *bf, size_t size,
@@ -185,8 +185,7 @@ static int lock__parse(struct ins_operands *ops)
185 return 0; 185 return 0;
186 186
187out_free_ops: 187out_free_ops:
188 free(ops->locked.ops); 188 zfree(&ops->locked.ops);
189 ops->locked.ops = NULL;
190 return 0; 189 return 0;
191} 190}
192 191
@@ -205,9 +204,9 @@ static int lock__scnprintf(struct ins *ins, char *bf, size_t size,
205 204
206static void lock__delete(struct ins_operands *ops) 205static void lock__delete(struct ins_operands *ops)
207{ 206{
208 free(ops->locked.ops); 207 zfree(&ops->locked.ops);
209 free(ops->target.raw); 208 zfree(&ops->target.raw);
210 free(ops->target.name); 209 zfree(&ops->target.name);
211} 210}
212 211
213static struct ins_ops lock_ops = { 212static struct ins_ops lock_ops = {
@@ -256,8 +255,7 @@ static int mov__parse(struct ins_operands *ops)
256 return 0; 255 return 0;
257 256
258out_free_source: 257out_free_source:
259 free(ops->source.raw); 258 zfree(&ops->source.raw);
260 ops->source.raw = NULL;
261 return -1; 259 return -1;
262} 260}
263 261
@@ -464,17 +462,12 @@ void symbol__annotate_zero_histograms(struct symbol *sym)
464 pthread_mutex_unlock(&notes->lock); 462 pthread_mutex_unlock(&notes->lock);
465} 463}
466 464
467int symbol__inc_addr_samples(struct symbol *sym, struct map *map, 465static int __symbol__inc_addr_samples(struct symbol *sym, struct map *map,
468 int evidx, u64 addr) 466 struct annotation *notes, int evidx, u64 addr)
469{ 467{
470 unsigned offset; 468 unsigned offset;
471 struct annotation *notes;
472 struct sym_hist *h; 469 struct sym_hist *h;
473 470
474 notes = symbol__annotation(sym);
475 if (notes->src == NULL)
476 return -ENOMEM;
477
478 pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr)); 471 pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr));
479 472
480 if (addr < sym->start || addr > sym->end) 473 if (addr < sym->start || addr > sym->end)
@@ -491,6 +484,33 @@ int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
491 return 0; 484 return 0;
492} 485}
493 486
487static int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
488 int evidx, u64 addr)
489{
490 struct annotation *notes;
491
492 if (sym == NULL || use_browser != 1 || !sort__has_sym)
493 return 0;
494
495 notes = symbol__annotation(sym);
496 if (notes->src == NULL) {
497 if (symbol__alloc_hist(sym) < 0)
498 return -ENOMEM;
499 }
500
501 return __symbol__inc_addr_samples(sym, map, notes, evidx, addr);
502}
503
504int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, int evidx)
505{
506 return symbol__inc_addr_samples(ams->sym, ams->map, evidx, ams->al_addr);
507}
508
509int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 ip)
510{
511 return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evidx, ip);
512}
513
494static void disasm_line__init_ins(struct disasm_line *dl) 514static void disasm_line__init_ins(struct disasm_line *dl)
495{ 515{
496 dl->ins = ins__find(dl->name); 516 dl->ins = ins__find(dl->name);
@@ -538,8 +558,7 @@ static int disasm_line__parse(char *line, char **namep, char **rawp)
538 return 0; 558 return 0;
539 559
540out_free_name: 560out_free_name:
541 free(*namep); 561 zfree(namep);
542 *namep = NULL;
543 return -1; 562 return -1;
544} 563}
545 564
@@ -564,7 +583,7 @@ static struct disasm_line *disasm_line__new(s64 offset, char *line, size_t privs
564 return dl; 583 return dl;
565 584
566out_free_line: 585out_free_line:
567 free(dl->line); 586 zfree(&dl->line);
568out_delete: 587out_delete:
569 free(dl); 588 free(dl);
570 return NULL; 589 return NULL;
@@ -572,8 +591,8 @@ out_delete:
572 591
573void disasm_line__free(struct disasm_line *dl) 592void disasm_line__free(struct disasm_line *dl)
574{ 593{
575 free(dl->line); 594 zfree(&dl->line);
576 free(dl->name); 595 zfree(&dl->name);
577 if (dl->ins && dl->ins->ops->free) 596 if (dl->ins && dl->ins->ops->free)
578 dl->ins->ops->free(&dl->ops); 597 dl->ins->ops->free(&dl->ops);
579 else 598 else
@@ -900,7 +919,7 @@ fallback:
900 * cache, or is just a kallsyms file, well, lets hope that this 919 * cache, or is just a kallsyms file, well, lets hope that this
901 * DSO is the same as when 'perf record' ran. 920 * DSO is the same as when 'perf record' ran.
902 */ 921 */
903 filename = dso->long_name; 922 filename = (char *)dso->long_name;
904 snprintf(symfs_filename, sizeof(symfs_filename), "%s%s", 923 snprintf(symfs_filename, sizeof(symfs_filename), "%s%s",
905 symbol_conf.symfs, filename); 924 symbol_conf.symfs, filename);
906 free_filename = false; 925 free_filename = false;
@@ -1091,8 +1110,7 @@ static void symbol__free_source_line(struct symbol *sym, int len)
1091 src_line = (void *)src_line + sizeof_src_line; 1110 src_line = (void *)src_line + sizeof_src_line;
1092 } 1111 }
1093 1112
1094 free(notes->src->lines); 1113 zfree(&notes->src->lines);
1095 notes->src->lines = NULL;
1096} 1114}
1097 1115
1098/* Get the filename:line for the colored entries */ 1116/* Get the filename:line for the colored entries */
@@ -1376,3 +1394,8 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map,
1376 1394
1377 return 0; 1395 return 0;
1378} 1396}
1397
1398int hist_entry__annotate(struct hist_entry *he, size_t privsize)
1399{
1400 return symbol__annotate(he->ms.sym, he->ms.map, privsize);
1401}
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index 834b7b57b788..b2aef59d6bb2 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -132,12 +132,17 @@ static inline struct annotation *symbol__annotation(struct symbol *sym)
132 return &a->annotation; 132 return &a->annotation;
133} 133}
134 134
135int symbol__inc_addr_samples(struct symbol *sym, struct map *map, 135int addr_map_symbol__inc_samples(struct addr_map_symbol *ams, int evidx);
136 int evidx, u64 addr); 136
137int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 addr);
138
137int symbol__alloc_hist(struct symbol *sym); 139int symbol__alloc_hist(struct symbol *sym);
138void symbol__annotate_zero_histograms(struct symbol *sym); 140void symbol__annotate_zero_histograms(struct symbol *sym);
139 141
140int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize); 142int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize);
143
144int hist_entry__annotate(struct hist_entry *he, size_t privsize);
145
141int symbol__annotate_init(struct map *map __maybe_unused, struct symbol *sym); 146int symbol__annotate_init(struct map *map __maybe_unused, struct symbol *sym);
142int symbol__annotate_printf(struct symbol *sym, struct map *map, 147int symbol__annotate_printf(struct symbol *sym, struct map *map,
143 struct perf_evsel *evsel, bool full_paths, 148 struct perf_evsel *evsel, bool full_paths,
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index a92770c98cc7..6baabe63182b 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -89,7 +89,7 @@ int build_id__sprintf(const u8 *build_id, int len, char *bf)
89 return raw - build_id; 89 return raw - build_id;
90} 90}
91 91
92char *dso__build_id_filename(struct dso *dso, char *bf, size_t size) 92char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size)
93{ 93{
94 char build_id_hex[BUILD_ID_SIZE * 2 + 1]; 94 char build_id_hex[BUILD_ID_SIZE * 2 + 1];
95 95
diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h
index 929f28a7c14d..845ef865eced 100644
--- a/tools/perf/util/build-id.h
+++ b/tools/perf/util/build-id.h
@@ -10,7 +10,7 @@ extern struct perf_tool build_id__mark_dso_hit_ops;
10struct dso; 10struct dso;
11 11
12int build_id__sprintf(const u8 *build_id, int len, char *bf); 12int build_id__sprintf(const u8 *build_id, int len, char *bf);
13char *dso__build_id_filename(struct dso *dso, char *bf, size_t size); 13char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size);
14 14
15int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event, 15int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event,
16 struct perf_sample *sample, struct perf_evsel *evsel, 16 struct perf_sample *sample, struct perf_evsel *evsel,
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index e3970e3eaacf..8d9db454f1a9 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -15,8 +15,12 @@
15#include <errno.h> 15#include <errno.h>
16#include <math.h> 16#include <math.h>
17 17
18#include "asm/bug.h"
19
18#include "hist.h" 20#include "hist.h"
19#include "util.h" 21#include "util.h"
22#include "sort.h"
23#include "machine.h"
20#include "callchain.h" 24#include "callchain.h"
21 25
22__thread struct callchain_cursor callchain_cursor; 26__thread struct callchain_cursor callchain_cursor;
@@ -356,19 +360,14 @@ append_chain_children(struct callchain_node *root,
356 /* lookup in childrens */ 360 /* lookup in childrens */
357 while (*p) { 361 while (*p) {
358 s64 ret; 362 s64 ret;
359 struct callchain_list *cnode;
360 363
361 parent = *p; 364 parent = *p;
362 rnode = rb_entry(parent, struct callchain_node, rb_node_in); 365 rnode = rb_entry(parent, struct callchain_node, rb_node_in);
363 cnode = list_first_entry(&rnode->val, struct callchain_list,
364 list);
365 366
366 /* just check first entry */ 367 /* If at least first entry matches, rely to children */
367 ret = match_chain(node, cnode); 368 ret = append_chain(rnode, cursor, period);
368 if (ret == 0) { 369 if (ret == 0)
369 append_chain(rnode, cursor, period);
370 goto inc_children_hit; 370 goto inc_children_hit;
371 }
372 371
373 if (ret < 0) 372 if (ret < 0)
374 p = &parent->rb_left; 373 p = &parent->rb_left;
@@ -389,11 +388,11 @@ append_chain(struct callchain_node *root,
389 struct callchain_cursor *cursor, 388 struct callchain_cursor *cursor,
390 u64 period) 389 u64 period)
391{ 390{
392 struct callchain_cursor_node *curr_snap = cursor->curr;
393 struct callchain_list *cnode; 391 struct callchain_list *cnode;
394 u64 start = cursor->pos; 392 u64 start = cursor->pos;
395 bool found = false; 393 bool found = false;
396 u64 matches; 394 u64 matches;
395 int cmp = 0;
397 396
398 /* 397 /*
399 * Lookup in the current node 398 * Lookup in the current node
@@ -408,7 +407,8 @@ append_chain(struct callchain_node *root,
408 if (!node) 407 if (!node)
409 break; 408 break;
410 409
411 if (match_chain(node, cnode) != 0) 410 cmp = match_chain(node, cnode);
411 if (cmp)
412 break; 412 break;
413 413
414 found = true; 414 found = true;
@@ -418,9 +418,8 @@ append_chain(struct callchain_node *root,
418 418
419 /* matches not, relay no the parent */ 419 /* matches not, relay no the parent */
420 if (!found) { 420 if (!found) {
421 cursor->curr = curr_snap; 421 WARN_ONCE(!cmp, "Chain comparison error\n");
422 cursor->pos = start; 422 return cmp;
423 return -1;
424 } 423 }
425 424
426 matches = cursor->pos - start; 425 matches = cursor->pos - start;
@@ -531,3 +530,24 @@ int callchain_cursor_append(struct callchain_cursor *cursor,
531 530
532 return 0; 531 return 0;
533} 532}
533
534int sample__resolve_callchain(struct perf_sample *sample, struct symbol **parent,
535 struct perf_evsel *evsel, struct addr_location *al,
536 int max_stack)
537{
538 if (sample->callchain == NULL)
539 return 0;
540
541 if (symbol_conf.use_callchain || sort__has_parent) {
542 return machine__resolve_callchain(al->machine, evsel, al->thread,
543 sample, parent, al, max_stack);
544 }
545 return 0;
546}
547
548int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample)
549{
550 if (!symbol_conf.use_callchain)
551 return 0;
552 return callchain_append(he->callchain, &callchain_cursor, sample->period);
553}
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index 4f7f989876ec..8ad97e9b119f 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -145,10 +145,16 @@ static inline void callchain_cursor_advance(struct callchain_cursor *cursor)
145} 145}
146 146
147struct option; 147struct option;
148struct hist_entry;
148 149
149int record_parse_callchain(const char *arg, struct perf_record_opts *opts); 150int record_parse_callchain(const char *arg, struct record_opts *opts);
150int record_parse_callchain_opt(const struct option *opt, const char *arg, int unset); 151int record_parse_callchain_opt(const struct option *opt, const char *arg, int unset);
151int record_callchain_opt(const struct option *opt, const char *arg, int unset); 152int record_callchain_opt(const struct option *opt, const char *arg, int unset);
152 153
154int sample__resolve_callchain(struct perf_sample *sample, struct symbol **parent,
155 struct perf_evsel *evsel, struct addr_location *al,
156 int max_stack);
157int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample);
158
153extern const char record_callchain_help[]; 159extern const char record_callchain_help[];
154#endif /* __PERF_CALLCHAIN_H */ 160#endif /* __PERF_CALLCHAIN_H */
diff --git a/tools/perf/util/cgroup.c b/tools/perf/util/cgroup.c
index 96bbda1ddb83..88f7be399432 100644
--- a/tools/perf/util/cgroup.c
+++ b/tools/perf/util/cgroup.c
@@ -81,7 +81,7 @@ static int add_cgroup(struct perf_evlist *evlist, char *str)
81 /* 81 /*
82 * check if cgrp is already defined, if so we reuse it 82 * check if cgrp is already defined, if so we reuse it
83 */ 83 */
84 list_for_each_entry(counter, &evlist->entries, node) { 84 evlist__for_each(evlist, counter) {
85 cgrp = counter->cgrp; 85 cgrp = counter->cgrp;
86 if (!cgrp) 86 if (!cgrp)
87 continue; 87 continue;
@@ -110,7 +110,7 @@ static int add_cgroup(struct perf_evlist *evlist, char *str)
110 * if add cgroup N, then need to find event N 110 * if add cgroup N, then need to find event N
111 */ 111 */
112 n = 0; 112 n = 0;
113 list_for_each_entry(counter, &evlist->entries, node) { 113 evlist__for_each(evlist, counter) {
114 if (n == nr_cgroups) 114 if (n == nr_cgroups)
115 goto found; 115 goto found;
116 n++; 116 n++;
@@ -133,7 +133,7 @@ void close_cgroup(struct cgroup_sel *cgrp)
133 /* XXX: not reentrant */ 133 /* XXX: not reentrant */
134 if (--cgrp->refcnt == 0) { 134 if (--cgrp->refcnt == 0) {
135 close(cgrp->fd); 135 close(cgrp->fd);
136 free(cgrp->name); 136 zfree(&cgrp->name);
137 free(cgrp); 137 free(cgrp);
138 } 138 }
139} 139}
diff --git a/tools/perf/util/color.c b/tools/perf/util/color.c
index 66e44a5019d5..87b8672eb413 100644
--- a/tools/perf/util/color.c
+++ b/tools/perf/util/color.c
@@ -1,6 +1,7 @@
1#include <linux/kernel.h> 1#include <linux/kernel.h>
2#include "cache.h" 2#include "cache.h"
3#include "color.h" 3#include "color.h"
4#include <math.h>
4 5
5int perf_use_color_default = -1; 6int perf_use_color_default = -1;
6 7
@@ -298,10 +299,10 @@ const char *get_percent_color(double percent)
298 * entries in green - and keep the low overhead places 299 * entries in green - and keep the low overhead places
299 * normal: 300 * normal:
300 */ 301 */
301 if (percent >= MIN_RED) 302 if (fabs(percent) >= MIN_RED)
302 color = PERF_COLOR_RED; 303 color = PERF_COLOR_RED;
303 else { 304 else {
304 if (percent > MIN_GREEN) 305 if (fabs(percent) > MIN_GREEN)
305 color = PERF_COLOR_GREEN; 306 color = PERF_COLOR_GREEN;
306 } 307 }
307 return color; 308 return color;
@@ -318,15 +319,19 @@ int percent_color_fprintf(FILE *fp, const char *fmt, double percent)
318 return r; 319 return r;
319} 320}
320 321
322int value_color_snprintf(char *bf, size_t size, const char *fmt, double value)
323{
324 const char *color = get_percent_color(value);
325 return color_snprintf(bf, size, color, fmt, value);
326}
327
321int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...) 328int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...)
322{ 329{
323 va_list args; 330 va_list args;
324 double percent; 331 double percent;
325 const char *color;
326 332
327 va_start(args, fmt); 333 va_start(args, fmt);
328 percent = va_arg(args, double); 334 percent = va_arg(args, double);
329 va_end(args); 335 va_end(args);
330 color = get_percent_color(percent); 336 return value_color_snprintf(bf, size, fmt, percent);
331 return color_snprintf(bf, size, color, fmt, percent);
332} 337}
diff --git a/tools/perf/util/color.h b/tools/perf/util/color.h
index fced3840e99c..7ff30a62a132 100644
--- a/tools/perf/util/color.h
+++ b/tools/perf/util/color.h
@@ -39,6 +39,7 @@ int color_fprintf(FILE *fp, const char *color, const char *fmt, ...);
39int color_snprintf(char *bf, size_t size, const char *color, const char *fmt, ...); 39int color_snprintf(char *bf, size_t size, const char *color, const char *fmt, ...);
40int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...); 40int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...);
41int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf); 41int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf);
42int value_color_snprintf(char *bf, size_t size, const char *fmt, double value);
42int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...); 43int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...);
43int percent_color_fprintf(FILE *fp, const char *fmt, double percent); 44int percent_color_fprintf(FILE *fp, const char *fmt, double percent);
44const char *get_percent_color(double percent); 45const char *get_percent_color(double percent);
diff --git a/tools/perf/util/comm.c b/tools/perf/util/comm.c
index ee0df0e24cdb..f9e777629e21 100644
--- a/tools/perf/util/comm.c
+++ b/tools/perf/util/comm.c
@@ -21,7 +21,7 @@ static void comm_str__put(struct comm_str *cs)
21{ 21{
22 if (!--cs->ref) { 22 if (!--cs->ref) {
23 rb_erase(&cs->rb_node, &comm_str_root); 23 rb_erase(&cs->rb_node, &comm_str_root);
24 free(cs->str); 24 zfree(&cs->str);
25 free(cs); 25 free(cs);
26 } 26 }
27} 27}
@@ -94,19 +94,20 @@ struct comm *comm__new(const char *str, u64 timestamp)
94 return comm; 94 return comm;
95} 95}
96 96
97void comm__override(struct comm *comm, const char *str, u64 timestamp) 97int comm__override(struct comm *comm, const char *str, u64 timestamp)
98{ 98{
99 struct comm_str *old = comm->comm_str; 99 struct comm_str *new, *old = comm->comm_str;
100 100
101 comm->comm_str = comm_str__findnew(str, &comm_str_root); 101 new = comm_str__findnew(str, &comm_str_root);
102 if (!comm->comm_str) { 102 if (!new)
103 comm->comm_str = old; 103 return -ENOMEM;
104 return;
105 }
106 104
107 comm->start = timestamp; 105 comm_str__get(new);
108 comm_str__get(comm->comm_str);
109 comm_str__put(old); 106 comm_str__put(old);
107 comm->comm_str = new;
108 comm->start = timestamp;
109
110 return 0;
110} 111}
111 112
112void comm__free(struct comm *comm) 113void comm__free(struct comm *comm)
diff --git a/tools/perf/util/comm.h b/tools/perf/util/comm.h
index 7a86e5656710..fac5bd51befc 100644
--- a/tools/perf/util/comm.h
+++ b/tools/perf/util/comm.h
@@ -16,6 +16,6 @@ struct comm {
16void comm__free(struct comm *comm); 16void comm__free(struct comm *comm);
17struct comm *comm__new(const char *str, u64 timestamp); 17struct comm *comm__new(const char *str, u64 timestamp);
18const char *comm__str(const struct comm *comm); 18const char *comm__str(const struct comm *comm);
19void comm__override(struct comm *comm, const char *str, u64 timestamp); 19int comm__override(struct comm *comm, const char *str, u64 timestamp);
20 20
21#endif /* __PERF_COMM_H */ 21#endif /* __PERF_COMM_H */
diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c
index 7d09faf85cf1..1fbcd8bdc11b 100644
--- a/tools/perf/util/data.c
+++ b/tools/perf/util/data.c
@@ -118,3 +118,9 @@ void perf_data_file__close(struct perf_data_file *file)
118{ 118{
119 close(file->fd); 119 close(file->fd);
120} 120}
121
122ssize_t perf_data_file__write(struct perf_data_file *file,
123 void *buf, size_t size)
124{
125 return writen(file->fd, buf, size);
126}
diff --git a/tools/perf/util/data.h b/tools/perf/util/data.h
index 8c2df80152a5..2b15d0c95c7f 100644
--- a/tools/perf/util/data.h
+++ b/tools/perf/util/data.h
@@ -9,12 +9,12 @@ enum perf_data_mode {
9}; 9};
10 10
11struct perf_data_file { 11struct perf_data_file {
12 const char *path; 12 const char *path;
13 int fd; 13 int fd;
14 bool is_pipe; 14 bool is_pipe;
15 bool force; 15 bool force;
16 unsigned long size; 16 unsigned long size;
17 enum perf_data_mode mode; 17 enum perf_data_mode mode;
18}; 18};
19 19
20static inline bool perf_data_file__is_read(struct perf_data_file *file) 20static inline bool perf_data_file__is_read(struct perf_data_file *file)
@@ -44,5 +44,7 @@ static inline unsigned long perf_data_file__size(struct perf_data_file *file)
44 44
45int perf_data_file__open(struct perf_data_file *file); 45int perf_data_file__open(struct perf_data_file *file);
46void perf_data_file__close(struct perf_data_file *file); 46void perf_data_file__close(struct perf_data_file *file);
47ssize_t perf_data_file__write(struct perf_data_file *file,
48 void *buf, size_t size);
47 49
48#endif /* __PERF_DATA_H */ 50#endif /* __PERF_DATA_H */
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index 399e74c34c1a..299b55586502 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -16,23 +16,46 @@
16int verbose; 16int verbose;
17bool dump_trace = false, quiet = false; 17bool dump_trace = false, quiet = false;
18 18
19int eprintf(int level, const char *fmt, ...) 19static int _eprintf(int level, const char *fmt, va_list args)
20{ 20{
21 va_list args;
22 int ret = 0; 21 int ret = 0;
23 22
24 if (verbose >= level) { 23 if (verbose >= level) {
25 va_start(args, fmt);
26 if (use_browser >= 1) 24 if (use_browser >= 1)
27 ui_helpline__vshow(fmt, args); 25 ui_helpline__vshow(fmt, args);
28 else 26 else
29 ret = vfprintf(stderr, fmt, args); 27 ret = vfprintf(stderr, fmt, args);
30 va_end(args);
31 } 28 }
32 29
33 return ret; 30 return ret;
34} 31}
35 32
33int eprintf(int level, const char *fmt, ...)
34{
35 va_list args;
36 int ret;
37
38 va_start(args, fmt);
39 ret = _eprintf(level, fmt, args);
40 va_end(args);
41
42 return ret;
43}
44
45/*
46 * Overloading libtraceevent standard info print
47 * function, display with -v in perf.
48 */
49void pr_stat(const char *fmt, ...)
50{
51 va_list args;
52
53 va_start(args, fmt);
54 _eprintf(1, fmt, args);
55 va_end(args);
56 eprintf(1, "\n");
57}
58
36int dump_printf(const char *fmt, ...) 59int dump_printf(const char *fmt, ...)
37{ 60{
38 va_list args; 61 va_list args;
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index efbd98805ad0..443694c36b03 100644
--- a/tools/perf/util/debug.h
+++ b/tools/perf/util/debug.h
@@ -17,4 +17,6 @@ void trace_event(union perf_event *event);
17int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2))); 17int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2)));
18int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2))); 18int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2)));
19 19
20void pr_stat(const char *fmt, ...);
21
20#endif /* __PERF_DEBUG_H */ 22#endif /* __PERF_DEBUG_H */
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index af4c687cc49b..4045d086d9d9 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -28,8 +28,9 @@ char dso__symtab_origin(const struct dso *dso)
28 return origin[dso->symtab_type]; 28 return origin[dso->symtab_type];
29} 29}
30 30
31int dso__binary_type_file(struct dso *dso, enum dso_binary_type type, 31int dso__read_binary_type_filename(const struct dso *dso,
32 char *root_dir, char *file, size_t size) 32 enum dso_binary_type type,
33 char *root_dir, char *filename, size_t size)
33{ 34{
34 char build_id_hex[BUILD_ID_SIZE * 2 + 1]; 35 char build_id_hex[BUILD_ID_SIZE * 2 + 1];
35 int ret = 0; 36 int ret = 0;
@@ -38,36 +39,36 @@ int dso__binary_type_file(struct dso *dso, enum dso_binary_type type,
38 case DSO_BINARY_TYPE__DEBUGLINK: { 39 case DSO_BINARY_TYPE__DEBUGLINK: {
39 char *debuglink; 40 char *debuglink;
40 41
41 strncpy(file, dso->long_name, size); 42 strncpy(filename, dso->long_name, size);
42 debuglink = file + dso->long_name_len; 43 debuglink = filename + dso->long_name_len;
43 while (debuglink != file && *debuglink != '/') 44 while (debuglink != filename && *debuglink != '/')
44 debuglink--; 45 debuglink--;
45 if (*debuglink == '/') 46 if (*debuglink == '/')
46 debuglink++; 47 debuglink++;
47 filename__read_debuglink(dso->long_name, debuglink, 48 filename__read_debuglink(dso->long_name, debuglink,
48 size - (debuglink - file)); 49 size - (debuglink - filename));
49 } 50 }
50 break; 51 break;
51 case DSO_BINARY_TYPE__BUILD_ID_CACHE: 52 case DSO_BINARY_TYPE__BUILD_ID_CACHE:
52 /* skip the locally configured cache if a symfs is given */ 53 /* skip the locally configured cache if a symfs is given */
53 if (symbol_conf.symfs[0] || 54 if (symbol_conf.symfs[0] ||
54 (dso__build_id_filename(dso, file, size) == NULL)) 55 (dso__build_id_filename(dso, filename, size) == NULL))
55 ret = -1; 56 ret = -1;
56 break; 57 break;
57 58
58 case DSO_BINARY_TYPE__FEDORA_DEBUGINFO: 59 case DSO_BINARY_TYPE__FEDORA_DEBUGINFO:
59 snprintf(file, size, "%s/usr/lib/debug%s.debug", 60 snprintf(filename, size, "%s/usr/lib/debug%s.debug",
60 symbol_conf.symfs, dso->long_name); 61 symbol_conf.symfs, dso->long_name);
61 break; 62 break;
62 63
63 case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO: 64 case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO:
64 snprintf(file, size, "%s/usr/lib/debug%s", 65 snprintf(filename, size, "%s/usr/lib/debug%s",
65 symbol_conf.symfs, dso->long_name); 66 symbol_conf.symfs, dso->long_name);
66 break; 67 break;
67 68
68 case DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO: 69 case DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO:
69 { 70 {
70 char *last_slash; 71 const char *last_slash;
71 size_t len; 72 size_t len;
72 size_t dir_size; 73 size_t dir_size;
73 74
@@ -75,14 +76,14 @@ int dso__binary_type_file(struct dso *dso, enum dso_binary_type type,
75 while (last_slash != dso->long_name && *last_slash != '/') 76 while (last_slash != dso->long_name && *last_slash != '/')
76 last_slash--; 77 last_slash--;
77 78
78 len = scnprintf(file, size, "%s", symbol_conf.symfs); 79 len = scnprintf(filename, size, "%s", symbol_conf.symfs);
79 dir_size = last_slash - dso->long_name + 2; 80 dir_size = last_slash - dso->long_name + 2;
80 if (dir_size > (size - len)) { 81 if (dir_size > (size - len)) {
81 ret = -1; 82 ret = -1;
82 break; 83 break;
83 } 84 }
84 len += scnprintf(file + len, dir_size, "%s", dso->long_name); 85 len += scnprintf(filename + len, dir_size, "%s", dso->long_name);
85 len += scnprintf(file + len , size - len, ".debug%s", 86 len += scnprintf(filename + len , size - len, ".debug%s",
86 last_slash); 87 last_slash);
87 break; 88 break;
88 } 89 }
@@ -96,7 +97,7 @@ int dso__binary_type_file(struct dso *dso, enum dso_binary_type type,
96 build_id__sprintf(dso->build_id, 97 build_id__sprintf(dso->build_id,
97 sizeof(dso->build_id), 98 sizeof(dso->build_id),
98 build_id_hex); 99 build_id_hex);
99 snprintf(file, size, 100 snprintf(filename, size,
100 "%s/usr/lib/debug/.build-id/%.2s/%s.debug", 101 "%s/usr/lib/debug/.build-id/%.2s/%s.debug",
101 symbol_conf.symfs, build_id_hex, build_id_hex + 2); 102 symbol_conf.symfs, build_id_hex, build_id_hex + 2);
102 break; 103 break;
@@ -104,23 +105,23 @@ int dso__binary_type_file(struct dso *dso, enum dso_binary_type type,
104 case DSO_BINARY_TYPE__VMLINUX: 105 case DSO_BINARY_TYPE__VMLINUX:
105 case DSO_BINARY_TYPE__GUEST_VMLINUX: 106 case DSO_BINARY_TYPE__GUEST_VMLINUX:
106 case DSO_BINARY_TYPE__SYSTEM_PATH_DSO: 107 case DSO_BINARY_TYPE__SYSTEM_PATH_DSO:
107 snprintf(file, size, "%s%s", 108 snprintf(filename, size, "%s%s",
108 symbol_conf.symfs, dso->long_name); 109 symbol_conf.symfs, dso->long_name);
109 break; 110 break;
110 111
111 case DSO_BINARY_TYPE__GUEST_KMODULE: 112 case DSO_BINARY_TYPE__GUEST_KMODULE:
112 snprintf(file, size, "%s%s%s", symbol_conf.symfs, 113 snprintf(filename, size, "%s%s%s", symbol_conf.symfs,
113 root_dir, dso->long_name); 114 root_dir, dso->long_name);
114 break; 115 break;
115 116
116 case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE: 117 case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE:
117 snprintf(file, size, "%s%s", symbol_conf.symfs, 118 snprintf(filename, size, "%s%s", symbol_conf.symfs,
118 dso->long_name); 119 dso->long_name);
119 break; 120 break;
120 121
121 case DSO_BINARY_TYPE__KCORE: 122 case DSO_BINARY_TYPE__KCORE:
122 case DSO_BINARY_TYPE__GUEST_KCORE: 123 case DSO_BINARY_TYPE__GUEST_KCORE:
123 snprintf(file, size, "%s", dso->long_name); 124 snprintf(filename, size, "%s", dso->long_name);
124 break; 125 break;
125 126
126 default: 127 default:
@@ -137,19 +138,18 @@ int dso__binary_type_file(struct dso *dso, enum dso_binary_type type,
137 138
138static int open_dso(struct dso *dso, struct machine *machine) 139static int open_dso(struct dso *dso, struct machine *machine)
139{ 140{
140 char *root_dir = (char *) "";
141 char *name;
142 int fd; 141 int fd;
142 char *root_dir = (char *)"";
143 char *name = malloc(PATH_MAX);
143 144
144 name = malloc(PATH_MAX);
145 if (!name) 145 if (!name)
146 return -ENOMEM; 146 return -ENOMEM;
147 147
148 if (machine) 148 if (machine)
149 root_dir = machine->root_dir; 149 root_dir = machine->root_dir;
150 150
151 if (dso__binary_type_file(dso, dso->data_type, 151 if (dso__read_binary_type_filename(dso, dso->binary_type,
152 root_dir, name, PATH_MAX)) { 152 root_dir, name, PATH_MAX)) {
153 free(name); 153 free(name);
154 return -EINVAL; 154 return -EINVAL;
155 } 155 }
@@ -161,26 +161,26 @@ static int open_dso(struct dso *dso, struct machine *machine)
161 161
162int dso__data_fd(struct dso *dso, struct machine *machine) 162int dso__data_fd(struct dso *dso, struct machine *machine)
163{ 163{
164 static enum dso_binary_type binary_type_data[] = { 164 enum dso_binary_type binary_type_data[] = {
165 DSO_BINARY_TYPE__BUILD_ID_CACHE, 165 DSO_BINARY_TYPE__BUILD_ID_CACHE,
166 DSO_BINARY_TYPE__SYSTEM_PATH_DSO, 166 DSO_BINARY_TYPE__SYSTEM_PATH_DSO,
167 DSO_BINARY_TYPE__NOT_FOUND, 167 DSO_BINARY_TYPE__NOT_FOUND,
168 }; 168 };
169 int i = 0; 169 int i = 0;
170 170
171 if (dso->data_type != DSO_BINARY_TYPE__NOT_FOUND) 171 if (dso->binary_type != DSO_BINARY_TYPE__NOT_FOUND)
172 return open_dso(dso, machine); 172 return open_dso(dso, machine);
173 173
174 do { 174 do {
175 int fd; 175 int fd;
176 176
177 dso->data_type = binary_type_data[i++]; 177 dso->binary_type = binary_type_data[i++];
178 178
179 fd = open_dso(dso, machine); 179 fd = open_dso(dso, machine);
180 if (fd >= 0) 180 if (fd >= 0)
181 return fd; 181 return fd;
182 182
183 } while (dso->data_type != DSO_BINARY_TYPE__NOT_FOUND); 183 } while (dso->binary_type != DSO_BINARY_TYPE__NOT_FOUND);
184 184
185 return -EINVAL; 185 return -EINVAL;
186} 186}
@@ -200,11 +200,10 @@ dso_cache__free(struct rb_root *root)
200 } 200 }
201} 201}
202 202
203static struct dso_cache* 203static struct dso_cache *dso_cache__find(const struct rb_root *root, u64 offset)
204dso_cache__find(struct rb_root *root, u64 offset)
205{ 204{
206 struct rb_node **p = &root->rb_node; 205 struct rb_node * const *p = &root->rb_node;
207 struct rb_node *parent = NULL; 206 const struct rb_node *parent = NULL;
208 struct dso_cache *cache; 207 struct dso_cache *cache;
209 208
210 while (*p != NULL) { 209 while (*p != NULL) {
@@ -379,32 +378,63 @@ struct dso *dso__kernel_findnew(struct machine *machine, const char *name,
379 * processing we had no idea this was the kernel dso. 378 * processing we had no idea this was the kernel dso.
380 */ 379 */
381 if (dso != NULL) { 380 if (dso != NULL) {
382 dso__set_short_name(dso, short_name); 381 dso__set_short_name(dso, short_name, false);
383 dso->kernel = dso_type; 382 dso->kernel = dso_type;
384 } 383 }
385 384
386 return dso; 385 return dso;
387} 386}
388 387
389void dso__set_long_name(struct dso *dso, char *name) 388void dso__set_long_name(struct dso *dso, const char *name, bool name_allocated)
390{ 389{
391 if (name == NULL) 390 if (name == NULL)
392 return; 391 return;
393 dso->long_name = name; 392
394 dso->long_name_len = strlen(name); 393 if (dso->long_name_allocated)
394 free((char *)dso->long_name);
395
396 dso->long_name = name;
397 dso->long_name_len = strlen(name);
398 dso->long_name_allocated = name_allocated;
395} 399}
396 400
397void dso__set_short_name(struct dso *dso, const char *name) 401void dso__set_short_name(struct dso *dso, const char *name, bool name_allocated)
398{ 402{
399 if (name == NULL) 403 if (name == NULL)
400 return; 404 return;
401 dso->short_name = name; 405
402 dso->short_name_len = strlen(name); 406 if (dso->short_name_allocated)
407 free((char *)dso->short_name);
408
409 dso->short_name = name;
410 dso->short_name_len = strlen(name);
411 dso->short_name_allocated = name_allocated;
403} 412}
404 413
405static void dso__set_basename(struct dso *dso) 414static void dso__set_basename(struct dso *dso)
406{ 415{
407 dso__set_short_name(dso, basename(dso->long_name)); 416 /*
417 * basename() may modify path buffer, so we must pass
418 * a copy.
419 */
420 char *base, *lname = strdup(dso->long_name);
421
422 if (!lname)
423 return;
424
425 /*
426 * basename() may return a pointer to internal
427 * storage which is reused in subsequent calls
428 * so copy the result.
429 */
430 base = strdup(basename(lname));
431
432 free(lname);
433
434 if (!base)
435 return;
436
437 dso__set_short_name(dso, base, true);
408} 438}
409 439
410int dso__name_len(const struct dso *dso) 440int dso__name_len(const struct dso *dso)
@@ -439,18 +469,19 @@ struct dso *dso__new(const char *name)
439 if (dso != NULL) { 469 if (dso != NULL) {
440 int i; 470 int i;
441 strcpy(dso->name, name); 471 strcpy(dso->name, name);
442 dso__set_long_name(dso, dso->name); 472 dso__set_long_name(dso, dso->name, false);
443 dso__set_short_name(dso, dso->name); 473 dso__set_short_name(dso, dso->name, false);
444 for (i = 0; i < MAP__NR_TYPES; ++i) 474 for (i = 0; i < MAP__NR_TYPES; ++i)
445 dso->symbols[i] = dso->symbol_names[i] = RB_ROOT; 475 dso->symbols[i] = dso->symbol_names[i] = RB_ROOT;
446 dso->cache = RB_ROOT; 476 dso->cache = RB_ROOT;
447 dso->symtab_type = DSO_BINARY_TYPE__NOT_FOUND; 477 dso->symtab_type = DSO_BINARY_TYPE__NOT_FOUND;
448 dso->data_type = DSO_BINARY_TYPE__NOT_FOUND; 478 dso->binary_type = DSO_BINARY_TYPE__NOT_FOUND;
449 dso->loaded = 0; 479 dso->loaded = 0;
450 dso->rel = 0; 480 dso->rel = 0;
451 dso->sorted_by_name = 0; 481 dso->sorted_by_name = 0;
452 dso->has_build_id = 0; 482 dso->has_build_id = 0;
453 dso->has_srcline = 1; 483 dso->has_srcline = 1;
484 dso->a2l_fails = 1;
454 dso->kernel = DSO_TYPE_USER; 485 dso->kernel = DSO_TYPE_USER;
455 dso->needs_swap = DSO_SWAP__UNSET; 486 dso->needs_swap = DSO_SWAP__UNSET;
456 INIT_LIST_HEAD(&dso->node); 487 INIT_LIST_HEAD(&dso->node);
@@ -464,11 +495,20 @@ void dso__delete(struct dso *dso)
464 int i; 495 int i;
465 for (i = 0; i < MAP__NR_TYPES; ++i) 496 for (i = 0; i < MAP__NR_TYPES; ++i)
466 symbols__delete(&dso->symbols[i]); 497 symbols__delete(&dso->symbols[i]);
467 if (dso->sname_alloc) 498
468 free((char *)dso->short_name); 499 if (dso->short_name_allocated) {
469 if (dso->lname_alloc) 500 zfree((char **)&dso->short_name);
470 free(dso->long_name); 501 dso->short_name_allocated = false;
502 }
503
504 if (dso->long_name_allocated) {
505 zfree((char **)&dso->long_name);
506 dso->long_name_allocated = false;
507 }
508
471 dso_cache__free(&dso->cache); 509 dso_cache__free(&dso->cache);
510 dso__free_a2l(dso);
511 zfree(&dso->symsrc_filename);
472 free(dso); 512 free(dso);
473} 513}
474 514
@@ -543,7 +583,7 @@ void dsos__add(struct list_head *head, struct dso *dso)
543 list_add_tail(&dso->node, head); 583 list_add_tail(&dso->node, head);
544} 584}
545 585
546struct dso *dsos__find(struct list_head *head, const char *name, bool cmp_short) 586struct dso *dsos__find(const struct list_head *head, const char *name, bool cmp_short)
547{ 587{
548 struct dso *pos; 588 struct dso *pos;
549 589
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index 9ac666abbe7e..cd7d6f078cdd 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -77,23 +77,26 @@ struct dso {
77 struct rb_root symbols[MAP__NR_TYPES]; 77 struct rb_root symbols[MAP__NR_TYPES];
78 struct rb_root symbol_names[MAP__NR_TYPES]; 78 struct rb_root symbol_names[MAP__NR_TYPES];
79 struct rb_root cache; 79 struct rb_root cache;
80 void *a2l;
81 char *symsrc_filename;
82 unsigned int a2l_fails;
80 enum dso_kernel_type kernel; 83 enum dso_kernel_type kernel;
81 enum dso_swap_type needs_swap; 84 enum dso_swap_type needs_swap;
82 enum dso_binary_type symtab_type; 85 enum dso_binary_type symtab_type;
83 enum dso_binary_type data_type; 86 enum dso_binary_type binary_type;
84 u8 adjust_symbols:1; 87 u8 adjust_symbols:1;
85 u8 has_build_id:1; 88 u8 has_build_id:1;
86 u8 has_srcline:1; 89 u8 has_srcline:1;
87 u8 hit:1; 90 u8 hit:1;
88 u8 annotate_warned:1; 91 u8 annotate_warned:1;
89 u8 sname_alloc:1; 92 u8 short_name_allocated:1;
90 u8 lname_alloc:1; 93 u8 long_name_allocated:1;
91 u8 sorted_by_name; 94 u8 sorted_by_name;
92 u8 loaded; 95 u8 loaded;
93 u8 rel; 96 u8 rel;
94 u8 build_id[BUILD_ID_SIZE]; 97 u8 build_id[BUILD_ID_SIZE];
95 const char *short_name; 98 const char *short_name;
96 char *long_name; 99 const char *long_name;
97 u16 long_name_len; 100 u16 long_name_len;
98 u16 short_name_len; 101 u16 short_name_len;
99 char name[0]; 102 char name[0];
@@ -107,8 +110,8 @@ static inline void dso__set_loaded(struct dso *dso, enum map_type type)
107struct dso *dso__new(const char *name); 110struct dso *dso__new(const char *name);
108void dso__delete(struct dso *dso); 111void dso__delete(struct dso *dso);
109 112
110void dso__set_short_name(struct dso *dso, const char *name); 113void dso__set_short_name(struct dso *dso, const char *name, bool name_allocated);
111void dso__set_long_name(struct dso *dso, char *name); 114void dso__set_long_name(struct dso *dso, const char *name, bool name_allocated);
112 115
113int dso__name_len(const struct dso *dso); 116int dso__name_len(const struct dso *dso);
114 117
@@ -125,8 +128,8 @@ void dso__read_running_kernel_build_id(struct dso *dso,
125int dso__kernel_module_get_build_id(struct dso *dso, const char *root_dir); 128int dso__kernel_module_get_build_id(struct dso *dso, const char *root_dir);
126 129
127char dso__symtab_origin(const struct dso *dso); 130char dso__symtab_origin(const struct dso *dso);
128int dso__binary_type_file(struct dso *dso, enum dso_binary_type type, 131int dso__read_binary_type_filename(const struct dso *dso, enum dso_binary_type type,
129 char *root_dir, char *file, size_t size); 132 char *root_dir, char *filename, size_t size);
130 133
131int dso__data_fd(struct dso *dso, struct machine *machine); 134int dso__data_fd(struct dso *dso, struct machine *machine);
132ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine, 135ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine,
@@ -140,7 +143,7 @@ struct dso *dso__kernel_findnew(struct machine *machine, const char *name,
140 const char *short_name, int dso_type); 143 const char *short_name, int dso_type);
141 144
142void dsos__add(struct list_head *head, struct dso *dso); 145void dsos__add(struct list_head *head, struct dso *dso);
143struct dso *dsos__find(struct list_head *head, const char *name, 146struct dso *dsos__find(const struct list_head *head, const char *name,
144 bool cmp_short); 147 bool cmp_short);
145struct dso *__dsos__findnew(struct list_head *head, const char *name); 148struct dso *__dsos__findnew(struct list_head *head, const char *name);
146bool __dsos__read_build_ids(struct list_head *head, bool with_hits); 149bool __dsos__read_build_ids(struct list_head *head, bool with_hits);
@@ -156,14 +159,16 @@ size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp);
156 159
157static inline bool dso__is_vmlinux(struct dso *dso) 160static inline bool dso__is_vmlinux(struct dso *dso)
158{ 161{
159 return dso->data_type == DSO_BINARY_TYPE__VMLINUX || 162 return dso->binary_type == DSO_BINARY_TYPE__VMLINUX ||
160 dso->data_type == DSO_BINARY_TYPE__GUEST_VMLINUX; 163 dso->binary_type == DSO_BINARY_TYPE__GUEST_VMLINUX;
161} 164}
162 165
163static inline bool dso__is_kcore(struct dso *dso) 166static inline bool dso__is_kcore(struct dso *dso)
164{ 167{
165 return dso->data_type == DSO_BINARY_TYPE__KCORE || 168 return dso->binary_type == DSO_BINARY_TYPE__KCORE ||
166 dso->data_type == DSO_BINARY_TYPE__GUEST_KCORE; 169 dso->binary_type == DSO_BINARY_TYPE__GUEST_KCORE;
167} 170}
168 171
172void dso__free_a2l(struct dso *dso);
173
169#endif /* __PERF_DSO */ 174#endif /* __PERF_DSO */
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index bb788c109fe6..1fc1c2f04772 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -7,6 +7,7 @@
7#include "strlist.h" 7#include "strlist.h"
8#include "thread.h" 8#include "thread.h"
9#include "thread_map.h" 9#include "thread_map.h"
10#include "symbol/kallsyms.h"
10 11
11static const char *perf_event__names[] = { 12static const char *perf_event__names[] = {
12 [0] = "TOTAL", 13 [0] = "TOTAL",
@@ -105,8 +106,12 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
105 106
106 memset(&event->comm, 0, sizeof(event->comm)); 107 memset(&event->comm, 0, sizeof(event->comm));
107 108
108 tgid = perf_event__get_comm_tgid(pid, event->comm.comm, 109 if (machine__is_host(machine))
109 sizeof(event->comm.comm)); 110 tgid = perf_event__get_comm_tgid(pid, event->comm.comm,
111 sizeof(event->comm.comm));
112 else
113 tgid = machine->pid;
114
110 if (tgid < 0) 115 if (tgid < 0)
111 goto out; 116 goto out;
112 117
@@ -128,7 +133,11 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
128 goto out; 133 goto out;
129 } 134 }
130 135
131 snprintf(filename, sizeof(filename), "/proc/%d/task", pid); 136 if (machine__is_default_guest(machine))
137 return 0;
138
139 snprintf(filename, sizeof(filename), "%s/proc/%d/task",
140 machine->root_dir, pid);
132 141
133 tasks = opendir(filename); 142 tasks = opendir(filename);
134 if (tasks == NULL) { 143 if (tasks == NULL) {
@@ -166,18 +175,22 @@ out:
166 return tgid; 175 return tgid;
167} 176}
168 177
169static int perf_event__synthesize_mmap_events(struct perf_tool *tool, 178int perf_event__synthesize_mmap_events(struct perf_tool *tool,
170 union perf_event *event, 179 union perf_event *event,
171 pid_t pid, pid_t tgid, 180 pid_t pid, pid_t tgid,
172 perf_event__handler_t process, 181 perf_event__handler_t process,
173 struct machine *machine, 182 struct machine *machine,
174 bool mmap_data) 183 bool mmap_data)
175{ 184{
176 char filename[PATH_MAX]; 185 char filename[PATH_MAX];
177 FILE *fp; 186 FILE *fp;
178 int rc = 0; 187 int rc = 0;
179 188
180 snprintf(filename, sizeof(filename), "/proc/%d/maps", pid); 189 if (machine__is_default_guest(machine))
190 return 0;
191
192 snprintf(filename, sizeof(filename), "%s/proc/%d/maps",
193 machine->root_dir, pid);
181 194
182 fp = fopen(filename, "r"); 195 fp = fopen(filename, "r");
183 if (fp == NULL) { 196 if (fp == NULL) {
@@ -217,7 +230,10 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool,
217 /* 230 /*
218 * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c 231 * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c
219 */ 232 */
220 event->header.misc = PERF_RECORD_MISC_USER; 233 if (machine__is_host(machine))
234 event->header.misc = PERF_RECORD_MISC_USER;
235 else
236 event->header.misc = PERF_RECORD_MISC_GUEST_USER;
221 237
222 if (prot[2] != 'x') { 238 if (prot[2] != 'x') {
223 if (!mmap_data || prot[0] != 'r') 239 if (!mmap_data || prot[0] != 'r')
@@ -386,6 +402,7 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
386 struct machine *machine, bool mmap_data) 402 struct machine *machine, bool mmap_data)
387{ 403{
388 DIR *proc; 404 DIR *proc;
405 char proc_path[PATH_MAX];
389 struct dirent dirent, *next; 406 struct dirent dirent, *next;
390 union perf_event *comm_event, *mmap_event; 407 union perf_event *comm_event, *mmap_event;
391 int err = -1; 408 int err = -1;
@@ -398,7 +415,12 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
398 if (mmap_event == NULL) 415 if (mmap_event == NULL)
399 goto out_free_comm; 416 goto out_free_comm;
400 417
401 proc = opendir("/proc"); 418 if (machine__is_default_guest(machine))
419 return 0;
420
421 snprintf(proc_path, sizeof(proc_path), "%s/proc", machine->root_dir);
422 proc = opendir(proc_path);
423
402 if (proc == NULL) 424 if (proc == NULL)
403 goto out_free_mmap; 425 goto out_free_mmap;
404 426
@@ -637,6 +659,7 @@ void thread__find_addr_map(struct thread *thread,
637 struct map_groups *mg = &thread->mg; 659 struct map_groups *mg = &thread->mg;
638 bool load_map = false; 660 bool load_map = false;
639 661
662 al->machine = machine;
640 al->thread = thread; 663 al->thread = thread;
641 al->addr = addr; 664 al->addr = addr;
642 al->cpumode = cpumode; 665 al->cpumode = cpumode;
@@ -657,15 +680,10 @@ void thread__find_addr_map(struct thread *thread,
657 al->level = 'g'; 680 al->level = 'g';
658 mg = &machine->kmaps; 681 mg = &machine->kmaps;
659 load_map = true; 682 load_map = true;
683 } else if (cpumode == PERF_RECORD_MISC_GUEST_USER && perf_guest) {
684 al->level = 'u';
660 } else { 685 } else {
661 /* 686 al->level = 'H';
662 * 'u' means guest os user space.
663 * TODO: We don't support guest user space. Might support late.
664 */
665 if (cpumode == PERF_RECORD_MISC_GUEST_USER && perf_guest)
666 al->level = 'u';
667 else
668 al->level = 'H';
669 al->map = NULL; 687 al->map = NULL;
670 688
671 if ((cpumode == PERF_RECORD_MISC_GUEST_USER || 689 if ((cpumode == PERF_RECORD_MISC_GUEST_USER ||
@@ -732,8 +750,7 @@ int perf_event__preprocess_sample(const union perf_event *event,
732 if (thread == NULL) 750 if (thread == NULL)
733 return -1; 751 return -1;
734 752
735 if (symbol_conf.comm_list && 753 if (thread__is_filtered(thread))
736 !strlist__has_entry(symbol_conf.comm_list, thread__comm_str(thread)))
737 goto out_filtered; 754 goto out_filtered;
738 755
739 dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread), thread->tid); 756 dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread), thread->tid);
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 30fec9901e44..faf6e219be21 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -266,6 +266,13 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type,
266 const struct perf_sample *sample, 266 const struct perf_sample *sample,
267 bool swapped); 267 bool swapped);
268 268
269int perf_event__synthesize_mmap_events(struct perf_tool *tool,
270 union perf_event *event,
271 pid_t pid, pid_t tgid,
272 perf_event__handler_t process,
273 struct machine *machine,
274 bool mmap_data);
275
269size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp); 276size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp);
270size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp); 277size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp);
271size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp); 278size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp);
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index bbc746aa5716..59ef2802fcf6 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -7,7 +7,7 @@
7 * Released under the GPL v2. (and only v2, not any later version) 7 * Released under the GPL v2. (and only v2, not any later version)
8 */ 8 */
9#include "util.h" 9#include "util.h"
10#include <lk/debugfs.h> 10#include <api/fs/debugfs.h>
11#include <poll.h> 11#include <poll.h>
12#include "cpumap.h" 12#include "cpumap.h"
13#include "thread_map.h" 13#include "thread_map.h"
@@ -81,7 +81,7 @@ static void perf_evlist__update_id_pos(struct perf_evlist *evlist)
81{ 81{
82 struct perf_evsel *evsel; 82 struct perf_evsel *evsel;
83 83
84 list_for_each_entry(evsel, &evlist->entries, node) 84 evlist__for_each(evlist, evsel)
85 perf_evsel__calc_id_pos(evsel); 85 perf_evsel__calc_id_pos(evsel);
86 86
87 perf_evlist__set_id_pos(evlist); 87 perf_evlist__set_id_pos(evlist);
@@ -91,7 +91,7 @@ static void perf_evlist__purge(struct perf_evlist *evlist)
91{ 91{
92 struct perf_evsel *pos, *n; 92 struct perf_evsel *pos, *n;
93 93
94 list_for_each_entry_safe(pos, n, &evlist->entries, node) { 94 evlist__for_each_safe(evlist, n, pos) {
95 list_del_init(&pos->node); 95 list_del_init(&pos->node);
96 perf_evsel__delete(pos); 96 perf_evsel__delete(pos);
97 } 97 }
@@ -101,14 +101,18 @@ static void perf_evlist__purge(struct perf_evlist *evlist)
101 101
102void perf_evlist__exit(struct perf_evlist *evlist) 102void perf_evlist__exit(struct perf_evlist *evlist)
103{ 103{
104 free(evlist->mmap); 104 zfree(&evlist->mmap);
105 free(evlist->pollfd); 105 zfree(&evlist->pollfd);
106 evlist->mmap = NULL;
107 evlist->pollfd = NULL;
108} 106}
109 107
110void perf_evlist__delete(struct perf_evlist *evlist) 108void perf_evlist__delete(struct perf_evlist *evlist)
111{ 109{
110 perf_evlist__munmap(evlist);
111 perf_evlist__close(evlist);
112 cpu_map__delete(evlist->cpus);
113 thread_map__delete(evlist->threads);
114 evlist->cpus = NULL;
115 evlist->threads = NULL;
112 perf_evlist__purge(evlist); 116 perf_evlist__purge(evlist);
113 perf_evlist__exit(evlist); 117 perf_evlist__exit(evlist);
114 free(evlist); 118 free(evlist);
@@ -144,7 +148,7 @@ void __perf_evlist__set_leader(struct list_head *list)
144 148
145 leader->nr_members = evsel->idx - leader->idx + 1; 149 leader->nr_members = evsel->idx - leader->idx + 1;
146 150
147 list_for_each_entry(evsel, list, node) { 151 __evlist__for_each(list, evsel) {
148 evsel->leader = leader; 152 evsel->leader = leader;
149 } 153 }
150} 154}
@@ -203,7 +207,7 @@ static int perf_evlist__add_attrs(struct perf_evlist *evlist,
203 return 0; 207 return 0;
204 208
205out_delete_partial_list: 209out_delete_partial_list:
206 list_for_each_entry_safe(evsel, n, &head, node) 210 __evlist__for_each_safe(&head, n, evsel)
207 perf_evsel__delete(evsel); 211 perf_evsel__delete(evsel);
208 return -1; 212 return -1;
209} 213}
@@ -224,7 +228,7 @@ perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id)
224{ 228{
225 struct perf_evsel *evsel; 229 struct perf_evsel *evsel;
226 230
227 list_for_each_entry(evsel, &evlist->entries, node) { 231 evlist__for_each(evlist, evsel) {
228 if (evsel->attr.type == PERF_TYPE_TRACEPOINT && 232 if (evsel->attr.type == PERF_TYPE_TRACEPOINT &&
229 (int)evsel->attr.config == id) 233 (int)evsel->attr.config == id)
230 return evsel; 234 return evsel;
@@ -239,7 +243,7 @@ perf_evlist__find_tracepoint_by_name(struct perf_evlist *evlist,
239{ 243{
240 struct perf_evsel *evsel; 244 struct perf_evsel *evsel;
241 245
242 list_for_each_entry(evsel, &evlist->entries, node) { 246 evlist__for_each(evlist, evsel) {
243 if ((evsel->attr.type == PERF_TYPE_TRACEPOINT) && 247 if ((evsel->attr.type == PERF_TYPE_TRACEPOINT) &&
244 (strcmp(evsel->name, name) == 0)) 248 (strcmp(evsel->name, name) == 0))
245 return evsel; 249 return evsel;
@@ -269,7 +273,7 @@ void perf_evlist__disable(struct perf_evlist *evlist)
269 int nr_threads = thread_map__nr(evlist->threads); 273 int nr_threads = thread_map__nr(evlist->threads);
270 274
271 for (cpu = 0; cpu < nr_cpus; cpu++) { 275 for (cpu = 0; cpu < nr_cpus; cpu++) {
272 list_for_each_entry(pos, &evlist->entries, node) { 276 evlist__for_each(evlist, pos) {
273 if (!perf_evsel__is_group_leader(pos) || !pos->fd) 277 if (!perf_evsel__is_group_leader(pos) || !pos->fd)
274 continue; 278 continue;
275 for (thread = 0; thread < nr_threads; thread++) 279 for (thread = 0; thread < nr_threads; thread++)
@@ -287,7 +291,7 @@ void perf_evlist__enable(struct perf_evlist *evlist)
287 int nr_threads = thread_map__nr(evlist->threads); 291 int nr_threads = thread_map__nr(evlist->threads);
288 292
289 for (cpu = 0; cpu < nr_cpus; cpu++) { 293 for (cpu = 0; cpu < nr_cpus; cpu++) {
290 list_for_each_entry(pos, &evlist->entries, node) { 294 evlist__for_each(evlist, pos) {
291 if (!perf_evsel__is_group_leader(pos) || !pos->fd) 295 if (!perf_evsel__is_group_leader(pos) || !pos->fd)
292 continue; 296 continue;
293 for (thread = 0; thread < nr_threads; thread++) 297 for (thread = 0; thread < nr_threads; thread++)
@@ -584,11 +588,13 @@ void perf_evlist__munmap(struct perf_evlist *evlist)
584{ 588{
585 int i; 589 int i;
586 590
591 if (evlist->mmap == NULL)
592 return;
593
587 for (i = 0; i < evlist->nr_mmaps; i++) 594 for (i = 0; i < evlist->nr_mmaps; i++)
588 __perf_evlist__munmap(evlist, i); 595 __perf_evlist__munmap(evlist, i);
589 596
590 free(evlist->mmap); 597 zfree(&evlist->mmap);
591 evlist->mmap = NULL;
592} 598}
593 599
594static int perf_evlist__alloc_mmap(struct perf_evlist *evlist) 600static int perf_evlist__alloc_mmap(struct perf_evlist *evlist)
@@ -624,7 +630,7 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
624{ 630{
625 struct perf_evsel *evsel; 631 struct perf_evsel *evsel;
626 632
627 list_for_each_entry(evsel, &evlist->entries, node) { 633 evlist__for_each(evlist, evsel) {
628 int fd = FD(evsel, cpu, thread); 634 int fd = FD(evsel, cpu, thread);
629 635
630 if (*output == -1) { 636 if (*output == -1) {
@@ -732,11 +738,13 @@ static long parse_pages_arg(const char *str, unsigned long min,
732 return -EINVAL; 738 return -EINVAL;
733 } 739 }
734 740
735 if ((pages == 0) && (min == 0)) { 741 if (pages == 0 && min == 0) {
736 /* leave number of pages at 0 */ 742 /* leave number of pages at 0 */
737 } else if (pages < (1UL << 31) && !is_power_of_2(pages)) { 743 } else if (!is_power_of_2(pages)) {
738 /* round pages up to next power of 2 */ 744 /* round pages up to next power of 2 */
739 pages = next_pow2(pages); 745 pages = next_pow2_l(pages);
746 if (!pages)
747 return -EINVAL;
740 pr_info("rounding mmap pages size to %lu bytes (%lu pages)\n", 748 pr_info("rounding mmap pages size to %lu bytes (%lu pages)\n",
741 pages * page_size, pages); 749 pages * page_size, pages);
742 } 750 }
@@ -754,7 +762,7 @@ int perf_evlist__parse_mmap_pages(const struct option *opt, const char *str,
754 unsigned long max = UINT_MAX; 762 unsigned long max = UINT_MAX;
755 long pages; 763 long pages;
756 764
757 if (max < SIZE_MAX / page_size) 765 if (max > SIZE_MAX / page_size)
758 max = SIZE_MAX / page_size; 766 max = SIZE_MAX / page_size;
759 767
760 pages = parse_pages_arg(str, 1, max); 768 pages = parse_pages_arg(str, 1, max);
@@ -798,7 +806,7 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
798 pr_debug("mmap size %zuB\n", evlist->mmap_len); 806 pr_debug("mmap size %zuB\n", evlist->mmap_len);
799 mask = evlist->mmap_len - page_size - 1; 807 mask = evlist->mmap_len - page_size - 1;
800 808
801 list_for_each_entry(evsel, &evlist->entries, node) { 809 evlist__for_each(evlist, evsel) {
802 if ((evsel->attr.read_format & PERF_FORMAT_ID) && 810 if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
803 evsel->sample_id == NULL && 811 evsel->sample_id == NULL &&
804 perf_evsel__alloc_id(evsel, cpu_map__nr(cpus), threads->nr) < 0) 812 perf_evsel__alloc_id(evsel, cpu_map__nr(cpus), threads->nr) < 0)
@@ -819,11 +827,7 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)
819 if (evlist->threads == NULL) 827 if (evlist->threads == NULL)
820 return -1; 828 return -1;
821 829
822 if (target->force_per_cpu) 830 if (target__uses_dummy_map(target))
823 evlist->cpus = cpu_map__new(target->cpu_list);
824 else if (target__has_task(target))
825 evlist->cpus = cpu_map__dummy_new();
826 else if (!target__has_cpu(target) && !target->uses_mmap)
827 evlist->cpus = cpu_map__dummy_new(); 831 evlist->cpus = cpu_map__dummy_new();
828 else 832 else
829 evlist->cpus = cpu_map__new(target->cpu_list); 833 evlist->cpus = cpu_map__new(target->cpu_list);
@@ -838,14 +842,6 @@ out_delete_threads:
838 return -1; 842 return -1;
839} 843}
840 844
841void perf_evlist__delete_maps(struct perf_evlist *evlist)
842{
843 cpu_map__delete(evlist->cpus);
844 thread_map__delete(evlist->threads);
845 evlist->cpus = NULL;
846 evlist->threads = NULL;
847}
848
849int perf_evlist__apply_filters(struct perf_evlist *evlist) 845int perf_evlist__apply_filters(struct perf_evlist *evlist)
850{ 846{
851 struct perf_evsel *evsel; 847 struct perf_evsel *evsel;
@@ -853,7 +849,7 @@ int perf_evlist__apply_filters(struct perf_evlist *evlist)
853 const int ncpus = cpu_map__nr(evlist->cpus), 849 const int ncpus = cpu_map__nr(evlist->cpus),
854 nthreads = thread_map__nr(evlist->threads); 850 nthreads = thread_map__nr(evlist->threads);
855 851
856 list_for_each_entry(evsel, &evlist->entries, node) { 852 evlist__for_each(evlist, evsel) {
857 if (evsel->filter == NULL) 853 if (evsel->filter == NULL)
858 continue; 854 continue;
859 855
@@ -872,7 +868,7 @@ int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter)
872 const int ncpus = cpu_map__nr(evlist->cpus), 868 const int ncpus = cpu_map__nr(evlist->cpus),
873 nthreads = thread_map__nr(evlist->threads); 869 nthreads = thread_map__nr(evlist->threads);
874 870
875 list_for_each_entry(evsel, &evlist->entries, node) { 871 evlist__for_each(evlist, evsel) {
876 err = perf_evsel__set_filter(evsel, ncpus, nthreads, filter); 872 err = perf_evsel__set_filter(evsel, ncpus, nthreads, filter);
877 if (err) 873 if (err)
878 break; 874 break;
@@ -891,7 +887,7 @@ bool perf_evlist__valid_sample_type(struct perf_evlist *evlist)
891 if (evlist->id_pos < 0 || evlist->is_pos < 0) 887 if (evlist->id_pos < 0 || evlist->is_pos < 0)
892 return false; 888 return false;
893 889
894 list_for_each_entry(pos, &evlist->entries, node) { 890 evlist__for_each(evlist, pos) {
895 if (pos->id_pos != evlist->id_pos || 891 if (pos->id_pos != evlist->id_pos ||
896 pos->is_pos != evlist->is_pos) 892 pos->is_pos != evlist->is_pos)
897 return false; 893 return false;
@@ -907,7 +903,7 @@ u64 __perf_evlist__combined_sample_type(struct perf_evlist *evlist)
907 if (evlist->combined_sample_type) 903 if (evlist->combined_sample_type)
908 return evlist->combined_sample_type; 904 return evlist->combined_sample_type;
909 905
910 list_for_each_entry(evsel, &evlist->entries, node) 906 evlist__for_each(evlist, evsel)
911 evlist->combined_sample_type |= evsel->attr.sample_type; 907 evlist->combined_sample_type |= evsel->attr.sample_type;
912 908
913 return evlist->combined_sample_type; 909 return evlist->combined_sample_type;
@@ -925,7 +921,7 @@ bool perf_evlist__valid_read_format(struct perf_evlist *evlist)
925 u64 read_format = first->attr.read_format; 921 u64 read_format = first->attr.read_format;
926 u64 sample_type = first->attr.sample_type; 922 u64 sample_type = first->attr.sample_type;
927 923
928 list_for_each_entry_continue(pos, &evlist->entries, node) { 924 evlist__for_each(evlist, pos) {
929 if (read_format != pos->attr.read_format) 925 if (read_format != pos->attr.read_format)
930 return false; 926 return false;
931 } 927 }
@@ -982,7 +978,7 @@ bool perf_evlist__valid_sample_id_all(struct perf_evlist *evlist)
982{ 978{
983 struct perf_evsel *first = perf_evlist__first(evlist), *pos = first; 979 struct perf_evsel *first = perf_evlist__first(evlist), *pos = first;
984 980
985 list_for_each_entry_continue(pos, &evlist->entries, node) { 981 evlist__for_each_continue(evlist, pos) {
986 if (first->attr.sample_id_all != pos->attr.sample_id_all) 982 if (first->attr.sample_id_all != pos->attr.sample_id_all)
987 return false; 983 return false;
988 } 984 }
@@ -1007,9 +1003,12 @@ void perf_evlist__close(struct perf_evlist *evlist)
1007 struct perf_evsel *evsel; 1003 struct perf_evsel *evsel;
1008 int ncpus = cpu_map__nr(evlist->cpus); 1004 int ncpus = cpu_map__nr(evlist->cpus);
1009 int nthreads = thread_map__nr(evlist->threads); 1005 int nthreads = thread_map__nr(evlist->threads);
1006 int n;
1010 1007
1011 list_for_each_entry_reverse(evsel, &evlist->entries, node) 1008 evlist__for_each_reverse(evlist, evsel) {
1012 perf_evsel__close(evsel, ncpus, nthreads); 1009 n = evsel->cpus ? evsel->cpus->nr : ncpus;
1010 perf_evsel__close(evsel, n, nthreads);
1011 }
1013} 1012}
1014 1013
1015int perf_evlist__open(struct perf_evlist *evlist) 1014int perf_evlist__open(struct perf_evlist *evlist)
@@ -1019,7 +1018,7 @@ int perf_evlist__open(struct perf_evlist *evlist)
1019 1018
1020 perf_evlist__update_id_pos(evlist); 1019 perf_evlist__update_id_pos(evlist);
1021 1020
1022 list_for_each_entry(evsel, &evlist->entries, node) { 1021 evlist__for_each(evlist, evsel) {
1023 err = perf_evsel__open(evsel, evlist->cpus, evlist->threads); 1022 err = perf_evsel__open(evsel, evlist->cpus, evlist->threads);
1024 if (err < 0) 1023 if (err < 0)
1025 goto out_err; 1024 goto out_err;
@@ -1034,7 +1033,7 @@ out_err:
1034 1033
1035int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *target, 1034int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *target,
1036 const char *argv[], bool pipe_output, 1035 const char *argv[], bool pipe_output,
1037 bool want_signal) 1036 void (*exec_error)(int signo, siginfo_t *info, void *ucontext))
1038{ 1037{
1039 int child_ready_pipe[2], go_pipe[2]; 1038 int child_ready_pipe[2], go_pipe[2];
1040 char bf; 1039 char bf;
@@ -1078,12 +1077,25 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *tar
1078 1077
1079 execvp(argv[0], (char **)argv); 1078 execvp(argv[0], (char **)argv);
1080 1079
1081 perror(argv[0]); 1080 if (exec_error) {
1082 if (want_signal) 1081 union sigval val;
1083 kill(getppid(), SIGUSR1); 1082
1083 val.sival_int = errno;
1084 if (sigqueue(getppid(), SIGUSR1, val))
1085 perror(argv[0]);
1086 } else
1087 perror(argv[0]);
1084 exit(-1); 1088 exit(-1);
1085 } 1089 }
1086 1090
1091 if (exec_error) {
1092 struct sigaction act = {
1093 .sa_flags = SA_SIGINFO,
1094 .sa_sigaction = exec_error,
1095 };
1096 sigaction(SIGUSR1, &act, NULL);
1097 }
1098
1087 if (target__none(target)) 1099 if (target__none(target))
1088 evlist->threads->map[0] = evlist->workload.pid; 1100 evlist->threads->map[0] = evlist->workload.pid;
1089 1101
@@ -1145,7 +1157,7 @@ size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp)
1145 struct perf_evsel *evsel; 1157 struct perf_evsel *evsel;
1146 size_t printed = 0; 1158 size_t printed = 0;
1147 1159
1148 list_for_each_entry(evsel, &evlist->entries, node) { 1160 evlist__for_each(evlist, evsel) {
1149 printed += fprintf(fp, "%s%s", evsel->idx ? ", " : "", 1161 printed += fprintf(fp, "%s%s", evsel->idx ? ", " : "",
1150 perf_evsel__name(evsel)); 1162 perf_evsel__name(evsel));
1151 } 1163 }
@@ -1193,8 +1205,7 @@ int perf_evlist__strerror_open(struct perf_evlist *evlist __maybe_unused,
1193 "Error:\t%s.\n" 1205 "Error:\t%s.\n"
1194 "Hint:\tCheck /proc/sys/kernel/perf_event_paranoid setting.", emsg); 1206 "Hint:\tCheck /proc/sys/kernel/perf_event_paranoid setting.", emsg);
1195 1207
1196 if (filename__read_int("/proc/sys/kernel/perf_event_paranoid", &value)) 1208 value = perf_event_paranoid();
1197 break;
1198 1209
1199 printed += scnprintf(buf + printed, size - printed, "\nHint:\t"); 1210 printed += scnprintf(buf + printed, size - printed, "\nHint:\t");
1200 1211
@@ -1215,3 +1226,20 @@ int perf_evlist__strerror_open(struct perf_evlist *evlist __maybe_unused,
1215 1226
1216 return 0; 1227 return 0;
1217} 1228}
1229
1230void perf_evlist__to_front(struct perf_evlist *evlist,
1231 struct perf_evsel *move_evsel)
1232{
1233 struct perf_evsel *evsel, *n;
1234 LIST_HEAD(move);
1235
1236 if (move_evsel == perf_evlist__first(evlist))
1237 return;
1238
1239 evlist__for_each_safe(evlist, n, evsel) {
1240 if (evsel->leader == move_evsel->leader)
1241 list_move_tail(&evsel->node, &move);
1242 }
1243
1244 list_splice(&move, &evlist->entries);
1245}
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 649d6ea98a84..f5173cd63693 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -12,7 +12,7 @@
12struct pollfd; 12struct pollfd;
13struct thread_map; 13struct thread_map;
14struct cpu_map; 14struct cpu_map;
15struct perf_record_opts; 15struct record_opts;
16 16
17#define PERF_EVLIST__HLIST_BITS 8 17#define PERF_EVLIST__HLIST_BITS 8
18#define PERF_EVLIST__HLIST_SIZE (1 << PERF_EVLIST__HLIST_BITS) 18#define PERF_EVLIST__HLIST_SIZE (1 << PERF_EVLIST__HLIST_BITS)
@@ -97,14 +97,14 @@ void perf_evlist__close(struct perf_evlist *evlist);
97 97
98void perf_evlist__set_id_pos(struct perf_evlist *evlist); 98void perf_evlist__set_id_pos(struct perf_evlist *evlist);
99bool perf_can_sample_identifier(void); 99bool perf_can_sample_identifier(void);
100void perf_evlist__config(struct perf_evlist *evlist, 100void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts);
101 struct perf_record_opts *opts); 101int record_opts__config(struct record_opts *opts);
102int perf_record_opts__config(struct perf_record_opts *opts);
103 102
104int perf_evlist__prepare_workload(struct perf_evlist *evlist, 103int perf_evlist__prepare_workload(struct perf_evlist *evlist,
105 struct target *target, 104 struct target *target,
106 const char *argv[], bool pipe_output, 105 const char *argv[], bool pipe_output,
107 bool want_signal); 106 void (*exec_error)(int signo, siginfo_t *info,
107 void *ucontext));
108int perf_evlist__start_workload(struct perf_evlist *evlist); 108int perf_evlist__start_workload(struct perf_evlist *evlist);
109 109
110int perf_evlist__parse_mmap_pages(const struct option *opt, 110int perf_evlist__parse_mmap_pages(const struct option *opt,
@@ -135,7 +135,6 @@ static inline void perf_evlist__set_maps(struct perf_evlist *evlist,
135} 135}
136 136
137int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target); 137int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target);
138void perf_evlist__delete_maps(struct perf_evlist *evlist);
139int perf_evlist__apply_filters(struct perf_evlist *evlist); 138int perf_evlist__apply_filters(struct perf_evlist *evlist);
140 139
141void __perf_evlist__set_leader(struct list_head *list); 140void __perf_evlist__set_leader(struct list_head *list);
@@ -193,4 +192,74 @@ static inline void perf_mmap__write_tail(struct perf_mmap *md,
193 pc->data_tail = tail; 192 pc->data_tail = tail;
194} 193}
195 194
195bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str);
196void perf_evlist__to_front(struct perf_evlist *evlist,
197 struct perf_evsel *move_evsel);
198
199/**
200 * __evlist__for_each - iterate thru all the evsels
201 * @list: list_head instance to iterate
202 * @evsel: struct evsel iterator
203 */
204#define __evlist__for_each(list, evsel) \
205 list_for_each_entry(evsel, list, node)
206
207/**
208 * evlist__for_each - iterate thru all the evsels
209 * @evlist: evlist instance to iterate
210 * @evsel: struct evsel iterator
211 */
212#define evlist__for_each(evlist, evsel) \
213 __evlist__for_each(&(evlist)->entries, evsel)
214
215/**
216 * __evlist__for_each_continue - continue iteration thru all the evsels
217 * @list: list_head instance to iterate
218 * @evsel: struct evsel iterator
219 */
220#define __evlist__for_each_continue(list, evsel) \
221 list_for_each_entry_continue(evsel, list, node)
222
223/**
224 * evlist__for_each_continue - continue iteration thru all the evsels
225 * @evlist: evlist instance to iterate
226 * @evsel: struct evsel iterator
227 */
228#define evlist__for_each_continue(evlist, evsel) \
229 __evlist__for_each_continue(&(evlist)->entries, evsel)
230
231/**
232 * __evlist__for_each_reverse - iterate thru all the evsels in reverse order
233 * @list: list_head instance to iterate
234 * @evsel: struct evsel iterator
235 */
236#define __evlist__for_each_reverse(list, evsel) \
237 list_for_each_entry_reverse(evsel, list, node)
238
239/**
240 * evlist__for_each_reverse - iterate thru all the evsels in reverse order
241 * @evlist: evlist instance to iterate
242 * @evsel: struct evsel iterator
243 */
244#define evlist__for_each_reverse(evlist, evsel) \
245 __evlist__for_each_reverse(&(evlist)->entries, evsel)
246
247/**
248 * __evlist__for_each_safe - safely iterate thru all the evsels
249 * @list: list_head instance to iterate
250 * @tmp: struct evsel temp iterator
251 * @evsel: struct evsel iterator
252 */
253#define __evlist__for_each_safe(list, tmp, evsel) \
254 list_for_each_entry_safe(evsel, tmp, list, node)
255
256/**
257 * evlist__for_each_safe - safely iterate thru all the evsels
258 * @evlist: evlist instance to iterate
259 * @evsel: struct evsel iterator
260 * @tmp: struct evsel temp iterator
261 */
262#define evlist__for_each_safe(evlist, tmp, evsel) \
263 __evlist__for_each_safe(&(evlist)->entries, tmp, evsel)
264
196#endif /* __PERF_EVLIST_H */ 265#endif /* __PERF_EVLIST_H */
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 46dd4c2a41ce..55407c594b87 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -9,7 +9,7 @@
9 9
10#include <byteswap.h> 10#include <byteswap.h>
11#include <linux/bitops.h> 11#include <linux/bitops.h>
12#include <lk/debugfs.h> 12#include <api/fs/debugfs.h>
13#include <traceevent/event-parse.h> 13#include <traceevent/event-parse.h>
14#include <linux/hw_breakpoint.h> 14#include <linux/hw_breakpoint.h>
15#include <linux/perf_event.h> 15#include <linux/perf_event.h>
@@ -23,6 +23,7 @@
23#include "target.h" 23#include "target.h"
24#include "perf_regs.h" 24#include "perf_regs.h"
25#include "debug.h" 25#include "debug.h"
26#include "trace-event.h"
26 27
27static struct { 28static struct {
28 bool sample_id_all; 29 bool sample_id_all;
@@ -162,6 +163,8 @@ void perf_evsel__init(struct perf_evsel *evsel,
162 evsel->idx = idx; 163 evsel->idx = idx;
163 evsel->attr = *attr; 164 evsel->attr = *attr;
164 evsel->leader = evsel; 165 evsel->leader = evsel;
166 evsel->unit = "";
167 evsel->scale = 1.0;
165 INIT_LIST_HEAD(&evsel->node); 168 INIT_LIST_HEAD(&evsel->node);
166 hists__init(&evsel->hists); 169 hists__init(&evsel->hists);
167 evsel->sample_size = __perf_evsel__sample_size(attr->sample_type); 170 evsel->sample_size = __perf_evsel__sample_size(attr->sample_type);
@@ -178,47 +181,6 @@ struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx)
178 return evsel; 181 return evsel;
179} 182}
180 183
181struct event_format *event_format__new(const char *sys, const char *name)
182{
183 int fd, n;
184 char *filename;
185 void *bf = NULL, *nbf;
186 size_t size = 0, alloc_size = 0;
187 struct event_format *format = NULL;
188
189 if (asprintf(&filename, "%s/%s/%s/format", tracing_events_path, sys, name) < 0)
190 goto out;
191
192 fd = open(filename, O_RDONLY);
193 if (fd < 0)
194 goto out_free_filename;
195
196 do {
197 if (size == alloc_size) {
198 alloc_size += BUFSIZ;
199 nbf = realloc(bf, alloc_size);
200 if (nbf == NULL)
201 goto out_free_bf;
202 bf = nbf;
203 }
204
205 n = read(fd, bf + size, alloc_size - size);
206 if (n < 0)
207 goto out_free_bf;
208 size += n;
209 } while (n > 0);
210
211 pevent_parse_format(&format, bf, size, sys);
212
213out_free_bf:
214 free(bf);
215 close(fd);
216out_free_filename:
217 free(filename);
218out:
219 return format;
220}
221
222struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx) 184struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx)
223{ 185{
224 struct perf_evsel *evsel = zalloc(sizeof(*evsel)); 186 struct perf_evsel *evsel = zalloc(sizeof(*evsel));
@@ -233,7 +195,7 @@ struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int
233 if (asprintf(&evsel->name, "%s:%s", sys, name) < 0) 195 if (asprintf(&evsel->name, "%s:%s", sys, name) < 0)
234 goto out_free; 196 goto out_free;
235 197
236 evsel->tp_format = event_format__new(sys, name); 198 evsel->tp_format = trace_event__tp_format(sys, name);
237 if (evsel->tp_format == NULL) 199 if (evsel->tp_format == NULL)
238 goto out_free; 200 goto out_free;
239 201
@@ -246,7 +208,7 @@ struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int
246 return evsel; 208 return evsel;
247 209
248out_free: 210out_free:
249 free(evsel->name); 211 zfree(&evsel->name);
250 free(evsel); 212 free(evsel);
251 return NULL; 213 return NULL;
252} 214}
@@ -566,12 +528,12 @@ int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size)
566 * enable/disable events specifically, as there's no 528 * enable/disable events specifically, as there's no
567 * initial traced exec call. 529 * initial traced exec call.
568 */ 530 */
569void perf_evsel__config(struct perf_evsel *evsel, 531void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
570 struct perf_record_opts *opts)
571{ 532{
572 struct perf_evsel *leader = evsel->leader; 533 struct perf_evsel *leader = evsel->leader;
573 struct perf_event_attr *attr = &evsel->attr; 534 struct perf_event_attr *attr = &evsel->attr;
574 int track = !evsel->idx; /* only the first counter needs these */ 535 int track = !evsel->idx; /* only the first counter needs these */
536 bool per_cpu = opts->target.default_per_cpu && !opts->target.per_thread;
575 537
576 attr->sample_id_all = perf_missing_features.sample_id_all ? 0 : 1; 538 attr->sample_id_all = perf_missing_features.sample_id_all ? 0 : 1;
577 attr->inherit = !opts->no_inherit; 539 attr->inherit = !opts->no_inherit;
@@ -645,7 +607,7 @@ void perf_evsel__config(struct perf_evsel *evsel,
645 } 607 }
646 } 608 }
647 609
648 if (target__has_cpu(&opts->target) || opts->target.force_per_cpu) 610 if (target__has_cpu(&opts->target))
649 perf_evsel__set_sample_bit(evsel, CPU); 611 perf_evsel__set_sample_bit(evsel, CPU);
650 612
651 if (opts->period) 613 if (opts->period)
@@ -653,7 +615,7 @@ void perf_evsel__config(struct perf_evsel *evsel,
653 615
654 if (!perf_missing_features.sample_id_all && 616 if (!perf_missing_features.sample_id_all &&
655 (opts->sample_time || !opts->no_inherit || 617 (opts->sample_time || !opts->no_inherit ||
656 target__has_cpu(&opts->target) || opts->target.force_per_cpu)) 618 target__has_cpu(&opts->target) || per_cpu))
657 perf_evsel__set_sample_bit(evsel, TIME); 619 perf_evsel__set_sample_bit(evsel, TIME);
658 620
659 if (opts->raw_samples) { 621 if (opts->raw_samples) {
@@ -665,7 +627,7 @@ void perf_evsel__config(struct perf_evsel *evsel,
665 if (opts->sample_address) 627 if (opts->sample_address)
666 perf_evsel__set_sample_bit(evsel, DATA_SRC); 628 perf_evsel__set_sample_bit(evsel, DATA_SRC);
667 629
668 if (opts->no_delay) { 630 if (opts->no_buffering) {
669 attr->watermark = 0; 631 attr->watermark = 0;
670 attr->wakeup_events = 1; 632 attr->wakeup_events = 1;
671 } 633 }
@@ -696,7 +658,8 @@ void perf_evsel__config(struct perf_evsel *evsel,
696 * Setting enable_on_exec for independent events and 658 * Setting enable_on_exec for independent events and
697 * group leaders for traced executed by perf. 659 * group leaders for traced executed by perf.
698 */ 660 */
699 if (target__none(&opts->target) && perf_evsel__is_group_leader(evsel)) 661 if (target__none(&opts->target) && perf_evsel__is_group_leader(evsel) &&
662 !opts->initial_delay)
700 attr->enable_on_exec = 1; 663 attr->enable_on_exec = 1;
701} 664}
702 665
@@ -788,8 +751,7 @@ void perf_evsel__free_id(struct perf_evsel *evsel)
788{ 751{
789 xyarray__delete(evsel->sample_id); 752 xyarray__delete(evsel->sample_id);
790 evsel->sample_id = NULL; 753 evsel->sample_id = NULL;
791 free(evsel->id); 754 zfree(&evsel->id);
792 evsel->id = NULL;
793} 755}
794 756
795void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads) 757void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
@@ -805,7 +767,7 @@ void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
805 767
806void perf_evsel__free_counts(struct perf_evsel *evsel) 768void perf_evsel__free_counts(struct perf_evsel *evsel)
807{ 769{
808 free(evsel->counts); 770 zfree(&evsel->counts);
809} 771}
810 772
811void perf_evsel__exit(struct perf_evsel *evsel) 773void perf_evsel__exit(struct perf_evsel *evsel)
@@ -819,10 +781,10 @@ void perf_evsel__delete(struct perf_evsel *evsel)
819{ 781{
820 perf_evsel__exit(evsel); 782 perf_evsel__exit(evsel);
821 close_cgroup(evsel->cgrp); 783 close_cgroup(evsel->cgrp);
822 free(evsel->group_name); 784 zfree(&evsel->group_name);
823 if (evsel->tp_format) 785 if (evsel->tp_format)
824 pevent_free_format(evsel->tp_format); 786 pevent_free_format(evsel->tp_format);
825 free(evsel->name); 787 zfree(&evsel->name);
826 free(evsel); 788 free(evsel);
827} 789}
828 790
@@ -1119,7 +1081,6 @@ void perf_evsel__close(struct perf_evsel *evsel, int ncpus, int nthreads)
1119 1081
1120 perf_evsel__close_fd(evsel, ncpus, nthreads); 1082 perf_evsel__close_fd(evsel, ncpus, nthreads);
1121 perf_evsel__free_fd(evsel); 1083 perf_evsel__free_fd(evsel);
1122 evsel->fd = NULL;
1123} 1084}
1124 1085
1125static struct { 1086static struct {
@@ -1998,8 +1959,7 @@ bool perf_evsel__fallback(struct perf_evsel *evsel, int err,
1998 evsel->attr.type = PERF_TYPE_SOFTWARE; 1959 evsel->attr.type = PERF_TYPE_SOFTWARE;
1999 evsel->attr.config = PERF_COUNT_SW_CPU_CLOCK; 1960 evsel->attr.config = PERF_COUNT_SW_CPU_CLOCK;
2000 1961
2001 free(evsel->name); 1962 zfree(&evsel->name);
2002 evsel->name = NULL;
2003 return true; 1963 return true;
2004 } 1964 }
2005 1965
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 1ea7c92e6e33..f1b325665aae 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -68,6 +68,8 @@ struct perf_evsel {
68 u32 ids; 68 u32 ids;
69 struct hists hists; 69 struct hists hists;
70 char *name; 70 char *name;
71 double scale;
72 const char *unit;
71 struct event_format *tp_format; 73 struct event_format *tp_format;
72 union { 74 union {
73 void *priv; 75 void *priv;
@@ -94,7 +96,7 @@ struct perf_evsel {
94struct cpu_map; 96struct cpu_map;
95struct thread_map; 97struct thread_map;
96struct perf_evlist; 98struct perf_evlist;
97struct perf_record_opts; 99struct record_opts;
98 100
99struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx); 101struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx);
100 102
@@ -118,7 +120,7 @@ void perf_evsel__exit(struct perf_evsel *evsel);
118void perf_evsel__delete(struct perf_evsel *evsel); 120void perf_evsel__delete(struct perf_evsel *evsel);
119 121
120void perf_evsel__config(struct perf_evsel *evsel, 122void perf_evsel__config(struct perf_evsel *evsel,
121 struct perf_record_opts *opts); 123 struct record_opts *opts);
122 124
123int __perf_evsel__sample_size(u64 sample_type); 125int __perf_evsel__sample_size(u64 sample_type);
124void perf_evsel__calc_id_pos(struct perf_evsel *evsel); 126void perf_evsel__calc_id_pos(struct perf_evsel *evsel);
@@ -138,6 +140,7 @@ extern const char *perf_evsel__sw_names[PERF_COUNT_SW_MAX];
138int __perf_evsel__hw_cache_type_op_res_name(u8 type, u8 op, u8 result, 140int __perf_evsel__hw_cache_type_op_res_name(u8 type, u8 op, u8 result,
139 char *bf, size_t size); 141 char *bf, size_t size);
140const char *perf_evsel__name(struct perf_evsel *evsel); 142const char *perf_evsel__name(struct perf_evsel *evsel);
143
141const char *perf_evsel__group_name(struct perf_evsel *evsel); 144const char *perf_evsel__group_name(struct perf_evsel *evsel);
142int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size); 145int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size);
143 146
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 369c03648f88..893f8e2df928 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -177,7 +177,7 @@ perf_header__set_cmdline(int argc, const char **argv)
177 continue; \ 177 continue; \
178 else 178 else
179 179
180static int write_buildid(char *name, size_t name_len, u8 *build_id, 180static int write_buildid(const char *name, size_t name_len, u8 *build_id,
181 pid_t pid, u16 misc, int fd) 181 pid_t pid, u16 misc, int fd)
182{ 182{
183 int err; 183 int err;
@@ -209,7 +209,7 @@ static int __dsos__write_buildid_table(struct list_head *head,
209 209
210 dsos__for_each_with_build_id(pos, head) { 210 dsos__for_each_with_build_id(pos, head) {
211 int err; 211 int err;
212 char *name; 212 const char *name;
213 size_t name_len; 213 size_t name_len;
214 214
215 if (!pos->hit) 215 if (!pos->hit)
@@ -387,7 +387,7 @@ static int dso__cache_build_id(struct dso *dso, struct machine *machine,
387{ 387{
388 bool is_kallsyms = dso->kernel && dso->long_name[0] != '/'; 388 bool is_kallsyms = dso->kernel && dso->long_name[0] != '/';
389 bool is_vdso = is_vdso_map(dso->short_name); 389 bool is_vdso = is_vdso_map(dso->short_name);
390 char *name = dso->long_name; 390 const char *name = dso->long_name;
391 char nm[PATH_MAX]; 391 char nm[PATH_MAX];
392 392
393 if (dso__is_kcore(dso)) { 393 if (dso__is_kcore(dso)) {
@@ -643,8 +643,7 @@ static int write_event_desc(int fd, struct perf_header *h __maybe_unused,
643 if (ret < 0) 643 if (ret < 0)
644 return ret; 644 return ret;
645 645
646 list_for_each_entry(evsel, &evlist->entries, node) { 646 evlist__for_each(evlist, evsel) {
647
648 ret = do_write(fd, &evsel->attr, sz); 647 ret = do_write(fd, &evsel->attr, sz);
649 if (ret < 0) 648 if (ret < 0)
650 return ret; 649 return ret;
@@ -800,10 +799,10 @@ static void free_cpu_topo(struct cpu_topo *tp)
800 return; 799 return;
801 800
802 for (i = 0 ; i < tp->core_sib; i++) 801 for (i = 0 ; i < tp->core_sib; i++)
803 free(tp->core_siblings[i]); 802 zfree(&tp->core_siblings[i]);
804 803
805 for (i = 0 ; i < tp->thread_sib; i++) 804 for (i = 0 ; i < tp->thread_sib; i++)
806 free(tp->thread_siblings[i]); 805 zfree(&tp->thread_siblings[i]);
807 806
808 free(tp); 807 free(tp);
809} 808}
@@ -931,7 +930,7 @@ static int write_topo_node(int fd, int node)
931 /* skip over invalid lines */ 930 /* skip over invalid lines */
932 if (!strchr(buf, ':')) 931 if (!strchr(buf, ':'))
933 continue; 932 continue;
934 if (sscanf(buf, "%*s %*d %s %"PRIu64, field, &mem) != 2) 933 if (sscanf(buf, "%*s %*d %31s %"PRIu64, field, &mem) != 2)
935 goto done; 934 goto done;
936 if (!strcmp(field, "MemTotal:")) 935 if (!strcmp(field, "MemTotal:"))
937 mem_total = mem; 936 mem_total = mem;
@@ -1092,7 +1091,7 @@ static int write_group_desc(int fd, struct perf_header *h __maybe_unused,
1092 if (ret < 0) 1091 if (ret < 0)
1093 return ret; 1092 return ret;
1094 1093
1095 list_for_each_entry(evsel, &evlist->entries, node) { 1094 evlist__for_each(evlist, evsel) {
1096 if (perf_evsel__is_group_leader(evsel) && 1095 if (perf_evsel__is_group_leader(evsel) &&
1097 evsel->nr_members > 1) { 1096 evsel->nr_members > 1) {
1098 const char *name = evsel->group_name ?: "{anon_group}"; 1097 const char *name = evsel->group_name ?: "{anon_group}";
@@ -1232,10 +1231,8 @@ static void free_event_desc(struct perf_evsel *events)
1232 return; 1231 return;
1233 1232
1234 for (evsel = events; evsel->attr.size; evsel++) { 1233 for (evsel = events; evsel->attr.size; evsel++) {
1235 if (evsel->name) 1234 zfree(&evsel->name);
1236 free(evsel->name); 1235 zfree(&evsel->id);
1237 if (evsel->id)
1238 free(evsel->id);
1239 } 1236 }
1240 1237
1241 free(events); 1238 free(events);
@@ -1326,8 +1323,7 @@ read_event_desc(struct perf_header *ph, int fd)
1326 } 1323 }
1327 } 1324 }
1328out: 1325out:
1329 if (buf) 1326 free(buf);
1330 free(buf);
1331 return events; 1327 return events;
1332error: 1328error:
1333 if (events) 1329 if (events)
@@ -1490,7 +1486,7 @@ static void print_group_desc(struct perf_header *ph, int fd __maybe_unused,
1490 1486
1491 session = container_of(ph, struct perf_session, header); 1487 session = container_of(ph, struct perf_session, header);
1492 1488
1493 list_for_each_entry(evsel, &session->evlist->entries, node) { 1489 evlist__for_each(session->evlist, evsel) {
1494 if (perf_evsel__is_group_leader(evsel) && 1490 if (perf_evsel__is_group_leader(evsel) &&
1495 evsel->nr_members > 1) { 1491 evsel->nr_members > 1) {
1496 fprintf(fp, "# group: %s{%s", evsel->group_name ?: "", 1492 fprintf(fp, "# group: %s{%s", evsel->group_name ?: "",
@@ -1709,7 +1705,7 @@ static int process_nrcpus(struct perf_file_section *section __maybe_unused,
1709 struct perf_header *ph, int fd, 1705 struct perf_header *ph, int fd,
1710 void *data __maybe_unused) 1706 void *data __maybe_unused)
1711{ 1707{
1712 size_t ret; 1708 ssize_t ret;
1713 u32 nr; 1709 u32 nr;
1714 1710
1715 ret = readn(fd, &nr, sizeof(nr)); 1711 ret = readn(fd, &nr, sizeof(nr));
@@ -1753,7 +1749,7 @@ static int process_total_mem(struct perf_file_section *section __maybe_unused,
1753 void *data __maybe_unused) 1749 void *data __maybe_unused)
1754{ 1750{
1755 uint64_t mem; 1751 uint64_t mem;
1756 size_t ret; 1752 ssize_t ret;
1757 1753
1758 ret = readn(fd, &mem, sizeof(mem)); 1754 ret = readn(fd, &mem, sizeof(mem));
1759 if (ret != sizeof(mem)) 1755 if (ret != sizeof(mem))
@@ -1771,7 +1767,7 @@ perf_evlist__find_by_index(struct perf_evlist *evlist, int idx)
1771{ 1767{
1772 struct perf_evsel *evsel; 1768 struct perf_evsel *evsel;
1773 1769
1774 list_for_each_entry(evsel, &evlist->entries, node) { 1770 evlist__for_each(evlist, evsel) {
1775 if (evsel->idx == idx) 1771 if (evsel->idx == idx)
1776 return evsel; 1772 return evsel;
1777 } 1773 }
@@ -1822,7 +1818,7 @@ static int process_cmdline(struct perf_file_section *section __maybe_unused,
1822 struct perf_header *ph, int fd, 1818 struct perf_header *ph, int fd,
1823 void *data __maybe_unused) 1819 void *data __maybe_unused)
1824{ 1820{
1825 size_t ret; 1821 ssize_t ret;
1826 char *str; 1822 char *str;
1827 u32 nr, i; 1823 u32 nr, i;
1828 struct strbuf sb; 1824 struct strbuf sb;
@@ -1858,7 +1854,7 @@ static int process_cpu_topology(struct perf_file_section *section __maybe_unused
1858 struct perf_header *ph, int fd, 1854 struct perf_header *ph, int fd,
1859 void *data __maybe_unused) 1855 void *data __maybe_unused)
1860{ 1856{
1861 size_t ret; 1857 ssize_t ret;
1862 u32 nr, i; 1858 u32 nr, i;
1863 char *str; 1859 char *str;
1864 struct strbuf sb; 1860 struct strbuf sb;
@@ -1914,7 +1910,7 @@ static int process_numa_topology(struct perf_file_section *section __maybe_unuse
1914 struct perf_header *ph, int fd, 1910 struct perf_header *ph, int fd,
1915 void *data __maybe_unused) 1911 void *data __maybe_unused)
1916{ 1912{
1917 size_t ret; 1913 ssize_t ret;
1918 u32 nr, node, i; 1914 u32 nr, node, i;
1919 char *str; 1915 char *str;
1920 uint64_t mem_total, mem_free; 1916 uint64_t mem_total, mem_free;
@@ -1974,7 +1970,7 @@ static int process_pmu_mappings(struct perf_file_section *section __maybe_unused
1974 struct perf_header *ph, int fd, 1970 struct perf_header *ph, int fd,
1975 void *data __maybe_unused) 1971 void *data __maybe_unused)
1976{ 1972{
1977 size_t ret; 1973 ssize_t ret;
1978 char *name; 1974 char *name;
1979 u32 pmu_num; 1975 u32 pmu_num;
1980 u32 type; 1976 u32 type;
@@ -2074,12 +2070,14 @@ static int process_group_desc(struct perf_file_section *section __maybe_unused,
2074 session->evlist->nr_groups = nr_groups; 2070 session->evlist->nr_groups = nr_groups;
2075 2071
2076 i = nr = 0; 2072 i = nr = 0;
2077 list_for_each_entry(evsel, &session->evlist->entries, node) { 2073 evlist__for_each(session->evlist, evsel) {
2078 if (evsel->idx == (int) desc[i].leader_idx) { 2074 if (evsel->idx == (int) desc[i].leader_idx) {
2079 evsel->leader = evsel; 2075 evsel->leader = evsel;
2080 /* {anon_group} is a dummy name */ 2076 /* {anon_group} is a dummy name */
2081 if (strcmp(desc[i].name, "{anon_group}")) 2077 if (strcmp(desc[i].name, "{anon_group}")) {
2082 evsel->group_name = desc[i].name; 2078 evsel->group_name = desc[i].name;
2079 desc[i].name = NULL;
2080 }
2083 evsel->nr_members = desc[i].nr_members; 2081 evsel->nr_members = desc[i].nr_members;
2084 2082
2085 if (i >= nr_groups || nr > 0) { 2083 if (i >= nr_groups || nr > 0) {
@@ -2105,8 +2103,8 @@ static int process_group_desc(struct perf_file_section *section __maybe_unused,
2105 2103
2106 ret = 0; 2104 ret = 0;
2107out_free: 2105out_free:
2108 while ((int) --i >= 0) 2106 for (i = 0; i < nr_groups; i++)
2109 free(desc[i].name); 2107 zfree(&desc[i].name);
2110 free(desc); 2108 free(desc);
2111 2109
2112 return ret; 2110 return ret;
@@ -2299,7 +2297,7 @@ int perf_session__write_header(struct perf_session *session,
2299 2297
2300 lseek(fd, sizeof(f_header), SEEK_SET); 2298 lseek(fd, sizeof(f_header), SEEK_SET);
2301 2299
2302 list_for_each_entry(evsel, &evlist->entries, node) { 2300 evlist__for_each(session->evlist, evsel) {
2303 evsel->id_offset = lseek(fd, 0, SEEK_CUR); 2301 evsel->id_offset = lseek(fd, 0, SEEK_CUR);
2304 err = do_write(fd, evsel->id, evsel->ids * sizeof(u64)); 2302 err = do_write(fd, evsel->id, evsel->ids * sizeof(u64));
2305 if (err < 0) { 2303 if (err < 0) {
@@ -2310,7 +2308,7 @@ int perf_session__write_header(struct perf_session *session,
2310 2308
2311 attr_offset = lseek(fd, 0, SEEK_CUR); 2309 attr_offset = lseek(fd, 0, SEEK_CUR);
2312 2310
2313 list_for_each_entry(evsel, &evlist->entries, node) { 2311 evlist__for_each(evlist, evsel) {
2314 f_attr = (struct perf_file_attr){ 2312 f_attr = (struct perf_file_attr){
2315 .attr = evsel->attr, 2313 .attr = evsel->attr,
2316 .ids = { 2314 .ids = {
@@ -2325,7 +2323,8 @@ int perf_session__write_header(struct perf_session *session,
2325 } 2323 }
2326 } 2324 }
2327 2325
2328 header->data_offset = lseek(fd, 0, SEEK_CUR); 2326 if (!header->data_offset)
2327 header->data_offset = lseek(fd, 0, SEEK_CUR);
2329 header->feat_offset = header->data_offset + header->data_size; 2328 header->feat_offset = header->data_offset + header->data_size;
2330 2329
2331 if (at_exit) { 2330 if (at_exit) {
@@ -2532,7 +2531,7 @@ static int check_magic_endian(u64 magic, uint64_t hdr_sz,
2532int perf_file_header__read(struct perf_file_header *header, 2531int perf_file_header__read(struct perf_file_header *header,
2533 struct perf_header *ph, int fd) 2532 struct perf_header *ph, int fd)
2534{ 2533{
2535 int ret; 2534 ssize_t ret;
2536 2535
2537 lseek(fd, 0, SEEK_SET); 2536 lseek(fd, 0, SEEK_SET);
2538 2537
@@ -2626,7 +2625,7 @@ static int perf_file_header__read_pipe(struct perf_pipe_file_header *header,
2626 struct perf_header *ph, int fd, 2625 struct perf_header *ph, int fd,
2627 bool repipe) 2626 bool repipe)
2628{ 2627{
2629 int ret; 2628 ssize_t ret;
2630 2629
2631 ret = readn(fd, header, sizeof(*header)); 2630 ret = readn(fd, header, sizeof(*header));
2632 if (ret <= 0) 2631 if (ret <= 0)
@@ -2667,7 +2666,7 @@ static int read_attr(int fd, struct perf_header *ph,
2667 struct perf_event_attr *attr = &f_attr->attr; 2666 struct perf_event_attr *attr = &f_attr->attr;
2668 size_t sz, left; 2667 size_t sz, left;
2669 size_t our_sz = sizeof(f_attr->attr); 2668 size_t our_sz = sizeof(f_attr->attr);
2670 int ret; 2669 ssize_t ret;
2671 2670
2672 memset(f_attr, 0, sizeof(*f_attr)); 2671 memset(f_attr, 0, sizeof(*f_attr));
2673 2672
@@ -2742,7 +2741,7 @@ static int perf_evlist__prepare_tracepoint_events(struct perf_evlist *evlist,
2742{ 2741{
2743 struct perf_evsel *pos; 2742 struct perf_evsel *pos;
2744 2743
2745 list_for_each_entry(pos, &evlist->entries, node) { 2744 evlist__for_each(evlist, pos) {
2746 if (pos->attr.type == PERF_TYPE_TRACEPOINT && 2745 if (pos->attr.type == PERF_TYPE_TRACEPOINT &&
2747 perf_evsel__prepare_tracepoint_event(pos, pevent)) 2746 perf_evsel__prepare_tracepoint_event(pos, pevent))
2748 return -1; 2747 return -1;
@@ -2832,11 +2831,11 @@ int perf_session__read_header(struct perf_session *session)
2832 2831
2833 symbol_conf.nr_events = nr_attrs; 2832 symbol_conf.nr_events = nr_attrs;
2834 2833
2835 perf_header__process_sections(header, fd, &session->pevent, 2834 perf_header__process_sections(header, fd, &session->tevent,
2836 perf_file_section__process); 2835 perf_file_section__process);
2837 2836
2838 if (perf_evlist__prepare_tracepoint_events(session->evlist, 2837 if (perf_evlist__prepare_tracepoint_events(session->evlist,
2839 session->pevent)) 2838 session->tevent.pevent))
2840 goto out_delete_evlist; 2839 goto out_delete_evlist;
2841 2840
2842 return 0; 2841 return 0;
@@ -2890,7 +2889,7 @@ int perf_event__synthesize_attrs(struct perf_tool *tool,
2890 struct perf_evsel *evsel; 2889 struct perf_evsel *evsel;
2891 int err = 0; 2890 int err = 0;
2892 2891
2893 list_for_each_entry(evsel, &session->evlist->entries, node) { 2892 evlist__for_each(session->evlist, evsel) {
2894 err = perf_event__synthesize_attr(tool, &evsel->attr, evsel->ids, 2893 err = perf_event__synthesize_attr(tool, &evsel->attr, evsel->ids,
2895 evsel->id, process); 2894 evsel->id, process);
2896 if (err) { 2895 if (err) {
@@ -3001,7 +3000,7 @@ int perf_event__process_tracing_data(struct perf_tool *tool __maybe_unused,
3001 lseek(fd, offset + sizeof(struct tracing_data_event), 3000 lseek(fd, offset + sizeof(struct tracing_data_event),
3002 SEEK_SET); 3001 SEEK_SET);
3003 3002
3004 size_read = trace_report(fd, &session->pevent, 3003 size_read = trace_report(fd, &session->tevent,
3005 session->repipe); 3004 session->repipe);
3006 padding = PERF_ALIGN(size_read, sizeof(u64)) - size_read; 3005 padding = PERF_ALIGN(size_read, sizeof(u64)) - size_read;
3007 3006
@@ -3023,7 +3022,7 @@ int perf_event__process_tracing_data(struct perf_tool *tool __maybe_unused,
3023 } 3022 }
3024 3023
3025 perf_evlist__prepare_tracepoint_events(session->evlist, 3024 perf_evlist__prepare_tracepoint_events(session->evlist,
3026 session->pevent); 3025 session->tevent.pevent);
3027 3026
3028 return size_read + padding; 3027 return size_read + padding;
3029} 3028}
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 307c9aed972e..a2d047bdf4ef 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -77,16 +77,16 @@ struct perf_session_env {
77 unsigned long long total_mem; 77 unsigned long long total_mem;
78 78
79 int nr_cmdline; 79 int nr_cmdline;
80 char *cmdline;
81 int nr_sibling_cores; 80 int nr_sibling_cores;
82 char *sibling_cores;
83 int nr_sibling_threads; 81 int nr_sibling_threads;
84 char *sibling_threads;
85 int nr_numa_nodes; 82 int nr_numa_nodes;
86 char *numa_nodes;
87 int nr_pmu_mappings; 83 int nr_pmu_mappings;
88 char *pmu_mappings;
89 int nr_groups; 84 int nr_groups;
85 char *cmdline;
86 char *sibling_cores;
87 char *sibling_threads;
88 char *numa_nodes;
89 char *pmu_mappings;
90}; 90};
91 91
92struct perf_header { 92struct perf_header {
diff --git a/tools/perf/util/help.c b/tools/perf/util/help.c
index 8b1f6e891b8a..86c37c472263 100644
--- a/tools/perf/util/help.c
+++ b/tools/perf/util/help.c
@@ -22,8 +22,8 @@ static void clean_cmdnames(struct cmdnames *cmds)
22 unsigned int i; 22 unsigned int i;
23 23
24 for (i = 0; i < cmds->cnt; ++i) 24 for (i = 0; i < cmds->cnt; ++i)
25 free(cmds->names[i]); 25 zfree(&cmds->names[i]);
26 free(cmds->names); 26 zfree(&cmds->names);
27 cmds->cnt = 0; 27 cmds->cnt = 0;
28 cmds->alloc = 0; 28 cmds->alloc = 0;
29} 29}
@@ -263,9 +263,8 @@ static void add_cmd_list(struct cmdnames *cmds, struct cmdnames *old)
263 263
264 for (i = 0; i < old->cnt; i++) 264 for (i = 0; i < old->cnt; i++)
265 cmds->names[cmds->cnt++] = old->names[i]; 265 cmds->names[cmds->cnt++] = old->names[i];
266 free(old->names); 266 zfree(&old->names);
267 old->cnt = 0; 267 old->cnt = 0;
268 old->names = NULL;
269} 268}
270 269
271const char *help_unknown_cmd(const char *cmd) 270const char *help_unknown_cmd(const char *cmd)
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 822903eaa201..e4e6249b87d4 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -1,4 +1,3 @@
1#include "annotate.h"
2#include "util.h" 1#include "util.h"
3#include "build-id.h" 2#include "build-id.h"
4#include "hist.h" 3#include "hist.h"
@@ -182,21 +181,21 @@ void hists__output_recalc_col_len(struct hists *hists, int max_rows)
182 } 181 }
183} 182}
184 183
185static void hist_entry__add_cpumode_period(struct hist_entry *he, 184static void he_stat__add_cpumode_period(struct he_stat *he_stat,
186 unsigned int cpumode, u64 period) 185 unsigned int cpumode, u64 period)
187{ 186{
188 switch (cpumode) { 187 switch (cpumode) {
189 case PERF_RECORD_MISC_KERNEL: 188 case PERF_RECORD_MISC_KERNEL:
190 he->stat.period_sys += period; 189 he_stat->period_sys += period;
191 break; 190 break;
192 case PERF_RECORD_MISC_USER: 191 case PERF_RECORD_MISC_USER:
193 he->stat.period_us += period; 192 he_stat->period_us += period;
194 break; 193 break;
195 case PERF_RECORD_MISC_GUEST_KERNEL: 194 case PERF_RECORD_MISC_GUEST_KERNEL:
196 he->stat.period_guest_sys += period; 195 he_stat->period_guest_sys += period;
197 break; 196 break;
198 case PERF_RECORD_MISC_GUEST_USER: 197 case PERF_RECORD_MISC_GUEST_USER:
199 he->stat.period_guest_us += period; 198 he_stat->period_guest_us += period;
200 break; 199 break;
201 default: 200 default:
202 break; 201 break;
@@ -223,10 +222,10 @@ static void he_stat__add_stat(struct he_stat *dest, struct he_stat *src)
223 dest->weight += src->weight; 222 dest->weight += src->weight;
224} 223}
225 224
226static void hist_entry__decay(struct hist_entry *he) 225static void he_stat__decay(struct he_stat *he_stat)
227{ 226{
228 he->stat.period = (he->stat.period * 7) / 8; 227 he_stat->period = (he_stat->period * 7) / 8;
229 he->stat.nr_events = (he->stat.nr_events * 7) / 8; 228 he_stat->nr_events = (he_stat->nr_events * 7) / 8;
230 /* XXX need decay for weight too? */ 229 /* XXX need decay for weight too? */
231} 230}
232 231
@@ -237,7 +236,7 @@ static bool hists__decay_entry(struct hists *hists, struct hist_entry *he)
237 if (prev_period == 0) 236 if (prev_period == 0)
238 return true; 237 return true;
239 238
240 hist_entry__decay(he); 239 he_stat__decay(&he->stat);
241 240
242 if (!he->filtered) 241 if (!he->filtered)
243 hists->stats.total_period -= prev_period - he->stat.period; 242 hists->stats.total_period -= prev_period - he->stat.period;
@@ -342,15 +341,15 @@ static u8 symbol__parent_filter(const struct symbol *parent)
342} 341}
343 342
344static struct hist_entry *add_hist_entry(struct hists *hists, 343static struct hist_entry *add_hist_entry(struct hists *hists,
345 struct hist_entry *entry, 344 struct hist_entry *entry,
346 struct addr_location *al, 345 struct addr_location *al)
347 u64 period,
348 u64 weight)
349{ 346{
350 struct rb_node **p; 347 struct rb_node **p;
351 struct rb_node *parent = NULL; 348 struct rb_node *parent = NULL;
352 struct hist_entry *he; 349 struct hist_entry *he;
353 int64_t cmp; 350 int64_t cmp;
351 u64 period = entry->stat.period;
352 u64 weight = entry->stat.weight;
354 353
355 p = &hists->entries_in->rb_node; 354 p = &hists->entries_in->rb_node;
356 355
@@ -373,7 +372,7 @@ static struct hist_entry *add_hist_entry(struct hists *hists,
373 * This mem info was allocated from machine__resolve_mem 372 * This mem info was allocated from machine__resolve_mem
374 * and will not be used anymore. 373 * and will not be used anymore.
375 */ 374 */
376 free(entry->mem_info); 375 zfree(&entry->mem_info);
377 376
378 /* If the map of an existing hist_entry has 377 /* If the map of an existing hist_entry has
379 * become out-of-date due to an exec() or 378 * become out-of-date due to an exec() or
@@ -403,7 +402,7 @@ static struct hist_entry *add_hist_entry(struct hists *hists,
403 rb_link_node(&he->rb_node_in, parent, p); 402 rb_link_node(&he->rb_node_in, parent, p);
404 rb_insert_color(&he->rb_node_in, hists->entries_in); 403 rb_insert_color(&he->rb_node_in, hists->entries_in);
405out: 404out:
406 hist_entry__add_cpumode_period(he, al->cpumode, period); 405 he_stat__add_cpumode_period(&he->stat, al->cpumode, period);
407 return he; 406 return he;
408} 407}
409 408
@@ -437,7 +436,7 @@ struct hist_entry *__hists__add_entry(struct hists *hists,
437 .transaction = transaction, 436 .transaction = transaction,
438 }; 437 };
439 438
440 return add_hist_entry(hists, &entry, al, period, weight); 439 return add_hist_entry(hists, &entry, al);
441} 440}
442 441
443int64_t 442int64_t
@@ -476,8 +475,8 @@ hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
476 475
477void hist_entry__free(struct hist_entry *he) 476void hist_entry__free(struct hist_entry *he)
478{ 477{
479 free(he->branch_info); 478 zfree(&he->branch_info);
480 free(he->mem_info); 479 zfree(&he->mem_info);
481 free_srcline(he->srcline); 480 free_srcline(he->srcline);
482 free(he); 481 free(he);
483} 482}
@@ -807,16 +806,6 @@ void hists__filter_by_symbol(struct hists *hists)
807 } 806 }
808} 807}
809 808
810int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 ip)
811{
812 return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evidx, ip);
813}
814
815int hist_entry__annotate(struct hist_entry *he, size_t privsize)
816{
817 return symbol__annotate(he->ms.sym, he->ms.map, privsize);
818}
819
820void events_stats__inc(struct events_stats *stats, u32 type) 809void events_stats__inc(struct events_stats *stats, u32 type)
821{ 810{
822 ++stats->nr_events[0]; 811 ++stats->nr_events[0];
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index b621347a1585..a59743fa3ef7 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -111,9 +111,6 @@ size_t events_stats__fprintf(struct events_stats *stats, FILE *fp);
111size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, 111size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
112 int max_cols, float min_pcnt, FILE *fp); 112 int max_cols, float min_pcnt, FILE *fp);
113 113
114int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 addr);
115int hist_entry__annotate(struct hist_entry *he, size_t privsize);
116
117void hists__filter_by_dso(struct hists *hists); 114void hists__filter_by_dso(struct hists *hists);
118void hists__filter_by_thread(struct hists *hists); 115void hists__filter_by_thread(struct hists *hists);
119void hists__filter_by_symbol(struct hists *hists); 116void hists__filter_by_symbol(struct hists *hists);
diff --git a/tools/perf/util/include/asm/bug.h b/tools/perf/util/include/asm/bug.h
deleted file mode 100644
index 7fcc6810adc2..000000000000
--- a/tools/perf/util/include/asm/bug.h
+++ /dev/null
@@ -1,22 +0,0 @@
1#ifndef _PERF_ASM_GENERIC_BUG_H
2#define _PERF_ASM_GENERIC_BUG_H
3
4#define __WARN_printf(arg...) do { fprintf(stderr, arg); } while (0)
5
6#define WARN(condition, format...) ({ \
7 int __ret_warn_on = !!(condition); \
8 if (unlikely(__ret_warn_on)) \
9 __WARN_printf(format); \
10 unlikely(__ret_warn_on); \
11})
12
13#define WARN_ONCE(condition, format...) ({ \
14 static int __warned; \
15 int __ret_warn_once = !!(condition); \
16 \
17 if (unlikely(__ret_warn_once)) \
18 if (WARN(!__warned, format)) \
19 __warned = 1; \
20 unlikely(__ret_warn_once); \
21})
22#endif
diff --git a/tools/perf/util/include/linux/compiler.h b/tools/perf/util/include/linux/compiler.h
deleted file mode 100644
index b003ad7200b2..000000000000
--- a/tools/perf/util/include/linux/compiler.h
+++ /dev/null
@@ -1,30 +0,0 @@
1#ifndef _PERF_LINUX_COMPILER_H_
2#define _PERF_LINUX_COMPILER_H_
3
4#ifndef __always_inline
5# define __always_inline inline __attribute__((always_inline))
6#endif
7
8#define __user
9
10#ifndef __attribute_const__
11# define __attribute_const__
12#endif
13
14#ifndef __maybe_unused
15# define __maybe_unused __attribute__((unused))
16#endif
17
18#ifndef __packed
19# define __packed __attribute__((__packed__))
20#endif
21
22#ifndef __force
23# define __force
24#endif
25
26#ifndef __weak
27# define __weak __attribute__((weak))
28#endif
29
30#endif
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 84cdb072ac83..ded74590b92f 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -9,6 +9,7 @@
9#include "strlist.h" 9#include "strlist.h"
10#include "thread.h" 10#include "thread.h"
11#include <stdbool.h> 11#include <stdbool.h>
12#include <symbol/kallsyms.h>
12#include "unwind.h" 13#include "unwind.h"
13 14
14int machine__init(struct machine *machine, const char *root_dir, pid_t pid) 15int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
@@ -26,6 +27,7 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
26 machine->pid = pid; 27 machine->pid = pid;
27 28
28 machine->symbol_filter = NULL; 29 machine->symbol_filter = NULL;
30 machine->id_hdr_size = 0;
29 31
30 machine->root_dir = strdup(root_dir); 32 machine->root_dir = strdup(root_dir);
31 if (machine->root_dir == NULL) 33 if (machine->root_dir == NULL)
@@ -101,8 +103,7 @@ void machine__exit(struct machine *machine)
101 map_groups__exit(&machine->kmaps); 103 map_groups__exit(&machine->kmaps);
102 dsos__delete(&machine->user_dsos); 104 dsos__delete(&machine->user_dsos);
103 dsos__delete(&machine->kernel_dsos); 105 dsos__delete(&machine->kernel_dsos);
104 free(machine->root_dir); 106 zfree(&machine->root_dir);
105 machine->root_dir = NULL;
106} 107}
107 108
108void machine__delete(struct machine *machine) 109void machine__delete(struct machine *machine)
@@ -502,15 +503,11 @@ static u64 machine__get_kernel_start_addr(struct machine *machine)
502 char path[PATH_MAX]; 503 char path[PATH_MAX];
503 struct process_args args; 504 struct process_args args;
504 505
505 if (machine__is_host(machine)) { 506 if (machine__is_default_guest(machine))
506 filename = "/proc/kallsyms"; 507 filename = (char *)symbol_conf.default_guest_kallsyms;
507 } else { 508 else {
508 if (machine__is_default_guest(machine)) 509 sprintf(path, "%s/proc/kallsyms", machine->root_dir);
509 filename = (char *)symbol_conf.default_guest_kallsyms; 510 filename = path;
510 else {
511 sprintf(path, "%s/proc/kallsyms", machine->root_dir);
512 filename = path;
513 }
514 } 511 }
515 512
516 if (symbol__restricted_filename(filename, "/proc/kallsyms")) 513 if (symbol__restricted_filename(filename, "/proc/kallsyms"))
@@ -565,11 +562,10 @@ void machine__destroy_kernel_maps(struct machine *machine)
565 * on one of them. 562 * on one of them.
566 */ 563 */
567 if (type == MAP__FUNCTION) { 564 if (type == MAP__FUNCTION) {
568 free((char *)kmap->ref_reloc_sym->name); 565 zfree((char **)&kmap->ref_reloc_sym->name);
569 kmap->ref_reloc_sym->name = NULL; 566 zfree(&kmap->ref_reloc_sym);
570 free(kmap->ref_reloc_sym); 567 } else
571 } 568 kmap->ref_reloc_sym = NULL;
572 kmap->ref_reloc_sym = NULL;
573 } 569 }
574 570
575 map__delete(machine->vmlinux_maps[type]); 571 map__delete(machine->vmlinux_maps[type]);
@@ -767,8 +763,7 @@ static int map_groups__set_modules_path_dir(struct map_groups *mg,
767 ret = -1; 763 ret = -1;
768 goto out; 764 goto out;
769 } 765 }
770 dso__set_long_name(map->dso, long_name); 766 dso__set_long_name(map->dso, long_name, true);
771 map->dso->lname_alloc = 1;
772 dso__kernel_module_get_build_id(map->dso, ""); 767 dso__kernel_module_get_build_id(map->dso, "");
773 } 768 }
774 } 769 }
@@ -939,8 +934,7 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
939 if (name == NULL) 934 if (name == NULL)
940 goto out_problem; 935 goto out_problem;
941 936
942 map->dso->short_name = name; 937 dso__set_short_name(map->dso, name, true);
943 map->dso->sname_alloc = 1;
944 map->end = map->start + event->mmap.len; 938 map->end = map->start + event->mmap.len;
945 } else if (is_kernel_mmap) { 939 } else if (is_kernel_mmap) {
946 const char *symbol_name = (event->mmap.filename + 940 const char *symbol_name = (event->mmap.filename +
@@ -1320,8 +1314,6 @@ static int machine__resolve_callchain_sample(struct machine *machine,
1320 *root_al = al; 1314 *root_al = al;
1321 callchain_cursor_reset(&callchain_cursor); 1315 callchain_cursor_reset(&callchain_cursor);
1322 } 1316 }
1323 if (!symbol_conf.use_callchain)
1324 break;
1325 } 1317 }
1326 1318
1327 err = callchain_cursor_append(&callchain_cursor, 1319 err = callchain_cursor_append(&callchain_cursor,
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index ef5bc913ca7a..3b97513f0e77 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -11,6 +11,7 @@
11#include "strlist.h" 11#include "strlist.h"
12#include "vdso.h" 12#include "vdso.h"
13#include "build-id.h" 13#include "build-id.h"
14#include "util.h"
14#include <linux/string.h> 15#include <linux/string.h>
15 16
16const char *map_type__name[MAP__NR_TYPES] = { 17const char *map_type__name[MAP__NR_TYPES] = {
@@ -68,7 +69,7 @@ struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
68 map->ino = ino; 69 map->ino = ino;
69 map->ino_generation = ino_gen; 70 map->ino_generation = ino_gen;
70 71
71 if (anon) { 72 if ((anon || no_dso) && type == MAP__FUNCTION) {
72 snprintf(newfilename, sizeof(newfilename), "/tmp/perf-%d.map", pid); 73 snprintf(newfilename, sizeof(newfilename), "/tmp/perf-%d.map", pid);
73 filename = newfilename; 74 filename = newfilename;
74 } 75 }
@@ -92,7 +93,7 @@ struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
92 * functions still return NULL, and we avoid the 93 * functions still return NULL, and we avoid the
93 * unnecessary map__load warning. 94 * unnecessary map__load warning.
94 */ 95 */
95 if (no_dso) 96 if (type != MAP__FUNCTION)
96 dso__set_loaded(dso, map->type); 97 dso__set_loaded(dso, map->type);
97 } 98 }
98 } 99 }
@@ -252,6 +253,22 @@ size_t map__fprintf_dsoname(struct map *map, FILE *fp)
252 return fprintf(fp, "%s", dsoname); 253 return fprintf(fp, "%s", dsoname);
253} 254}
254 255
256int map__fprintf_srcline(struct map *map, u64 addr, const char *prefix,
257 FILE *fp)
258{
259 char *srcline;
260 int ret = 0;
261
262 if (map && map->dso) {
263 srcline = get_srcline(map->dso,
264 map__rip_2objdump(map, addr));
265 if (srcline != SRCLINE_UNKNOWN)
266 ret = fprintf(fp, "%s%s", prefix, srcline);
267 free_srcline(srcline);
268 }
269 return ret;
270}
271
255/** 272/**
256 * map__rip_2objdump - convert symbol start address to objdump address. 273 * map__rip_2objdump - convert symbol start address to objdump address.
257 * @map: memory map 274 * @map: memory map
@@ -369,7 +386,8 @@ struct symbol *map_groups__find_symbol(struct map_groups *mg,
369{ 386{
370 struct map *map = map_groups__find(mg, type, addr); 387 struct map *map = map_groups__find(mg, type, addr);
371 388
372 if (map != NULL) { 389 /* Ensure map is loaded before using map->map_ip */
390 if (map != NULL && map__load(map, filter) >= 0) {
373 if (mapp != NULL) 391 if (mapp != NULL)
374 *mapp = map; 392 *mapp = map;
375 return map__find_symbol(map, map->map_ip(map, addr), filter); 393 return map__find_symbol(map, map->map_ip(map, addr), filter);
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index e4e259c3ba16..18068c6b71c1 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -103,6 +103,8 @@ struct map *map__clone(struct map *map);
103int map__overlap(struct map *l, struct map *r); 103int map__overlap(struct map *l, struct map *r);
104size_t map__fprintf(struct map *map, FILE *fp); 104size_t map__fprintf(struct map *map, FILE *fp);
105size_t map__fprintf_dsoname(struct map *map, FILE *fp); 105size_t map__fprintf_dsoname(struct map *map, FILE *fp);
106int map__fprintf_srcline(struct map *map, u64 addr, const char *prefix,
107 FILE *fp);
106 108
107int map__load(struct map *map, symbol_filter_t filter); 109int map__load(struct map *map, symbol_filter_t filter);
108struct symbol *map__find_symbol(struct map *map, 110struct symbol *map__find_symbol(struct map *map,
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 6de6f89c2a61..d248fca6d7ed 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -10,7 +10,7 @@
10#include "symbol.h" 10#include "symbol.h"
11#include "cache.h" 11#include "cache.h"
12#include "header.h" 12#include "header.h"
13#include <lk/debugfs.h> 13#include <api/fs/debugfs.h>
14#include "parse-events-bison.h" 14#include "parse-events-bison.h"
15#define YY_EXTRA_TYPE int 15#define YY_EXTRA_TYPE int
16#include "parse-events-flex.h" 16#include "parse-events-flex.h"
@@ -204,7 +204,7 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config)
204 } 204 }
205 path->name = malloc(MAX_EVENT_LENGTH); 205 path->name = malloc(MAX_EVENT_LENGTH);
206 if (!path->name) { 206 if (!path->name) {
207 free(path->system); 207 zfree(&path->system);
208 free(path); 208 free(path);
209 return NULL; 209 return NULL;
210 } 210 }
@@ -236,8 +236,8 @@ struct tracepoint_path *tracepoint_name_to_path(const char *name)
236 path->name = strdup(str+1); 236 path->name = strdup(str+1);
237 237
238 if (path->system == NULL || path->name == NULL) { 238 if (path->system == NULL || path->name == NULL) {
239 free(path->system); 239 zfree(&path->system);
240 free(path->name); 240 zfree(&path->name);
241 free(path); 241 free(path);
242 path = NULL; 242 path = NULL;
243 } 243 }
@@ -269,9 +269,10 @@ const char *event_type(int type)
269 269
270 270
271 271
272static int __add_event(struct list_head *list, int *idx, 272static struct perf_evsel *
273 struct perf_event_attr *attr, 273__add_event(struct list_head *list, int *idx,
274 char *name, struct cpu_map *cpus) 274 struct perf_event_attr *attr,
275 char *name, struct cpu_map *cpus)
275{ 276{
276 struct perf_evsel *evsel; 277 struct perf_evsel *evsel;
277 278
@@ -279,19 +280,19 @@ static int __add_event(struct list_head *list, int *idx,
279 280
280 evsel = perf_evsel__new_idx(attr, (*idx)++); 281 evsel = perf_evsel__new_idx(attr, (*idx)++);
281 if (!evsel) 282 if (!evsel)
282 return -ENOMEM; 283 return NULL;
283 284
284 evsel->cpus = cpus; 285 evsel->cpus = cpus;
285 if (name) 286 if (name)
286 evsel->name = strdup(name); 287 evsel->name = strdup(name);
287 list_add_tail(&evsel->node, list); 288 list_add_tail(&evsel->node, list);
288 return 0; 289 return evsel;
289} 290}
290 291
291static int add_event(struct list_head *list, int *idx, 292static int add_event(struct list_head *list, int *idx,
292 struct perf_event_attr *attr, char *name) 293 struct perf_event_attr *attr, char *name)
293{ 294{
294 return __add_event(list, idx, attr, name, NULL); 295 return __add_event(list, idx, attr, name, NULL) ? 0 : -ENOMEM;
295} 296}
296 297
297static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES], int size) 298static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES], int size)
@@ -633,6 +634,9 @@ int parse_events_add_pmu(struct list_head *list, int *idx,
633{ 634{
634 struct perf_event_attr attr; 635 struct perf_event_attr attr;
635 struct perf_pmu *pmu; 636 struct perf_pmu *pmu;
637 struct perf_evsel *evsel;
638 const char *unit;
639 double scale;
636 640
637 pmu = perf_pmu__find(name); 641 pmu = perf_pmu__find(name);
638 if (!pmu) 642 if (!pmu)
@@ -640,7 +644,7 @@ int parse_events_add_pmu(struct list_head *list, int *idx,
640 644
641 memset(&attr, 0, sizeof(attr)); 645 memset(&attr, 0, sizeof(attr));
642 646
643 if (perf_pmu__check_alias(pmu, head_config)) 647 if (perf_pmu__check_alias(pmu, head_config, &unit, &scale))
644 return -EINVAL; 648 return -EINVAL;
645 649
646 /* 650 /*
@@ -652,8 +656,14 @@ int parse_events_add_pmu(struct list_head *list, int *idx,
652 if (perf_pmu__config(pmu, &attr, head_config)) 656 if (perf_pmu__config(pmu, &attr, head_config))
653 return -EINVAL; 657 return -EINVAL;
654 658
655 return __add_event(list, idx, &attr, pmu_event_name(head_config), 659 evsel = __add_event(list, idx, &attr, pmu_event_name(head_config),
656 pmu->cpus); 660 pmu->cpus);
661 if (evsel) {
662 evsel->unit = unit;
663 evsel->scale = scale;
664 }
665
666 return evsel ? 0 : -ENOMEM;
657} 667}
658 668
659int parse_events__modifier_group(struct list_head *list, 669int parse_events__modifier_group(struct list_head *list,
@@ -810,8 +820,7 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add)
810 if (!add && get_event_modifier(&mod, str, NULL)) 820 if (!add && get_event_modifier(&mod, str, NULL))
811 return -EINVAL; 821 return -EINVAL;
812 822
813 list_for_each_entry(evsel, list, node) { 823 __evlist__for_each(list, evsel) {
814
815 if (add && get_event_modifier(&mod, str, evsel)) 824 if (add && get_event_modifier(&mod, str, evsel))
816 return -EINVAL; 825 return -EINVAL;
817 826
@@ -835,7 +844,7 @@ int parse_events_name(struct list_head *list, char *name)
835{ 844{
836 struct perf_evsel *evsel; 845 struct perf_evsel *evsel;
837 846
838 list_for_each_entry(evsel, list, node) { 847 __evlist__for_each(list, evsel) {
839 if (!evsel->name) 848 if (!evsel->name)
840 evsel->name = strdup(name); 849 evsel->name = strdup(name);
841 } 850 }
@@ -907,7 +916,7 @@ int parse_events_terms(struct list_head *terms, const char *str)
907 ret = parse_events__scanner(str, &data, PE_START_TERMS); 916 ret = parse_events__scanner(str, &data, PE_START_TERMS);
908 if (!ret) { 917 if (!ret) {
909 list_splice(data.terms, terms); 918 list_splice(data.terms, terms);
910 free(data.terms); 919 zfree(&data.terms);
911 return 0; 920 return 0;
912 } 921 }
913 922
diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c
index 31f404a032a9..d22e3f8017dc 100644
--- a/tools/perf/util/parse-options.c
+++ b/tools/perf/util/parse-options.c
@@ -78,6 +78,8 @@ static int get_value(struct parse_opt_ctx_t *p,
78 78
79 case OPTION_BOOLEAN: 79 case OPTION_BOOLEAN:
80 *(bool *)opt->value = unset ? false : true; 80 *(bool *)opt->value = unset ? false : true;
81 if (opt->set)
82 *(bool *)opt->set = true;
81 return 0; 83 return 0;
82 84
83 case OPTION_INCR: 85 case OPTION_INCR:
@@ -224,6 +226,24 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,
224 return 0; 226 return 0;
225 } 227 }
226 if (!rest) { 228 if (!rest) {
229 if (!prefixcmp(options->long_name, "no-")) {
230 /*
231 * The long name itself starts with "no-", so
232 * accept the option without "no-" so that users
233 * do not have to enter "no-no-" to get the
234 * negation.
235 */
236 rest = skip_prefix(arg, options->long_name + 3);
237 if (rest) {
238 flags |= OPT_UNSET;
239 goto match;
240 }
241 /* Abbreviated case */
242 if (!prefixcmp(options->long_name + 3, arg)) {
243 flags |= OPT_UNSET;
244 goto is_abbreviated;
245 }
246 }
227 /* abbreviated? */ 247 /* abbreviated? */
228 if (!strncmp(options->long_name, arg, arg_end - arg)) { 248 if (!strncmp(options->long_name, arg, arg_end - arg)) {
229is_abbreviated: 249is_abbreviated:
@@ -259,6 +279,7 @@ is_abbreviated:
259 if (!rest) 279 if (!rest)
260 continue; 280 continue;
261 } 281 }
282match:
262 if (*rest) { 283 if (*rest) {
263 if (*rest != '=') 284 if (*rest != '=')
264 continue; 285 continue;
diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h
index b0241e28eaf7..cbf0149cf221 100644
--- a/tools/perf/util/parse-options.h
+++ b/tools/perf/util/parse-options.h
@@ -82,6 +82,9 @@ typedef int parse_opt_cb(const struct option *, const char *arg, int unset);
82 * OPTION_{BIT,SET_UINT,SET_PTR} store the {mask,integer,pointer} to put in 82 * OPTION_{BIT,SET_UINT,SET_PTR} store the {mask,integer,pointer} to put in
83 * the value when met. 83 * the value when met.
84 * CALLBACKS can use it like they want. 84 * CALLBACKS can use it like they want.
85 *
86 * `set`::
87 * whether an option was set by the user
85 */ 88 */
86struct option { 89struct option {
87 enum parse_opt_type type; 90 enum parse_opt_type type;
@@ -94,6 +97,7 @@ struct option {
94 int flags; 97 int flags;
95 parse_opt_cb *callback; 98 parse_opt_cb *callback;
96 intptr_t defval; 99 intptr_t defval;
100 bool *set;
97}; 101};
98 102
99#define check_vtype(v, type) ( BUILD_BUG_ON_ZERO(!__builtin_types_compatible_p(typeof(v), type)) + v ) 103#define check_vtype(v, type) ( BUILD_BUG_ON_ZERO(!__builtin_types_compatible_p(typeof(v), type)) + v )
@@ -103,6 +107,10 @@ struct option {
103#define OPT_GROUP(h) { .type = OPTION_GROUP, .help = (h) } 107#define OPT_GROUP(h) { .type = OPTION_GROUP, .help = (h) }
104#define OPT_BIT(s, l, v, h, b) { .type = OPTION_BIT, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h), .defval = (b) } 108#define OPT_BIT(s, l, v, h, b) { .type = OPTION_BIT, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h), .defval = (b) }
105#define OPT_BOOLEAN(s, l, v, h) { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), .value = check_vtype(v, bool *), .help = (h) } 109#define OPT_BOOLEAN(s, l, v, h) { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), .value = check_vtype(v, bool *), .help = (h) }
110#define OPT_BOOLEAN_SET(s, l, v, os, h) \
111 { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), \
112 .value = check_vtype(v, bool *), .help = (h), \
113 .set = check_vtype(os, bool *)}
106#define OPT_INCR(s, l, v, h) { .type = OPTION_INCR, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h) } 114#define OPT_INCR(s, l, v, h) { .type = OPTION_INCR, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h) }
107#define OPT_SET_UINT(s, l, v, h, i) { .type = OPTION_SET_UINT, .short_name = (s), .long_name = (l), .value = check_vtype(v, unsigned int *), .help = (h), .defval = (i) } 115#define OPT_SET_UINT(s, l, v, h, i) { .type = OPTION_SET_UINT, .short_name = (s), .long_name = (l), .value = check_vtype(v, unsigned int *), .help = (h), .defval = (i) }
108#define OPT_SET_PTR(s, l, v, h, p) { .type = OPTION_SET_PTR, .short_name = (s), .long_name = (l), .value = (v), .help = (h), .defval = (p) } 116#define OPT_SET_PTR(s, l, v, h, p) { .type = OPTION_SET_PTR, .short_name = (s), .long_name = (l), .value = (v), .help = (h), .defval = (p) }
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index c232d8dd410b..b752ecb40d86 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -1,19 +1,23 @@
1#include <linux/list.h> 1#include <linux/list.h>
2#include <sys/types.h> 2#include <sys/types.h>
3#include <sys/stat.h>
4#include <unistd.h> 3#include <unistd.h>
5#include <stdio.h> 4#include <stdio.h>
6#include <dirent.h> 5#include <dirent.h>
7#include "fs.h" 6#include "fs.h"
7#include <locale.h>
8#include "util.h" 8#include "util.h"
9#include "pmu.h" 9#include "pmu.h"
10#include "parse-events.h" 10#include "parse-events.h"
11#include "cpumap.h" 11#include "cpumap.h"
12 12
13#define UNIT_MAX_LEN 31 /* max length for event unit name */
14
13struct perf_pmu_alias { 15struct perf_pmu_alias {
14 char *name; 16 char *name;
15 struct list_head terms; 17 struct list_head terms;
16 struct list_head list; 18 struct list_head list;
19 char unit[UNIT_MAX_LEN+1];
20 double scale;
17}; 21};
18 22
19struct perf_pmu_format { 23struct perf_pmu_format {
@@ -94,7 +98,80 @@ static int pmu_format(const char *name, struct list_head *format)
94 return 0; 98 return 0;
95} 99}
96 100
97static int perf_pmu__new_alias(struct list_head *list, char *name, FILE *file) 101static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char *name)
102{
103 struct stat st;
104 ssize_t sret;
105 char scale[128];
106 int fd, ret = -1;
107 char path[PATH_MAX];
108 const char *lc;
109
110 snprintf(path, PATH_MAX, "%s/%s.scale", dir, name);
111
112 fd = open(path, O_RDONLY);
113 if (fd == -1)
114 return -1;
115
116 if (fstat(fd, &st) < 0)
117 goto error;
118
119 sret = read(fd, scale, sizeof(scale)-1);
120 if (sret < 0)
121 goto error;
122
123 scale[sret] = '\0';
124 /*
125 * save current locale
126 */
127 lc = setlocale(LC_NUMERIC, NULL);
128
129 /*
130 * force to C locale to ensure kernel
131 * scale string is converted correctly.
132 * kernel uses default C locale.
133 */
134 setlocale(LC_NUMERIC, "C");
135
136 alias->scale = strtod(scale, NULL);
137
138 /* restore locale */
139 setlocale(LC_NUMERIC, lc);
140
141 ret = 0;
142error:
143 close(fd);
144 return ret;
145}
146
147static int perf_pmu__parse_unit(struct perf_pmu_alias *alias, char *dir, char *name)
148{
149 char path[PATH_MAX];
150 ssize_t sret;
151 int fd;
152
153 snprintf(path, PATH_MAX, "%s/%s.unit", dir, name);
154
155 fd = open(path, O_RDONLY);
156 if (fd == -1)
157 return -1;
158
159 sret = read(fd, alias->unit, UNIT_MAX_LEN);
160 if (sret < 0)
161 goto error;
162
163 close(fd);
164
165 alias->unit[sret] = '\0';
166
167 return 0;
168error:
169 close(fd);
170 alias->unit[0] = '\0';
171 return -1;
172}
173
174static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FILE *file)
98{ 175{
99 struct perf_pmu_alias *alias; 176 struct perf_pmu_alias *alias;
100 char buf[256]; 177 char buf[256];
@@ -110,6 +187,9 @@ static int perf_pmu__new_alias(struct list_head *list, char *name, FILE *file)
110 return -ENOMEM; 187 return -ENOMEM;
111 188
112 INIT_LIST_HEAD(&alias->terms); 189 INIT_LIST_HEAD(&alias->terms);
190 alias->scale = 1.0;
191 alias->unit[0] = '\0';
192
113 ret = parse_events_terms(&alias->terms, buf); 193 ret = parse_events_terms(&alias->terms, buf);
114 if (ret) { 194 if (ret) {
115 free(alias); 195 free(alias);
@@ -117,7 +197,14 @@ static int perf_pmu__new_alias(struct list_head *list, char *name, FILE *file)
117 } 197 }
118 198
119 alias->name = strdup(name); 199 alias->name = strdup(name);
200 /*
201 * load unit name and scale if available
202 */
203 perf_pmu__parse_unit(alias, dir, name);
204 perf_pmu__parse_scale(alias, dir, name);
205
120 list_add_tail(&alias->list, list); 206 list_add_tail(&alias->list, list);
207
121 return 0; 208 return 0;
122} 209}
123 210
@@ -129,6 +216,7 @@ static int pmu_aliases_parse(char *dir, struct list_head *head)
129{ 216{
130 struct dirent *evt_ent; 217 struct dirent *evt_ent;
131 DIR *event_dir; 218 DIR *event_dir;
219 size_t len;
132 int ret = 0; 220 int ret = 0;
133 221
134 event_dir = opendir(dir); 222 event_dir = opendir(dir);
@@ -143,13 +231,24 @@ static int pmu_aliases_parse(char *dir, struct list_head *head)
143 if (!strcmp(name, ".") || !strcmp(name, "..")) 231 if (!strcmp(name, ".") || !strcmp(name, ".."))
144 continue; 232 continue;
145 233
234 /*
235 * skip .unit and .scale info files
236 * parsed in perf_pmu__new_alias()
237 */
238 len = strlen(name);
239 if (len > 5 && !strcmp(name + len - 5, ".unit"))
240 continue;
241 if (len > 6 && !strcmp(name + len - 6, ".scale"))
242 continue;
243
146 snprintf(path, PATH_MAX, "%s/%s", dir, name); 244 snprintf(path, PATH_MAX, "%s/%s", dir, name);
147 245
148 ret = -EINVAL; 246 ret = -EINVAL;
149 file = fopen(path, "r"); 247 file = fopen(path, "r");
150 if (!file) 248 if (!file)
151 break; 249 break;
152 ret = perf_pmu__new_alias(head, name, file); 250
251 ret = perf_pmu__new_alias(head, dir, name, file);
153 fclose(file); 252 fclose(file);
154 } 253 }
155 254
@@ -406,7 +505,7 @@ static __u64 pmu_format_value(unsigned long *format, __u64 value)
406 505
407/* 506/*
408 * Setup one of config[12] attr members based on the 507 * Setup one of config[12] attr members based on the
409 * user input data - temr parameter. 508 * user input data - term parameter.
410 */ 509 */
411static int pmu_config_term(struct list_head *formats, 510static int pmu_config_term(struct list_head *formats,
412 struct perf_event_attr *attr, 511 struct perf_event_attr *attr,
@@ -508,16 +607,46 @@ static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,
508 return NULL; 607 return NULL;
509} 608}
510 609
610
611static int check_unit_scale(struct perf_pmu_alias *alias,
612 const char **unit, double *scale)
613{
614 /*
615 * Only one term in event definition can
616 * define unit and scale, fail if there's
617 * more than one.
618 */
619 if ((*unit && alias->unit) ||
620 (*scale && alias->scale))
621 return -EINVAL;
622
623 if (alias->unit)
624 *unit = alias->unit;
625
626 if (alias->scale)
627 *scale = alias->scale;
628
629 return 0;
630}
631
511/* 632/*
512 * Find alias in the terms list and replace it with the terms 633 * Find alias in the terms list and replace it with the terms
513 * defined for the alias 634 * defined for the alias
514 */ 635 */
515int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms) 636int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
637 const char **unit, double *scale)
516{ 638{
517 struct parse_events_term *term, *h; 639 struct parse_events_term *term, *h;
518 struct perf_pmu_alias *alias; 640 struct perf_pmu_alias *alias;
519 int ret; 641 int ret;
520 642
643 /*
644 * Mark unit and scale as not set
645 * (different from default values, see below)
646 */
647 *unit = NULL;
648 *scale = 0.0;
649
521 list_for_each_entry_safe(term, h, head_terms, list) { 650 list_for_each_entry_safe(term, h, head_terms, list) {
522 alias = pmu_find_alias(pmu, term); 651 alias = pmu_find_alias(pmu, term);
523 if (!alias) 652 if (!alias)
@@ -525,9 +654,26 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms)
525 ret = pmu_alias_terms(alias, &term->list); 654 ret = pmu_alias_terms(alias, &term->list);
526 if (ret) 655 if (ret)
527 return ret; 656 return ret;
657
658 ret = check_unit_scale(alias, unit, scale);
659 if (ret)
660 return ret;
661
528 list_del(&term->list); 662 list_del(&term->list);
529 free(term); 663 free(term);
530 } 664 }
665
666 /*
667 * if no unit or scale foundin aliases, then
668 * set defaults as for evsel
669 * unit cannot left to NULL
670 */
671 if (*unit == NULL)
672 *unit = "";
673
674 if (*scale == 0.0)
675 *scale = 1.0;
676
531 return 0; 677 return 0;
532} 678}
533 679
@@ -625,7 +771,7 @@ void print_pmu_events(const char *event_glob, bool name_only)
625 continue; 771 continue;
626 } 772 }
627 printf(" %-50s [Kernel PMU event]\n", aliases[j]); 773 printf(" %-50s [Kernel PMU event]\n", aliases[j]);
628 free(aliases[j]); 774 zfree(&aliases[j]);
629 printed++; 775 printed++;
630 } 776 }
631 if (printed) 777 if (printed)
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index 1179b26f244a..8b64125a9281 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -28,7 +28,8 @@ int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
28int perf_pmu__config_terms(struct list_head *formats, 28int perf_pmu__config_terms(struct list_head *formats,
29 struct perf_event_attr *attr, 29 struct perf_event_attr *attr,
30 struct list_head *head_terms); 30 struct list_head *head_terms);
31int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms); 31int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
32 const char **unit, double *scale);
32struct list_head *perf_pmu__alias(struct perf_pmu *pmu, 33struct list_head *perf_pmu__alias(struct perf_pmu *pmu,
33 struct list_head *head_terms); 34 struct list_head *head_terms);
34int perf_pmu_wrap(void); 35int perf_pmu_wrap(void);
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 9c6989ca2bea..a8a9b6cd93a8 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -40,7 +40,7 @@
40#include "color.h" 40#include "color.h"
41#include "symbol.h" 41#include "symbol.h"
42#include "thread.h" 42#include "thread.h"
43#include <lk/debugfs.h> 43#include <api/fs/debugfs.h>
44#include "trace-event.h" /* For __maybe_unused */ 44#include "trace-event.h" /* For __maybe_unused */
45#include "probe-event.h" 45#include "probe-event.h"
46#include "probe-finder.h" 46#include "probe-finder.h"
@@ -72,6 +72,7 @@ static int e_snprintf(char *str, size_t size, const char *format, ...)
72static char *synthesize_perf_probe_point(struct perf_probe_point *pp); 72static char *synthesize_perf_probe_point(struct perf_probe_point *pp);
73static int convert_name_to_addr(struct perf_probe_event *pev, 73static int convert_name_to_addr(struct perf_probe_event *pev,
74 const char *exec); 74 const char *exec);
75static void clear_probe_trace_event(struct probe_trace_event *tev);
75static struct machine machine; 76static struct machine machine;
76 77
77/* Initialize symbol maps and path of vmlinux/modules */ 78/* Initialize symbol maps and path of vmlinux/modules */
@@ -154,7 +155,7 @@ static struct dso *kernel_get_module_dso(const char *module)
154 155
155 vmlinux_name = symbol_conf.vmlinux_name; 156 vmlinux_name = symbol_conf.vmlinux_name;
156 if (vmlinux_name) { 157 if (vmlinux_name) {
157 if (dso__load_vmlinux(dso, map, vmlinux_name, NULL) <= 0) 158 if (dso__load_vmlinux(dso, map, vmlinux_name, false, NULL) <= 0)
158 return NULL; 159 return NULL;
159 } else { 160 } else {
160 if (dso__load_vmlinux_path(dso, map, NULL) <= 0) { 161 if (dso__load_vmlinux_path(dso, map, NULL) <= 0) {
@@ -186,6 +187,37 @@ static int init_user_exec(void)
186 return ret; 187 return ret;
187} 188}
188 189
190static int convert_exec_to_group(const char *exec, char **result)
191{
192 char *ptr1, *ptr2, *exec_copy;
193 char buf[64];
194 int ret;
195
196 exec_copy = strdup(exec);
197 if (!exec_copy)
198 return -ENOMEM;
199
200 ptr1 = basename(exec_copy);
201 if (!ptr1) {
202 ret = -EINVAL;
203 goto out;
204 }
205
206 ptr2 = strpbrk(ptr1, "-._");
207 if (ptr2)
208 *ptr2 = '\0';
209 ret = e_snprintf(buf, 64, "%s_%s", PERFPROBE_GROUP, ptr1);
210 if (ret < 0)
211 goto out;
212
213 *result = strdup(buf);
214 ret = *result ? 0 : -ENOMEM;
215
216out:
217 free(exec_copy);
218 return ret;
219}
220
189static int convert_to_perf_probe_point(struct probe_trace_point *tp, 221static int convert_to_perf_probe_point(struct probe_trace_point *tp,
190 struct perf_probe_point *pp) 222 struct perf_probe_point *pp)
191{ 223{
@@ -261,6 +293,68 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
261 return 0; 293 return 0;
262} 294}
263 295
296static int get_text_start_address(const char *exec, unsigned long *address)
297{
298 Elf *elf;
299 GElf_Ehdr ehdr;
300 GElf_Shdr shdr;
301 int fd, ret = -ENOENT;
302
303 fd = open(exec, O_RDONLY);
304 if (fd < 0)
305 return -errno;
306
307 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
308 if (elf == NULL)
309 return -EINVAL;
310
311 if (gelf_getehdr(elf, &ehdr) == NULL)
312 goto out;
313
314 if (!elf_section_by_name(elf, &ehdr, &shdr, ".text", NULL))
315 goto out;
316
317 *address = shdr.sh_addr - shdr.sh_offset;
318 ret = 0;
319out:
320 elf_end(elf);
321 return ret;
322}
323
324static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs,
325 int ntevs, const char *exec)
326{
327 int i, ret = 0;
328 unsigned long offset, stext = 0;
329 char buf[32];
330
331 if (!exec)
332 return 0;
333
334 ret = get_text_start_address(exec, &stext);
335 if (ret < 0)
336 return ret;
337
338 for (i = 0; i < ntevs && ret >= 0; i++) {
339 offset = tevs[i].point.address - stext;
340 offset += tevs[i].point.offset;
341 tevs[i].point.offset = 0;
342 zfree(&tevs[i].point.symbol);
343 ret = e_snprintf(buf, 32, "0x%lx", offset);
344 if (ret < 0)
345 break;
346 tevs[i].point.module = strdup(exec);
347 tevs[i].point.symbol = strdup(buf);
348 if (!tevs[i].point.symbol || !tevs[i].point.module) {
349 ret = -ENOMEM;
350 break;
351 }
352 tevs[i].uprobes = true;
353 }
354
355 return ret;
356}
357
264static int add_module_to_probe_trace_events(struct probe_trace_event *tevs, 358static int add_module_to_probe_trace_events(struct probe_trace_event *tevs,
265 int ntevs, const char *module) 359 int ntevs, const char *module)
266{ 360{
@@ -290,12 +384,18 @@ static int add_module_to_probe_trace_events(struct probe_trace_event *tevs,
290 } 384 }
291 } 385 }
292 386
293 if (tmp) 387 free(tmp);
294 free(tmp);
295
296 return ret; 388 return ret;
297} 389}
298 390
391static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs)
392{
393 int i;
394
395 for (i = 0; i < ntevs; i++)
396 clear_probe_trace_event(tevs + i);
397}
398
299/* Try to find perf_probe_event with debuginfo */ 399/* Try to find perf_probe_event with debuginfo */
300static int try_to_find_probe_trace_events(struct perf_probe_event *pev, 400static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
301 struct probe_trace_event **tevs, 401 struct probe_trace_event **tevs,
@@ -305,15 +405,6 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
305 struct debuginfo *dinfo; 405 struct debuginfo *dinfo;
306 int ntevs, ret = 0; 406 int ntevs, ret = 0;
307 407
308 if (pev->uprobes) {
309 if (need_dwarf) {
310 pr_warning("Debuginfo-analysis is not yet supported"
311 " with -x/--exec option.\n");
312 return -ENOSYS;
313 }
314 return convert_name_to_addr(pev, target);
315 }
316
317 dinfo = open_debuginfo(target); 408 dinfo = open_debuginfo(target);
318 409
319 if (!dinfo) { 410 if (!dinfo) {
@@ -332,9 +423,18 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
332 423
333 if (ntevs > 0) { /* Succeeded to find trace events */ 424 if (ntevs > 0) { /* Succeeded to find trace events */
334 pr_debug("find %d probe_trace_events.\n", ntevs); 425 pr_debug("find %d probe_trace_events.\n", ntevs);
335 if (target) 426 if (target) {
336 ret = add_module_to_probe_trace_events(*tevs, ntevs, 427 if (pev->uprobes)
337 target); 428 ret = add_exec_to_probe_trace_events(*tevs,
429 ntevs, target);
430 else
431 ret = add_module_to_probe_trace_events(*tevs,
432 ntevs, target);
433 }
434 if (ret < 0) {
435 clear_probe_trace_events(*tevs, ntevs);
436 zfree(tevs);
437 }
338 return ret < 0 ? ret : ntevs; 438 return ret < 0 ? ret : ntevs;
339 } 439 }
340 440
@@ -401,15 +501,13 @@ static int get_real_path(const char *raw_path, const char *comp_dir,
401 case EFAULT: 501 case EFAULT:
402 raw_path = strchr(++raw_path, '/'); 502 raw_path = strchr(++raw_path, '/');
403 if (!raw_path) { 503 if (!raw_path) {
404 free(*new_path); 504 zfree(new_path);
405 *new_path = NULL;
406 return -ENOENT; 505 return -ENOENT;
407 } 506 }
408 continue; 507 continue;
409 508
410 default: 509 default:
411 free(*new_path); 510 zfree(new_path);
412 *new_path = NULL;
413 return -errno; 511 return -errno;
414 } 512 }
415 } 513 }
@@ -580,7 +678,7 @@ static int show_available_vars_at(struct debuginfo *dinfo,
580 */ 678 */
581 fprintf(stdout, "\t@<%s+%lu>\n", vl->point.symbol, 679 fprintf(stdout, "\t@<%s+%lu>\n", vl->point.symbol,
582 vl->point.offset); 680 vl->point.offset);
583 free(vl->point.symbol); 681 zfree(&vl->point.symbol);
584 nvars = 0; 682 nvars = 0;
585 if (vl->vars) { 683 if (vl->vars) {
586 strlist__for_each(node, vl->vars) { 684 strlist__for_each(node, vl->vars) {
@@ -647,16 +745,14 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
647 745
648static int try_to_find_probe_trace_events(struct perf_probe_event *pev, 746static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
649 struct probe_trace_event **tevs __maybe_unused, 747 struct probe_trace_event **tevs __maybe_unused,
650 int max_tevs __maybe_unused, const char *target) 748 int max_tevs __maybe_unused,
749 const char *target __maybe_unused)
651{ 750{
652 if (perf_probe_event_need_dwarf(pev)) { 751 if (perf_probe_event_need_dwarf(pev)) {
653 pr_warning("Debuginfo-analysis is not supported.\n"); 752 pr_warning("Debuginfo-analysis is not supported.\n");
654 return -ENOSYS; 753 return -ENOSYS;
655 } 754 }
656 755
657 if (pev->uprobes)
658 return convert_name_to_addr(pev, target);
659
660 return 0; 756 return 0;
661} 757}
662 758
@@ -678,6 +774,28 @@ int show_available_vars(struct perf_probe_event *pevs __maybe_unused,
678} 774}
679#endif 775#endif
680 776
777void line_range__clear(struct line_range *lr)
778{
779 struct line_node *ln;
780
781 free(lr->function);
782 free(lr->file);
783 free(lr->path);
784 free(lr->comp_dir);
785 while (!list_empty(&lr->line_list)) {
786 ln = list_first_entry(&lr->line_list, struct line_node, list);
787 list_del(&ln->list);
788 free(ln);
789 }
790 memset(lr, 0, sizeof(*lr));
791}
792
793void line_range__init(struct line_range *lr)
794{
795 memset(lr, 0, sizeof(*lr));
796 INIT_LIST_HEAD(&lr->line_list);
797}
798
681static int parse_line_num(char **ptr, int *val, const char *what) 799static int parse_line_num(char **ptr, int *val, const char *what)
682{ 800{
683 const char *start = *ptr; 801 const char *start = *ptr;
@@ -1278,8 +1396,7 @@ static char *synthesize_perf_probe_point(struct perf_probe_point *pp)
1278error: 1396error:
1279 pr_debug("Failed to synthesize perf probe point: %s\n", 1397 pr_debug("Failed to synthesize perf probe point: %s\n",
1280 strerror(-ret)); 1398 strerror(-ret));
1281 if (buf) 1399 free(buf);
1282 free(buf);
1283 return NULL; 1400 return NULL;
1284} 1401}
1285 1402
@@ -1480,34 +1597,25 @@ void clear_perf_probe_event(struct perf_probe_event *pev)
1480 struct perf_probe_arg_field *field, *next; 1597 struct perf_probe_arg_field *field, *next;
1481 int i; 1598 int i;
1482 1599
1483 if (pev->event) 1600 free(pev->event);
1484 free(pev->event); 1601 free(pev->group);
1485 if (pev->group) 1602 free(pp->file);
1486 free(pev->group); 1603 free(pp->function);
1487 if (pp->file) 1604 free(pp->lazy_line);
1488 free(pp->file); 1605
1489 if (pp->function)
1490 free(pp->function);
1491 if (pp->lazy_line)
1492 free(pp->lazy_line);
1493 for (i = 0; i < pev->nargs; i++) { 1606 for (i = 0; i < pev->nargs; i++) {
1494 if (pev->args[i].name) 1607 free(pev->args[i].name);
1495 free(pev->args[i].name); 1608 free(pev->args[i].var);
1496 if (pev->args[i].var) 1609 free(pev->args[i].type);
1497 free(pev->args[i].var);
1498 if (pev->args[i].type)
1499 free(pev->args[i].type);
1500 field = pev->args[i].field; 1610 field = pev->args[i].field;
1501 while (field) { 1611 while (field) {
1502 next = field->next; 1612 next = field->next;
1503 if (field->name) 1613 zfree(&field->name);
1504 free(field->name);
1505 free(field); 1614 free(field);
1506 field = next; 1615 field = next;
1507 } 1616 }
1508 } 1617 }
1509 if (pev->args) 1618 free(pev->args);
1510 free(pev->args);
1511 memset(pev, 0, sizeof(*pev)); 1619 memset(pev, 0, sizeof(*pev));
1512} 1620}
1513 1621
@@ -1516,21 +1624,14 @@ static void clear_probe_trace_event(struct probe_trace_event *tev)
1516 struct probe_trace_arg_ref *ref, *next; 1624 struct probe_trace_arg_ref *ref, *next;
1517 int i; 1625 int i;
1518 1626
1519 if (tev->event) 1627 free(tev->event);
1520 free(tev->event); 1628 free(tev->group);
1521 if (tev->group) 1629 free(tev->point.symbol);
1522 free(tev->group); 1630 free(tev->point.module);
1523 if (tev->point.symbol)
1524 free(tev->point.symbol);
1525 if (tev->point.module)
1526 free(tev->point.module);
1527 for (i = 0; i < tev->nargs; i++) { 1631 for (i = 0; i < tev->nargs; i++) {
1528 if (tev->args[i].name) 1632 free(tev->args[i].name);
1529 free(tev->args[i].name); 1633 free(tev->args[i].value);
1530 if (tev->args[i].value) 1634 free(tev->args[i].type);
1531 free(tev->args[i].value);
1532 if (tev->args[i].type)
1533 free(tev->args[i].type);
1534 ref = tev->args[i].ref; 1635 ref = tev->args[i].ref;
1535 while (ref) { 1636 while (ref) {
1536 next = ref->next; 1637 next = ref->next;
@@ -1538,8 +1639,7 @@ static void clear_probe_trace_event(struct probe_trace_event *tev)
1538 ref = next; 1639 ref = next;
1539 } 1640 }
1540 } 1641 }
1541 if (tev->args) 1642 free(tev->args);
1542 free(tev->args);
1543 memset(tev, 0, sizeof(*tev)); 1643 memset(tev, 0, sizeof(*tev));
1544} 1644}
1545 1645
@@ -1913,14 +2013,29 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
1913 int max_tevs, const char *target) 2013 int max_tevs, const char *target)
1914{ 2014{
1915 struct symbol *sym; 2015 struct symbol *sym;
1916 int ret = 0, i; 2016 int ret, i;
1917 struct probe_trace_event *tev; 2017 struct probe_trace_event *tev;
1918 2018
2019 if (pev->uprobes && !pev->group) {
2020 /* Replace group name if not given */
2021 ret = convert_exec_to_group(target, &pev->group);
2022 if (ret != 0) {
2023 pr_warning("Failed to make a group name.\n");
2024 return ret;
2025 }
2026 }
2027
1919 /* Convert perf_probe_event with debuginfo */ 2028 /* Convert perf_probe_event with debuginfo */
1920 ret = try_to_find_probe_trace_events(pev, tevs, max_tevs, target); 2029 ret = try_to_find_probe_trace_events(pev, tevs, max_tevs, target);
1921 if (ret != 0) 2030 if (ret != 0)
1922 return ret; /* Found in debuginfo or got an error */ 2031 return ret; /* Found in debuginfo or got an error */
1923 2032
2033 if (pev->uprobes) {
2034 ret = convert_name_to_addr(pev, target);
2035 if (ret < 0)
2036 return ret;
2037 }
2038
1924 /* Allocate trace event buffer */ 2039 /* Allocate trace event buffer */
1925 tev = *tevs = zalloc(sizeof(struct probe_trace_event)); 2040 tev = *tevs = zalloc(sizeof(struct probe_trace_event));
1926 if (tev == NULL) 2041 if (tev == NULL)
@@ -2056,7 +2171,7 @@ end:
2056 for (i = 0; i < npevs; i++) { 2171 for (i = 0; i < npevs; i++) {
2057 for (j = 0; j < pkgs[i].ntevs; j++) 2172 for (j = 0; j < pkgs[i].ntevs; j++)
2058 clear_probe_trace_event(&pkgs[i].tevs[j]); 2173 clear_probe_trace_event(&pkgs[i].tevs[j]);
2059 free(pkgs[i].tevs); 2174 zfree(&pkgs[i].tevs);
2060 } 2175 }
2061 free(pkgs); 2176 free(pkgs);
2062 2177
@@ -2281,7 +2396,7 @@ static int convert_name_to_addr(struct perf_probe_event *pev, const char *exec)
2281 struct perf_probe_point *pp = &pev->point; 2396 struct perf_probe_point *pp = &pev->point;
2282 struct symbol *sym; 2397 struct symbol *sym;
2283 struct map *map = NULL; 2398 struct map *map = NULL;
2284 char *function = NULL, *name = NULL; 2399 char *function = NULL;
2285 int ret = -EINVAL; 2400 int ret = -EINVAL;
2286 unsigned long long vaddr = 0; 2401 unsigned long long vaddr = 0;
2287 2402
@@ -2297,12 +2412,7 @@ static int convert_name_to_addr(struct perf_probe_event *pev, const char *exec)
2297 goto out; 2412 goto out;
2298 } 2413 }
2299 2414
2300 name = realpath(exec, NULL); 2415 map = dso__new_map(exec);
2301 if (!name) {
2302 pr_warning("Cannot find realpath for %s.\n", exec);
2303 goto out;
2304 }
2305 map = dso__new_map(name);
2306 if (!map) { 2416 if (!map) {
2307 pr_warning("Cannot find appropriate DSO for %s.\n", exec); 2417 pr_warning("Cannot find appropriate DSO for %s.\n", exec);
2308 goto out; 2418 goto out;
@@ -2367,7 +2477,5 @@ out:
2367 } 2477 }
2368 if (function) 2478 if (function)
2369 free(function); 2479 free(function);
2370 if (name)
2371 free(name);
2372 return ret; 2480 return ret;
2373} 2481}
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index f9f3de8b4220..fcaf7273e85a 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -12,6 +12,7 @@ struct probe_trace_point {
12 char *symbol; /* Base symbol */ 12 char *symbol; /* Base symbol */
13 char *module; /* Module name */ 13 char *module; /* Module name */
14 unsigned long offset; /* Offset from symbol */ 14 unsigned long offset; /* Offset from symbol */
15 unsigned long address; /* Actual address of the trace point */
15 bool retprobe; /* Return probe flag */ 16 bool retprobe; /* Return probe flag */
16}; 17};
17 18
@@ -119,6 +120,12 @@ extern void clear_perf_probe_event(struct perf_probe_event *pev);
119/* Command string to line-range */ 120/* Command string to line-range */
120extern int parse_line_range_desc(const char *cmd, struct line_range *lr); 121extern int parse_line_range_desc(const char *cmd, struct line_range *lr);
121 122
123/* Release line range members */
124extern void line_range__clear(struct line_range *lr);
125
126/* Initialize line range */
127extern void line_range__init(struct line_range *lr);
128
122/* Internal use: Return kernel/module path */ 129/* Internal use: Return kernel/module path */
123extern const char *kernel_get_module_path(const char *module); 130extern const char *kernel_get_module_path(const char *module);
124 131
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index ffb657ffd327..061edb162b5b 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -226,10 +226,8 @@ struct debuginfo *debuginfo__new(const char *path)
226 if (!dbg) 226 if (!dbg)
227 return NULL; 227 return NULL;
228 228
229 if (debuginfo__init_offline_dwarf(dbg, path) < 0) { 229 if (debuginfo__init_offline_dwarf(dbg, path) < 0)
230 free(dbg); 230 zfree(&dbg);
231 dbg = NULL;
232 }
233 231
234 return dbg; 232 return dbg;
235} 233}
@@ -241,10 +239,8 @@ struct debuginfo *debuginfo__new_online_kernel(unsigned long addr)
241 if (!dbg) 239 if (!dbg)
242 return NULL; 240 return NULL;
243 241
244 if (debuginfo__init_online_kernel_dwarf(dbg, (Dwarf_Addr)addr) < 0) { 242 if (debuginfo__init_online_kernel_dwarf(dbg, (Dwarf_Addr)addr) < 0)
245 free(dbg); 243 zfree(&dbg);
246 dbg = NULL;
247 }
248 244
249 return dbg; 245 return dbg;
250} 246}
@@ -729,6 +725,7 @@ static int convert_to_trace_point(Dwarf_Die *sp_die, Dwfl_Module *mod,
729 return -ENOENT; 725 return -ENOENT;
730 } 726 }
731 tp->offset = (unsigned long)(paddr - sym.st_value); 727 tp->offset = (unsigned long)(paddr - sym.st_value);
728 tp->address = (unsigned long)paddr;
732 tp->symbol = strdup(symbol); 729 tp->symbol = strdup(symbol);
733 if (!tp->symbol) 730 if (!tp->symbol)
734 return -ENOMEM; 731 return -ENOMEM;
@@ -1301,8 +1298,7 @@ int debuginfo__find_trace_events(struct debuginfo *dbg,
1301 1298
1302 ret = debuginfo__find_probes(dbg, &tf.pf); 1299 ret = debuginfo__find_probes(dbg, &tf.pf);
1303 if (ret < 0) { 1300 if (ret < 0) {
1304 free(*tevs); 1301 zfree(tevs);
1305 *tevs = NULL;
1306 return ret; 1302 return ret;
1307 } 1303 }
1308 1304
@@ -1413,13 +1409,10 @@ int debuginfo__find_available_vars_at(struct debuginfo *dbg,
1413 if (ret < 0) { 1409 if (ret < 0) {
1414 /* Free vlist for error */ 1410 /* Free vlist for error */
1415 while (af.nvls--) { 1411 while (af.nvls--) {
1416 if (af.vls[af.nvls].point.symbol) 1412 zfree(&af.vls[af.nvls].point.symbol);
1417 free(af.vls[af.nvls].point.symbol); 1413 strlist__delete(af.vls[af.nvls].vars);
1418 if (af.vls[af.nvls].vars)
1419 strlist__delete(af.vls[af.nvls].vars);
1420 } 1414 }
1421 free(af.vls); 1415 zfree(vls);
1422 *vls = NULL;
1423 return ret; 1416 return ret;
1424 } 1417 }
1425 1418
@@ -1523,10 +1516,7 @@ post:
1523 if (fname) { 1516 if (fname) {
1524 ppt->file = strdup(fname); 1517 ppt->file = strdup(fname);
1525 if (ppt->file == NULL) { 1518 if (ppt->file == NULL) {
1526 if (ppt->function) { 1519 zfree(&ppt->function);
1527 free(ppt->function);
1528 ppt->function = NULL;
1529 }
1530 ret = -ENOMEM; 1520 ret = -ENOMEM;
1531 goto end; 1521 goto end;
1532 } 1522 }
@@ -1580,8 +1570,7 @@ static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf)
1580 else 1570 else
1581 ret = 0; /* Lines are not found */ 1571 ret = 0; /* Lines are not found */
1582 else { 1572 else {
1583 free(lf->lr->path); 1573 zfree(&lf->lr->path);
1584 lf->lr->path = NULL;
1585 } 1574 }
1586 return ret; 1575 return ret;
1587} 1576}
diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources
index 239036fb2b2c..595bfc73d2ed 100644
--- a/tools/perf/util/python-ext-sources
+++ b/tools/perf/util/python-ext-sources
@@ -18,4 +18,5 @@ util/cgroup.c
18util/rblist.c 18util/rblist.c
19util/strlist.c 19util/strlist.c
20util/fs.c 20util/fs.c
21util/trace-event.c
21../../lib/rbtree.c 22../../lib/rbtree.c
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 4bf8ace7f511..122669c18ff4 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -908,9 +908,10 @@ static PyObject *pyrf_evlist__item(PyObject *obj, Py_ssize_t i)
908 if (i >= pevlist->evlist.nr_entries) 908 if (i >= pevlist->evlist.nr_entries)
909 return NULL; 909 return NULL;
910 910
911 list_for_each_entry(pos, &pevlist->evlist.entries, node) 911 evlist__for_each(&pevlist->evlist, pos) {
912 if (i-- == 0) 912 if (i-- == 0)
913 break; 913 break;
914 }
914 915
915 return Py_BuildValue("O", container_of(pos, struct pyrf_evsel, evsel)); 916 return Py_BuildValue("O", container_of(pos, struct pyrf_evsel, evsel));
916} 917}
diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c
index c8845b107f60..373762501dad 100644
--- a/tools/perf/util/record.c
+++ b/tools/perf/util/record.c
@@ -74,8 +74,7 @@ bool perf_can_sample_identifier(void)
74 return perf_probe_api(perf_probe_sample_identifier); 74 return perf_probe_api(perf_probe_sample_identifier);
75} 75}
76 76
77void perf_evlist__config(struct perf_evlist *evlist, 77void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts)
78 struct perf_record_opts *opts)
79{ 78{
80 struct perf_evsel *evsel; 79 struct perf_evsel *evsel;
81 bool use_sample_identifier = false; 80 bool use_sample_identifier = false;
@@ -90,19 +89,19 @@ void perf_evlist__config(struct perf_evlist *evlist,
90 if (evlist->cpus->map[0] < 0) 89 if (evlist->cpus->map[0] < 0)
91 opts->no_inherit = true; 90 opts->no_inherit = true;
92 91
93 list_for_each_entry(evsel, &evlist->entries, node) 92 evlist__for_each(evlist, evsel)
94 perf_evsel__config(evsel, opts); 93 perf_evsel__config(evsel, opts);
95 94
96 if (evlist->nr_entries > 1) { 95 if (evlist->nr_entries > 1) {
97 struct perf_evsel *first = perf_evlist__first(evlist); 96 struct perf_evsel *first = perf_evlist__first(evlist);
98 97
99 list_for_each_entry(evsel, &evlist->entries, node) { 98 evlist__for_each(evlist, evsel) {
100 if (evsel->attr.sample_type == first->attr.sample_type) 99 if (evsel->attr.sample_type == first->attr.sample_type)
101 continue; 100 continue;
102 use_sample_identifier = perf_can_sample_identifier(); 101 use_sample_identifier = perf_can_sample_identifier();
103 break; 102 break;
104 } 103 }
105 list_for_each_entry(evsel, &evlist->entries, node) 104 evlist__for_each(evlist, evsel)
106 perf_evsel__set_sample_id(evsel, use_sample_identifier); 105 perf_evsel__set_sample_id(evsel, use_sample_identifier);
107 } 106 }
108 107
@@ -123,7 +122,7 @@ static int get_max_rate(unsigned int *rate)
123 return filename__read_int(path, (int *) rate); 122 return filename__read_int(path, (int *) rate);
124} 123}
125 124
126static int perf_record_opts__config_freq(struct perf_record_opts *opts) 125static int record_opts__config_freq(struct record_opts *opts)
127{ 126{
128 bool user_freq = opts->user_freq != UINT_MAX; 127 bool user_freq = opts->user_freq != UINT_MAX;
129 unsigned int max_rate; 128 unsigned int max_rate;
@@ -173,7 +172,44 @@ static int perf_record_opts__config_freq(struct perf_record_opts *opts)
173 return 0; 172 return 0;
174} 173}
175 174
176int perf_record_opts__config(struct perf_record_opts *opts) 175int record_opts__config(struct record_opts *opts)
177{ 176{
178 return perf_record_opts__config_freq(opts); 177 return record_opts__config_freq(opts);
178}
179
180bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str)
181{
182 struct perf_evlist *temp_evlist;
183 struct perf_evsel *evsel;
184 int err, fd, cpu;
185 bool ret = false;
186
187 temp_evlist = perf_evlist__new();
188 if (!temp_evlist)
189 return false;
190
191 err = parse_events(temp_evlist, str);
192 if (err)
193 goto out_delete;
194
195 evsel = perf_evlist__last(temp_evlist);
196
197 if (!evlist || cpu_map__empty(evlist->cpus)) {
198 struct cpu_map *cpus = cpu_map__new(NULL);
199
200 cpu = cpus ? cpus->map[0] : 0;
201 cpu_map__delete(cpus);
202 } else {
203 cpu = evlist->cpus->map[0];
204 }
205
206 fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1, 0);
207 if (fd >= 0) {
208 close(fd);
209 ret = true;
210 }
211
212out_delete:
213 perf_evlist__delete(temp_evlist);
214 return ret;
179} 215}
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index d5e5969f6fea..e108207c5de0 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -194,8 +194,7 @@ static void define_event_symbols(struct event_format *event,
194 zero_flag_atom = 0; 194 zero_flag_atom = 0;
195 break; 195 break;
196 case PRINT_FIELD: 196 case PRINT_FIELD:
197 if (cur_field_name) 197 free(cur_field_name);
198 free(cur_field_name);
199 cur_field_name = strdup(args->field.name); 198 cur_field_name = strdup(args->field.name);
200 break; 199 break;
201 case PRINT_FLAGS: 200 case PRINT_FLAGS:
@@ -257,12 +256,9 @@ static inline struct event_format *find_cache_event(struct perf_evsel *evsel)
257 return event; 256 return event;
258} 257}
259 258
260static void perl_process_tracepoint(union perf_event *perf_event __maybe_unused, 259static void perl_process_tracepoint(struct perf_sample *sample,
261 struct perf_sample *sample,
262 struct perf_evsel *evsel, 260 struct perf_evsel *evsel,
263 struct machine *machine __maybe_unused, 261 struct thread *thread)
264 struct thread *thread,
265 struct addr_location *al)
266{ 262{
267 struct format_field *field; 263 struct format_field *field;
268 static char handler[256]; 264 static char handler[256];
@@ -349,10 +345,7 @@ static void perl_process_tracepoint(union perf_event *perf_event __maybe_unused,
349 345
350static void perl_process_event_generic(union perf_event *event, 346static void perl_process_event_generic(union perf_event *event,
351 struct perf_sample *sample, 347 struct perf_sample *sample,
352 struct perf_evsel *evsel, 348 struct perf_evsel *evsel)
353 struct machine *machine __maybe_unused,
354 struct thread *thread __maybe_unused,
355 struct addr_location *al __maybe_unused)
356{ 349{
357 dSP; 350 dSP;
358 351
@@ -377,12 +370,11 @@ static void perl_process_event_generic(union perf_event *event,
377static void perl_process_event(union perf_event *event, 370static void perl_process_event(union perf_event *event,
378 struct perf_sample *sample, 371 struct perf_sample *sample,
379 struct perf_evsel *evsel, 372 struct perf_evsel *evsel,
380 struct machine *machine,
381 struct thread *thread, 373 struct thread *thread,
382 struct addr_location *al) 374 struct addr_location *al __maybe_unused)
383{ 375{
384 perl_process_tracepoint(event, sample, evsel, machine, thread, al); 376 perl_process_tracepoint(sample, evsel, thread);
385 perl_process_event_generic(event, sample, evsel, machine, thread, al); 377 perl_process_event_generic(event, sample, evsel);
386} 378}
387 379
388static void run_start_sub(void) 380static void run_start_sub(void)
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 53c20e7fd900..cd9774df3750 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -161,8 +161,7 @@ static void define_event_symbols(struct event_format *event,
161 zero_flag_atom = 0; 161 zero_flag_atom = 0;
162 break; 162 break;
163 case PRINT_FIELD: 163 case PRINT_FIELD:
164 if (cur_field_name) 164 free(cur_field_name);
165 free(cur_field_name);
166 cur_field_name = strdup(args->field.name); 165 cur_field_name = strdup(args->field.name);
167 break; 166 break;
168 case PRINT_FLAGS: 167 case PRINT_FLAGS:
@@ -231,13 +230,10 @@ static inline struct event_format *find_cache_event(struct perf_evsel *evsel)
231 return event; 230 return event;
232} 231}
233 232
234static void python_process_tracepoint(union perf_event *perf_event 233static void python_process_tracepoint(struct perf_sample *sample,
235 __maybe_unused, 234 struct perf_evsel *evsel,
236 struct perf_sample *sample, 235 struct thread *thread,
237 struct perf_evsel *evsel, 236 struct addr_location *al)
238 struct machine *machine __maybe_unused,
239 struct thread *thread,
240 struct addr_location *al)
241{ 237{
242 PyObject *handler, *retval, *context, *t, *obj, *dict = NULL; 238 PyObject *handler, *retval, *context, *t, *obj, *dict = NULL;
243 static char handler_name[256]; 239 static char handler_name[256];
@@ -351,11 +347,8 @@ static void python_process_tracepoint(union perf_event *perf_event
351 Py_DECREF(t); 347 Py_DECREF(t);
352} 348}
353 349
354static void python_process_general_event(union perf_event *perf_event 350static void python_process_general_event(struct perf_sample *sample,
355 __maybe_unused,
356 struct perf_sample *sample,
357 struct perf_evsel *evsel, 351 struct perf_evsel *evsel,
358 struct machine *machine __maybe_unused,
359 struct thread *thread, 352 struct thread *thread,
360 struct addr_location *al) 353 struct addr_location *al)
361{ 354{
@@ -411,22 +404,19 @@ exit:
411 Py_DECREF(t); 404 Py_DECREF(t);
412} 405}
413 406
414static void python_process_event(union perf_event *perf_event, 407static void python_process_event(union perf_event *event __maybe_unused,
415 struct perf_sample *sample, 408 struct perf_sample *sample,
416 struct perf_evsel *evsel, 409 struct perf_evsel *evsel,
417 struct machine *machine,
418 struct thread *thread, 410 struct thread *thread,
419 struct addr_location *al) 411 struct addr_location *al)
420{ 412{
421 switch (evsel->attr.type) { 413 switch (evsel->attr.type) {
422 case PERF_TYPE_TRACEPOINT: 414 case PERF_TYPE_TRACEPOINT:
423 python_process_tracepoint(perf_event, sample, evsel, 415 python_process_tracepoint(sample, evsel, thread, al);
424 machine, thread, al);
425 break; 416 break;
426 /* Reserve for future process_hw/sw/raw APIs */ 417 /* Reserve for future process_hw/sw/raw APIs */
427 default: 418 default:
428 python_process_general_event(perf_event, sample, evsel, 419 python_process_general_event(sample, evsel, thread, al);
429 machine, thread, al);
430 } 420 }
431} 421}
432 422
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index f36d24a02445..0b39a48e5110 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -132,18 +132,18 @@ static void perf_session__delete_threads(struct perf_session *session)
132 132
133static void perf_session_env__delete(struct perf_session_env *env) 133static void perf_session_env__delete(struct perf_session_env *env)
134{ 134{
135 free(env->hostname); 135 zfree(&env->hostname);
136 free(env->os_release); 136 zfree(&env->os_release);
137 free(env->version); 137 zfree(&env->version);
138 free(env->arch); 138 zfree(&env->arch);
139 free(env->cpu_desc); 139 zfree(&env->cpu_desc);
140 free(env->cpuid); 140 zfree(&env->cpuid);
141 141
142 free(env->cmdline); 142 zfree(&env->cmdline);
143 free(env->sibling_cores); 143 zfree(&env->sibling_cores);
144 free(env->sibling_threads); 144 zfree(&env->sibling_threads);
145 free(env->numa_nodes); 145 zfree(&env->numa_nodes);
146 free(env->pmu_mappings); 146 zfree(&env->pmu_mappings);
147} 147}
148 148
149void perf_session__delete(struct perf_session *session) 149void perf_session__delete(struct perf_session *session)
@@ -247,27 +247,6 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
247 } 247 }
248} 248}
249 249
250void mem_bswap_32(void *src, int byte_size)
251{
252 u32 *m = src;
253 while (byte_size > 0) {
254 *m = bswap_32(*m);
255 byte_size -= sizeof(u32);
256 ++m;
257 }
258}
259
260void mem_bswap_64(void *src, int byte_size)
261{
262 u64 *m = src;
263
264 while (byte_size > 0) {
265 *m = bswap_64(*m);
266 byte_size -= sizeof(u64);
267 ++m;
268 }
269}
270
271static void swap_sample_id_all(union perf_event *event, void *data) 250static void swap_sample_id_all(union perf_event *event, void *data)
272{ 251{
273 void *end = (void *) event + event->header.size; 252 void *end = (void *) event + event->header.size;
@@ -851,6 +830,7 @@ static struct machine *
851 struct perf_sample *sample) 830 struct perf_sample *sample)
852{ 831{
853 const u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 832 const u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
833 struct machine *machine;
854 834
855 if (perf_guest && 835 if (perf_guest &&
856 ((cpumode == PERF_RECORD_MISC_GUEST_KERNEL) || 836 ((cpumode == PERF_RECORD_MISC_GUEST_KERNEL) ||
@@ -863,7 +843,11 @@ static struct machine *
863 else 843 else
864 pid = sample->pid; 844 pid = sample->pid;
865 845
866 return perf_session__findnew_machine(session, pid); 846 machine = perf_session__find_machine(session, pid);
847 if (!machine)
848 machine = perf_session__findnew_machine(session,
849 DEFAULT_GUEST_KERNEL_ID);
850 return machine;
867 } 851 }
868 852
869 return &session->machines.host; 853 return &session->machines.host;
@@ -1158,7 +1142,7 @@ static int __perf_session__process_pipe_events(struct perf_session *session,
1158 void *buf = NULL; 1142 void *buf = NULL;
1159 int skip = 0; 1143 int skip = 0;
1160 u64 head; 1144 u64 head;
1161 int err; 1145 ssize_t err;
1162 void *p; 1146 void *p;
1163 1147
1164 perf_tool__fill_defaults(tool); 1148 perf_tool__fill_defaults(tool);
@@ -1400,7 +1384,7 @@ bool perf_session__has_traces(struct perf_session *session, const char *msg)
1400{ 1384{
1401 struct perf_evsel *evsel; 1385 struct perf_evsel *evsel;
1402 1386
1403 list_for_each_entry(evsel, &session->evlist->entries, node) { 1387 evlist__for_each(session->evlist, evsel) {
1404 if (evsel->attr.type == PERF_TYPE_TRACEPOINT) 1388 if (evsel->attr.type == PERF_TYPE_TRACEPOINT)
1405 return true; 1389 return true;
1406 } 1390 }
@@ -1458,7 +1442,7 @@ size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp)
1458 1442
1459 ret += events_stats__fprintf(&session->stats, fp); 1443 ret += events_stats__fprintf(&session->stats, fp);
1460 1444
1461 list_for_each_entry(pos, &session->evlist->entries, node) { 1445 evlist__for_each(session->evlist, pos) {
1462 ret += fprintf(fp, "%s stats:\n", perf_evsel__name(pos)); 1446 ret += fprintf(fp, "%s stats:\n", perf_evsel__name(pos));
1463 ret += events_stats__fprintf(&pos->hists.stats, fp); 1447 ret += events_stats__fprintf(&pos->hists.stats, fp);
1464 } 1448 }
@@ -1480,35 +1464,30 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
1480{ 1464{
1481 struct perf_evsel *pos; 1465 struct perf_evsel *pos;
1482 1466
1483 list_for_each_entry(pos, &session->evlist->entries, node) { 1467 evlist__for_each(session->evlist, pos) {
1484 if (pos->attr.type == type) 1468 if (pos->attr.type == type)
1485 return pos; 1469 return pos;
1486 } 1470 }
1487 return NULL; 1471 return NULL;
1488} 1472}
1489 1473
1490void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event, 1474void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample,
1491 struct perf_sample *sample, struct machine *machine, 1475 struct addr_location *al,
1492 unsigned int print_opts, unsigned int stack_depth) 1476 unsigned int print_opts, unsigned int stack_depth)
1493{ 1477{
1494 struct addr_location al;
1495 struct callchain_cursor_node *node; 1478 struct callchain_cursor_node *node;
1496 int print_ip = print_opts & PRINT_IP_OPT_IP; 1479 int print_ip = print_opts & PRINT_IP_OPT_IP;
1497 int print_sym = print_opts & PRINT_IP_OPT_SYM; 1480 int print_sym = print_opts & PRINT_IP_OPT_SYM;
1498 int print_dso = print_opts & PRINT_IP_OPT_DSO; 1481 int print_dso = print_opts & PRINT_IP_OPT_DSO;
1499 int print_symoffset = print_opts & PRINT_IP_OPT_SYMOFFSET; 1482 int print_symoffset = print_opts & PRINT_IP_OPT_SYMOFFSET;
1500 int print_oneline = print_opts & PRINT_IP_OPT_ONELINE; 1483 int print_oneline = print_opts & PRINT_IP_OPT_ONELINE;
1484 int print_srcline = print_opts & PRINT_IP_OPT_SRCLINE;
1501 char s = print_oneline ? ' ' : '\t'; 1485 char s = print_oneline ? ' ' : '\t';
1502 1486
1503 if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) {
1504 error("problem processing %d event, skipping it.\n",
1505 event->header.type);
1506 return;
1507 }
1508
1509 if (symbol_conf.use_callchain && sample->callchain) { 1487 if (symbol_conf.use_callchain && sample->callchain) {
1488 struct addr_location node_al;
1510 1489
1511 if (machine__resolve_callchain(machine, evsel, al.thread, 1490 if (machine__resolve_callchain(al->machine, evsel, al->thread,
1512 sample, NULL, NULL, 1491 sample, NULL, NULL,
1513 PERF_MAX_STACK_DEPTH) != 0) { 1492 PERF_MAX_STACK_DEPTH) != 0) {
1514 if (verbose) 1493 if (verbose)
@@ -1517,20 +1496,31 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event,
1517 } 1496 }
1518 callchain_cursor_commit(&callchain_cursor); 1497 callchain_cursor_commit(&callchain_cursor);
1519 1498
1499 if (print_symoffset)
1500 node_al = *al;
1501
1520 while (stack_depth) { 1502 while (stack_depth) {
1503 u64 addr = 0;
1504
1521 node = callchain_cursor_current(&callchain_cursor); 1505 node = callchain_cursor_current(&callchain_cursor);
1522 if (!node) 1506 if (!node)
1523 break; 1507 break;
1524 1508
1509 if (node->sym && node->sym->ignore)
1510 goto next;
1511
1525 if (print_ip) 1512 if (print_ip)
1526 printf("%c%16" PRIx64, s, node->ip); 1513 printf("%c%16" PRIx64, s, node->ip);
1527 1514
1515 if (node->map)
1516 addr = node->map->map_ip(node->map, node->ip);
1517
1528 if (print_sym) { 1518 if (print_sym) {
1529 printf(" "); 1519 printf(" ");
1530 if (print_symoffset) { 1520 if (print_symoffset) {
1531 al.addr = node->ip; 1521 node_al.addr = addr;
1532 al.map = node->map; 1522 node_al.map = node->map;
1533 symbol__fprintf_symname_offs(node->sym, &al, stdout); 1523 symbol__fprintf_symname_offs(node->sym, &node_al, stdout);
1534 } else 1524 } else
1535 symbol__fprintf_symname(node->sym, stdout); 1525 symbol__fprintf_symname(node->sym, stdout);
1536 } 1526 }
@@ -1541,39 +1531,49 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event,
1541 printf(")"); 1531 printf(")");
1542 } 1532 }
1543 1533
1534 if (print_srcline)
1535 map__fprintf_srcline(node->map, addr, "\n ",
1536 stdout);
1537
1544 if (!print_oneline) 1538 if (!print_oneline)
1545 printf("\n"); 1539 printf("\n");
1546 1540
1547 callchain_cursor_advance(&callchain_cursor);
1548
1549 stack_depth--; 1541 stack_depth--;
1542next:
1543 callchain_cursor_advance(&callchain_cursor);
1550 } 1544 }
1551 1545
1552 } else { 1546 } else {
1547 if (al->sym && al->sym->ignore)
1548 return;
1549
1553 if (print_ip) 1550 if (print_ip)
1554 printf("%16" PRIx64, sample->ip); 1551 printf("%16" PRIx64, sample->ip);
1555 1552
1556 if (print_sym) { 1553 if (print_sym) {
1557 printf(" "); 1554 printf(" ");
1558 if (print_symoffset) 1555 if (print_symoffset)
1559 symbol__fprintf_symname_offs(al.sym, &al, 1556 symbol__fprintf_symname_offs(al->sym, al,
1560 stdout); 1557 stdout);
1561 else 1558 else
1562 symbol__fprintf_symname(al.sym, stdout); 1559 symbol__fprintf_symname(al->sym, stdout);
1563 } 1560 }
1564 1561
1565 if (print_dso) { 1562 if (print_dso) {
1566 printf(" ("); 1563 printf(" (");
1567 map__fprintf_dsoname(al.map, stdout); 1564 map__fprintf_dsoname(al->map, stdout);
1568 printf(")"); 1565 printf(")");
1569 } 1566 }
1567
1568 if (print_srcline)
1569 map__fprintf_srcline(al->map, al->addr, "\n ", stdout);
1570 } 1570 }
1571} 1571}
1572 1572
1573int perf_session__cpu_bitmap(struct perf_session *session, 1573int perf_session__cpu_bitmap(struct perf_session *session,
1574 const char *cpu_list, unsigned long *cpu_bitmap) 1574 const char *cpu_list, unsigned long *cpu_bitmap)
1575{ 1575{
1576 int i; 1576 int i, err = -1;
1577 struct cpu_map *map; 1577 struct cpu_map *map;
1578 1578
1579 for (i = 0; i < PERF_TYPE_MAX; ++i) { 1579 for (i = 0; i < PERF_TYPE_MAX; ++i) {
@@ -1602,13 +1602,17 @@ int perf_session__cpu_bitmap(struct perf_session *session,
1602 if (cpu >= MAX_NR_CPUS) { 1602 if (cpu >= MAX_NR_CPUS) {
1603 pr_err("Requested CPU %d too large. " 1603 pr_err("Requested CPU %d too large. "
1604 "Consider raising MAX_NR_CPUS\n", cpu); 1604 "Consider raising MAX_NR_CPUS\n", cpu);
1605 return -1; 1605 goto out_delete_map;
1606 } 1606 }
1607 1607
1608 set_bit(cpu, cpu_bitmap); 1608 set_bit(cpu, cpu_bitmap);
1609 } 1609 }
1610 1610
1611 return 0; 1611 err = 0;
1612
1613out_delete_map:
1614 cpu_map__delete(map);
1615 return err;
1612} 1616}
1613 1617
1614void perf_session__fprintf_info(struct perf_session *session, FILE *fp, 1618void perf_session__fprintf_info(struct perf_session *session, FILE *fp,
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 50f640958f0f..3140f8ae6148 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -1,6 +1,7 @@
1#ifndef __PERF_SESSION_H 1#ifndef __PERF_SESSION_H
2#define __PERF_SESSION_H 2#define __PERF_SESSION_H
3 3
4#include "trace-event.h"
4#include "hist.h" 5#include "hist.h"
5#include "event.h" 6#include "event.h"
6#include "header.h" 7#include "header.h"
@@ -32,7 +33,7 @@ struct perf_session {
32 struct perf_header header; 33 struct perf_header header;
33 struct machines machines; 34 struct machines machines;
34 struct perf_evlist *evlist; 35 struct perf_evlist *evlist;
35 struct pevent *pevent; 36 struct trace_event tevent;
36 struct events_stats stats; 37 struct events_stats stats;
37 bool repipe; 38 bool repipe;
38 struct ordered_samples ordered_samples; 39 struct ordered_samples ordered_samples;
@@ -44,6 +45,7 @@ struct perf_session {
44#define PRINT_IP_OPT_DSO (1<<2) 45#define PRINT_IP_OPT_DSO (1<<2)
45#define PRINT_IP_OPT_SYMOFFSET (1<<3) 46#define PRINT_IP_OPT_SYMOFFSET (1<<3)
46#define PRINT_IP_OPT_ONELINE (1<<4) 47#define PRINT_IP_OPT_ONELINE (1<<4)
48#define PRINT_IP_OPT_SRCLINE (1<<5)
47 49
48struct perf_tool; 50struct perf_tool;
49 51
@@ -72,8 +74,6 @@ int perf_session__resolve_callchain(struct perf_session *session,
72 74
73bool perf_session__has_traces(struct perf_session *session, const char *msg); 75bool perf_session__has_traces(struct perf_session *session, const char *msg);
74 76
75void mem_bswap_64(void *src, int byte_size);
76void mem_bswap_32(void *src, int byte_size);
77void perf_event__attr_swap(struct perf_event_attr *attr); 77void perf_event__attr_swap(struct perf_event_attr *attr);
78 78
79int perf_session__create_kernel_maps(struct perf_session *session); 79int perf_session__create_kernel_maps(struct perf_session *session);
@@ -105,8 +105,8 @@ size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp);
105struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, 105struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
106 unsigned int type); 106 unsigned int type);
107 107
108void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event, 108void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample,
109 struct perf_sample *sample, struct machine *machine, 109 struct addr_location *al,
110 unsigned int print_opts, unsigned int stack_depth); 110 unsigned int print_opts, unsigned int stack_depth);
111 111
112int perf_session__cpu_bitmap(struct perf_session *session, 112int perf_session__cpu_bitmap(struct perf_session *session,
diff --git a/tools/perf/util/setup.py b/tools/perf/util/setup.py
index 58ea5ca6c255..d0aee4b9dfd4 100644
--- a/tools/perf/util/setup.py
+++ b/tools/perf/util/setup.py
@@ -25,7 +25,7 @@ cflags += ['-fno-strict-aliasing', '-Wno-write-strings', '-Wno-unused-parameter'
25build_lib = getenv('PYTHON_EXTBUILD_LIB') 25build_lib = getenv('PYTHON_EXTBUILD_LIB')
26build_tmp = getenv('PYTHON_EXTBUILD_TMP') 26build_tmp = getenv('PYTHON_EXTBUILD_TMP')
27libtraceevent = getenv('LIBTRACEEVENT') 27libtraceevent = getenv('LIBTRACEEVENT')
28liblk = getenv('LIBLK') 28libapikfs = getenv('LIBAPIKFS')
29 29
30ext_sources = [f.strip() for f in file('util/python-ext-sources') 30ext_sources = [f.strip() for f in file('util/python-ext-sources')
31 if len(f.strip()) > 0 and f[0] != '#'] 31 if len(f.strip()) > 0 and f[0] != '#']
@@ -34,7 +34,7 @@ perf = Extension('perf',
34 sources = ext_sources, 34 sources = ext_sources,
35 include_dirs = ['util/include'], 35 include_dirs = ['util/include'],
36 extra_compile_args = cflags, 36 extra_compile_args = cflags,
37 extra_objects = [libtraceevent, liblk], 37 extra_objects = [libtraceevent, libapikfs],
38 ) 38 )
39 39
40setup(name='perf', 40setup(name='perf',
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 8b0bb1f4494a..635cd8f8b22e 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -13,6 +13,7 @@ int have_ignore_callees = 0;
13int sort__need_collapse = 0; 13int sort__need_collapse = 0;
14int sort__has_parent = 0; 14int sort__has_parent = 0;
15int sort__has_sym = 0; 15int sort__has_sym = 0;
16int sort__has_dso = 0;
16enum sort_mode sort__mode = SORT_MODE__NORMAL; 17enum sort_mode sort__mode = SORT_MODE__NORMAL;
17 18
18enum sort_type sort__first_dimension; 19enum sort_type sort__first_dimension;
@@ -161,6 +162,11 @@ struct sort_entry sort_dso = {
161 162
162/* --sort symbol */ 163/* --sort symbol */
163 164
165static int64_t _sort__addr_cmp(u64 left_ip, u64 right_ip)
166{
167 return (int64_t)(right_ip - left_ip);
168}
169
164static int64_t _sort__sym_cmp(struct symbol *sym_l, struct symbol *sym_r) 170static int64_t _sort__sym_cmp(struct symbol *sym_l, struct symbol *sym_r)
165{ 171{
166 u64 ip_l, ip_r; 172 u64 ip_l, ip_r;
@@ -183,15 +189,17 @@ sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
183 int64_t ret; 189 int64_t ret;
184 190
185 if (!left->ms.sym && !right->ms.sym) 191 if (!left->ms.sym && !right->ms.sym)
186 return right->level - left->level; 192 return _sort__addr_cmp(left->ip, right->ip);
187 193
188 /* 194 /*
189 * comparing symbol address alone is not enough since it's a 195 * comparing symbol address alone is not enough since it's a
190 * relative address within a dso. 196 * relative address within a dso.
191 */ 197 */
192 ret = sort__dso_cmp(left, right); 198 if (!sort__has_dso) {
193 if (ret != 0) 199 ret = sort__dso_cmp(left, right);
194 return ret; 200 if (ret != 0)
201 return ret;
202 }
195 203
196 return _sort__sym_cmp(left->ms.sym, right->ms.sym); 204 return _sort__sym_cmp(left->ms.sym, right->ms.sym);
197} 205}
@@ -372,7 +380,7 @@ sort__sym_from_cmp(struct hist_entry *left, struct hist_entry *right)
372 struct addr_map_symbol *from_r = &right->branch_info->from; 380 struct addr_map_symbol *from_r = &right->branch_info->from;
373 381
374 if (!from_l->sym && !from_r->sym) 382 if (!from_l->sym && !from_r->sym)
375 return right->level - left->level; 383 return _sort__addr_cmp(from_l->addr, from_r->addr);
376 384
377 return _sort__sym_cmp(from_l->sym, from_r->sym); 385 return _sort__sym_cmp(from_l->sym, from_r->sym);
378} 386}
@@ -384,7 +392,7 @@ sort__sym_to_cmp(struct hist_entry *left, struct hist_entry *right)
384 struct addr_map_symbol *to_r = &right->branch_info->to; 392 struct addr_map_symbol *to_r = &right->branch_info->to;
385 393
386 if (!to_l->sym && !to_r->sym) 394 if (!to_l->sym && !to_r->sym)
387 return right->level - left->level; 395 return _sort__addr_cmp(to_l->addr, to_r->addr);
388 396
389 return _sort__sym_cmp(to_l->sym, to_r->sym); 397 return _sort__sym_cmp(to_l->sym, to_r->sym);
390} 398}
@@ -1056,6 +1064,8 @@ int sort_dimension__add(const char *tok)
1056 sort__has_parent = 1; 1064 sort__has_parent = 1;
1057 } else if (sd->entry == &sort_sym) { 1065 } else if (sd->entry == &sort_sym) {
1058 sort__has_sym = 1; 1066 sort__has_sym = 1;
1067 } else if (sd->entry == &sort_dso) {
1068 sort__has_dso = 1;
1059 } 1069 }
1060 1070
1061 __sort_dimension__add(sd, i); 1071 __sort_dimension__add(sd, i);
diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c
index d11aefbc4b8d..f3e4bc5fe5d2 100644
--- a/tools/perf/util/srcline.c
+++ b/tools/perf/util/srcline.c
@@ -129,7 +129,7 @@ static struct a2l_data *addr2line_init(const char *path)
129 129
130out: 130out:
131 if (a2l) { 131 if (a2l) {
132 free((void *)a2l->input); 132 zfree((char **)&a2l->input);
133 free(a2l); 133 free(a2l);
134 } 134 }
135 bfd_close(abfd); 135 bfd_close(abfd);
@@ -140,24 +140,30 @@ static void addr2line_cleanup(struct a2l_data *a2l)
140{ 140{
141 if (a2l->abfd) 141 if (a2l->abfd)
142 bfd_close(a2l->abfd); 142 bfd_close(a2l->abfd);
143 free((void *)a2l->input); 143 zfree((char **)&a2l->input);
144 free(a2l->syms); 144 zfree(&a2l->syms);
145 free(a2l); 145 free(a2l);
146} 146}
147 147
148static int addr2line(const char *dso_name, unsigned long addr, 148static int addr2line(const char *dso_name, unsigned long addr,
149 char **file, unsigned int *line) 149 char **file, unsigned int *line, struct dso *dso)
150{ 150{
151 int ret = 0; 151 int ret = 0;
152 struct a2l_data *a2l; 152 struct a2l_data *a2l = dso->a2l;
153
154 if (!a2l) {
155 dso->a2l = addr2line_init(dso_name);
156 a2l = dso->a2l;
157 }
153 158
154 a2l = addr2line_init(dso_name);
155 if (a2l == NULL) { 159 if (a2l == NULL) {
156 pr_warning("addr2line_init failed for %s\n", dso_name); 160 pr_warning("addr2line_init failed for %s\n", dso_name);
157 return 0; 161 return 0;
158 } 162 }
159 163
160 a2l->addr = addr; 164 a2l->addr = addr;
165 a2l->found = false;
166
161 bfd_map_over_sections(a2l->abfd, find_address_in_section, a2l); 167 bfd_map_over_sections(a2l->abfd, find_address_in_section, a2l);
162 168
163 if (a2l->found && a2l->filename) { 169 if (a2l->found && a2l->filename) {
@@ -168,14 +174,26 @@ static int addr2line(const char *dso_name, unsigned long addr,
168 ret = 1; 174 ret = 1;
169 } 175 }
170 176
171 addr2line_cleanup(a2l);
172 return ret; 177 return ret;
173} 178}
174 179
180void dso__free_a2l(struct dso *dso)
181{
182 struct a2l_data *a2l = dso->a2l;
183
184 if (!a2l)
185 return;
186
187 addr2line_cleanup(a2l);
188
189 dso->a2l = NULL;
190}
191
175#else /* HAVE_LIBBFD_SUPPORT */ 192#else /* HAVE_LIBBFD_SUPPORT */
176 193
177static int addr2line(const char *dso_name, unsigned long addr, 194static int addr2line(const char *dso_name, unsigned long addr,
178 char **file, unsigned int *line_nr) 195 char **file, unsigned int *line_nr,
196 struct dso *dso __maybe_unused)
179{ 197{
180 FILE *fp; 198 FILE *fp;
181 char cmd[PATH_MAX]; 199 char cmd[PATH_MAX];
@@ -219,42 +237,58 @@ out:
219 pclose(fp); 237 pclose(fp);
220 return ret; 238 return ret;
221} 239}
240
241void dso__free_a2l(struct dso *dso __maybe_unused)
242{
243}
244
222#endif /* HAVE_LIBBFD_SUPPORT */ 245#endif /* HAVE_LIBBFD_SUPPORT */
223 246
247/*
248 * Number of addr2line failures (without success) before disabling it for that
249 * dso.
250 */
251#define A2L_FAIL_LIMIT 123
252
224char *get_srcline(struct dso *dso, unsigned long addr) 253char *get_srcline(struct dso *dso, unsigned long addr)
225{ 254{
226 char *file = NULL; 255 char *file = NULL;
227 unsigned line = 0; 256 unsigned line = 0;
228 char *srcline; 257 char *srcline;
229 char *dso_name = dso->long_name; 258 const char *dso_name;
230 size_t size;
231 259
232 if (!dso->has_srcline) 260 if (!dso->has_srcline)
233 return SRCLINE_UNKNOWN; 261 return SRCLINE_UNKNOWN;
234 262
263 if (dso->symsrc_filename)
264 dso_name = dso->symsrc_filename;
265 else
266 dso_name = dso->long_name;
267
235 if (dso_name[0] == '[') 268 if (dso_name[0] == '[')
236 goto out; 269 goto out;
237 270
238 if (!strncmp(dso_name, "/tmp/perf-", 10)) 271 if (!strncmp(dso_name, "/tmp/perf-", 10))
239 goto out; 272 goto out;
240 273
241 if (!addr2line(dso_name, addr, &file, &line)) 274 if (!addr2line(dso_name, addr, &file, &line, dso))
242 goto out; 275 goto out;
243 276
244 /* just calculate actual length */ 277 if (asprintf(&srcline, "%s:%u", file, line) < 0) {
245 size = snprintf(NULL, 0, "%s:%u", file, line) + 1; 278 free(file);
279 goto out;
280 }
246 281
247 srcline = malloc(size); 282 dso->a2l_fails = 0;
248 if (srcline)
249 snprintf(srcline, size, "%s:%u", file, line);
250 else
251 srcline = SRCLINE_UNKNOWN;
252 283
253 free(file); 284 free(file);
254 return srcline; 285 return srcline;
255 286
256out: 287out:
257 dso->has_srcline = 0; 288 if (dso->a2l_fails && ++dso->a2l_fails > A2L_FAIL_LIMIT) {
289 dso->has_srcline = 0;
290 dso__free_a2l(dso);
291 }
258 return SRCLINE_UNKNOWN; 292 return SRCLINE_UNKNOWN;
259} 293}
260 294
diff --git a/tools/perf/util/strbuf.c b/tools/perf/util/strbuf.c
index cfa906882e2c..4abe23550c73 100644
--- a/tools/perf/util/strbuf.c
+++ b/tools/perf/util/strbuf.c
@@ -28,7 +28,7 @@ void strbuf_init(struct strbuf *sb, ssize_t hint)
28void strbuf_release(struct strbuf *sb) 28void strbuf_release(struct strbuf *sb)
29{ 29{
30 if (sb->alloc) { 30 if (sb->alloc) {
31 free(sb->buf); 31 zfree(&sb->buf);
32 strbuf_init(sb, 0); 32 strbuf_init(sb, 0);
33 } 33 }
34} 34}
diff --git a/tools/perf/util/strfilter.c b/tools/perf/util/strfilter.c
index 3edd0538161f..79a757a2a15c 100644
--- a/tools/perf/util/strfilter.c
+++ b/tools/perf/util/strfilter.c
@@ -14,7 +14,7 @@ static void strfilter_node__delete(struct strfilter_node *node)
14{ 14{
15 if (node) { 15 if (node) {
16 if (node->p && !is_operator(*node->p)) 16 if (node->p && !is_operator(*node->p))
17 free((char *)node->p); 17 zfree((char **)&node->p);
18 strfilter_node__delete(node->l); 18 strfilter_node__delete(node->l);
19 strfilter_node__delete(node->r); 19 strfilter_node__delete(node->r);
20 free(node); 20 free(node);
diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c
index f0b0c008c507..2553e5b55b89 100644
--- a/tools/perf/util/string.c
+++ b/tools/perf/util/string.c
@@ -128,7 +128,7 @@ void argv_free(char **argv)
128{ 128{
129 char **p; 129 char **p;
130 for (p = argv; *p; p++) 130 for (p = argv; *p; p++)
131 free(*p); 131 zfree(p);
132 132
133 free(argv); 133 free(argv);
134} 134}
diff --git a/tools/perf/util/strlist.c b/tools/perf/util/strlist.c
index eabdce0a2daa..71f9d102b96f 100644
--- a/tools/perf/util/strlist.c
+++ b/tools/perf/util/strlist.c
@@ -5,6 +5,7 @@
5 */ 5 */
6 6
7#include "strlist.h" 7#include "strlist.h"
8#include "util.h"
8#include <errno.h> 9#include <errno.h>
9#include <stdio.h> 10#include <stdio.h>
10#include <stdlib.h> 11#include <stdlib.h>
@@ -38,7 +39,7 @@ out_delete:
38static void str_node__delete(struct str_node *snode, bool dupstr) 39static void str_node__delete(struct str_node *snode, bool dupstr)
39{ 40{
40 if (dupstr) 41 if (dupstr)
41 free((void *)snode->s); 42 zfree((char **)&snode->s);
42 free(snode); 43 free(snode);
43} 44}
44 45
diff --git a/tools/perf/util/svghelper.c b/tools/perf/util/svghelper.c
index 96c866045d60..43262b83c541 100644
--- a/tools/perf/util/svghelper.c
+++ b/tools/perf/util/svghelper.c
@@ -17,8 +17,12 @@
17#include <stdlib.h> 17#include <stdlib.h>
18#include <unistd.h> 18#include <unistd.h>
19#include <string.h> 19#include <string.h>
20#include <linux/bitops.h>
20 21
22#include "perf.h"
21#include "svghelper.h" 23#include "svghelper.h"
24#include "util.h"
25#include "cpumap.h"
22 26
23static u64 first_time, last_time; 27static u64 first_time, last_time;
24static u64 turbo_frequency, max_freq; 28static u64 turbo_frequency, max_freq;
@@ -28,6 +32,8 @@ static u64 turbo_frequency, max_freq;
28#define SLOT_HEIGHT 25.0 32#define SLOT_HEIGHT 25.0
29 33
30int svg_page_width = 1000; 34int svg_page_width = 1000;
35u64 svg_highlight;
36const char *svg_highlight_name;
31 37
32#define MIN_TEXT_SIZE 0.01 38#define MIN_TEXT_SIZE 0.01
33 39
@@ -39,9 +45,14 @@ static double cpu2slot(int cpu)
39 return 2 * cpu + 1; 45 return 2 * cpu + 1;
40} 46}
41 47
48static int *topology_map;
49
42static double cpu2y(int cpu) 50static double cpu2y(int cpu)
43{ 51{
44 return cpu2slot(cpu) * SLOT_MULT; 52 if (topology_map)
53 return cpu2slot(topology_map[cpu]) * SLOT_MULT;
54 else
55 return cpu2slot(cpu) * SLOT_MULT;
45} 56}
46 57
47static double time2pixels(u64 __time) 58static double time2pixels(u64 __time)
@@ -95,6 +106,7 @@ void open_svg(const char *filename, int cpus, int rows, u64 start, u64 end)
95 106
96 total_height = (1 + rows + cpu2slot(cpus)) * SLOT_MULT; 107 total_height = (1 + rows + cpu2slot(cpus)) * SLOT_MULT;
97 fprintf(svgfile, "<?xml version=\"1.0\" standalone=\"no\"?> \n"); 108 fprintf(svgfile, "<?xml version=\"1.0\" standalone=\"no\"?> \n");
109 fprintf(svgfile, "<!DOCTYPE svg SYSTEM \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n");
98 fprintf(svgfile, "<svg width=\"%i\" height=\"%" PRIu64 "\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n", svg_page_width, total_height); 110 fprintf(svgfile, "<svg width=\"%i\" height=\"%" PRIu64 "\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n", svg_page_width, total_height);
99 111
100 fprintf(svgfile, "<defs>\n <style type=\"text/css\">\n <![CDATA[\n"); 112 fprintf(svgfile, "<defs>\n <style type=\"text/css\">\n <![CDATA[\n");
@@ -103,6 +115,7 @@ void open_svg(const char *filename, int cpus, int rows, u64 start, u64 end)
103 fprintf(svgfile, " rect.process { fill:rgb(180,180,180); fill-opacity:0.9; stroke-width:1; stroke:rgb( 0, 0, 0); } \n"); 115 fprintf(svgfile, " rect.process { fill:rgb(180,180,180); fill-opacity:0.9; stroke-width:1; stroke:rgb( 0, 0, 0); } \n");
104 fprintf(svgfile, " rect.process2 { fill:rgb(180,180,180); fill-opacity:0.9; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); 116 fprintf(svgfile, " rect.process2 { fill:rgb(180,180,180); fill-opacity:0.9; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
105 fprintf(svgfile, " rect.sample { fill:rgb( 0, 0,255); fill-opacity:0.8; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); 117 fprintf(svgfile, " rect.sample { fill:rgb( 0, 0,255); fill-opacity:0.8; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
118 fprintf(svgfile, " rect.sample_hi{ fill:rgb(255,128, 0); fill-opacity:0.8; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
106 fprintf(svgfile, " rect.blocked { fill:rgb(255, 0, 0); fill-opacity:0.5; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); 119 fprintf(svgfile, " rect.blocked { fill:rgb(255, 0, 0); fill-opacity:0.5; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
107 fprintf(svgfile, " rect.waiting { fill:rgb(224,214, 0); fill-opacity:0.8; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); 120 fprintf(svgfile, " rect.waiting { fill:rgb(224,214, 0); fill-opacity:0.8; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
108 fprintf(svgfile, " rect.WAITING { fill:rgb(255,214, 48); fill-opacity:0.6; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); 121 fprintf(svgfile, " rect.WAITING { fill:rgb(255,214, 48); fill-opacity:0.6; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
@@ -128,14 +141,42 @@ void svg_box(int Yslot, u64 start, u64 end, const char *type)
128 time2pixels(start), time2pixels(end)-time2pixels(start), Yslot * SLOT_MULT, SLOT_HEIGHT, type); 141 time2pixels(start), time2pixels(end)-time2pixels(start), Yslot * SLOT_MULT, SLOT_HEIGHT, type);
129} 142}
130 143
131void svg_sample(int Yslot, int cpu, u64 start, u64 end) 144static char *time_to_string(u64 duration);
145void svg_blocked(int Yslot, int cpu, u64 start, u64 end, const char *backtrace)
146{
147 if (!svgfile)
148 return;
149
150 fprintf(svgfile, "<g>\n");
151 fprintf(svgfile, "<title>#%d blocked %s</title>\n", cpu,
152 time_to_string(end - start));
153 if (backtrace)
154 fprintf(svgfile, "<desc>Blocked on:\n%s</desc>\n", backtrace);
155 svg_box(Yslot, start, end, "blocked");
156 fprintf(svgfile, "</g>\n");
157}
158
159void svg_running(int Yslot, int cpu, u64 start, u64 end, const char *backtrace)
132{ 160{
133 double text_size; 161 double text_size;
162 const char *type;
163
134 if (!svgfile) 164 if (!svgfile)
135 return; 165 return;
136 166
137 fprintf(svgfile, "<rect x=\"%4.8f\" width=\"%4.8f\" y=\"%4.1f\" height=\"%4.1f\" class=\"sample\"/>\n", 167 if (svg_highlight && end - start > svg_highlight)
138 time2pixels(start), time2pixels(end)-time2pixels(start), Yslot * SLOT_MULT, SLOT_HEIGHT); 168 type = "sample_hi";
169 else
170 type = "sample";
171 fprintf(svgfile, "<g>\n");
172
173 fprintf(svgfile, "<title>#%d running %s</title>\n",
174 cpu, time_to_string(end - start));
175 if (backtrace)
176 fprintf(svgfile, "<desc>Switched because:\n%s</desc>\n", backtrace);
177 fprintf(svgfile, "<rect x=\"%4.8f\" width=\"%4.8f\" y=\"%4.1f\" height=\"%4.1f\" class=\"%s\"/>\n",
178 time2pixels(start), time2pixels(end)-time2pixels(start), Yslot * SLOT_MULT, SLOT_HEIGHT,
179 type);
139 180
140 text_size = (time2pixels(end)-time2pixels(start)); 181 text_size = (time2pixels(end)-time2pixels(start));
141 if (cpu > 9) 182 if (cpu > 9)
@@ -148,6 +189,7 @@ void svg_sample(int Yslot, int cpu, u64 start, u64 end)
148 fprintf(svgfile, "<text x=\"%1.8f\" y=\"%1.8f\" font-size=\"%1.8fpt\">%i</text>\n", 189 fprintf(svgfile, "<text x=\"%1.8f\" y=\"%1.8f\" font-size=\"%1.8fpt\">%i</text>\n",
149 time2pixels(start), Yslot * SLOT_MULT + SLOT_HEIGHT - 1, text_size, cpu + 1); 190 time2pixels(start), Yslot * SLOT_MULT + SLOT_HEIGHT - 1, text_size, cpu + 1);
150 191
192 fprintf(svgfile, "</g>\n");
151} 193}
152 194
153static char *time_to_string(u64 duration) 195static char *time_to_string(u64 duration)
@@ -168,7 +210,7 @@ static char *time_to_string(u64 duration)
168 return text; 210 return text;
169} 211}
170 212
171void svg_waiting(int Yslot, u64 start, u64 end) 213void svg_waiting(int Yslot, int cpu, u64 start, u64 end, const char *backtrace)
172{ 214{
173 char *text; 215 char *text;
174 const char *style; 216 const char *style;
@@ -192,6 +234,9 @@ void svg_waiting(int Yslot, u64 start, u64 end)
192 font_size = round_text_size(font_size); 234 font_size = round_text_size(font_size);
193 235
194 fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\">\n", time2pixels(start), Yslot * SLOT_MULT); 236 fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\">\n", time2pixels(start), Yslot * SLOT_MULT);
237 fprintf(svgfile, "<title>#%d waiting %s</title>\n", cpu, time_to_string(end - start));
238 if (backtrace)
239 fprintf(svgfile, "<desc>Waiting on:\n%s</desc>\n", backtrace);
195 fprintf(svgfile, "<rect x=\"0\" width=\"%4.8f\" y=\"0\" height=\"%4.1f\" class=\"%s\"/>\n", 240 fprintf(svgfile, "<rect x=\"0\" width=\"%4.8f\" y=\"0\" height=\"%4.1f\" class=\"%s\"/>\n",
196 time2pixels(end)-time2pixels(start), SLOT_HEIGHT, style); 241 time2pixels(end)-time2pixels(start), SLOT_HEIGHT, style);
197 if (font_size > MIN_TEXT_SIZE) 242 if (font_size > MIN_TEXT_SIZE)
@@ -242,28 +287,42 @@ void svg_cpu_box(int cpu, u64 __max_freq, u64 __turbo_freq)
242 max_freq = __max_freq; 287 max_freq = __max_freq;
243 turbo_frequency = __turbo_freq; 288 turbo_frequency = __turbo_freq;
244 289
290 fprintf(svgfile, "<g>\n");
291
245 fprintf(svgfile, "<rect x=\"%4.8f\" width=\"%4.8f\" y=\"%4.1f\" height=\"%4.1f\" class=\"cpu\"/>\n", 292 fprintf(svgfile, "<rect x=\"%4.8f\" width=\"%4.8f\" y=\"%4.1f\" height=\"%4.1f\" class=\"cpu\"/>\n",
246 time2pixels(first_time), 293 time2pixels(first_time),
247 time2pixels(last_time)-time2pixels(first_time), 294 time2pixels(last_time)-time2pixels(first_time),
248 cpu2y(cpu), SLOT_MULT+SLOT_HEIGHT); 295 cpu2y(cpu), SLOT_MULT+SLOT_HEIGHT);
249 296
250 sprintf(cpu_string, "CPU %i", (int)cpu+1); 297 sprintf(cpu_string, "CPU %i", (int)cpu);
251 fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\">%s</text>\n", 298 fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\">%s</text>\n",
252 10+time2pixels(first_time), cpu2y(cpu) + SLOT_HEIGHT/2, cpu_string); 299 10+time2pixels(first_time), cpu2y(cpu) + SLOT_HEIGHT/2, cpu_string);
253 300
254 fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f)\" font-size=\"1.25pt\">%s</text>\n", 301 fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f)\" font-size=\"1.25pt\">%s</text>\n",
255 10+time2pixels(first_time), cpu2y(cpu) + SLOT_MULT + SLOT_HEIGHT - 4, cpu_model()); 302 10+time2pixels(first_time), cpu2y(cpu) + SLOT_MULT + SLOT_HEIGHT - 4, cpu_model());
303
304 fprintf(svgfile, "</g>\n");
256} 305}
257 306
258void svg_process(int cpu, u64 start, u64 end, const char *type, const char *name) 307void svg_process(int cpu, u64 start, u64 end, int pid, const char *name, const char *backtrace)
259{ 308{
260 double width; 309 double width;
310 const char *type;
261 311
262 if (!svgfile) 312 if (!svgfile)
263 return; 313 return;
264 314
315 if (svg_highlight && end - start >= svg_highlight)
316 type = "sample_hi";
317 else if (svg_highlight_name && strstr(name, svg_highlight_name))
318 type = "sample_hi";
319 else
320 type = "sample";
265 321
266 fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\">\n", time2pixels(start), cpu2y(cpu)); 322 fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\">\n", time2pixels(start), cpu2y(cpu));
323 fprintf(svgfile, "<title>%d %s running %s</title>\n", pid, name, time_to_string(end - start));
324 if (backtrace)
325 fprintf(svgfile, "<desc>Switched because:\n%s</desc>\n", backtrace);
267 fprintf(svgfile, "<rect x=\"0\" width=\"%4.8f\" y=\"0\" height=\"%4.1f\" class=\"%s\"/>\n", 326 fprintf(svgfile, "<rect x=\"0\" width=\"%4.8f\" y=\"0\" height=\"%4.1f\" class=\"%s\"/>\n",
268 time2pixels(end)-time2pixels(start), SLOT_MULT+SLOT_HEIGHT, type); 327 time2pixels(end)-time2pixels(start), SLOT_MULT+SLOT_HEIGHT, type);
269 width = time2pixels(end)-time2pixels(start); 328 width = time2pixels(end)-time2pixels(start);
@@ -288,6 +347,8 @@ void svg_cstate(int cpu, u64 start, u64 end, int type)
288 return; 347 return;
289 348
290 349
350 fprintf(svgfile, "<g>\n");
351
291 if (type > 6) 352 if (type > 6)
292 type = 6; 353 type = 6;
293 sprintf(style, "c%i", type); 354 sprintf(style, "c%i", type);
@@ -306,6 +367,8 @@ void svg_cstate(int cpu, u64 start, u64 end, int type)
306 if (width > MIN_TEXT_SIZE) 367 if (width > MIN_TEXT_SIZE)
307 fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\" font-size=\"%3.8fpt\">C%i</text>\n", 368 fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\" font-size=\"%3.8fpt\">C%i</text>\n",
308 time2pixels(start), cpu2y(cpu)+width, width, type); 369 time2pixels(start), cpu2y(cpu)+width, width, type);
370
371 fprintf(svgfile, "</g>\n");
309} 372}
310 373
311static char *HzToHuman(unsigned long hz) 374static char *HzToHuman(unsigned long hz)
@@ -339,6 +402,8 @@ void svg_pstate(int cpu, u64 start, u64 end, u64 freq)
339 if (!svgfile) 402 if (!svgfile)
340 return; 403 return;
341 404
405 fprintf(svgfile, "<g>\n");
406
342 if (max_freq) 407 if (max_freq)
343 height = freq * 1.0 / max_freq * (SLOT_HEIGHT + SLOT_MULT); 408 height = freq * 1.0 / max_freq * (SLOT_HEIGHT + SLOT_MULT);
344 height = 1 + cpu2y(cpu) + SLOT_MULT + SLOT_HEIGHT - height; 409 height = 1 + cpu2y(cpu) + SLOT_MULT + SLOT_HEIGHT - height;
@@ -347,10 +412,11 @@ void svg_pstate(int cpu, u64 start, u64 end, u64 freq)
347 fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\" font-size=\"0.25pt\">%s</text>\n", 412 fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\" font-size=\"0.25pt\">%s</text>\n",
348 time2pixels(start), height+0.9, HzToHuman(freq)); 413 time2pixels(start), height+0.9, HzToHuman(freq));
349 414
415 fprintf(svgfile, "</g>\n");
350} 416}
351 417
352 418
353void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc2) 419void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc2, const char *backtrace)
354{ 420{
355 double height; 421 double height;
356 422
@@ -358,6 +424,15 @@ void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc
358 return; 424 return;
359 425
360 426
427 fprintf(svgfile, "<g>\n");
428
429 fprintf(svgfile, "<title>%s wakes up %s</title>\n",
430 desc1 ? desc1 : "?",
431 desc2 ? desc2 : "?");
432
433 if (backtrace)
434 fprintf(svgfile, "<desc>%s</desc>\n", backtrace);
435
361 if (row1 < row2) { 436 if (row1 < row2) {
362 if (row1) { 437 if (row1) {
363 fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%4.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n", 438 fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%4.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n",
@@ -395,9 +470,11 @@ void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc
395 if (row1) 470 if (row1)
396 fprintf(svgfile, "<circle cx=\"%4.8f\" cy=\"%4.2f\" r = \"0.01\" style=\"fill:rgb(32,255,32)\"/>\n", 471 fprintf(svgfile, "<circle cx=\"%4.8f\" cy=\"%4.2f\" r = \"0.01\" style=\"fill:rgb(32,255,32)\"/>\n",
397 time2pixels(start), height); 472 time2pixels(start), height);
473
474 fprintf(svgfile, "</g>\n");
398} 475}
399 476
400void svg_wakeline(u64 start, int row1, int row2) 477void svg_wakeline(u64 start, int row1, int row2, const char *backtrace)
401{ 478{
402 double height; 479 double height;
403 480
@@ -405,6 +482,11 @@ void svg_wakeline(u64 start, int row1, int row2)
405 return; 482 return;
406 483
407 484
485 fprintf(svgfile, "<g>\n");
486
487 if (backtrace)
488 fprintf(svgfile, "<desc>%s</desc>\n", backtrace);
489
408 if (row1 < row2) 490 if (row1 < row2)
409 fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%4.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n", 491 fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%4.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n",
410 time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT, time2pixels(start), row2 * SLOT_MULT); 492 time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT, time2pixels(start), row2 * SLOT_MULT);
@@ -417,17 +499,28 @@ void svg_wakeline(u64 start, int row1, int row2)
417 height += SLOT_HEIGHT; 499 height += SLOT_HEIGHT;
418 fprintf(svgfile, "<circle cx=\"%4.8f\" cy=\"%4.2f\" r = \"0.01\" style=\"fill:rgb(32,255,32)\"/>\n", 500 fprintf(svgfile, "<circle cx=\"%4.8f\" cy=\"%4.2f\" r = \"0.01\" style=\"fill:rgb(32,255,32)\"/>\n",
419 time2pixels(start), height); 501 time2pixels(start), height);
502
503 fprintf(svgfile, "</g>\n");
420} 504}
421 505
422void svg_interrupt(u64 start, int row) 506void svg_interrupt(u64 start, int row, const char *backtrace)
423{ 507{
424 if (!svgfile) 508 if (!svgfile)
425 return; 509 return;
426 510
511 fprintf(svgfile, "<g>\n");
512
513 fprintf(svgfile, "<title>Wakeup from interrupt</title>\n");
514
515 if (backtrace)
516 fprintf(svgfile, "<desc>%s</desc>\n", backtrace);
517
427 fprintf(svgfile, "<circle cx=\"%4.8f\" cy=\"%4.2f\" r = \"0.01\" style=\"fill:rgb(255,128,128)\"/>\n", 518 fprintf(svgfile, "<circle cx=\"%4.8f\" cy=\"%4.2f\" r = \"0.01\" style=\"fill:rgb(255,128,128)\"/>\n",
428 time2pixels(start), row * SLOT_MULT); 519 time2pixels(start), row * SLOT_MULT);
429 fprintf(svgfile, "<circle cx=\"%4.8f\" cy=\"%4.2f\" r = \"0.01\" style=\"fill:rgb(255,128,128)\"/>\n", 520 fprintf(svgfile, "<circle cx=\"%4.8f\" cy=\"%4.2f\" r = \"0.01\" style=\"fill:rgb(255,128,128)\"/>\n",
430 time2pixels(start), row * SLOT_MULT + SLOT_HEIGHT); 521 time2pixels(start), row * SLOT_MULT + SLOT_HEIGHT);
522
523 fprintf(svgfile, "</g>\n");
431} 524}
432 525
433void svg_text(int Yslot, u64 start, const char *text) 526void svg_text(int Yslot, u64 start, const char *text)
@@ -455,6 +548,7 @@ void svg_legenda(void)
455 if (!svgfile) 548 if (!svgfile)
456 return; 549 return;
457 550
551 fprintf(svgfile, "<g>\n");
458 svg_legenda_box(0, "Running", "sample"); 552 svg_legenda_box(0, "Running", "sample");
459 svg_legenda_box(100, "Idle","c1"); 553 svg_legenda_box(100, "Idle","c1");
460 svg_legenda_box(200, "Deeper Idle", "c3"); 554 svg_legenda_box(200, "Deeper Idle", "c3");
@@ -462,6 +556,7 @@ void svg_legenda(void)
462 svg_legenda_box(550, "Sleeping", "process2"); 556 svg_legenda_box(550, "Sleeping", "process2");
463 svg_legenda_box(650, "Waiting for cpu", "waiting"); 557 svg_legenda_box(650, "Waiting for cpu", "waiting");
464 svg_legenda_box(800, "Blocked on IO", "blocked"); 558 svg_legenda_box(800, "Blocked on IO", "blocked");
559 fprintf(svgfile, "</g>\n");
465} 560}
466 561
467void svg_time_grid(void) 562void svg_time_grid(void)
@@ -499,3 +594,123 @@ void svg_close(void)
499 svgfile = NULL; 594 svgfile = NULL;
500 } 595 }
501} 596}
597
598#define cpumask_bits(maskp) ((maskp)->bits)
599typedef struct { DECLARE_BITMAP(bits, MAX_NR_CPUS); } cpumask_t;
600
601struct topology {
602 cpumask_t *sib_core;
603 int sib_core_nr;
604 cpumask_t *sib_thr;
605 int sib_thr_nr;
606};
607
608static void scan_thread_topology(int *map, struct topology *t, int cpu, int *pos)
609{
610 int i;
611 int thr;
612
613 for (i = 0; i < t->sib_thr_nr; i++) {
614 if (!test_bit(cpu, cpumask_bits(&t->sib_thr[i])))
615 continue;
616
617 for_each_set_bit(thr,
618 cpumask_bits(&t->sib_thr[i]),
619 MAX_NR_CPUS)
620 if (map[thr] == -1)
621 map[thr] = (*pos)++;
622 }
623}
624
625static void scan_core_topology(int *map, struct topology *t)
626{
627 int pos = 0;
628 int i;
629 int cpu;
630
631 for (i = 0; i < t->sib_core_nr; i++)
632 for_each_set_bit(cpu,
633 cpumask_bits(&t->sib_core[i]),
634 MAX_NR_CPUS)
635 scan_thread_topology(map, t, cpu, &pos);
636}
637
638static int str_to_bitmap(char *s, cpumask_t *b)
639{
640 int i;
641 int ret = 0;
642 struct cpu_map *m;
643 int c;
644
645 m = cpu_map__new(s);
646 if (!m)
647 return -1;
648
649 for (i = 0; i < m->nr; i++) {
650 c = m->map[i];
651 if (c >= MAX_NR_CPUS) {
652 ret = -1;
653 break;
654 }
655
656 set_bit(c, cpumask_bits(b));
657 }
658
659 cpu_map__delete(m);
660
661 return ret;
662}
663
664int svg_build_topology_map(char *sib_core, int sib_core_nr,
665 char *sib_thr, int sib_thr_nr)
666{
667 int i;
668 struct topology t;
669
670 t.sib_core_nr = sib_core_nr;
671 t.sib_thr_nr = sib_thr_nr;
672 t.sib_core = calloc(sib_core_nr, sizeof(cpumask_t));
673 t.sib_thr = calloc(sib_thr_nr, sizeof(cpumask_t));
674
675 if (!t.sib_core || !t.sib_thr) {
676 fprintf(stderr, "topology: no memory\n");
677 goto exit;
678 }
679
680 for (i = 0; i < sib_core_nr; i++) {
681 if (str_to_bitmap(sib_core, &t.sib_core[i])) {
682 fprintf(stderr, "topology: can't parse siblings map\n");
683 goto exit;
684 }
685
686 sib_core += strlen(sib_core) + 1;
687 }
688
689 for (i = 0; i < sib_thr_nr; i++) {
690 if (str_to_bitmap(sib_thr, &t.sib_thr[i])) {
691 fprintf(stderr, "topology: can't parse siblings map\n");
692 goto exit;
693 }
694
695 sib_thr += strlen(sib_thr) + 1;
696 }
697
698 topology_map = malloc(sizeof(int) * MAX_NR_CPUS);
699 if (!topology_map) {
700 fprintf(stderr, "topology: no memory\n");
701 goto exit;
702 }
703
704 for (i = 0; i < MAX_NR_CPUS; i++)
705 topology_map[i] = -1;
706
707 scan_core_topology(topology_map, &t);
708
709 return 0;
710
711exit:
712 zfree(&t.sib_core);
713 zfree(&t.sib_thr);
714
715 return -1;
716}
diff --git a/tools/perf/util/svghelper.h b/tools/perf/util/svghelper.h
index e0781989cc31..f7b4d6e699ea 100644
--- a/tools/perf/util/svghelper.h
+++ b/tools/perf/util/svghelper.h
@@ -5,24 +5,29 @@
5 5
6extern void open_svg(const char *filename, int cpus, int rows, u64 start, u64 end); 6extern void open_svg(const char *filename, int cpus, int rows, u64 start, u64 end);
7extern void svg_box(int Yslot, u64 start, u64 end, const char *type); 7extern void svg_box(int Yslot, u64 start, u64 end, const char *type);
8extern void svg_sample(int Yslot, int cpu, u64 start, u64 end); 8extern void svg_blocked(int Yslot, int cpu, u64 start, u64 end, const char *backtrace);
9extern void svg_waiting(int Yslot, u64 start, u64 end); 9extern void svg_running(int Yslot, int cpu, u64 start, u64 end, const char *backtrace);
10extern void svg_waiting(int Yslot, int cpu, u64 start, u64 end, const char *backtrace);
10extern void svg_cpu_box(int cpu, u64 max_frequency, u64 turbo_frequency); 11extern void svg_cpu_box(int cpu, u64 max_frequency, u64 turbo_frequency);
11 12
12 13
13extern void svg_process(int cpu, u64 start, u64 end, const char *type, const char *name); 14extern void svg_process(int cpu, u64 start, u64 end, int pid, const char *name, const char *backtrace);
14extern void svg_cstate(int cpu, u64 start, u64 end, int type); 15extern void svg_cstate(int cpu, u64 start, u64 end, int type);
15extern void svg_pstate(int cpu, u64 start, u64 end, u64 freq); 16extern void svg_pstate(int cpu, u64 start, u64 end, u64 freq);
16 17
17 18
18extern void svg_time_grid(void); 19extern void svg_time_grid(void);
19extern void svg_legenda(void); 20extern void svg_legenda(void);
20extern void svg_wakeline(u64 start, int row1, int row2); 21extern void svg_wakeline(u64 start, int row1, int row2, const char *backtrace);
21extern void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc2); 22extern void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc2, const char *backtrace);
22extern void svg_interrupt(u64 start, int row); 23extern void svg_interrupt(u64 start, int row, const char *backtrace);
23extern void svg_text(int Yslot, u64 start, const char *text); 24extern void svg_text(int Yslot, u64 start, const char *text);
24extern void svg_close(void); 25extern void svg_close(void);
26extern int svg_build_topology_map(char *sib_core, int sib_core_nr,
27 char *sib_thr, int sib_thr_nr);
25 28
26extern int svg_page_width; 29extern int svg_page_width;
30extern u64 svg_highlight;
31extern const char *svg_highlight_name;
27 32
28#endif /* __PERF_SVGHELPER_H */ 33#endif /* __PERF_SVGHELPER_H */
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index eed0b96302af..759456728703 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -6,6 +6,7 @@
6#include <inttypes.h> 6#include <inttypes.h>
7 7
8#include "symbol.h" 8#include "symbol.h"
9#include <symbol/kallsyms.h>
9#include "debug.h" 10#include "debug.h"
10 11
11#ifndef HAVE_ELF_GETPHDRNUM_SUPPORT 12#ifndef HAVE_ELF_GETPHDRNUM_SUPPORT
@@ -135,9 +136,8 @@ static size_t elf_addr_to_index(Elf *elf, GElf_Addr addr)
135 return -1; 136 return -1;
136} 137}
137 138
138static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep, 139Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
139 GElf_Shdr *shp, const char *name, 140 GElf_Shdr *shp, const char *name, size_t *idx)
140 size_t *idx)
141{ 141{
142 Elf_Scn *sec = NULL; 142 Elf_Scn *sec = NULL;
143 size_t cnt = 1; 143 size_t cnt = 1;
@@ -553,7 +553,7 @@ bool symsrc__has_symtab(struct symsrc *ss)
553 553
554void symsrc__destroy(struct symsrc *ss) 554void symsrc__destroy(struct symsrc *ss)
555{ 555{
556 free(ss->name); 556 zfree(&ss->name);
557 elf_end(ss->elf); 557 elf_end(ss->elf);
558 close(ss->fd); 558 close(ss->fd);
559} 559}
diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c
index 2d2dd0532b5a..bd15f490d04f 100644
--- a/tools/perf/util/symbol-minimal.c
+++ b/tools/perf/util/symbol-minimal.c
@@ -1,4 +1,5 @@
1#include "symbol.h" 1#include "symbol.h"
2#include "util.h"
2 3
3#include <stdio.h> 4#include <stdio.h>
4#include <fcntl.h> 5#include <fcntl.h>
@@ -253,6 +254,7 @@ int symsrc__init(struct symsrc *ss, struct dso *dso __maybe_unused,
253 if (!ss->name) 254 if (!ss->name)
254 goto out_close; 255 goto out_close;
255 256
257 ss->fd = fd;
256 ss->type = type; 258 ss->type = type;
257 259
258 return 0; 260 return 0;
@@ -274,7 +276,7 @@ bool symsrc__has_symtab(struct symsrc *ss __maybe_unused)
274 276
275void symsrc__destroy(struct symsrc *ss) 277void symsrc__destroy(struct symsrc *ss)
276{ 278{
277 free(ss->name); 279 zfree(&ss->name);
278 close(ss->fd); 280 close(ss->fd);
279} 281}
280 282
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index c0c36965fff0..39ce9adbaaf0 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -18,12 +18,9 @@
18 18
19#include <elf.h> 19#include <elf.h>
20#include <limits.h> 20#include <limits.h>
21#include <symbol/kallsyms.h>
21#include <sys/utsname.h> 22#include <sys/utsname.h>
22 23
23#ifndef KSYM_NAME_LEN
24#define KSYM_NAME_LEN 256
25#endif
26
27static int dso__load_kernel_sym(struct dso *dso, struct map *map, 24static int dso__load_kernel_sym(struct dso *dso, struct map *map,
28 symbol_filter_t filter); 25 symbol_filter_t filter);
29static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map, 26static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map,
@@ -446,62 +443,6 @@ size_t dso__fprintf_symbols_by_name(struct dso *dso,
446 return ret; 443 return ret;
447} 444}
448 445
449int kallsyms__parse(const char *filename, void *arg,
450 int (*process_symbol)(void *arg, const char *name,
451 char type, u64 start))
452{
453 char *line = NULL;
454 size_t n;
455 int err = -1;
456 FILE *file = fopen(filename, "r");
457
458 if (file == NULL)
459 goto out_failure;
460
461 err = 0;
462
463 while (!feof(file)) {
464 u64 start;
465 int line_len, len;
466 char symbol_type;
467 char *symbol_name;
468
469 line_len = getline(&line, &n, file);
470 if (line_len < 0 || !line)
471 break;
472
473 line[--line_len] = '\0'; /* \n */
474
475 len = hex2u64(line, &start);
476
477 len++;
478 if (len + 2 >= line_len)
479 continue;
480
481 symbol_type = line[len];
482 len += 2;
483 symbol_name = line + len;
484 len = line_len - len;
485
486 if (len >= KSYM_NAME_LEN) {
487 err = -1;
488 break;
489 }
490
491 err = process_symbol(arg, symbol_name,
492 symbol_type, start);
493 if (err)
494 break;
495 }
496
497 free(line);
498 fclose(file);
499 return err;
500
501out_failure:
502 return -1;
503}
504
505int modules__parse(const char *filename, void *arg, 446int modules__parse(const char *filename, void *arg,
506 int (*process_module)(void *arg, const char *name, 447 int (*process_module)(void *arg, const char *name,
507 u64 start)) 448 u64 start))
@@ -565,12 +506,34 @@ struct process_kallsyms_args {
565 struct dso *dso; 506 struct dso *dso;
566}; 507};
567 508
568static u8 kallsyms2elf_type(char type) 509bool symbol__is_idle(struct symbol *sym)
569{ 510{
570 if (type == 'W') 511 const char * const idle_symbols[] = {
571 return STB_WEAK; 512 "cpu_idle",
513 "intel_idle",
514 "default_idle",
515 "native_safe_halt",
516 "enter_idle",
517 "exit_idle",
518 "mwait_idle",
519 "mwait_idle_with_hints",
520 "poll_idle",
521 "ppc64_runlatch_off",
522 "pseries_dedicated_idle_sleep",
523 NULL
524 };
525
526 int i;
527
528 if (!sym)
529 return false;
530
531 for (i = 0; idle_symbols[i]; i++) {
532 if (!strcmp(idle_symbols[i], sym->name))
533 return true;
534 }
572 535
573 return isupper(type) ? STB_GLOBAL : STB_LOCAL; 536 return false;
574} 537}
575 538
576static int map__process_kallsym_symbol(void *arg, const char *name, 539static int map__process_kallsym_symbol(void *arg, const char *name,
@@ -833,7 +796,7 @@ static void delete_modules(struct rb_root *modules)
833 mi = rb_entry(next, struct module_info, rb_node); 796 mi = rb_entry(next, struct module_info, rb_node);
834 next = rb_next(&mi->rb_node); 797 next = rb_next(&mi->rb_node);
835 rb_erase(&mi->rb_node, modules); 798 rb_erase(&mi->rb_node, modules);
836 free(mi->name); 799 zfree(&mi->name);
837 free(mi); 800 free(mi);
838 } 801 }
839} 802}
@@ -1126,10 +1089,10 @@ static int dso__load_kcore(struct dso *dso, struct map *map,
1126 * dso__data_read_addr(). 1089 * dso__data_read_addr().
1127 */ 1090 */
1128 if (dso->kernel == DSO_TYPE_GUEST_KERNEL) 1091 if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
1129 dso->data_type = DSO_BINARY_TYPE__GUEST_KCORE; 1092 dso->binary_type = DSO_BINARY_TYPE__GUEST_KCORE;
1130 else 1093 else
1131 dso->data_type = DSO_BINARY_TYPE__KCORE; 1094 dso->binary_type = DSO_BINARY_TYPE__KCORE;
1132 dso__set_long_name(dso, strdup(kcore_filename)); 1095 dso__set_long_name(dso, strdup(kcore_filename), true);
1133 1096
1134 close(fd); 1097 close(fd);
1135 1098
@@ -1295,8 +1258,8 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1295 1258
1296 enum dso_binary_type symtab_type = binary_type_symtab[i]; 1259 enum dso_binary_type symtab_type = binary_type_symtab[i];
1297 1260
1298 if (dso__binary_type_file(dso, symtab_type, 1261 if (dso__read_binary_type_filename(dso, symtab_type,
1299 root_dir, name, PATH_MAX)) 1262 root_dir, name, PATH_MAX))
1300 continue; 1263 continue;
1301 1264
1302 /* Name is now the name of the next image to try */ 1265 /* Name is now the name of the next image to try */
@@ -1306,6 +1269,8 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1306 if (!syms_ss && symsrc__has_symtab(ss)) { 1269 if (!syms_ss && symsrc__has_symtab(ss)) {
1307 syms_ss = ss; 1270 syms_ss = ss;
1308 next_slot = true; 1271 next_slot = true;
1272 if (!dso->symsrc_filename)
1273 dso->symsrc_filename = strdup(name);
1309 } 1274 }
1310 1275
1311 if (!runtime_ss && symsrc__possibly_runtime(ss)) { 1276 if (!runtime_ss && symsrc__possibly_runtime(ss)) {
@@ -1376,7 +1341,8 @@ struct map *map_groups__find_by_name(struct map_groups *mg,
1376} 1341}
1377 1342
1378int dso__load_vmlinux(struct dso *dso, struct map *map, 1343int dso__load_vmlinux(struct dso *dso, struct map *map,
1379 const char *vmlinux, symbol_filter_t filter) 1344 const char *vmlinux, bool vmlinux_allocated,
1345 symbol_filter_t filter)
1380{ 1346{
1381 int err = -1; 1347 int err = -1;
1382 struct symsrc ss; 1348 struct symsrc ss;
@@ -1402,10 +1368,10 @@ int dso__load_vmlinux(struct dso *dso, struct map *map,
1402 1368
1403 if (err > 0) { 1369 if (err > 0) {
1404 if (dso->kernel == DSO_TYPE_GUEST_KERNEL) 1370 if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
1405 dso->data_type = DSO_BINARY_TYPE__GUEST_VMLINUX; 1371 dso->binary_type = DSO_BINARY_TYPE__GUEST_VMLINUX;
1406 else 1372 else
1407 dso->data_type = DSO_BINARY_TYPE__VMLINUX; 1373 dso->binary_type = DSO_BINARY_TYPE__VMLINUX;
1408 dso__set_long_name(dso, (char *)vmlinux); 1374 dso__set_long_name(dso, vmlinux, vmlinux_allocated);
1409 dso__set_loaded(dso, map->type); 1375 dso__set_loaded(dso, map->type);
1410 pr_debug("Using %s for symbols\n", symfs_vmlinux); 1376 pr_debug("Using %s for symbols\n", symfs_vmlinux);
1411 } 1377 }
@@ -1424,21 +1390,16 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map,
1424 1390
1425 filename = dso__build_id_filename(dso, NULL, 0); 1391 filename = dso__build_id_filename(dso, NULL, 0);
1426 if (filename != NULL) { 1392 if (filename != NULL) {
1427 err = dso__load_vmlinux(dso, map, filename, filter); 1393 err = dso__load_vmlinux(dso, map, filename, true, filter);
1428 if (err > 0) { 1394 if (err > 0)
1429 dso->lname_alloc = 1;
1430 goto out; 1395 goto out;
1431 }
1432 free(filename); 1396 free(filename);
1433 } 1397 }
1434 1398
1435 for (i = 0; i < vmlinux_path__nr_entries; ++i) { 1399 for (i = 0; i < vmlinux_path__nr_entries; ++i) {
1436 err = dso__load_vmlinux(dso, map, vmlinux_path[i], filter); 1400 err = dso__load_vmlinux(dso, map, vmlinux_path[i], false, filter);
1437 if (err > 0) { 1401 if (err > 0)
1438 dso__set_long_name(dso, strdup(vmlinux_path[i]));
1439 dso->lname_alloc = 1;
1440 break; 1402 break;
1441 }
1442 } 1403 }
1443out: 1404out:
1444 return err; 1405 return err;
@@ -1496,14 +1457,15 @@ static char *dso__find_kallsyms(struct dso *dso, struct map *map)
1496 1457
1497 build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id); 1458 build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
1498 1459
1460 scnprintf(path, sizeof(path), "%s/[kernel.kcore]/%s", buildid_dir,
1461 sbuild_id);
1462
1499 /* Use /proc/kallsyms if possible */ 1463 /* Use /proc/kallsyms if possible */
1500 if (is_host) { 1464 if (is_host) {
1501 DIR *d; 1465 DIR *d;
1502 int fd; 1466 int fd;
1503 1467
1504 /* If no cached kcore go with /proc/kallsyms */ 1468 /* If no cached kcore go with /proc/kallsyms */
1505 scnprintf(path, sizeof(path), "%s/[kernel.kcore]/%s",
1506 buildid_dir, sbuild_id);
1507 d = opendir(path); 1469 d = opendir(path);
1508 if (!d) 1470 if (!d)
1509 goto proc_kallsyms; 1471 goto proc_kallsyms;
@@ -1528,6 +1490,10 @@ static char *dso__find_kallsyms(struct dso *dso, struct map *map)
1528 goto proc_kallsyms; 1490 goto proc_kallsyms;
1529 } 1491 }
1530 1492
1493 /* Find kallsyms in build-id cache with kcore */
1494 if (!find_matching_kcore(map, path, sizeof(path)))
1495 return strdup(path);
1496
1531 scnprintf(path, sizeof(path), "%s/[kernel.kallsyms]/%s", 1497 scnprintf(path, sizeof(path), "%s/[kernel.kallsyms]/%s",
1532 buildid_dir, sbuild_id); 1498 buildid_dir, sbuild_id);
1533 1499
@@ -1570,15 +1536,8 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map,
1570 } 1536 }
1571 1537
1572 if (!symbol_conf.ignore_vmlinux && symbol_conf.vmlinux_name != NULL) { 1538 if (!symbol_conf.ignore_vmlinux && symbol_conf.vmlinux_name != NULL) {
1573 err = dso__load_vmlinux(dso, map, 1539 return dso__load_vmlinux(dso, map, symbol_conf.vmlinux_name,
1574 symbol_conf.vmlinux_name, filter); 1540 false, filter);
1575 if (err > 0) {
1576 dso__set_long_name(dso,
1577 strdup(symbol_conf.vmlinux_name));
1578 dso->lname_alloc = 1;
1579 return err;
1580 }
1581 return err;
1582 } 1541 }
1583 1542
1584 if (!symbol_conf.ignore_vmlinux && vmlinux_path != NULL) { 1543 if (!symbol_conf.ignore_vmlinux && vmlinux_path != NULL) {
@@ -1604,7 +1563,7 @@ do_kallsyms:
1604 free(kallsyms_allocated_filename); 1563 free(kallsyms_allocated_filename);
1605 1564
1606 if (err > 0 && !dso__is_kcore(dso)) { 1565 if (err > 0 && !dso__is_kcore(dso)) {
1607 dso__set_long_name(dso, strdup("[kernel.kallsyms]")); 1566 dso__set_long_name(dso, "[kernel.kallsyms]", false);
1608 map__fixup_start(map); 1567 map__fixup_start(map);
1609 map__fixup_end(map); 1568 map__fixup_end(map);
1610 } 1569 }
@@ -1634,7 +1593,8 @@ static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map,
1634 */ 1593 */
1635 if (symbol_conf.default_guest_vmlinux_name != NULL) { 1594 if (symbol_conf.default_guest_vmlinux_name != NULL) {
1636 err = dso__load_vmlinux(dso, map, 1595 err = dso__load_vmlinux(dso, map,
1637 symbol_conf.default_guest_vmlinux_name, filter); 1596 symbol_conf.default_guest_vmlinux_name,
1597 false, filter);
1638 return err; 1598 return err;
1639 } 1599 }
1640 1600
@@ -1651,7 +1611,7 @@ static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map,
1651 pr_debug("Using %s for symbols\n", kallsyms_filename); 1611 pr_debug("Using %s for symbols\n", kallsyms_filename);
1652 if (err > 0 && !dso__is_kcore(dso)) { 1612 if (err > 0 && !dso__is_kcore(dso)) {
1653 machine__mmap_name(machine, path, sizeof(path)); 1613 machine__mmap_name(machine, path, sizeof(path));
1654 dso__set_long_name(dso, strdup(path)); 1614 dso__set_long_name(dso, strdup(path), true);
1655 map__fixup_start(map); 1615 map__fixup_start(map);
1656 map__fixup_end(map); 1616 map__fixup_end(map);
1657 } 1617 }
@@ -1661,13 +1621,10 @@ static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map,
1661 1621
1662static void vmlinux_path__exit(void) 1622static void vmlinux_path__exit(void)
1663{ 1623{
1664 while (--vmlinux_path__nr_entries >= 0) { 1624 while (--vmlinux_path__nr_entries >= 0)
1665 free(vmlinux_path[vmlinux_path__nr_entries]); 1625 zfree(&vmlinux_path[vmlinux_path__nr_entries]);
1666 vmlinux_path[vmlinux_path__nr_entries] = NULL;
1667 }
1668 1626
1669 free(vmlinux_path); 1627 zfree(&vmlinux_path);
1670 vmlinux_path = NULL;
1671} 1628}
1672 1629
1673static int vmlinux_path__init(void) 1630static int vmlinux_path__init(void)
@@ -1719,7 +1676,7 @@ out_fail:
1719 return -1; 1676 return -1;
1720} 1677}
1721 1678
1722static int setup_list(struct strlist **list, const char *list_str, 1679int setup_list(struct strlist **list, const char *list_str,
1723 const char *list_name) 1680 const char *list_name)
1724{ 1681{
1725 if (list_str == NULL) 1682 if (list_str == NULL)
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 07de8fea2f48..fffe2888a1c7 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -52,6 +52,11 @@ static inline char *bfd_demangle(void __maybe_unused *v,
52# define PERF_ELF_C_READ_MMAP ELF_C_READ 52# define PERF_ELF_C_READ_MMAP ELF_C_READ
53#endif 53#endif
54 54
55#ifdef HAVE_LIBELF_SUPPORT
56extern Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
57 GElf_Shdr *shp, const char *name, size_t *idx);
58#endif
59
55#ifndef DMGL_PARAMS 60#ifndef DMGL_PARAMS
56#define DMGL_PARAMS (1 << 0) /* Include function args */ 61#define DMGL_PARAMS (1 << 0) /* Include function args */
57#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */ 62#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */
@@ -164,6 +169,7 @@ struct mem_info {
164}; 169};
165 170
166struct addr_location { 171struct addr_location {
172 struct machine *machine;
167 struct thread *thread; 173 struct thread *thread;
168 struct map *map; 174 struct map *map;
169 struct symbol *sym; 175 struct symbol *sym;
@@ -206,7 +212,8 @@ bool symsrc__possibly_runtime(struct symsrc *ss);
206 212
207int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter); 213int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter);
208int dso__load_vmlinux(struct dso *dso, struct map *map, 214int dso__load_vmlinux(struct dso *dso, struct map *map,
209 const char *vmlinux, symbol_filter_t filter); 215 const char *vmlinux, bool vmlinux_allocated,
216 symbol_filter_t filter);
210int dso__load_vmlinux_path(struct dso *dso, struct map *map, 217int dso__load_vmlinux_path(struct dso *dso, struct map *map,
211 symbol_filter_t filter); 218 symbol_filter_t filter);
212int dso__load_kallsyms(struct dso *dso, const char *filename, struct map *map, 219int dso__load_kallsyms(struct dso *dso, const char *filename, struct map *map,
@@ -220,9 +227,6 @@ struct symbol *dso__first_symbol(struct dso *dso, enum map_type type);
220 227
221int filename__read_build_id(const char *filename, void *bf, size_t size); 228int filename__read_build_id(const char *filename, void *bf, size_t size);
222int sysfs__read_build_id(const char *filename, void *bf, size_t size); 229int sysfs__read_build_id(const char *filename, void *bf, size_t size);
223int kallsyms__parse(const char *filename, void *arg,
224 int (*process_symbol)(void *arg, const char *name,
225 char type, u64 start));
226int modules__parse(const char *filename, void *arg, 230int modules__parse(const char *filename, void *arg,
227 int (*process_module)(void *arg, const char *name, 231 int (*process_module)(void *arg, const char *name,
228 u64 start)); 232 u64 start));
@@ -240,6 +244,7 @@ size_t symbol__fprintf(struct symbol *sym, FILE *fp);
240bool symbol_type__is_a(char symbol_type, enum map_type map_type); 244bool symbol_type__is_a(char symbol_type, enum map_type map_type);
241bool symbol__restricted_filename(const char *filename, 245bool symbol__restricted_filename(const char *filename,
242 const char *restricted_filename); 246 const char *restricted_filename);
247bool symbol__is_idle(struct symbol *sym);
243 248
244int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss, 249int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss,
245 struct symsrc *runtime_ss, symbol_filter_t filter, 250 struct symsrc *runtime_ss, symbol_filter_t filter,
@@ -273,4 +278,7 @@ void kcore_extract__delete(struct kcore_extract *kce);
273int kcore_copy(const char *from_dir, const char *to_dir); 278int kcore_copy(const char *from_dir, const char *to_dir);
274int compare_proc_modules(const char *from, const char *to); 279int compare_proc_modules(const char *from, const char *to);
275 280
281int setup_list(struct strlist **list, const char *list_str,
282 const char *list_name);
283
276#endif /* __PERF_SYMBOL */ 284#endif /* __PERF_SYMBOL */
diff --git a/tools/perf/util/target.c b/tools/perf/util/target.c
index 3c778a07b7cc..e74c5963dc7a 100644
--- a/tools/perf/util/target.c
+++ b/tools/perf/util/target.c
@@ -55,6 +55,13 @@ enum target_errno target__validate(struct target *target)
55 ret = TARGET_ERRNO__UID_OVERRIDE_SYSTEM; 55 ret = TARGET_ERRNO__UID_OVERRIDE_SYSTEM;
56 } 56 }
57 57
58 /* THREAD and SYSTEM/CPU are mutually exclusive */
59 if (target->per_thread && (target->system_wide || target->cpu_list)) {
60 target->per_thread = false;
61 if (ret == TARGET_ERRNO__SUCCESS)
62 ret = TARGET_ERRNO__SYSTEM_OVERRIDE_THREAD;
63 }
64
58 return ret; 65 return ret;
59} 66}
60 67
@@ -100,6 +107,7 @@ static const char *target__error_str[] = {
100 "UID switch overriding CPU", 107 "UID switch overriding CPU",
101 "PID/TID switch overriding SYSTEM", 108 "PID/TID switch overriding SYSTEM",
102 "UID switch overriding SYSTEM", 109 "UID switch overriding SYSTEM",
110 "SYSTEM/CPU switch overriding PER-THREAD",
103 "Invalid User: %s", 111 "Invalid User: %s",
104 "Problems obtaining information for user %s", 112 "Problems obtaining information for user %s",
105}; 113};
@@ -131,7 +139,8 @@ int target__strerror(struct target *target, int errnum,
131 msg = target__error_str[idx]; 139 msg = target__error_str[idx];
132 140
133 switch (errnum) { 141 switch (errnum) {
134 case TARGET_ERRNO__PID_OVERRIDE_CPU ... TARGET_ERRNO__UID_OVERRIDE_SYSTEM: 142 case TARGET_ERRNO__PID_OVERRIDE_CPU ...
143 TARGET_ERRNO__SYSTEM_OVERRIDE_THREAD:
135 snprintf(buf, buflen, "%s", msg); 144 snprintf(buf, buflen, "%s", msg);
136 break; 145 break;
137 146
diff --git a/tools/perf/util/target.h b/tools/perf/util/target.h
index 2d0c50690892..7381b1ca4041 100644
--- a/tools/perf/util/target.h
+++ b/tools/perf/util/target.h
@@ -12,7 +12,8 @@ struct target {
12 uid_t uid; 12 uid_t uid;
13 bool system_wide; 13 bool system_wide;
14 bool uses_mmap; 14 bool uses_mmap;
15 bool force_per_cpu; 15 bool default_per_cpu;
16 bool per_thread;
16}; 17};
17 18
18enum target_errno { 19enum target_errno {
@@ -33,6 +34,7 @@ enum target_errno {
33 TARGET_ERRNO__UID_OVERRIDE_CPU, 34 TARGET_ERRNO__UID_OVERRIDE_CPU,
34 TARGET_ERRNO__PID_OVERRIDE_SYSTEM, 35 TARGET_ERRNO__PID_OVERRIDE_SYSTEM,
35 TARGET_ERRNO__UID_OVERRIDE_SYSTEM, 36 TARGET_ERRNO__UID_OVERRIDE_SYSTEM,
37 TARGET_ERRNO__SYSTEM_OVERRIDE_THREAD,
36 38
37 /* for target__parse_uid() */ 39 /* for target__parse_uid() */
38 TARGET_ERRNO__INVALID_UID, 40 TARGET_ERRNO__INVALID_UID,
@@ -61,4 +63,17 @@ static inline bool target__none(struct target *target)
61 return !target__has_task(target) && !target__has_cpu(target); 63 return !target__has_task(target) && !target__has_cpu(target);
62} 64}
63 65
66static inline bool target__uses_dummy_map(struct target *target)
67{
68 bool use_dummy = false;
69
70 if (target->default_per_cpu)
71 use_dummy = target->per_thread ? true : false;
72 else if (target__has_task(target) ||
73 (!target__has_cpu(target) && !target->uses_mmap))
74 use_dummy = true;
75
76 return use_dummy;
77}
78
64#endif /* _PERF_TARGET_H */ 79#endif /* _PERF_TARGET_H */
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index cd8e2f592719..0358882c8910 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -66,18 +66,20 @@ struct comm *thread__comm(const struct thread *thread)
66int thread__set_comm(struct thread *thread, const char *str, u64 timestamp) 66int thread__set_comm(struct thread *thread, const char *str, u64 timestamp)
67{ 67{
68 struct comm *new, *curr = thread__comm(thread); 68 struct comm *new, *curr = thread__comm(thread);
69 int err;
69 70
70 /* Override latest entry if it had no specific time coverage */ 71 /* Override latest entry if it had no specific time coverage */
71 if (!curr->start) { 72 if (!curr->start) {
72 comm__override(curr, str, timestamp); 73 err = comm__override(curr, str, timestamp);
73 return 0; 74 if (err)
75 return err;
76 } else {
77 new = comm__new(str, timestamp);
78 if (!new)
79 return -ENOMEM;
80 list_add(&new->list, &thread->comm_list);
74 } 81 }
75 82
76 new = comm__new(str, timestamp);
77 if (!new)
78 return -ENOMEM;
79
80 list_add(&new->list, &thread->comm_list);
81 thread->comm_set = true; 83 thread->comm_set = true;
82 84
83 return 0; 85 return 0;
@@ -127,7 +129,7 @@ int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp)
127 if (!comm) 129 if (!comm)
128 return -ENOMEM; 130 return -ENOMEM;
129 err = thread__set_comm(thread, comm, timestamp); 131 err = thread__set_comm(thread, comm, timestamp);
130 if (!err) 132 if (err)
131 return err; 133 return err;
132 thread->comm_set = true; 134 thread->comm_set = true;
133 } 135 }
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 897c1b2a750a..5b856bf942e1 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -6,6 +6,7 @@
6#include <unistd.h> 6#include <unistd.h>
7#include <sys/types.h> 7#include <sys/types.h>
8#include "symbol.h" 8#include "symbol.h"
9#include <strlist.h>
9 10
10struct thread { 11struct thread {
11 union { 12 union {
@@ -66,4 +67,15 @@ static inline void thread__set_priv(struct thread *thread, void *p)
66{ 67{
67 thread->priv = p; 68 thread->priv = p;
68} 69}
70
71static inline bool thread__is_filtered(struct thread *thread)
72{
73 if (symbol_conf.comm_list &&
74 !strlist__has_entry(symbol_conf.comm_list, thread__comm_str(thread))) {
75 return true;
76 }
77
78 return false;
79}
80
69#endif /* __PERF_THREAD_H */ 81#endif /* __PERF_THREAD_H */
diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c
index 9b5f856cc280..5d3215912105 100644
--- a/tools/perf/util/thread_map.c
+++ b/tools/perf/util/thread_map.c
@@ -9,6 +9,7 @@
9#include "strlist.h" 9#include "strlist.h"
10#include <string.h> 10#include <string.h>
11#include "thread_map.h" 11#include "thread_map.h"
12#include "util.h"
12 13
13/* Skip "." and ".." directories */ 14/* Skip "." and ".." directories */
14static int filter(const struct dirent *dir) 15static int filter(const struct dirent *dir)
@@ -40,7 +41,7 @@ struct thread_map *thread_map__new_by_pid(pid_t pid)
40 } 41 }
41 42
42 for (i=0; i<items; i++) 43 for (i=0; i<items; i++)
43 free(namelist[i]); 44 zfree(&namelist[i]);
44 free(namelist); 45 free(namelist);
45 46
46 return threads; 47 return threads;
@@ -117,7 +118,7 @@ struct thread_map *thread_map__new_by_uid(uid_t uid)
117 threads->map[threads->nr + i] = atoi(namelist[i]->d_name); 118 threads->map[threads->nr + i] = atoi(namelist[i]->d_name);
118 119
119 for (i = 0; i < items; i++) 120 for (i = 0; i < items; i++)
120 free(namelist[i]); 121 zfree(&namelist[i]);
121 free(namelist); 122 free(namelist);
122 123
123 threads->nr += items; 124 threads->nr += items;
@@ -134,12 +135,11 @@ out_free_threads:
134 135
135out_free_namelist: 136out_free_namelist:
136 for (i = 0; i < items; i++) 137 for (i = 0; i < items; i++)
137 free(namelist[i]); 138 zfree(&namelist[i]);
138 free(namelist); 139 free(namelist);
139 140
140out_free_closedir: 141out_free_closedir:
141 free(threads); 142 zfree(&threads);
142 threads = NULL;
143 goto out_closedir; 143 goto out_closedir;
144} 144}
145 145
@@ -194,7 +194,7 @@ static struct thread_map *thread_map__new_by_pid_str(const char *pid_str)
194 194
195 for (i = 0; i < items; i++) { 195 for (i = 0; i < items; i++) {
196 threads->map[j++] = atoi(namelist[i]->d_name); 196 threads->map[j++] = atoi(namelist[i]->d_name);
197 free(namelist[i]); 197 zfree(&namelist[i]);
198 } 198 }
199 threads->nr = total_tasks; 199 threads->nr = total_tasks;
200 free(namelist); 200 free(namelist);
@@ -206,12 +206,11 @@ out:
206 206
207out_free_namelist: 207out_free_namelist:
208 for (i = 0; i < items; i++) 208 for (i = 0; i < items; i++)
209 free(namelist[i]); 209 zfree(&namelist[i]);
210 free(namelist); 210 free(namelist);
211 211
212out_free_threads: 212out_free_threads:
213 free(threads); 213 zfree(&threads);
214 threads = NULL;
215 goto out; 214 goto out;
216} 215}
217 216
@@ -262,8 +261,7 @@ out:
262 return threads; 261 return threads;
263 262
264out_free_threads: 263out_free_threads:
265 free(threads); 264 zfree(&threads);
266 threads = NULL;
267 goto out; 265 goto out;
268} 266}
269 267
diff --git a/tools/perf/util/top.c b/tools/perf/util/top.c
index ce793c7dd23c..8e517def925b 100644
--- a/tools/perf/util/top.c
+++ b/tools/perf/util/top.c
@@ -26,7 +26,7 @@ size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size)
26 float samples_per_sec; 26 float samples_per_sec;
27 float ksamples_per_sec; 27 float ksamples_per_sec;
28 float esamples_percent; 28 float esamples_percent;
29 struct perf_record_opts *opts = &top->record_opts; 29 struct record_opts *opts = &top->record_opts;
30 struct target *target = &opts->target; 30 struct target *target = &opts->target;
31 size_t ret = 0; 31 size_t ret = 0;
32 32
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h
index 88cfeaff600b..dab14d0ad3d0 100644
--- a/tools/perf/util/top.h
+++ b/tools/perf/util/top.h
@@ -14,7 +14,7 @@ struct perf_session;
14struct perf_top { 14struct perf_top {
15 struct perf_tool tool; 15 struct perf_tool tool;
16 struct perf_evlist *evlist; 16 struct perf_evlist *evlist;
17 struct perf_record_opts record_opts; 17 struct record_opts record_opts;
18 /* 18 /*
19 * Symbols will be added here in perf_event__process_sample and will 19 * Symbols will be added here in perf_event__process_sample and will
20 * get out after decayed. 20 * get out after decayed.
diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c
index f3c9e551bd35..7e6fcfe8b438 100644
--- a/tools/perf/util/trace-event-info.c
+++ b/tools/perf/util/trace-event-info.c
@@ -38,7 +38,7 @@
38 38
39#include "../perf.h" 39#include "../perf.h"
40#include "trace-event.h" 40#include "trace-event.h"
41#include <lk/debugfs.h> 41#include <api/fs/debugfs.h>
42#include "evsel.h" 42#include "evsel.h"
43 43
44#define VERSION "0.5" 44#define VERSION "0.5"
@@ -397,8 +397,8 @@ put_tracepoints_path(struct tracepoint_path *tps)
397 struct tracepoint_path *t = tps; 397 struct tracepoint_path *t = tps;
398 398
399 tps = tps->next; 399 tps = tps->next;
400 free(t->name); 400 zfree(&t->name);
401 free(t->system); 401 zfree(&t->system);
402 free(t); 402 free(t);
403 } 403 }
404} 404}
@@ -562,10 +562,8 @@ out:
562 output_fd = fd; 562 output_fd = fd;
563 } 563 }
564 564
565 if (err) { 565 if (err)
566 free(tdata); 566 zfree(&tdata);
567 tdata = NULL;
568 }
569 567
570 put_tracepoints_path(tps); 568 put_tracepoints_path(tps);
571 return tdata; 569 return tdata;
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index 6681f71f2f95..e0d6d07f6848 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -28,19 +28,6 @@
28#include "util.h" 28#include "util.h"
29#include "trace-event.h" 29#include "trace-event.h"
30 30
31struct pevent *read_trace_init(int file_bigendian, int host_bigendian)
32{
33 struct pevent *pevent = pevent_alloc();
34
35 if (pevent != NULL) {
36 pevent_set_flag(pevent, PEVENT_NSEC_OUTPUT);
37 pevent_set_file_bigendian(pevent, file_bigendian);
38 pevent_set_host_bigendian(pevent, host_bigendian);
39 }
40
41 return pevent;
42}
43
44static int get_common_field(struct scripting_context *context, 31static int get_common_field(struct scripting_context *context,
45 int *offset, int *size, const char *type) 32 int *offset, int *size, const char *type)
46{ 33{
diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c
index f2112270c663..e113e180c48f 100644
--- a/tools/perf/util/trace-event-read.c
+++ b/tools/perf/util/trace-event-read.c
@@ -343,7 +343,7 @@ static int read_event_files(struct pevent *pevent)
343 return 0; 343 return 0;
344} 344}
345 345
346ssize_t trace_report(int fd, struct pevent **ppevent, bool __repipe) 346ssize_t trace_report(int fd, struct trace_event *tevent, bool __repipe)
347{ 347{
348 char buf[BUFSIZ]; 348 char buf[BUFSIZ];
349 char test[] = { 23, 8, 68 }; 349 char test[] = { 23, 8, 68 };
@@ -356,11 +356,9 @@ ssize_t trace_report(int fd, struct pevent **ppevent, bool __repipe)
356 int host_bigendian; 356 int host_bigendian;
357 int file_long_size; 357 int file_long_size;
358 int file_page_size; 358 int file_page_size;
359 struct pevent *pevent; 359 struct pevent *pevent = NULL;
360 int err; 360 int err;
361 361
362 *ppevent = NULL;
363
364 repipe = __repipe; 362 repipe = __repipe;
365 input_fd = fd; 363 input_fd = fd;
366 364
@@ -390,12 +388,17 @@ ssize_t trace_report(int fd, struct pevent **ppevent, bool __repipe)
390 file_bigendian = buf[0]; 388 file_bigendian = buf[0];
391 host_bigendian = bigendian(); 389 host_bigendian = bigendian();
392 390
393 pevent = read_trace_init(file_bigendian, host_bigendian); 391 if (trace_event__init(tevent)) {
394 if (pevent == NULL) { 392 pr_debug("trace_event__init failed");
395 pr_debug("read_trace_init failed");
396 goto out; 393 goto out;
397 } 394 }
398 395
396 pevent = tevent->pevent;
397
398 pevent_set_flag(pevent, PEVENT_NSEC_OUTPUT);
399 pevent_set_file_bigendian(pevent, file_bigendian);
400 pevent_set_host_bigendian(pevent, host_bigendian);
401
399 if (do_read(buf, 1) < 0) 402 if (do_read(buf, 1) < 0)
400 goto out; 403 goto out;
401 file_long_size = buf[0]; 404 file_long_size = buf[0];
@@ -432,11 +435,10 @@ ssize_t trace_report(int fd, struct pevent **ppevent, bool __repipe)
432 pevent_print_printk(pevent); 435 pevent_print_printk(pevent);
433 } 436 }
434 437
435 *ppevent = pevent;
436 pevent = NULL; 438 pevent = NULL;
437 439
438out: 440out:
439 if (pevent) 441 if (pevent)
440 pevent_free(pevent); 442 trace_event__cleanup(tevent);
441 return size; 443 return size;
442} 444}
diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c
index 95199e4eea97..57aaccc1692e 100644
--- a/tools/perf/util/trace-event-scripting.c
+++ b/tools/perf/util/trace-event-scripting.c
@@ -38,9 +38,8 @@ static int stop_script_unsupported(void)
38static void process_event_unsupported(union perf_event *event __maybe_unused, 38static void process_event_unsupported(union perf_event *event __maybe_unused,
39 struct perf_sample *sample __maybe_unused, 39 struct perf_sample *sample __maybe_unused,
40 struct perf_evsel *evsel __maybe_unused, 40 struct perf_evsel *evsel __maybe_unused,
41 struct machine *machine __maybe_unused,
42 struct thread *thread __maybe_unused, 41 struct thread *thread __maybe_unused,
43 struct addr_location *al __maybe_unused) 42 struct addr_location *al __maybe_unused)
44{ 43{
45} 44}
46 45
diff --git a/tools/perf/util/trace-event.c b/tools/perf/util/trace-event.c
new file mode 100644
index 000000000000..6322d37164c5
--- /dev/null
+++ b/tools/perf/util/trace-event.c
@@ -0,0 +1,82 @@
1
2#include <stdio.h>
3#include <unistd.h>
4#include <stdlib.h>
5#include <errno.h>
6#include <sys/types.h>
7#include <sys/stat.h>
8#include <fcntl.h>
9#include <linux/kernel.h>
10#include <traceevent/event-parse.h>
11#include "trace-event.h"
12#include "util.h"
13
14/*
15 * global trace_event object used by trace_event__tp_format
16 *
17 * TODO There's no cleanup call for this. Add some sort of
18 * __exit function support and call trace_event__cleanup
19 * there.
20 */
21static struct trace_event tevent;
22
23int trace_event__init(struct trace_event *t)
24{
25 struct pevent *pevent = pevent_alloc();
26
27 if (pevent) {
28 t->plugin_list = traceevent_load_plugins(pevent);
29 t->pevent = pevent;
30 }
31
32 return pevent ? 0 : -1;
33}
34
35void trace_event__cleanup(struct trace_event *t)
36{
37 traceevent_unload_plugins(t->plugin_list, t->pevent);
38 pevent_free(t->pevent);
39}
40
41static struct event_format*
42tp_format(const char *sys, const char *name)
43{
44 struct pevent *pevent = tevent.pevent;
45 struct event_format *event = NULL;
46 char path[PATH_MAX];
47 size_t size;
48 char *data;
49
50 scnprintf(path, PATH_MAX, "%s/%s/%s/format",
51 tracing_events_path, sys, name);
52
53 if (filename__read_str(path, &data, &size))
54 return NULL;
55
56 pevent_parse_format(pevent, &event, data, size, sys);
57
58 free(data);
59 return event;
60}
61
62struct event_format*
63trace_event__tp_format(const char *sys, const char *name)
64{
65 static bool initialized;
66
67 if (!initialized) {
68 int be = traceevent_host_bigendian();
69 struct pevent *pevent;
70
71 if (trace_event__init(&tevent))
72 return NULL;
73
74 pevent = tevent.pevent;
75 pevent_set_flag(pevent, PEVENT_NSEC_OUTPUT);
76 pevent_set_file_bigendian(pevent, be);
77 pevent_set_host_bigendian(pevent, be);
78 initialized = true;
79 }
80
81 return tp_format(sys, name);
82}
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index 04df63114109..7b6d68688327 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -3,17 +3,26 @@
3 3
4#include <traceevent/event-parse.h> 4#include <traceevent/event-parse.h>
5#include "parse-events.h" 5#include "parse-events.h"
6#include "session.h"
7 6
8struct machine; 7struct machine;
9struct perf_sample; 8struct perf_sample;
10union perf_event; 9union perf_event;
11struct perf_tool; 10struct perf_tool;
12struct thread; 11struct thread;
12struct plugin_list;
13
14struct trace_event {
15 struct pevent *pevent;
16 struct plugin_list *plugin_list;
17};
18
19int trace_event__init(struct trace_event *t);
20void trace_event__cleanup(struct trace_event *t);
21struct event_format*
22trace_event__tp_format(const char *sys, const char *name);
13 23
14int bigendian(void); 24int bigendian(void);
15 25
16struct pevent *read_trace_init(int file_bigendian, int host_bigendian);
17void event_format__print(struct event_format *event, 26void event_format__print(struct event_format *event,
18 int cpu, void *data, int size); 27 int cpu, void *data, int size);
19 28
@@ -27,7 +36,7 @@ raw_field_value(struct event_format *event, const char *name, void *data);
27void parse_proc_kallsyms(struct pevent *pevent, char *file, unsigned int size); 36void parse_proc_kallsyms(struct pevent *pevent, char *file, unsigned int size);
28void parse_ftrace_printk(struct pevent *pevent, char *file, unsigned int size); 37void parse_ftrace_printk(struct pevent *pevent, char *file, unsigned int size);
29 38
30ssize_t trace_report(int fd, struct pevent **pevent, bool repipe); 39ssize_t trace_report(int fd, struct trace_event *tevent, bool repipe);
31 40
32struct event_format *trace_find_next_event(struct pevent *pevent, 41struct event_format *trace_find_next_event(struct pevent *pevent,
33 struct event_format *event); 42 struct event_format *event);
@@ -59,7 +68,6 @@ struct scripting_ops {
59 void (*process_event) (union perf_event *event, 68 void (*process_event) (union perf_event *event,
60 struct perf_sample *sample, 69 struct perf_sample *sample,
61 struct perf_evsel *evsel, 70 struct perf_evsel *evsel,
62 struct machine *machine,
63 struct thread *thread, 71 struct thread *thread,
64 struct addr_location *al); 72 struct addr_location *al);
65 int (*generate_script) (struct pevent *pevent, const char *outfile); 73 int (*generate_script) (struct pevent *pevent, const char *outfile);
diff --git a/tools/perf/util/unwind.c b/tools/perf/util/unwind.c
index 0efd5393de85..742f23bf35ff 100644
--- a/tools/perf/util/unwind.c
+++ b/tools/perf/util/unwind.c
@@ -28,6 +28,7 @@
28#include "session.h" 28#include "session.h"
29#include "perf_regs.h" 29#include "perf_regs.h"
30#include "unwind.h" 30#include "unwind.h"
31#include "symbol.h"
31#include "util.h" 32#include "util.h"
32 33
33extern int 34extern int
@@ -158,23 +159,6 @@ static int __dw_read_encoded_value(u8 **p, u8 *end, u64 *val,
158 __v; \ 159 __v; \
159 }) 160 })
160 161
161static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
162 GElf_Shdr *shp, const char *name)
163{
164 Elf_Scn *sec = NULL;
165
166 while ((sec = elf_nextscn(elf, sec)) != NULL) {
167 char *str;
168
169 gelf_getshdr(sec, shp);
170 str = elf_strptr(elf, ep->e_shstrndx, shp->sh_name);
171 if (!strcmp(name, str))
172 break;
173 }
174
175 return sec;
176}
177
178static u64 elf_section_offset(int fd, const char *name) 162static u64 elf_section_offset(int fd, const char *name)
179{ 163{
180 Elf *elf; 164 Elf *elf;
@@ -190,7 +174,7 @@ static u64 elf_section_offset(int fd, const char *name)
190 if (gelf_getehdr(elf, &ehdr) == NULL) 174 if (gelf_getehdr(elf, &ehdr) == NULL)
191 break; 175 break;
192 176
193 if (!elf_section_by_name(elf, &ehdr, &shdr, name)) 177 if (!elf_section_by_name(elf, &ehdr, &shdr, name, NULL))
194 break; 178 break;
195 179
196 offset = shdr.sh_offset; 180 offset = shdr.sh_offset;
@@ -340,10 +324,10 @@ find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
340 /* Check the .debug_frame section for unwinding info */ 324 /* Check the .debug_frame section for unwinding info */
341 if (!read_unwind_spec_debug_frame(map->dso, ui->machine, &segbase)) { 325 if (!read_unwind_spec_debug_frame(map->dso, ui->machine, &segbase)) {
342 memset(&di, 0, sizeof(di)); 326 memset(&di, 0, sizeof(di));
343 dwarf_find_debug_frame(0, &di, ip, 0, map->dso->name, 327 if (dwarf_find_debug_frame(0, &di, ip, 0, map->dso->name,
344 map->start, map->end); 328 map->start, map->end))
345 return dwarf_search_unwind_table(as, ip, &di, pi, 329 return dwarf_search_unwind_table(as, ip, &di, pi,
346 need_unwind_info, arg); 330 need_unwind_info, arg);
347 } 331 }
348#endif 332#endif
349 333
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 28a0a89c1f73..42ad667bb317 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -1,11 +1,17 @@
1#include "../perf.h" 1#include "../perf.h"
2#include "util.h" 2#include "util.h"
3#include "fs.h"
3#include <sys/mman.h> 4#include <sys/mman.h>
4#ifdef HAVE_BACKTRACE_SUPPORT 5#ifdef HAVE_BACKTRACE_SUPPORT
5#include <execinfo.h> 6#include <execinfo.h>
6#endif 7#endif
7#include <stdio.h> 8#include <stdio.h>
8#include <stdlib.h> 9#include <stdlib.h>
10#include <string.h>
11#include <errno.h>
12#include <limits.h>
13#include <byteswap.h>
14#include <linux/kernel.h>
9 15
10/* 16/*
11 * XXX We need to find a better place for these things... 17 * XXX We need to find a better place for these things...
@@ -151,21 +157,40 @@ unsigned long convert_unit(unsigned long value, char *unit)
151 return value; 157 return value;
152} 158}
153 159
154int readn(int fd, void *buf, size_t n) 160static ssize_t ion(bool is_read, int fd, void *buf, size_t n)
155{ 161{
156 void *buf_start = buf; 162 void *buf_start = buf;
163 size_t left = n;
157 164
158 while (n) { 165 while (left) {
159 int ret = read(fd, buf, n); 166 ssize_t ret = is_read ? read(fd, buf, left) :
167 write(fd, buf, left);
160 168
161 if (ret <= 0) 169 if (ret <= 0)
162 return ret; 170 return ret;
163 171
164 n -= ret; 172 left -= ret;
165 buf += ret; 173 buf += ret;
166 } 174 }
167 175
168 return buf - buf_start; 176 BUG_ON((size_t)(buf - buf_start) != n);
177 return n;
178}
179
180/*
181 * Read exactly 'n' bytes or return an error.
182 */
183ssize_t readn(int fd, void *buf, size_t n)
184{
185 return ion(true, fd, buf, n);
186}
187
188/*
189 * Write exactly 'n' bytes or return an error.
190 */
191ssize_t writen(int fd, void *buf, size_t n)
192{
193 return ion(false, fd, buf, n);
169} 194}
170 195
171size_t hex_width(u64 v) 196size_t hex_width(u64 v)
@@ -413,3 +438,102 @@ int filename__read_int(const char *filename, int *value)
413 close(fd); 438 close(fd);
414 return err; 439 return err;
415} 440}
441
442int filename__read_str(const char *filename, char **buf, size_t *sizep)
443{
444 size_t size = 0, alloc_size = 0;
445 void *bf = NULL, *nbf;
446 int fd, n, err = 0;
447
448 fd = open(filename, O_RDONLY);
449 if (fd < 0)
450 return -errno;
451
452 do {
453 if (size == alloc_size) {
454 alloc_size += BUFSIZ;
455 nbf = realloc(bf, alloc_size);
456 if (!nbf) {
457 err = -ENOMEM;
458 break;
459 }
460
461 bf = nbf;
462 }
463
464 n = read(fd, bf + size, alloc_size - size);
465 if (n < 0) {
466 if (size) {
467 pr_warning("read failed %d: %s\n",
468 errno, strerror(errno));
469 err = 0;
470 } else
471 err = -errno;
472
473 break;
474 }
475
476 size += n;
477 } while (n > 0);
478
479 if (!err) {
480 *sizep = size;
481 *buf = bf;
482 } else
483 free(bf);
484
485 close(fd);
486 return err;
487}
488
489const char *get_filename_for_perf_kvm(void)
490{
491 const char *filename;
492
493 if (perf_host && !perf_guest)
494 filename = strdup("perf.data.host");
495 else if (!perf_host && perf_guest)
496 filename = strdup("perf.data.guest");
497 else
498 filename = strdup("perf.data.kvm");
499
500 return filename;
501}
502
503int perf_event_paranoid(void)
504{
505 char path[PATH_MAX];
506 const char *procfs = procfs__mountpoint();
507 int value;
508
509 if (!procfs)
510 return INT_MAX;
511
512 scnprintf(path, PATH_MAX, "%s/sys/kernel/perf_event_paranoid", procfs);
513
514 if (filename__read_int(path, &value))
515 return INT_MAX;
516
517 return value;
518}
519
520void mem_bswap_32(void *src, int byte_size)
521{
522 u32 *m = src;
523 while (byte_size > 0) {
524 *m = bswap_32(*m);
525 byte_size -= sizeof(u32);
526 ++m;
527 }
528}
529
530void mem_bswap_64(void *src, int byte_size)
531{
532 u64 *m = src;
533
534 while (byte_size > 0) {
535 *m = bswap_64(*m);
536 byte_size -= sizeof(u64);
537 ++m;
538 }
539}
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index c8f362daba87..6995d66f225c 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -71,8 +71,9 @@
71#include <linux/magic.h> 71#include <linux/magic.h>
72#include "types.h" 72#include "types.h"
73#include <sys/ttydefaults.h> 73#include <sys/ttydefaults.h>
74#include <lk/debugfs.h> 74#include <api/fs/debugfs.h>
75#include <termios.h> 75#include <termios.h>
76#include <linux/bitops.h>
76 77
77extern const char *graph_line; 78extern const char *graph_line;
78extern const char *graph_dotted_line; 79extern const char *graph_dotted_line;
@@ -185,6 +186,8 @@ static inline void *zalloc(size_t size)
185 return calloc(1, size); 186 return calloc(1, size);
186} 187}
187 188
189#define zfree(ptr) ({ free(*ptr); *ptr = NULL; })
190
188static inline int has_extension(const char *filename, const char *ext) 191static inline int has_extension(const char *filename, const char *ext)
189{ 192{
190 size_t len = strlen(filename); 193 size_t len = strlen(filename);
@@ -253,7 +256,8 @@ bool strlazymatch(const char *str, const char *pat);
253int strtailcmp(const char *s1, const char *s2); 256int strtailcmp(const char *s1, const char *s2);
254char *strxfrchar(char *s, char from, char to); 257char *strxfrchar(char *s, char from, char to);
255unsigned long convert_unit(unsigned long value, char *unit); 258unsigned long convert_unit(unsigned long value, char *unit);
256int readn(int fd, void *buf, size_t size); 259ssize_t readn(int fd, void *buf, size_t n);
260ssize_t writen(int fd, void *buf, size_t n);
257 261
258struct perf_event_attr; 262struct perf_event_attr;
259 263
@@ -280,6 +284,17 @@ static inline unsigned next_pow2(unsigned x)
280 return 1ULL << (32 - __builtin_clz(x - 1)); 284 return 1ULL << (32 - __builtin_clz(x - 1));
281} 285}
282 286
287static inline unsigned long next_pow2_l(unsigned long x)
288{
289#if BITS_PER_LONG == 64
290 if (x <= (1UL << 31))
291 return next_pow2(x);
292 return (unsigned long)next_pow2(x >> 32) << 32;
293#else
294 return next_pow2(x);
295#endif
296}
297
283size_t hex_width(u64 v); 298size_t hex_width(u64 v);
284int hex2u64(const char *ptr, u64 *val); 299int hex2u64(const char *ptr, u64 *val);
285 300
@@ -307,4 +322,11 @@ char *get_srcline(struct dso *dso, unsigned long addr);
307void free_srcline(char *srcline); 322void free_srcline(char *srcline);
308 323
309int filename__read_int(const char *filename, int *value); 324int filename__read_int(const char *filename, int *value);
325int filename__read_str(const char *filename, char **buf, size_t *sizep);
326int perf_event_paranoid(void);
327
328void mem_bswap_64(void *src, int byte_size);
329void mem_bswap_32(void *src, int byte_size);
330
331const char *get_filename_for_perf_kvm(void);
310#endif /* GIT_COMPAT_UTIL_H */ 332#endif /* GIT_COMPAT_UTIL_H */
diff --git a/tools/perf/util/values.c b/tools/perf/util/values.c
index 697c8b4e59cc..0fb3c1fcd3e6 100644
--- a/tools/perf/util/values.c
+++ b/tools/perf/util/values.c
@@ -31,14 +31,14 @@ void perf_read_values_destroy(struct perf_read_values *values)
31 return; 31 return;
32 32
33 for (i = 0; i < values->threads; i++) 33 for (i = 0; i < values->threads; i++)
34 free(values->value[i]); 34 zfree(&values->value[i]);
35 free(values->value); 35 zfree(&values->value);
36 free(values->pid); 36 zfree(&values->pid);
37 free(values->tid); 37 zfree(&values->tid);
38 free(values->counterrawid); 38 zfree(&values->counterrawid);
39 for (i = 0; i < values->counters; i++) 39 for (i = 0; i < values->counters; i++)
40 free(values->countername[i]); 40 zfree(&values->countername[i]);
41 free(values->countername); 41 zfree(&values->countername);
42} 42}
43 43
44static void perf_read_values__enlarge_threads(struct perf_read_values *values) 44static void perf_read_values__enlarge_threads(struct perf_read_values *values)
diff --git a/tools/perf/util/vdso.c b/tools/perf/util/vdso.c
index 39159822d58f..0ddb3b8a89ec 100644
--- a/tools/perf/util/vdso.c
+++ b/tools/perf/util/vdso.c
@@ -103,7 +103,7 @@ struct dso *vdso__dso_findnew(struct list_head *head)
103 dso = dso__new(VDSO__MAP_NAME); 103 dso = dso__new(VDSO__MAP_NAME);
104 if (dso != NULL) { 104 if (dso != NULL) {
105 dsos__add(head, dso); 105 dsos__add(head, dso);
106 dso__set_long_name(dso, file); 106 dso__set_long_name(dso, file, false);
107 } 107 }
108 } 108 }
109 109