aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2009-08-14 01:41:02 -0400
committerTejun Heo <tj@kernel.org>2009-08-14 01:45:31 -0400
commit384be2b18a5f9475eab9ca2bdfa95cc1a04ef59c (patch)
tree04c93f391a1b65c8bf8d7ba8643c07d26c26590a /tools
parenta76761b621bcd8336065c4fe3a74f046858bc34c (diff)
parent142d44b0dd6741a64a7bdbe029110e7c1dcf1d23 (diff)
Merge branch 'percpu-for-linus' into percpu-for-next
Conflicts: arch/sparc/kernel/smp_64.c arch/x86/kernel/cpu/perf_counter.c arch/x86/kernel/setup_percpu.c drivers/cpufreq/cpufreq_ondemand.c mm/percpu.c Conflicts in core and arch percpu codes are mostly from commit ed78e1e078dd44249f88b1dd8c76dafb39567161 which substituted many num_possible_cpus() with nr_cpu_ids. As for-next branch has moved all the first chunk allocators into mm/percpu.c, the changes are moved from arch code to mm/percpu.c. Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/Documentation/perf-examples.txt225
-rw-r--r--tools/perf/Documentation/perf-record.txt60
-rw-r--r--tools/perf/Documentation/perf-report.txt15
-rw-r--r--tools/perf/Documentation/perf-stat.txt2
-rw-r--r--tools/perf/Documentation/perf-top.txt112
-rw-r--r--tools/perf/Makefile60
-rw-r--r--tools/perf/builtin-annotate.c93
-rw-r--r--tools/perf/builtin-help.c6
-rw-r--r--tools/perf/builtin-list.c5
-rw-r--r--tools/perf/builtin-record.c125
-rw-r--r--tools/perf/builtin-report.c751
-rw-r--r--tools/perf/builtin-stat.c56
-rw-r--r--tools/perf/builtin-top.c625
-rw-r--r--tools/perf/perf.c82
-rw-r--r--tools/perf/perf.h16
-rw-r--r--tools/perf/util/alias.c2
-rw-r--r--tools/perf/util/cache.h2
-rw-r--r--tools/perf/util/callchain.c263
-rw-r--r--tools/perf/util/callchain.h47
-rw-r--r--tools/perf/util/color.c37
-rw-r--r--tools/perf/util/color.h5
-rw-r--r--tools/perf/util/config.c18
-rw-r--r--tools/perf/util/exec_cmd.c5
-rw-r--r--tools/perf/util/header.c5
-rw-r--r--tools/perf/util/header.h2
-rw-r--r--tools/perf/util/help.c26
-rw-r--r--tools/perf/util/help.h6
-rw-r--r--tools/perf/util/include/asm/system.h1
-rw-r--r--tools/perf/util/include/linux/kernel.h29
-rw-r--r--tools/perf/util/include/linux/list.h18
-rw-r--r--tools/perf/util/include/linux/module.h6
-rw-r--r--tools/perf/util/include/linux/poison.h1
-rw-r--r--tools/perf/util/include/linux/prefetch.h6
-rw-r--r--tools/perf/util/include/linux/rbtree.h1
-rw-r--r--tools/perf/util/list.h603
-rw-r--r--tools/perf/util/module.c509
-rw-r--r--tools/perf/util/module.h53
-rw-r--r--tools/perf/util/parse-events.c465
-rw-r--r--tools/perf/util/parse-events.h6
-rw-r--r--tools/perf/util/parse-options.c5
-rw-r--r--tools/perf/util/parse-options.h27
-rw-r--r--tools/perf/util/quote.c48
-rw-r--r--tools/perf/util/quote.h2
-rw-r--r--tools/perf/util/rbtree.c383
-rw-r--r--tools/perf/util/rbtree.h171
-rw-r--r--tools/perf/util/strbuf.c13
-rw-r--r--tools/perf/util/strbuf.h10
-rw-r--r--tools/perf/util/string.h3
-rw-r--r--tools/perf/util/strlist.c20
-rw-r--r--tools/perf/util/strlist.h13
-rw-r--r--tools/perf/util/symbol.c441
-rw-r--r--tools/perf/util/symbol.h38
-rw-r--r--tools/perf/util/util.h2
-rw-r--r--tools/perf/util/wrapper.c5
54 files changed, 3660 insertions, 1870 deletions
diff --git a/tools/perf/Documentation/perf-examples.txt b/tools/perf/Documentation/perf-examples.txt
new file mode 100644
index 000000000000..8eb6c489fb15
--- /dev/null
+++ b/tools/perf/Documentation/perf-examples.txt
@@ -0,0 +1,225 @@
1
2 ------------------------------
3 ****** perf by examples ******
4 ------------------------------
5
6[ From an e-mail by Ingo Molnar, http://lkml.org/lkml/2009/8/4/346 ]
7
8
9First, discovery/enumeration of available counters can be done via
10'perf list':
11
12titan:~> perf list
13 [...]
14 kmem:kmalloc [Tracepoint event]
15 kmem:kmem_cache_alloc [Tracepoint event]
16 kmem:kmalloc_node [Tracepoint event]
17 kmem:kmem_cache_alloc_node [Tracepoint event]
18 kmem:kfree [Tracepoint event]
19 kmem:kmem_cache_free [Tracepoint event]
20 kmem:mm_page_free_direct [Tracepoint event]
21 kmem:mm_pagevec_free [Tracepoint event]
22 kmem:mm_page_alloc [Tracepoint event]
23 kmem:mm_page_alloc_zone_locked [Tracepoint event]
24 kmem:mm_page_pcpu_drain [Tracepoint event]
25 kmem:mm_page_alloc_extfrag [Tracepoint event]
26
27Then any (or all) of the above event sources can be activated and
28measured. For example the page alloc/free properties of a 'hackbench
29run' are:
30
31 titan:~> perf stat -e kmem:mm_page_pcpu_drain -e kmem:mm_page_alloc
32 -e kmem:mm_pagevec_free -e kmem:mm_page_free_direct ./hackbench 10
33 Time: 0.575
34
35 Performance counter stats for './hackbench 10':
36
37 13857 kmem:mm_page_pcpu_drain
38 27576 kmem:mm_page_alloc
39 6025 kmem:mm_pagevec_free
40 20934 kmem:mm_page_free_direct
41
42 0.613972165 seconds time elapsed
43
44You can observe the statistical properties as well, by using the
45'repeat the workload N times' feature of perf stat:
46
47 titan:~> perf stat --repeat 5 -e kmem:mm_page_pcpu_drain -e
48 kmem:mm_page_alloc -e kmem:mm_pagevec_free -e
49 kmem:mm_page_free_direct ./hackbench 10
50 Time: 0.627
51 Time: 0.644
52 Time: 0.564
53 Time: 0.559
54 Time: 0.626
55
56 Performance counter stats for './hackbench 10' (5 runs):
57
58 12920 kmem:mm_page_pcpu_drain ( +- 3.359% )
59 25035 kmem:mm_page_alloc ( +- 3.783% )
60 6104 kmem:mm_pagevec_free ( +- 0.934% )
61 18376 kmem:mm_page_free_direct ( +- 4.941% )
62
63 0.643954516 seconds time elapsed ( +- 2.363% )
64
65Furthermore, these tracepoints can be used to sample the workload as
66well. For example the page allocations done by a 'git gc' can be
67captured the following way:
68
69 titan:~/git> perf record -f -e kmem:mm_page_alloc -c 1 ./git gc
70 Counting objects: 1148, done.
71 Delta compression using up to 2 threads.
72 Compressing objects: 100% (450/450), done.
73 Writing objects: 100% (1148/1148), done.
74 Total 1148 (delta 690), reused 1148 (delta 690)
75 [ perf record: Captured and wrote 0.267 MB perf.data (~11679 samples) ]
76
77To check which functions generated page allocations:
78
79 titan:~/git> perf report
80 # Samples: 10646
81 #
82 # Overhead Command Shared Object
83 # ........ ............... ..........................
84 #
85 23.57% git-repack /lib64/libc-2.5.so
86 21.81% git /lib64/libc-2.5.so
87 14.59% git ./git
88 11.79% git-repack ./git
89 7.12% git /lib64/ld-2.5.so
90 3.16% git-repack /lib64/libpthread-2.5.so
91 2.09% git-repack /bin/bash
92 1.97% rm /lib64/libc-2.5.so
93 1.39% mv /lib64/ld-2.5.so
94 1.37% mv /lib64/libc-2.5.so
95 1.12% git-repack /lib64/ld-2.5.so
96 0.95% rm /lib64/ld-2.5.so
97 0.90% git-update-serv /lib64/libc-2.5.so
98 0.73% git-update-serv /lib64/ld-2.5.so
99 0.68% perf /lib64/libpthread-2.5.so
100 0.64% git-repack /usr/lib64/libz.so.1.2.3
101
102Or to see it on a more finegrained level:
103
104titan:~/git> perf report --sort comm,dso,symbol
105# Samples: 10646
106#
107# Overhead Command Shared Object Symbol
108# ........ ............... .......................... ......
109#
110 9.35% git-repack ./git [.] insert_obj_hash
111 9.12% git ./git [.] insert_obj_hash
112 7.31% git /lib64/libc-2.5.so [.] memcpy
113 6.34% git-repack /lib64/libc-2.5.so [.] _int_malloc
114 6.24% git-repack /lib64/libc-2.5.so [.] memcpy
115 5.82% git-repack /lib64/libc-2.5.so [.] __GI___fork
116 5.47% git /lib64/libc-2.5.so [.] _int_malloc
117 2.99% git /lib64/libc-2.5.so [.] memset
118
119Furthermore, call-graph sampling can be done too, of page
120allocations - to see precisely what kind of page allocations there
121are:
122
123 titan:~/git> perf record -f -g -e kmem:mm_page_alloc -c 1 ./git gc
124 Counting objects: 1148, done.
125 Delta compression using up to 2 threads.
126 Compressing objects: 100% (450/450), done.
127 Writing objects: 100% (1148/1148), done.
128 Total 1148 (delta 690), reused 1148 (delta 690)
129 [ perf record: Captured and wrote 0.963 MB perf.data (~42069 samples) ]
130
131 titan:~/git> perf report -g
132 # Samples: 10686
133 #
134 # Overhead Command Shared Object
135 # ........ ............... ..........................
136 #
137 23.25% git-repack /lib64/libc-2.5.so
138 |
139 |--50.00%-- _int_free
140 |
141 |--37.50%-- __GI___fork
142 | make_child
143 |
144 |--12.50%-- ptmalloc_unlock_all2
145 | make_child
146 |
147 --6.25%-- __GI_strcpy
148 21.61% git /lib64/libc-2.5.so
149 |
150 |--30.00%-- __GI_read
151 | |
152 | --83.33%-- git_config_from_file
153 | git_config
154 | |
155 [...]
156
157Or you can observe the whole system's page allocations for 10
158seconds:
159
160titan:~/git> perf stat -a -e kmem:mm_page_pcpu_drain -e
161kmem:mm_page_alloc -e kmem:mm_pagevec_free -e
162kmem:mm_page_free_direct sleep 10
163
164 Performance counter stats for 'sleep 10':
165
166 171585 kmem:mm_page_pcpu_drain
167 322114 kmem:mm_page_alloc
168 73623 kmem:mm_pagevec_free
169 254115 kmem:mm_page_free_direct
170
171 10.000591410 seconds time elapsed
172
173Or observe how fluctuating the page allocations are, via statistical
174analysis done over ten 1-second intervals:
175
176 titan:~/git> perf stat --repeat 10 -a -e kmem:mm_page_pcpu_drain -e
177 kmem:mm_page_alloc -e kmem:mm_pagevec_free -e
178 kmem:mm_page_free_direct sleep 1
179
180 Performance counter stats for 'sleep 1' (10 runs):
181
182 17254 kmem:mm_page_pcpu_drain ( +- 3.709% )
183 34394 kmem:mm_page_alloc ( +- 4.617% )
184 7509 kmem:mm_pagevec_free ( +- 4.820% )
185 25653 kmem:mm_page_free_direct ( +- 3.672% )
186
187 1.058135029 seconds time elapsed ( +- 3.089% )
188
189Or you can annotate the recorded 'git gc' run on a per symbol basis
190and check which instructions/source-code generated page allocations:
191
192 titan:~/git> perf annotate __GI___fork
193 ------------------------------------------------
194 Percent | Source code & Disassembly of libc-2.5.so
195 ------------------------------------------------
196 :
197 :
198 : Disassembly of section .plt:
199 : Disassembly of section .text:
200 :
201 : 00000031a2e95560 <__fork>:
202 [...]
203 0.00 : 31a2e95602: b8 38 00 00 00 mov $0x38,%eax
204 0.00 : 31a2e95607: 0f 05 syscall
205 83.42 : 31a2e95609: 48 3d 00 f0 ff ff cmp $0xfffffffffffff000,%rax
206 0.00 : 31a2e9560f: 0f 87 4d 01 00 00 ja 31a2e95762 <__fork+0x202>
207 0.00 : 31a2e95615: 85 c0 test %eax,%eax
208
209( this shows that 83.42% of __GI___fork's page allocations come from
210 the 0x38 system call it performs. )
211
212etc. etc. - a lot more is possible. I could list a dozen of
213other different usecases straight away - neither of which is
214possible via /proc/vmstat.
215
216/proc/vmstat is not in the same league really, in terms of
217expressive power of system analysis and performance
218analysis.
219
220All that the above results needed were those new tracepoints
221in include/tracing/events/kmem.h.
222
223 Ingo
224
225
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 1dbc1eeb4c01..6be696b0a2bb 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -29,13 +29,67 @@ OPTIONS
29 Select the PMU event. Selection can be a symbolic event name 29 Select the PMU event. Selection can be a symbolic event name
30 (use 'perf list' to list all events) or a raw PMU 30 (use 'perf list' to list all events) or a raw PMU
31 event (eventsel+umask) in the form of rNNN where NNN is a 31 event (eventsel+umask) in the form of rNNN where NNN is a
32 hexadecimal event descriptor. 32 hexadecimal event descriptor.
33 33
34-a:: 34-a::
35 system-wide collection 35 System-wide collection.
36 36
37-l:: 37-l::
38 scale counter values 38 Scale counter values.
39
40-p::
41--pid=::
42 Record events on existing pid.
43
44-r::
45--realtime=::
46 Collect data with this RT SCHED_FIFO priority.
47-A::
48--append::
49 Append to the output file to do incremental profiling.
50
51-f::
52--force::
53 Overwrite existing data file.
54
55-c::
56--count=::
57 Event period to sample.
58
59-o::
60--output=::
61 Output file name.
62
63-i::
64--inherit::
65 Child tasks inherit counters.
66-F::
67--freq=::
68 Profile at this frequency.
69
70-m::
71--mmap-pages=::
72 Number of mmap data pages.
73
74-g::
75--call-graph::
76 Do call-graph (stack chain/backtrace) recording.
77
78-v::
79--verbose::
80 Be more verbose (show counter open errors, etc).
81
82-s::
83--stat::
84 Per thread counts.
85
86-d::
87--data::
88 Sample addresses.
89
90-n::
91--no-samples::
92 Don't sample.
39 93
40SEE ALSO 94SEE ALSO
41-------- 95--------
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 8aa3f8c88707..e72e93110782 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -24,6 +24,9 @@ OPTIONS
24--dsos=:: 24--dsos=::
25 Only consider symbols in these dsos. CSV that understands 25 Only consider symbols in these dsos. CSV that understands
26 file://filename entries. 26 file://filename entries.
27-n
28--show-nr-samples
29 Show the number of samples for each symbol
27-C:: 30-C::
28--comms=:: 31--comms=::
29 Only consider symbols in these comms. CSV that understands 32 Only consider symbols in these comms. CSV that understands
@@ -33,6 +36,18 @@ OPTIONS
33 Only consider these symbols. CSV that understands 36 Only consider these symbols. CSV that understands
34 file://filename entries. 37 file://filename entries.
35 38
39-w::
40--field-width=::
41 Force each column width to the provided list, for large terminal
42 readability.
43
44-t::
45--field-separator=::
46
47 Use a special separator character and don't pad with spaces, replacing
48 all occurances of this separator in symbol names (and other output)
49 with a '.' character, that thus it's the only non valid separator.
50
36SEE ALSO 51SEE ALSO
37-------- 52--------
38linkperf:perf-stat[1] 53linkperf:perf-stat[1]
diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index 0d74346d21ab..484080dd5b6f 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -40,7 +40,7 @@ OPTIONS
40-a:: 40-a::
41 system-wide collection 41 system-wide collection
42 42
43-S:: 43-c::
44 scale counter values 44 scale counter values
45 45
46EXAMPLES 46EXAMPLES
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt
index 539d01289725..4a7d558dc309 100644
--- a/tools/perf/Documentation/perf-top.txt
+++ b/tools/perf/Documentation/perf-top.txt
@@ -3,36 +3,122 @@ perf-top(1)
3 3
4NAME 4NAME
5---- 5----
6perf-top - Run a command and profile it 6perf-top - System profiling tool.
7 7
8SYNOPSIS 8SYNOPSIS
9-------- 9--------
10[verse] 10[verse]
11'perf top' [-e <EVENT> | --event=EVENT] [-l] [-a] <command> 11'perf top' [-e <EVENT> | --event=EVENT] [<options>]
12 12
13DESCRIPTION 13DESCRIPTION
14----------- 14-----------
15This command runs a command and gathers a performance counter profile 15This command generates and displays a performance counter profile in realtime.
16from it.
17 16
18 17
19OPTIONS 18OPTIONS
20------- 19-------
21<command>...:: 20-a::
22 Any command you can specify in a shell. 21--all-cpus::
22 System-wide collection. (default)
23
24-c <count>::
25--count=<count>::
26 Event period to sample.
27
28-C <cpu>::
29--CPU=<cpu>::
30 CPU to profile.
31
32-d <seconds>::
33--delay=<seconds>::
34 Number of seconds to delay between refreshes.
23 35
24-e:: 36-e <event>::
25--event=:: 37--event=<event>::
26 Select the PMU event. Selection can be a symbolic event name 38 Select the PMU event. Selection can be a symbolic event name
27 (use 'perf list' to list all events) or a raw PMU 39 (use 'perf list' to list all events) or a raw PMU
28 event (eventsel+umask) in the form of rNNN where NNN is a 40 event (eventsel+umask) in the form of rNNN where NNN is a
29 hexadecimal event descriptor. 41 hexadecimal event descriptor.
30 42
31-a:: 43-E <entries>::
32 system-wide collection 44--entries=<entries>::
45 Display this many functions.
46
47-f <count>::
48--count-filter=<count>::
49 Only display functions with more events than this.
50
51-F <freq>::
52--freq=<freq>::
53 Profile at this frequency.
54
55-i::
56--inherit::
57 Child tasks inherit counters, only makes sens with -p option.
58
59-k <path>::
60--vmlinux=<path>::
61 Path to vmlinux. Required for annotation functionality.
62
63-m <pages>::
64--mmap-pages=<pages>::
65 Number of mmapped data pages.
66
67-p <pid>::
68--pid=<pid>::
69 Profile events on existing pid.
70
71-r <priority>::
72--realtime=<priority>::
73 Collect data with this RT SCHED_FIFO priority.
74
75-s <symbol>::
76--sym-annotate=<symbol>::
77 Annotate this symbol. Requires -k option.
78
79-v::
80--verbose::
81 Be more verbose (show counter open errors, etc).
82
83-z::
84--zero::
85 Zero history across display updates.
86
87INTERACTIVE PROMPTING KEYS
88--------------------------
89
90[d]::
91 Display refresh delay.
92
93[e]::
94 Number of entries to display.
95
96[E]::
97 Event to display when multiple counters are active.
98
99[f]::
100 Profile display filter (>= hit count).
101
102[F]::
103 Annotation display filter (>= % of total).
104
105[s]::
106 Annotate symbol.
107
108[S]::
109 Stop annotation, return to full profile display.
110
111[w]::
112 Toggle between weighted sum and individual count[E]r profile.
113
114[z]::
115 Toggle event count zeroing across display updates.
116
117[qQ]::
118 Quit.
119
120Pressing any unmapped key displays a menu, and prompts for input.
33 121
34-l::
35 scale counter values
36 122
37SEE ALSO 123SEE ALSO
38-------- 124--------
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 9c6d0ae3708e..c045b4271e57 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -158,13 +158,15 @@ uname_P := $(shell sh -c 'uname -p 2>/dev/null || echo not')
158uname_V := $(shell sh -c 'uname -v 2>/dev/null || echo not') 158uname_V := $(shell sh -c 'uname -v 2>/dev/null || echo not')
159 159
160# If we're on a 64-bit kernel, use -m64 160# If we're on a 64-bit kernel, use -m64
161ifneq ($(patsubst %64,%,$(uname_M)),$(uname_M)) 161ifndef NO_64BIT
162 M64 := -m64 162 ifneq ($(patsubst %64,%,$(uname_M)),$(uname_M))
163 M64 := -m64
164 endif
163endif 165endif
164 166
165# CFLAGS and LDFLAGS are for the users to override from the command line. 167# CFLAGS and LDFLAGS are for the users to override from the command line.
166 168
167CFLAGS = $(M64) -ggdb3 -Wall -Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes -std=gnu99 -Wdeclaration-after-statement -Werror -O6 169CFLAGS = $(M64) -ggdb3 -Wall -Wextra -Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes -std=gnu99 -Wdeclaration-after-statement -Werror -O6
168LDFLAGS = -lpthread -lrt -lelf -lm 170LDFLAGS = -lpthread -lrt -lelf -lm
169ALL_CFLAGS = $(CFLAGS) 171ALL_CFLAGS = $(CFLAGS)
170ALL_LDFLAGS = $(LDFLAGS) 172ALL_LDFLAGS = $(LDFLAGS)
@@ -223,7 +225,7 @@ SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__
223# Those must not be GNU-specific; they are shared with perl/ which may 225# Those must not be GNU-specific; they are shared with perl/ which may
224# be built by a different compiler. (Note that this is an artifact now 226# be built by a different compiler. (Note that this is an artifact now
225# but it still might be nice to keep that distinction.) 227# but it still might be nice to keep that distinction.)
226BASIC_CFLAGS = 228BASIC_CFLAGS = -Iutil/include
227BASIC_LDFLAGS = 229BASIC_LDFLAGS =
228 230
229# Guard against environment variables 231# Guard against environment variables
@@ -289,10 +291,11 @@ export PERL_PATH
289LIB_FILE=libperf.a 291LIB_FILE=libperf.a
290 292
291LIB_H += ../../include/linux/perf_counter.h 293LIB_H += ../../include/linux/perf_counter.h
294LIB_H += ../../include/linux/rbtree.h
295LIB_H += ../../include/linux/list.h
296LIB_H += util/include/linux/list.h
292LIB_H += perf.h 297LIB_H += perf.h
293LIB_H += util/types.h 298LIB_H += util/types.h
294LIB_H += util/list.h
295LIB_H += util/rbtree.h
296LIB_H += util/levenshtein.h 299LIB_H += util/levenshtein.h
297LIB_H += util/parse-options.h 300LIB_H += util/parse-options.h
298LIB_H += util/parse-events.h 301LIB_H += util/parse-events.h
@@ -305,6 +308,7 @@ LIB_H += util/strlist.h
305LIB_H += util/run-command.h 308LIB_H += util/run-command.h
306LIB_H += util/sigchain.h 309LIB_H += util/sigchain.h
307LIB_H += util/symbol.h 310LIB_H += util/symbol.h
311LIB_H += util/module.h
308LIB_H += util/color.h 312LIB_H += util/color.h
309 313
310LIB_OBJS += util/abspath.o 314LIB_OBJS += util/abspath.o
@@ -328,6 +332,7 @@ LIB_OBJS += util/usage.o
328LIB_OBJS += util/wrapper.o 332LIB_OBJS += util/wrapper.o
329LIB_OBJS += util/sigchain.o 333LIB_OBJS += util/sigchain.o
330LIB_OBJS += util/symbol.o 334LIB_OBJS += util/symbol.o
335LIB_OBJS += util/module.o
331LIB_OBJS += util/color.o 336LIB_OBJS += util/color.o
332LIB_OBJS += util/pager.o 337LIB_OBJS += util/pager.o
333LIB_OBJS += util/header.o 338LIB_OBJS += util/header.o
@@ -342,7 +347,6 @@ BUILTIN_OBJS += builtin-stat.o
342BUILTIN_OBJS += builtin-top.o 347BUILTIN_OBJS += builtin-top.o
343 348
344PERFLIBS = $(LIB_FILE) 349PERFLIBS = $(LIB_FILE)
345EXTLIBS =
346 350
347# 351#
348# Platform specific tweaks 352# Platform specific tweaks
@@ -371,6 +375,39 @@ ifeq ($(uname_S),Darwin)
371 PTHREAD_LIBS = 375 PTHREAD_LIBS =
372endif 376endif
373 377
378ifneq ($(shell sh -c "(echo '\#include <libelf.h>'; echo 'int main(void) { Elf * elf = elf_begin(0, ELF_C_READ_MMAP, 0); return (long)elf; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -o /dev/null $(ALL_LDFLAGS) > /dev/null 2>&1 && echo y"), y)
379 msg := $(error No libelf.h/libelf found, please install libelf-dev/elfutils-libelf-devel);
380endif
381
382ifdef NO_DEMANGLE
383 BASIC_CFLAGS += -DNO_DEMANGLE
384else
385 has_bfd := $(shell sh -c "(echo '\#include <bfd.h>'; echo 'int main(void) { bfd_demangle(0, 0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o /dev/null $(ALL_LDFLAGS) -lbfd > /dev/null 2>&1 && echo y")
386
387 ifeq ($(has_bfd),y)
388 EXTLIBS += -lbfd
389 else
390 has_bfd_iberty := $(shell sh -c "(echo '\#include <bfd.h>'; echo 'int main(void) { bfd_demangle(0, 0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o /dev/null $(ALL_LDFLAGS) -lbfd -liberty > /dev/null 2>&1 && echo y")
391 ifeq ($(has_bfd_iberty),y)
392 EXTLIBS += -lbfd -liberty
393 else
394 has_bfd_iberty_z := $(shell sh -c "(echo '\#include <bfd.h>'; echo 'int main(void) { bfd_demangle(0, 0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o /dev/null $(ALL_LDFLAGS) -lbfd -liberty -lz > /dev/null 2>&1 && echo y")
395 ifeq ($(has_bfd_iberty_z),y)
396 EXTLIBS += -lbfd -liberty -lz
397 else
398 has_cplus_demangle := $(shell sh -c "(echo 'extern char *cplus_demangle(const char *, int);'; echo 'int main(void) { cplus_demangle(0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o /dev/null $(ALL_LDFLAGS) -liberty > /dev/null 2>&1 && echo y")
399 ifeq ($(has_cplus_demangle),y)
400 EXTLIBS += -liberty
401 BASIC_CFLAGS += -DHAVE_CPLUS_DEMANGLE
402 else
403 msg := $(warning No bfd.h/libbfd found, install binutils-dev[el] to gain symbol demangling)
404 BASIC_CFLAGS += -DNO_DEMANGLE
405 endif
406 endif
407 endif
408 endif
409endif
410
374ifndef CC_LD_DYNPATH 411ifndef CC_LD_DYNPATH
375 ifdef NO_R_TO_GCC_LINKER 412 ifdef NO_R_TO_GCC_LINKER
376 # Some gcc does not accept and pass -R to the linker to specify 413 # Some gcc does not accept and pass -R to the linker to specify
@@ -381,12 +418,6 @@ ifndef CC_LD_DYNPATH
381 endif 418 endif
382endif 419endif
383 420
384ifdef ZLIB_PATH
385 BASIC_CFLAGS += -I$(ZLIB_PATH)/include
386 EXTLIBS += -L$(ZLIB_PATH)/$(lib) $(CC_LD_DYNPATH)$(ZLIB_PATH)/$(lib)
387endif
388EXTLIBS += -lz
389
390ifdef NEEDS_SOCKET 421ifdef NEEDS_SOCKET
391 EXTLIBS += -lsocket 422 EXTLIBS += -lsocket
392endif 423endif
@@ -697,6 +728,9 @@ builtin-init-db.o: builtin-init-db.c PERF-CFLAGS
697util/config.o: util/config.c PERF-CFLAGS 728util/config.o: util/config.c PERF-CFLAGS
698 $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< 729 $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
699 730
731util/rbtree.o: ../../lib/rbtree.c PERF-CFLAGS
732 $(QUIET_CC)$(CC) -o util/rbtree.o -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
733
700perf-%$X: %.o $(PERFLIBS) 734perf-%$X: %.o $(PERFLIBS)
701 $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS) 735 $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)
702 736
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 722c0f54e549..1dba568e1941 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -10,9 +10,9 @@
10#include "util/util.h" 10#include "util/util.h"
11 11
12#include "util/color.h" 12#include "util/color.h"
13#include "util/list.h" 13#include <linux/list.h>
14#include "util/cache.h" 14#include "util/cache.h"
15#include "util/rbtree.h" 15#include <linux/rbtree.h>
16#include "util/symbol.h" 16#include "util/symbol.h"
17#include "util/string.h" 17#include "util/string.h"
18 18
@@ -25,10 +25,6 @@
25#define SHOW_USER 2 25#define SHOW_USER 2
26#define SHOW_HV 4 26#define SHOW_HV 4
27 27
28#define MIN_GREEN 0.5
29#define MIN_RED 5.0
30
31
32static char const *input_name = "perf.data"; 28static char const *input_name = "perf.data";
33static char *vmlinux = "vmlinux"; 29static char *vmlinux = "vmlinux";
34 30
@@ -43,6 +39,10 @@ static int dump_trace = 0;
43 39
44static int verbose; 40static int verbose;
45 41
42static int modules;
43
44static int full_paths;
45
46static int print_line; 46static int print_line;
47 47
48static unsigned long page_size; 48static unsigned long page_size;
@@ -74,20 +74,12 @@ struct fork_event {
74 u32 pid, ppid; 74 u32 pid, ppid;
75}; 75};
76 76
77struct period_event {
78 struct perf_event_header header;
79 u64 time;
80 u64 id;
81 u64 sample_period;
82};
83
84typedef union event_union { 77typedef union event_union {
85 struct perf_event_header header; 78 struct perf_event_header header;
86 struct ip_event ip; 79 struct ip_event ip;
87 struct mmap_event mmap; 80 struct mmap_event mmap;
88 struct comm_event comm; 81 struct comm_event comm;
89 struct fork_event fork; 82 struct fork_event fork;
90 struct period_event period;
91} event_t; 83} event_t;
92 84
93 85
@@ -160,7 +152,7 @@ static void dsos__fprintf(FILE *fp)
160 152
161static struct symbol *vdso__find_symbol(struct dso *dso, u64 ip) 153static struct symbol *vdso__find_symbol(struct dso *dso, u64 ip)
162{ 154{
163 return dso__find_symbol(kernel_dso, ip); 155 return dso__find_symbol(dso, ip);
164} 156}
165 157
166static int load_kernel(void) 158static int load_kernel(void)
@@ -171,8 +163,8 @@ static int load_kernel(void)
171 if (!kernel_dso) 163 if (!kernel_dso)
172 return -1; 164 return -1;
173 165
174 err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose); 166 err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose, modules);
175 if (err) { 167 if (err <= 0) {
176 dso__delete(kernel_dso); 168 dso__delete(kernel_dso);
177 kernel_dso = NULL; 169 kernel_dso = NULL;
178 } else 170 } else
@@ -203,7 +195,7 @@ static u64 map__map_ip(struct map *map, u64 ip)
203 return ip - map->start + map->pgoff; 195 return ip - map->start + map->pgoff;
204} 196}
205 197
206static u64 vdso__map_ip(struct map *map, u64 ip) 198static u64 vdso__map_ip(struct map *map __used, u64 ip)
207{ 199{
208 return ip; 200 return ip;
209} 201}
@@ -600,7 +592,7 @@ static LIST_HEAD(hist_entry__sort_list);
600 592
601static int sort_dimension__add(char *tok) 593static int sort_dimension__add(char *tok)
602{ 594{
603 int i; 595 unsigned int i;
604 596
605 for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) { 597 for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) {
606 struct sort_dimension *sd = &sort_dimensions[i]; 598 struct sort_dimension *sd = &sort_dimensions[i];
@@ -998,19 +990,6 @@ process_fork_event(event_t *event, unsigned long offset, unsigned long head)
998} 990}
999 991
1000static int 992static int
1001process_period_event(event_t *event, unsigned long offset, unsigned long head)
1002{
1003 dprintf("%p [%p]: PERF_EVENT_PERIOD: time:%Ld, id:%Ld: period:%Ld\n",
1004 (void *)(offset + head),
1005 (void *)(long)(event->header.size),
1006 event->period.time,
1007 event->period.id,
1008 event->period.sample_period);
1009
1010 return 0;
1011}
1012
1013static int
1014process_event(event_t *event, unsigned long offset, unsigned long head) 993process_event(event_t *event, unsigned long offset, unsigned long head)
1015{ 994{
1016 switch (event->header.type) { 995 switch (event->header.type) {
@@ -1025,9 +1004,6 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
1025 1004
1026 case PERF_EVENT_FORK: 1005 case PERF_EVENT_FORK:
1027 return process_fork_event(event, offset, head); 1006 return process_fork_event(event, offset, head);
1028
1029 case PERF_EVENT_PERIOD:
1030 return process_period_event(event, offset, head);
1031 /* 1007 /*
1032 * We dont process them right now but they are fine: 1008 * We dont process them right now but they are fine:
1033 */ 1009 */
@@ -1043,24 +1019,6 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
1043 return 0; 1019 return 0;
1044} 1020}
1045 1021
1046static char *get_color(double percent)
1047{
1048 char *color = PERF_COLOR_NORMAL;
1049
1050 /*
1051 * We color high-overhead entries in red, mid-overhead
1052 * entries in green - and keep the low overhead places
1053 * normal:
1054 */
1055 if (percent >= MIN_RED)
1056 color = PERF_COLOR_RED;
1057 else {
1058 if (percent > MIN_GREEN)
1059 color = PERF_COLOR_GREEN;
1060 }
1061 return color;
1062}
1063
1064static int 1022static int
1065parse_line(FILE *file, struct symbol *sym, u64 start, u64 len) 1023parse_line(FILE *file, struct symbol *sym, u64 start, u64 len)
1066{ 1024{
@@ -1069,7 +1027,7 @@ parse_line(FILE *file, struct symbol *sym, u64 start, u64 len)
1069 static const char *prev_color; 1027 static const char *prev_color;
1070 unsigned int offset; 1028 unsigned int offset;
1071 size_t line_len; 1029 size_t line_len;
1072 u64 line_ip; 1030 s64 line_ip;
1073 int ret; 1031 int ret;
1074 char *c; 1032 char *c;
1075 1033
@@ -1122,7 +1080,7 @@ parse_line(FILE *file, struct symbol *sym, u64 start, u64 len)
1122 } else if (sym->hist_sum) 1080 } else if (sym->hist_sum)
1123 percent = 100.0 * hits / sym->hist_sum; 1081 percent = 100.0 * hits / sym->hist_sum;
1124 1082
1125 color = get_color(percent); 1083 color = get_percent_color(percent);
1126 1084
1127 /* 1085 /*
1128 * Also color the filename and line if needed, with 1086 * Also color the filename and line if needed, with
@@ -1258,7 +1216,7 @@ static void print_summary(char *filename)
1258 1216
1259 sym_ext = rb_entry(node, struct sym_ext, node); 1217 sym_ext = rb_entry(node, struct sym_ext, node);
1260 percent = sym_ext->percent; 1218 percent = sym_ext->percent;
1261 color = get_color(percent); 1219 color = get_percent_color(percent);
1262 path = sym_ext->path; 1220 path = sym_ext->path;
1263 1221
1264 color_fprintf(stdout, color, " %7.2f %s", percent, path); 1222 color_fprintf(stdout, color, " %7.2f %s", percent, path);
@@ -1268,19 +1226,25 @@ static void print_summary(char *filename)
1268 1226
1269static void annotate_sym(struct dso *dso, struct symbol *sym) 1227static void annotate_sym(struct dso *dso, struct symbol *sym)
1270{ 1228{
1271 char *filename = dso->name; 1229 char *filename = dso->name, *d_filename;
1272 u64 start, end, len; 1230 u64 start, end, len;
1273 char command[PATH_MAX*2]; 1231 char command[PATH_MAX*2];
1274 FILE *file; 1232 FILE *file;
1275 1233
1276 if (!filename) 1234 if (!filename)
1277 return; 1235 return;
1278 if (dso == kernel_dso) 1236 if (sym->module)
1237 filename = sym->module->path;
1238 else if (dso == kernel_dso)
1279 filename = vmlinux; 1239 filename = vmlinux;
1280 1240
1281 start = sym->obj_start; 1241 start = sym->obj_start;
1282 if (!start) 1242 if (!start)
1283 start = sym->start; 1243 start = sym->start;
1244 if (full_paths)
1245 d_filename = filename;
1246 else
1247 d_filename = basename(filename);
1284 1248
1285 end = start + sym->end - sym->start + 1; 1249 end = start + sym->end - sym->start + 1;
1286 len = sym->end - sym->start; 1250 len = sym->end - sym->start;
@@ -1291,13 +1255,14 @@ static void annotate_sym(struct dso *dso, struct symbol *sym)
1291 } 1255 }
1292 1256
1293 printf("\n\n------------------------------------------------\n"); 1257 printf("\n\n------------------------------------------------\n");
1294 printf(" Percent | Source code & Disassembly of %s\n", filename); 1258 printf(" Percent | Source code & Disassembly of %s\n", d_filename);
1295 printf("------------------------------------------------\n"); 1259 printf("------------------------------------------------\n");
1296 1260
1297 if (verbose >= 2) 1261 if (verbose >= 2)
1298 printf("annotating [%p] %30s : [%p] %30s\n", dso, dso->name, sym, sym->name); 1262 printf("annotating [%p] %30s : [%p] %30s\n", dso, dso->name, sym, sym->name);
1299 1263
1300 sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s", (u64)start, (u64)end, filename); 1264 sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s|grep -v %s",
1265 (u64)start, (u64)end, filename, filename);
1301 1266
1302 if (verbose >= 3) 1267 if (verbose >= 3)
1303 printf("doing: %s\n", command); 1268 printf("doing: %s\n", command);
@@ -1428,7 +1393,7 @@ more:
1428 1393
1429 head += size; 1394 head += size;
1430 1395
1431 if (offset + head < stat.st_size) 1396 if (offset + head < (unsigned long)stat.st_size)
1432 goto more; 1397 goto more;
1433 1398
1434 rc = EXIT_SUCCESS; 1399 rc = EXIT_SUCCESS;
@@ -1472,8 +1437,12 @@ static const struct option options[] = {
1472 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 1437 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
1473 "dump raw trace in ASCII"), 1438 "dump raw trace in ASCII"),
1474 OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"), 1439 OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"),
1440 OPT_BOOLEAN('m', "modules", &modules,
1441 "load module symbols - WARNING: use only with -k and LIVE kernel"),
1475 OPT_BOOLEAN('l', "print-line", &print_line, 1442 OPT_BOOLEAN('l', "print-line", &print_line,
1476 "print matching source lines (may be slow)"), 1443 "print matching source lines (may be slow)"),
1444 OPT_BOOLEAN('P', "full-paths", &full_paths,
1445 "Don't shorten the displayed pathnames"),
1477 OPT_END() 1446 OPT_END()
1478}; 1447};
1479 1448
@@ -1492,7 +1461,7 @@ static void setup_sorting(void)
1492 free(str); 1461 free(str);
1493} 1462}
1494 1463
1495int cmd_annotate(int argc, const char **argv, const char *prefix) 1464int cmd_annotate(int argc, const char **argv, const char *prefix __used)
1496{ 1465{
1497 symbol__init(); 1466 symbol__init();
1498 1467
diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c
index 0f32dc3f3c4c..2599d86a733b 100644
--- a/tools/perf/builtin-help.c
+++ b/tools/perf/builtin-help.c
@@ -3,6 +3,7 @@
3 * 3 *
4 * Builtin help command 4 * Builtin help command
5 */ 5 */
6#include "perf.h"
6#include "util/cache.h" 7#include "util/cache.h"
7#include "builtin.h" 8#include "builtin.h"
8#include "util/exec_cmd.h" 9#include "util/exec_cmd.h"
@@ -277,7 +278,7 @@ static struct cmdnames main_cmds, other_cmds;
277 278
278void list_common_cmds_help(void) 279void list_common_cmds_help(void)
279{ 280{
280 int i, longest = 0; 281 unsigned int i, longest = 0;
281 282
282 for (i = 0; i < ARRAY_SIZE(common_cmds); i++) { 283 for (i = 0; i < ARRAY_SIZE(common_cmds); i++) {
283 if (longest < strlen(common_cmds[i].name)) 284 if (longest < strlen(common_cmds[i].name))
@@ -415,9 +416,10 @@ static void show_html_page(const char *perf_cmd)
415 open_html(page_path.buf); 416 open_html(page_path.buf);
416} 417}
417 418
418int cmd_help(int argc, const char **argv, const char *prefix) 419int cmd_help(int argc, const char **argv, const char *prefix __used)
419{ 420{
420 const char *alias; 421 const char *alias;
422
421 load_command_list("perf-", &main_cmds, &other_cmds); 423 load_command_list("perf-", &main_cmds, &other_cmds);
422 424
423 perf_config(perf_help_config, NULL); 425 perf_config(perf_help_config, NULL);
diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
index fe60e37c96ef..d88c6961274c 100644
--- a/tools/perf/builtin-list.c
+++ b/tools/perf/builtin-list.c
@@ -10,11 +10,12 @@
10 10
11#include "perf.h" 11#include "perf.h"
12 12
13#include "util/parse-options.h"
14#include "util/parse-events.h" 13#include "util/parse-events.h"
14#include "util/cache.h"
15 15
16int cmd_list(int argc, const char **argv, const char *prefix) 16int cmd_list(int argc __used, const char **argv __used, const char *prefix __used)
17{ 17{
18 setup_pager();
18 print_events(); 19 print_events();
19 return 0; 20 return 0;
20} 21}
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index d18546f37d7c..3d051b9cf25f 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -34,7 +34,9 @@ static int output;
34static const char *output_name = "perf.data"; 34static const char *output_name = "perf.data";
35static int group = 0; 35static int group = 0;
36static unsigned int realtime_prio = 0; 36static unsigned int realtime_prio = 0;
37static int raw_samples = 0;
37static int system_wide = 0; 38static int system_wide = 0;
39static int profile_cpu = -1;
38static pid_t target_pid = -1; 40static pid_t target_pid = -1;
39static int inherit = 1; 41static int inherit = 1;
40static int force = 0; 42static int force = 0;
@@ -43,6 +45,7 @@ static int call_graph = 0;
43static int verbose = 0; 45static int verbose = 0;
44static int inherit_stat = 0; 46static int inherit_stat = 0;
45static int no_samples = 0; 47static int no_samples = 0;
48static int sample_address = 0;
46 49
47static long samples; 50static long samples;
48static struct timeval last_read; 51static struct timeval last_read;
@@ -202,46 +205,48 @@ static void sig_atexit(void)
202 kill(getpid(), signr); 205 kill(getpid(), signr);
203} 206}
204 207
205static void pid_synthesize_comm_event(pid_t pid, int full) 208static pid_t pid_synthesize_comm_event(pid_t pid, int full)
206{ 209{
207 struct comm_event comm_ev; 210 struct comm_event comm_ev;
208 char filename[PATH_MAX]; 211 char filename[PATH_MAX];
209 char bf[BUFSIZ]; 212 char bf[BUFSIZ];
210 int fd; 213 FILE *fp;
211 size_t size; 214 size_t size = 0;
212 char *field, *sep;
213 DIR *tasks; 215 DIR *tasks;
214 struct dirent dirent, *next; 216 struct dirent dirent, *next;
217 pid_t tgid = 0;
215 218
216 snprintf(filename, sizeof(filename), "/proc/%d/stat", pid); 219 snprintf(filename, sizeof(filename), "/proc/%d/status", pid);
217 220
218 fd = open(filename, O_RDONLY); 221 fp = fopen(filename, "r");
219 if (fd < 0) { 222 if (fd == NULL) {
220 /* 223 /*
221 * We raced with a task exiting - just return: 224 * We raced with a task exiting - just return:
222 */ 225 */
223 if (verbose) 226 if (verbose)
224 fprintf(stderr, "couldn't open %s\n", filename); 227 fprintf(stderr, "couldn't open %s\n", filename);
225 return; 228 return 0;
226 } 229 }
227 if (read(fd, bf, sizeof(bf)) < 0) {
228 fprintf(stderr, "couldn't read %s\n", filename);
229 exit(EXIT_FAILURE);
230 }
231 close(fd);
232 230
233 /* 9027 (cat) R 6747 9027 6747 34816 9027 ... */
234 memset(&comm_ev, 0, sizeof(comm_ev)); 231 memset(&comm_ev, 0, sizeof(comm_ev));
235 field = strchr(bf, '('); 232 while (!comm_ev.comm[0] || !comm_ev.pid) {
236 if (field == NULL) 233 if (fgets(bf, sizeof(bf), fp) == NULL)
237 goto out_failure; 234 goto out_failure;
238 sep = strchr(++field, ')'); 235
239 if (sep == NULL) 236 if (memcmp(bf, "Name:", 5) == 0) {
240 goto out_failure; 237 char *name = bf + 5;
241 size = sep - field; 238 while (*name && isspace(*name))
242 memcpy(comm_ev.comm, field, size++); 239 ++name;
243 240 size = strlen(name) - 1;
244 comm_ev.pid = pid; 241 memcpy(comm_ev.comm, name, size++);
242 } else if (memcmp(bf, "Tgid:", 5) == 0) {
243 char *tgids = bf + 5;
244 while (*tgids && isspace(*tgids))
245 ++tgids;
246 tgid = comm_ev.pid = atoi(tgids);
247 }
248 }
249
245 comm_ev.header.type = PERF_EVENT_COMM; 250 comm_ev.header.type = PERF_EVENT_COMM;
246 size = ALIGN(size, sizeof(u64)); 251 size = ALIGN(size, sizeof(u64));
247 comm_ev.header.size = sizeof(comm_ev) - (sizeof(comm_ev.comm) - size); 252 comm_ev.header.size = sizeof(comm_ev) - (sizeof(comm_ev.comm) - size);
@@ -250,7 +255,7 @@ static void pid_synthesize_comm_event(pid_t pid, int full)
250 comm_ev.tid = pid; 255 comm_ev.tid = pid;
251 256
252 write_output(&comm_ev, comm_ev.header.size); 257 write_output(&comm_ev, comm_ev.header.size);
253 return; 258 goto out_fclose;
254 } 259 }
255 260
256 snprintf(filename, sizeof(filename), "/proc/%d/task", pid); 261 snprintf(filename, sizeof(filename), "/proc/%d/task", pid);
@@ -267,7 +272,10 @@ static void pid_synthesize_comm_event(pid_t pid, int full)
267 write_output(&comm_ev, comm_ev.header.size); 272 write_output(&comm_ev, comm_ev.header.size);
268 } 273 }
269 closedir(tasks); 274 closedir(tasks);
270 return; 275
276out_fclose:
277 fclose(fp);
278 return tgid;
271 279
272out_failure: 280out_failure:
273 fprintf(stderr, "couldn't get COMM and pgid, malformed %s\n", 281 fprintf(stderr, "couldn't get COMM and pgid, malformed %s\n",
@@ -275,7 +283,7 @@ out_failure:
275 exit(EXIT_FAILURE); 283 exit(EXIT_FAILURE);
276} 284}
277 285
278static void pid_synthesize_mmap_samples(pid_t pid) 286static void pid_synthesize_mmap_samples(pid_t pid, pid_t tgid)
279{ 287{
280 char filename[PATH_MAX]; 288 char filename[PATH_MAX];
281 FILE *fp; 289 FILE *fp;
@@ -294,7 +302,7 @@ static void pid_synthesize_mmap_samples(pid_t pid)
294 while (1) { 302 while (1) {
295 char bf[BUFSIZ], *pbf = bf; 303 char bf[BUFSIZ], *pbf = bf;
296 struct mmap_event mmap_ev = { 304 struct mmap_event mmap_ev = {
297 .header.type = PERF_EVENT_MMAP, 305 .header = { .type = PERF_EVENT_MMAP },
298 }; 306 };
299 int n; 307 int n;
300 size_t size; 308 size_t size;
@@ -313,6 +321,10 @@ static void pid_synthesize_mmap_samples(pid_t pid)
313 if (*pbf == 'x') { /* vm_exec */ 321 if (*pbf == 'x') { /* vm_exec */
314 char *execname = strchr(bf, '/'); 322 char *execname = strchr(bf, '/');
315 323
324 /* Catch VDSO */
325 if (execname == NULL)
326 execname = strstr(bf, "[vdso]");
327
316 if (execname == NULL) 328 if (execname == NULL)
317 continue; 329 continue;
318 330
@@ -323,7 +335,7 @@ static void pid_synthesize_mmap_samples(pid_t pid)
323 mmap_ev.len -= mmap_ev.start; 335 mmap_ev.len -= mmap_ev.start;
324 mmap_ev.header.size = (sizeof(mmap_ev) - 336 mmap_ev.header.size = (sizeof(mmap_ev) -
325 (sizeof(mmap_ev.filename) - size)); 337 (sizeof(mmap_ev.filename) - size));
326 mmap_ev.pid = pid; 338 mmap_ev.pid = tgid;
327 mmap_ev.tid = pid; 339 mmap_ev.tid = pid;
328 340
329 write_output(&mmap_ev, mmap_ev.header.size); 341 write_output(&mmap_ev, mmap_ev.header.size);
@@ -342,14 +354,14 @@ static void synthesize_all(void)
342 354
343 while (!readdir_r(proc, &dirent, &next) && next) { 355 while (!readdir_r(proc, &dirent, &next) && next) {
344 char *end; 356 char *end;
345 pid_t pid; 357 pid_t pid, tgid;
346 358
347 pid = strtol(dirent.d_name, &end, 10); 359 pid = strtol(dirent.d_name, &end, 10);
348 if (*end) /* only interested in proper numerical dirents */ 360 if (*end) /* only interested in proper numerical dirents */
349 continue; 361 continue;
350 362
351 pid_synthesize_comm_event(pid, 1); 363 tgid = pid_synthesize_comm_event(pid, 1);
352 pid_synthesize_mmap_samples(pid); 364 pid_synthesize_mmap_samples(pid, tgid);
353 } 365 }
354 366
355 closedir(proc); 367 closedir(proc);
@@ -387,7 +399,7 @@ static void create_counter(int counter, int cpu, pid_t pid)
387 PERF_FORMAT_TOTAL_TIME_RUNNING | 399 PERF_FORMAT_TOTAL_TIME_RUNNING |
388 PERF_FORMAT_ID; 400 PERF_FORMAT_ID;
389 401
390 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID; 402 attr->sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID;
391 403
392 if (freq) { 404 if (freq) {
393 attr->sample_type |= PERF_SAMPLE_PERIOD; 405 attr->sample_type |= PERF_SAMPLE_PERIOD;
@@ -401,9 +413,15 @@ static void create_counter(int counter, int cpu, pid_t pid)
401 if (inherit_stat) 413 if (inherit_stat)
402 attr->inherit_stat = 1; 414 attr->inherit_stat = 1;
403 415
416 if (sample_address)
417 attr->sample_type |= PERF_SAMPLE_ADDR;
418
404 if (call_graph) 419 if (call_graph)
405 attr->sample_type |= PERF_SAMPLE_CALLCHAIN; 420 attr->sample_type |= PERF_SAMPLE_CALLCHAIN;
406 421
422 if (raw_samples)
423 attr->sample_type |= PERF_SAMPLE_RAW;
424
407 attr->mmap = track; 425 attr->mmap = track;
408 attr->comm = track; 426 attr->comm = track;
409 attr->inherit = (cpu < 0) && inherit; 427 attr->inherit = (cpu < 0) && inherit;
@@ -417,6 +435,8 @@ try_again:
417 435
418 if (err == EPERM) 436 if (err == EPERM)
419 die("Permission error - are you root?\n"); 437 die("Permission error - are you root?\n");
438 else if (err == ENODEV && profile_cpu != -1)
439 die("No such device - did you specify an out-of-range profile CPU?\n");
420 440
421 /* 441 /*
422 * If it's cycles then fall back to hrtimer 442 * If it's cycles then fall back to hrtimer
@@ -516,10 +536,14 @@ static int __cmd_record(int argc, const char **argv)
516 signal(SIGCHLD, sig_handler); 536 signal(SIGCHLD, sig_handler);
517 signal(SIGINT, sig_handler); 537 signal(SIGINT, sig_handler);
518 538
519 if (!stat(output_name, &st) && !force && !append_file) { 539 if (!stat(output_name, &st) && st.st_size) {
520 fprintf(stderr, "Error, output file %s exists, use -A to append or -f to overwrite.\n", 540 if (!force && !append_file) {
521 output_name); 541 fprintf(stderr, "Error, output file %s exists, use -A to append or -f to overwrite.\n",
522 exit(-1); 542 output_name);
543 exit(-1);
544 }
545 } else {
546 append_file = 0;
523 } 547 }
524 548
525 flags = O_CREAT|O_RDWR; 549 flags = O_CREAT|O_RDWR;
@@ -546,16 +570,22 @@ static int __cmd_record(int argc, const char **argv)
546 if (pid == -1) 570 if (pid == -1)
547 pid = getpid(); 571 pid = getpid();
548 572
549 open_counters(-1, pid); 573 open_counters(profile_cpu, pid);
550 } else for (i = 0; i < nr_cpus; i++) 574 } else {
551 open_counters(i, target_pid); 575 if (profile_cpu != -1) {
576 open_counters(profile_cpu, target_pid);
577 } else {
578 for (i = 0; i < nr_cpus; i++)
579 open_counters(i, target_pid);
580 }
581 }
552 582
553 if (file_new) 583 if (file_new)
554 perf_header__write(header, output); 584 perf_header__write(header, output);
555 585
556 if (!system_wide) { 586 if (!system_wide) {
557 pid_synthesize_comm_event(pid, 0); 587 pid_t tgid = pid_synthesize_comm_event(pid, 0);
558 pid_synthesize_mmap_samples(pid); 588 pid_synthesize_mmap_samples(pid, tgid);
559 } else 589 } else
560 synthesize_all(); 590 synthesize_all();
561 591
@@ -623,10 +653,14 @@ static const struct option options[] = {
623 "record events on existing pid"), 653 "record events on existing pid"),
624 OPT_INTEGER('r', "realtime", &realtime_prio, 654 OPT_INTEGER('r', "realtime", &realtime_prio,
625 "collect data with this RT SCHED_FIFO priority"), 655 "collect data with this RT SCHED_FIFO priority"),
656 OPT_BOOLEAN('R', "raw-samples", &raw_samples,
657 "collect raw sample records from all opened counters"),
626 OPT_BOOLEAN('a', "all-cpus", &system_wide, 658 OPT_BOOLEAN('a', "all-cpus", &system_wide,
627 "system-wide collection from all CPUs"), 659 "system-wide collection from all CPUs"),
628 OPT_BOOLEAN('A', "append", &append_file, 660 OPT_BOOLEAN('A', "append", &append_file,
629 "append to the output file to do incremental profiling"), 661 "append to the output file to do incremental profiling"),
662 OPT_INTEGER('C', "profile_cpu", &profile_cpu,
663 "CPU to profile on"),
630 OPT_BOOLEAN('f', "force", &force, 664 OPT_BOOLEAN('f', "force", &force,
631 "overwrite existing data file"), 665 "overwrite existing data file"),
632 OPT_LONG('c', "count", &default_interval, 666 OPT_LONG('c', "count", &default_interval,
@@ -645,16 +679,19 @@ static const struct option options[] = {
645 "be more verbose (show counter open errors, etc)"), 679 "be more verbose (show counter open errors, etc)"),
646 OPT_BOOLEAN('s', "stat", &inherit_stat, 680 OPT_BOOLEAN('s', "stat", &inherit_stat,
647 "per thread counts"), 681 "per thread counts"),
682 OPT_BOOLEAN('d', "data", &sample_address,
683 "Sample addresses"),
648 OPT_BOOLEAN('n', "no-samples", &no_samples, 684 OPT_BOOLEAN('n', "no-samples", &no_samples,
649 "don't sample"), 685 "don't sample"),
650 OPT_END() 686 OPT_END()
651}; 687};
652 688
653int cmd_record(int argc, const char **argv, const char *prefix) 689int cmd_record(int argc, const char **argv, const char *prefix __used)
654{ 690{
655 int counter; 691 int counter;
656 692
657 argc = parse_options(argc, argv, options, record_usage, 0); 693 argc = parse_options(argc, argv, options, record_usage,
694 PARSE_OPT_STOP_AT_NON_OPTION);
658 if (!argc && target_pid == -1 && !system_wide) 695 if (!argc && target_pid == -1 && !system_wide)
659 usage_with_options(record_usage, options); 696 usage_with_options(record_usage, options);
660 697
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 135b7837e6bf..b53a60fc12de 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -10,9 +10,9 @@
10#include "util/util.h" 10#include "util/util.h"
11 11
12#include "util/color.h" 12#include "util/color.h"
13#include "util/list.h" 13#include <linux/list.h>
14#include "util/cache.h" 14#include "util/cache.h"
15#include "util/rbtree.h" 15#include <linux/rbtree.h>
16#include "util/symbol.h" 16#include "util/symbol.h"
17#include "util/string.h" 17#include "util/string.h"
18#include "util/callchain.h" 18#include "util/callchain.h"
@@ -31,10 +31,12 @@
31static char const *input_name = "perf.data"; 31static char const *input_name = "perf.data";
32static char *vmlinux = NULL; 32static char *vmlinux = NULL;
33 33
34static char default_sort_order[] = "comm,dso"; 34static char default_sort_order[] = "comm,dso,symbol";
35static char *sort_order = default_sort_order; 35static char *sort_order = default_sort_order;
36static char *dso_list_str, *comm_list_str, *sym_list_str; 36static char *dso_list_str, *comm_list_str, *sym_list_str,
37 *col_width_list_str;
37static struct strlist *dso_list, *comm_list, *sym_list; 38static struct strlist *dso_list, *comm_list, *sym_list;
39static char *field_sep;
38 40
39static int input; 41static int input;
40static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV; 42static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV;
@@ -46,7 +48,10 @@ static int dump_trace = 0;
46static int verbose; 48static int verbose;
47#define eprintf(x...) do { if (verbose) fprintf(stderr, x); } while (0) 49#define eprintf(x...) do { if (verbose) fprintf(stderr, x); } while (0)
48 50
51static int modules;
52
49static int full_paths; 53static int full_paths;
54static int show_nr_samples;
50 55
51static unsigned long page_size; 56static unsigned long page_size;
52static unsigned long mmap_window = 32; 57static unsigned long mmap_window = 32;
@@ -56,8 +61,17 @@ static char *parent_pattern = default_parent_pattern;
56static regex_t parent_regex; 61static regex_t parent_regex;
57 62
58static int exclude_other = 1; 63static int exclude_other = 1;
64
65static char callchain_default_opt[] = "fractal,0.5";
66
59static int callchain; 67static int callchain;
60 68
69static
70struct callchain_param callchain_param = {
71 .mode = CHAIN_GRAPH_REL,
72 .min_percent = 0.5
73};
74
61static u64 sample_type; 75static u64 sample_type;
62 76
63struct ip_event { 77struct ip_event {
@@ -85,13 +99,7 @@ struct comm_event {
85struct fork_event { 99struct fork_event {
86 struct perf_event_header header; 100 struct perf_event_header header;
87 u32 pid, ppid; 101 u32 pid, ppid;
88}; 102 u32 tid, ptid;
89
90struct period_event {
91 struct perf_event_header header;
92 u64 time;
93 u64 id;
94 u64 sample_period;
95}; 103};
96 104
97struct lost_event { 105struct lost_event {
@@ -104,7 +112,9 @@ struct read_event {
104 struct perf_event_header header; 112 struct perf_event_header header;
105 u32 pid,tid; 113 u32 pid,tid;
106 u64 value; 114 u64 value;
107 u64 format[3]; 115 u64 time_enabled;
116 u64 time_running;
117 u64 id;
108}; 118};
109 119
110typedef union event_union { 120typedef union event_union {
@@ -113,14 +123,41 @@ typedef union event_union {
113 struct mmap_event mmap; 123 struct mmap_event mmap;
114 struct comm_event comm; 124 struct comm_event comm;
115 struct fork_event fork; 125 struct fork_event fork;
116 struct period_event period;
117 struct lost_event lost; 126 struct lost_event lost;
118 struct read_event read; 127 struct read_event read;
119} event_t; 128} event_t;
120 129
130static int repsep_fprintf(FILE *fp, const char *fmt, ...)
131{
132 int n;
133 va_list ap;
134
135 va_start(ap, fmt);
136 if (!field_sep)
137 n = vfprintf(fp, fmt, ap);
138 else {
139 char *bf = NULL;
140 n = vasprintf(&bf, fmt, ap);
141 if (n > 0) {
142 char *sep = bf;
143 while (1) {
144 sep = strchr(sep, *field_sep);
145 if (sep == NULL)
146 break;
147 *sep = '.';
148 }
149 }
150 fputs(bf, fp);
151 free(bf);
152 }
153 va_end(ap);
154 return n;
155}
156
121static LIST_HEAD(dsos); 157static LIST_HEAD(dsos);
122static struct dso *kernel_dso; 158static struct dso *kernel_dso;
123static struct dso *vdso; 159static struct dso *vdso;
160static struct dso *hypervisor_dso;
124 161
125static void dsos__add(struct dso *dso) 162static void dsos__add(struct dso *dso)
126{ 163{
@@ -176,7 +213,7 @@ static void dsos__fprintf(FILE *fp)
176 213
177static struct symbol *vdso__find_symbol(struct dso *dso, u64 ip) 214static struct symbol *vdso__find_symbol(struct dso *dso, u64 ip)
178{ 215{
179 return dso__find_symbol(kernel_dso, ip); 216 return dso__find_symbol(dso, ip);
180} 217}
181 218
182static int load_kernel(void) 219static int load_kernel(void)
@@ -187,8 +224,8 @@ static int load_kernel(void)
187 if (!kernel_dso) 224 if (!kernel_dso)
188 return -1; 225 return -1;
189 226
190 err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose); 227 err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose, modules);
191 if (err) { 228 if (err <= 0) {
192 dso__delete(kernel_dso); 229 dso__delete(kernel_dso);
193 kernel_dso = NULL; 230 kernel_dso = NULL;
194 } else 231 } else
@@ -202,6 +239,11 @@ static int load_kernel(void)
202 239
203 dsos__add(vdso); 240 dsos__add(vdso);
204 241
242 hypervisor_dso = dso__new("[hypervisor]", 0);
243 if (!hypervisor_dso)
244 return -1;
245 dsos__add(hypervisor_dso);
246
205 return err; 247 return err;
206} 248}
207 249
@@ -213,7 +255,7 @@ static int strcommon(const char *pathname)
213{ 255{
214 int n = 0; 256 int n = 0;
215 257
216 while (pathname[n] == cwd[n] && n < cwdlen) 258 while (n < cwdlen && pathname[n] == cwd[n])
217 ++n; 259 ++n;
218 260
219 return n; 261 return n;
@@ -233,7 +275,7 @@ static u64 map__map_ip(struct map *map, u64 ip)
233 return ip - map->start + map->pgoff; 275 return ip - map->start + map->pgoff;
234} 276}
235 277
236static u64 vdso__map_ip(struct map *map, u64 ip) 278static u64 vdso__map_ip(struct map *map __used, u64 ip)
237{ 279{
238 return ip; 280 return ip;
239} 281}
@@ -343,12 +385,28 @@ static struct thread *thread__new(pid_t pid)
343 return self; 385 return self;
344} 386}
345 387
388static unsigned int dsos__col_width,
389 comms__col_width,
390 threads__col_width;
391
346static int thread__set_comm(struct thread *self, const char *comm) 392static int thread__set_comm(struct thread *self, const char *comm)
347{ 393{
348 if (self->comm) 394 if (self->comm)
349 free(self->comm); 395 free(self->comm);
350 self->comm = strdup(comm); 396 self->comm = strdup(comm);
351 return self->comm ? 0 : -ENOMEM; 397 if (!self->comm)
398 return -ENOMEM;
399
400 if (!col_width_list_str && !field_sep &&
401 (!comm_list || strlist__has_entry(comm_list, comm))) {
402 unsigned int slen = strlen(comm);
403 if (slen > comms__col_width) {
404 comms__col_width = slen;
405 threads__col_width = slen + 6;
406 }
407 }
408
409 return 0;
352} 410}
353 411
354static size_t thread__fprintf(struct thread *self, FILE *fp) 412static size_t thread__fprintf(struct thread *self, FILE *fp)
@@ -519,7 +577,9 @@ struct sort_entry {
519 577
520 int64_t (*cmp)(struct hist_entry *, struct hist_entry *); 578 int64_t (*cmp)(struct hist_entry *, struct hist_entry *);
521 int64_t (*collapse)(struct hist_entry *, struct hist_entry *); 579 int64_t (*collapse)(struct hist_entry *, struct hist_entry *);
522 size_t (*print)(FILE *fp, struct hist_entry *); 580 size_t (*print)(FILE *fp, struct hist_entry *, unsigned int width);
581 unsigned int *width;
582 bool elide;
523}; 583};
524 584
525static int64_t cmp_null(void *l, void *r) 585static int64_t cmp_null(void *l, void *r)
@@ -541,15 +601,17 @@ sort__thread_cmp(struct hist_entry *left, struct hist_entry *right)
541} 601}
542 602
543static size_t 603static size_t
544sort__thread_print(FILE *fp, struct hist_entry *self) 604sort__thread_print(FILE *fp, struct hist_entry *self, unsigned int width)
545{ 605{
546 return fprintf(fp, "%16s:%5d", self->thread->comm ?: "", self->thread->pid); 606 return repsep_fprintf(fp, "%*s:%5d", width - 6,
607 self->thread->comm ?: "", self->thread->pid);
547} 608}
548 609
549static struct sort_entry sort_thread = { 610static struct sort_entry sort_thread = {
550 .header = " Command: Pid", 611 .header = "Command: Pid",
551 .cmp = sort__thread_cmp, 612 .cmp = sort__thread_cmp,
552 .print = sort__thread_print, 613 .print = sort__thread_print,
614 .width = &threads__col_width,
553}; 615};
554 616
555/* --sort comm */ 617/* --sort comm */
@@ -573,16 +635,17 @@ sort__comm_collapse(struct hist_entry *left, struct hist_entry *right)
573} 635}
574 636
575static size_t 637static size_t
576sort__comm_print(FILE *fp, struct hist_entry *self) 638sort__comm_print(FILE *fp, struct hist_entry *self, unsigned int width)
577{ 639{
578 return fprintf(fp, "%16s", self->thread->comm); 640 return repsep_fprintf(fp, "%*s", width, self->thread->comm);
579} 641}
580 642
581static struct sort_entry sort_comm = { 643static struct sort_entry sort_comm = {
582 .header = " Command", 644 .header = "Command",
583 .cmp = sort__comm_cmp, 645 .cmp = sort__comm_cmp,
584 .collapse = sort__comm_collapse, 646 .collapse = sort__comm_collapse,
585 .print = sort__comm_print, 647 .print = sort__comm_print,
648 .width = &comms__col_width,
586}; 649};
587 650
588/* --sort dso */ 651/* --sort dso */
@@ -600,18 +663,19 @@ sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
600} 663}
601 664
602static size_t 665static size_t
603sort__dso_print(FILE *fp, struct hist_entry *self) 666sort__dso_print(FILE *fp, struct hist_entry *self, unsigned int width)
604{ 667{
605 if (self->dso) 668 if (self->dso)
606 return fprintf(fp, "%-25s", self->dso->name); 669 return repsep_fprintf(fp, "%-*s", width, self->dso->name);
607 670
608 return fprintf(fp, "%016llx ", (u64)self->ip); 671 return repsep_fprintf(fp, "%*llx", width, (u64)self->ip);
609} 672}
610 673
611static struct sort_entry sort_dso = { 674static struct sort_entry sort_dso = {
612 .header = "Shared Object ", 675 .header = "Shared Object",
613 .cmp = sort__dso_cmp, 676 .cmp = sort__dso_cmp,
614 .print = sort__dso_print, 677 .print = sort__dso_print,
678 .width = &dsos__col_width,
615}; 679};
616 680
617/* --sort symbol */ 681/* --sort symbol */
@@ -631,18 +695,23 @@ sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
631} 695}
632 696
633static size_t 697static size_t
634sort__sym_print(FILE *fp, struct hist_entry *self) 698sort__sym_print(FILE *fp, struct hist_entry *self, unsigned int width __used)
635{ 699{
636 size_t ret = 0; 700 size_t ret = 0;
637 701
638 if (verbose) 702 if (verbose)
639 ret += fprintf(fp, "%#018llx ", (u64)self->ip); 703 ret += repsep_fprintf(fp, "%#018llx %c ", (u64)self->ip,
704 dso__symtab_origin(self->dso));
640 705
706 ret += repsep_fprintf(fp, "[%c] ", self->level);
641 if (self->sym) { 707 if (self->sym) {
642 ret += fprintf(fp, "[%c] %s", 708 ret += repsep_fprintf(fp, "%s", self->sym->name);
643 self->dso == kernel_dso ? 'k' : '.', self->sym->name); 709
710 if (self->sym->module)
711 ret += repsep_fprintf(fp, "\t[%s]",
712 self->sym->module->name);
644 } else { 713 } else {
645 ret += fprintf(fp, "%#016llx", (u64)self->ip); 714 ret += repsep_fprintf(fp, "%#016llx", (u64)self->ip);
646 } 715 }
647 716
648 return ret; 717 return ret;
@@ -669,19 +738,19 @@ sort__parent_cmp(struct hist_entry *left, struct hist_entry *right)
669} 738}
670 739
671static size_t 740static size_t
672sort__parent_print(FILE *fp, struct hist_entry *self) 741sort__parent_print(FILE *fp, struct hist_entry *self, unsigned int width)
673{ 742{
674 size_t ret = 0; 743 return repsep_fprintf(fp, "%-*s", width,
675 744 self->parent ? self->parent->name : "[other]");
676 ret += fprintf(fp, "%-20s", self->parent ? self->parent->name : "[other]");
677
678 return ret;
679} 745}
680 746
747static unsigned int parent_symbol__col_width;
748
681static struct sort_entry sort_parent = { 749static struct sort_entry sort_parent = {
682 .header = "Parent symbol ", 750 .header = "Parent symbol",
683 .cmp = sort__parent_cmp, 751 .cmp = sort__parent_cmp,
684 .print = sort__parent_print, 752 .print = sort__parent_print,
753 .width = &parent_symbol__col_width,
685}; 754};
686 755
687static int sort__need_collapse = 0; 756static int sort__need_collapse = 0;
@@ -705,7 +774,7 @@ static LIST_HEAD(hist_entry__sort_list);
705 774
706static int sort_dimension__add(char *tok) 775static int sort_dimension__add(char *tok)
707{ 776{
708 int i; 777 unsigned int i;
709 778
710 for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) { 779 for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) {
711 struct sort_dimension *sd = &sort_dimensions[i]; 780 struct sort_dimension *sd = &sort_dimensions[i];
@@ -775,8 +844,146 @@ hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
775 return cmp; 844 return cmp;
776} 845}
777 846
847static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask)
848{
849 int i;
850 size_t ret = 0;
851
852 ret += fprintf(fp, "%s", " ");
853
854 for (i = 0; i < depth; i++)
855 if (depth_mask & (1 << i))
856 ret += fprintf(fp, "| ");
857 else
858 ret += fprintf(fp, " ");
859
860 ret += fprintf(fp, "\n");
861
862 return ret;
863}
778static size_t 864static size_t
779callchain__fprintf(FILE *fp, struct callchain_node *self, u64 total_samples) 865ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, int depth,
866 int depth_mask, int count, u64 total_samples,
867 int hits)
868{
869 int i;
870 size_t ret = 0;
871
872 ret += fprintf(fp, "%s", " ");
873 for (i = 0; i < depth; i++) {
874 if (depth_mask & (1 << i))
875 ret += fprintf(fp, "|");
876 else
877 ret += fprintf(fp, " ");
878 if (!count && i == depth - 1) {
879 double percent;
880
881 percent = hits * 100.0 / total_samples;
882 ret += percent_color_fprintf(fp, "--%2.2f%%-- ", percent);
883 } else
884 ret += fprintf(fp, "%s", " ");
885 }
886 if (chain->sym)
887 ret += fprintf(fp, "%s\n", chain->sym->name);
888 else
889 ret += fprintf(fp, "%p\n", (void *)(long)chain->ip);
890
891 return ret;
892}
893
894static struct symbol *rem_sq_bracket;
895static struct callchain_list rem_hits;
896
897static void init_rem_hits(void)
898{
899 rem_sq_bracket = malloc(sizeof(*rem_sq_bracket) + 6);
900 if (!rem_sq_bracket) {
901 fprintf(stderr, "Not enough memory to display remaining hits\n");
902 return;
903 }
904
905 strcpy(rem_sq_bracket->name, "[...]");
906 rem_hits.sym = rem_sq_bracket;
907}
908
909static size_t
910callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
911 u64 total_samples, int depth, int depth_mask)
912{
913 struct rb_node *node, *next;
914 struct callchain_node *child;
915 struct callchain_list *chain;
916 int new_depth_mask = depth_mask;
917 u64 new_total;
918 u64 remaining;
919 size_t ret = 0;
920 int i;
921
922 if (callchain_param.mode == CHAIN_GRAPH_REL)
923 new_total = self->children_hit;
924 else
925 new_total = total_samples;
926
927 remaining = new_total;
928
929 node = rb_first(&self->rb_root);
930 while (node) {
931 u64 cumul;
932
933 child = rb_entry(node, struct callchain_node, rb_node);
934 cumul = cumul_hits(child);
935 remaining -= cumul;
936
937 /*
938 * The depth mask manages the output of pipes that show
939 * the depth. We don't want to keep the pipes of the current
940 * level for the last child of this depth.
941 * Except if we have remaining filtered hits. They will
942 * supersede the last child
943 */
944 next = rb_next(node);
945 if (!next && (callchain_param.mode != CHAIN_GRAPH_REL || !remaining))
946 new_depth_mask &= ~(1 << (depth - 1));
947
948 /*
949 * But we keep the older depth mask for the line seperator
950 * to keep the level link until we reach the last child
951 */
952 ret += ipchain__fprintf_graph_line(fp, depth, depth_mask);
953 i = 0;
954 list_for_each_entry(chain, &child->val, list) {
955 if (chain->ip >= PERF_CONTEXT_MAX)
956 continue;
957 ret += ipchain__fprintf_graph(fp, chain, depth,
958 new_depth_mask, i++,
959 new_total,
960 cumul);
961 }
962 ret += callchain__fprintf_graph(fp, child, new_total,
963 depth + 1,
964 new_depth_mask | (1 << depth));
965 node = next;
966 }
967
968 if (callchain_param.mode == CHAIN_GRAPH_REL &&
969 remaining && remaining != new_total) {
970
971 if (!rem_sq_bracket)
972 return ret;
973
974 new_depth_mask &= ~(1 << (depth - 1));
975
976 ret += ipchain__fprintf_graph(fp, &rem_hits, depth,
977 new_depth_mask, 0, new_total,
978 remaining);
979 }
980
981 return ret;
982}
983
984static size_t
985callchain__fprintf_flat(FILE *fp, struct callchain_node *self,
986 u64 total_samples)
780{ 987{
781 struct callchain_list *chain; 988 struct callchain_list *chain;
782 size_t ret = 0; 989 size_t ret = 0;
@@ -784,11 +991,18 @@ callchain__fprintf(FILE *fp, struct callchain_node *self, u64 total_samples)
784 if (!self) 991 if (!self)
785 return 0; 992 return 0;
786 993
787 ret += callchain__fprintf(fp, self->parent, total_samples); 994 ret += callchain__fprintf_flat(fp, self->parent, total_samples);
788 995
789 996
790 list_for_each_entry(chain, &self->val, list) 997 list_for_each_entry(chain, &self->val, list) {
791 ret += fprintf(fp, " %p\n", (void *)chain->ip); 998 if (chain->ip >= PERF_CONTEXT_MAX)
999 continue;
1000 if (chain->sym)
1001 ret += fprintf(fp, " %s\n", chain->sym->name);
1002 else
1003 ret += fprintf(fp, " %p\n",
1004 (void *)(long)chain->ip);
1005 }
792 1006
793 return ret; 1007 return ret;
794} 1008}
@@ -807,8 +1021,19 @@ hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self,
807 1021
808 chain = rb_entry(rb_node, struct callchain_node, rb_node); 1022 chain = rb_entry(rb_node, struct callchain_node, rb_node);
809 percent = chain->hit * 100.0 / total_samples; 1023 percent = chain->hit * 100.0 / total_samples;
810 ret += fprintf(fp, " %6.2f%%\n", percent); 1024 switch (callchain_param.mode) {
811 ret += callchain__fprintf(fp, chain, total_samples); 1025 case CHAIN_FLAT:
1026 ret += percent_color_fprintf(fp, " %6.2f%%\n",
1027 percent);
1028 ret += callchain__fprintf_flat(fp, chain, total_samples);
1029 break;
1030 case CHAIN_GRAPH_ABS: /* Falldown */
1031 case CHAIN_GRAPH_REL:
1032 ret += callchain__fprintf_graph(fp, chain,
1033 total_samples, 1, 1);
1034 default:
1035 break;
1036 }
812 ret += fprintf(fp, "\n"); 1037 ret += fprintf(fp, "\n");
813 rb_node = rb_next(rb_node); 1038 rb_node = rb_next(rb_node);
814 } 1039 }
@@ -826,33 +1051,26 @@ hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples)
826 if (exclude_other && !self->parent) 1051 if (exclude_other && !self->parent)
827 return 0; 1052 return 0;
828 1053
829 if (total_samples) { 1054 if (total_samples)
830 double percent = self->count * 100.0 / total_samples; 1055 ret = percent_color_fprintf(fp,
831 char *color = PERF_COLOR_NORMAL; 1056 field_sep ? "%.2f" : " %6.2f%%",
832 1057 (self->count * 100.0) / total_samples);
833 /* 1058 else
834 * We color high-overhead entries in red, mid-overhead 1059 ret = fprintf(fp, field_sep ? "%lld" : "%12lld ", self->count);
835 * entries in green - and keep the low overhead places
836 * normal:
837 */
838 if (percent >= 5.0) {
839 color = PERF_COLOR_RED;
840 } else {
841 if (percent >= 0.5)
842 color = PERF_COLOR_GREEN;
843 }
844 1060
845 ret = color_fprintf(fp, color, " %6.2f%%", 1061 if (show_nr_samples) {
846 (self->count * 100.0) / total_samples); 1062 if (field_sep)
847 } else 1063 fprintf(fp, "%c%lld", *field_sep, self->count);
848 ret = fprintf(fp, "%12Ld ", self->count); 1064 else
1065 fprintf(fp, "%11lld", self->count);
1066 }
849 1067
850 list_for_each_entry(se, &hist_entry__sort_list, list) { 1068 list_for_each_entry(se, &hist_entry__sort_list, list) {
851 if (exclude_other && (se == &sort_parent)) 1069 if (se->elide)
852 continue; 1070 continue;
853 1071
854 fprintf(fp, " "); 1072 fprintf(fp, "%s", field_sep ?: " ");
855 ret += se->print(fp, self); 1073 ret += se->print(fp, self, se->width ? *se->width : 0);
856 } 1074 }
857 1075
858 ret += fprintf(fp, "\n"); 1076 ret += fprintf(fp, "\n");
@@ -867,6 +1085,18 @@ hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples)
867 * 1085 *
868 */ 1086 */
869 1087
1088static void dso__calc_col_width(struct dso *self)
1089{
1090 if (!col_width_list_str && !field_sep &&
1091 (!dso_list || strlist__has_entry(dso_list, self->name))) {
1092 unsigned int slen = strlen(self->name);
1093 if (slen > dsos__col_width)
1094 dsos__col_width = slen;
1095 }
1096
1097 self->slen_calculated = 1;
1098}
1099
870static struct symbol * 1100static struct symbol *
871resolve_symbol(struct thread *thread, struct map **mapp, 1101resolve_symbol(struct thread *thread, struct map **mapp,
872 struct dso **dsop, u64 *ipp) 1102 struct dso **dsop, u64 *ipp)
@@ -886,6 +1116,14 @@ resolve_symbol(struct thread *thread, struct map **mapp,
886 1116
887 map = thread__find_map(thread, ip); 1117 map = thread__find_map(thread, ip);
888 if (map != NULL) { 1118 if (map != NULL) {
1119 /*
1120 * We have to do this here as we may have a dso
1121 * with no symbol hit that has a name longer than
1122 * the ones with symbols sampled.
1123 */
1124 if (!sort_dso.elide && !map->dso->slen_calculated)
1125 dso__calc_col_width(map->dso);
1126
889 if (mapp) 1127 if (mapp)
890 *mapp = map; 1128 *mapp = map;
891got_map: 1129got_map:
@@ -923,6 +1161,58 @@ static int call__match(struct symbol *sym)
923 return 0; 1161 return 0;
924} 1162}
925 1163
1164static struct symbol **
1165resolve_callchain(struct thread *thread, struct map *map __used,
1166 struct ip_callchain *chain, struct hist_entry *entry)
1167{
1168 u64 context = PERF_CONTEXT_MAX;
1169 struct symbol **syms = NULL;
1170 unsigned int i;
1171
1172 if (callchain) {
1173 syms = calloc(chain->nr, sizeof(*syms));
1174 if (!syms) {
1175 fprintf(stderr, "Can't allocate memory for symbols\n");
1176 exit(-1);
1177 }
1178 }
1179
1180 for (i = 0; i < chain->nr; i++) {
1181 u64 ip = chain->ips[i];
1182 struct dso *dso = NULL;
1183 struct symbol *sym;
1184
1185 if (ip >= PERF_CONTEXT_MAX) {
1186 context = ip;
1187 continue;
1188 }
1189
1190 switch (context) {
1191 case PERF_CONTEXT_HV:
1192 dso = hypervisor_dso;
1193 break;
1194 case PERF_CONTEXT_KERNEL:
1195 dso = kernel_dso;
1196 break;
1197 default:
1198 break;
1199 }
1200
1201 sym = resolve_symbol(thread, NULL, &dso, &ip);
1202
1203 if (sym) {
1204 if (sort__has_parent && call__match(sym) &&
1205 !entry->parent)
1206 entry->parent = sym;
1207 if (!callchain)
1208 break;
1209 syms[i] = sym;
1210 }
1211 }
1212
1213 return syms;
1214}
1215
926/* 1216/*
927 * collect histogram counts 1217 * collect histogram counts
928 */ 1218 */
@@ -935,6 +1225,7 @@ hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
935 struct rb_node **p = &hist.rb_node; 1225 struct rb_node **p = &hist.rb_node;
936 struct rb_node *parent = NULL; 1226 struct rb_node *parent = NULL;
937 struct hist_entry *he; 1227 struct hist_entry *he;
1228 struct symbol **syms = NULL;
938 struct hist_entry entry = { 1229 struct hist_entry entry = {
939 .thread = thread, 1230 .thread = thread,
940 .map = map, 1231 .map = map,
@@ -948,36 +1239,8 @@ hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
948 }; 1239 };
949 int cmp; 1240 int cmp;
950 1241
951 if (sort__has_parent && chain) { 1242 if ((sort__has_parent || callchain) && chain)
952 u64 context = PERF_CONTEXT_MAX; 1243 syms = resolve_callchain(thread, map, chain, &entry);
953 int i;
954
955 for (i = 0; i < chain->nr; i++) {
956 u64 ip = chain->ips[i];
957 struct dso *dso = NULL;
958 struct symbol *sym;
959
960 if (ip >= PERF_CONTEXT_MAX) {
961 context = ip;
962 continue;
963 }
964
965 switch (context) {
966 case PERF_CONTEXT_KERNEL:
967 dso = kernel_dso;
968 break;
969 default:
970 break;
971 }
972
973 sym = resolve_symbol(thread, NULL, &dso, &ip);
974
975 if (sym && call__match(sym)) {
976 entry.parent = sym;
977 break;
978 }
979 }
980 }
981 1244
982 while (*p != NULL) { 1245 while (*p != NULL) {
983 parent = *p; 1246 parent = *p;
@@ -987,8 +1250,10 @@ hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
987 1250
988 if (!cmp) { 1251 if (!cmp) {
989 he->count += count; 1252 he->count += count;
990 if (callchain) 1253 if (callchain) {
991 append_chain(&he->callchain, chain); 1254 append_chain(&he->callchain, chain, syms);
1255 free(syms);
1256 }
992 return 0; 1257 return 0;
993 } 1258 }
994 1259
@@ -1004,7 +1269,8 @@ hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
1004 *he = entry; 1269 *he = entry;
1005 if (callchain) { 1270 if (callchain) {
1006 callchain_init(&he->callchain); 1271 callchain_init(&he->callchain);
1007 append_chain(&he->callchain, chain); 1272 append_chain(&he->callchain, chain, syms);
1273 free(syms);
1008 } 1274 }
1009 rb_link_node(&he->rb_node, parent, p); 1275 rb_link_node(&he->rb_node, parent, p);
1010 rb_insert_color(&he->rb_node, &hist); 1276 rb_insert_color(&he->rb_node, &hist);
@@ -1076,14 +1342,15 @@ static void collapse__resort(void)
1076 1342
1077static struct rb_root output_hists; 1343static struct rb_root output_hists;
1078 1344
1079static void output__insert_entry(struct hist_entry *he) 1345static void output__insert_entry(struct hist_entry *he, u64 min_callchain_hits)
1080{ 1346{
1081 struct rb_node **p = &output_hists.rb_node; 1347 struct rb_node **p = &output_hists.rb_node;
1082 struct rb_node *parent = NULL; 1348 struct rb_node *parent = NULL;
1083 struct hist_entry *iter; 1349 struct hist_entry *iter;
1084 1350
1085 if (callchain) 1351 if (callchain)
1086 sort_chain_to_rbtree(&he->sorted_chain, &he->callchain); 1352 callchain_param.sort(&he->sorted_chain, &he->callchain,
1353 min_callchain_hits, &callchain_param);
1087 1354
1088 while (*p != NULL) { 1355 while (*p != NULL) {
1089 parent = *p; 1356 parent = *p;
@@ -1099,11 +1366,14 @@ static void output__insert_entry(struct hist_entry *he)
1099 rb_insert_color(&he->rb_node, &output_hists); 1366 rb_insert_color(&he->rb_node, &output_hists);
1100} 1367}
1101 1368
1102static void output__resort(void) 1369static void output__resort(u64 total_samples)
1103{ 1370{
1104 struct rb_node *next; 1371 struct rb_node *next;
1105 struct hist_entry *n; 1372 struct hist_entry *n;
1106 struct rb_root *tree = &hist; 1373 struct rb_root *tree = &hist;
1374 u64 min_callchain_hits;
1375
1376 min_callchain_hits = total_samples * (callchain_param.min_percent / 100);
1107 1377
1108 if (sort__need_collapse) 1378 if (sort__need_collapse)
1109 tree = &collapse_hists; 1379 tree = &collapse_hists;
@@ -1115,7 +1385,7 @@ static void output__resort(void)
1115 next = rb_next(&n->rb_node); 1385 next = rb_next(&n->rb_node);
1116 1386
1117 rb_erase(&n->rb_node, tree); 1387 rb_erase(&n->rb_node, tree);
1118 output__insert_entry(n); 1388 output__insert_entry(n, min_callchain_hits);
1119 } 1389 }
1120} 1390}
1121 1391
@@ -1125,35 +1395,69 @@ static size_t output__fprintf(FILE *fp, u64 total_samples)
1125 struct sort_entry *se; 1395 struct sort_entry *se;
1126 struct rb_node *nd; 1396 struct rb_node *nd;
1127 size_t ret = 0; 1397 size_t ret = 0;
1398 unsigned int width;
1399 char *col_width = col_width_list_str;
1128 1400
1129 fprintf(fp, "\n"); 1401 init_rem_hits();
1130 fprintf(fp, "#\n"); 1402
1131 fprintf(fp, "# (%Ld samples)\n", (u64)total_samples); 1403 fprintf(fp, "# Samples: %Ld\n", (u64)total_samples);
1132 fprintf(fp, "#\n"); 1404 fprintf(fp, "#\n");
1133 1405
1134 fprintf(fp, "# Overhead"); 1406 fprintf(fp, "# Overhead");
1407 if (show_nr_samples) {
1408 if (field_sep)
1409 fprintf(fp, "%cSamples", *field_sep);
1410 else
1411 fputs(" Samples ", fp);
1412 }
1135 list_for_each_entry(se, &hist_entry__sort_list, list) { 1413 list_for_each_entry(se, &hist_entry__sort_list, list) {
1136 if (exclude_other && (se == &sort_parent)) 1414 if (se->elide)
1137 continue; 1415 continue;
1138 fprintf(fp, " %s", se->header); 1416 if (field_sep) {
1417 fprintf(fp, "%c%s", *field_sep, se->header);
1418 continue;
1419 }
1420 width = strlen(se->header);
1421 if (se->width) {
1422 if (col_width_list_str) {
1423 if (col_width) {
1424 *se->width = atoi(col_width);
1425 col_width = strchr(col_width, ',');
1426 if (col_width)
1427 ++col_width;
1428 }
1429 }
1430 width = *se->width = max(*se->width, width);
1431 }
1432 fprintf(fp, " %*s", width, se->header);
1139 } 1433 }
1140 fprintf(fp, "\n"); 1434 fprintf(fp, "\n");
1141 1435
1436 if (field_sep)
1437 goto print_entries;
1438
1142 fprintf(fp, "# ........"); 1439 fprintf(fp, "# ........");
1440 if (show_nr_samples)
1441 fprintf(fp, " ..........");
1143 list_for_each_entry(se, &hist_entry__sort_list, list) { 1442 list_for_each_entry(se, &hist_entry__sort_list, list) {
1144 int i; 1443 unsigned int i;
1145 1444
1146 if (exclude_other && (se == &sort_parent)) 1445 if (se->elide)
1147 continue; 1446 continue;
1148 1447
1149 fprintf(fp, " "); 1448 fprintf(fp, " ");
1150 for (i = 0; i < strlen(se->header); i++) 1449 if (se->width)
1450 width = *se->width;
1451 else
1452 width = strlen(se->header);
1453 for (i = 0; i < width; i++)
1151 fprintf(fp, "."); 1454 fprintf(fp, ".");
1152 } 1455 }
1153 fprintf(fp, "\n"); 1456 fprintf(fp, "\n");
1154 1457
1155 fprintf(fp, "#\n"); 1458 fprintf(fp, "#\n");
1156 1459
1460print_entries:
1157 for (nd = rb_first(&output_hists); nd; nd = rb_next(nd)) { 1461 for (nd = rb_first(&output_hists); nd; nd = rb_next(nd)) {
1158 pos = rb_entry(nd, struct hist_entry, rb_node); 1462 pos = rb_entry(nd, struct hist_entry, rb_node);
1159 ret += hist_entry__fprintf(fp, pos, total_samples); 1463 ret += hist_entry__fprintf(fp, pos, total_samples);
@@ -1162,11 +1466,13 @@ static size_t output__fprintf(FILE *fp, u64 total_samples)
1162 if (sort_order == default_sort_order && 1466 if (sort_order == default_sort_order &&
1163 parent_pattern == default_parent_pattern) { 1467 parent_pattern == default_parent_pattern) {
1164 fprintf(fp, "#\n"); 1468 fprintf(fp, "#\n");
1165 fprintf(fp, "# (For more details, try: perf report --sort comm,dso,symbol)\n"); 1469 fprintf(fp, "# (For a higher level overview, try: perf report --sort comm,dso)\n");
1166 fprintf(fp, "#\n"); 1470 fprintf(fp, "#\n");
1167 } 1471 }
1168 fprintf(fp, "\n"); 1472 fprintf(fp, "\n");
1169 1473
1474 free(rem_sq_bracket);
1475
1170 return ret; 1476 return ret;
1171} 1477}
1172 1478
@@ -1213,22 +1519,23 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
1213 struct map *map = NULL; 1519 struct map *map = NULL;
1214 void *more_data = event->ip.__more_data; 1520 void *more_data = event->ip.__more_data;
1215 struct ip_callchain *chain = NULL; 1521 struct ip_callchain *chain = NULL;
1522 int cpumode;
1216 1523
1217 if (sample_type & PERF_SAMPLE_PERIOD) { 1524 if (sample_type & PERF_SAMPLE_PERIOD) {
1218 period = *(u64 *)more_data; 1525 period = *(u64 *)more_data;
1219 more_data += sizeof(u64); 1526 more_data += sizeof(u64);
1220 } 1527 }
1221 1528
1222 dprintf("%p [%p]: PERF_EVENT_SAMPLE (IP, %d): %d: %p period: %Ld\n", 1529 dprintf("%p [%p]: PERF_EVENT_SAMPLE (IP, %d): %d/%d: %p period: %Ld\n",
1223 (void *)(offset + head), 1530 (void *)(offset + head),
1224 (void *)(long)(event->header.size), 1531 (void *)(long)(event->header.size),
1225 event->header.misc, 1532 event->header.misc,
1226 event->ip.pid, 1533 event->ip.pid, event->ip.tid,
1227 (void *)(long)ip, 1534 (void *)(long)ip,
1228 (long long)period); 1535 (long long)period);
1229 1536
1230 if (sample_type & PERF_SAMPLE_CALLCHAIN) { 1537 if (sample_type & PERF_SAMPLE_CALLCHAIN) {
1231 int i; 1538 unsigned int i;
1232 1539
1233 chain = (void *)more_data; 1540 chain = (void *)more_data;
1234 1541
@@ -1256,7 +1563,9 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
1256 if (comm_list && !strlist__has_entry(comm_list, thread->comm)) 1563 if (comm_list && !strlist__has_entry(comm_list, thread->comm))
1257 return 0; 1564 return 0;
1258 1565
1259 if (event->header.misc & PERF_EVENT_MISC_KERNEL) { 1566 cpumode = event->header.misc & PERF_EVENT_MISC_CPUMODE_MASK;
1567
1568 if (cpumode == PERF_EVENT_MISC_KERNEL) {
1260 show = SHOW_KERNEL; 1569 show = SHOW_KERNEL;
1261 level = 'k'; 1570 level = 'k';
1262 1571
@@ -1264,7 +1573,7 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
1264 1573
1265 dprintf(" ...... dso: %s\n", dso->name); 1574 dprintf(" ...... dso: %s\n", dso->name);
1266 1575
1267 } else if (event->header.misc & PERF_EVENT_MISC_USER) { 1576 } else if (cpumode == PERF_EVENT_MISC_USER) {
1268 1577
1269 show = SHOW_USER; 1578 show = SHOW_USER;
1270 level = '.'; 1579 level = '.';
@@ -1272,16 +1581,20 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
1272 } else { 1581 } else {
1273 show = SHOW_HV; 1582 show = SHOW_HV;
1274 level = 'H'; 1583 level = 'H';
1584
1585 dso = hypervisor_dso;
1586
1275 dprintf(" ...... dso: [hypervisor]\n"); 1587 dprintf(" ...... dso: [hypervisor]\n");
1276 } 1588 }
1277 1589
1278 if (show & show_mask) { 1590 if (show & show_mask) {
1279 struct symbol *sym = resolve_symbol(thread, &map, &dso, &ip); 1591 struct symbol *sym = resolve_symbol(thread, &map, &dso, &ip);
1280 1592
1281 if (dso_list && dso && dso->name && !strlist__has_entry(dso_list, dso->name)) 1593 if (dso_list && (!dso || !dso->name ||
1594 !strlist__has_entry(dso_list, dso->name)))
1282 return 0; 1595 return 0;
1283 1596
1284 if (sym_list && sym && !strlist__has_entry(sym_list, sym->name)) 1597 if (sym_list && (!sym || !strlist__has_entry(sym_list, sym->name)))
1285 return 0; 1598 return 0;
1286 1599
1287 if (hist_entry__add(thread, map, dso, sym, ip, chain, level, period)) { 1600 if (hist_entry__add(thread, map, dso, sym, ip, chain, level, period)) {
@@ -1300,10 +1613,11 @@ process_mmap_event(event_t *event, unsigned long offset, unsigned long head)
1300 struct thread *thread = threads__findnew(event->mmap.pid); 1613 struct thread *thread = threads__findnew(event->mmap.pid);
1301 struct map *map = map__new(&event->mmap); 1614 struct map *map = map__new(&event->mmap);
1302 1615
1303 dprintf("%p [%p]: PERF_EVENT_MMAP %d: [%p(%p) @ %p]: %s\n", 1616 dprintf("%p [%p]: PERF_EVENT_MMAP %d/%d: [%p(%p) @ %p]: %s\n",
1304 (void *)(offset + head), 1617 (void *)(offset + head),
1305 (void *)(long)(event->header.size), 1618 (void *)(long)(event->header.size),
1306 event->mmap.pid, 1619 event->mmap.pid,
1620 event->mmap.tid,
1307 (void *)(long)event->mmap.start, 1621 (void *)(long)event->mmap.start,
1308 (void *)(long)event->mmap.len, 1622 (void *)(long)event->mmap.len,
1309 (void *)(long)event->mmap.pgoff, 1623 (void *)(long)event->mmap.pgoff,
@@ -1341,15 +1655,27 @@ process_comm_event(event_t *event, unsigned long offset, unsigned long head)
1341} 1655}
1342 1656
1343static int 1657static int
1344process_fork_event(event_t *event, unsigned long offset, unsigned long head) 1658process_task_event(event_t *event, unsigned long offset, unsigned long head)
1345{ 1659{
1346 struct thread *thread = threads__findnew(event->fork.pid); 1660 struct thread *thread = threads__findnew(event->fork.pid);
1347 struct thread *parent = threads__findnew(event->fork.ppid); 1661 struct thread *parent = threads__findnew(event->fork.ppid);
1348 1662
1349 dprintf("%p [%p]: PERF_EVENT_FORK: %d:%d\n", 1663 dprintf("%p [%p]: PERF_EVENT_%s: (%d:%d):(%d:%d)\n",
1350 (void *)(offset + head), 1664 (void *)(offset + head),
1351 (void *)(long)(event->header.size), 1665 (void *)(long)(event->header.size),
1352 event->fork.pid, event->fork.ppid); 1666 event->header.type == PERF_EVENT_FORK ? "FORK" : "EXIT",
1667 event->fork.pid, event->fork.tid,
1668 event->fork.ppid, event->fork.ptid);
1669
1670 /*
1671 * A thread clone will have the same PID for both
1672 * parent and child.
1673 */
1674 if (thread == parent)
1675 return 0;
1676
1677 if (event->header.type == PERF_EVENT_EXIT)
1678 return 0;
1353 1679
1354 if (!thread || !parent || thread__fork(thread, parent)) { 1680 if (!thread || !parent || thread__fork(thread, parent)) {
1355 dprintf("problem processing PERF_EVENT_FORK, skipping event.\n"); 1681 dprintf("problem processing PERF_EVENT_FORK, skipping event.\n");
@@ -1361,19 +1687,6 @@ process_fork_event(event_t *event, unsigned long offset, unsigned long head)
1361} 1687}
1362 1688
1363static int 1689static int
1364process_period_event(event_t *event, unsigned long offset, unsigned long head)
1365{
1366 dprintf("%p [%p]: PERF_EVENT_PERIOD: time:%Ld, id:%Ld: period:%Ld\n",
1367 (void *)(offset + head),
1368 (void *)(long)(event->header.size),
1369 event->period.time,
1370 event->period.id,
1371 event->period.sample_period);
1372
1373 return 0;
1374}
1375
1376static int
1377process_lost_event(event_t *event, unsigned long offset, unsigned long head) 1690process_lost_event(event_t *event, unsigned long offset, unsigned long head)
1378{ 1691{
1379 dprintf("%p [%p]: PERF_EVENT_LOST: id:%Ld: lost:%Ld\n", 1692 dprintf("%p [%p]: PERF_EVENT_LOST: id:%Ld: lost:%Ld\n",
@@ -1423,14 +1736,37 @@ static void trace_event(event_t *event)
1423 dprintf(".\n"); 1736 dprintf(".\n");
1424} 1737}
1425 1738
1739static struct perf_header *header;
1740
1741static struct perf_counter_attr *perf_header__find_attr(u64 id)
1742{
1743 int i;
1744
1745 for (i = 0; i < header->attrs; i++) {
1746 struct perf_header_attr *attr = header->attr[i];
1747 int j;
1748
1749 for (j = 0; j < attr->ids; j++) {
1750 if (attr->id[j] == id)
1751 return &attr->attr;
1752 }
1753 }
1754
1755 return NULL;
1756}
1757
1426static int 1758static int
1427process_read_event(event_t *event, unsigned long offset, unsigned long head) 1759process_read_event(event_t *event, unsigned long offset, unsigned long head)
1428{ 1760{
1429 dprintf("%p [%p]: PERF_EVENT_READ: %d %d %Lu\n", 1761 struct perf_counter_attr *attr = perf_header__find_attr(event->read.id);
1762
1763 dprintf("%p [%p]: PERF_EVENT_READ: %d %d %s %Lu\n",
1430 (void *)(offset + head), 1764 (void *)(offset + head),
1431 (void *)(long)(event->header.size), 1765 (void *)(long)(event->header.size),
1432 event->read.pid, 1766 event->read.pid,
1433 event->read.tid, 1767 event->read.tid,
1768 attr ? __event_name(attr->type, attr->config)
1769 : "FAIL",
1434 event->read.value); 1770 event->read.value);
1435 1771
1436 return 0; 1772 return 0;
@@ -1452,10 +1788,8 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
1452 return process_comm_event(event, offset, head); 1788 return process_comm_event(event, offset, head);
1453 1789
1454 case PERF_EVENT_FORK: 1790 case PERF_EVENT_FORK:
1455 return process_fork_event(event, offset, head); 1791 case PERF_EVENT_EXIT:
1456 1792 return process_task_event(event, offset, head);
1457 case PERF_EVENT_PERIOD:
1458 return process_period_event(event, offset, head);
1459 1793
1460 case PERF_EVENT_LOST: 1794 case PERF_EVENT_LOST:
1461 return process_lost_event(event, offset, head); 1795 return process_lost_event(event, offset, head);
@@ -1478,8 +1812,6 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
1478 return 0; 1812 return 0;
1479} 1813}
1480 1814
1481static struct perf_header *header;
1482
1483static u64 perf_header__sample_type(void) 1815static u64 perf_header__sample_type(void)
1484{ 1816{
1485 u64 sample_type = 0; 1817 u64 sample_type = 0;
@@ -1534,9 +1866,26 @@ static int __cmd_report(void)
1534 1866
1535 sample_type = perf_header__sample_type(); 1867 sample_type = perf_header__sample_type();
1536 1868
1537 if (sort__has_parent && !(sample_type & PERF_SAMPLE_CALLCHAIN)) { 1869 if (!(sample_type & PERF_SAMPLE_CALLCHAIN)) {
1538 fprintf(stderr, "selected --sort parent, but no callchain data\n"); 1870 if (sort__has_parent) {
1539 exit(-1); 1871 fprintf(stderr, "selected --sort parent, but no"
1872 " callchain data. Did you call"
1873 " perf record without -g?\n");
1874 exit(-1);
1875 }
1876 if (callchain) {
1877 fprintf(stderr, "selected -c but no callchain data."
1878 " Did you call perf record without"
1879 " -g?\n");
1880 exit(-1);
1881 }
1882 } else if (callchain_param.mode != CHAIN_NONE && !callchain) {
1883 callchain = 1;
1884 if (register_callchain_param(&callchain_param) < 0) {
1885 fprintf(stderr, "Can't register callchain"
1886 " params\n");
1887 exit(-1);
1888 }
1540 } 1889 }
1541 1890
1542 if (load_kernel() < 0) { 1891 if (load_kernel() < 0) {
@@ -1619,7 +1968,7 @@ more:
1619 if (offset + head >= header->data_offset + header->data_size) 1968 if (offset + head >= header->data_offset + header->data_size)
1620 goto done; 1969 goto done;
1621 1970
1622 if (offset + head < stat.st_size) 1971 if (offset + head < (unsigned long)stat.st_size)
1623 goto more; 1972 goto more;
1624 1973
1625done: 1974done:
@@ -1643,12 +1992,65 @@ done:
1643 dsos__fprintf(stdout); 1992 dsos__fprintf(stdout);
1644 1993
1645 collapse__resort(); 1994 collapse__resort();
1646 output__resort(); 1995 output__resort(total);
1647 output__fprintf(stdout, total); 1996 output__fprintf(stdout, total);
1648 1997
1649 return rc; 1998 return rc;
1650} 1999}
1651 2000
2001static int
2002parse_callchain_opt(const struct option *opt __used, const char *arg,
2003 int unset __used)
2004{
2005 char *tok;
2006 char *endptr;
2007
2008 callchain = 1;
2009
2010 if (!arg)
2011 return 0;
2012
2013 tok = strtok((char *)arg, ",");
2014 if (!tok)
2015 return -1;
2016
2017 /* get the output mode */
2018 if (!strncmp(tok, "graph", strlen(arg)))
2019 callchain_param.mode = CHAIN_GRAPH_ABS;
2020
2021 else if (!strncmp(tok, "flat", strlen(arg)))
2022 callchain_param.mode = CHAIN_FLAT;
2023
2024 else if (!strncmp(tok, "fractal", strlen(arg)))
2025 callchain_param.mode = CHAIN_GRAPH_REL;
2026
2027 else if (!strncmp(tok, "none", strlen(arg))) {
2028 callchain_param.mode = CHAIN_NONE;
2029 callchain = 0;
2030
2031 return 0;
2032 }
2033
2034 else
2035 return -1;
2036
2037 /* get the min percentage */
2038 tok = strtok(NULL, ",");
2039 if (!tok)
2040 goto setup;
2041
2042 callchain_param.min_percent = strtod(tok, &endptr);
2043 if (tok == endptr)
2044 return -1;
2045
2046setup:
2047 if (register_callchain_param(&callchain_param) < 0) {
2048 fprintf(stderr, "Can't register callchain params\n");
2049 return -1;
2050 }
2051 return 0;
2052}
2053
1652static const char * const report_usage[] = { 2054static const char * const report_usage[] = {
1653 "perf report [<options>] <command>", 2055 "perf report [<options>] <command>",
1654 NULL 2056 NULL
@@ -1662,6 +2064,10 @@ static const struct option options[] = {
1662 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 2064 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
1663 "dump raw trace in ASCII"), 2065 "dump raw trace in ASCII"),
1664 OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"), 2066 OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"),
2067 OPT_BOOLEAN('m', "modules", &modules,
2068 "load module symbols - WARNING: use only with -k and LIVE kernel"),
2069 OPT_BOOLEAN('n', "show-nr-samples", &show_nr_samples,
2070 "Show a column with the number of samples"),
1665 OPT_STRING('s', "sort", &sort_order, "key[,key2...]", 2071 OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
1666 "sort by key(s): pid, comm, dso, symbol, parent"), 2072 "sort by key(s): pid, comm, dso, symbol, parent"),
1667 OPT_BOOLEAN('P', "full-paths", &full_paths, 2073 OPT_BOOLEAN('P', "full-paths", &full_paths,
@@ -1670,13 +2076,21 @@ static const struct option options[] = {
1670 "regex filter to identify parent, see: '--sort parent'"), 2076 "regex filter to identify parent, see: '--sort parent'"),
1671 OPT_BOOLEAN('x', "exclude-other", &exclude_other, 2077 OPT_BOOLEAN('x', "exclude-other", &exclude_other,
1672 "Only display entries with parent-match"), 2078 "Only display entries with parent-match"),
1673 OPT_BOOLEAN('c', "callchain", &callchain, "Display callchains"), 2079 OPT_CALLBACK_DEFAULT('g', "call-graph", NULL, "output_type,min_percent",
2080 "Display callchains using output_type and min percent threshold. "
2081 "Default: fractal,0.5", &parse_callchain_opt, callchain_default_opt),
1674 OPT_STRING('d', "dsos", &dso_list_str, "dso[,dso...]", 2082 OPT_STRING('d', "dsos", &dso_list_str, "dso[,dso...]",
1675 "only consider symbols in these dsos"), 2083 "only consider symbols in these dsos"),
1676 OPT_STRING('C', "comms", &comm_list_str, "comm[,comm...]", 2084 OPT_STRING('C', "comms", &comm_list_str, "comm[,comm...]",
1677 "only consider symbols in these comms"), 2085 "only consider symbols in these comms"),
1678 OPT_STRING('S', "symbols", &sym_list_str, "symbol[,symbol...]", 2086 OPT_STRING('S', "symbols", &sym_list_str, "symbol[,symbol...]",
1679 "only consider these symbols"), 2087 "only consider these symbols"),
2088 OPT_STRING('w', "column-widths", &col_width_list_str,
2089 "width[,width...]",
2090 "don't try to adjust column width, use these fixed values"),
2091 OPT_STRING('t', "field-separator", &field_sep, "separator",
2092 "separator for columns, no spaces will be added between "
2093 "columns '.' is reserved."),
1680 OPT_END() 2094 OPT_END()
1681}; 2095};
1682 2096
@@ -1696,7 +2110,8 @@ static void setup_sorting(void)
1696} 2110}
1697 2111
1698static void setup_list(struct strlist **list, const char *list_str, 2112static void setup_list(struct strlist **list, const char *list_str,
1699 const char *list_name) 2113 struct sort_entry *se, const char *list_name,
2114 FILE *fp)
1700{ 2115{
1701 if (list_str) { 2116 if (list_str) {
1702 *list = strlist__new(true, list_str); 2117 *list = strlist__new(true, list_str);
@@ -1705,10 +2120,15 @@ static void setup_list(struct strlist **list, const char *list_str,
1705 list_name); 2120 list_name);
1706 exit(129); 2121 exit(129);
1707 } 2122 }
2123 if (strlist__nr_entries(*list) == 1) {
2124 fprintf(fp, "# %s: %s\n", list_name,
2125 strlist__entry(*list, 0)->s);
2126 se->elide = true;
2127 }
1708 } 2128 }
1709} 2129}
1710 2130
1711int cmd_report(int argc, const char **argv, const char *prefix) 2131int cmd_report(int argc, const char **argv, const char *prefix __used)
1712{ 2132{
1713 symbol__init(); 2133 symbol__init();
1714 2134
@@ -1718,9 +2138,10 @@ int cmd_report(int argc, const char **argv, const char *prefix)
1718 2138
1719 setup_sorting(); 2139 setup_sorting();
1720 2140
1721 if (parent_pattern != default_parent_pattern) 2141 if (parent_pattern != default_parent_pattern) {
1722 sort_dimension__add("parent"); 2142 sort_dimension__add("parent");
1723 else 2143 sort_parent.elide = 1;
2144 } else
1724 exclude_other = 0; 2145 exclude_other = 0;
1725 2146
1726 /* 2147 /*
@@ -1729,11 +2150,17 @@ int cmd_report(int argc, const char **argv, const char *prefix)
1729 if (argc) 2150 if (argc)
1730 usage_with_options(report_usage, options); 2151 usage_with_options(report_usage, options);
1731 2152
1732 setup_list(&dso_list, dso_list_str, "dso");
1733 setup_list(&comm_list, comm_list_str, "comm");
1734 setup_list(&sym_list, sym_list_str, "symbol");
1735
1736 setup_pager(); 2153 setup_pager();
1737 2154
2155 setup_list(&dso_list, dso_list_str, &sort_dso, "dso", stdout);
2156 setup_list(&comm_list, comm_list_str, &sort_comm, "comm", stdout);
2157 setup_list(&sym_list, sym_list_str, &sort_sym, "symbol", stdout);
2158
2159 if (field_sep && *field_sep == '.') {
2160 fputs("'.' is the only non valid --field-separator argument\n",
2161 stderr);
2162 exit(129);
2163 }
2164
1738 return __cmd_report(); 2165 return __cmd_report();
1739} 2166}
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 2e03524a1de0..b4b06c7903e1 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -64,7 +64,7 @@ static struct perf_counter_attr default_attrs[] = {
64 64
65static int system_wide = 0; 65static int system_wide = 0;
66static int verbose = 0; 66static int verbose = 0;
67static int nr_cpus = 0; 67static unsigned int nr_cpus = 0;
68static int run_idx = 0; 68static int run_idx = 0;
69 69
70static int run_count = 1; 70static int run_count = 1;
@@ -96,6 +96,10 @@ static u64 walltime_nsecs_noise;
96static u64 runtime_cycles_avg; 96static u64 runtime_cycles_avg;
97static u64 runtime_cycles_noise; 97static u64 runtime_cycles_noise;
98 98
99#define MATCH_EVENT(t, c, counter) \
100 (attrs[counter].type == PERF_TYPE_##t && \
101 attrs[counter].config == PERF_COUNT_##c)
102
99#define ERR_PERF_OPEN \ 103#define ERR_PERF_OPEN \
100"Error: counter %d, sys_perf_counter_open() syscall returned with %d (%s)\n" 104"Error: counter %d, sys_perf_counter_open() syscall returned with %d (%s)\n"
101 105
@@ -108,7 +112,8 @@ static void create_perf_stat_counter(int counter, int pid)
108 PERF_FORMAT_TOTAL_TIME_RUNNING; 112 PERF_FORMAT_TOTAL_TIME_RUNNING;
109 113
110 if (system_wide) { 114 if (system_wide) {
111 int cpu; 115 unsigned int cpu;
116
112 for (cpu = 0; cpu < nr_cpus; cpu++) { 117 for (cpu = 0; cpu < nr_cpus; cpu++) {
113 fd[cpu][counter] = sys_perf_counter_open(attr, -1, cpu, -1, 0); 118 fd[cpu][counter] = sys_perf_counter_open(attr, -1, cpu, -1, 0);
114 if (fd[cpu][counter] < 0 && verbose) 119 if (fd[cpu][counter] < 0 && verbose)
@@ -132,13 +137,8 @@ static void create_perf_stat_counter(int counter, int pid)
132 */ 137 */
133static inline int nsec_counter(int counter) 138static inline int nsec_counter(int counter)
134{ 139{
135 if (attrs[counter].type != PERF_TYPE_SOFTWARE) 140 if (MATCH_EVENT(SOFTWARE, SW_CPU_CLOCK, counter) ||
136 return 0; 141 MATCH_EVENT(SOFTWARE, SW_TASK_CLOCK, counter))
137
138 if (attrs[counter].config == PERF_COUNT_SW_CPU_CLOCK)
139 return 1;
140
141 if (attrs[counter].config == PERF_COUNT_SW_TASK_CLOCK)
142 return 1; 142 return 1;
143 143
144 return 0; 144 return 0;
@@ -150,8 +150,8 @@ static inline int nsec_counter(int counter)
150static void read_counter(int counter) 150static void read_counter(int counter)
151{ 151{
152 u64 *count, single_count[3]; 152 u64 *count, single_count[3];
153 ssize_t res; 153 unsigned int cpu;
154 int cpu, nv; 154 size_t res, nv;
155 int scaled; 155 int scaled;
156 156
157 count = event_res[run_idx][counter]; 157 count = event_res[run_idx][counter];
@@ -165,6 +165,7 @@ static void read_counter(int counter)
165 165
166 res = read(fd[cpu][counter], single_count, nv * sizeof(u64)); 166 res = read(fd[cpu][counter], single_count, nv * sizeof(u64));
167 assert(res == nv * sizeof(u64)); 167 assert(res == nv * sizeof(u64));
168
168 close(fd[cpu][counter]); 169 close(fd[cpu][counter]);
169 fd[cpu][counter] = -1; 170 fd[cpu][counter] = -1;
170 171
@@ -192,15 +193,13 @@ static void read_counter(int counter)
192 /* 193 /*
193 * Save the full runtime - to allow normalization during printout: 194 * Save the full runtime - to allow normalization during printout:
194 */ 195 */
195 if (attrs[counter].type == PERF_TYPE_SOFTWARE && 196 if (MATCH_EVENT(SOFTWARE, SW_TASK_CLOCK, counter))
196 attrs[counter].config == PERF_COUNT_SW_TASK_CLOCK)
197 runtime_nsecs[run_idx] = count[0]; 197 runtime_nsecs[run_idx] = count[0];
198 if (attrs[counter].type == PERF_TYPE_HARDWARE && 198 if (MATCH_EVENT(HARDWARE, HW_CPU_CYCLES, counter))
199 attrs[counter].config == PERF_COUNT_HW_CPU_CYCLES)
200 runtime_cycles[run_idx] = count[0]; 199 runtime_cycles[run_idx] = count[0];
201} 200}
202 201
203static int run_perf_stat(int argc, const char **argv) 202static int run_perf_stat(int argc __used, const char **argv)
204{ 203{
205 unsigned long long t0, t1; 204 unsigned long long t0, t1;
206 int status = 0; 205 int status = 0;
@@ -240,7 +239,8 @@ static int run_perf_stat(int argc, const char **argv)
240 /* 239 /*
241 * Wait until the parent tells us to go. 240 * Wait until the parent tells us to go.
242 */ 241 */
243 read(go_pipe[0], &buf, 1); 242 if (read(go_pipe[0], &buf, 1) == -1)
243 perror("unable to read pipe");
244 244
245 execvp(argv[0], (char **)argv); 245 execvp(argv[0], (char **)argv);
246 246
@@ -253,7 +253,8 @@ static int run_perf_stat(int argc, const char **argv)
253 */ 253 */
254 close(child_ready_pipe[1]); 254 close(child_ready_pipe[1]);
255 close(go_pipe[0]); 255 close(go_pipe[0]);
256 read(child_ready_pipe[0], &buf, 1); 256 if (read(child_ready_pipe[0], &buf, 1) == -1)
257 perror("unable to read pipe");
257 close(child_ready_pipe[0]); 258 close(child_ready_pipe[0]);
258 259
259 for (counter = 0; counter < nr_counters; counter++) 260 for (counter = 0; counter < nr_counters; counter++)
@@ -290,9 +291,7 @@ static void nsec_printout(int counter, u64 *count, u64 *noise)
290 291
291 fprintf(stderr, " %14.6f %-24s", msecs, event_name(counter)); 292 fprintf(stderr, " %14.6f %-24s", msecs, event_name(counter));
292 293
293 if (attrs[counter].type == PERF_TYPE_SOFTWARE && 294 if (MATCH_EVENT(SOFTWARE, SW_TASK_CLOCK, counter)) {
294 attrs[counter].config == PERF_COUNT_SW_TASK_CLOCK) {
295
296 if (walltime_nsecs_avg) 295 if (walltime_nsecs_avg)
297 fprintf(stderr, " # %10.3f CPUs ", 296 fprintf(stderr, " # %10.3f CPUs ",
298 (double)count[0] / (double)walltime_nsecs_avg); 297 (double)count[0] / (double)walltime_nsecs_avg);
@@ -305,9 +304,7 @@ static void abs_printout(int counter, u64 *count, u64 *noise)
305 fprintf(stderr, " %14Ld %-24s", count[0], event_name(counter)); 304 fprintf(stderr, " %14Ld %-24s", count[0], event_name(counter));
306 305
307 if (runtime_cycles_avg && 306 if (runtime_cycles_avg &&
308 attrs[counter].type == PERF_TYPE_HARDWARE && 307 MATCH_EVENT(HARDWARE, HW_INSTRUCTIONS, counter)) {
309 attrs[counter].config == PERF_COUNT_HW_INSTRUCTIONS) {
310
311 fprintf(stderr, " # %10.3f IPC ", 308 fprintf(stderr, " # %10.3f IPC ",
312 (double)count[0] / (double)runtime_cycles_avg); 309 (double)count[0] / (double)runtime_cycles_avg);
313 } else { 310 } else {
@@ -390,7 +387,7 @@ static void calc_avg(void)
390 event_res_avg[j]+1, event_res[i][j]+1); 387 event_res_avg[j]+1, event_res[i][j]+1);
391 update_avg("counter/2", j, 388 update_avg("counter/2", j,
392 event_res_avg[j]+2, event_res[i][j]+2); 389 event_res_avg[j]+2, event_res[i][j]+2);
393 if (event_scaled[i][j] != -1) 390 if (event_scaled[i][j] != (u64)-1)
394 update_avg("scaled", j, 391 update_avg("scaled", j,
395 event_scaled_avg + j, event_scaled[i]+j); 392 event_scaled_avg + j, event_scaled[i]+j);
396 else 393 else
@@ -499,7 +496,7 @@ static const struct option options[] = {
499 "stat events on existing pid"), 496 "stat events on existing pid"),
500 OPT_BOOLEAN('a', "all-cpus", &system_wide, 497 OPT_BOOLEAN('a', "all-cpus", &system_wide,
501 "system-wide collection from all CPUs"), 498 "system-wide collection from all CPUs"),
502 OPT_BOOLEAN('S', "scale", &scale, 499 OPT_BOOLEAN('c', "scale", &scale,
503 "scale/normalize counters"), 500 "scale/normalize counters"),
504 OPT_BOOLEAN('v', "verbose", &verbose, 501 OPT_BOOLEAN('v', "verbose", &verbose,
505 "be more verbose (show counter open errors, etc)"), 502 "be more verbose (show counter open errors, etc)"),
@@ -510,11 +507,12 @@ static const struct option options[] = {
510 OPT_END() 507 OPT_END()
511}; 508};
512 509
513int cmd_stat(int argc, const char **argv, const char *prefix) 510int cmd_stat(int argc, const char **argv, const char *prefix __used)
514{ 511{
515 int status; 512 int status;
516 513
517 argc = parse_options(argc, argv, options, stat_usage, 0); 514 argc = parse_options(argc, argv, options, stat_usage,
515 PARSE_OPT_STOP_AT_NON_OPTION);
518 if (!argc) 516 if (!argc)
519 usage_with_options(stat_usage, options); 517 usage_with_options(stat_usage, options);
520 if (run_count <= 0 || run_count > MAX_RUN) 518 if (run_count <= 0 || run_count > MAX_RUN)
@@ -528,7 +526,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix)
528 526
529 nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); 527 nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
530 assert(nr_cpus <= MAX_NR_CPUS); 528 assert(nr_cpus <= MAX_NR_CPUS);
531 assert(nr_cpus >= 0); 529 assert((int)nr_cpus >= 0);
532 530
533 /* 531 /*
534 * We dont want to block the signals - that would cause 532 * We dont want to block the signals - that would cause
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index cf0d21f1ae10..7de28ce9ca26 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -23,7 +23,7 @@
23#include "util/symbol.h" 23#include "util/symbol.h"
24#include "util/color.h" 24#include "util/color.h"
25#include "util/util.h" 25#include "util/util.h"
26#include "util/rbtree.h" 26#include <linux/rbtree.h>
27#include "util/parse-options.h" 27#include "util/parse-options.h"
28#include "util/parse-events.h" 28#include "util/parse-events.h"
29 29
@@ -31,6 +31,8 @@
31#include <fcntl.h> 31#include <fcntl.h>
32 32
33#include <stdio.h> 33#include <stdio.h>
34#include <termios.h>
35#include <unistd.h>
34 36
35#include <errno.h> 37#include <errno.h>
36#include <time.h> 38#include <time.h>
@@ -54,10 +56,11 @@ static int system_wide = 0;
54 56
55static int default_interval = 100000; 57static int default_interval = 100000;
56 58
57static u64 count_filter = 5; 59static int count_filter = 5;
58static int print_entries = 15; 60static int print_entries = 15;
59 61
60static int target_pid = -1; 62static int target_pid = -1;
63static int inherit = 0;
61static int profile_cpu = -1; 64static int profile_cpu = -1;
62static int nr_cpus = 0; 65static int nr_cpus = 0;
63static unsigned int realtime_prio = 0; 66static unsigned int realtime_prio = 0;
@@ -66,16 +69,30 @@ static unsigned int page_size;
66static unsigned int mmap_pages = 16; 69static unsigned int mmap_pages = 16;
67static int freq = 0; 70static int freq = 0;
68static int verbose = 0; 71static int verbose = 0;
69 72static char *vmlinux = NULL;
70static char *sym_filter;
71static unsigned long filter_start;
72static unsigned long filter_end;
73 73
74static int delay_secs = 2; 74static int delay_secs = 2;
75static int zero; 75static int zero;
76static int dump_symtab; 76static int dump_symtab;
77 77
78/* 78/*
79 * Source
80 */
81
82struct source_line {
83 u64 eip;
84 unsigned long count[MAX_COUNTERS];
85 char *line;
86 struct source_line *next;
87};
88
89static char *sym_filter = NULL;
90struct sym_entry *sym_filter_entry = NULL;
91static int sym_pcnt_filter = 5;
92static int sym_counter = 0;
93static int display_weighted = -1;
94
95/*
79 * Symbols 96 * Symbols
80 */ 97 */
81 98
@@ -89,9 +106,237 @@ struct sym_entry {
89 unsigned long snap_count; 106 unsigned long snap_count;
90 double weight; 107 double weight;
91 int skip; 108 int skip;
109 struct source_line *source;
110 struct source_line *lines;
111 struct source_line **lines_tail;
112 pthread_mutex_t source_lock;
92}; 113};
93 114
94struct sym_entry *sym_filter_entry; 115/*
116 * Source functions
117 */
118
119static void parse_source(struct sym_entry *syme)
120{
121 struct symbol *sym;
122 struct module *module;
123 struct section *section = NULL;
124 FILE *file;
125 char command[PATH_MAX*2], *path = vmlinux;
126 u64 start, end, len;
127
128 if (!syme)
129 return;
130
131 if (syme->lines) {
132 pthread_mutex_lock(&syme->source_lock);
133 goto out_assign;
134 }
135
136 sym = (struct symbol *)(syme + 1);
137 module = sym->module;
138
139 if (module)
140 path = module->path;
141 if (!path)
142 return;
143
144 start = sym->obj_start;
145 if (!start)
146 start = sym->start;
147
148 if (module) {
149 section = module->sections->find_section(module->sections, ".text");
150 if (section)
151 start -= section->vma;
152 }
153
154 end = start + sym->end - sym->start + 1;
155 len = sym->end - sym->start;
156
157 sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s", start, end, path);
158
159 file = popen(command, "r");
160 if (!file)
161 return;
162
163 pthread_mutex_lock(&syme->source_lock);
164 syme->lines_tail = &syme->lines;
165 while (!feof(file)) {
166 struct source_line *src;
167 size_t dummy = 0;
168 char *c;
169
170 src = malloc(sizeof(struct source_line));
171 assert(src != NULL);
172 memset(src, 0, sizeof(struct source_line));
173
174 if (getline(&src->line, &dummy, file) < 0)
175 break;
176 if (!src->line)
177 break;
178
179 c = strchr(src->line, '\n');
180 if (c)
181 *c = 0;
182
183 src->next = NULL;
184 *syme->lines_tail = src;
185 syme->lines_tail = &src->next;
186
187 if (strlen(src->line)>8 && src->line[8] == ':') {
188 src->eip = strtoull(src->line, NULL, 16);
189 if (section)
190 src->eip += section->vma;
191 }
192 if (strlen(src->line)>8 && src->line[16] == ':') {
193 src->eip = strtoull(src->line, NULL, 16);
194 if (section)
195 src->eip += section->vma;
196 }
197 }
198 pclose(file);
199out_assign:
200 sym_filter_entry = syme;
201 pthread_mutex_unlock(&syme->source_lock);
202}
203
204static void __zero_source_counters(struct sym_entry *syme)
205{
206 int i;
207 struct source_line *line;
208
209 line = syme->lines;
210 while (line) {
211 for (i = 0; i < nr_counters; i++)
212 line->count[i] = 0;
213 line = line->next;
214 }
215}
216
217static void record_precise_ip(struct sym_entry *syme, int counter, u64 ip)
218{
219 struct source_line *line;
220
221 if (syme != sym_filter_entry)
222 return;
223
224 if (pthread_mutex_trylock(&syme->source_lock))
225 return;
226
227 if (!syme->source)
228 goto out_unlock;
229
230 for (line = syme->lines; line; line = line->next) {
231 if (line->eip == ip) {
232 line->count[counter]++;
233 break;
234 }
235 if (line->eip > ip)
236 break;
237 }
238out_unlock:
239 pthread_mutex_unlock(&syme->source_lock);
240}
241
242static void lookup_sym_source(struct sym_entry *syme)
243{
244 struct symbol *symbol = (struct symbol *)(syme + 1);
245 struct source_line *line;
246 char pattern[PATH_MAX];
247 char *idx;
248
249 sprintf(pattern, "<%s>:", symbol->name);
250
251 if (symbol->module) {
252 idx = strstr(pattern, "\t");
253 if (idx)
254 *idx = 0;
255 }
256
257 pthread_mutex_lock(&syme->source_lock);
258 for (line = syme->lines; line; line = line->next) {
259 if (strstr(line->line, pattern)) {
260 syme->source = line;
261 break;
262 }
263 }
264 pthread_mutex_unlock(&syme->source_lock);
265}
266
267static void show_lines(struct source_line *queue, int count, int total)
268{
269 int i;
270 struct source_line *line;
271
272 line = queue;
273 for (i = 0; i < count; i++) {
274 float pcnt = 100.0*(float)line->count[sym_counter]/(float)total;
275
276 printf("%8li %4.1f%%\t%s\n", line->count[sym_counter], pcnt, line->line);
277 line = line->next;
278 }
279}
280
281#define TRACE_COUNT 3
282
283static void show_details(struct sym_entry *syme)
284{
285 struct symbol *symbol;
286 struct source_line *line;
287 struct source_line *line_queue = NULL;
288 int displayed = 0;
289 int line_queue_count = 0, total = 0, more = 0;
290
291 if (!syme)
292 return;
293
294 if (!syme->source)
295 lookup_sym_source(syme);
296
297 if (!syme->source)
298 return;
299
300 symbol = (struct symbol *)(syme + 1);
301 printf("Showing %s for %s\n", event_name(sym_counter), symbol->name);
302 printf(" Events Pcnt (>=%d%%)\n", sym_pcnt_filter);
303
304 pthread_mutex_lock(&syme->source_lock);
305 line = syme->source;
306 while (line) {
307 total += line->count[sym_counter];
308 line = line->next;
309 }
310
311 line = syme->source;
312 while (line) {
313 float pcnt = 0.0;
314
315 if (!line_queue_count)
316 line_queue = line;
317 line_queue_count++;
318
319 if (line->count[sym_counter])
320 pcnt = 100.0 * line->count[sym_counter] / (float)total;
321 if (pcnt >= (float)sym_pcnt_filter) {
322 if (displayed <= print_entries)
323 show_lines(line_queue, line_queue_count, total);
324 else more++;
325 displayed += line_queue_count;
326 line_queue_count = 0;
327 line_queue = NULL;
328 } else if (line_queue_count > TRACE_COUNT) {
329 line_queue = line_queue->next;
330 line_queue_count--;
331 }
332
333 line->count[sym_counter] = zero ? 0 : line->count[sym_counter] * 7 / 8;
334 line = line->next;
335 }
336 pthread_mutex_unlock(&syme->source_lock);
337 if (more)
338 printf("%d lines not displayed, maybe increase display entries [e]\n", more);
339}
95 340
96struct dso *kernel_dso; 341struct dso *kernel_dso;
97 342
@@ -110,6 +355,9 @@ static double sym_weight(const struct sym_entry *sym)
110 double weight = sym->snap_count; 355 double weight = sym->snap_count;
111 int counter; 356 int counter;
112 357
358 if (!display_weighted)
359 return weight;
360
113 for (counter = 1; counter < nr_counters-1; counter++) 361 for (counter = 1; counter < nr_counters-1; counter++)
114 weight *= sym->count[counter]; 362 weight *= sym->count[counter];
115 363
@@ -157,7 +405,7 @@ static void rb_insert_active_sym(struct rb_root *tree, struct sym_entry *se)
157static void print_sym_table(void) 405static void print_sym_table(void)
158{ 406{
159 int printed = 0, j; 407 int printed = 0, j;
160 int counter; 408 int counter, snap = !display_weighted ? sym_counter : 0;
161 float samples_per_sec = samples/delay_secs; 409 float samples_per_sec = samples/delay_secs;
162 float ksamples_per_sec = (samples-userspace_samples)/delay_secs; 410 float ksamples_per_sec = (samples-userspace_samples)/delay_secs;
163 float sum_ksamples = 0.0; 411 float sum_ksamples = 0.0;
@@ -173,7 +421,7 @@ static void print_sym_table(void)
173 pthread_mutex_unlock(&active_symbols_lock); 421 pthread_mutex_unlock(&active_symbols_lock);
174 422
175 list_for_each_entry_safe_from(syme, n, &active_symbols, node) { 423 list_for_each_entry_safe_from(syme, n, &active_symbols, node) {
176 syme->snap_count = syme->count[0]; 424 syme->snap_count = syme->count[snap];
177 if (syme->snap_count != 0) { 425 if (syme->snap_count != 0) {
178 syme->weight = sym_weight(syme); 426 syme->weight = sym_weight(syme);
179 rb_insert_active_sym(&tmp, syme); 427 rb_insert_active_sym(&tmp, syme);
@@ -193,7 +441,7 @@ static void print_sym_table(void)
193 samples_per_sec, 441 samples_per_sec,
194 100.0 - (100.0*((samples_per_sec-ksamples_per_sec)/samples_per_sec))); 442 100.0 - (100.0*((samples_per_sec-ksamples_per_sec)/samples_per_sec)));
195 443
196 if (nr_counters == 1) { 444 if (nr_counters == 1 || !display_weighted) {
197 printf("%Ld", (u64)attrs[0].sample_period); 445 printf("%Ld", (u64)attrs[0].sample_period);
198 if (freq) 446 if (freq)
199 printf("Hz "); 447 printf("Hz ");
@@ -201,7 +449,9 @@ static void print_sym_table(void)
201 printf(" "); 449 printf(" ");
202 } 450 }
203 451
204 for (counter = 0; counter < nr_counters; counter++) { 452 if (!display_weighted)
453 printf("%s", event_name(sym_counter));
454 else for (counter = 0; counter < nr_counters; counter++) {
205 if (counter) 455 if (counter)
206 printf("/"); 456 printf("/");
207 457
@@ -226,6 +476,11 @@ static void print_sym_table(void)
226 476
227 printf("------------------------------------------------------------------------------\n\n"); 477 printf("------------------------------------------------------------------------------\n\n");
228 478
479 if (sym_filter_entry) {
480 show_details(sym_filter_entry);
481 return;
482 }
483
229 if (nr_counters == 1) 484 if (nr_counters == 1)
230 printf(" samples pcnt"); 485 printf(" samples pcnt");
231 else 486 else
@@ -238,59 +493,300 @@ static void print_sym_table(void)
238 for (nd = rb_first(&tmp); nd; nd = rb_next(nd)) { 493 for (nd = rb_first(&tmp); nd; nd = rb_next(nd)) {
239 struct sym_entry *syme = rb_entry(nd, struct sym_entry, rb_node); 494 struct sym_entry *syme = rb_entry(nd, struct sym_entry, rb_node);
240 struct symbol *sym = (struct symbol *)(syme + 1); 495 struct symbol *sym = (struct symbol *)(syme + 1);
241 char *color = PERF_COLOR_NORMAL;
242 double pcnt; 496 double pcnt;
243 497
244 if (++printed > print_entries || syme->snap_count < count_filter) 498 if (++printed > print_entries || (int)syme->snap_count < count_filter)
245 continue; 499 continue;
246 500
247 pcnt = 100.0 - (100.0 * ((sum_ksamples - syme->snap_count) / 501 pcnt = 100.0 - (100.0 * ((sum_ksamples - syme->snap_count) /
248 sum_ksamples)); 502 sum_ksamples));
249 503
250 /* 504 if (nr_counters == 1 || !display_weighted)
251 * We color high-overhead entries in red, mid-overhead
252 * entries in green - and keep the low overhead places
253 * normal:
254 */
255 if (pcnt >= 5.0) {
256 color = PERF_COLOR_RED;
257 } else {
258 if (pcnt >= 0.5)
259 color = PERF_COLOR_GREEN;
260 }
261
262 if (nr_counters == 1)
263 printf("%20.2f - ", syme->weight); 505 printf("%20.2f - ", syme->weight);
264 else 506 else
265 printf("%9.1f %10ld - ", syme->weight, syme->snap_count); 507 printf("%9.1f %10ld - ", syme->weight, syme->snap_count);
266 508
267 color_fprintf(stdout, color, "%4.1f%%", pcnt); 509 percent_color_fprintf(stdout, "%4.1f%%", pcnt);
268 printf(" - %016llx : %s\n", sym->start, sym->name); 510 printf(" - %016llx : %s", sym->start, sym->name);
511 if (sym->module)
512 printf("\t[%s]", sym->module->name);
513 printf("\n");
514 }
515}
516
517static void prompt_integer(int *target, const char *msg)
518{
519 char *buf = malloc(0), *p;
520 size_t dummy = 0;
521 int tmp;
522
523 fprintf(stdout, "\n%s: ", msg);
524 if (getline(&buf, &dummy, stdin) < 0)
525 return;
526
527 p = strchr(buf, '\n');
528 if (p)
529 *p = 0;
530
531 p = buf;
532 while(*p) {
533 if (!isdigit(*p))
534 goto out_free;
535 p++;
536 }
537 tmp = strtoul(buf, NULL, 10);
538 *target = tmp;
539out_free:
540 free(buf);
541}
542
543static void prompt_percent(int *target, const char *msg)
544{
545 int tmp = 0;
546
547 prompt_integer(&tmp, msg);
548 if (tmp >= 0 && tmp <= 100)
549 *target = tmp;
550}
551
552static void prompt_symbol(struct sym_entry **target, const char *msg)
553{
554 char *buf = malloc(0), *p;
555 struct sym_entry *syme = *target, *n, *found = NULL;
556 size_t dummy = 0;
557
558 /* zero counters of active symbol */
559 if (syme) {
560 pthread_mutex_lock(&syme->source_lock);
561 __zero_source_counters(syme);
562 *target = NULL;
563 pthread_mutex_unlock(&syme->source_lock);
564 }
565
566 fprintf(stdout, "\n%s: ", msg);
567 if (getline(&buf, &dummy, stdin) < 0)
568 goto out_free;
569
570 p = strchr(buf, '\n');
571 if (p)
572 *p = 0;
573
574 pthread_mutex_lock(&active_symbols_lock);
575 syme = list_entry(active_symbols.next, struct sym_entry, node);
576 pthread_mutex_unlock(&active_symbols_lock);
577
578 list_for_each_entry_safe_from(syme, n, &active_symbols, node) {
579 struct symbol *sym = (struct symbol *)(syme + 1);
580
581 if (!strcmp(buf, sym->name)) {
582 found = syme;
583 break;
584 }
269 } 585 }
586
587 if (!found) {
588 fprintf(stderr, "Sorry, %s is not active.\n", sym_filter);
589 sleep(1);
590 return;
591 } else
592 parse_source(found);
593
594out_free:
595 free(buf);
270} 596}
271 597
272static void *display_thread(void *arg) 598static void print_mapped_keys(void)
599{
600 char *name = NULL;
601
602 if (sym_filter_entry) {
603 struct symbol *sym = (struct symbol *)(sym_filter_entry+1);
604 name = sym->name;
605 }
606
607 fprintf(stdout, "\nMapped keys:\n");
608 fprintf(stdout, "\t[d] display refresh delay. \t(%d)\n", delay_secs);
609 fprintf(stdout, "\t[e] display entries (lines). \t(%d)\n", print_entries);
610
611 if (nr_counters > 1)
612 fprintf(stdout, "\t[E] active event counter. \t(%s)\n", event_name(sym_counter));
613
614 fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", count_filter);
615
616 if (vmlinux) {
617 fprintf(stdout, "\t[F] annotate display filter (percent). \t(%d%%)\n", sym_pcnt_filter);
618 fprintf(stdout, "\t[s] annotate symbol. \t(%s)\n", name?: "NULL");
619 fprintf(stdout, "\t[S] stop annotation.\n");
620 }
621
622 if (nr_counters > 1)
623 fprintf(stdout, "\t[w] toggle display weighted/count[E]r. \t(%d)\n", display_weighted ? 1 : 0);
624
625 fprintf(stdout, "\t[z] toggle sample zeroing. \t(%d)\n", zero ? 1 : 0);
626 fprintf(stdout, "\t[qQ] quit.\n");
627}
628
629static int key_mapped(int c)
630{
631 switch (c) {
632 case 'd':
633 case 'e':
634 case 'f':
635 case 'z':
636 case 'q':
637 case 'Q':
638 return 1;
639 case 'E':
640 case 'w':
641 return nr_counters > 1 ? 1 : 0;
642 case 'F':
643 case 's':
644 case 'S':
645 return vmlinux ? 1 : 0;
646 }
647
648 return 0;
649}
650
651static void handle_keypress(int c)
652{
653 if (!key_mapped(c)) {
654 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN };
655 struct termios tc, save;
656
657 print_mapped_keys();
658 fprintf(stdout, "\nEnter selection, or unmapped key to continue: ");
659 fflush(stdout);
660
661 tcgetattr(0, &save);
662 tc = save;
663 tc.c_lflag &= ~(ICANON | ECHO);
664 tc.c_cc[VMIN] = 0;
665 tc.c_cc[VTIME] = 0;
666 tcsetattr(0, TCSANOW, &tc);
667
668 poll(&stdin_poll, 1, -1);
669 c = getc(stdin);
670
671 tcsetattr(0, TCSAFLUSH, &save);
672 if (!key_mapped(c))
673 return;
674 }
675
676 switch (c) {
677 case 'd':
678 prompt_integer(&delay_secs, "Enter display delay");
679 break;
680 case 'e':
681 prompt_integer(&print_entries, "Enter display entries (lines)");
682 break;
683 case 'E':
684 if (nr_counters > 1) {
685 int i;
686
687 fprintf(stderr, "\nAvailable events:");
688 for (i = 0; i < nr_counters; i++)
689 fprintf(stderr, "\n\t%d %s", i, event_name(i));
690
691 prompt_integer(&sym_counter, "Enter details event counter");
692
693 if (sym_counter >= nr_counters) {
694 fprintf(stderr, "Sorry, no such event, using %s.\n", event_name(0));
695 sym_counter = 0;
696 sleep(1);
697 }
698 } else sym_counter = 0;
699 break;
700 case 'f':
701 prompt_integer(&count_filter, "Enter display event count filter");
702 break;
703 case 'F':
704 prompt_percent(&sym_pcnt_filter, "Enter details display event filter (percent)");
705 break;
706 case 'q':
707 case 'Q':
708 printf("exiting.\n");
709 exit(0);
710 case 's':
711 prompt_symbol(&sym_filter_entry, "Enter details symbol");
712 break;
713 case 'S':
714 if (!sym_filter_entry)
715 break;
716 else {
717 struct sym_entry *syme = sym_filter_entry;
718
719 pthread_mutex_lock(&syme->source_lock);
720 sym_filter_entry = NULL;
721 __zero_source_counters(syme);
722 pthread_mutex_unlock(&syme->source_lock);
723 }
724 break;
725 case 'w':
726 display_weighted = ~display_weighted;
727 break;
728 case 'z':
729 zero = ~zero;
730 break;
731 }
732}
733
734static void *display_thread(void *arg __used)
273{ 735{
274 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN }; 736 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN };
275 int delay_msecs = delay_secs * 1000; 737 struct termios tc, save;
738 int delay_msecs, c;
276 739
277 printf("PerfTop refresh period: %d seconds\n", delay_secs); 740 tcgetattr(0, &save);
741 tc = save;
742 tc.c_lflag &= ~(ICANON | ECHO);
743 tc.c_cc[VMIN] = 0;
744 tc.c_cc[VTIME] = 0;
745
746repeat:
747 delay_msecs = delay_secs * 1000;
748 tcsetattr(0, TCSANOW, &tc);
749 /* trash return*/
750 getc(stdin);
278 751
279 do { 752 do {
280 print_sym_table(); 753 print_sym_table();
281 } while (!poll(&stdin_poll, 1, delay_msecs) == 1); 754 } while (!poll(&stdin_poll, 1, delay_msecs) == 1);
282 755
283 printf("key pressed - exiting.\n"); 756 c = getc(stdin);
284 exit(0); 757 tcsetattr(0, TCSAFLUSH, &save);
758
759 handle_keypress(c);
760 goto repeat;
285 761
286 return NULL; 762 return NULL;
287} 763}
288 764
765/* Tag samples to be skipped. */
766static const char *skip_symbols[] = {
767 "default_idle",
768 "cpu_idle",
769 "enter_idle",
770 "exit_idle",
771 "mwait_idle",
772 "mwait_idle_with_hints",
773 "ppc64_runlatch_off",
774 "pseries_dedicated_idle_sleep",
775 NULL
776};
777
289static int symbol_filter(struct dso *self, struct symbol *sym) 778static int symbol_filter(struct dso *self, struct symbol *sym)
290{ 779{
291 static int filter_match;
292 struct sym_entry *syme; 780 struct sym_entry *syme;
293 const char *name = sym->name; 781 const char *name = sym->name;
782 int i;
783
784 /*
785 * ppc64 uses function descriptors and appends a '.' to the
786 * start of every instruction address. Remove it.
787 */
788 if (name[0] == '.')
789 name++;
294 790
295 if (!strcmp(name, "_text") || 791 if (!strcmp(name, "_text") ||
296 !strcmp(name, "_etext") || 792 !strcmp(name, "_etext") ||
@@ -302,37 +798,17 @@ static int symbol_filter(struct dso *self, struct symbol *sym)
302 return 1; 798 return 1;
303 799
304 syme = dso__sym_priv(self, sym); 800 syme = dso__sym_priv(self, sym);
305 /* Tag samples to be skipped. */ 801 pthread_mutex_init(&syme->source_lock, NULL);
306 if (!strcmp("default_idle", name) || 802 if (!sym_filter_entry && sym_filter && !strcmp(name, sym_filter))
307 !strcmp("cpu_idle", name) || 803 sym_filter_entry = syme;
308 !strcmp("enter_idle", name) || 804
309 !strcmp("exit_idle", name) || 805 for (i = 0; skip_symbols[i]; i++) {
310 !strcmp("mwait_idle", name)) 806 if (!strcmp(skip_symbols[i], name)) {
311 syme->skip = 1; 807 syme->skip = 1;
312 808 break;
313 if (filter_match == 1) {
314 filter_end = sym->start;
315 filter_match = -1;
316 if (filter_end - filter_start > 10000) {
317 fprintf(stderr,
318 "hm, too large filter symbol <%s> - skipping.\n",
319 sym_filter);
320 fprintf(stderr, "symbol filter start: %016lx\n",
321 filter_start);
322 fprintf(stderr, " end: %016lx\n",
323 filter_end);
324 filter_end = filter_start = 0;
325 sym_filter = NULL;
326 sleep(1);
327 } 809 }
328 } 810 }
329 811
330 if (filter_match == 0 && sym_filter && !strcmp(name, sym_filter)) {
331 filter_match = 1;
332 filter_start = sym->start;
333 }
334
335
336 return 0; 812 return 0;
337} 813}
338 814
@@ -340,12 +816,13 @@ static int parse_symbols(void)
340{ 816{
341 struct rb_node *node; 817 struct rb_node *node;
342 struct symbol *sym; 818 struct symbol *sym;
819 int modules = vmlinux ? 1 : 0;
343 820
344 kernel_dso = dso__new("[kernel]", sizeof(struct sym_entry)); 821 kernel_dso = dso__new("[kernel]", sizeof(struct sym_entry));
345 if (kernel_dso == NULL) 822 if (kernel_dso == NULL)
346 return -1; 823 return -1;
347 824
348 if (dso__load_kernel(kernel_dso, NULL, symbol_filter, 1) != 0) 825 if (dso__load_kernel(kernel_dso, vmlinux, symbol_filter, verbose, modules) <= 0)
349 goto out_delete_dso; 826 goto out_delete_dso;
350 827
351 node = rb_first(&kernel_dso->syms); 828 node = rb_first(&kernel_dso->syms);
@@ -367,8 +844,6 @@ out_delete_dso:
367 return -1; 844 return -1;
368} 845}
369 846
370#define TRACE_COUNT 3
371
372/* 847/*
373 * Binary search in the histogram table and record the hit: 848 * Binary search in the histogram table and record the hit:
374 */ 849 */
@@ -381,6 +856,7 @@ static void record_ip(u64 ip, int counter)
381 856
382 if (!syme->skip) { 857 if (!syme->skip) {
383 syme->count[counter]++; 858 syme->count[counter]++;
859 record_precise_ip(syme, counter, ip);
384 pthread_mutex_lock(&active_symbols_lock); 860 pthread_mutex_lock(&active_symbols_lock);
385 if (list_empty(&syme->node) || !syme->node.next) 861 if (list_empty(&syme->node) || !syme->node.next)
386 __list_insert_active_sym(syme); 862 __list_insert_active_sym(syme);
@@ -407,7 +883,7 @@ static void process_event(u64 ip, int counter, int user)
407struct mmap_data { 883struct mmap_data {
408 int counter; 884 int counter;
409 void *base; 885 void *base;
410 unsigned int mask; 886 int mask;
411 unsigned int prev; 887 unsigned int prev;
412}; 888};
413 889
@@ -538,7 +1014,7 @@ int group_fd;
538static void start_counter(int i, int counter) 1014static void start_counter(int i, int counter)
539{ 1015{
540 struct perf_counter_attr *attr; 1016 struct perf_counter_attr *attr;
541 unsigned int cpu; 1017 int cpu;
542 1018
543 cpu = profile_cpu; 1019 cpu = profile_cpu;
544 if (target_pid == -1 && profile_cpu == -1) 1020 if (target_pid == -1 && profile_cpu == -1)
@@ -548,6 +1024,7 @@ static void start_counter(int i, int counter)
548 1024
549 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID; 1025 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID;
550 attr->freq = freq; 1026 attr->freq = freq;
1027 attr->inherit = (cpu < 0) && inherit;
551 1028
552try_again: 1029try_again:
553 fd[i][counter] = sys_perf_counter_open(attr, target_pid, cpu, group_fd, 0); 1030 fd[i][counter] = sys_perf_counter_open(attr, target_pid, cpu, group_fd, 0);
@@ -661,6 +1138,7 @@ static const struct option options[] = {
661 "system-wide collection from all CPUs"), 1138 "system-wide collection from all CPUs"),
662 OPT_INTEGER('C', "CPU", &profile_cpu, 1139 OPT_INTEGER('C', "CPU", &profile_cpu,
663 "CPU to profile on"), 1140 "CPU to profile on"),
1141 OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"),
664 OPT_INTEGER('m', "mmap-pages", &mmap_pages, 1142 OPT_INTEGER('m', "mmap-pages", &mmap_pages,
665 "number of mmap data pages"), 1143 "number of mmap data pages"),
666 OPT_INTEGER('r', "realtime", &realtime_prio, 1144 OPT_INTEGER('r', "realtime", &realtime_prio,
@@ -673,9 +1151,11 @@ static const struct option options[] = {
673 "only display functions with more events than this"), 1151 "only display functions with more events than this"),
674 OPT_BOOLEAN('g', "group", &group, 1152 OPT_BOOLEAN('g', "group", &group,
675 "put the counters into a counter group"), 1153 "put the counters into a counter group"),
676 OPT_STRING('s', "sym-filter", &sym_filter, "pattern", 1154 OPT_BOOLEAN('i', "inherit", &inherit,
677 "only display symbols matchig this pattern"), 1155 "child tasks inherit counters"),
678 OPT_BOOLEAN('z', "zero", &group, 1156 OPT_STRING('s', "sym-annotate", &sym_filter, "symbol name",
1157 "symbol to annotate - requires -k option"),
1158 OPT_BOOLEAN('z', "zero", &zero,
679 "zero history across updates"), 1159 "zero history across updates"),
680 OPT_INTEGER('F', "freq", &freq, 1160 OPT_INTEGER('F', "freq", &freq,
681 "profile at this frequency"), 1161 "profile at this frequency"),
@@ -686,10 +1166,12 @@ static const struct option options[] = {
686 OPT_END() 1166 OPT_END()
687}; 1167};
688 1168
689int cmd_top(int argc, const char **argv, const char *prefix) 1169int cmd_top(int argc, const char **argv, const char *prefix __used)
690{ 1170{
691 int counter; 1171 int counter;
692 1172
1173 symbol__init();
1174
693 page_size = sysconf(_SC_PAGE_SIZE); 1175 page_size = sysconf(_SC_PAGE_SIZE);
694 1176
695 argc = parse_options(argc, argv, options, top_usage, 0); 1177 argc = parse_options(argc, argv, options, top_usage, 0);
@@ -715,6 +1197,7 @@ int cmd_top(int argc, const char **argv, const char *prefix)
715 delay_secs = 1; 1197 delay_secs = 1;
716 1198
717 parse_symbols(); 1199 parse_symbols();
1200 parse_source(sym_filter_entry);
718 1201
719 /* 1202 /*
720 * Fill in the ones not specifically initialized via -c: 1203 * Fill in the ones not specifically initialized via -c:
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 4eb725933703..31982ad064b4 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -12,6 +12,8 @@
12#include "util/cache.h" 12#include "util/cache.h"
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"
16#include "util/string.h"
15 17
16const char perf_usage_string[] = 18const char perf_usage_string[] =
17 "perf [--version] [--help] COMMAND [ARGS]"; 19 "perf [--version] [--help] COMMAND [ARGS]";
@@ -25,6 +27,8 @@ struct pager_config {
25 int val; 27 int val;
26}; 28};
27 29
30static char debugfs_mntpt[MAXPATHLEN];
31
28static int pager_command_config(const char *var, const char *value, void *data) 32static int pager_command_config(const char *var, const char *value, void *data)
29{ 33{
30 struct pager_config *c = data; 34 struct pager_config *c = data;
@@ -56,6 +60,15 @@ static void commit_pager_choice(void) {
56 } 60 }
57} 61}
58 62
63static void set_debugfs_path(void)
64{
65 char *path;
66
67 path = getenv(PERF_DEBUGFS_ENVIRONMENT);
68 snprintf(debugfs_path, MAXPATHLEN, "%s/%s", path ?: debugfs_mntpt,
69 "tracing/events");
70}
71
59static int handle_options(const char*** argv, int* argc, int* envchanged) 72static int handle_options(const char*** argv, int* argc, int* envchanged)
60{ 73{
61 int handled = 0; 74 int handled = 0;
@@ -122,6 +135,22 @@ static int handle_options(const char*** argv, int* argc, int* envchanged)
122 setenv(PERF_WORK_TREE_ENVIRONMENT, cmd + 12, 1); 135 setenv(PERF_WORK_TREE_ENVIRONMENT, cmd + 12, 1);
123 if (envchanged) 136 if (envchanged)
124 *envchanged = 1; 137 *envchanged = 1;
138 } else if (!strcmp(cmd, "--debugfs-dir")) {
139 if (*argc < 2) {
140 fprintf(stderr, "No directory given for --debugfs-dir.\n");
141 usage(perf_usage_string);
142 }
143 strncpy(debugfs_mntpt, (*argv)[1], MAXPATHLEN);
144 debugfs_mntpt[MAXPATHLEN - 1] = '\0';
145 if (envchanged)
146 *envchanged = 1;
147 (*argv)++;
148 (*argc)--;
149 } else if (!prefixcmp(cmd, "--debugfs-dir=")) {
150 strncpy(debugfs_mntpt, cmd + 14, MAXPATHLEN);
151 debugfs_mntpt[MAXPATHLEN - 1] = '\0';
152 if (envchanged)
153 *envchanged = 1;
125 } else { 154 } else {
126 fprintf(stderr, "Unknown option: %s\n", cmd); 155 fprintf(stderr, "Unknown option: %s\n", cmd);
127 usage(perf_usage_string); 156 usage(perf_usage_string);
@@ -228,9 +257,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
228 if (use_pager == -1 && p->option & USE_PAGER) 257 if (use_pager == -1 && p->option & USE_PAGER)
229 use_pager = 1; 258 use_pager = 1;
230 commit_pager_choice(); 259 commit_pager_choice();
231 260 set_debugfs_path();
232 if (p->option & NEED_WORK_TREE)
233 /* setup_work_tree() */;
234 261
235 status = p->fn(argc, argv, prefix); 262 status = p->fn(argc, argv, prefix);
236 if (status) 263 if (status)
@@ -266,7 +293,7 @@ static void handle_internal_command(int argc, const char **argv)
266 { "annotate", cmd_annotate, 0 }, 293 { "annotate", cmd_annotate, 0 },
267 { "version", cmd_version, 0 }, 294 { "version", cmd_version, 0 },
268 }; 295 };
269 int i; 296 unsigned int i;
270 static const char ext[] = STRIP_EXTENSION; 297 static const char ext[] = STRIP_EXTENSION;
271 298
272 if (sizeof(ext) > 1) { 299 if (sizeof(ext) > 1) {
@@ -349,6 +376,49 @@ static int run_argv(int *argcp, const char ***argv)
349 return done_alias; 376 return done_alias;
350} 377}
351 378
379/* mini /proc/mounts parser: searching for "^blah /mount/point debugfs" */
380static void get_debugfs_mntpt(void)
381{
382 FILE *file;
383 char fs_type[100];
384 char debugfs[MAXPATHLEN];
385
386 /*
387 * try the standard location
388 */
389 if (valid_debugfs_mount("/sys/kernel/debug/") == 0) {
390 strcpy(debugfs_mntpt, "/sys/kernel/debug/");
391 return;
392 }
393
394 /*
395 * try the sane location
396 */
397 if (valid_debugfs_mount("/debug/") == 0) {
398 strcpy(debugfs_mntpt, "/debug/");
399 return;
400 }
401
402 /*
403 * give up and parse /proc/mounts
404 */
405 file = fopen("/proc/mounts", "r");
406 if (file == NULL)
407 return;
408
409 while (fscanf(file, "%*s %"
410 STR(MAXPATHLEN)
411 "s %99s %*s %*d %*d\n",
412 debugfs, fs_type) == 2) {
413 if (strcmp(fs_type, "debugfs") == 0)
414 break;
415 }
416 fclose(file);
417 if (strcmp(fs_type, "debugfs") == 0) {
418 strncpy(debugfs_mntpt, debugfs, MAXPATHLEN);
419 debugfs_mntpt[MAXPATHLEN - 1] = '\0';
420 }
421}
352 422
353int main(int argc, const char **argv) 423int main(int argc, const char **argv)
354{ 424{
@@ -357,7 +427,8 @@ int main(int argc, const char **argv)
357 cmd = perf_extract_argv0_path(argv[0]); 427 cmd = perf_extract_argv0_path(argv[0]);
358 if (!cmd) 428 if (!cmd)
359 cmd = "perf-help"; 429 cmd = "perf-help";
360 430 /* get debugfs mount point from /proc/mounts */
431 get_debugfs_mntpt();
361 /* 432 /*
362 * "perf-xxxx" is the same as "perf xxxx", but we obviously: 433 * "perf-xxxx" is the same as "perf xxxx", but we obviously:
363 * 434 *
@@ -380,6 +451,7 @@ int main(int argc, const char **argv)
380 argc--; 451 argc--;
381 handle_options(&argv, &argc, NULL); 452 handle_options(&argv, &argc, NULL);
382 commit_pager_choice(); 453 commit_pager_choice();
454 set_debugfs_path();
383 if (argc > 0) { 455 if (argc > 0) {
384 if (!prefixcmp(argv[0], "--")) 456 if (!prefixcmp(argv[0], "--"))
385 argv[0] += 2; 457 argv[0] += 2;
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 8f729aedc1a3..e5148e2b6134 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -1,7 +1,13 @@
1#ifndef _PERF_PERF_H 1#ifndef _PERF_PERF_H
2#define _PERF_PERF_H 2#define _PERF_PERF_H
3 3
4#if defined(__x86_64__) || defined(__i386__) 4#if defined(__i386__)
5#include "../../arch/x86/include/asm/unistd.h"
6#define rmb() asm volatile("lock; addl $0,0(%%esp)" ::: "memory")
7#define cpu_relax() asm volatile("rep; nop" ::: "memory");
8#endif
9
10#if defined(__x86_64__)
5#include "../../arch/x86/include/asm/unistd.h" 11#include "../../arch/x86/include/asm/unistd.h"
6#define rmb() asm volatile("lfence" ::: "memory") 12#define rmb() asm volatile("lfence" ::: "memory")
7#define cpu_relax() asm volatile("rep; nop" ::: "memory"); 13#define cpu_relax() asm volatile("rep; nop" ::: "memory");
@@ -29,6 +35,12 @@
29#define cpu_relax() asm volatile("" ::: "memory") 35#define cpu_relax() asm volatile("" ::: "memory")
30#endif 36#endif
31 37
38#ifdef __hppa__
39#include "../../arch/parisc/include/asm/unistd.h"
40#define rmb() asm volatile("" ::: "memory")
41#define cpu_relax() asm volatile("" ::: "memory");
42#endif
43
32#include <time.h> 44#include <time.h>
33#include <unistd.h> 45#include <unistd.h>
34#include <sys/types.h> 46#include <sys/types.h>
@@ -62,6 +74,8 @@ static inline unsigned long long rdclock(void)
62#define __user 74#define __user
63#define asmlinkage 75#define asmlinkage
64 76
77#define __used __attribute__((__unused__))
78
65#define unlikely(x) __builtin_expect(!!(x), 0) 79#define unlikely(x) __builtin_expect(!!(x), 0)
66#define min(x, y) ({ \ 80#define min(x, y) ({ \
67 typeof(x) _min1 = (x); \ 81 typeof(x) _min1 = (x); \
diff --git a/tools/perf/util/alias.c b/tools/perf/util/alias.c
index 9b3dd2b428df..b8144e80bb1e 100644
--- a/tools/perf/util/alias.c
+++ b/tools/perf/util/alias.c
@@ -3,7 +3,7 @@
3static const char *alias_key; 3static const char *alias_key;
4static char *alias_val; 4static char *alias_val;
5 5
6static int alias_lookup_cb(const char *k, const char *v, void *cb) 6static int alias_lookup_cb(const char *k, const char *v, void *cb __used)
7{ 7{
8 if (!prefixcmp(k, "alias.") && !strcmp(k+6, alias_key)) { 8 if (!prefixcmp(k, "alias.") && !strcmp(k+6, alias_key)) {
9 if (!v) 9 if (!v)
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index 393d6146d13b..4b50c412b9c5 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -3,6 +3,7 @@
3 3
4#include "util.h" 4#include "util.h"
5#include "strbuf.h" 5#include "strbuf.h"
6#include "../perf.h"
6 7
7#define PERF_DIR_ENVIRONMENT "PERF_DIR" 8#define PERF_DIR_ENVIRONMENT "PERF_DIR"
8#define PERF_WORK_TREE_ENVIRONMENT "PERF_WORK_TREE" 9#define PERF_WORK_TREE_ENVIRONMENT "PERF_WORK_TREE"
@@ -17,6 +18,7 @@
17#define PERFATTRIBUTES_FILE ".perfattributes" 18#define PERFATTRIBUTES_FILE ".perfattributes"
18#define INFOATTRIBUTES_FILE "info/attributes" 19#define INFOATTRIBUTES_FILE "info/attributes"
19#define ATTRIBUTE_MACRO_PREFIX "[attr]" 20#define ATTRIBUTE_MACRO_PREFIX "[attr]"
21#define PERF_DEBUGFS_ENVIRONMENT "PERF_DEBUGFS_DIR"
20 22
21typedef int (*config_fn_t)(const char *, const char *, void *); 23typedef int (*config_fn_t)(const char *, const char *, void *);
22extern int perf_default_config(const char *, const char *, void *); 24extern int perf_default_config(const char *, const char *, void *);
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index ad3c28578961..011473411642 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -4,52 +4,157 @@
4 * Handle the callchains from the stream in an ad-hoc radix tree and then 4 * Handle the callchains from the stream in an ad-hoc radix tree and then
5 * sort them in an rbtree. 5 * sort them in an rbtree.
6 * 6 *
7 * Using a radix for code path provides a fast retrieval and factorizes
8 * memory use. Also that lets us use the paths in a hierarchical graph view.
9 *
7 */ 10 */
8 11
9#include <stdlib.h> 12#include <stdlib.h>
10#include <stdio.h> 13#include <stdio.h>
11#include <stdbool.h> 14#include <stdbool.h>
12#include <errno.h> 15#include <errno.h>
16#include <math.h>
13 17
14#include "callchain.h" 18#include "callchain.h"
15 19
20#define chain_for_each_child(child, parent) \
21 list_for_each_entry(child, &parent->children, brothers)
16 22
17static void rb_insert_callchain(struct rb_root *root, struct callchain_node *chain) 23static void
24rb_insert_callchain(struct rb_root *root, struct callchain_node *chain,
25 enum chain_mode mode)
18{ 26{
19 struct rb_node **p = &root->rb_node; 27 struct rb_node **p = &root->rb_node;
20 struct rb_node *parent = NULL; 28 struct rb_node *parent = NULL;
21 struct callchain_node *rnode; 29 struct callchain_node *rnode;
30 u64 chain_cumul = cumul_hits(chain);
22 31
23 while (*p) { 32 while (*p) {
33 u64 rnode_cumul;
34
24 parent = *p; 35 parent = *p;
25 rnode = rb_entry(parent, struct callchain_node, rb_node); 36 rnode = rb_entry(parent, struct callchain_node, rb_node);
26 37 rnode_cumul = cumul_hits(rnode);
27 if (rnode->hit < chain->hit) 38
28 p = &(*p)->rb_left; 39 switch (mode) {
29 else 40 case CHAIN_FLAT:
30 p = &(*p)->rb_right; 41 if (rnode->hit < chain->hit)
42 p = &(*p)->rb_left;
43 else
44 p = &(*p)->rb_right;
45 break;
46 case CHAIN_GRAPH_ABS: /* Falldown */
47 case CHAIN_GRAPH_REL:
48 if (rnode_cumul < chain_cumul)
49 p = &(*p)->rb_left;
50 else
51 p = &(*p)->rb_right;
52 break;
53 default:
54 break;
55 }
31 } 56 }
32 57
33 rb_link_node(&chain->rb_node, parent, p); 58 rb_link_node(&chain->rb_node, parent, p);
34 rb_insert_color(&chain->rb_node, root); 59 rb_insert_color(&chain->rb_node, root);
35} 60}
36 61
62static void
63__sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node,
64 u64 min_hit)
65{
66 struct callchain_node *child;
67
68 chain_for_each_child(child, node)
69 __sort_chain_flat(rb_root, child, min_hit);
70
71 if (node->hit && node->hit >= min_hit)
72 rb_insert_callchain(rb_root, node, CHAIN_FLAT);
73}
74
37/* 75/*
38 * Once we get every callchains from the stream, we can now 76 * Once we get every callchains from the stream, we can now
39 * sort them by hit 77 * sort them by hit
40 */ 78 */
41void sort_chain_to_rbtree(struct rb_root *rb_root, struct callchain_node *node) 79static void
80sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node,
81 u64 min_hit, struct callchain_param *param __used)
82{
83 __sort_chain_flat(rb_root, node, min_hit);
84}
85
86static void __sort_chain_graph_abs(struct callchain_node *node,
87 u64 min_hit)
88{
89 struct callchain_node *child;
90
91 node->rb_root = RB_ROOT;
92
93 chain_for_each_child(child, node) {
94 __sort_chain_graph_abs(child, min_hit);
95 if (cumul_hits(child) >= min_hit)
96 rb_insert_callchain(&node->rb_root, child,
97 CHAIN_GRAPH_ABS);
98 }
99}
100
101static void
102sort_chain_graph_abs(struct rb_root *rb_root, struct callchain_node *chain_root,
103 u64 min_hit, struct callchain_param *param __used)
104{
105 __sort_chain_graph_abs(chain_root, min_hit);
106 rb_root->rb_node = chain_root->rb_root.rb_node;
107}
108
109static void __sort_chain_graph_rel(struct callchain_node *node,
110 double min_percent)
42{ 111{
43 struct callchain_node *child; 112 struct callchain_node *child;
113 u64 min_hit;
114
115 node->rb_root = RB_ROOT;
116 min_hit = ceil(node->children_hit * min_percent);
117
118 chain_for_each_child(child, node) {
119 __sort_chain_graph_rel(child, min_percent);
120 if (cumul_hits(child) >= min_hit)
121 rb_insert_callchain(&node->rb_root, child,
122 CHAIN_GRAPH_REL);
123 }
124}
44 125
45 list_for_each_entry(child, &node->children, brothers) 126static void
46 sort_chain_to_rbtree(rb_root, child); 127sort_chain_graph_rel(struct rb_root *rb_root, struct callchain_node *chain_root,
128 u64 min_hit __used, struct callchain_param *param)
129{
130 __sort_chain_graph_rel(chain_root, param->min_percent / 100.0);
131 rb_root->rb_node = chain_root->rb_root.rb_node;
132}
47 133
48 if (node->hit) 134int register_callchain_param(struct callchain_param *param)
49 rb_insert_callchain(rb_root, node); 135{
136 switch (param->mode) {
137 case CHAIN_GRAPH_ABS:
138 param->sort = sort_chain_graph_abs;
139 break;
140 case CHAIN_GRAPH_REL:
141 param->sort = sort_chain_graph_rel;
142 break;
143 case CHAIN_FLAT:
144 param->sort = sort_chain_flat;
145 break;
146 default:
147 return -1;
148 }
149 return 0;
50} 150}
51 151
52static struct callchain_node *create_child(struct callchain_node *parent) 152/*
153 * Create a child for a parent. If inherit_children, then the new child
154 * will become the new parent of it's parent children
155 */
156static struct callchain_node *
157create_child(struct callchain_node *parent, bool inherit_children)
53{ 158{
54 struct callchain_node *new; 159 struct callchain_node *new;
55 160
@@ -61,91 +166,150 @@ static struct callchain_node *create_child(struct callchain_node *parent)
61 new->parent = parent; 166 new->parent = parent;
62 INIT_LIST_HEAD(&new->children); 167 INIT_LIST_HEAD(&new->children);
63 INIT_LIST_HEAD(&new->val); 168 INIT_LIST_HEAD(&new->val);
169
170 if (inherit_children) {
171 struct callchain_node *next;
172
173 list_splice(&parent->children, &new->children);
174 INIT_LIST_HEAD(&parent->children);
175
176 chain_for_each_child(next, new)
177 next->parent = new;
178 }
64 list_add_tail(&new->brothers, &parent->children); 179 list_add_tail(&new->brothers, &parent->children);
65 180
66 return new; 181 return new;
67} 182}
68 183
184/*
185 * Fill the node with callchain values
186 */
69static void 187static void
70fill_node(struct callchain_node *node, struct ip_callchain *chain, int start) 188fill_node(struct callchain_node *node, struct ip_callchain *chain,
189 int start, struct symbol **syms)
71{ 190{
72 int i; 191 unsigned int i;
73 192
74 for (i = start; i < chain->nr; i++) { 193 for (i = start; i < chain->nr; i++) {
75 struct callchain_list *call; 194 struct callchain_list *call;
76 195
77 call = malloc(sizeof(*chain)); 196 call = malloc(sizeof(*call));
78 if (!call) { 197 if (!call) {
79 perror("not enough memory for the code path tree"); 198 perror("not enough memory for the code path tree");
80 return; 199 return;
81 } 200 }
82 call->ip = chain->ips[i]; 201 call->ip = chain->ips[i];
202 call->sym = syms[i];
83 list_add_tail(&call->list, &node->val); 203 list_add_tail(&call->list, &node->val);
84 } 204 }
85 node->val_nr = i - start; 205 node->val_nr = chain->nr - start;
206 if (!node->val_nr)
207 printf("Warning: empty node in callchain tree\n");
86} 208}
87 209
88static void add_child(struct callchain_node *parent, struct ip_callchain *chain) 210static void
211add_child(struct callchain_node *parent, struct ip_callchain *chain,
212 int start, struct symbol **syms)
89{ 213{
90 struct callchain_node *new; 214 struct callchain_node *new;
91 215
92 new = create_child(parent); 216 new = create_child(parent, false);
93 fill_node(new, chain, parent->val_nr); 217 fill_node(new, chain, start, syms);
94 218
219 new->children_hit = 0;
95 new->hit = 1; 220 new->hit = 1;
96} 221}
97 222
223/*
224 * Split the parent in two parts (a new child is created) and
225 * give a part of its callchain to the created child.
226 * Then create another child to host the given callchain of new branch
227 */
98static void 228static void
99split_add_child(struct callchain_node *parent, struct ip_callchain *chain, 229split_add_child(struct callchain_node *parent, struct ip_callchain *chain,
100 struct callchain_list *to_split, int idx) 230 struct callchain_list *to_split, int idx_parents, int idx_local,
231 struct symbol **syms)
101{ 232{
102 struct callchain_node *new; 233 struct callchain_node *new;
234 struct list_head *old_tail;
235 unsigned int idx_total = idx_parents + idx_local;
103 236
104 /* split */ 237 /* split */
105 new = create_child(parent); 238 new = create_child(parent, true);
106 list_move_tail(&to_split->list, &new->val);
107 new->hit = parent->hit;
108 parent->hit = 0;
109 parent->val_nr = idx;
110 239
111 /* create the new one */ 240 /* split the callchain and move a part to the new child */
112 add_child(parent, chain); 241 old_tail = parent->val.prev;
242 list_del_range(&to_split->list, old_tail);
243 new->val.next = &to_split->list;
244 new->val.prev = old_tail;
245 to_split->list.prev = &new->val;
246 old_tail->next = &new->val;
247
248 /* split the hits */
249 new->hit = parent->hit;
250 new->children_hit = parent->children_hit;
251 parent->children_hit = cumul_hits(new);
252 new->val_nr = parent->val_nr - idx_local;
253 parent->val_nr = idx_local;
254
255 /* create a new child for the new branch if any */
256 if (idx_total < chain->nr) {
257 parent->hit = 0;
258 add_child(parent, chain, idx_total, syms);
259 parent->children_hit++;
260 } else {
261 parent->hit = 1;
262 }
113} 263}
114 264
115static int 265static int
116__append_chain(struct callchain_node *root, struct ip_callchain *chain, 266__append_chain(struct callchain_node *root, struct ip_callchain *chain,
117 int start); 267 unsigned int start, struct symbol **syms);
118 268
119static int 269static void
120__append_chain_children(struct callchain_node *root, struct ip_callchain *chain) 270__append_chain_children(struct callchain_node *root, struct ip_callchain *chain,
271 struct symbol **syms, unsigned int start)
121{ 272{
122 struct callchain_node *rnode; 273 struct callchain_node *rnode;
123 274
124 /* lookup in childrens */ 275 /* lookup in childrens */
125 list_for_each_entry(rnode, &root->children, brothers) { 276 chain_for_each_child(rnode, root) {
126 int ret = __append_chain(rnode, chain, root->val_nr); 277 unsigned int ret = __append_chain(rnode, chain, start, syms);
278
127 if (!ret) 279 if (!ret)
128 return 0; 280 goto inc_children_hit;
129 } 281 }
130 return -1; 282 /* nothing in children, add to the current node */
283 add_child(root, chain, start, syms);
284
285inc_children_hit:
286 root->children_hit++;
131} 287}
132 288
133static int 289static int
134__append_chain(struct callchain_node *root, struct ip_callchain *chain, 290__append_chain(struct callchain_node *root, struct ip_callchain *chain,
135 int start) 291 unsigned int start, struct symbol **syms)
136{ 292{
137 struct callchain_list *cnode; 293 struct callchain_list *cnode;
138 int i = start; 294 unsigned int i = start;
139 bool found = false; 295 bool found = false;
140 296
141 /* lookup in the current node */ 297 /*
298 * Lookup in the current node
299 * If we have a symbol, then compare the start to match
300 * anywhere inside a function.
301 */
142 list_for_each_entry(cnode, &root->val, list) { 302 list_for_each_entry(cnode, &root->val, list) {
143 if (cnode->ip != chain->ips[i++]) 303 if (i == chain->nr)
304 break;
305 if (cnode->sym && syms[i]) {
306 if (cnode->sym->start != syms[i]->start)
307 break;
308 } else if (cnode->ip != chain->ips[i])
144 break; 309 break;
145 if (!found) 310 if (!found)
146 found = true; 311 found = true;
147 if (i == chain->nr) 312 i++;
148 break;
149 } 313 }
150 314
151 /* matches not, relay on the parent */ 315 /* matches not, relay on the parent */
@@ -153,22 +317,27 @@ __append_chain(struct callchain_node *root, struct ip_callchain *chain,
153 return -1; 317 return -1;
154 318
155 /* we match only a part of the node. Split it and add the new chain */ 319 /* we match only a part of the node. Split it and add the new chain */
156 if (i < root->val_nr) { 320 if (i - start < root->val_nr) {
157 split_add_child(root, chain, cnode, i); 321 split_add_child(root, chain, cnode, start, i - start, syms);
158 return 0; 322 return 0;
159 } 323 }
160 324
161 /* we match 100% of the path, increment the hit */ 325 /* we match 100% of the path, increment the hit */
162 if (i == root->val_nr) { 326 if (i - start == root->val_nr && i == chain->nr) {
163 root->hit++; 327 root->hit++;
164 return 0; 328 return 0;
165 } 329 }
166 330
167 return __append_chain_children(root, chain); 331 /* We match the node and still have a part remaining */
332 __append_chain_children(root, chain, syms, i);
333
334 return 0;
168} 335}
169 336
170void append_chain(struct callchain_node *root, struct ip_callchain *chain) 337void append_chain(struct callchain_node *root, struct ip_callchain *chain,
338 struct symbol **syms)
171{ 339{
172 if (__append_chain_children(root, chain) == -1) 340 if (!chain->nr)
173 add_child(root, chain); 341 return;
342 __append_chain_children(root, chain, syms, 0);
174} 343}
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index fa1cd2f71fd3..a926ae4f5a16 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -2,22 +2,43 @@
2#define __PERF_CALLCHAIN_H 2#define __PERF_CALLCHAIN_H
3 3
4#include "../perf.h" 4#include "../perf.h"
5#include "list.h" 5#include <linux/list.h>
6#include "rbtree.h" 6#include <linux/rbtree.h>
7#include "symbol.h"
7 8
9enum chain_mode {
10 CHAIN_NONE,
11 CHAIN_FLAT,
12 CHAIN_GRAPH_ABS,
13 CHAIN_GRAPH_REL
14};
8 15
9struct callchain_node { 16struct callchain_node {
10 struct callchain_node *parent; 17 struct callchain_node *parent;
11 struct list_head brothers; 18 struct list_head brothers;
12 struct list_head children; 19 struct list_head children;
13 struct list_head val; 20 struct list_head val;
14 struct rb_node rb_node; 21 struct rb_node rb_node; /* to sort nodes in an rbtree */
15 int val_nr; 22 struct rb_root rb_root; /* sorted tree of children */
16 int hit; 23 unsigned int val_nr;
24 u64 hit;
25 u64 children_hit;
26};
27
28struct callchain_param;
29
30typedef void (*sort_chain_func_t)(struct rb_root *, struct callchain_node *,
31 u64, struct callchain_param *);
32
33struct callchain_param {
34 enum chain_mode mode;
35 double min_percent;
36 sort_chain_func_t sort;
17}; 37};
18 38
19struct callchain_list { 39struct callchain_list {
20 unsigned long ip; 40 u64 ip;
41 struct symbol *sym;
21 struct list_head list; 42 struct list_head list;
22}; 43};
23 44
@@ -28,6 +49,12 @@ static inline void callchain_init(struct callchain_node *node)
28 INIT_LIST_HEAD(&node->val); 49 INIT_LIST_HEAD(&node->val);
29} 50}
30 51
31void append_chain(struct callchain_node *root, struct ip_callchain *chain); 52static inline u64 cumul_hits(struct callchain_node *node)
32void sort_chain_to_rbtree(struct rb_root *rb_root, struct callchain_node *node); 53{
54 return node->hit + node->children_hit;
55}
56
57int register_callchain_param(struct callchain_param *param);
58void append_chain(struct callchain_node *root, struct ip_callchain *chain,
59 struct symbol **syms);
33#endif 60#endif
diff --git a/tools/perf/util/color.c b/tools/perf/util/color.c
index 9a8c20ccc53e..90a044d1fe7d 100644
--- a/tools/perf/util/color.c
+++ b/tools/perf/util/color.c
@@ -11,7 +11,8 @@ static int parse_color(const char *name, int len)
11 }; 11 };
12 char *end; 12 char *end;
13 int i; 13 int i;
14 for (i = 0; i < ARRAY_SIZE(color_names); i++) { 14
15 for (i = 0; i < (int)ARRAY_SIZE(color_names); i++) {
15 const char *str = color_names[i]; 16 const char *str = color_names[i];
16 if (!strncasecmp(name, str, len) && !str[len]) 17 if (!strncasecmp(name, str, len) && !str[len])
17 return i - 1; 18 return i - 1;
@@ -28,7 +29,8 @@ static int parse_attr(const char *name, int len)
28 static const char * const attr_names[] = { 29 static const char * const attr_names[] = {
29 "bold", "dim", "ul", "blink", "reverse" 30 "bold", "dim", "ul", "blink", "reverse"
30 }; 31 };
31 int i; 32 unsigned int i;
33
32 for (i = 0; i < ARRAY_SIZE(attr_names); i++) { 34 for (i = 0; i < ARRAY_SIZE(attr_names); i++) {
33 const char *str = attr_names[i]; 35 const char *str = attr_names[i];
34 if (!strncasecmp(name, str, len) && !str[len]) 36 if (!strncasecmp(name, str, len) && !str[len])
@@ -222,10 +224,12 @@ int color_fwrite_lines(FILE *fp, const char *color,
222{ 224{
223 if (!*color) 225 if (!*color)
224 return fwrite(buf, count, 1, fp) != 1; 226 return fwrite(buf, count, 1, fp) != 1;
227
225 while (count) { 228 while (count) {
226 char *p = memchr(buf, '\n', count); 229 char *p = memchr(buf, '\n', count);
230
227 if (p != buf && (fputs(color, fp) < 0 || 231 if (p != buf && (fputs(color, fp) < 0 ||
228 fwrite(buf, p ? p - buf : count, 1, fp) != 1 || 232 fwrite(buf, p ? (size_t)(p - buf) : count, 1, fp) != 1 ||
229 fputs(PERF_COLOR_RESET, fp) < 0)) 233 fputs(PERF_COLOR_RESET, fp) < 0))
230 return -1; 234 return -1;
231 if (!p) 235 if (!p)
@@ -238,4 +242,31 @@ int color_fwrite_lines(FILE *fp, const char *color,
238 return 0; 242 return 0;
239} 243}
240 244
245char *get_percent_color(double percent)
246{
247 char *color = PERF_COLOR_NORMAL;
241 248
249 /*
250 * We color high-overhead entries in red, mid-overhead
251 * entries in green - and keep the low overhead places
252 * normal:
253 */
254 if (percent >= MIN_RED)
255 color = PERF_COLOR_RED;
256 else {
257 if (percent > MIN_GREEN)
258 color = PERF_COLOR_GREEN;
259 }
260 return color;
261}
262
263int percent_color_fprintf(FILE *fp, const char *fmt, double percent)
264{
265 int r;
266 char *color;
267
268 color = get_percent_color(percent);
269 r = color_fprintf(fp, color, fmt, percent);
270
271 return r;
272}
diff --git a/tools/perf/util/color.h b/tools/perf/util/color.h
index 5abfd379582b..706cec50bd25 100644
--- a/tools/perf/util/color.h
+++ b/tools/perf/util/color.h
@@ -15,6 +15,9 @@
15#define PERF_COLOR_CYAN "\033[36m" 15#define PERF_COLOR_CYAN "\033[36m"
16#define PERF_COLOR_BG_RED "\033[41m" 16#define PERF_COLOR_BG_RED "\033[41m"
17 17
18#define MIN_GREEN 0.5
19#define MIN_RED 5.0
20
18/* 21/*
19 * This variable stores the value of color.ui 22 * This variable stores the value of color.ui
20 */ 23 */
@@ -32,5 +35,7 @@ void color_parse_mem(const char *value, int len, const char *var, char *dst);
32int color_fprintf(FILE *fp, const char *color, const char *fmt, ...); 35int color_fprintf(FILE *fp, const char *color, const char *fmt, ...);
33int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...); 36int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...);
34int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf); 37int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf);
38int percent_color_fprintf(FILE *fp, const char *fmt, double percent);
39char *get_percent_color(double percent);
35 40
36#endif /* COLOR_H */ 41#endif /* COLOR_H */
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
index 3dd13faa6a27..780df541006d 100644
--- a/tools/perf/util/config.c
+++ b/tools/perf/util/config.c
@@ -47,10 +47,12 @@ static int get_next_char(void)
47static char *parse_value(void) 47static char *parse_value(void)
48{ 48{
49 static char value[1024]; 49 static char value[1024];
50 int quote = 0, comment = 0, len = 0, space = 0; 50 int quote = 0, comment = 0, space = 0;
51 size_t len = 0;
51 52
52 for (;;) { 53 for (;;) {
53 int c = get_next_char(); 54 int c = get_next_char();
55
54 if (len >= sizeof(value) - 1) 56 if (len >= sizeof(value) - 1)
55 return NULL; 57 return NULL;
56 if (c == '\n') { 58 if (c == '\n') {
@@ -353,13 +355,13 @@ int perf_config_string(const char **dest, const char *var, const char *value)
353 return 0; 355 return 0;
354} 356}
355 357
356static int perf_default_core_config(const char *var, const char *value) 358static int perf_default_core_config(const char *var __used, const char *value __used)
357{ 359{
358 /* Add other config variables here and to Documentation/config.txt. */ 360 /* Add other config variables here and to Documentation/config.txt. */
359 return 0; 361 return 0;
360} 362}
361 363
362int perf_default_config(const char *var, const char *value, void *dummy) 364int perf_default_config(const char *var, const char *value, void *dummy __used)
363{ 365{
364 if (!prefixcmp(var, "core.")) 366 if (!prefixcmp(var, "core."))
365 return perf_default_core_config(var, value); 367 return perf_default_core_config(var, value);
@@ -471,10 +473,10 @@ static int matches(const char* key, const char* value)
471 !regexec(store.value_regex, value, 0, NULL, 0))); 473 !regexec(store.value_regex, value, 0, NULL, 0)));
472} 474}
473 475
474static int store_aux(const char* key, const char* value, void *cb) 476static int store_aux(const char* key, const char* value, void *cb __used)
475{ 477{
478 int section_len;
476 const char *ep; 479 const char *ep;
477 size_t section_len;
478 480
479 switch (store.state) { 481 switch (store.state) {
480 case KEY_SEEN: 482 case KEY_SEEN:
@@ -551,7 +553,7 @@ static int store_write_section(int fd, const char* key)
551 strbuf_addf(&sb, "[%.*s]\n", store.baselen, key); 553 strbuf_addf(&sb, "[%.*s]\n", store.baselen, key);
552 } 554 }
553 555
554 success = write_in_full(fd, sb.buf, sb.len) == sb.len; 556 success = (write_in_full(fd, sb.buf, sb.len) == (ssize_t)sb.len);
555 strbuf_release(&sb); 557 strbuf_release(&sb);
556 558
557 return success; 559 return success;
@@ -599,7 +601,7 @@ static int store_write_pair(int fd, const char* key, const char* value)
599 } 601 }
600 strbuf_addf(&sb, "%s\n", quote); 602 strbuf_addf(&sb, "%s\n", quote);
601 603
602 success = write_in_full(fd, sb.buf, sb.len) == sb.len; 604 success = (write_in_full(fd, sb.buf, sb.len) == (ssize_t)sb.len);
603 strbuf_release(&sb); 605 strbuf_release(&sb);
604 606
605 return success; 607 return success;
@@ -741,7 +743,7 @@ int perf_config_set_multivar(const char* key, const char* value,
741 } else { 743 } else {
742 struct stat st; 744 struct stat st;
743 char* contents; 745 char* contents;
744 size_t contents_sz, copy_begin, copy_end; 746 ssize_t contents_sz, copy_begin, copy_end;
745 int i, new_line = 0; 747 int i, new_line = 0;
746 748
747 if (value_regex == NULL) 749 if (value_regex == NULL)
diff --git a/tools/perf/util/exec_cmd.c b/tools/perf/util/exec_cmd.c
index d39292263153..34a352867382 100644
--- a/tools/perf/util/exec_cmd.c
+++ b/tools/perf/util/exec_cmd.c
@@ -1,6 +1,9 @@
1#include "cache.h" 1#include "cache.h"
2#include "exec_cmd.h" 2#include "exec_cmd.h"
3#include "quote.h" 3#include "quote.h"
4
5#include <string.h>
6
4#define MAX_ARGS 32 7#define MAX_ARGS 32
5 8
6extern char **environ; 9extern char **environ;
@@ -51,7 +54,7 @@ const char *perf_extract_argv0_path(const char *argv0)
51 slash--; 54 slash--;
52 55
53 if (slash >= argv0) { 56 if (slash >= argv0) {
54 argv0_path = strndup(argv0, slash - argv0); 57 argv0_path = xstrndup(argv0, slash - argv0);
55 return slash + 1; 58 return slash + 1;
56 } 59 }
57 60
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 450384b3bbe5..b92a457ca32e 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -185,6 +185,8 @@ static void do_read(int fd, void *buf, size_t size)
185 185
186 if (ret < 0) 186 if (ret < 0)
187 die("failed to read"); 187 die("failed to read");
188 if (ret == 0)
189 die("failed to read: missing data");
188 190
189 size -= ret; 191 size -= ret;
190 buf += ret; 192 buf += ret;
@@ -213,9 +215,10 @@ struct perf_header *perf_header__read(int fd)
213 215
214 for (i = 0; i < nr_attrs; i++) { 216 for (i = 0; i < nr_attrs; i++) {
215 struct perf_header_attr *attr; 217 struct perf_header_attr *attr;
216 off_t tmp = lseek(fd, 0, SEEK_CUR); 218 off_t tmp;
217 219
218 do_read(fd, &f_attr, sizeof(f_attr)); 220 do_read(fd, &f_attr, sizeof(f_attr));
221 tmp = lseek(fd, 0, SEEK_CUR);
219 222
220 attr = perf_header_attr__new(&f_attr.attr); 223 attr = perf_header_attr__new(&f_attr.attr);
221 224
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index b5ef53ad4c7a..bf280449fcfd 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -16,7 +16,7 @@ struct perf_header {
16 int frozen; 16 int frozen;
17 int attrs, size; 17 int attrs, size;
18 struct perf_header_attr **attr; 18 struct perf_header_attr **attr;
19 off_t attr_offset; 19 s64 attr_offset;
20 u64 data_offset; 20 u64 data_offset;
21 u64 data_size; 21 u64 data_size;
22}; 22};
diff --git a/tools/perf/util/help.c b/tools/perf/util/help.c
index 17a00e0df2c4..fbb00978b2e2 100644
--- a/tools/perf/util/help.c
+++ b/tools/perf/util/help.c
@@ -26,7 +26,7 @@ static int term_columns(void)
26 return 80; 26 return 80;
27} 27}
28 28
29void add_cmdname(struct cmdnames *cmds, const char *name, int len) 29void add_cmdname(struct cmdnames *cmds, const char *name, size_t len)
30{ 30{
31 struct cmdname *ent = malloc(sizeof(*ent) + len + 1); 31 struct cmdname *ent = malloc(sizeof(*ent) + len + 1);
32 32
@@ -40,7 +40,8 @@ void add_cmdname(struct cmdnames *cmds, const char *name, int len)
40 40
41static void clean_cmdnames(struct cmdnames *cmds) 41static void clean_cmdnames(struct cmdnames *cmds)
42{ 42{
43 int i; 43 unsigned int i;
44
44 for (i = 0; i < cmds->cnt; ++i) 45 for (i = 0; i < cmds->cnt; ++i)
45 free(cmds->names[i]); 46 free(cmds->names[i]);
46 free(cmds->names); 47 free(cmds->names);
@@ -57,7 +58,7 @@ static int cmdname_compare(const void *a_, const void *b_)
57 58
58static void uniq(struct cmdnames *cmds) 59static void uniq(struct cmdnames *cmds)
59{ 60{
60 int i, j; 61 unsigned int i, j;
61 62
62 if (!cmds->cnt) 63 if (!cmds->cnt)
63 return; 64 return;
@@ -71,7 +72,7 @@ static void uniq(struct cmdnames *cmds)
71 72
72void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes) 73void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes)
73{ 74{
74 int ci, cj, ei; 75 size_t ci, cj, ei;
75 int cmp; 76 int cmp;
76 77
77 ci = cj = ei = 0; 78 ci = cj = ei = 0;
@@ -106,8 +107,9 @@ static void pretty_print_string_list(struct cmdnames *cmds, int longest)
106 printf(" "); 107 printf(" ");
107 108
108 for (j = 0; j < cols; j++) { 109 for (j = 0; j < cols; j++) {
109 int n = j * rows + i; 110 unsigned int n = j * rows + i;
110 int size = space; 111 unsigned int size = space;
112
111 if (n >= cmds->cnt) 113 if (n >= cmds->cnt)
112 break; 114 break;
113 if (j == cols-1 || n + rows >= cmds->cnt) 115 if (j == cols-1 || n + rows >= cmds->cnt)
@@ -208,7 +210,7 @@ void load_command_list(const char *prefix,
208void list_commands(const char *title, struct cmdnames *main_cmds, 210void list_commands(const char *title, struct cmdnames *main_cmds,
209 struct cmdnames *other_cmds) 211 struct cmdnames *other_cmds)
210{ 212{
211 int i, longest = 0; 213 unsigned int i, longest = 0;
212 214
213 for (i = 0; i < main_cmds->cnt; i++) 215 for (i = 0; i < main_cmds->cnt; i++)
214 if (longest < main_cmds->names[i]->len) 216 if (longest < main_cmds->names[i]->len)
@@ -239,7 +241,8 @@ void list_commands(const char *title, struct cmdnames *main_cmds,
239 241
240int is_in_cmdlist(struct cmdnames *c, const char *s) 242int is_in_cmdlist(struct cmdnames *c, const char *s)
241{ 243{
242 int i; 244 unsigned int i;
245
243 for (i = 0; i < c->cnt; i++) 246 for (i = 0; i < c->cnt; i++)
244 if (!strcmp(s, c->names[i]->name)) 247 if (!strcmp(s, c->names[i]->name))
245 return 1; 248 return 1;
@@ -271,7 +274,8 @@ static int levenshtein_compare(const void *p1, const void *p2)
271 274
272static void add_cmd_list(struct cmdnames *cmds, struct cmdnames *old) 275static void add_cmd_list(struct cmdnames *cmds, struct cmdnames *old)
273{ 276{
274 int i; 277 unsigned int i;
278
275 ALLOC_GROW(cmds->names, cmds->cnt + old->cnt, cmds->alloc); 279 ALLOC_GROW(cmds->names, cmds->cnt + old->cnt, cmds->alloc);
276 280
277 for (i = 0; i < old->cnt; i++) 281 for (i = 0; i < old->cnt; i++)
@@ -283,7 +287,7 @@ static void add_cmd_list(struct cmdnames *cmds, struct cmdnames *old)
283 287
284const char *help_unknown_cmd(const char *cmd) 288const char *help_unknown_cmd(const char *cmd)
285{ 289{
286 int i, n = 0, best_similarity = 0; 290 unsigned int i, n = 0, best_similarity = 0;
287 struct cmdnames main_cmds, other_cmds; 291 struct cmdnames main_cmds, other_cmds;
288 292
289 memset(&main_cmds, 0, sizeof(main_cmds)); 293 memset(&main_cmds, 0, sizeof(main_cmds));
@@ -345,7 +349,7 @@ const char *help_unknown_cmd(const char *cmd)
345 exit(1); 349 exit(1);
346} 350}
347 351
348int cmd_version(int argc, const char **argv, const char *prefix) 352int cmd_version(int argc __used, const char **argv __used, const char *prefix __used)
349{ 353{
350 printf("perf version %s\n", perf_version_string); 354 printf("perf version %s\n", perf_version_string);
351 return 0; 355 return 0;
diff --git a/tools/perf/util/help.h b/tools/perf/util/help.h
index 56bc15406ffc..7128783637b4 100644
--- a/tools/perf/util/help.h
+++ b/tools/perf/util/help.h
@@ -2,8 +2,8 @@
2#define HELP_H 2#define HELP_H
3 3
4struct cmdnames { 4struct cmdnames {
5 int alloc; 5 size_t alloc;
6 int cnt; 6 size_t cnt;
7 struct cmdname { 7 struct cmdname {
8 size_t len; /* also used for similarity index in help.c */ 8 size_t len; /* also used for similarity index in help.c */
9 char name[FLEX_ARRAY]; 9 char name[FLEX_ARRAY];
@@ -19,7 +19,7 @@ static inline void mput_char(char c, unsigned int num)
19void load_command_list(const char *prefix, 19void load_command_list(const char *prefix,
20 struct cmdnames *main_cmds, 20 struct cmdnames *main_cmds,
21 struct cmdnames *other_cmds); 21 struct cmdnames *other_cmds);
22void add_cmdname(struct cmdnames *cmds, const char *name, int len); 22void add_cmdname(struct cmdnames *cmds, const char *name, size_t len);
23/* Here we require that excludes is a sorted list. */ 23/* Here we require that excludes is a sorted list. */
24void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes); 24void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes);
25int is_in_cmdlist(struct cmdnames *c, const char *s); 25int is_in_cmdlist(struct cmdnames *c, const char *s);
diff --git a/tools/perf/util/include/asm/system.h b/tools/perf/util/include/asm/system.h
new file mode 100644
index 000000000000..710cecca972d
--- /dev/null
+++ b/tools/perf/util/include/asm/system.h
@@ -0,0 +1 @@
/* Empty */
diff --git a/tools/perf/util/include/linux/kernel.h b/tools/perf/util/include/linux/kernel.h
new file mode 100644
index 000000000000..a6b87390cb52
--- /dev/null
+++ b/tools/perf/util/include/linux/kernel.h
@@ -0,0 +1,29 @@
1#ifndef PERF_LINUX_KERNEL_H_
2#define PERF_LINUX_KERNEL_H_
3
4#ifndef offsetof
5#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
6#endif
7
8#ifndef container_of
9/**
10 * container_of - cast a member of a structure out to the containing structure
11 * @ptr: the pointer to the member.
12 * @type: the type of the container struct this is embedded in.
13 * @member: the name of the member within the struct.
14 *
15 */
16#define container_of(ptr, type, member) ({ \
17 const typeof(((type *)0)->member) * __mptr = (ptr); \
18 (type *)((char *)__mptr - offsetof(type, member)); })
19#endif
20
21#ifndef max
22#define max(x, y) ({ \
23 typeof(x) _max1 = (x); \
24 typeof(y) _max2 = (y); \
25 (void) (&_max1 == &_max2); \
26 _max1 > _max2 ? _max1 : _max2; })
27#endif
28
29#endif
diff --git a/tools/perf/util/include/linux/list.h b/tools/perf/util/include/linux/list.h
new file mode 100644
index 000000000000..dbe4b814382a
--- /dev/null
+++ b/tools/perf/util/include/linux/list.h
@@ -0,0 +1,18 @@
1#include "../../../../include/linux/list.h"
2
3#ifndef PERF_LIST_H
4#define PERF_LIST_H
5/**
6 * list_del_range - deletes range of entries from list.
7 * @begin: first element in the range to delete from the list.
8 * @end: last element in the range to delete from the list.
9 * Note: list_empty on the range of entries does not return true after this,
10 * the entries is in an undefined state.
11 */
12static inline void list_del_range(struct list_head *begin,
13 struct list_head *end)
14{
15 begin->prev->next = end->next;
16 end->next->prev = begin->prev;
17}
18#endif
diff --git a/tools/perf/util/include/linux/module.h b/tools/perf/util/include/linux/module.h
new file mode 100644
index 000000000000..b43e2dc21e04
--- /dev/null
+++ b/tools/perf/util/include/linux/module.h
@@ -0,0 +1,6 @@
1#ifndef PERF_LINUX_MODULE_H
2#define PERF_LINUX_MODULE_H
3
4#define EXPORT_SYMBOL(name)
5
6#endif
diff --git a/tools/perf/util/include/linux/poison.h b/tools/perf/util/include/linux/poison.h
new file mode 100644
index 000000000000..fef6dbc9ce13
--- /dev/null
+++ b/tools/perf/util/include/linux/poison.h
@@ -0,0 +1 @@
#include "../../../../include/linux/poison.h"
diff --git a/tools/perf/util/include/linux/prefetch.h b/tools/perf/util/include/linux/prefetch.h
new file mode 100644
index 000000000000..7841e485d8c3
--- /dev/null
+++ b/tools/perf/util/include/linux/prefetch.h
@@ -0,0 +1,6 @@
1#ifndef PERF_LINUX_PREFETCH_H
2#define PERF_LINUX_PREFETCH_H
3
4static inline void prefetch(void *a __attribute__((unused))) { }
5
6#endif
diff --git a/tools/perf/util/include/linux/rbtree.h b/tools/perf/util/include/linux/rbtree.h
new file mode 100644
index 000000000000..7a243a143037
--- /dev/null
+++ b/tools/perf/util/include/linux/rbtree.h
@@ -0,0 +1 @@
#include "../../../../include/linux/rbtree.h"
diff --git a/tools/perf/util/list.h b/tools/perf/util/list.h
deleted file mode 100644
index e2548e8072cf..000000000000
--- a/tools/perf/util/list.h
+++ /dev/null
@@ -1,603 +0,0 @@
1#ifndef _LINUX_LIST_H
2#define _LINUX_LIST_H
3/*
4 Copyright (C) Cast of dozens, comes from the Linux kernel
5
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of version 2 of the GNU General Public License as
8 published by the Free Software Foundation.
9*/
10
11#include <stddef.h>
12
13/*
14 * These are non-NULL pointers that will result in page faults
15 * under normal circumstances, used to verify that nobody uses
16 * non-initialized list entries.
17 */
18#define LIST_POISON1 ((void *)0x00100100)
19#define LIST_POISON2 ((void *)0x00200200)
20
21/**
22 * container_of - cast a member of a structure out to the containing structure
23 * @ptr: the pointer to the member.
24 * @type: the type of the container struct this is embedded in.
25 * @member: the name of the member within the struct.
26 *
27 */
28#define container_of(ptr, type, member) ({ \
29 const typeof( ((type *)0)->member ) *__mptr = (ptr); \
30 (type *)( (char *)__mptr - offsetof(type,member) );})
31
32/*
33 * Simple doubly linked list implementation.
34 *
35 * Some of the internal functions ("__xxx") are useful when
36 * manipulating whole lists rather than single entries, as
37 * sometimes we already know the next/prev entries and we can
38 * generate better code by using them directly rather than
39 * using the generic single-entry routines.
40 */
41
42struct list_head {
43 struct list_head *next, *prev;
44};
45
46#define LIST_HEAD_INIT(name) { &(name), &(name) }
47
48#define LIST_HEAD(name) \
49 struct list_head name = LIST_HEAD_INIT(name)
50
51static inline void INIT_LIST_HEAD(struct list_head *list)
52{
53 list->next = list;
54 list->prev = list;
55}
56
57/*
58 * Insert a new entry between two known consecutive entries.
59 *
60 * This is only for internal list manipulation where we know
61 * the prev/next entries already!
62 */
63static inline void __list_add(struct list_head *new,
64 struct list_head *prev,
65 struct list_head *next)
66{
67 next->prev = new;
68 new->next = next;
69 new->prev = prev;
70 prev->next = new;
71}
72
73/**
74 * list_add - add a new entry
75 * @new: new entry to be added
76 * @head: list head to add it after
77 *
78 * Insert a new entry after the specified head.
79 * This is good for implementing stacks.
80 */
81static inline void list_add(struct list_head *new, struct list_head *head)
82{
83 __list_add(new, head, head->next);
84}
85
86/**
87 * list_add_tail - add a new entry
88 * @new: new entry to be added
89 * @head: list head to add it before
90 *
91 * Insert a new entry before the specified head.
92 * This is useful for implementing queues.
93 */
94static inline void list_add_tail(struct list_head *new, struct list_head *head)
95{
96 __list_add(new, head->prev, head);
97}
98
99/*
100 * Delete a list entry by making the prev/next entries
101 * point to each other.
102 *
103 * This is only for internal list manipulation where we know
104 * the prev/next entries already!
105 */
106static inline void __list_del(struct list_head * prev, struct list_head * next)
107{
108 next->prev = prev;
109 prev->next = next;
110}
111
112/**
113 * list_del - deletes entry from list.
114 * @entry: the element to delete from the list.
115 * Note: list_empty on entry does not return true after this, the entry is
116 * in an undefined state.
117 */
118static inline void list_del(struct list_head *entry)
119{
120 __list_del(entry->prev, entry->next);
121 entry->next = LIST_POISON1;
122 entry->prev = LIST_POISON2;
123}
124
125/**
126 * list_del_range - deletes range of entries from list.
127 * @beging: first element in the range to delete from the list.
128 * @beging: first element in the range to delete from the list.
129 * Note: list_empty on the range of entries does not return true after this,
130 * the entries is in an undefined state.
131 */
132static inline void list_del_range(struct list_head *begin,
133 struct list_head *end)
134{
135 begin->prev->next = end->next;
136 end->next->prev = begin->prev;
137}
138
139/**
140 * list_replace - replace old entry by new one
141 * @old : the element to be replaced
142 * @new : the new element to insert
143 * Note: if 'old' was empty, it will be overwritten.
144 */
145static inline void list_replace(struct list_head *old,
146 struct list_head *new)
147{
148 new->next = old->next;
149 new->next->prev = new;
150 new->prev = old->prev;
151 new->prev->next = new;
152}
153
154static inline void list_replace_init(struct list_head *old,
155 struct list_head *new)
156{
157 list_replace(old, new);
158 INIT_LIST_HEAD(old);
159}
160
161/**
162 * list_del_init - deletes entry from list and reinitialize it.
163 * @entry: the element to delete from the list.
164 */
165static inline void list_del_init(struct list_head *entry)
166{
167 __list_del(entry->prev, entry->next);
168 INIT_LIST_HEAD(entry);
169}
170
171/**
172 * list_move - delete from one list and add as another's head
173 * @list: the entry to move
174 * @head: the head that will precede our entry
175 */
176static inline void list_move(struct list_head *list, struct list_head *head)
177{
178 __list_del(list->prev, list->next);
179 list_add(list, head);
180}
181
182/**
183 * list_move_tail - delete from one list and add as another's tail
184 * @list: the entry to move
185 * @head: the head that will follow our entry
186 */
187static inline void list_move_tail(struct list_head *list,
188 struct list_head *head)
189{
190 __list_del(list->prev, list->next);
191 list_add_tail(list, head);
192}
193
194/**
195 * list_is_last - tests whether @list is the last entry in list @head
196 * @list: the entry to test
197 * @head: the head of the list
198 */
199static inline int list_is_last(const struct list_head *list,
200 const struct list_head *head)
201{
202 return list->next == head;
203}
204
205/**
206 * list_empty - tests whether a list is empty
207 * @head: the list to test.
208 */
209static inline int list_empty(const struct list_head *head)
210{
211 return head->next == head;
212}
213
214/**
215 * list_empty_careful - tests whether a list is empty and not being modified
216 * @head: the list to test
217 *
218 * Description:
219 * tests whether a list is empty _and_ checks that no other CPU might be
220 * in the process of modifying either member (next or prev)
221 *
222 * NOTE: using list_empty_careful() without synchronization
223 * can only be safe if the only activity that can happen
224 * to the list entry is list_del_init(). Eg. it cannot be used
225 * if another CPU could re-list_add() it.
226 */
227static inline int list_empty_careful(const struct list_head *head)
228{
229 struct list_head *next = head->next;
230 return (next == head) && (next == head->prev);
231}
232
233static inline void __list_splice(struct list_head *list,
234 struct list_head *head)
235{
236 struct list_head *first = list->next;
237 struct list_head *last = list->prev;
238 struct list_head *at = head->next;
239
240 first->prev = head;
241 head->next = first;
242
243 last->next = at;
244 at->prev = last;
245}
246
247/**
248 * list_splice - join two lists
249 * @list: the new list to add.
250 * @head: the place to add it in the first list.
251 */
252static inline void list_splice(struct list_head *list, struct list_head *head)
253{
254 if (!list_empty(list))
255 __list_splice(list, head);
256}
257
258/**
259 * list_splice_init - join two lists and reinitialise the emptied list.
260 * @list: the new list to add.
261 * @head: the place to add it in the first list.
262 *
263 * The list at @list is reinitialised
264 */
265static inline void list_splice_init(struct list_head *list,
266 struct list_head *head)
267{
268 if (!list_empty(list)) {
269 __list_splice(list, head);
270 INIT_LIST_HEAD(list);
271 }
272}
273
274/**
275 * list_entry - get the struct for this entry
276 * @ptr: the &struct list_head pointer.
277 * @type: the type of the struct this is embedded in.
278 * @member: the name of the list_struct within the struct.
279 */
280#define list_entry(ptr, type, member) \
281 container_of(ptr, type, member)
282
283/**
284 * list_first_entry - get the first element from a list
285 * @ptr: the list head to take the element from.
286 * @type: the type of the struct this is embedded in.
287 * @member: the name of the list_struct within the struct.
288 *
289 * Note, that list is expected to be not empty.
290 */
291#define list_first_entry(ptr, type, member) \
292 list_entry((ptr)->next, type, member)
293
294/**
295 * list_for_each - iterate over a list
296 * @pos: the &struct list_head to use as a loop cursor.
297 * @head: the head for your list.
298 */
299#define list_for_each(pos, head) \
300 for (pos = (head)->next; pos != (head); \
301 pos = pos->next)
302
303/**
304 * __list_for_each - iterate over a list
305 * @pos: the &struct list_head to use as a loop cursor.
306 * @head: the head for your list.
307 *
308 * This variant differs from list_for_each() in that it's the
309 * simplest possible list iteration code, no prefetching is done.
310 * Use this for code that knows the list to be very short (empty
311 * or 1 entry) most of the time.
312 */
313#define __list_for_each(pos, head) \
314 for (pos = (head)->next; pos != (head); pos = pos->next)
315
316/**
317 * list_for_each_prev - iterate over a list backwards
318 * @pos: the &struct list_head to use as a loop cursor.
319 * @head: the head for your list.
320 */
321#define list_for_each_prev(pos, head) \
322 for (pos = (head)->prev; pos != (head); \
323 pos = pos->prev)
324
325/**
326 * list_for_each_safe - iterate over a list safe against removal of list entry
327 * @pos: the &struct list_head to use as a loop cursor.
328 * @n: another &struct list_head to use as temporary storage
329 * @head: the head for your list.
330 */
331#define list_for_each_safe(pos, n, head) \
332 for (pos = (head)->next, n = pos->next; pos != (head); \
333 pos = n, n = pos->next)
334
335/**
336 * list_for_each_entry - iterate over list of given type
337 * @pos: the type * to use as a loop cursor.
338 * @head: the head for your list.
339 * @member: the name of the list_struct within the struct.
340 */
341#define list_for_each_entry(pos, head, member) \
342 for (pos = list_entry((head)->next, typeof(*pos), member); \
343 &pos->member != (head); \
344 pos = list_entry(pos->member.next, typeof(*pos), member))
345
346/**
347 * list_for_each_entry_reverse - iterate backwards over list of given type.
348 * @pos: the type * to use as a loop cursor.
349 * @head: the head for your list.
350 * @member: the name of the list_struct within the struct.
351 */
352#define list_for_each_entry_reverse(pos, head, member) \
353 for (pos = list_entry((head)->prev, typeof(*pos), member); \
354 &pos->member != (head); \
355 pos = list_entry(pos->member.prev, typeof(*pos), member))
356
357/**
358 * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue
359 * @pos: the type * to use as a start point
360 * @head: the head of the list
361 * @member: the name of the list_struct within the struct.
362 *
363 * Prepares a pos entry for use as a start point in list_for_each_entry_continue.
364 */
365#define list_prepare_entry(pos, head, member) \
366 ((pos) ? : list_entry(head, typeof(*pos), member))
367
368/**
369 * list_for_each_entry_continue - continue iteration over list of given type
370 * @pos: the type * to use as a loop cursor.
371 * @head: the head for your list.
372 * @member: the name of the list_struct within the struct.
373 *
374 * Continue to iterate over list of given type, continuing after
375 * the current position.
376 */
377#define list_for_each_entry_continue(pos, head, member) \
378 for (pos = list_entry(pos->member.next, typeof(*pos), member); \
379 &pos->member != (head); \
380 pos = list_entry(pos->member.next, typeof(*pos), member))
381
382/**
383 * list_for_each_entry_from - iterate over list of given type from the current point
384 * @pos: the type * to use as a loop cursor.
385 * @head: the head for your list.
386 * @member: the name of the list_struct within the struct.
387 *
388 * Iterate over list of given type, continuing from current position.
389 */
390#define list_for_each_entry_from(pos, head, member) \
391 for (; &pos->member != (head); \
392 pos = list_entry(pos->member.next, typeof(*pos), member))
393
394/**
395 * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
396 * @pos: the type * to use as a loop cursor.
397 * @n: another type * to use as temporary storage
398 * @head: the head for your list.
399 * @member: the name of the list_struct within the struct.
400 */
401#define list_for_each_entry_safe(pos, n, head, member) \
402 for (pos = list_entry((head)->next, typeof(*pos), member), \
403 n = list_entry(pos->member.next, typeof(*pos), member); \
404 &pos->member != (head); \
405 pos = n, n = list_entry(n->member.next, typeof(*n), member))
406
407/**
408 * list_for_each_entry_safe_continue
409 * @pos: the type * to use as a loop cursor.
410 * @n: another type * to use as temporary storage
411 * @head: the head for your list.
412 * @member: the name of the list_struct within the struct.
413 *
414 * Iterate over list of given type, continuing after current point,
415 * safe against removal of list entry.
416 */
417#define list_for_each_entry_safe_continue(pos, n, head, member) \
418 for (pos = list_entry(pos->member.next, typeof(*pos), member), \
419 n = list_entry(pos->member.next, typeof(*pos), member); \
420 &pos->member != (head); \
421 pos = n, n = list_entry(n->member.next, typeof(*n), member))
422
423/**
424 * list_for_each_entry_safe_from
425 * @pos: the type * to use as a loop cursor.
426 * @n: another type * to use as temporary storage
427 * @head: the head for your list.
428 * @member: the name of the list_struct within the struct.
429 *
430 * Iterate over list of given type from current point, safe against
431 * removal of list entry.
432 */
433#define list_for_each_entry_safe_from(pos, n, head, member) \
434 for (n = list_entry(pos->member.next, typeof(*pos), member); \
435 &pos->member != (head); \
436 pos = n, n = list_entry(n->member.next, typeof(*n), member))
437
438/**
439 * list_for_each_entry_safe_reverse
440 * @pos: the type * to use as a loop cursor.
441 * @n: another type * to use as temporary storage
442 * @head: the head for your list.
443 * @member: the name of the list_struct within the struct.
444 *
445 * Iterate backwards over list of given type, safe against removal
446 * of list entry.
447 */
448#define list_for_each_entry_safe_reverse(pos, n, head, member) \
449 for (pos = list_entry((head)->prev, typeof(*pos), member), \
450 n = list_entry(pos->member.prev, typeof(*pos), member); \
451 &pos->member != (head); \
452 pos = n, n = list_entry(n->member.prev, typeof(*n), member))
453
454/*
455 * Double linked lists with a single pointer list head.
456 * Mostly useful for hash tables where the two pointer list head is
457 * too wasteful.
458 * You lose the ability to access the tail in O(1).
459 */
460
461struct hlist_head {
462 struct hlist_node *first;
463};
464
465struct hlist_node {
466 struct hlist_node *next, **pprev;
467};
468
469#define HLIST_HEAD_INIT { .first = NULL }
470#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL }
471#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
472static inline void INIT_HLIST_NODE(struct hlist_node *h)
473{
474 h->next = NULL;
475 h->pprev = NULL;
476}
477
478static inline int hlist_unhashed(const struct hlist_node *h)
479{
480 return !h->pprev;
481}
482
483static inline int hlist_empty(const struct hlist_head *h)
484{
485 return !h->first;
486}
487
488static inline void __hlist_del(struct hlist_node *n)
489{
490 struct hlist_node *next = n->next;
491 struct hlist_node **pprev = n->pprev;
492 *pprev = next;
493 if (next)
494 next->pprev = pprev;
495}
496
497static inline void hlist_del(struct hlist_node *n)
498{
499 __hlist_del(n);
500 n->next = LIST_POISON1;
501 n->pprev = LIST_POISON2;
502}
503
504static inline void hlist_del_init(struct hlist_node *n)
505{
506 if (!hlist_unhashed(n)) {
507 __hlist_del(n);
508 INIT_HLIST_NODE(n);
509 }
510}
511
512static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
513{
514 struct hlist_node *first = h->first;
515 n->next = first;
516 if (first)
517 first->pprev = &n->next;
518 h->first = n;
519 n->pprev = &h->first;
520}
521
522/* next must be != NULL */
523static inline void hlist_add_before(struct hlist_node *n,
524 struct hlist_node *next)
525{
526 n->pprev = next->pprev;
527 n->next = next;
528 next->pprev = &n->next;
529 *(n->pprev) = n;
530}
531
532static inline void hlist_add_after(struct hlist_node *n,
533 struct hlist_node *next)
534{
535 next->next = n->next;
536 n->next = next;
537 next->pprev = &n->next;
538
539 if(next->next)
540 next->next->pprev = &next->next;
541}
542
543#define hlist_entry(ptr, type, member) container_of(ptr,type,member)
544
545#define hlist_for_each(pos, head) \
546 for (pos = (head)->first; pos; \
547 pos = pos->next)
548
549#define hlist_for_each_safe(pos, n, head) \
550 for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
551 pos = n)
552
553/**
554 * hlist_for_each_entry - iterate over list of given type
555 * @tpos: the type * to use as a loop cursor.
556 * @pos: the &struct hlist_node to use as a loop cursor.
557 * @head: the head for your list.
558 * @member: the name of the hlist_node within the struct.
559 */
560#define hlist_for_each_entry(tpos, pos, head, member) \
561 for (pos = (head)->first; \
562 pos && \
563 ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
564 pos = pos->next)
565
566/**
567 * hlist_for_each_entry_continue - iterate over a hlist continuing after current point
568 * @tpos: the type * to use as a loop cursor.
569 * @pos: the &struct hlist_node to use as a loop cursor.
570 * @member: the name of the hlist_node within the struct.
571 */
572#define hlist_for_each_entry_continue(tpos, pos, member) \
573 for (pos = (pos)->next; \
574 pos && \
575 ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
576 pos = pos->next)
577
578/**
579 * hlist_for_each_entry_from - iterate over a hlist continuing from current point
580 * @tpos: the type * to use as a loop cursor.
581 * @pos: the &struct hlist_node to use as a loop cursor.
582 * @member: the name of the hlist_node within the struct.
583 */
584#define hlist_for_each_entry_from(tpos, pos, member) \
585 for (; pos && \
586 ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
587 pos = pos->next)
588
589/**
590 * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
591 * @tpos: the type * to use as a loop cursor.
592 * @pos: the &struct hlist_node to use as a loop cursor.
593 * @n: another &struct hlist_node to use as temporary storage
594 * @head: the head for your list.
595 * @member: the name of the hlist_node within the struct.
596 */
597#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \
598 for (pos = (head)->first; \
599 pos && ({ n = pos->next; 1; }) && \
600 ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
601 pos = n)
602
603#endif
diff --git a/tools/perf/util/module.c b/tools/perf/util/module.c
new file mode 100644
index 000000000000..ddabe925d65d
--- /dev/null
+++ b/tools/perf/util/module.c
@@ -0,0 +1,509 @@
1#include "util.h"
2#include "../perf.h"
3#include "string.h"
4#include "module.h"
5
6#include <libelf.h>
7#include <gelf.h>
8#include <elf.h>
9#include <dirent.h>
10#include <sys/utsname.h>
11
12static unsigned int crc32(const char *p, unsigned int len)
13{
14 int i;
15 unsigned int crc = 0;
16
17 while (len--) {
18 crc ^= *p++;
19 for (i = 0; i < 8; i++)
20 crc = (crc >> 1) ^ ((crc & 1) ? 0xedb88320 : 0);
21 }
22 return crc;
23}
24
25/* module section methods */
26
27struct sec_dso *sec_dso__new_dso(const char *name)
28{
29 struct sec_dso *self = malloc(sizeof(*self) + strlen(name) + 1);
30
31 if (self != NULL) {
32 strcpy(self->name, name);
33 self->secs = RB_ROOT;
34 self->find_section = sec_dso__find_section;
35 }
36
37 return self;
38}
39
40static void sec_dso__delete_section(struct section *self)
41{
42 free(((void *)self));
43}
44
45void sec_dso__delete_sections(struct sec_dso *self)
46{
47 struct section *pos;
48 struct rb_node *next = rb_first(&self->secs);
49
50 while (next) {
51 pos = rb_entry(next, struct section, rb_node);
52 next = rb_next(&pos->rb_node);
53 rb_erase(&pos->rb_node, &self->secs);
54 sec_dso__delete_section(pos);
55 }
56}
57
58void sec_dso__delete_self(struct sec_dso *self)
59{
60 sec_dso__delete_sections(self);
61 free(self);
62}
63
64static void sec_dso__insert_section(struct sec_dso *self, struct section *sec)
65{
66 struct rb_node **p = &self->secs.rb_node;
67 struct rb_node *parent = NULL;
68 const u64 hash = sec->hash;
69 struct section *s;
70
71 while (*p != NULL) {
72 parent = *p;
73 s = rb_entry(parent, struct section, rb_node);
74 if (hash < s->hash)
75 p = &(*p)->rb_left;
76 else
77 p = &(*p)->rb_right;
78 }
79 rb_link_node(&sec->rb_node, parent, p);
80 rb_insert_color(&sec->rb_node, &self->secs);
81}
82
83struct section *sec_dso__find_section(struct sec_dso *self, const char *name)
84{
85 struct rb_node *n;
86 u64 hash;
87 int len;
88
89 if (self == NULL)
90 return NULL;
91
92 len = strlen(name);
93 hash = crc32(name, len);
94
95 n = self->secs.rb_node;
96
97 while (n) {
98 struct section *s = rb_entry(n, struct section, rb_node);
99
100 if (hash < s->hash)
101 n = n->rb_left;
102 else if (hash > s->hash)
103 n = n->rb_right;
104 else {
105 if (!strcmp(name, s->name))
106 return s;
107 else
108 n = rb_next(&s->rb_node);
109 }
110 }
111
112 return NULL;
113}
114
115static size_t sec_dso__fprintf_section(struct section *self, FILE *fp)
116{
117 return fprintf(fp, "name:%s vma:%llx path:%s\n",
118 self->name, self->vma, self->path);
119}
120
121size_t sec_dso__fprintf(struct sec_dso *self, FILE *fp)
122{
123 size_t ret = fprintf(fp, "dso: %s\n", self->name);
124
125 struct rb_node *nd;
126 for (nd = rb_first(&self->secs); nd; nd = rb_next(nd)) {
127 struct section *pos = rb_entry(nd, struct section, rb_node);
128 ret += sec_dso__fprintf_section(pos, fp);
129 }
130
131 return ret;
132}
133
134static struct section *section__new(const char *name, const char *path)
135{
136 struct section *self = calloc(1, sizeof(*self));
137
138 if (!self)
139 goto out_failure;
140
141 self->name = calloc(1, strlen(name) + 1);
142 if (!self->name)
143 goto out_failure;
144
145 self->path = calloc(1, strlen(path) + 1);
146 if (!self->path)
147 goto out_failure;
148
149 strcpy(self->name, name);
150 strcpy(self->path, path);
151 self->hash = crc32(self->name, strlen(name));
152
153 return self;
154
155out_failure:
156 if (self) {
157 if (self->name)
158 free(self->name);
159 if (self->path)
160 free(self->path);
161 free(self);
162 }
163
164 return NULL;
165}
166
167/* module methods */
168
169struct mod_dso *mod_dso__new_dso(const char *name)
170{
171 struct mod_dso *self = malloc(sizeof(*self) + strlen(name) + 1);
172
173 if (self != NULL) {
174 strcpy(self->name, name);
175 self->mods = RB_ROOT;
176 self->find_module = mod_dso__find_module;
177 }
178
179 return self;
180}
181
182static void mod_dso__delete_module(struct module *self)
183{
184 free(((void *)self));
185}
186
187void mod_dso__delete_modules(struct mod_dso *self)
188{
189 struct module *pos;
190 struct rb_node *next = rb_first(&self->mods);
191
192 while (next) {
193 pos = rb_entry(next, struct module, rb_node);
194 next = rb_next(&pos->rb_node);
195 rb_erase(&pos->rb_node, &self->mods);
196 mod_dso__delete_module(pos);
197 }
198}
199
200void mod_dso__delete_self(struct mod_dso *self)
201{
202 mod_dso__delete_modules(self);
203 free(self);
204}
205
206static void mod_dso__insert_module(struct mod_dso *self, struct module *mod)
207{
208 struct rb_node **p = &self->mods.rb_node;
209 struct rb_node *parent = NULL;
210 const u64 hash = mod->hash;
211 struct module *m;
212
213 while (*p != NULL) {
214 parent = *p;
215 m = rb_entry(parent, struct module, rb_node);
216 if (hash < m->hash)
217 p = &(*p)->rb_left;
218 else
219 p = &(*p)->rb_right;
220 }
221 rb_link_node(&mod->rb_node, parent, p);
222 rb_insert_color(&mod->rb_node, &self->mods);
223}
224
225struct module *mod_dso__find_module(struct mod_dso *self, const char *name)
226{
227 struct rb_node *n;
228 u64 hash;
229 int len;
230
231 if (self == NULL)
232 return NULL;
233
234 len = strlen(name);
235 hash = crc32(name, len);
236
237 n = self->mods.rb_node;
238
239 while (n) {
240 struct module *m = rb_entry(n, struct module, rb_node);
241
242 if (hash < m->hash)
243 n = n->rb_left;
244 else if (hash > m->hash)
245 n = n->rb_right;
246 else {
247 if (!strcmp(name, m->name))
248 return m;
249 else
250 n = rb_next(&m->rb_node);
251 }
252 }
253
254 return NULL;
255}
256
257static size_t mod_dso__fprintf_module(struct module *self, FILE *fp)
258{
259 return fprintf(fp, "name:%s path:%s\n", self->name, self->path);
260}
261
262size_t mod_dso__fprintf(struct mod_dso *self, FILE *fp)
263{
264 struct rb_node *nd;
265 size_t ret;
266
267 ret = fprintf(fp, "dso: %s\n", self->name);
268
269 for (nd = rb_first(&self->mods); nd; nd = rb_next(nd)) {
270 struct module *pos = rb_entry(nd, struct module, rb_node);
271
272 ret += mod_dso__fprintf_module(pos, fp);
273 }
274
275 return ret;
276}
277
278static struct module *module__new(const char *name, const char *path)
279{
280 struct module *self = calloc(1, sizeof(*self));
281
282 if (!self)
283 goto out_failure;
284
285 self->name = calloc(1, strlen(name) + 1);
286 if (!self->name)
287 goto out_failure;
288
289 self->path = calloc(1, strlen(path) + 1);
290 if (!self->path)
291 goto out_failure;
292
293 strcpy(self->name, name);
294 strcpy(self->path, path);
295 self->hash = crc32(self->name, strlen(name));
296
297 return self;
298
299out_failure:
300 if (self) {
301 if (self->name)
302 free(self->name);
303 if (self->path)
304 free(self->path);
305 free(self);
306 }
307
308 return NULL;
309}
310
311static int mod_dso__load_sections(struct module *mod)
312{
313 int count = 0, path_len;
314 struct dirent *entry;
315 char *line = NULL;
316 char *dir_path;
317 DIR *dir;
318 size_t n;
319
320 path_len = strlen("/sys/module/");
321 path_len += strlen(mod->name);
322 path_len += strlen("/sections/");
323
324 dir_path = calloc(1, path_len + 1);
325 if (dir_path == NULL)
326 goto out_failure;
327
328 strcat(dir_path, "/sys/module/");
329 strcat(dir_path, mod->name);
330 strcat(dir_path, "/sections/");
331
332 dir = opendir(dir_path);
333 if (dir == NULL)
334 goto out_free;
335
336 while ((entry = readdir(dir))) {
337 struct section *section;
338 char *path, *vma;
339 int line_len;
340 FILE *file;
341
342 if (!strcmp(".", entry->d_name) || !strcmp("..", entry->d_name))
343 continue;
344
345 path = calloc(1, path_len + strlen(entry->d_name) + 1);
346 if (path == NULL)
347 break;
348 strcat(path, dir_path);
349 strcat(path, entry->d_name);
350
351 file = fopen(path, "r");
352 if (file == NULL) {
353 free(path);
354 break;
355 }
356
357 line_len = getline(&line, &n, file);
358 if (line_len < 0) {
359 free(path);
360 fclose(file);
361 break;
362 }
363
364 if (!line) {
365 free(path);
366 fclose(file);
367 break;
368 }
369
370 line[--line_len] = '\0'; /* \n */
371
372 vma = strstr(line, "0x");
373 if (!vma) {
374 free(path);
375 fclose(file);
376 break;
377 }
378 vma += 2;
379
380 section = section__new(entry->d_name, path);
381 if (!section) {
382 fprintf(stderr, "load_sections: allocation error\n");
383 free(path);
384 fclose(file);
385 break;
386 }
387
388 hex2u64(vma, &section->vma);
389 sec_dso__insert_section(mod->sections, section);
390
391 free(path);
392 fclose(file);
393 count++;
394 }
395
396 closedir(dir);
397 free(line);
398 free(dir_path);
399
400 return count;
401
402out_free:
403 free(dir_path);
404
405out_failure:
406 return count;
407}
408
409static int mod_dso__load_module_paths(struct mod_dso *self)
410{
411 struct utsname uts;
412 int count = 0, len;
413 char *line = NULL;
414 FILE *file;
415 char *path;
416 size_t n;
417
418 if (uname(&uts) < 0)
419 goto out_failure;
420
421 len = strlen("/lib/modules/");
422 len += strlen(uts.release);
423 len += strlen("/modules.dep");
424
425 path = calloc(1, len);
426 if (path == NULL)
427 goto out_failure;
428
429 strcat(path, "/lib/modules/");
430 strcat(path, uts.release);
431 strcat(path, "/modules.dep");
432
433 file = fopen(path, "r");
434 free(path);
435 if (file == NULL)
436 goto out_failure;
437
438 while (!feof(file)) {
439 char *path, *name, *tmp;
440 struct module *module;
441 int line_len, len;
442
443 line_len = getline(&line, &n, file);
444 if (line_len < 0)
445 break;
446
447 if (!line)
448 goto out_failure;
449
450 line[--line_len] = '\0'; /* \n */
451
452 path = strtok(line, ":");
453 if (!path)
454 goto out_failure;
455
456 name = strdup(path);
457 name = strtok(name, "/");
458
459 tmp = name;
460
461 while (tmp) {
462 tmp = strtok(NULL, "/");
463 if (tmp)
464 name = tmp;
465 }
466 name = strsep(&name, ".");
467
468 /* Quirk: replace '-' with '_' in sound modules */
469 for (len = strlen(name); len; len--) {
470 if (*(name+len) == '-')
471 *(name+len) = '_';
472 }
473
474 module = module__new(name, path);
475 if (!module) {
476 fprintf(stderr, "load_module_paths: allocation error\n");
477 goto out_failure;
478 }
479 mod_dso__insert_module(self, module);
480
481 module->sections = sec_dso__new_dso("sections");
482 if (!module->sections) {
483 fprintf(stderr, "load_module_paths: allocation error\n");
484 goto out_failure;
485 }
486
487 module->active = mod_dso__load_sections(module);
488
489 if (module->active > 0)
490 count++;
491 }
492
493 free(line);
494 fclose(file);
495
496 return count;
497
498out_failure:
499 return -1;
500}
501
502int mod_dso__load_modules(struct mod_dso *dso)
503{
504 int err;
505
506 err = mod_dso__load_module_paths(dso);
507
508 return err;
509}
diff --git a/tools/perf/util/module.h b/tools/perf/util/module.h
new file mode 100644
index 000000000000..8a592ef641ca
--- /dev/null
+++ b/tools/perf/util/module.h
@@ -0,0 +1,53 @@
1#ifndef _PERF_MODULE_
2#define _PERF_MODULE_ 1
3
4#include <linux/types.h>
5#include "../types.h"
6#include <linux/list.h>
7#include <linux/rbtree.h>
8
9struct section {
10 struct rb_node rb_node;
11 u64 hash;
12 u64 vma;
13 char *name;
14 char *path;
15};
16
17struct sec_dso {
18 struct list_head node;
19 struct rb_root secs;
20 struct section *(*find_section)(struct sec_dso *, const char *name);
21 char name[0];
22};
23
24struct module {
25 struct rb_node rb_node;
26 u64 hash;
27 char *name;
28 char *path;
29 struct sec_dso *sections;
30 int active;
31};
32
33struct mod_dso {
34 struct list_head node;
35 struct rb_root mods;
36 struct module *(*find_module)(struct mod_dso *, const char *name);
37 char name[0];
38};
39
40struct sec_dso *sec_dso__new_dso(const char *name);
41void sec_dso__delete_sections(struct sec_dso *self);
42void sec_dso__delete_self(struct sec_dso *self);
43size_t sec_dso__fprintf(struct sec_dso *self, FILE *fp);
44struct section *sec_dso__find_section(struct sec_dso *self, const char *name);
45
46struct mod_dso *mod_dso__new_dso(const char *name);
47void mod_dso__delete_modules(struct mod_dso *self);
48void mod_dso__delete_self(struct mod_dso *self);
49size_t mod_dso__fprintf(struct mod_dso *self, FILE *fp);
50struct module *mod_dso__find_module(struct mod_dso *self, const char *name);
51int mod_dso__load_modules(struct mod_dso *dso);
52
53#endif /* _PERF_MODULE_ */
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 4d042f104cdc..044178408783 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -5,6 +5,7 @@
5#include "parse-events.h" 5#include "parse-events.h"
6#include "exec_cmd.h" 6#include "exec_cmd.h"
7#include "string.h" 7#include "string.h"
8#include "cache.h"
8 9
9extern char *strcasestr(const char *haystack, const char *needle); 10extern char *strcasestr(const char *haystack, const char *needle);
10 11
@@ -19,6 +20,8 @@ struct event_symbol {
19 char *alias; 20 char *alias;
20}; 21};
21 22
23char debugfs_path[MAXPATHLEN];
24
22#define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x 25#define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x
23#define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x 26#define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x
24 27
@@ -71,8 +74,8 @@ static char *sw_event_names[] = {
71#define MAX_ALIASES 8 74#define MAX_ALIASES 8
72 75
73static char *hw_cache[][MAX_ALIASES] = { 76static char *hw_cache[][MAX_ALIASES] = {
74 { "L1-d$", "l1-d", "l1d", "L1-data", }, 77 { "L1-dcache", "l1-d", "l1d", "L1-data", },
75 { "L1-i$", "l1-i", "l1i", "L1-instruction", }, 78 { "L1-icache", "l1-i", "l1i", "L1-instruction", },
76 { "LLC", "L2" }, 79 { "LLC", "L2" },
77 { "dTLB", "d-tlb", "Data-TLB", }, 80 { "dTLB", "d-tlb", "Data-TLB", },
78 { "iTLB", "i-tlb", "Instruction-TLB", }, 81 { "iTLB", "i-tlb", "Instruction-TLB", },
@@ -110,6 +113,104 @@ static unsigned long hw_cache_stat[C(MAX)] = {
110 [C(BPU)] = (CACHE_READ), 113 [C(BPU)] = (CACHE_READ),
111}; 114};
112 115
116#define for_each_subsystem(sys_dir, sys_dirent, sys_next, file, st) \
117 while (!readdir_r(sys_dir, &sys_dirent, &sys_next) && sys_next) \
118 if (snprintf(file, MAXPATHLEN, "%s/%s", debugfs_path, \
119 sys_dirent.d_name) && \
120 (!stat(file, &st)) && (S_ISDIR(st.st_mode)) && \
121 (strcmp(sys_dirent.d_name, ".")) && \
122 (strcmp(sys_dirent.d_name, "..")))
123
124static int tp_event_has_id(struct dirent *sys_dir, struct dirent *evt_dir)
125{
126 char evt_path[MAXPATHLEN];
127 int fd;
128
129 snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path,
130 sys_dir->d_name, evt_dir->d_name);
131 fd = open(evt_path, O_RDONLY);
132 if (fd < 0)
133 return -EINVAL;
134 close(fd);
135
136 return 0;
137}
138
139#define for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next, file, st) \
140 while (!readdir_r(evt_dir, &evt_dirent, &evt_next) && evt_next) \
141 if (snprintf(file, MAXPATHLEN, "%s/%s/%s", debugfs_path, \
142 sys_dirent.d_name, evt_dirent.d_name) && \
143 (!stat(file, &st)) && (S_ISDIR(st.st_mode)) && \
144 (strcmp(evt_dirent.d_name, ".")) && \
145 (strcmp(evt_dirent.d_name, "..")) && \
146 (!tp_event_has_id(&sys_dirent, &evt_dirent)))
147
148#define MAX_EVENT_LENGTH 30
149
150int valid_debugfs_mount(const char *debugfs)
151{
152 struct statfs st_fs;
153
154 if (statfs(debugfs, &st_fs) < 0)
155 return -ENOENT;
156 else if (st_fs.f_type != (long) DEBUGFS_MAGIC)
157 return -ENOENT;
158 return 0;
159}
160
161static char *tracepoint_id_to_name(u64 config)
162{
163 static char tracepoint_name[2 * MAX_EVENT_LENGTH];
164 DIR *sys_dir, *evt_dir;
165 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
166 struct stat st;
167 char id_buf[4];
168 int fd;
169 u64 id;
170 char evt_path[MAXPATHLEN];
171
172 if (valid_debugfs_mount(debugfs_path))
173 return "unkown";
174
175 sys_dir = opendir(debugfs_path);
176 if (!sys_dir)
177 goto cleanup;
178
179 for_each_subsystem(sys_dir, sys_dirent, sys_next, evt_path, st) {
180 evt_dir = opendir(evt_path);
181 if (!evt_dir)
182 goto cleanup;
183 for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next,
184 evt_path, st) {
185 snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id",
186 debugfs_path, sys_dirent.d_name,
187 evt_dirent.d_name);
188 fd = open(evt_path, O_RDONLY);
189 if (fd < 0)
190 continue;
191 if (read(fd, id_buf, sizeof(id_buf)) < 0) {
192 close(fd);
193 continue;
194 }
195 close(fd);
196 id = atoll(id_buf);
197 if (id == config) {
198 closedir(evt_dir);
199 closedir(sys_dir);
200 snprintf(tracepoint_name, 2 * MAX_EVENT_LENGTH,
201 "%s:%s", sys_dirent.d_name,
202 evt_dirent.d_name);
203 return tracepoint_name;
204 }
205 }
206 closedir(evt_dir);
207 }
208
209cleanup:
210 closedir(sys_dir);
211 return "unkown";
212}
213
113static int is_cache_op_valid(u8 cache_type, u8 cache_op) 214static int is_cache_op_valid(u8 cache_type, u8 cache_op)
114{ 215{
115 if (hw_cache_stat[cache_type] & COP(cache_op)) 216 if (hw_cache_stat[cache_type] & COP(cache_op))
@@ -138,9 +239,15 @@ char *event_name(int counter)
138{ 239{
139 u64 config = attrs[counter].config; 240 u64 config = attrs[counter].config;
140 int type = attrs[counter].type; 241 int type = attrs[counter].type;
242
243 return __event_name(type, config);
244}
245
246char *__event_name(int type, u64 config)
247{
141 static char buf[32]; 248 static char buf[32];
142 249
143 if (attrs[counter].type == PERF_TYPE_RAW) { 250 if (type == PERF_TYPE_RAW) {
144 sprintf(buf, "raw 0x%llx", config); 251 sprintf(buf, "raw 0x%llx", config);
145 return buf; 252 return buf;
146 } 253 }
@@ -177,6 +284,9 @@ char *event_name(int counter)
177 return sw_event_names[config]; 284 return sw_event_names[config];
178 return "unknown-software"; 285 return "unknown-software";
179 286
287 case PERF_TYPE_TRACEPOINT:
288 return tracepoint_id_to_name(config);
289
180 default: 290 default:
181 break; 291 break;
182 } 292 }
@@ -184,16 +294,20 @@ char *event_name(int counter)
184 return "unknown"; 294 return "unknown";
185} 295}
186 296
187static int parse_aliases(const char *str, char *names[][MAX_ALIASES], int size) 297static int parse_aliases(const char **str, char *names[][MAX_ALIASES], int size)
188{ 298{
189 int i, j; 299 int i, j;
300 int n, longest = -1;
190 301
191 for (i = 0; i < size; i++) { 302 for (i = 0; i < size; i++) {
192 for (j = 0; j < MAX_ALIASES; j++) { 303 for (j = 0; j < MAX_ALIASES && names[i][j]; j++) {
193 if (!names[i][j]) 304 n = strlen(names[i][j]);
194 break; 305 if (n > longest && !strncasecmp(*str, names[i][j], n))
195 if (strcasestr(str, names[i][j])) 306 longest = n;
196 return i; 307 }
308 if (longest > 0) {
309 *str += longest;
310 return i;
197 } 311 }
198 } 312 }
199 313
@@ -201,30 +315,53 @@ static int parse_aliases(const char *str, char *names[][MAX_ALIASES], int size)
201} 315}
202 316
203static int 317static int
204parse_generic_hw_symbols(const char *str, struct perf_counter_attr *attr) 318parse_generic_hw_event(const char **str, struct perf_counter_attr *attr)
205{ 319{
206 int cache_type = -1, cache_op = 0, cache_result = 0; 320 const char *s = *str;
321 int cache_type = -1, cache_op = -1, cache_result = -1;
207 322
208 cache_type = parse_aliases(str, hw_cache, PERF_COUNT_HW_CACHE_MAX); 323 cache_type = parse_aliases(&s, hw_cache, PERF_COUNT_HW_CACHE_MAX);
209 /* 324 /*
210 * No fallback - if we cannot get a clear cache type 325 * No fallback - if we cannot get a clear cache type
211 * then bail out: 326 * then bail out:
212 */ 327 */
213 if (cache_type == -1) 328 if (cache_type == -1)
214 return -EINVAL; 329 return 0;
330
331 while ((cache_op == -1 || cache_result == -1) && *s == '-') {
332 ++s;
333
334 if (cache_op == -1) {
335 cache_op = parse_aliases(&s, hw_cache_op,
336 PERF_COUNT_HW_CACHE_OP_MAX);
337 if (cache_op >= 0) {
338 if (!is_cache_op_valid(cache_type, cache_op))
339 return 0;
340 continue;
341 }
342 }
343
344 if (cache_result == -1) {
345 cache_result = parse_aliases(&s, hw_cache_result,
346 PERF_COUNT_HW_CACHE_RESULT_MAX);
347 if (cache_result >= 0)
348 continue;
349 }
350
351 /*
352 * Can't parse this as a cache op or result, so back up
353 * to the '-'.
354 */
355 --s;
356 break;
357 }
215 358
216 cache_op = parse_aliases(str, hw_cache_op, PERF_COUNT_HW_CACHE_OP_MAX);
217 /* 359 /*
218 * Fall back to reads: 360 * Fall back to reads:
219 */ 361 */
220 if (cache_op == -1) 362 if (cache_op == -1)
221 cache_op = PERF_COUNT_HW_CACHE_OP_READ; 363 cache_op = PERF_COUNT_HW_CACHE_OP_READ;
222 364
223 if (!is_cache_op_valid(cache_type, cache_op))
224 return -EINVAL;
225
226 cache_result = parse_aliases(str, hw_cache_result,
227 PERF_COUNT_HW_CACHE_RESULT_MAX);
228 /* 365 /*
229 * Fall back to accesses: 366 * Fall back to accesses:
230 */ 367 */
@@ -234,93 +371,212 @@ parse_generic_hw_symbols(const char *str, struct perf_counter_attr *attr)
234 attr->config = cache_type | (cache_op << 8) | (cache_result << 16); 371 attr->config = cache_type | (cache_op << 8) | (cache_result << 16);
235 attr->type = PERF_TYPE_HW_CACHE; 372 attr->type = PERF_TYPE_HW_CACHE;
236 373
237 return 0; 374 *str = s;
375 return 1;
376}
377
378static int parse_tracepoint_event(const char **strp,
379 struct perf_counter_attr *attr)
380{
381 const char *evt_name;
382 char *flags;
383 char sys_name[MAX_EVENT_LENGTH];
384 char id_buf[4];
385 int fd;
386 unsigned int sys_length, evt_length;
387 u64 id;
388 char evt_path[MAXPATHLEN];
389
390 if (valid_debugfs_mount(debugfs_path))
391 return 0;
392
393 evt_name = strchr(*strp, ':');
394 if (!evt_name)
395 return 0;
396
397 sys_length = evt_name - *strp;
398 if (sys_length >= MAX_EVENT_LENGTH)
399 return 0;
400
401 strncpy(sys_name, *strp, sys_length);
402 sys_name[sys_length] = '\0';
403 evt_name = evt_name + 1;
404
405 flags = strchr(evt_name, ':');
406 if (flags) {
407 *flags = '\0';
408 flags++;
409 if (!strncmp(flags, "record", strlen(flags)))
410 attr->sample_type |= PERF_SAMPLE_RAW;
411 }
412
413 evt_length = strlen(evt_name);
414 if (evt_length >= MAX_EVENT_LENGTH)
415 return 0;
416
417 snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path,
418 sys_name, evt_name);
419 fd = open(evt_path, O_RDONLY);
420 if (fd < 0)
421 return 0;
422
423 if (read(fd, id_buf, sizeof(id_buf)) < 0) {
424 close(fd);
425 return 0;
426 }
427 close(fd);
428 id = atoll(id_buf);
429 attr->config = id;
430 attr->type = PERF_TYPE_TRACEPOINT;
431 *strp = evt_name + evt_length;
432 return 1;
238} 433}
239 434
240static int check_events(const char *str, unsigned int i) 435static int check_events(const char *str, unsigned int i)
241{ 436{
242 if (!strncmp(str, event_symbols[i].symbol, 437 int n;
243 strlen(event_symbols[i].symbol)))
244 return 1;
245 438
246 if (strlen(event_symbols[i].alias)) 439 n = strlen(event_symbols[i].symbol);
247 if (!strncmp(str, event_symbols[i].alias, 440 if (!strncmp(str, event_symbols[i].symbol, n))
248 strlen(event_symbols[i].alias))) 441 return n;
249 return 1; 442
443 n = strlen(event_symbols[i].alias);
444 if (n)
445 if (!strncmp(str, event_symbols[i].alias, n))
446 return n;
250 return 0; 447 return 0;
251} 448}
252 449
253/* 450static int
254 * Each event can have multiple symbolic names. 451parse_symbolic_event(const char **strp, struct perf_counter_attr *attr)
255 * Symbolic names are (almost) exactly matched.
256 */
257static int parse_event_symbols(const char *str, struct perf_counter_attr *attr)
258{ 452{
259 u64 config, id; 453 const char *str = *strp;
260 int type;
261 unsigned int i; 454 unsigned int i;
262 const char *sep, *pstr; 455 int n;
263 456
264 if (str[0] == 'r' && hex2u64(str + 1, &config) > 0) { 457 for (i = 0; i < ARRAY_SIZE(event_symbols); i++) {
265 attr->type = PERF_TYPE_RAW; 458 n = check_events(str, i);
266 attr->config = config; 459 if (n > 0) {
460 attr->type = event_symbols[i].type;
461 attr->config = event_symbols[i].config;
462 *strp = str + n;
463 return 1;
464 }
465 }
466 return 0;
467}
468
469static int parse_raw_event(const char **strp, struct perf_counter_attr *attr)
470{
471 const char *str = *strp;
472 u64 config;
473 int n;
267 474
475 if (*str != 'r')
268 return 0; 476 return 0;
477 n = hex2u64(str + 1, &config);
478 if (n > 0) {
479 *strp = str + n + 1;
480 attr->type = PERF_TYPE_RAW;
481 attr->config = config;
482 return 1;
269 } 483 }
484 return 0;
485}
270 486
271 pstr = str; 487static int
272 sep = strchr(pstr, ':'); 488parse_numeric_event(const char **strp, struct perf_counter_attr *attr)
273 if (sep) { 489{
274 type = atoi(pstr); 490 const char *str = *strp;
275 pstr = sep + 1; 491 char *endp;
276 id = atoi(pstr); 492 unsigned long type;
277 sep = strchr(pstr, ':'); 493 u64 config;
278 if (sep) { 494
279 pstr = sep + 1; 495 type = strtoul(str, &endp, 0);
280 if (strchr(pstr, 'k')) 496 if (endp > str && type < PERF_TYPE_MAX && *endp == ':') {
281 attr->exclude_user = 1; 497 str = endp + 1;
282 if (strchr(pstr, 'u')) 498 config = strtoul(str, &endp, 0);
283 attr->exclude_kernel = 1; 499 if (endp > str) {
500 attr->type = type;
501 attr->config = config;
502 *strp = endp;
503 return 1;
284 } 504 }
285 attr->type = type; 505 }
286 attr->config = id; 506 return 0;
507}
287 508
509static int
510parse_event_modifier(const char **strp, struct perf_counter_attr *attr)
511{
512 const char *str = *strp;
513 int eu = 1, ek = 1, eh = 1;
514
515 if (*str++ != ':')
288 return 0; 516 return 0;
517 while (*str) {
518 if (*str == 'u')
519 eu = 0;
520 else if (*str == 'k')
521 ek = 0;
522 else if (*str == 'h')
523 eh = 0;
524 else
525 break;
526 ++str;
289 } 527 }
528 if (str >= *strp + 2) {
529 *strp = str;
530 attr->exclude_user = eu;
531 attr->exclude_kernel = ek;
532 attr->exclude_hv = eh;
533 return 1;
534 }
535 return 0;
536}
290 537
291 for (i = 0; i < ARRAY_SIZE(event_symbols); i++) { 538/*
292 if (check_events(str, i)) { 539 * Each event can have multiple symbolic names.
293 attr->type = event_symbols[i].type; 540 * Symbolic names are (almost) exactly matched.
294 attr->config = event_symbols[i].config; 541 */
542static int parse_event_symbols(const char **str, struct perf_counter_attr *attr)
543{
544 if (!(parse_tracepoint_event(str, attr) ||
545 parse_raw_event(str, attr) ||
546 parse_numeric_event(str, attr) ||
547 parse_symbolic_event(str, attr) ||
548 parse_generic_hw_event(str, attr)))
549 return 0;
295 550
296 return 0; 551 parse_event_modifier(str, attr);
297 }
298 }
299 552
300 return parse_generic_hw_symbols(str, attr); 553 return 1;
301} 554}
302 555
303int parse_events(const struct option *opt, const char *str, int unset) 556int parse_events(const struct option *opt __used, const char *str, int unset __used)
304{ 557{
305 struct perf_counter_attr attr; 558 struct perf_counter_attr attr;
306 int ret;
307 559
308 memset(&attr, 0, sizeof(attr)); 560 for (;;) {
309again: 561 if (nr_counters == MAX_COUNTERS)
310 if (nr_counters == MAX_COUNTERS) 562 return -1;
311 return -1;
312 563
313 ret = parse_event_symbols(str, &attr); 564 memset(&attr, 0, sizeof(attr));
314 if (ret < 0) 565 if (!parse_event_symbols(&str, &attr))
315 return ret; 566 return -1;
316 567
317 attrs[nr_counters] = attr; 568 if (!(*str == 0 || *str == ',' || isspace(*str)))
318 nr_counters++; 569 return -1;
319 570
320 str = strstr(str, ","); 571 attrs[nr_counters] = attr;
321 if (str) { 572 nr_counters++;
322 str++; 573
323 goto again; 574 if (*str == 0)
575 break;
576 if (*str == ',')
577 ++str;
578 while (isspace(*str))
579 ++str;
324 } 580 }
325 581
326 return 0; 582 return 0;
@@ -335,12 +591,48 @@ static const char * const event_type_descriptors[] = {
335}; 591};
336 592
337/* 593/*
594 * Print the events from <debugfs_mount_point>/tracing/events
595 */
596
597static void print_tracepoint_events(void)
598{
599 DIR *sys_dir, *evt_dir;
600 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
601 struct stat st;
602 char evt_path[MAXPATHLEN];
603
604 if (valid_debugfs_mount(debugfs_path))
605 return;
606
607 sys_dir = opendir(debugfs_path);
608 if (!sys_dir)
609 goto cleanup;
610
611 for_each_subsystem(sys_dir, sys_dirent, sys_next, evt_path, st) {
612 evt_dir = opendir(evt_path);
613 if (!evt_dir)
614 goto cleanup;
615 for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next,
616 evt_path, st) {
617 snprintf(evt_path, MAXPATHLEN, "%s:%s",
618 sys_dirent.d_name, evt_dirent.d_name);
619 fprintf(stderr, " %-40s [%s]\n", evt_path,
620 event_type_descriptors[PERF_TYPE_TRACEPOINT+1]);
621 }
622 closedir(evt_dir);
623 }
624
625cleanup:
626 closedir(sys_dir);
627}
628
629/*
338 * Print the help text for the event symbols: 630 * Print the help text for the event symbols:
339 */ 631 */
340void print_events(void) 632void print_events(void)
341{ 633{
342 struct event_symbol *syms = event_symbols; 634 struct event_symbol *syms = event_symbols;
343 unsigned int i, type, prev_type = -1; 635 unsigned int i, type, op, prev_type = -1;
344 char name[40]; 636 char name[40];
345 637
346 fprintf(stderr, "\n"); 638 fprintf(stderr, "\n");
@@ -348,7 +640,7 @@ void print_events(void)
348 640
349 for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) { 641 for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
350 type = syms->type + 1; 642 type = syms->type + 1;
351 if (type > ARRAY_SIZE(event_type_descriptors)) 643 if (type >= ARRAY_SIZE(event_type_descriptors))
352 type = 0; 644 type = 0;
353 645
354 if (type != prev_type) 646 if (type != prev_type)
@@ -365,9 +657,26 @@ void print_events(void)
365 } 657 }
366 658
367 fprintf(stderr, "\n"); 659 fprintf(stderr, "\n");
660 for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
661 for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
662 /* skip invalid cache type */
663 if (!is_cache_op_valid(type, op))
664 continue;
665
666 for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
667 fprintf(stderr, " %-40s [%s]\n",
668 event_cache_name(type, op, i),
669 event_type_descriptors[4]);
670 }
671 }
672 }
673
674 fprintf(stderr, "\n");
368 fprintf(stderr, " %-40s [raw hardware event descriptor]\n", 675 fprintf(stderr, " %-40s [raw hardware event descriptor]\n",
369 "rNNN"); 676 "rNNN");
370 fprintf(stderr, "\n"); 677 fprintf(stderr, "\n");
371 678
679 print_tracepoint_events();
680
372 exit(129); 681 exit(129);
373} 682}
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index e3d552908e60..192a962e3a0f 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -3,11 +3,14 @@
3 * Parse symbolic events/counts passed in as options: 3 * Parse symbolic events/counts passed in as options:
4 */ 4 */
5 5
6struct option;
7
6extern int nr_counters; 8extern int nr_counters;
7 9
8extern struct perf_counter_attr attrs[MAX_COUNTERS]; 10extern struct perf_counter_attr attrs[MAX_COUNTERS];
9 11
10extern char *event_name(int ctr); 12extern char *event_name(int ctr);
13extern char *__event_name(int type, u64 config);
11 14
12extern int parse_events(const struct option *opt, const char *str, int unset); 15extern int parse_events(const struct option *opt, const char *str, int unset);
13 16
@@ -15,3 +18,6 @@ extern int parse_events(const struct option *opt, const char *str, int unset);
15 18
16extern void print_events(void); 19extern void print_events(void);
17 20
21extern char debugfs_path[];
22extern int valid_debugfs_mount(const char *debugfs);
23
diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c
index b3affb1658d2..1bf67190c820 100644
--- a/tools/perf/util/parse-options.c
+++ b/tools/perf/util/parse-options.c
@@ -20,7 +20,8 @@ static int get_arg(struct parse_opt_ctx_t *p, const struct option *opt,
20 if (p->opt) { 20 if (p->opt) {
21 *arg = p->opt; 21 *arg = p->opt;
22 p->opt = NULL; 22 p->opt = NULL;
23 } else if (p->argc == 1 && (opt->flags & PARSE_OPT_LASTARG_DEFAULT)) { 23 } else if ((opt->flags & PARSE_OPT_LASTARG_DEFAULT) && (p->argc == 1 ||
24 **(p->argv + 1) == '-')) {
24 *arg = (const char *)opt->defval; 25 *arg = (const char *)opt->defval;
25 } else if (p->argc > 1) { 26 } else if (p->argc > 1) {
26 p->argc--; 27 p->argc--;
@@ -485,7 +486,7 @@ int parse_options_usage(const char * const *usagestr,
485} 486}
486 487
487 488
488int parse_opt_verbosity_cb(const struct option *opt, const char *arg, 489int parse_opt_verbosity_cb(const struct option *opt, const char *arg __used,
489 int unset) 490 int unset)
490{ 491{
491 int *target = opt->value; 492 int *target = opt->value;
diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h
index a1039a6ce0eb..8aa3464c7090 100644
--- a/tools/perf/util/parse-options.h
+++ b/tools/perf/util/parse-options.h
@@ -90,21 +90,22 @@ struct option {
90 intptr_t defval; 90 intptr_t defval;
91}; 91};
92 92
93#define OPT_END() { OPTION_END } 93#define OPT_END() { .type = OPTION_END }
94#define OPT_ARGUMENT(l, h) { OPTION_ARGUMENT, 0, (l), NULL, NULL, (h) } 94#define OPT_ARGUMENT(l, h) { .type = OPTION_ARGUMENT, .long_name = (l), .help = (h) }
95#define OPT_GROUP(h) { OPTION_GROUP, 0, NULL, NULL, NULL, (h) } 95#define OPT_GROUP(h) { .type = OPTION_GROUP, .help = (h) }
96#define OPT_BIT(s, l, v, h, b) { OPTION_BIT, (s), (l), (v), NULL, (h), 0, NULL, (b) } 96#define OPT_BIT(s, l, v, h, b) { .type = OPTION_BIT, .short_name = (s), .long_name = (l), .value = (v), .help = (h), .defval = (b) }
97#define OPT_BOOLEAN(s, l, v, h) { OPTION_BOOLEAN, (s), (l), (v), NULL, (h) } 97#define OPT_BOOLEAN(s, l, v, h) { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), .value = (v), .help = (h) }
98#define OPT_SET_INT(s, l, v, h, i) { OPTION_SET_INT, (s), (l), (v), NULL, (h), 0, NULL, (i) } 98#define OPT_SET_INT(s, l, v, h, i) { .type = OPTION_SET_INT, .short_name = (s), .long_name = (l), .value = (v), .help = (h), .defval = (i) }
99#define OPT_SET_PTR(s, l, v, h, p) { OPTION_SET_PTR, (s), (l), (v), NULL, (h), 0, NULL, (p) } 99#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) }
100#define OPT_INTEGER(s, l, v, h) { OPTION_INTEGER, (s), (l), (v), NULL, (h) } 100#define OPT_INTEGER(s, l, v, h) { .type = OPTION_INTEGER, .short_name = (s), .long_name = (l), .value = (v), .help = (h) }
101#define OPT_LONG(s, l, v, h) { OPTION_LONG, (s), (l), (v), NULL, (h) } 101#define OPT_LONG(s, l, v, h) { .type = OPTION_LONG, .short_name = (s), .long_name = (l), .value = (v), .help = (h) }
102#define OPT_STRING(s, l, v, a, h) { OPTION_STRING, (s), (l), (v), (a), (h) } 102#define OPT_STRING(s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h) }
103#define OPT_DATE(s, l, v, h) \ 103#define OPT_DATE(s, l, v, h) \
104 { OPTION_CALLBACK, (s), (l), (v), "time",(h), 0, \ 104 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = "time", .help = (h), .callback = parse_opt_approxidate_cb }
105 parse_opt_approxidate_cb }
106#define OPT_CALLBACK(s, l, v, a, h, f) \ 105#define OPT_CALLBACK(s, l, v, a, h, f) \
107 { OPTION_CALLBACK, (s), (l), (v), (a), (h), 0, (f) } 106 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f) }
107#define OPT_CALLBACK_DEFAULT(s, l, v, a, h, f, d) \
108 { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f), .defval = (intptr_t)d, .flags = PARSE_OPT_LASTARG_DEFAULT }
108 109
109/* parse_options() will filter out the processed options and leave the 110/* parse_options() will filter out the processed options and leave the
110 * non-option argments in argv[]. 111 * non-option argments in argv[].
diff --git a/tools/perf/util/quote.c b/tools/perf/util/quote.c
index f18c5212bc92..2726fe40eb5d 100644
--- a/tools/perf/util/quote.c
+++ b/tools/perf/util/quote.c
@@ -162,12 +162,16 @@ static inline int sq_must_quote(char c)
162 return sq_lookup[(unsigned char)c] + quote_path_fully > 0; 162 return sq_lookup[(unsigned char)c] + quote_path_fully > 0;
163} 163}
164 164
165/* returns the longest prefix not needing a quote up to maxlen if positive. 165/*
166 This stops at the first \0 because it's marked as a character needing an 166 * Returns the longest prefix not needing a quote up to maxlen if
167 escape */ 167 * positive.
168static size_t next_quote_pos(const char *s, ssize_t maxlen) 168 * This stops at the first \0 because it's marked as a character
169 * needing an escape.
170 */
171static ssize_t next_quote_pos(const char *s, ssize_t maxlen)
169{ 172{
170 size_t len; 173 ssize_t len;
174
171 if (maxlen < 0) { 175 if (maxlen < 0) {
172 for (len = 0; !sq_must_quote(s[len]); len++); 176 for (len = 0; !sq_must_quote(s[len]); len++);
173 } else { 177 } else {
@@ -192,22 +196,22 @@ static size_t next_quote_pos(const char *s, ssize_t maxlen)
192static size_t quote_c_style_counted(const char *name, ssize_t maxlen, 196static size_t quote_c_style_counted(const char *name, ssize_t maxlen,
193 struct strbuf *sb, FILE *fp, int no_dq) 197 struct strbuf *sb, FILE *fp, int no_dq)
194{ 198{
195#undef EMIT 199#define EMIT(c) \
196#define EMIT(c) \ 200 do { \
197 do { \ 201 if (sb) strbuf_addch(sb, (c)); \
198 if (sb) strbuf_addch(sb, (c)); \ 202 if (fp) fputc((c), fp); \
199 if (fp) fputc((c), fp); \ 203 count++; \
200 count++; \
201 } while (0) 204 } while (0)
202#define EMITBUF(s, l) \ 205
203 do { \ 206#define EMITBUF(s, l) \
204 int __ret; \ 207 do { \
205 if (sb) strbuf_add(sb, (s), (l)); \ 208 int __ret; \
206 if (fp) __ret = fwrite((s), (l), 1, fp); \ 209 if (sb) strbuf_add(sb, (s), (l)); \
207 count += (l); \ 210 if (fp) __ret = fwrite((s), (l), 1, fp); \
211 count += (l); \
208 } while (0) 212 } while (0)
209 213
210 size_t len, count = 0; 214 ssize_t len, count = 0;
211 const char *p = name; 215 const char *p = name;
212 216
213 for (;;) { 217 for (;;) {
@@ -273,8 +277,8 @@ void write_name_quoted(const char *name, FILE *fp, int terminator)
273 fputc(terminator, fp); 277 fputc(terminator, fp);
274} 278}
275 279
276extern void write_name_quotedpfx(const char *pfx, size_t pfxlen, 280void write_name_quotedpfx(const char *pfx, ssize_t pfxlen,
277 const char *name, FILE *fp, int terminator) 281 const char *name, FILE *fp, int terminator)
278{ 282{
279 int needquote = 0; 283 int needquote = 0;
280 284
@@ -306,7 +310,7 @@ char *quote_path_relative(const char *in, int len,
306 len = strlen(in); 310 len = strlen(in);
307 311
308 /* "../" prefix itself does not need quoting, but "in" might. */ 312 /* "../" prefix itself does not need quoting, but "in" might. */
309 needquote = next_quote_pos(in, len) < len; 313 needquote = (next_quote_pos(in, len) < len);
310 strbuf_setlen(out, 0); 314 strbuf_setlen(out, 0);
311 strbuf_grow(out, len); 315 strbuf_grow(out, len);
312 316
@@ -314,7 +318,7 @@ char *quote_path_relative(const char *in, int len,
314 strbuf_addch(out, '"'); 318 strbuf_addch(out, '"');
315 if (prefix) { 319 if (prefix) {
316 int off = 0; 320 int off = 0;
317 while (prefix[off] && off < len && prefix[off] == in[off]) 321 while (off < len && prefix[off] && prefix[off] == in[off])
318 if (prefix[off] == '/') { 322 if (prefix[off] == '/') {
319 prefix += off + 1; 323 prefix += off + 1;
320 in += off + 1; 324 in += off + 1;
diff --git a/tools/perf/util/quote.h b/tools/perf/util/quote.h
index 5dfad89816db..a5454a1d1c13 100644
--- a/tools/perf/util/quote.h
+++ b/tools/perf/util/quote.h
@@ -53,7 +53,7 @@ extern size_t quote_c_style(const char *name, struct strbuf *, FILE *, int no_dq
53extern void quote_two_c_style(struct strbuf *, const char *, const char *, int); 53extern void quote_two_c_style(struct strbuf *, const char *, const char *, int);
54 54
55extern void write_name_quoted(const char *name, FILE *, int terminator); 55extern void write_name_quoted(const char *name, FILE *, int terminator);
56extern void write_name_quotedpfx(const char *pfx, size_t pfxlen, 56extern void write_name_quotedpfx(const char *pfx, ssize_t pfxlen,
57 const char *name, FILE *, int terminator); 57 const char *name, FILE *, int terminator);
58 58
59/* quote path as relative to the given prefix */ 59/* quote path as relative to the given prefix */
diff --git a/tools/perf/util/rbtree.c b/tools/perf/util/rbtree.c
deleted file mode 100644
index b15ba9c7cb3f..000000000000
--- a/tools/perf/util/rbtree.c
+++ /dev/null
@@ -1,383 +0,0 @@
1/*
2 Red Black Trees
3 (C) 1999 Andrea Arcangeli <andrea@suse.de>
4 (C) 2002 David Woodhouse <dwmw2@infradead.org>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
20 linux/lib/rbtree.c
21*/
22
23#include "rbtree.h"
24
25static void __rb_rotate_left(struct rb_node *node, struct rb_root *root)
26{
27 struct rb_node *right = node->rb_right;
28 struct rb_node *parent = rb_parent(node);
29
30 if ((node->rb_right = right->rb_left))
31 rb_set_parent(right->rb_left, node);
32 right->rb_left = node;
33
34 rb_set_parent(right, parent);
35
36 if (parent)
37 {
38 if (node == parent->rb_left)
39 parent->rb_left = right;
40 else
41 parent->rb_right = right;
42 }
43 else
44 root->rb_node = right;
45 rb_set_parent(node, right);
46}
47
48static void __rb_rotate_right(struct rb_node *node, struct rb_root *root)
49{
50 struct rb_node *left = node->rb_left;
51 struct rb_node *parent = rb_parent(node);
52
53 if ((node->rb_left = left->rb_right))
54 rb_set_parent(left->rb_right, node);
55 left->rb_right = node;
56
57 rb_set_parent(left, parent);
58
59 if (parent)
60 {
61 if (node == parent->rb_right)
62 parent->rb_right = left;
63 else
64 parent->rb_left = left;
65 }
66 else
67 root->rb_node = left;
68 rb_set_parent(node, left);
69}
70
71void rb_insert_color(struct rb_node *node, struct rb_root *root)
72{
73 struct rb_node *parent, *gparent;
74
75 while ((parent = rb_parent(node)) && rb_is_red(parent))
76 {
77 gparent = rb_parent(parent);
78
79 if (parent == gparent->rb_left)
80 {
81 {
82 register struct rb_node *uncle = gparent->rb_right;
83 if (uncle && rb_is_red(uncle))
84 {
85 rb_set_black(uncle);
86 rb_set_black(parent);
87 rb_set_red(gparent);
88 node = gparent;
89 continue;
90 }
91 }
92
93 if (parent->rb_right == node)
94 {
95 register struct rb_node *tmp;
96 __rb_rotate_left(parent, root);
97 tmp = parent;
98 parent = node;
99 node = tmp;
100 }
101
102 rb_set_black(parent);
103 rb_set_red(gparent);
104 __rb_rotate_right(gparent, root);
105 } else {
106 {
107 register struct rb_node *uncle = gparent->rb_left;
108 if (uncle && rb_is_red(uncle))
109 {
110 rb_set_black(uncle);
111 rb_set_black(parent);
112 rb_set_red(gparent);
113 node = gparent;
114 continue;
115 }
116 }
117
118 if (parent->rb_left == node)
119 {
120 register struct rb_node *tmp;
121 __rb_rotate_right(parent, root);
122 tmp = parent;
123 parent = node;
124 node = tmp;
125 }
126
127 rb_set_black(parent);
128 rb_set_red(gparent);
129 __rb_rotate_left(gparent, root);
130 }
131 }
132
133 rb_set_black(root->rb_node);
134}
135
136static void __rb_erase_color(struct rb_node *node, struct rb_node *parent,
137 struct rb_root *root)
138{
139 struct rb_node *other;
140
141 while ((!node || rb_is_black(node)) && node != root->rb_node)
142 {
143 if (parent->rb_left == node)
144 {
145 other = parent->rb_right;
146 if (rb_is_red(other))
147 {
148 rb_set_black(other);
149 rb_set_red(parent);
150 __rb_rotate_left(parent, root);
151 other = parent->rb_right;
152 }
153 if ((!other->rb_left || rb_is_black(other->rb_left)) &&
154 (!other->rb_right || rb_is_black(other->rb_right)))
155 {
156 rb_set_red(other);
157 node = parent;
158 parent = rb_parent(node);
159 }
160 else
161 {
162 if (!other->rb_right || rb_is_black(other->rb_right))
163 {
164 rb_set_black(other->rb_left);
165 rb_set_red(other);
166 __rb_rotate_right(other, root);
167 other = parent->rb_right;
168 }
169 rb_set_color(other, rb_color(parent));
170 rb_set_black(parent);
171 rb_set_black(other->rb_right);
172 __rb_rotate_left(parent, root);
173 node = root->rb_node;
174 break;
175 }
176 }
177 else
178 {
179 other = parent->rb_left;
180 if (rb_is_red(other))
181 {
182 rb_set_black(other);
183 rb_set_red(parent);
184 __rb_rotate_right(parent, root);
185 other = parent->rb_left;
186 }
187 if ((!other->rb_left || rb_is_black(other->rb_left)) &&
188 (!other->rb_right || rb_is_black(other->rb_right)))
189 {
190 rb_set_red(other);
191 node = parent;
192 parent = rb_parent(node);
193 }
194 else
195 {
196 if (!other->rb_left || rb_is_black(other->rb_left))
197 {
198 rb_set_black(other->rb_right);
199 rb_set_red(other);
200 __rb_rotate_left(other, root);
201 other = parent->rb_left;
202 }
203 rb_set_color(other, rb_color(parent));
204 rb_set_black(parent);
205 rb_set_black(other->rb_left);
206 __rb_rotate_right(parent, root);
207 node = root->rb_node;
208 break;
209 }
210 }
211 }
212 if (node)
213 rb_set_black(node);
214}
215
216void rb_erase(struct rb_node *node, struct rb_root *root)
217{
218 struct rb_node *child, *parent;
219 int color;
220
221 if (!node->rb_left)
222 child = node->rb_right;
223 else if (!node->rb_right)
224 child = node->rb_left;
225 else
226 {
227 struct rb_node *old = node, *left;
228
229 node = node->rb_right;
230 while ((left = node->rb_left) != NULL)
231 node = left;
232 child = node->rb_right;
233 parent = rb_parent(node);
234 color = rb_color(node);
235
236 if (child)
237 rb_set_parent(child, parent);
238 if (parent == old) {
239 parent->rb_right = child;
240 parent = node;
241 } else
242 parent->rb_left = child;
243
244 node->rb_parent_color = old->rb_parent_color;
245 node->rb_right = old->rb_right;
246 node->rb_left = old->rb_left;
247
248 if (rb_parent(old))
249 {
250 if (rb_parent(old)->rb_left == old)
251 rb_parent(old)->rb_left = node;
252 else
253 rb_parent(old)->rb_right = node;
254 } else
255 root->rb_node = node;
256
257 rb_set_parent(old->rb_left, node);
258 if (old->rb_right)
259 rb_set_parent(old->rb_right, node);
260 goto color;
261 }
262
263 parent = rb_parent(node);
264 color = rb_color(node);
265
266 if (child)
267 rb_set_parent(child, parent);
268 if (parent)
269 {
270 if (parent->rb_left == node)
271 parent->rb_left = child;
272 else
273 parent->rb_right = child;
274 }
275 else
276 root->rb_node = child;
277
278 color:
279 if (color == RB_BLACK)
280 __rb_erase_color(child, parent, root);
281}
282
283/*
284 * This function returns the first node (in sort order) of the tree.
285 */
286struct rb_node *rb_first(const struct rb_root *root)
287{
288 struct rb_node *n;
289
290 n = root->rb_node;
291 if (!n)
292 return NULL;
293 while (n->rb_left)
294 n = n->rb_left;
295 return n;
296}
297
298struct rb_node *rb_last(const struct rb_root *root)
299{
300 struct rb_node *n;
301
302 n = root->rb_node;
303 if (!n)
304 return NULL;
305 while (n->rb_right)
306 n = n->rb_right;
307 return n;
308}
309
310struct rb_node *rb_next(const struct rb_node *node)
311{
312 struct rb_node *parent;
313
314 if (rb_parent(node) == node)
315 return NULL;
316
317 /* If we have a right-hand child, go down and then left as far
318 as we can. */
319 if (node->rb_right) {
320 node = node->rb_right;
321 while (node->rb_left)
322 node=node->rb_left;
323 return (struct rb_node *)node;
324 }
325
326 /* No right-hand children. Everything down and left is
327 smaller than us, so any 'next' node must be in the general
328 direction of our parent. Go up the tree; any time the
329 ancestor is a right-hand child of its parent, keep going
330 up. First time it's a left-hand child of its parent, said
331 parent is our 'next' node. */
332 while ((parent = rb_parent(node)) && node == parent->rb_right)
333 node = parent;
334
335 return parent;
336}
337
338struct rb_node *rb_prev(const struct rb_node *node)
339{
340 struct rb_node *parent;
341
342 if (rb_parent(node) == node)
343 return NULL;
344
345 /* If we have a left-hand child, go down and then right as far
346 as we can. */
347 if (node->rb_left) {
348 node = node->rb_left;
349 while (node->rb_right)
350 node=node->rb_right;
351 return (struct rb_node *)node;
352 }
353
354 /* No left-hand children. Go up till we find an ancestor which
355 is a right-hand child of its parent */
356 while ((parent = rb_parent(node)) && node == parent->rb_left)
357 node = parent;
358
359 return parent;
360}
361
362void rb_replace_node(struct rb_node *victim, struct rb_node *new,
363 struct rb_root *root)
364{
365 struct rb_node *parent = rb_parent(victim);
366
367 /* Set the surrounding nodes to point to the replacement */
368 if (parent) {
369 if (victim == parent->rb_left)
370 parent->rb_left = new;
371 else
372 parent->rb_right = new;
373 } else {
374 root->rb_node = new;
375 }
376 if (victim->rb_left)
377 rb_set_parent(victim->rb_left, new);
378 if (victim->rb_right)
379 rb_set_parent(victim->rb_right, new);
380
381 /* Copy the pointers/colour from the victim to the replacement */
382 *new = *victim;
383}
diff --git a/tools/perf/util/rbtree.h b/tools/perf/util/rbtree.h
deleted file mode 100644
index 6bdc488a47fb..000000000000
--- a/tools/perf/util/rbtree.h
+++ /dev/null
@@ -1,171 +0,0 @@
1/*
2 Red Black Trees
3 (C) 1999 Andrea Arcangeli <andrea@suse.de>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19 linux/include/linux/rbtree.h
20
21 To use rbtrees you'll have to implement your own insert and search cores.
22 This will avoid us to use callbacks and to drop drammatically performances.
23 I know it's not the cleaner way, but in C (not in C++) to get
24 performances and genericity...
25
26 Some example of insert and search follows here. The search is a plain
27 normal search over an ordered tree. The insert instead must be implemented
28 int two steps: as first thing the code must insert the element in
29 order as a red leaf in the tree, then the support library function
30 rb_insert_color() must be called. Such function will do the
31 not trivial work to rebalance the rbtree if necessary.
32
33-----------------------------------------------------------------------
34static inline struct page * rb_search_page_cache(struct inode * inode,
35 unsigned long offset)
36{
37 struct rb_node * n = inode->i_rb_page_cache.rb_node;
38 struct page * page;
39
40 while (n)
41 {
42 page = rb_entry(n, struct page, rb_page_cache);
43
44 if (offset < page->offset)
45 n = n->rb_left;
46 else if (offset > page->offset)
47 n = n->rb_right;
48 else
49 return page;
50 }
51 return NULL;
52}
53
54static inline struct page * __rb_insert_page_cache(struct inode * inode,
55 unsigned long offset,
56 struct rb_node * node)
57{
58 struct rb_node ** p = &inode->i_rb_page_cache.rb_node;
59 struct rb_node * parent = NULL;
60 struct page * page;
61
62 while (*p)
63 {
64 parent = *p;
65 page = rb_entry(parent, struct page, rb_page_cache);
66
67 if (offset < page->offset)
68 p = &(*p)->rb_left;
69 else if (offset > page->offset)
70 p = &(*p)->rb_right;
71 else
72 return page;
73 }
74
75 rb_link_node(node, parent, p);
76
77 return NULL;
78}
79
80static inline struct page * rb_insert_page_cache(struct inode * inode,
81 unsigned long offset,
82 struct rb_node * node)
83{
84 struct page * ret;
85 if ((ret = __rb_insert_page_cache(inode, offset, node)))
86 goto out;
87 rb_insert_color(node, &inode->i_rb_page_cache);
88 out:
89 return ret;
90}
91-----------------------------------------------------------------------
92*/
93
94#ifndef _LINUX_RBTREE_H
95#define _LINUX_RBTREE_H
96
97#include <stddef.h>
98
99/**
100 * container_of - cast a member of a structure out to the containing structure
101 * @ptr: the pointer to the member.
102 * @type: the type of the container struct this is embedded in.
103 * @member: the name of the member within the struct.
104 *
105 */
106#define container_of(ptr, type, member) ({ \
107 const typeof( ((type *)0)->member ) *__mptr = (ptr); \
108 (type *)( (char *)__mptr - offsetof(type,member) );})
109
110struct rb_node
111{
112 unsigned long rb_parent_color;
113#define RB_RED 0
114#define RB_BLACK 1
115 struct rb_node *rb_right;
116 struct rb_node *rb_left;
117} __attribute__((aligned(sizeof(long))));
118 /* The alignment might seem pointless, but allegedly CRIS needs it */
119
120struct rb_root
121{
122 struct rb_node *rb_node;
123};
124
125
126#define rb_parent(r) ((struct rb_node *)((r)->rb_parent_color & ~3))
127#define rb_color(r) ((r)->rb_parent_color & 1)
128#define rb_is_red(r) (!rb_color(r))
129#define rb_is_black(r) rb_color(r)
130#define rb_set_red(r) do { (r)->rb_parent_color &= ~1; } while (0)
131#define rb_set_black(r) do { (r)->rb_parent_color |= 1; } while (0)
132
133static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p)
134{
135 rb->rb_parent_color = (rb->rb_parent_color & 3) | (unsigned long)p;
136}
137static inline void rb_set_color(struct rb_node *rb, int color)
138{
139 rb->rb_parent_color = (rb->rb_parent_color & ~1) | color;
140}
141
142#define RB_ROOT (struct rb_root) { NULL, }
143#define rb_entry(ptr, type, member) container_of(ptr, type, member)
144
145#define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL)
146#define RB_EMPTY_NODE(node) (rb_parent(node) == node)
147#define RB_CLEAR_NODE(node) (rb_set_parent(node, node))
148
149extern void rb_insert_color(struct rb_node *, struct rb_root *);
150extern void rb_erase(struct rb_node *, struct rb_root *);
151
152/* Find logical next and previous nodes in a tree */
153extern struct rb_node *rb_next(const struct rb_node *);
154extern struct rb_node *rb_prev(const struct rb_node *);
155extern struct rb_node *rb_first(const struct rb_root *);
156extern struct rb_node *rb_last(const struct rb_root *);
157
158/* Fast replacement of a single node without remove/rebalance/add/rebalance */
159extern void rb_replace_node(struct rb_node *victim, struct rb_node *new,
160 struct rb_root *root);
161
162static inline void rb_link_node(struct rb_node * node, struct rb_node * parent,
163 struct rb_node ** rb_link)
164{
165 node->rb_parent_color = (unsigned long )parent;
166 node->rb_left = node->rb_right = NULL;
167
168 *rb_link = node;
169}
170
171#endif /* _LINUX_RBTREE_H */
diff --git a/tools/perf/util/strbuf.c b/tools/perf/util/strbuf.c
index 464e7ca898cf..5249d5a1b0c2 100644
--- a/tools/perf/util/strbuf.c
+++ b/tools/perf/util/strbuf.c
@@ -16,7 +16,7 @@ int prefixcmp(const char *str, const char *prefix)
16 */ 16 */
17char strbuf_slopbuf[1]; 17char strbuf_slopbuf[1];
18 18
19void strbuf_init(struct strbuf *sb, size_t hint) 19void strbuf_init(struct strbuf *sb, ssize_t hint)
20{ 20{
21 sb->alloc = sb->len = 0; 21 sb->alloc = sb->len = 0;
22 sb->buf = strbuf_slopbuf; 22 sb->buf = strbuf_slopbuf;
@@ -92,7 +92,8 @@ void strbuf_ltrim(struct strbuf *sb)
92 92
93void strbuf_tolower(struct strbuf *sb) 93void strbuf_tolower(struct strbuf *sb)
94{ 94{
95 int i; 95 unsigned int i;
96
96 for (i = 0; i < sb->len; i++) 97 for (i = 0; i < sb->len; i++)
97 sb->buf[i] = tolower(sb->buf[i]); 98 sb->buf[i] = tolower(sb->buf[i]);
98} 99}
@@ -264,7 +265,7 @@ size_t strbuf_fread(struct strbuf *sb, size_t size, FILE *f)
264 return res; 265 return res;
265} 266}
266 267
267ssize_t strbuf_read(struct strbuf *sb, int fd, size_t hint) 268ssize_t strbuf_read(struct strbuf *sb, int fd, ssize_t hint)
268{ 269{
269 size_t oldlen = sb->len; 270 size_t oldlen = sb->len;
270 size_t oldalloc = sb->alloc; 271 size_t oldalloc = sb->alloc;
@@ -293,7 +294,7 @@ ssize_t strbuf_read(struct strbuf *sb, int fd, size_t hint)
293 294
294#define STRBUF_MAXLINK (2*PATH_MAX) 295#define STRBUF_MAXLINK (2*PATH_MAX)
295 296
296int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint) 297int strbuf_readlink(struct strbuf *sb, const char *path, ssize_t hint)
297{ 298{
298 size_t oldalloc = sb->alloc; 299 size_t oldalloc = sb->alloc;
299 300
@@ -301,7 +302,7 @@ int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint)
301 hint = 32; 302 hint = 32;
302 303
303 while (hint < STRBUF_MAXLINK) { 304 while (hint < STRBUF_MAXLINK) {
304 int len; 305 ssize_t len;
305 306
306 strbuf_grow(sb, hint); 307 strbuf_grow(sb, hint);
307 len = readlink(path, sb->buf, hint); 308 len = readlink(path, sb->buf, hint);
@@ -343,7 +344,7 @@ int strbuf_getline(struct strbuf *sb, FILE *fp, int term)
343 return 0; 344 return 0;
344} 345}
345 346
346int strbuf_read_file(struct strbuf *sb, const char *path, size_t hint) 347int strbuf_read_file(struct strbuf *sb, const char *path, ssize_t hint)
347{ 348{
348 int fd, len; 349 int fd, len;
349 350
diff --git a/tools/perf/util/strbuf.h b/tools/perf/util/strbuf.h
index 9ee908a3ec5d..d2aa86c014c1 100644
--- a/tools/perf/util/strbuf.h
+++ b/tools/perf/util/strbuf.h
@@ -50,7 +50,7 @@ struct strbuf {
50#define STRBUF_INIT { 0, 0, strbuf_slopbuf } 50#define STRBUF_INIT { 0, 0, strbuf_slopbuf }
51 51
52/*----- strbuf life cycle -----*/ 52/*----- strbuf life cycle -----*/
53extern void strbuf_init(struct strbuf *, size_t); 53extern void strbuf_init(struct strbuf *buf, ssize_t hint);
54extern void strbuf_release(struct strbuf *); 54extern void strbuf_release(struct strbuf *);
55extern char *strbuf_detach(struct strbuf *, size_t *); 55extern char *strbuf_detach(struct strbuf *, size_t *);
56extern void strbuf_attach(struct strbuf *, void *, size_t, size_t); 56extern void strbuf_attach(struct strbuf *, void *, size_t, size_t);
@@ -61,7 +61,7 @@ static inline void strbuf_swap(struct strbuf *a, struct strbuf *b) {
61} 61}
62 62
63/*----- strbuf size related -----*/ 63/*----- strbuf size related -----*/
64static inline size_t strbuf_avail(const struct strbuf *sb) { 64static inline ssize_t strbuf_avail(const struct strbuf *sb) {
65 return sb->alloc ? sb->alloc - sb->len - 1 : 0; 65 return sb->alloc ? sb->alloc - sb->len - 1 : 0;
66} 66}
67 67
@@ -122,9 +122,9 @@ extern void strbuf_addf(struct strbuf *sb, const char *fmt, ...);
122 122
123extern size_t strbuf_fread(struct strbuf *, size_t, FILE *); 123extern size_t strbuf_fread(struct strbuf *, size_t, FILE *);
124/* XXX: if read fails, any partial read is undone */ 124/* XXX: if read fails, any partial read is undone */
125extern ssize_t strbuf_read(struct strbuf *, int fd, size_t hint); 125extern ssize_t strbuf_read(struct strbuf *, int fd, ssize_t hint);
126extern int strbuf_read_file(struct strbuf *sb, const char *path, size_t hint); 126extern int strbuf_read_file(struct strbuf *sb, const char *path, ssize_t hint);
127extern int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint); 127extern int strbuf_readlink(struct strbuf *sb, const char *path, ssize_t hint);
128 128
129extern int strbuf_getline(struct strbuf *, FILE *, int); 129extern int strbuf_getline(struct strbuf *, FILE *, int);
130 130
diff --git a/tools/perf/util/string.h b/tools/perf/util/string.h
index 3dca2f654cd0..bf39dfadfd24 100644
--- a/tools/perf/util/string.h
+++ b/tools/perf/util/string.h
@@ -5,4 +5,7 @@
5 5
6int hex2u64(const char *ptr, u64 *val); 6int hex2u64(const char *ptr, u64 *val);
7 7
8#define _STR(x) #x
9#define STR(x) _STR(x)
10
8#endif 11#endif
diff --git a/tools/perf/util/strlist.c b/tools/perf/util/strlist.c
index 025a78edfffe..7ad38171dc2b 100644
--- a/tools/perf/util/strlist.c
+++ b/tools/perf/util/strlist.c
@@ -64,6 +64,7 @@ int strlist__add(struct strlist *self, const char *new_entry)
64 64
65 rb_link_node(&sn->rb_node, parent, p); 65 rb_link_node(&sn->rb_node, parent, p);
66 rb_insert_color(&sn->rb_node, &self->entries); 66 rb_insert_color(&sn->rb_node, &self->entries);
67 ++self->nr_entries;
67 68
68 return 0; 69 return 0;
69} 70}
@@ -155,8 +156,9 @@ struct strlist *strlist__new(bool dupstr, const char *slist)
155 struct strlist *self = malloc(sizeof(*self)); 156 struct strlist *self = malloc(sizeof(*self));
156 157
157 if (self != NULL) { 158 if (self != NULL) {
158 self->entries = RB_ROOT; 159 self->entries = RB_ROOT;
159 self->dupstr = dupstr; 160 self->dupstr = dupstr;
161 self->nr_entries = 0;
160 if (slist && strlist__parse_list(self, slist) != 0) 162 if (slist && strlist__parse_list(self, slist) != 0)
161 goto out_error; 163 goto out_error;
162 } 164 }
@@ -182,3 +184,17 @@ void strlist__delete(struct strlist *self)
182 free(self); 184 free(self);
183 } 185 }
184} 186}
187
188struct str_node *strlist__entry(const struct strlist *self, unsigned int idx)
189{
190 struct rb_node *nd;
191
192 for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) {
193 struct str_node *pos = rb_entry(nd, struct str_node, rb_node);
194
195 if (!idx--)
196 return pos;
197 }
198
199 return NULL;
200}
diff --git a/tools/perf/util/strlist.h b/tools/perf/util/strlist.h
index 2fb117fb4b67..921818e44a54 100644
--- a/tools/perf/util/strlist.h
+++ b/tools/perf/util/strlist.h
@@ -1,7 +1,7 @@
1#ifndef STRLIST_H_ 1#ifndef STRLIST_H_
2#define STRLIST_H_ 2#define STRLIST_H_
3 3
4#include "rbtree.h" 4#include <linux/rbtree.h>
5#include <stdbool.h> 5#include <stdbool.h>
6 6
7struct str_node { 7struct str_node {
@@ -11,7 +11,8 @@ struct str_node {
11 11
12struct strlist { 12struct strlist {
13 struct rb_root entries; 13 struct rb_root entries;
14 bool dupstr; 14 unsigned int nr_entries;
15 bool dupstr;
15}; 16};
16 17
17struct strlist *strlist__new(bool dupstr, const char *slist); 18struct strlist *strlist__new(bool dupstr, const char *slist);
@@ -21,11 +22,17 @@ void strlist__remove(struct strlist *self, struct str_node *sn);
21int strlist__load(struct strlist *self, const char *filename); 22int strlist__load(struct strlist *self, const char *filename);
22int strlist__add(struct strlist *self, const char *str); 23int strlist__add(struct strlist *self, const char *str);
23 24
25struct str_node *strlist__entry(const struct strlist *self, unsigned int idx);
24bool strlist__has_entry(struct strlist *self, const char *entry); 26bool strlist__has_entry(struct strlist *self, const char *entry);
25 27
26static inline bool strlist__empty(const struct strlist *self) 28static inline bool strlist__empty(const struct strlist *self)
27{ 29{
28 return rb_first(&self->entries) == NULL; 30 return self->nr_entries == 0;
31}
32
33static inline unsigned int strlist__nr_entries(const struct strlist *self)
34{
35 return self->nr_entries;
29} 36}
30 37
31int strlist__parse_list(struct strlist *self, const char *s); 38int strlist__parse_list(struct strlist *self, const char *s);
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 78c2efde01b7..5c0f42e6b33b 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -9,6 +9,16 @@
9 9
10const char *sym_hist_filter; 10const char *sym_hist_filter;
11 11
12enum dso_origin {
13 DSO__ORIG_KERNEL = 0,
14 DSO__ORIG_JAVA_JIT,
15 DSO__ORIG_FEDORA,
16 DSO__ORIG_UBUNTU,
17 DSO__ORIG_BUILDID,
18 DSO__ORIG_DSO,
19 DSO__ORIG_NOT_FOUND,
20};
21
12static struct symbol *symbol__new(u64 start, u64 len, 22static struct symbol *symbol__new(u64 start, u64 len,
13 const char *name, unsigned int priv_size, 23 const char *name, unsigned int priv_size,
14 u64 obj_start, int verbose) 24 u64 obj_start, int verbose)
@@ -35,7 +45,7 @@ static struct symbol *symbol__new(u64 start, u64 len,
35 self = ((void *)self) + priv_size; 45 self = ((void *)self) + priv_size;
36 } 46 }
37 self->start = start; 47 self->start = start;
38 self->end = start + len - 1; 48 self->end = len ? start + len - 1 : start;
39 memcpy(self->name, name, namelen); 49 memcpy(self->name, name, namelen);
40 50
41 return self; 51 return self;
@@ -48,8 +58,12 @@ static void symbol__delete(struct symbol *self, unsigned int priv_size)
48 58
49static size_t symbol__fprintf(struct symbol *self, FILE *fp) 59static size_t symbol__fprintf(struct symbol *self, FILE *fp)
50{ 60{
51 return fprintf(fp, " %llx-%llx %s\n", 61 if (!self->module)
62 return fprintf(fp, " %llx-%llx %s\n",
52 self->start, self->end, self->name); 63 self->start, self->end, self->name);
64 else
65 return fprintf(fp, " %llx-%llx %s \t[%s]\n",
66 self->start, self->end, self->name, self->module->name);
53} 67}
54 68
55struct dso *dso__new(const char *name, unsigned int sym_priv_size) 69struct dso *dso__new(const char *name, unsigned int sym_priv_size)
@@ -61,6 +75,8 @@ struct dso *dso__new(const char *name, unsigned int sym_priv_size)
61 self->syms = RB_ROOT; 75 self->syms = RB_ROOT;
62 self->sym_priv_size = sym_priv_size; 76 self->sym_priv_size = sym_priv_size;
63 self->find_symbol = dso__find_symbol; 77 self->find_symbol = dso__find_symbol;
78 self->slen_calculated = 0;
79 self->origin = DSO__ORIG_NOT_FOUND;
64 } 80 }
65 81
66 return self; 82 return self;
@@ -146,6 +162,7 @@ static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int verb
146 char *line = NULL; 162 char *line = NULL;
147 size_t n; 163 size_t n;
148 FILE *file = fopen("/proc/kallsyms", "r"); 164 FILE *file = fopen("/proc/kallsyms", "r");
165 int count = 0;
149 166
150 if (file == NULL) 167 if (file == NULL)
151 goto out_failure; 168 goto out_failure;
@@ -188,8 +205,10 @@ static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int verb
188 205
189 if (filter && filter(self, sym)) 206 if (filter && filter(self, sym))
190 symbol__delete(sym, self->sym_priv_size); 207 symbol__delete(sym, self->sym_priv_size);
191 else 208 else {
192 dso__insert_symbol(self, sym); 209 dso__insert_symbol(self, sym);
210 count++;
211 }
193 } 212 }
194 213
195 /* 214 /*
@@ -212,7 +231,7 @@ static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int verb
212 free(line); 231 free(line);
213 fclose(file); 232 fclose(file);
214 233
215 return 0; 234 return count;
216 235
217out_delete_line: 236out_delete_line:
218 free(line); 237 free(line);
@@ -307,6 +326,26 @@ static inline int elf_sym__is_function(const GElf_Sym *sym)
307 sym->st_size != 0; 326 sym->st_size != 0;
308} 327}
309 328
329static inline int elf_sym__is_label(const GElf_Sym *sym)
330{
331 return elf_sym__type(sym) == STT_NOTYPE &&
332 sym->st_name != 0 &&
333 sym->st_shndx != SHN_UNDEF &&
334 sym->st_shndx != SHN_ABS;
335}
336
337static inline const char *elf_sec__name(const GElf_Shdr *shdr,
338 const Elf_Data *secstrs)
339{
340 return secstrs->d_buf + shdr->sh_name;
341}
342
343static inline int elf_sec__is_text(const GElf_Shdr *shdr,
344 const Elf_Data *secstrs)
345{
346 return strstr(elf_sec__name(shdr, secstrs), "text") != NULL;
347}
348
310static inline const char *elf_sym__name(const GElf_Sym *sym, 349static inline const char *elf_sym__name(const GElf_Sym *sym,
311 const Elf_Data *symstrs) 350 const Elf_Data *symstrs)
312{ 351{
@@ -346,36 +385,61 @@ static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
346 idx < nr_entries; \ 385 idx < nr_entries; \
347 ++idx, pos = gelf_getrela(reldata, idx, &pos_mem)) 386 ++idx, pos = gelf_getrela(reldata, idx, &pos_mem))
348 387
349static int dso__synthesize_plt_symbols(struct dso *self, Elf *elf, 388/*
350 GElf_Ehdr *ehdr, Elf_Scn *scn_dynsym, 389 * We need to check if we have a .dynsym, so that we can handle the
351 GElf_Shdr *shdr_dynsym, 390 * .plt, synthesizing its symbols, that aren't on the symtabs (be it
352 size_t dynsym_idx, int verbose) 391 * .dynsym or .symtab).
392 * And always look at the original dso, not at debuginfo packages, that
393 * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS).
394 */
395static int dso__synthesize_plt_symbols(struct dso *self, int verbose)
353{ 396{
354 uint32_t nr_rel_entries, idx; 397 uint32_t nr_rel_entries, idx;
355 GElf_Sym sym; 398 GElf_Sym sym;
356 u64 plt_offset; 399 u64 plt_offset;
357 GElf_Shdr shdr_plt; 400 GElf_Shdr shdr_plt;
358 struct symbol *f; 401 struct symbol *f;
359 GElf_Shdr shdr_rel_plt; 402 GElf_Shdr shdr_rel_plt, shdr_dynsym;
360 Elf_Data *reldata, *syms, *symstrs; 403 Elf_Data *reldata, *syms, *symstrs;
361 Elf_Scn *scn_plt_rel, *scn_symstrs; 404 Elf_Scn *scn_plt_rel, *scn_symstrs, *scn_dynsym;
405 size_t dynsym_idx;
406 GElf_Ehdr ehdr;
362 char sympltname[1024]; 407 char sympltname[1024];
363 int nr = 0, symidx; 408 Elf *elf;
409 int nr = 0, symidx, fd, err = 0;
364 410
365 scn_plt_rel = elf_section_by_name(elf, ehdr, &shdr_rel_plt, 411 fd = open(self->name, O_RDONLY);
412 if (fd < 0)
413 goto out;
414
415 elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
416 if (elf == NULL)
417 goto out_close;
418
419 if (gelf_getehdr(elf, &ehdr) == NULL)
420 goto out_elf_end;
421
422 scn_dynsym = elf_section_by_name(elf, &ehdr, &shdr_dynsym,
423 ".dynsym", &dynsym_idx);
424 if (scn_dynsym == NULL)
425 goto out_elf_end;
426
427 scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt,
366 ".rela.plt", NULL); 428 ".rela.plt", NULL);
367 if (scn_plt_rel == NULL) { 429 if (scn_plt_rel == NULL) {
368 scn_plt_rel = elf_section_by_name(elf, ehdr, &shdr_rel_plt, 430 scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt,
369 ".rel.plt", NULL); 431 ".rel.plt", NULL);
370 if (scn_plt_rel == NULL) 432 if (scn_plt_rel == NULL)
371 return 0; 433 goto out_elf_end;
372 } 434 }
373 435
436 err = -1;
437
374 if (shdr_rel_plt.sh_link != dynsym_idx) 438 if (shdr_rel_plt.sh_link != dynsym_idx)
375 return 0; 439 goto out_elf_end;
376 440
377 if (elf_section_by_name(elf, ehdr, &shdr_plt, ".plt", NULL) == NULL) 441 if (elf_section_by_name(elf, &ehdr, &shdr_plt, ".plt", NULL) == NULL)
378 return 0; 442 goto out_elf_end;
379 443
380 /* 444 /*
381 * Fetch the relocation section to find the indexes to the GOT 445 * Fetch the relocation section to find the indexes to the GOT
@@ -383,19 +447,19 @@ static int dso__synthesize_plt_symbols(struct dso *self, Elf *elf,
383 */ 447 */
384 reldata = elf_getdata(scn_plt_rel, NULL); 448 reldata = elf_getdata(scn_plt_rel, NULL);
385 if (reldata == NULL) 449 if (reldata == NULL)
386 return -1; 450 goto out_elf_end;
387 451
388 syms = elf_getdata(scn_dynsym, NULL); 452 syms = elf_getdata(scn_dynsym, NULL);
389 if (syms == NULL) 453 if (syms == NULL)
390 return -1; 454 goto out_elf_end;
391 455
392 scn_symstrs = elf_getscn(elf, shdr_dynsym->sh_link); 456 scn_symstrs = elf_getscn(elf, shdr_dynsym.sh_link);
393 if (scn_symstrs == NULL) 457 if (scn_symstrs == NULL)
394 return -1; 458 goto out_elf_end;
395 459
396 symstrs = elf_getdata(scn_symstrs, NULL); 460 symstrs = elf_getdata(scn_symstrs, NULL);
397 if (symstrs == NULL) 461 if (symstrs == NULL)
398 return -1; 462 goto out_elf_end;
399 463
400 nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize; 464 nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize;
401 plt_offset = shdr_plt.sh_offset; 465 plt_offset = shdr_plt.sh_offset;
@@ -414,7 +478,7 @@ static int dso__synthesize_plt_symbols(struct dso *self, Elf *elf,
414 f = symbol__new(plt_offset, shdr_plt.sh_entsize, 478 f = symbol__new(plt_offset, shdr_plt.sh_entsize,
415 sympltname, self->sym_priv_size, 0, verbose); 479 sympltname, self->sym_priv_size, 0, verbose);
416 if (!f) 480 if (!f)
417 return -1; 481 goto out_elf_end;
418 482
419 dso__insert_symbol(self, f); 483 dso__insert_symbol(self, f);
420 ++nr; 484 ++nr;
@@ -432,25 +496,31 @@ static int dso__synthesize_plt_symbols(struct dso *self, Elf *elf,
432 f = symbol__new(plt_offset, shdr_plt.sh_entsize, 496 f = symbol__new(plt_offset, shdr_plt.sh_entsize,
433 sympltname, self->sym_priv_size, 0, verbose); 497 sympltname, self->sym_priv_size, 0, verbose);
434 if (!f) 498 if (!f)
435 return -1; 499 goto out_elf_end;
436 500
437 dso__insert_symbol(self, f); 501 dso__insert_symbol(self, f);
438 ++nr; 502 ++nr;
439 } 503 }
440 } else {
441 /*
442 * TODO: There are still one more shdr_rel_plt.sh_type
443 * I have to investigate, but probably should be ignored.
444 */
445 } 504 }
446 505
447 return nr; 506 err = 0;
507out_elf_end:
508 elf_end(elf);
509out_close:
510 close(fd);
511
512 if (err == 0)
513 return nr;
514out:
515 fprintf(stderr, "%s: problems reading %s PLT info.\n",
516 __func__, self->name);
517 return 0;
448} 518}
449 519
450static int dso__load_sym(struct dso *self, int fd, const char *name, 520static int dso__load_sym(struct dso *self, int fd, const char *name,
451 symbol_filter_t filter, int verbose) 521 symbol_filter_t filter, int verbose, struct module *mod)
452{ 522{
453 Elf_Data *symstrs; 523 Elf_Data *symstrs, *secstrs;
454 uint32_t nr_syms; 524 uint32_t nr_syms;
455 int err = -1; 525 int err = -1;
456 uint32_t index; 526 uint32_t index;
@@ -458,10 +528,9 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
458 GElf_Shdr shdr; 528 GElf_Shdr shdr;
459 Elf_Data *syms; 529 Elf_Data *syms;
460 GElf_Sym sym; 530 GElf_Sym sym;
461 Elf_Scn *sec, *sec_dynsym; 531 Elf_Scn *sec, *sec_strndx;
462 Elf *elf; 532 Elf *elf;
463 size_t dynsym_idx; 533 int nr = 0, kernel = !strcmp("[kernel]", self->name);
464 int nr = 0;
465 534
466 elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); 535 elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
467 if (elf == NULL) { 536 if (elf == NULL) {
@@ -477,32 +546,11 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
477 goto out_elf_end; 546 goto out_elf_end;
478 } 547 }
479 548
480 /*
481 * We need to check if we have a .dynsym, so that we can handle the
482 * .plt, synthesizing its symbols, that aren't on the symtabs (be it
483 * .dynsym or .symtab)
484 */
485 sec_dynsym = elf_section_by_name(elf, &ehdr, &shdr,
486 ".dynsym", &dynsym_idx);
487 if (sec_dynsym != NULL) {
488 nr = dso__synthesize_plt_symbols(self, elf, &ehdr,
489 sec_dynsym, &shdr,
490 dynsym_idx, verbose);
491 if (nr < 0)
492 goto out_elf_end;
493 }
494
495 /*
496 * But if we have a full .symtab (that is a superset of .dynsym) we
497 * should add the symbols not in the .dynsyn
498 */
499 sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL); 549 sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL);
500 if (sec == NULL) { 550 if (sec == NULL) {
501 if (sec_dynsym == NULL) 551 sec = elf_section_by_name(elf, &ehdr, &shdr, ".dynsym", NULL);
552 if (sec == NULL)
502 goto out_elf_end; 553 goto out_elf_end;
503
504 sec = sec_dynsym;
505 gelf_getshdr(sec, &shdr);
506 } 554 }
507 555
508 syms = elf_getdata(sec, NULL); 556 syms = elf_getdata(sec, NULL);
@@ -517,17 +565,34 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
517 if (symstrs == NULL) 565 if (symstrs == NULL)
518 goto out_elf_end; 566 goto out_elf_end;
519 567
568 sec_strndx = elf_getscn(elf, ehdr.e_shstrndx);
569 if (sec_strndx == NULL)
570 goto out_elf_end;
571
572 secstrs = elf_getdata(sec_strndx, NULL);
573 if (secstrs == NULL)
574 goto out_elf_end;
575
520 nr_syms = shdr.sh_size / shdr.sh_entsize; 576 nr_syms = shdr.sh_size / shdr.sh_entsize;
521 577
522 memset(&sym, 0, sizeof(sym)); 578 memset(&sym, 0, sizeof(sym));
523 self->prelinked = elf_section_by_name(elf, &ehdr, &shdr, 579 if (!kernel) {
524 ".gnu.prelink_undo", 580 self->adjust_symbols = (ehdr.e_type == ET_EXEC ||
525 NULL) != NULL; 581 elf_section_by_name(elf, &ehdr, &shdr,
582 ".gnu.prelink_undo",
583 NULL) != NULL);
584 } else self->adjust_symbols = 0;
585
526 elf_symtab__for_each_symbol(syms, nr_syms, index, sym) { 586 elf_symtab__for_each_symbol(syms, nr_syms, index, sym) {
527 struct symbol *f; 587 struct symbol *f;
588 const char *name;
589 char *demangled;
528 u64 obj_start; 590 u64 obj_start;
591 struct section *section = NULL;
592 int is_label = elf_sym__is_label(&sym);
593 const char *section_name;
529 594
530 if (!elf_sym__is_function(&sym)) 595 if (!is_label && !elf_sym__is_function(&sym))
531 continue; 596 continue;
532 597
533 sec = elf_getscn(elf, sym.st_shndx); 598 sec = elf_getscn(elf, sym.st_shndx);
@@ -535,9 +600,14 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
535 goto out_elf_end; 600 goto out_elf_end;
536 601
537 gelf_getshdr(sec, &shdr); 602 gelf_getshdr(sec, &shdr);
603
604 if (is_label && !elf_sec__is_text(&shdr, secstrs))
605 continue;
606
607 section_name = elf_sec__name(&shdr, secstrs);
538 obj_start = sym.st_value; 608 obj_start = sym.st_value;
539 609
540 if (self->prelinked) { 610 if (self->adjust_symbols) {
541 if (verbose >= 2) 611 if (verbose >= 2)
542 printf("adjusting symbol: st_value: %Lx sh_addr: %Lx sh_offset: %Lx\n", 612 printf("adjusting symbol: st_value: %Lx sh_addr: %Lx sh_offset: %Lx\n",
543 (u64)sym.st_value, (u64)shdr.sh_addr, (u64)shdr.sh_offset); 613 (u64)sym.st_value, (u64)shdr.sh_addr, (u64)shdr.sh_offset);
@@ -545,15 +615,36 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
545 sym.st_value -= shdr.sh_addr - shdr.sh_offset; 615 sym.st_value -= shdr.sh_addr - shdr.sh_offset;
546 } 616 }
547 617
548 f = symbol__new(sym.st_value, sym.st_size, 618 if (mod) {
549 elf_sym__name(&sym, symstrs), 619 section = mod->sections->find_section(mod->sections, section_name);
620 if (section)
621 sym.st_value += section->vma;
622 else {
623 fprintf(stderr, "dso__load_sym() module %s lookup of %s failed\n",
624 mod->name, section_name);
625 goto out_elf_end;
626 }
627 }
628 /*
629 * We need to figure out if the object was created from C++ sources
630 * DWARF DW_compile_unit has this, but we don't always have access
631 * to it...
632 */
633 name = elf_sym__name(&sym, symstrs);
634 demangled = bfd_demangle(NULL, name, DMGL_PARAMS | DMGL_ANSI);
635 if (demangled != NULL)
636 name = demangled;
637
638 f = symbol__new(sym.st_value, sym.st_size, name,
550 self->sym_priv_size, obj_start, verbose); 639 self->sym_priv_size, obj_start, verbose);
640 free(demangled);
551 if (!f) 641 if (!f)
552 goto out_elf_end; 642 goto out_elf_end;
553 643
554 if (filter && filter(self, f)) 644 if (filter && filter(self, f))
555 symbol__delete(f, self->sym_priv_size); 645 symbol__delete(f, self->sym_priv_size);
556 else { 646 else {
647 f->module = mod;
557 dso__insert_symbol(self, f); 648 dso__insert_symbol(self, f);
558 nr++; 649 nr++;
559 } 650 }
@@ -566,44 +657,135 @@ out_close:
566 return err; 657 return err;
567} 658}
568 659
660#define BUILD_ID_SIZE 128
661
662static char *dso__read_build_id(struct dso *self, int verbose)
663{
664 int i;
665 GElf_Ehdr ehdr;
666 GElf_Shdr shdr;
667 Elf_Data *build_id_data;
668 Elf_Scn *sec;
669 char *build_id = NULL, *bid;
670 unsigned char *raw;
671 Elf *elf;
672 int fd = open(self->name, O_RDONLY);
673
674 if (fd < 0)
675 goto out;
676
677 elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
678 if (elf == NULL) {
679 if (verbose)
680 fprintf(stderr, "%s: cannot read %s ELF file.\n",
681 __func__, self->name);
682 goto out_close;
683 }
684
685 if (gelf_getehdr(elf, &ehdr) == NULL) {
686 if (verbose)
687 fprintf(stderr, "%s: cannot get elf header.\n", __func__);
688 goto out_elf_end;
689 }
690
691 sec = elf_section_by_name(elf, &ehdr, &shdr, ".note.gnu.build-id", NULL);
692 if (sec == NULL)
693 goto out_elf_end;
694
695 build_id_data = elf_getdata(sec, NULL);
696 if (build_id_data == NULL)
697 goto out_elf_end;
698 build_id = malloc(BUILD_ID_SIZE);
699 if (build_id == NULL)
700 goto out_elf_end;
701 raw = build_id_data->d_buf + 16;
702 bid = build_id;
703
704 for (i = 0; i < 20; ++i) {
705 sprintf(bid, "%02x", *raw);
706 ++raw;
707 bid += 2;
708 }
709 if (verbose >= 2)
710 printf("%s(%s): %s\n", __func__, self->name, build_id);
711out_elf_end:
712 elf_end(elf);
713out_close:
714 close(fd);
715out:
716 return build_id;
717}
718
719char dso__symtab_origin(const struct dso *self)
720{
721 static const char origin[] = {
722 [DSO__ORIG_KERNEL] = 'k',
723 [DSO__ORIG_JAVA_JIT] = 'j',
724 [DSO__ORIG_FEDORA] = 'f',
725 [DSO__ORIG_UBUNTU] = 'u',
726 [DSO__ORIG_BUILDID] = 'b',
727 [DSO__ORIG_DSO] = 'd',
728 };
729
730 if (self == NULL || self->origin == DSO__ORIG_NOT_FOUND)
731 return '!';
732 return origin[self->origin];
733}
734
569int dso__load(struct dso *self, symbol_filter_t filter, int verbose) 735int dso__load(struct dso *self, symbol_filter_t filter, int verbose)
570{ 736{
571 int size = strlen(self->name) + sizeof("/usr/lib/debug%s.debug"); 737 int size = PATH_MAX;
572 char *name = malloc(size); 738 char *name = malloc(size), *build_id = NULL;
573 int variant = 0;
574 int ret = -1; 739 int ret = -1;
575 int fd; 740 int fd;
576 741
577 if (!name) 742 if (!name)
578 return -1; 743 return -1;
579 744
580 self->prelinked = 0; 745 self->adjust_symbols = 0;
746
747 if (strncmp(self->name, "/tmp/perf-", 10) == 0) {
748 ret = dso__load_perf_map(self, filter, verbose);
749 self->origin = ret > 0 ? DSO__ORIG_JAVA_JIT :
750 DSO__ORIG_NOT_FOUND;
751 return ret;
752 }
581 753
582 if (strncmp(self->name, "/tmp/perf-", 10) == 0) 754 self->origin = DSO__ORIG_FEDORA - 1;
583 return dso__load_perf_map(self, filter, verbose);
584 755
585more: 756more:
586 do { 757 do {
587 switch (variant) { 758 self->origin++;
588 case 0: /* Fedora */ 759 switch (self->origin) {
760 case DSO__ORIG_FEDORA:
589 snprintf(name, size, "/usr/lib/debug%s.debug", self->name); 761 snprintf(name, size, "/usr/lib/debug%s.debug", self->name);
590 break; 762 break;
591 case 1: /* Ubuntu */ 763 case DSO__ORIG_UBUNTU:
592 snprintf(name, size, "/usr/lib/debug%s", self->name); 764 snprintf(name, size, "/usr/lib/debug%s", self->name);
593 break; 765 break;
594 case 2: /* Sane people */ 766 case DSO__ORIG_BUILDID:
767 build_id = dso__read_build_id(self, verbose);
768 if (build_id != NULL) {
769 snprintf(name, size,
770 "/usr/lib/debug/.build-id/%.2s/%s.debug",
771 build_id, build_id + 2);
772 free(build_id);
773 break;
774 }
775 self->origin++;
776 /* Fall thru */
777 case DSO__ORIG_DSO:
595 snprintf(name, size, "%s", self->name); 778 snprintf(name, size, "%s", self->name);
596 break; 779 break;
597 780
598 default: 781 default:
599 goto out; 782 goto out;
600 } 783 }
601 variant++;
602 784
603 fd = open(name, O_RDONLY); 785 fd = open(name, O_RDONLY);
604 } while (fd < 0); 786 } while (fd < 0);
605 787
606 ret = dso__load_sym(self, fd, name, filter, verbose); 788 ret = dso__load_sym(self, fd, name, filter, verbose, NULL);
607 close(fd); 789 close(fd);
608 790
609 /* 791 /*
@@ -612,11 +794,98 @@ more:
612 if (!ret) 794 if (!ret)
613 goto more; 795 goto more;
614 796
797 if (ret > 0) {
798 int nr_plt = dso__synthesize_plt_symbols(self, verbose);
799 if (nr_plt > 0)
800 ret += nr_plt;
801 }
615out: 802out:
616 free(name); 803 free(name);
804 if (ret < 0 && strstr(self->name, " (deleted)") != NULL)
805 return 0;
617 return ret; 806 return ret;
618} 807}
619 808
809static int dso__load_module(struct dso *self, struct mod_dso *mods, const char *name,
810 symbol_filter_t filter, int verbose)
811{
812 struct module *mod = mod_dso__find_module(mods, name);
813 int err = 0, fd;
814
815 if (mod == NULL || !mod->active)
816 return err;
817
818 fd = open(mod->path, O_RDONLY);
819
820 if (fd < 0)
821 return err;
822
823 err = dso__load_sym(self, fd, name, filter, verbose, mod);
824 close(fd);
825
826 return err;
827}
828
829int dso__load_modules(struct dso *self, symbol_filter_t filter, int verbose)
830{
831 struct mod_dso *mods = mod_dso__new_dso("modules");
832 struct module *pos;
833 struct rb_node *next;
834 int err;
835
836 err = mod_dso__load_modules(mods);
837
838 if (err <= 0)
839 return err;
840
841 /*
842 * Iterate over modules, and load active symbols.
843 */
844 next = rb_first(&mods->mods);
845 while (next) {
846 pos = rb_entry(next, struct module, rb_node);
847 err = dso__load_module(self, mods, pos->name, filter, verbose);
848
849 if (err < 0)
850 break;
851
852 next = rb_next(&pos->rb_node);
853 }
854
855 if (err < 0) {
856 mod_dso__delete_modules(mods);
857 mod_dso__delete_self(mods);
858 }
859
860 return err;
861}
862
863static inline void dso__fill_symbol_holes(struct dso *self)
864{
865 struct symbol *prev = NULL;
866 struct rb_node *nd;
867
868 for (nd = rb_last(&self->syms); nd; nd = rb_prev(nd)) {
869 struct symbol *pos = rb_entry(nd, struct symbol, rb_node);
870
871 if (prev) {
872 u64 hole = 0;
873 int alias = pos->start == prev->start;
874
875 if (!alias)
876 hole = prev->start - pos->end - 1;
877
878 if (hole || alias) {
879 if (alias)
880 pos->end = prev->end;
881 else if (hole)
882 pos->end = prev->start - 1;
883 }
884 }
885 prev = pos;
886 }
887}
888
620static int dso__load_vmlinux(struct dso *self, const char *vmlinux, 889static int dso__load_vmlinux(struct dso *self, const char *vmlinux,
621 symbol_filter_t filter, int verbose) 890 symbol_filter_t filter, int verbose)
622{ 891{
@@ -625,23 +894,33 @@ static int dso__load_vmlinux(struct dso *self, const char *vmlinux,
625 if (fd < 0) 894 if (fd < 0)
626 return -1; 895 return -1;
627 896
628 err = dso__load_sym(self, fd, vmlinux, filter, verbose); 897 err = dso__load_sym(self, fd, vmlinux, filter, verbose, NULL);
898
899 if (err > 0)
900 dso__fill_symbol_holes(self);
901
629 close(fd); 902 close(fd);
630 903
631 return err; 904 return err;
632} 905}
633 906
634int dso__load_kernel(struct dso *self, const char *vmlinux, 907int dso__load_kernel(struct dso *self, const char *vmlinux,
635 symbol_filter_t filter, int verbose) 908 symbol_filter_t filter, int verbose, int modules)
636{ 909{
637 int err = -1; 910 int err = -1;
638 911
639 if (vmlinux) 912 if (vmlinux) {
640 err = dso__load_vmlinux(self, vmlinux, filter, verbose); 913 err = dso__load_vmlinux(self, vmlinux, filter, verbose);
914 if (err > 0 && modules)
915 err = dso__load_modules(self, filter, verbose);
916 }
641 917
642 if (err < 0) 918 if (err <= 0)
643 err = dso__load_kallsyms(self, filter, verbose); 919 err = dso__load_kallsyms(self, filter, verbose);
644 920
921 if (err > 0)
922 self->origin = DSO__ORIG_KERNEL;
923
645 return err; 924 return err;
646} 925}
647 926
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 2c48ace8203b..b53bf0125c1b 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -3,8 +3,33 @@
3 3
4#include <linux/types.h> 4#include <linux/types.h>
5#include "types.h" 5#include "types.h"
6#include "list.h" 6#include <linux/list.h>
7#include "rbtree.h" 7#include <linux/rbtree.h>
8#include "module.h"
9
10#ifdef HAVE_CPLUS_DEMANGLE
11extern char *cplus_demangle(const char *, int);
12
13static inline char *bfd_demangle(void __used *v, const char *c, int i)
14{
15 return cplus_demangle(c, i);
16}
17#else
18#ifdef NO_DEMANGLE
19static inline char *bfd_demangle(void __used *v, const char __used *c,
20 int __used i)
21{
22 return NULL;
23}
24#else
25#include <bfd.h>
26#endif
27#endif
28
29#ifndef DMGL_PARAMS
30#define DMGL_PARAMS (1 << 0) /* Include function args */
31#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */
32#endif
8 33
9struct symbol { 34struct symbol {
10 struct rb_node rb_node; 35 struct rb_node rb_node;
@@ -13,6 +38,7 @@ struct symbol {
13 u64 obj_start; 38 u64 obj_start;
14 u64 hist_sum; 39 u64 hist_sum;
15 u64 *hist; 40 u64 *hist;
41 struct module *module;
16 void *priv; 42 void *priv;
17 char name[0]; 43 char name[0];
18}; 44};
@@ -22,7 +48,9 @@ struct dso {
22 struct rb_root syms; 48 struct rb_root syms;
23 struct symbol *(*find_symbol)(struct dso *, u64 ip); 49 struct symbol *(*find_symbol)(struct dso *, u64 ip);
24 unsigned int sym_priv_size; 50 unsigned int sym_priv_size;
25 unsigned char prelinked; 51 unsigned char adjust_symbols;
52 unsigned char slen_calculated;
53 unsigned char origin;
26 char name[0]; 54 char name[0];
27}; 55};
28 56
@@ -41,10 +69,12 @@ static inline void *dso__sym_priv(struct dso *self, struct symbol *sym)
41struct symbol *dso__find_symbol(struct dso *self, u64 ip); 69struct symbol *dso__find_symbol(struct dso *self, u64 ip);
42 70
43int dso__load_kernel(struct dso *self, const char *vmlinux, 71int dso__load_kernel(struct dso *self, const char *vmlinux,
44 symbol_filter_t filter, int verbose); 72 symbol_filter_t filter, int verbose, int modules);
73int dso__load_modules(struct dso *self, symbol_filter_t filter, int verbose);
45int dso__load(struct dso *self, symbol_filter_t filter, int verbose); 74int dso__load(struct dso *self, symbol_filter_t filter, int verbose);
46 75
47size_t dso__fprintf(struct dso *self, FILE *fp); 76size_t dso__fprintf(struct dso *self, FILE *fp);
77char dso__symtab_origin(const struct dso *self);
48 78
49void symbol__init(void); 79void symbol__init(void);
50#endif /* _PERF_SYMBOL_ */ 80#endif /* _PERF_SYMBOL_ */
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index b4be6071c105..68fe157d72fb 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -50,6 +50,7 @@
50#include <unistd.h> 50#include <unistd.h>
51#include <stdio.h> 51#include <stdio.h>
52#include <sys/stat.h> 52#include <sys/stat.h>
53#include <sys/statfs.h>
53#include <fcntl.h> 54#include <fcntl.h>
54#include <stddef.h> 55#include <stddef.h>
55#include <stdlib.h> 56#include <stdlib.h>
@@ -80,6 +81,7 @@
80#include <netdb.h> 81#include <netdb.h>
81#include <pwd.h> 82#include <pwd.h>
82#include <inttypes.h> 83#include <inttypes.h>
84#include "../../../include/linux/magic.h"
83 85
84#ifndef NO_ICONV 86#ifndef NO_ICONV
85#include <iconv.h> 87#include <iconv.h>
diff --git a/tools/perf/util/wrapper.c b/tools/perf/util/wrapper.c
index 6350d65f6d9e..4574ac28396f 100644
--- a/tools/perf/util/wrapper.c
+++ b/tools/perf/util/wrapper.c
@@ -7,7 +7,7 @@
7 * There's no pack memory to release - but stay close to the Git 7 * There's no pack memory to release - but stay close to the Git
8 * version so wrap this away: 8 * version so wrap this away:
9 */ 9 */
10static inline void release_pack_memory(size_t size, int flag) 10static inline void release_pack_memory(size_t size __used, int flag __used)
11{ 11{
12} 12}
13 13
@@ -59,7 +59,8 @@ void *xmemdupz(const void *data, size_t len)
59char *xstrndup(const char *str, size_t len) 59char *xstrndup(const char *str, size_t len)
60{ 60{
61 char *p = memchr(str, '\0', len); 61 char *p = memchr(str, '\0', len);
62 return xmemdupz(str, p ? p - str : len); 62
63 return xmemdupz(str, p ? (size_t)(p - str) : len);
63} 64}
64 65
65void *xrealloc(void *ptr, size_t size) 66void *xrealloc(void *ptr, size_t size)