aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/CREDITS30
-rw-r--r--tools/perf/Documentation/Makefile2
-rw-r--r--tools/perf/Documentation/examples.txt225
-rw-r--r--tools/perf/Documentation/perf-record.txt60
-rw-r--r--tools/perf/Documentation/perf-report.txt29
-rw-r--r--tools/perf/Documentation/perf-stat.txt6
-rw-r--r--tools/perf/Documentation/perf-top.txt112
-rw-r--r--tools/perf/Makefile66
-rw-r--r--tools/perf/builtin-annotate.c108
-rw-r--r--tools/perf/builtin-help.c6
-rw-r--r--tools/perf/builtin-list.c5
-rw-r--r--tools/perf/builtin-record.c242
-rw-r--r--tools/perf/builtin-report.c933
-rw-r--r--tools/perf/builtin-stat.c221
-rw-r--r--tools/perf/builtin-top.c636
-rw-r--r--tools/perf/perf.c82
-rw-r--r--tools/perf/perf.h35
-rw-r--r--tools/perf/util/alias.c2
-rw-r--r--tools/perf/util/cache.h2
-rw-r--r--tools/perf/util/callchain.c343
-rw-r--r--tools/perf/util/callchain.h60
-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.c245
-rw-r--r--tools/perf/util/header.h37
-rw-r--r--tools/perf/util/help.c41
-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/pager.c5
-rw-r--r--tools/perf/util/parse-events.c584
-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/run-command.c95
-rw-r--r--tools/perf/util/run-command.h5
-rw-r--r--tools/perf/util/strbuf.c15
-rw-r--r--tools/perf/util/strbuf.h10
-rw-r--r--tools/perf/util/string.h5
-rw-r--r--tools/perf/util/strlist.c200
-rw-r--r--tools/perf/util/strlist.h39
-rw-r--r--tools/perf/util/symbol.c443
-rw-r--r--tools/perf/util/symbol.h41
-rw-r--r--tools/perf/util/types.h (renamed from tools/perf/types.h)0
-rw-r--r--tools/perf/util/util.h17
-rw-r--r--tools/perf/util/wrapper.c5
60 files changed, 4832 insertions, 2100 deletions
diff --git a/tools/perf/CREDITS b/tools/perf/CREDITS
new file mode 100644
index 000000000000..c2ddcb3acbd0
--- /dev/null
+++ b/tools/perf/CREDITS
@@ -0,0 +1,30 @@
1Most of the infrastructure that 'perf' uses here has been reused
2from the Git project, as of version:
3
4 66996ec: Sync with 1.6.2.4
5
6Here is an (incomplete!) list of main contributors to those files
7in util/* and elsewhere:
8
9 Alex Riesen
10 Christian Couder
11 Dmitry Potapov
12 Jeff King
13 Johannes Schindelin
14 Johannes Sixt
15 Junio C Hamano
16 Linus Torvalds
17 Matthias Kestenholz
18 Michal Ostrowski
19 Miklos Vajna
20 Petr Baudis
21 Pierre Habouzit
22 René Scharfe
23 Samuel Tardieu
24 Shawn O. Pearce
25 Steffen Prohaska
26 Steve Haslam
27
28Thanks guys!
29
30The full history of the files can be found in the upstream Git commits.
diff --git a/tools/perf/Documentation/Makefile b/tools/perf/Documentation/Makefile
index 5457192e1b41..bdd3b7ecad0a 100644
--- a/tools/perf/Documentation/Makefile
+++ b/tools/perf/Documentation/Makefile
@@ -35,7 +35,7 @@ man7dir=$(mandir)/man7
35# DESTDIR= 35# DESTDIR=
36 36
37ASCIIDOC=asciidoc 37ASCIIDOC=asciidoc
38ASCIIDOC_EXTRA = 38ASCIIDOC_EXTRA = --unsafe
39MANPAGE_XSL = manpage-normal.xsl 39MANPAGE_XSL = manpage-normal.xsl
40XMLTO_EXTRA = 40XMLTO_EXTRA =
41INSTALL?=install 41INSTALL?=install
diff --git a/tools/perf/Documentation/examples.txt b/tools/perf/Documentation/examples.txt
new file mode 100644
index 000000000000..8eb6c489fb15
--- /dev/null
+++ b/tools/perf/Documentation/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 52d3fc6846a9..e72e93110782 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -13,13 +13,40 @@ SYNOPSIS
13DESCRIPTION 13DESCRIPTION
14----------- 14-----------
15This command displays the performance counter profile information recorded 15This command displays the performance counter profile information recorded
16via perf report. 16via perf record.
17 17
18OPTIONS 18OPTIONS
19------- 19-------
20-i:: 20-i::
21--input=:: 21--input=::
22 Input file name. (default: perf.data) 22 Input file name. (default: perf.data)
23-d::
24--dsos=::
25 Only consider symbols in these dsos. CSV that understands
26 file://filename entries.
27-n
28--show-nr-samples
29 Show the number of samples for each symbol
30-C::
31--comms=::
32 Only consider symbols in these comms. CSV that understands
33 file://filename entries.
34-S::
35--symbols=::
36 Only consider these symbols. CSV that understands
37 file://filename entries.
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.
23 50
24SEE ALSO 51SEE ALSO
25-------- 52--------
diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index c368a72721d7..484080dd5b6f 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -8,8 +8,8 @@ perf-stat - Run a command and gather performance counter statistics
8SYNOPSIS 8SYNOPSIS
9-------- 9--------
10[verse] 10[verse]
11'perf stat' [-e <EVENT> | --event=EVENT] [-l] [-a] <command> 11'perf stat' [-e <EVENT> | --event=EVENT] [-S] [-a] <command>
12'perf stat' [-e <EVENT> | --event=EVENT] [-l] [-a] -- <command> [<options>] 12'perf stat' [-e <EVENT> | --event=EVENT] [-S] [-a] -- <command> [<options>]
13 13
14DESCRIPTION 14DESCRIPTION
15----------- 15-----------
@@ -40,7 +40,7 @@ OPTIONS
40-a:: 40-a::
41 system-wide collection 41 system-wide collection
42 42
43-l:: 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 36d7eef49913..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 += 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
@@ -301,9 +304,11 @@ LIB_H += util/util.h
301LIB_H += util/help.h 304LIB_H += util/help.h
302LIB_H += util/strbuf.h 305LIB_H += util/strbuf.h
303LIB_H += util/string.h 306LIB_H += util/string.h
307LIB_H += util/strlist.h
304LIB_H += util/run-command.h 308LIB_H += util/run-command.h
305LIB_H += util/sigchain.h 309LIB_H += util/sigchain.h
306LIB_H += util/symbol.h 310LIB_H += util/symbol.h
311LIB_H += util/module.h
307LIB_H += util/color.h 312LIB_H += util/color.h
308 313
309LIB_OBJS += util/abspath.o 314LIB_OBJS += util/abspath.o
@@ -322,12 +327,16 @@ LIB_OBJS += util/run-command.o
322LIB_OBJS += util/quote.o 327LIB_OBJS += util/quote.o
323LIB_OBJS += util/strbuf.o 328LIB_OBJS += util/strbuf.o
324LIB_OBJS += util/string.o 329LIB_OBJS += util/string.o
330LIB_OBJS += util/strlist.o
325LIB_OBJS += util/usage.o 331LIB_OBJS += util/usage.o
326LIB_OBJS += util/wrapper.o 332LIB_OBJS += util/wrapper.o
327LIB_OBJS += util/sigchain.o 333LIB_OBJS += util/sigchain.o
328LIB_OBJS += util/symbol.o 334LIB_OBJS += util/symbol.o
335LIB_OBJS += util/module.o
329LIB_OBJS += util/color.o 336LIB_OBJS += util/color.o
330LIB_OBJS += util/pager.o 337LIB_OBJS += util/pager.o
338LIB_OBJS += util/header.o
339LIB_OBJS += util/callchain.o
331 340
332BUILTIN_OBJS += builtin-annotate.o 341BUILTIN_OBJS += builtin-annotate.o
333BUILTIN_OBJS += builtin-help.o 342BUILTIN_OBJS += builtin-help.o
@@ -338,7 +347,6 @@ BUILTIN_OBJS += builtin-stat.o
338BUILTIN_OBJS += builtin-top.o 347BUILTIN_OBJS += builtin-top.o
339 348
340PERFLIBS = $(LIB_FILE) 349PERFLIBS = $(LIB_FILE)
341EXTLIBS =
342 350
343# 351#
344# Platform specific tweaks 352# Platform specific tweaks
@@ -367,6 +375,39 @@ ifeq ($(uname_S),Darwin)
367 PTHREAD_LIBS = 375 PTHREAD_LIBS =
368endif 376endif
369 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
370ifndef CC_LD_DYNPATH 411ifndef CC_LD_DYNPATH
371 ifdef NO_R_TO_GCC_LINKER 412 ifdef NO_R_TO_GCC_LINKER
372 # 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
@@ -377,12 +418,6 @@ ifndef CC_LD_DYNPATH
377 endif 418 endif
378endif 419endif
379 420
380ifdef ZLIB_PATH
381 BASIC_CFLAGS += -I$(ZLIB_PATH)/include
382 EXTLIBS += -L$(ZLIB_PATH)/$(lib) $(CC_LD_DYNPATH)$(ZLIB_PATH)/$(lib)
383endif
384EXTLIBS += -lz
385
386ifdef NEEDS_SOCKET 421ifdef NEEDS_SOCKET
387 EXTLIBS += -lsocket 422 EXTLIBS += -lsocket
388endif 423endif
@@ -693,6 +728,9 @@ builtin-init-db.o: builtin-init-db.c PERF-CFLAGS
693util/config.o: util/config.c PERF-CFLAGS 728util/config.o: util/config.c PERF-CFLAGS
694 $(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)"' $<
695 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
696perf-%$X: %.o $(PERFLIBS) 734perf-%$X: %.o $(PERFLIBS)
697 $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS) 735 $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)
698 736
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 7e58e3ad1508..343e7b14bf01 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];
@@ -855,7 +847,7 @@ static unsigned long total = 0,
855 total_unknown = 0; 847 total_unknown = 0;
856 848
857static int 849static int
858process_overflow_event(event_t *event, unsigned long offset, unsigned long head) 850process_sample_event(event_t *event, unsigned long offset, unsigned long head)
859{ 851{
860 char level; 852 char level;
861 int show = 0; 853 int show = 0;
@@ -988,6 +980,13 @@ process_fork_event(event_t *event, unsigned long offset, unsigned long head)
988 (void *)(long)(event->header.size), 980 (void *)(long)(event->header.size),
989 event->fork.pid, event->fork.ppid); 981 event->fork.pid, event->fork.ppid);
990 982
983 /*
984 * A thread clone will have the same PID for both
985 * parent and child.
986 */
987 if (thread == parent)
988 return 0;
989
991 if (!thread || !parent || thread__fork(thread, parent)) { 990 if (!thread || !parent || thread__fork(thread, parent)) {
992 dprintf("problem processing PERF_EVENT_FORK, skipping event.\n"); 991 dprintf("problem processing PERF_EVENT_FORK, skipping event.\n");
993 return -1; 992 return -1;
@@ -998,25 +997,12 @@ process_fork_event(event_t *event, unsigned long offset, unsigned long head)
998} 997}
999 998
1000static int 999static 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) 1000process_event(event_t *event, unsigned long offset, unsigned long head)
1015{ 1001{
1016 if (event->header.misc & PERF_EVENT_MISC_OVERFLOW)
1017 return process_overflow_event(event, offset, head);
1018
1019 switch (event->header.type) { 1002 switch (event->header.type) {
1003 case PERF_EVENT_SAMPLE:
1004 return process_sample_event(event, offset, head);
1005
1020 case PERF_EVENT_MMAP: 1006 case PERF_EVENT_MMAP:
1021 return process_mmap_event(event, offset, head); 1007 return process_mmap_event(event, offset, head);
1022 1008
@@ -1025,9 +1011,6 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
1025 1011
1026 case PERF_EVENT_FORK: 1012 case PERF_EVENT_FORK:
1027 return process_fork_event(event, offset, head); 1013 return process_fork_event(event, offset, head);
1028
1029 case PERF_EVENT_PERIOD:
1030 return process_period_event(event, offset, head);
1031 /* 1014 /*
1032 * We dont process them right now but they are fine: 1015 * We dont process them right now but they are fine:
1033 */ 1016 */
@@ -1043,24 +1026,6 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
1043 return 0; 1026 return 0;
1044} 1027}
1045 1028
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 1029static int
1065parse_line(FILE *file, struct symbol *sym, u64 start, u64 len) 1030parse_line(FILE *file, struct symbol *sym, u64 start, u64 len)
1066{ 1031{
@@ -1069,7 +1034,7 @@ parse_line(FILE *file, struct symbol *sym, u64 start, u64 len)
1069 static const char *prev_color; 1034 static const char *prev_color;
1070 unsigned int offset; 1035 unsigned int offset;
1071 size_t line_len; 1036 size_t line_len;
1072 u64 line_ip; 1037 s64 line_ip;
1073 int ret; 1038 int ret;
1074 char *c; 1039 char *c;
1075 1040
@@ -1122,7 +1087,7 @@ parse_line(FILE *file, struct symbol *sym, u64 start, u64 len)
1122 } else if (sym->hist_sum) 1087 } else if (sym->hist_sum)
1123 percent = 100.0 * hits / sym->hist_sum; 1088 percent = 100.0 * hits / sym->hist_sum;
1124 1089
1125 color = get_color(percent); 1090 color = get_percent_color(percent);
1126 1091
1127 /* 1092 /*
1128 * Also color the filename and line if needed, with 1093 * Also color the filename and line if needed, with
@@ -1258,7 +1223,7 @@ static void print_summary(char *filename)
1258 1223
1259 sym_ext = rb_entry(node, struct sym_ext, node); 1224 sym_ext = rb_entry(node, struct sym_ext, node);
1260 percent = sym_ext->percent; 1225 percent = sym_ext->percent;
1261 color = get_color(percent); 1226 color = get_percent_color(percent);
1262 path = sym_ext->path; 1227 path = sym_ext->path;
1263 1228
1264 color_fprintf(stdout, color, " %7.2f %s", percent, path); 1229 color_fprintf(stdout, color, " %7.2f %s", percent, path);
@@ -1268,19 +1233,25 @@ static void print_summary(char *filename)
1268 1233
1269static void annotate_sym(struct dso *dso, struct symbol *sym) 1234static void annotate_sym(struct dso *dso, struct symbol *sym)
1270{ 1235{
1271 char *filename = dso->name; 1236 char *filename = dso->name, *d_filename;
1272 u64 start, end, len; 1237 u64 start, end, len;
1273 char command[PATH_MAX*2]; 1238 char command[PATH_MAX*2];
1274 FILE *file; 1239 FILE *file;
1275 1240
1276 if (!filename) 1241 if (!filename)
1277 return; 1242 return;
1278 if (dso == kernel_dso) 1243 if (sym->module)
1244 filename = sym->module->path;
1245 else if (dso == kernel_dso)
1279 filename = vmlinux; 1246 filename = vmlinux;
1280 1247
1281 start = sym->obj_start; 1248 start = sym->obj_start;
1282 if (!start) 1249 if (!start)
1283 start = sym->start; 1250 start = sym->start;
1251 if (full_paths)
1252 d_filename = filename;
1253 else
1254 d_filename = basename(filename);
1284 1255
1285 end = start + sym->end - sym->start + 1; 1256 end = start + sym->end - sym->start + 1;
1286 len = sym->end - sym->start; 1257 len = sym->end - sym->start;
@@ -1291,13 +1262,14 @@ static void annotate_sym(struct dso *dso, struct symbol *sym)
1291 } 1262 }
1292 1263
1293 printf("\n\n------------------------------------------------\n"); 1264 printf("\n\n------------------------------------------------\n");
1294 printf(" Percent | Source code & Disassembly of %s\n", filename); 1265 printf(" Percent | Source code & Disassembly of %s\n", d_filename);
1295 printf("------------------------------------------------\n"); 1266 printf("------------------------------------------------\n");
1296 1267
1297 if (verbose >= 2) 1268 if (verbose >= 2)
1298 printf("annotating [%p] %30s : [%p] %30s\n", dso, dso->name, sym, sym->name); 1269 printf("annotating [%p] %30s : [%p] %30s\n", dso, dso->name, sym, sym->name);
1299 1270
1300 sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s", (u64)start, (u64)end, filename); 1271 sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s|grep -v %s",
1272 (u64)start, (u64)end, filename, filename);
1301 1273
1302 if (verbose >= 3) 1274 if (verbose >= 3)
1303 printf("doing: %s\n", command); 1275 printf("doing: %s\n", command);
@@ -1428,7 +1400,7 @@ more:
1428 1400
1429 head += size; 1401 head += size;
1430 1402
1431 if (offset + head < stat.st_size) 1403 if (offset + head < (unsigned long)stat.st_size)
1432 goto more; 1404 goto more;
1433 1405
1434 rc = EXIT_SUCCESS; 1406 rc = EXIT_SUCCESS;
@@ -1472,8 +1444,12 @@ static const struct option options[] = {
1472 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 1444 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
1473 "dump raw trace in ASCII"), 1445 "dump raw trace in ASCII"),
1474 OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"), 1446 OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"),
1447 OPT_BOOLEAN('m', "modules", &modules,
1448 "load module symbols - WARNING: use only with -k and LIVE kernel"),
1475 OPT_BOOLEAN('l', "print-line", &print_line, 1449 OPT_BOOLEAN('l', "print-line", &print_line,
1476 "print matching source lines (may be slow)"), 1450 "print matching source lines (may be slow)"),
1451 OPT_BOOLEAN('P', "full-paths", &full_paths,
1452 "Don't shorten the displayed pathnames"),
1477 OPT_END() 1453 OPT_END()
1478}; 1454};
1479 1455
@@ -1492,7 +1468,7 @@ static void setup_sorting(void)
1492 free(str); 1468 free(str);
1493} 1469}
1494 1470
1495int cmd_annotate(int argc, const char **argv, const char *prefix) 1471int cmd_annotate(int argc, const char **argv, const char *prefix __used)
1496{ 1472{
1497 symbol__init(); 1473 symbol__init();
1498 1474
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 d7ebbd757543..89a5ddcd1ded 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -14,6 +14,8 @@
14#include "util/parse-events.h" 14#include "util/parse-events.h"
15#include "util/string.h" 15#include "util/string.h"
16 16
17#include "util/header.h"
18
17#include <unistd.h> 19#include <unistd.h>
18#include <sched.h> 20#include <sched.h>
19 21
@@ -32,13 +34,18 @@ static int output;
32static const char *output_name = "perf.data"; 34static const char *output_name = "perf.data";
33static int group = 0; 35static int group = 0;
34static unsigned int realtime_prio = 0; 36static unsigned int realtime_prio = 0;
37static int raw_samples = 0;
35static int system_wide = 0; 38static int system_wide = 0;
39static int profile_cpu = -1;
36static pid_t target_pid = -1; 40static pid_t target_pid = -1;
37static int inherit = 1; 41static int inherit = 1;
38static int force = 0; 42static int force = 0;
39static int append_file = 0; 43static int append_file = 0;
40static int call_graph = 0; 44static int call_graph = 0;
41static int verbose = 0; 45static int verbose = 0;
46static int inherit_stat = 0;
47static int no_samples = 0;
48static int sample_address = 0;
42 49
43static long samples; 50static long samples;
44static struct timeval last_read; 51static struct timeval last_read;
@@ -52,7 +59,8 @@ static int nr_poll;
52static int nr_cpu; 59static int nr_cpu;
53 60
54static int file_new = 1; 61static int file_new = 1;
55static struct perf_file_header file_header; 62
63struct perf_header *header;
56 64
57struct mmap_event { 65struct mmap_event {
58 struct perf_event_header header; 66 struct perf_event_header header;
@@ -197,46 +205,48 @@ static void sig_atexit(void)
197 kill(getpid(), signr); 205 kill(getpid(), signr);
198} 206}
199 207
200static void pid_synthesize_comm_event(pid_t pid, int full) 208static pid_t pid_synthesize_comm_event(pid_t pid, int full)
201{ 209{
202 struct comm_event comm_ev; 210 struct comm_event comm_ev;
203 char filename[PATH_MAX]; 211 char filename[PATH_MAX];
204 char bf[BUFSIZ]; 212 char bf[BUFSIZ];
205 int fd; 213 FILE *fp;
206 size_t size; 214 size_t size = 0;
207 char *field, *sep;
208 DIR *tasks; 215 DIR *tasks;
209 struct dirent dirent, *next; 216 struct dirent dirent, *next;
217 pid_t tgid = 0;
210 218
211 snprintf(filename, sizeof(filename), "/proc/%d/stat", pid); 219 snprintf(filename, sizeof(filename), "/proc/%d/status", pid);
212 220
213 fd = open(filename, O_RDONLY); 221 fp = fopen(filename, "r");
214 if (fd < 0) { 222 if (fp == NULL) {
215 /* 223 /*
216 * We raced with a task exiting - just return: 224 * We raced with a task exiting - just return:
217 */ 225 */
218 if (verbose) 226 if (verbose)
219 fprintf(stderr, "couldn't open %s\n", filename); 227 fprintf(stderr, "couldn't open %s\n", filename);
220 return; 228 return 0;
221 } 229 }
222 if (read(fd, bf, sizeof(bf)) < 0) {
223 fprintf(stderr, "couldn't read %s\n", filename);
224 exit(EXIT_FAILURE);
225 }
226 close(fd);
227 230
228 /* 9027 (cat) R 6747 9027 6747 34816 9027 ... */
229 memset(&comm_ev, 0, sizeof(comm_ev)); 231 memset(&comm_ev, 0, sizeof(comm_ev));
230 field = strchr(bf, '('); 232 while (!comm_ev.comm[0] || !comm_ev.pid) {
231 if (field == NULL) 233 if (fgets(bf, sizeof(bf), fp) == NULL)
232 goto out_failure; 234 goto out_failure;
233 sep = strchr(++field, ')'); 235
234 if (sep == NULL) 236 if (memcmp(bf, "Name:", 5) == 0) {
235 goto out_failure; 237 char *name = bf + 5;
236 size = sep - field; 238 while (*name && isspace(*name))
237 memcpy(comm_ev.comm, field, size++); 239 ++name;
238 240 size = strlen(name) - 1;
239 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
240 comm_ev.header.type = PERF_EVENT_COMM; 250 comm_ev.header.type = PERF_EVENT_COMM;
241 size = ALIGN(size, sizeof(u64)); 251 size = ALIGN(size, sizeof(u64));
242 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);
@@ -245,7 +255,7 @@ static void pid_synthesize_comm_event(pid_t pid, int full)
245 comm_ev.tid = pid; 255 comm_ev.tid = pid;
246 256
247 write_output(&comm_ev, comm_ev.header.size); 257 write_output(&comm_ev, comm_ev.header.size);
248 return; 258 goto out_fclose;
249 } 259 }
250 260
251 snprintf(filename, sizeof(filename), "/proc/%d/task", pid); 261 snprintf(filename, sizeof(filename), "/proc/%d/task", pid);
@@ -262,7 +272,10 @@ static void pid_synthesize_comm_event(pid_t pid, int full)
262 write_output(&comm_ev, comm_ev.header.size); 272 write_output(&comm_ev, comm_ev.header.size);
263 } 273 }
264 closedir(tasks); 274 closedir(tasks);
265 return; 275
276out_fclose:
277 fclose(fp);
278 return tgid;
266 279
267out_failure: 280out_failure:
268 fprintf(stderr, "couldn't get COMM and pgid, malformed %s\n", 281 fprintf(stderr, "couldn't get COMM and pgid, malformed %s\n",
@@ -270,7 +283,7 @@ out_failure:
270 exit(EXIT_FAILURE); 283 exit(EXIT_FAILURE);
271} 284}
272 285
273static void pid_synthesize_mmap_samples(pid_t pid) 286static void pid_synthesize_mmap_samples(pid_t pid, pid_t tgid)
274{ 287{
275 char filename[PATH_MAX]; 288 char filename[PATH_MAX];
276 FILE *fp; 289 FILE *fp;
@@ -289,7 +302,7 @@ static void pid_synthesize_mmap_samples(pid_t pid)
289 while (1) { 302 while (1) {
290 char bf[BUFSIZ], *pbf = bf; 303 char bf[BUFSIZ], *pbf = bf;
291 struct mmap_event mmap_ev = { 304 struct mmap_event mmap_ev = {
292 .header.type = PERF_EVENT_MMAP, 305 .header = { .type = PERF_EVENT_MMAP },
293 }; 306 };
294 int n; 307 int n;
295 size_t size; 308 size_t size;
@@ -306,12 +319,15 @@ static void pid_synthesize_mmap_samples(pid_t pid)
306 continue; 319 continue;
307 pbf += n + 3; 320 pbf += n + 3;
308 if (*pbf == 'x') { /* vm_exec */ 321 if (*pbf == 'x') { /* vm_exec */
309 char *execname = strrchr(bf, ' '); 322 char *execname = strchr(bf, '/');
310 323
311 if (execname == NULL || execname[1] != '/') 324 /* Catch VDSO */
325 if (execname == NULL)
326 execname = strstr(bf, "[vdso]");
327
328 if (execname == NULL)
312 continue; 329 continue;
313 330
314 execname += 1;
315 size = strlen(execname); 331 size = strlen(execname);
316 execname[size - 1] = '\0'; /* Remove \n */ 332 execname[size - 1] = '\0'; /* Remove \n */
317 memcpy(mmap_ev.filename, execname, size); 333 memcpy(mmap_ev.filename, execname, size);
@@ -319,7 +335,7 @@ static void pid_synthesize_mmap_samples(pid_t pid)
319 mmap_ev.len -= mmap_ev.start; 335 mmap_ev.len -= mmap_ev.start;
320 mmap_ev.header.size = (sizeof(mmap_ev) - 336 mmap_ev.header.size = (sizeof(mmap_ev) -
321 (sizeof(mmap_ev.filename) - size)); 337 (sizeof(mmap_ev.filename) - size));
322 mmap_ev.pid = pid; 338 mmap_ev.pid = tgid;
323 mmap_ev.tid = pid; 339 mmap_ev.tid = pid;
324 340
325 write_output(&mmap_ev, mmap_ev.header.size); 341 write_output(&mmap_ev, mmap_ev.header.size);
@@ -329,7 +345,7 @@ static void pid_synthesize_mmap_samples(pid_t pid)
329 fclose(fp); 345 fclose(fp);
330} 346}
331 347
332static void synthesize_samples(void) 348static void synthesize_all(void)
333{ 349{
334 DIR *proc; 350 DIR *proc;
335 struct dirent dirent, *next; 351 struct dirent dirent, *next;
@@ -338,14 +354,14 @@ static void synthesize_samples(void)
338 354
339 while (!readdir_r(proc, &dirent, &next) && next) { 355 while (!readdir_r(proc, &dirent, &next) && next) {
340 char *end; 356 char *end;
341 pid_t pid; 357 pid_t pid, tgid;
342 358
343 pid = strtol(dirent.d_name, &end, 10); 359 pid = strtol(dirent.d_name, &end, 10);
344 if (*end) /* only interested in proper numerical dirents */ 360 if (*end) /* only interested in proper numerical dirents */
345 continue; 361 continue;
346 362
347 pid_synthesize_comm_event(pid, 1); 363 tgid = pid_synthesize_comm_event(pid, 1);
348 pid_synthesize_mmap_samples(pid); 364 pid_synthesize_mmap_samples(pid, tgid);
349 } 365 }
350 366
351 closedir(proc); 367 closedir(proc);
@@ -353,12 +369,37 @@ static void synthesize_samples(void)
353 369
354static int group_fd; 370static int group_fd;
355 371
372static struct perf_header_attr *get_header_attr(struct perf_counter_attr *a, int nr)
373{
374 struct perf_header_attr *h_attr;
375
376 if (nr < header->attrs) {
377 h_attr = header->attr[nr];
378 } else {
379 h_attr = perf_header_attr__new(a);
380 perf_header__add_attr(header, h_attr);
381 }
382
383 return h_attr;
384}
385
356static void create_counter(int counter, int cpu, pid_t pid) 386static void create_counter(int counter, int cpu, pid_t pid)
357{ 387{
358 struct perf_counter_attr *attr = attrs + counter; 388 struct perf_counter_attr *attr = attrs + counter;
359 int track = 1; 389 struct perf_header_attr *h_attr;
390 int track = !counter; /* only the first counter needs these */
391 struct {
392 u64 count;
393 u64 time_enabled;
394 u64 time_running;
395 u64 id;
396 } read_data;
360 397
361 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID; 398 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
399 PERF_FORMAT_TOTAL_TIME_RUNNING |
400 PERF_FORMAT_ID;
401
402 attr->sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID;
362 403
363 if (freq) { 404 if (freq) {
364 attr->sample_type |= PERF_SAMPLE_PERIOD; 405 attr->sample_type |= PERF_SAMPLE_PERIOD;
@@ -366,25 +407,26 @@ static void create_counter(int counter, int cpu, pid_t pid)
366 attr->sample_freq = freq; 407 attr->sample_freq = freq;
367 } 408 }
368 409
410 if (no_samples)
411 attr->sample_freq = 0;
412
413 if (inherit_stat)
414 attr->inherit_stat = 1;
415
416 if (sample_address)
417 attr->sample_type |= PERF_SAMPLE_ADDR;
418
369 if (call_graph) 419 if (call_graph)
370 attr->sample_type |= PERF_SAMPLE_CALLCHAIN; 420 attr->sample_type |= PERF_SAMPLE_CALLCHAIN;
371 421
372 if (file_new) { 422 if (raw_samples)
373 file_header.sample_type = attr->sample_type; 423 attr->sample_type |= PERF_SAMPLE_RAW;
374 } else {
375 if (file_header.sample_type != attr->sample_type) {
376 fprintf(stderr, "incompatible append\n");
377 exit(-1);
378 }
379 }
380 424
381 attr->mmap = track; 425 attr->mmap = track;
382 attr->comm = track; 426 attr->comm = track;
383 attr->inherit = (cpu < 0) && inherit; 427 attr->inherit = (cpu < 0) && inherit;
384 attr->disabled = 1; 428 attr->disabled = 1;
385 429
386 track = 0; /* only the first counter needs these */
387
388try_again: 430try_again:
389 fd[nr_cpu][counter] = sys_perf_counter_open(attr, pid, cpu, group_fd, 0); 431 fd[nr_cpu][counter] = sys_perf_counter_open(attr, pid, cpu, group_fd, 0);
390 432
@@ -393,6 +435,8 @@ try_again:
393 435
394 if (err == EPERM) 436 if (err == EPERM)
395 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");
396 440
397 /* 441 /*
398 * If it's cycles then fall back to hrtimer 442 * If it's cycles then fall back to hrtimer
@@ -415,6 +459,22 @@ try_again:
415 exit(-1); 459 exit(-1);
416 } 460 }
417 461
462 h_attr = get_header_attr(attr, counter);
463
464 if (!file_new) {
465 if (memcmp(&h_attr->attr, attr, sizeof(*attr))) {
466 fprintf(stderr, "incompatible append\n");
467 exit(-1);
468 }
469 }
470
471 if (read(fd[nr_cpu][counter], &read_data, sizeof(read_data)) == -1) {
472 perror("Unable to read perf file descriptor\n");
473 exit(-1);
474 }
475
476 perf_header_attr__add_id(h_attr, read_data.id);
477
418 assert(fd[nr_cpu][counter] >= 0); 478 assert(fd[nr_cpu][counter] >= 0);
419 fcntl(fd[nr_cpu][counter], F_SETFL, O_NONBLOCK); 479 fcntl(fd[nr_cpu][counter], F_SETFL, O_NONBLOCK);
420 480
@@ -445,11 +505,6 @@ static void open_counters(int cpu, pid_t pid)
445{ 505{
446 int counter; 506 int counter;
447 507
448 if (pid > 0) {
449 pid_synthesize_comm_event(pid, 0);
450 pid_synthesize_mmap_samples(pid);
451 }
452
453 group_fd = -1; 508 group_fd = -1;
454 for (counter = 0; counter < nr_counters; counter++) 509 for (counter = 0; counter < nr_counters; counter++)
455 create_counter(counter, cpu, pid); 510 create_counter(counter, cpu, pid);
@@ -459,17 +514,16 @@ static void open_counters(int cpu, pid_t pid)
459 514
460static void atexit_header(void) 515static void atexit_header(void)
461{ 516{
462 file_header.data_size += bytes_written; 517 header->data_size += bytes_written;
463 518
464 if (pwrite(output, &file_header, sizeof(file_header), 0) == -1) 519 perf_header__write(header, output);
465 perror("failed to write on file headers");
466} 520}
467 521
468static int __cmd_record(int argc, const char **argv) 522static int __cmd_record(int argc, const char **argv)
469{ 523{
470 int i, counter; 524 int i, counter;
471 struct stat st; 525 struct stat st;
472 pid_t pid; 526 pid_t pid = 0;
473 int flags; 527 int flags;
474 int ret; 528 int ret;
475 529
@@ -482,10 +536,14 @@ static int __cmd_record(int argc, const char **argv)
482 signal(SIGCHLD, sig_handler); 536 signal(SIGCHLD, sig_handler);
483 signal(SIGINT, sig_handler); 537 signal(SIGINT, sig_handler);
484 538
485 if (!stat(output_name, &st) && !force && !append_file) { 539 if (!stat(output_name, &st) && st.st_size) {
486 fprintf(stderr, "Error, output file %s exists, use -A to append or -f to overwrite.\n", 540 if (!force && !append_file) {
487 output_name); 541 fprintf(stderr, "Error, output file %s exists, use -A to append or -f to overwrite.\n",
488 exit(-1); 542 output_name);
543 exit(-1);
544 }
545 } else {
546 append_file = 0;
489 } 547 }
490 548
491 flags = O_CREAT|O_RDWR; 549 flags = O_CREAT|O_RDWR;
@@ -500,21 +558,36 @@ static int __cmd_record(int argc, const char **argv)
500 exit(-1); 558 exit(-1);
501 } 559 }
502 560
503 if (!file_new) { 561 if (!file_new)
504 if (read(output, &file_header, sizeof(file_header)) == -1) { 562 header = perf_header__read(output);
505 perror("failed to read file headers"); 563 else
506 exit(-1); 564 header = perf_header__new();
507 } 565
566 atexit(atexit_header);
508 567
509 lseek(output, file_header.data_size, SEEK_CUR); 568 if (!system_wide) {
569 pid = target_pid;
570 if (pid == -1)
571 pid = getpid();
572
573 open_counters(profile_cpu, pid);
574 } else {
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 }
510 } 581 }
511 582
512 atexit(atexit_header); 583 if (file_new)
584 perf_header__write(header, output);
513 585
514 if (!system_wide) { 586 if (!system_wide) {
515 open_counters(-1, target_pid != -1 ? target_pid : getpid()); 587 pid_t tgid = pid_synthesize_comm_event(pid, 0);
516 } else for (i = 0; i < nr_cpus; i++) 588 pid_synthesize_mmap_samples(pid, tgid);
517 open_counters(i, target_pid); 589 } else
590 synthesize_all();
518 591
519 if (target_pid == -1 && argc) { 592 if (target_pid == -1 && argc) {
520 pid = fork(); 593 pid = fork();
@@ -539,10 +612,7 @@ static int __cmd_record(int argc, const char **argv)
539 } 612 }
540 } 613 }
541 614
542 if (system_wide) 615 for (;;) {
543 synthesize_samples();
544
545 while (!done) {
546 int hits = samples; 616 int hits = samples;
547 617
548 for (i = 0; i < nr_cpu; i++) { 618 for (i = 0; i < nr_cpu; i++) {
@@ -550,8 +620,11 @@ static int __cmd_record(int argc, const char **argv)
550 mmap_read(&mmap_array[i][counter]); 620 mmap_read(&mmap_array[i][counter]);
551 } 621 }
552 622
553 if (hits == samples) 623 if (hits == samples) {
624 if (done)
625 break;
554 ret = poll(event_array, nr_poll, 100); 626 ret = poll(event_array, nr_poll, 100);
627 }
555 } 628 }
556 629
557 /* 630 /*
@@ -580,10 +653,14 @@ static const struct option options[] = {
580 "record events on existing pid"), 653 "record events on existing pid"),
581 OPT_INTEGER('r', "realtime", &realtime_prio, 654 OPT_INTEGER('r', "realtime", &realtime_prio,
582 "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"),
583 OPT_BOOLEAN('a', "all-cpus", &system_wide, 658 OPT_BOOLEAN('a', "all-cpus", &system_wide,
584 "system-wide collection from all CPUs"), 659 "system-wide collection from all CPUs"),
585 OPT_BOOLEAN('A', "append", &append_file, 660 OPT_BOOLEAN('A', "append", &append_file,
586 "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"),
587 OPT_BOOLEAN('f', "force", &force, 664 OPT_BOOLEAN('f', "force", &force,
588 "overwrite existing data file"), 665 "overwrite existing data file"),
589 OPT_LONG('c', "count", &default_interval, 666 OPT_LONG('c', "count", &default_interval,
@@ -600,14 +677,21 @@ static const struct option options[] = {
600 "do call-graph (stack chain/backtrace) recording"), 677 "do call-graph (stack chain/backtrace) recording"),
601 OPT_BOOLEAN('v', "verbose", &verbose, 678 OPT_BOOLEAN('v', "verbose", &verbose,
602 "be more verbose (show counter open errors, etc)"), 679 "be more verbose (show counter open errors, etc)"),
680 OPT_BOOLEAN('s', "stat", &inherit_stat,
681 "per thread counts"),
682 OPT_BOOLEAN('d', "data", &sample_address,
683 "Sample addresses"),
684 OPT_BOOLEAN('n', "no-samples", &no_samples,
685 "don't sample"),
603 OPT_END() 686 OPT_END()
604}; 687};
605 688
606int cmd_record(int argc, const char **argv, const char *prefix) 689int cmd_record(int argc, const char **argv, const char *prefix __used)
607{ 690{
608 int counter; 691 int counter;
609 692
610 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);
611 if (!argc && target_pid == -1 && !system_wide) 695 if (!argc && target_pid == -1 && !system_wide)
612 usage_with_options(record_usage, options); 696 usage_with_options(record_usage, options);
613 697
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 5eb5566f0c95..b53a60fc12de 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -10,13 +10,16 @@
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"
19#include "util/strlist.h"
18 20
19#include "perf.h" 21#include "perf.h"
22#include "util/header.h"
20 23
21#include "util/parse-options.h" 24#include "util/parse-options.h"
22#include "util/parse-events.h" 25#include "util/parse-events.h"
@@ -28,8 +31,12 @@
28static char const *input_name = "perf.data"; 31static char const *input_name = "perf.data";
29static char *vmlinux = NULL; 32static char *vmlinux = NULL;
30 33
31static char default_sort_order[] = "comm,dso"; 34static char default_sort_order[] = "comm,dso,symbol";
32static char *sort_order = default_sort_order; 35static char *sort_order = default_sort_order;
36static char *dso_list_str, *comm_list_str, *sym_list_str,
37 *col_width_list_str;
38static struct strlist *dso_list, *comm_list, *sym_list;
39static char *field_sep;
33 40
34static int input; 41static int input;
35static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV; 42static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV;
@@ -41,7 +48,10 @@ static int dump_trace = 0;
41static int verbose; 48static int verbose;
42#define eprintf(x...) do { if (verbose) fprintf(stderr, x); } while (0) 49#define eprintf(x...) do { if (verbose) fprintf(stderr, x); } while (0)
43 50
51static int modules;
52
44static int full_paths; 53static int full_paths;
54static int show_nr_samples;
45 55
46static unsigned long page_size; 56static unsigned long page_size;
47static unsigned long mmap_window = 32; 57static unsigned long mmap_window = 32;
@@ -52,6 +62,18 @@ static regex_t parent_regex;
52 62
53static int exclude_other = 1; 63static int exclude_other = 1;
54 64
65static char callchain_default_opt[] = "fractal,0.5";
66
67static int callchain;
68
69static
70struct callchain_param callchain_param = {
71 .mode = CHAIN_GRAPH_REL,
72 .min_percent = 0.5
73};
74
75static u64 sample_type;
76
55struct ip_event { 77struct ip_event {
56 struct perf_event_header header; 78 struct perf_event_header header;
57 u64 ip; 79 u64 ip;
@@ -59,11 +81,6 @@ struct ip_event {
59 unsigned char __more_data[]; 81 unsigned char __more_data[];
60}; 82};
61 83
62struct ip_callchain {
63 u64 nr;
64 u64 ips[0];
65};
66
67struct mmap_event { 84struct mmap_event {
68 struct perf_event_header header; 85 struct perf_event_header header;
69 u32 pid, tid; 86 u32 pid, tid;
@@ -82,19 +99,22 @@ struct comm_event {
82struct fork_event { 99struct fork_event {
83 struct perf_event_header header; 100 struct perf_event_header header;
84 u32 pid, ppid; 101 u32 pid, ppid;
102 u32 tid, ptid;
85}; 103};
86 104
87struct period_event { 105struct lost_event {
88 struct perf_event_header header; 106 struct perf_event_header header;
89 u64 time;
90 u64 id; 107 u64 id;
91 u64 sample_period; 108 u64 lost;
92}; 109};
93 110
94struct lost_event { 111struct read_event {
95 struct perf_event_header header; 112 struct perf_event_header header;
113 u32 pid,tid;
114 u64 value;
115 u64 time_enabled;
116 u64 time_running;
96 u64 id; 117 u64 id;
97 u64 lost;
98}; 118};
99 119
100typedef union event_union { 120typedef union event_union {
@@ -103,13 +123,41 @@ typedef union event_union {
103 struct mmap_event mmap; 123 struct mmap_event mmap;
104 struct comm_event comm; 124 struct comm_event comm;
105 struct fork_event fork; 125 struct fork_event fork;
106 struct period_event period;
107 struct lost_event lost; 126 struct lost_event lost;
127 struct read_event read;
108} event_t; 128} event_t;
109 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
110static LIST_HEAD(dsos); 157static LIST_HEAD(dsos);
111static struct dso *kernel_dso; 158static struct dso *kernel_dso;
112static struct dso *vdso; 159static struct dso *vdso;
160static struct dso *hypervisor_dso;
113 161
114static void dsos__add(struct dso *dso) 162static void dsos__add(struct dso *dso)
115{ 163{
@@ -165,7 +213,7 @@ static void dsos__fprintf(FILE *fp)
165 213
166static struct symbol *vdso__find_symbol(struct dso *dso, u64 ip) 214static struct symbol *vdso__find_symbol(struct dso *dso, u64 ip)
167{ 215{
168 return dso__find_symbol(kernel_dso, ip); 216 return dso__find_symbol(dso, ip);
169} 217}
170 218
171static int load_kernel(void) 219static int load_kernel(void)
@@ -176,8 +224,8 @@ static int load_kernel(void)
176 if (!kernel_dso) 224 if (!kernel_dso)
177 return -1; 225 return -1;
178 226
179 err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose); 227 err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose, modules);
180 if (err) { 228 if (err <= 0) {
181 dso__delete(kernel_dso); 229 dso__delete(kernel_dso);
182 kernel_dso = NULL; 230 kernel_dso = NULL;
183 } else 231 } else
@@ -191,6 +239,11 @@ static int load_kernel(void)
191 239
192 dsos__add(vdso); 240 dsos__add(vdso);
193 241
242 hypervisor_dso = dso__new("[hypervisor]", 0);
243 if (!hypervisor_dso)
244 return -1;
245 dsos__add(hypervisor_dso);
246
194 return err; 247 return err;
195} 248}
196 249
@@ -202,7 +255,7 @@ static int strcommon(const char *pathname)
202{ 255{
203 int n = 0; 256 int n = 0;
204 257
205 while (pathname[n] == cwd[n] && n < cwdlen) 258 while (n < cwdlen && pathname[n] == cwd[n])
206 ++n; 259 ++n;
207 260
208 return n; 261 return n;
@@ -222,14 +275,14 @@ static u64 map__map_ip(struct map *map, u64 ip)
222 return ip - map->start + map->pgoff; 275 return ip - map->start + map->pgoff;
223} 276}
224 277
225static u64 vdso__map_ip(struct map *map, u64 ip) 278static u64 vdso__map_ip(struct map *map __used, u64 ip)
226{ 279{
227 return ip; 280 return ip;
228} 281}
229 282
230static inline int is_anon_memory(const char *filename) 283static inline int is_anon_memory(const char *filename)
231{ 284{
232 return strcmp(filename, "//anon") == 0; 285 return strcmp(filename, "//anon") == 0;
233} 286}
234 287
235static struct map *map__new(struct mmap_event *event) 288static struct map *map__new(struct mmap_event *event)
@@ -332,12 +385,28 @@ static struct thread *thread__new(pid_t pid)
332 return self; 385 return self;
333} 386}
334 387
388static unsigned int dsos__col_width,
389 comms__col_width,
390 threads__col_width;
391
335static int thread__set_comm(struct thread *self, const char *comm) 392static int thread__set_comm(struct thread *self, const char *comm)
336{ 393{
337 if (self->comm) 394 if (self->comm)
338 free(self->comm); 395 free(self->comm);
339 self->comm = strdup(comm); 396 self->comm = strdup(comm);
340 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;
341} 410}
342 411
343static size_t thread__fprintf(struct thread *self, FILE *fp) 412static size_t thread__fprintf(struct thread *self, FILE *fp)
@@ -400,9 +469,27 @@ static void thread__insert_map(struct thread *self, struct map *map)
400 469
401 list_for_each_entry_safe(pos, tmp, &self->maps, node) { 470 list_for_each_entry_safe(pos, tmp, &self->maps, node) {
402 if (map__overlap(pos, map)) { 471 if (map__overlap(pos, map)) {
403 list_del_init(&pos->node); 472 if (verbose >= 2) {
404 /* XXX leaks dsos */ 473 printf("overlapping maps:\n");
405 free(pos); 474 map__fprintf(map, stdout);
475 map__fprintf(pos, stdout);
476 }
477
478 if (map->start <= pos->start && map->end > pos->start)
479 pos->start = map->end;
480
481 if (map->end >= pos->end && map->start < pos->end)
482 pos->end = map->start;
483
484 if (verbose >= 2) {
485 printf("after collision:\n");
486 map__fprintf(pos, stdout);
487 }
488
489 if (pos->start >= pos->end) {
490 list_del_init(&pos->node);
491 free(pos);
492 }
406 } 493 }
407 } 494 }
408 495
@@ -464,17 +551,19 @@ static size_t threads__fprintf(FILE *fp)
464static struct rb_root hist; 551static struct rb_root hist;
465 552
466struct hist_entry { 553struct hist_entry {
467 struct rb_node rb_node; 554 struct rb_node rb_node;
468 555
469 struct thread *thread; 556 struct thread *thread;
470 struct map *map; 557 struct map *map;
471 struct dso *dso; 558 struct dso *dso;
472 struct symbol *sym; 559 struct symbol *sym;
473 struct symbol *parent; 560 struct symbol *parent;
474 u64 ip; 561 u64 ip;
475 char level; 562 char level;
476 563 struct callchain_node callchain;
477 u64 count; 564 struct rb_root sorted_chain;
565
566 u64 count;
478}; 567};
479 568
480/* 569/*
@@ -488,7 +577,9 @@ struct sort_entry {
488 577
489 int64_t (*cmp)(struct hist_entry *, struct hist_entry *); 578 int64_t (*cmp)(struct hist_entry *, struct hist_entry *);
490 int64_t (*collapse)(struct hist_entry *, struct hist_entry *); 579 int64_t (*collapse)(struct hist_entry *, struct hist_entry *);
491 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;
492}; 583};
493 584
494static int64_t cmp_null(void *l, void *r) 585static int64_t cmp_null(void *l, void *r)
@@ -510,15 +601,17 @@ sort__thread_cmp(struct hist_entry *left, struct hist_entry *right)
510} 601}
511 602
512static size_t 603static size_t
513sort__thread_print(FILE *fp, struct hist_entry *self) 604sort__thread_print(FILE *fp, struct hist_entry *self, unsigned int width)
514{ 605{
515 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);
516} 608}
517 609
518static struct sort_entry sort_thread = { 610static struct sort_entry sort_thread = {
519 .header = " Command: Pid", 611 .header = "Command: Pid",
520 .cmp = sort__thread_cmp, 612 .cmp = sort__thread_cmp,
521 .print = sort__thread_print, 613 .print = sort__thread_print,
614 .width = &threads__col_width,
522}; 615};
523 616
524/* --sort comm */ 617/* --sort comm */
@@ -542,16 +635,17 @@ sort__comm_collapse(struct hist_entry *left, struct hist_entry *right)
542} 635}
543 636
544static size_t 637static size_t
545sort__comm_print(FILE *fp, struct hist_entry *self) 638sort__comm_print(FILE *fp, struct hist_entry *self, unsigned int width)
546{ 639{
547 return fprintf(fp, "%16s", self->thread->comm); 640 return repsep_fprintf(fp, "%*s", width, self->thread->comm);
548} 641}
549 642
550static struct sort_entry sort_comm = { 643static struct sort_entry sort_comm = {
551 .header = " Command", 644 .header = "Command",
552 .cmp = sort__comm_cmp, 645 .cmp = sort__comm_cmp,
553 .collapse = sort__comm_collapse, 646 .collapse = sort__comm_collapse,
554 .print = sort__comm_print, 647 .print = sort__comm_print,
648 .width = &comms__col_width,
555}; 649};
556 650
557/* --sort dso */ 651/* --sort dso */
@@ -569,18 +663,19 @@ sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
569} 663}
570 664
571static size_t 665static size_t
572sort__dso_print(FILE *fp, struct hist_entry *self) 666sort__dso_print(FILE *fp, struct hist_entry *self, unsigned int width)
573{ 667{
574 if (self->dso) 668 if (self->dso)
575 return fprintf(fp, "%-25s", self->dso->name); 669 return repsep_fprintf(fp, "%-*s", width, self->dso->name);
576 670
577 return fprintf(fp, "%016llx ", (u64)self->ip); 671 return repsep_fprintf(fp, "%*llx", width, (u64)self->ip);
578} 672}
579 673
580static struct sort_entry sort_dso = { 674static struct sort_entry sort_dso = {
581 .header = "Shared Object ", 675 .header = "Shared Object",
582 .cmp = sort__dso_cmp, 676 .cmp = sort__dso_cmp,
583 .print = sort__dso_print, 677 .print = sort__dso_print,
678 .width = &dsos__col_width,
584}; 679};
585 680
586/* --sort symbol */ 681/* --sort symbol */
@@ -600,18 +695,23 @@ sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
600} 695}
601 696
602static size_t 697static size_t
603sort__sym_print(FILE *fp, struct hist_entry *self) 698sort__sym_print(FILE *fp, struct hist_entry *self, unsigned int width __used)
604{ 699{
605 size_t ret = 0; 700 size_t ret = 0;
606 701
607 if (verbose) 702 if (verbose)
608 ret += fprintf(fp, "%#018llx ", (u64)self->ip); 703 ret += repsep_fprintf(fp, "%#018llx %c ", (u64)self->ip,
704 dso__symtab_origin(self->dso));
609 705
706 ret += repsep_fprintf(fp, "[%c] ", self->level);
610 if (self->sym) { 707 if (self->sym) {
611 ret += fprintf(fp, "[%c] %s", 708 ret += repsep_fprintf(fp, "%s", self->sym->name);
612 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);
613 } else { 713 } else {
614 ret += fprintf(fp, "%#016llx", (u64)self->ip); 714 ret += repsep_fprintf(fp, "%#016llx", (u64)self->ip);
615 } 715 }
616 716
617 return ret; 717 return ret;
@@ -638,19 +738,19 @@ sort__parent_cmp(struct hist_entry *left, struct hist_entry *right)
638} 738}
639 739
640static size_t 740static size_t
641sort__parent_print(FILE *fp, struct hist_entry *self) 741sort__parent_print(FILE *fp, struct hist_entry *self, unsigned int width)
642{ 742{
643 size_t ret = 0; 743 return repsep_fprintf(fp, "%-*s", width,
644 744 self->parent ? self->parent->name : "[other]");
645 ret += fprintf(fp, "%-20s", self->parent ? self->parent->name : "[other]");
646
647 return ret;
648} 745}
649 746
747static unsigned int parent_symbol__col_width;
748
650static struct sort_entry sort_parent = { 749static struct sort_entry sort_parent = {
651 .header = "Parent symbol ", 750 .header = "Parent symbol",
652 .cmp = sort__parent_cmp, 751 .cmp = sort__parent_cmp,
653 .print = sort__parent_print, 752 .print = sort__parent_print,
753 .width = &parent_symbol__col_width,
654}; 754};
655 755
656static int sort__need_collapse = 0; 756static int sort__need_collapse = 0;
@@ -674,7 +774,7 @@ static LIST_HEAD(hist_entry__sort_list);
674 774
675static int sort_dimension__add(char *tok) 775static int sort_dimension__add(char *tok)
676{ 776{
677 int i; 777 unsigned int i;
678 778
679 for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) { 779 for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) {
680 struct sort_dimension *sd = &sort_dimensions[i]; 780 struct sort_dimension *sd = &sort_dimensions[i];
@@ -744,6 +844,204 @@ hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
744 return cmp; 844 return cmp;
745} 845}
746 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}
864static size_t
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)
987{
988 struct callchain_list *chain;
989 size_t ret = 0;
990
991 if (!self)
992 return 0;
993
994 ret += callchain__fprintf_flat(fp, self->parent, total_samples);
995
996
997 list_for_each_entry(chain, &self->val, list) {
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 }
1006
1007 return ret;
1008}
1009
1010static size_t
1011hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self,
1012 u64 total_samples)
1013{
1014 struct rb_node *rb_node;
1015 struct callchain_node *chain;
1016 size_t ret = 0;
1017
1018 rb_node = rb_first(&self->sorted_chain);
1019 while (rb_node) {
1020 double percent;
1021
1022 chain = rb_entry(rb_node, struct callchain_node, rb_node);
1023 percent = chain->hit * 100.0 / total_samples;
1024 switch (callchain_param.mode) {
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 }
1037 ret += fprintf(fp, "\n");
1038 rb_node = rb_next(rb_node);
1039 }
1040
1041 return ret;
1042}
1043
1044
747static size_t 1045static size_t
748hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples) 1046hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples)
749{ 1047{
@@ -753,37 +1051,33 @@ hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples)
753 if (exclude_other && !self->parent) 1051 if (exclude_other && !self->parent)
754 return 0; 1052 return 0;
755 1053
756 if (total_samples) { 1054 if (total_samples)
757 double percent = self->count * 100.0 / total_samples; 1055 ret = percent_color_fprintf(fp,
758 char *color = PERF_COLOR_NORMAL; 1056 field_sep ? "%.2f" : " %6.2f%%",
759 1057 (self->count * 100.0) / total_samples);
760 /* 1058 else
761 * We color high-overhead entries in red, mid-overhead 1059 ret = fprintf(fp, field_sep ? "%lld" : "%12lld ", self->count);
762 * entries in green - and keep the low overhead places
763 * normal:
764 */
765 if (percent >= 5.0) {
766 color = PERF_COLOR_RED;
767 } else {
768 if (percent >= 0.5)
769 color = PERF_COLOR_GREEN;
770 }
771 1060
772 ret = color_fprintf(fp, color, " %6.2f%%", 1061 if (show_nr_samples) {
773 (self->count * 100.0) / total_samples); 1062 if (field_sep)
774 } else 1063 fprintf(fp, "%c%lld", *field_sep, self->count);
775 ret = fprintf(fp, "%12Ld ", self->count); 1064 else
1065 fprintf(fp, "%11lld", self->count);
1066 }
776 1067
777 list_for_each_entry(se, &hist_entry__sort_list, list) { 1068 list_for_each_entry(se, &hist_entry__sort_list, list) {
778 if (exclude_other && (se == &sort_parent)) 1069 if (se->elide)
779 continue; 1070 continue;
780 1071
781 fprintf(fp, " "); 1072 fprintf(fp, "%s", field_sep ?: " ");
782 ret += se->print(fp, self); 1073 ret += se->print(fp, self, se->width ? *se->width : 0);
783 } 1074 }
784 1075
785 ret += fprintf(fp, "\n"); 1076 ret += fprintf(fp, "\n");
786 1077
1078 if (callchain)
1079 hist_entry_callchain__fprintf(fp, self, total_samples);
1080
787 return ret; 1081 return ret;
788} 1082}
789 1083
@@ -791,13 +1085,25 @@ hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples)
791 * 1085 *
792 */ 1086 */
793 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
794static struct symbol * 1100static struct symbol *
795resolve_symbol(struct thread *thread, struct map **mapp, 1101resolve_symbol(struct thread *thread, struct map **mapp,
796 struct dso **dsop, u64 *ipp) 1102 struct dso **dsop, u64 *ipp)
797{ 1103{
798 struct dso *dso = dsop ? *dsop : NULL; 1104 struct dso *dso = dsop ? *dsop : NULL;
799 struct map *map = mapp ? *mapp : NULL; 1105 struct map *map = mapp ? *mapp : NULL;
800 uint64_t ip = *ipp; 1106 u64 ip = *ipp;
801 1107
802 if (!thread) 1108 if (!thread)
803 return NULL; 1109 return NULL;
@@ -810,11 +1116,18 @@ resolve_symbol(struct thread *thread, struct map **mapp,
810 1116
811 map = thread__find_map(thread, ip); 1117 map = thread__find_map(thread, ip);
812 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
813 if (mapp) 1127 if (mapp)
814 *mapp = map; 1128 *mapp = map;
815got_map: 1129got_map:
816 ip = map->map_ip(map, ip); 1130 ip = map->map_ip(map, ip);
817 *ipp = ip;
818 1131
819 dso = map->dso; 1132 dso = map->dso;
820 } else { 1133 } else {
@@ -828,6 +1141,8 @@ got_map:
828 dso = kernel_dso; 1141 dso = kernel_dso;
829 } 1142 }
830 dprintf(" ...... dso: %s\n", dso ? dso->name : "<not found>"); 1143 dprintf(" ...... dso: %s\n", dso ? dso->name : "<not found>");
1144 dprintf(" ...... map: %Lx -> %Lx\n", *ipp, ip);
1145 *ipp = ip;
831 1146
832 if (dsop) 1147 if (dsop)
833 *dsop = dso; 1148 *dsop = dso;
@@ -846,6 +1161,58 @@ static int call__match(struct symbol *sym)
846 return 0; 1161 return 0;
847} 1162}
848 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
849/* 1216/*
850 * collect histogram counts 1217 * collect histogram counts
851 */ 1218 */
@@ -858,6 +1225,7 @@ hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
858 struct rb_node **p = &hist.rb_node; 1225 struct rb_node **p = &hist.rb_node;
859 struct rb_node *parent = NULL; 1226 struct rb_node *parent = NULL;
860 struct hist_entry *he; 1227 struct hist_entry *he;
1228 struct symbol **syms = NULL;
861 struct hist_entry entry = { 1229 struct hist_entry entry = {
862 .thread = thread, 1230 .thread = thread,
863 .map = map, 1231 .map = map,
@@ -867,39 +1235,12 @@ hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
867 .level = level, 1235 .level = level,
868 .count = count, 1236 .count = count,
869 .parent = NULL, 1237 .parent = NULL,
1238 .sorted_chain = RB_ROOT
870 }; 1239 };
871 int cmp; 1240 int cmp;
872 1241
873 if (sort__has_parent && chain) { 1242 if ((sort__has_parent || callchain) && chain)
874 u64 context = PERF_CONTEXT_MAX; 1243 syms = resolve_callchain(thread, map, chain, &entry);
875 int i;
876
877 for (i = 0; i < chain->nr; i++) {
878 u64 ip = chain->ips[i];
879 struct dso *dso = NULL;
880 struct symbol *sym;
881
882 if (ip >= PERF_CONTEXT_MAX) {
883 context = ip;
884 continue;
885 }
886
887 switch (context) {
888 case PERF_CONTEXT_KERNEL:
889 dso = kernel_dso;
890 break;
891 default:
892 break;
893 }
894
895 sym = resolve_symbol(thread, NULL, &dso, &ip);
896
897 if (sym && call__match(sym)) {
898 entry.parent = sym;
899 break;
900 }
901 }
902 }
903 1244
904 while (*p != NULL) { 1245 while (*p != NULL) {
905 parent = *p; 1246 parent = *p;
@@ -909,6 +1250,10 @@ hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
909 1250
910 if (!cmp) { 1251 if (!cmp) {
911 he->count += count; 1252 he->count += count;
1253 if (callchain) {
1254 append_chain(&he->callchain, chain, syms);
1255 free(syms);
1256 }
912 return 0; 1257 return 0;
913 } 1258 }
914 1259
@@ -922,6 +1267,11 @@ hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
922 if (!he) 1267 if (!he)
923 return -ENOMEM; 1268 return -ENOMEM;
924 *he = entry; 1269 *he = entry;
1270 if (callchain) {
1271 callchain_init(&he->callchain);
1272 append_chain(&he->callchain, chain, syms);
1273 free(syms);
1274 }
925 rb_link_node(&he->rb_node, parent, p); 1275 rb_link_node(&he->rb_node, parent, p);
926 rb_insert_color(&he->rb_node, &hist); 1276 rb_insert_color(&he->rb_node, &hist);
927 1277
@@ -992,12 +1342,16 @@ static void collapse__resort(void)
992 1342
993static struct rb_root output_hists; 1343static struct rb_root output_hists;
994 1344
995static void output__insert_entry(struct hist_entry *he) 1345static void output__insert_entry(struct hist_entry *he, u64 min_callchain_hits)
996{ 1346{
997 struct rb_node **p = &output_hists.rb_node; 1347 struct rb_node **p = &output_hists.rb_node;
998 struct rb_node *parent = NULL; 1348 struct rb_node *parent = NULL;
999 struct hist_entry *iter; 1349 struct hist_entry *iter;
1000 1350
1351 if (callchain)
1352 callchain_param.sort(&he->sorted_chain, &he->callchain,
1353 min_callchain_hits, &callchain_param);
1354
1001 while (*p != NULL) { 1355 while (*p != NULL) {
1002 parent = *p; 1356 parent = *p;
1003 iter = rb_entry(parent, struct hist_entry, rb_node); 1357 iter = rb_entry(parent, struct hist_entry, rb_node);
@@ -1012,11 +1366,14 @@ static void output__insert_entry(struct hist_entry *he)
1012 rb_insert_color(&he->rb_node, &output_hists); 1366 rb_insert_color(&he->rb_node, &output_hists);
1013} 1367}
1014 1368
1015static void output__resort(void) 1369static void output__resort(u64 total_samples)
1016{ 1370{
1017 struct rb_node *next; 1371 struct rb_node *next;
1018 struct hist_entry *n; 1372 struct hist_entry *n;
1019 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);
1020 1377
1021 if (sort__need_collapse) 1378 if (sort__need_collapse)
1022 tree = &collapse_hists; 1379 tree = &collapse_hists;
@@ -1028,7 +1385,7 @@ static void output__resort(void)
1028 next = rb_next(&n->rb_node); 1385 next = rb_next(&n->rb_node);
1029 1386
1030 rb_erase(&n->rb_node, tree); 1387 rb_erase(&n->rb_node, tree);
1031 output__insert_entry(n); 1388 output__insert_entry(n, min_callchain_hits);
1032 } 1389 }
1033} 1390}
1034 1391
@@ -1038,35 +1395,69 @@ static size_t output__fprintf(FILE *fp, u64 total_samples)
1038 struct sort_entry *se; 1395 struct sort_entry *se;
1039 struct rb_node *nd; 1396 struct rb_node *nd;
1040 size_t ret = 0; 1397 size_t ret = 0;
1398 unsigned int width;
1399 char *col_width = col_width_list_str;
1041 1400
1042 fprintf(fp, "\n"); 1401 init_rem_hits();
1043 fprintf(fp, "#\n"); 1402
1044 fprintf(fp, "# (%Ld samples)\n", (u64)total_samples); 1403 fprintf(fp, "# Samples: %Ld\n", (u64)total_samples);
1045 fprintf(fp, "#\n"); 1404 fprintf(fp, "#\n");
1046 1405
1047 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 }
1048 list_for_each_entry(se, &hist_entry__sort_list, list) { 1413 list_for_each_entry(se, &hist_entry__sort_list, list) {
1049 if (exclude_other && (se == &sort_parent)) 1414 if (se->elide)
1415 continue;
1416 if (field_sep) {
1417 fprintf(fp, "%c%s", *field_sep, se->header);
1050 continue; 1418 continue;
1051 fprintf(fp, " %s", se->header); 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);
1052 } 1433 }
1053 fprintf(fp, "\n"); 1434 fprintf(fp, "\n");
1054 1435
1436 if (field_sep)
1437 goto print_entries;
1438
1055 fprintf(fp, "# ........"); 1439 fprintf(fp, "# ........");
1440 if (show_nr_samples)
1441 fprintf(fp, " ..........");
1056 list_for_each_entry(se, &hist_entry__sort_list, list) { 1442 list_for_each_entry(se, &hist_entry__sort_list, list) {
1057 int i; 1443 unsigned int i;
1058 1444
1059 if (exclude_other && (se == &sort_parent)) 1445 if (se->elide)
1060 continue; 1446 continue;
1061 1447
1062 fprintf(fp, " "); 1448 fprintf(fp, " ");
1063 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++)
1064 fprintf(fp, "."); 1454 fprintf(fp, ".");
1065 } 1455 }
1066 fprintf(fp, "\n"); 1456 fprintf(fp, "\n");
1067 1457
1068 fprintf(fp, "#\n"); 1458 fprintf(fp, "#\n");
1069 1459
1460print_entries:
1070 for (nd = rb_first(&output_hists); nd; nd = rb_next(nd)) { 1461 for (nd = rb_first(&output_hists); nd; nd = rb_next(nd)) {
1071 pos = rb_entry(nd, struct hist_entry, rb_node); 1462 pos = rb_entry(nd, struct hist_entry, rb_node);
1072 ret += hist_entry__fprintf(fp, pos, total_samples); 1463 ret += hist_entry__fprintf(fp, pos, total_samples);
@@ -1075,11 +1466,13 @@ static size_t output__fprintf(FILE *fp, u64 total_samples)
1075 if (sort_order == default_sort_order && 1466 if (sort_order == default_sort_order &&
1076 parent_pattern == default_parent_pattern) { 1467 parent_pattern == default_parent_pattern) {
1077 fprintf(fp, "#\n"); 1468 fprintf(fp, "#\n");
1078 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");
1079 fprintf(fp, "#\n"); 1470 fprintf(fp, "#\n");
1080 } 1471 }
1081 fprintf(fp, "\n"); 1472 fprintf(fp, "\n");
1082 1473
1474 free(rem_sq_bracket);
1475
1083 return ret; 1476 return ret;
1084} 1477}
1085 1478
@@ -1115,7 +1508,7 @@ static int validate_chain(struct ip_callchain *chain, event_t *event)
1115} 1508}
1116 1509
1117static int 1510static int
1118process_overflow_event(event_t *event, unsigned long offset, unsigned long head) 1511process_sample_event(event_t *event, unsigned long offset, unsigned long head)
1119{ 1512{
1120 char level; 1513 char level;
1121 int show = 0; 1514 int show = 0;
@@ -1126,22 +1519,23 @@ process_overflow_event(event_t *event, unsigned long offset, unsigned long head)
1126 struct map *map = NULL; 1519 struct map *map = NULL;
1127 void *more_data = event->ip.__more_data; 1520 void *more_data = event->ip.__more_data;
1128 struct ip_callchain *chain = NULL; 1521 struct ip_callchain *chain = NULL;
1522 int cpumode;
1129 1523
1130 if (event->header.type & PERF_SAMPLE_PERIOD) { 1524 if (sample_type & PERF_SAMPLE_PERIOD) {
1131 period = *(u64 *)more_data; 1525 period = *(u64 *)more_data;
1132 more_data += sizeof(u64); 1526 more_data += sizeof(u64);
1133 } 1527 }
1134 1528
1135 dprintf("%p [%p]: PERF_EVENT (IP, %d): %d: %p period: %Ld\n", 1529 dprintf("%p [%p]: PERF_EVENT_SAMPLE (IP, %d): %d/%d: %p period: %Ld\n",
1136 (void *)(offset + head), 1530 (void *)(offset + head),
1137 (void *)(long)(event->header.size), 1531 (void *)(long)(event->header.size),
1138 event->header.misc, 1532 event->header.misc,
1139 event->ip.pid, 1533 event->ip.pid, event->ip.tid,
1140 (void *)(long)ip, 1534 (void *)(long)ip,
1141 (long long)period); 1535 (long long)period);
1142 1536
1143 if (event->header.type & PERF_SAMPLE_CALLCHAIN) { 1537 if (sample_type & PERF_SAMPLE_CALLCHAIN) {
1144 int i; 1538 unsigned int i;
1145 1539
1146 chain = (void *)more_data; 1540 chain = (void *)more_data;
1147 1541
@@ -1166,7 +1560,12 @@ process_overflow_event(event_t *event, unsigned long offset, unsigned long head)
1166 return -1; 1560 return -1;
1167 } 1561 }
1168 1562
1169 if (event->header.misc & PERF_EVENT_MISC_KERNEL) { 1563 if (comm_list && !strlist__has_entry(comm_list, thread->comm))
1564 return 0;
1565
1566 cpumode = event->header.misc & PERF_EVENT_MISC_CPUMODE_MASK;
1567
1568 if (cpumode == PERF_EVENT_MISC_KERNEL) {
1170 show = SHOW_KERNEL; 1569 show = SHOW_KERNEL;
1171 level = 'k'; 1570 level = 'k';
1172 1571
@@ -1174,7 +1573,7 @@ process_overflow_event(event_t *event, unsigned long offset, unsigned long head)
1174 1573
1175 dprintf(" ...... dso: %s\n", dso->name); 1574 dprintf(" ...... dso: %s\n", dso->name);
1176 1575
1177 } else if (event->header.misc & PERF_EVENT_MISC_USER) { 1576 } else if (cpumode == PERF_EVENT_MISC_USER) {
1178 1577
1179 show = SHOW_USER; 1578 show = SHOW_USER;
1180 level = '.'; 1579 level = '.';
@@ -1182,12 +1581,22 @@ process_overflow_event(event_t *event, unsigned long offset, unsigned long head)
1182 } else { 1581 } else {
1183 show = SHOW_HV; 1582 show = SHOW_HV;
1184 level = 'H'; 1583 level = 'H';
1584
1585 dso = hypervisor_dso;
1586
1185 dprintf(" ...... dso: [hypervisor]\n"); 1587 dprintf(" ...... dso: [hypervisor]\n");
1186 } 1588 }
1187 1589
1188 if (show & show_mask) { 1590 if (show & show_mask) {
1189 struct symbol *sym = resolve_symbol(thread, &map, &dso, &ip); 1591 struct symbol *sym = resolve_symbol(thread, &map, &dso, &ip);
1190 1592
1593 if (dso_list && (!dso || !dso->name ||
1594 !strlist__has_entry(dso_list, dso->name)))
1595 return 0;
1596
1597 if (sym_list && (!sym || !strlist__has_entry(sym_list, sym->name)))
1598 return 0;
1599
1191 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)) {
1192 eprintf("problem incrementing symbol count, skipping event\n"); 1601 eprintf("problem incrementing symbol count, skipping event\n");
1193 return -1; 1602 return -1;
@@ -1204,10 +1613,11 @@ process_mmap_event(event_t *event, unsigned long offset, unsigned long head)
1204 struct thread *thread = threads__findnew(event->mmap.pid); 1613 struct thread *thread = threads__findnew(event->mmap.pid);
1205 struct map *map = map__new(&event->mmap); 1614 struct map *map = map__new(&event->mmap);
1206 1615
1207 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",
1208 (void *)(offset + head), 1617 (void *)(offset + head),
1209 (void *)(long)(event->header.size), 1618 (void *)(long)(event->header.size),
1210 event->mmap.pid, 1619 event->mmap.pid,
1620 event->mmap.tid,
1211 (void *)(long)event->mmap.start, 1621 (void *)(long)event->mmap.start,
1212 (void *)(long)event->mmap.len, 1622 (void *)(long)event->mmap.len,
1213 (void *)(long)event->mmap.pgoff, 1623 (void *)(long)event->mmap.pgoff,
@@ -1245,15 +1655,27 @@ process_comm_event(event_t *event, unsigned long offset, unsigned long head)
1245} 1655}
1246 1656
1247static int 1657static int
1248process_fork_event(event_t *event, unsigned long offset, unsigned long head) 1658process_task_event(event_t *event, unsigned long offset, unsigned long head)
1249{ 1659{
1250 struct thread *thread = threads__findnew(event->fork.pid); 1660 struct thread *thread = threads__findnew(event->fork.pid);
1251 struct thread *parent = threads__findnew(event->fork.ppid); 1661 struct thread *parent = threads__findnew(event->fork.ppid);
1252 1662
1253 dprintf("%p [%p]: PERF_EVENT_FORK: %d:%d\n", 1663 dprintf("%p [%p]: PERF_EVENT_%s: (%d:%d):(%d:%d)\n",
1254 (void *)(offset + head), 1664 (void *)(offset + head),
1255 (void *)(long)(event->header.size), 1665 (void *)(long)(event->header.size),
1256 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;
1257 1679
1258 if (!thread || !parent || thread__fork(thread, parent)) { 1680 if (!thread || !parent || thread__fork(thread, parent)) {
1259 dprintf("problem processing PERF_EVENT_FORK, skipping event.\n"); 1681 dprintf("problem processing PERF_EVENT_FORK, skipping event.\n");
@@ -1265,19 +1687,6 @@ process_fork_event(event_t *event, unsigned long offset, unsigned long head)
1265} 1687}
1266 1688
1267static int 1689static int
1268process_period_event(event_t *event, unsigned long offset, unsigned long head)
1269{
1270 dprintf("%p [%p]: PERF_EVENT_PERIOD: time:%Ld, id:%Ld: period:%Ld\n",
1271 (void *)(offset + head),
1272 (void *)(long)(event->header.size),
1273 event->period.time,
1274 event->period.id,
1275 event->period.sample_period);
1276
1277 return 0;
1278}
1279
1280static int
1281process_lost_event(event_t *event, unsigned long offset, unsigned long head) 1690process_lost_event(event_t *event, unsigned long offset, unsigned long head)
1282{ 1691{
1283 dprintf("%p [%p]: PERF_EVENT_LOST: id:%Ld: lost:%Ld\n", 1692 dprintf("%p [%p]: PERF_EVENT_LOST: id:%Ld: lost:%Ld\n",
@@ -1327,15 +1736,51 @@ static void trace_event(event_t *event)
1327 dprintf(".\n"); 1736 dprintf(".\n");
1328} 1737}
1329 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
1758static int
1759process_read_event(event_t *event, unsigned long offset, unsigned long head)
1760{
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",
1764 (void *)(offset + head),
1765 (void *)(long)(event->header.size),
1766 event->read.pid,
1767 event->read.tid,
1768 attr ? __event_name(attr->type, attr->config)
1769 : "FAIL",
1770 event->read.value);
1771
1772 return 0;
1773}
1774
1330static int 1775static int
1331process_event(event_t *event, unsigned long offset, unsigned long head) 1776process_event(event_t *event, unsigned long offset, unsigned long head)
1332{ 1777{
1333 trace_event(event); 1778 trace_event(event);
1334 1779
1335 if (event->header.misc & PERF_EVENT_MISC_OVERFLOW)
1336 return process_overflow_event(event, offset, head);
1337
1338 switch (event->header.type) { 1780 switch (event->header.type) {
1781 case PERF_EVENT_SAMPLE:
1782 return process_sample_event(event, offset, head);
1783
1339 case PERF_EVENT_MMAP: 1784 case PERF_EVENT_MMAP:
1340 return process_mmap_event(event, offset, head); 1785 return process_mmap_event(event, offset, head);
1341 1786
@@ -1343,14 +1788,15 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
1343 return process_comm_event(event, offset, head); 1788 return process_comm_event(event, offset, head);
1344 1789
1345 case PERF_EVENT_FORK: 1790 case PERF_EVENT_FORK:
1346 return process_fork_event(event, offset, head); 1791 case PERF_EVENT_EXIT:
1347 1792 return process_task_event(event, offset, head);
1348 case PERF_EVENT_PERIOD:
1349 return process_period_event(event, offset, head);
1350 1793
1351 case PERF_EVENT_LOST: 1794 case PERF_EVENT_LOST:
1352 return process_lost_event(event, offset, head); 1795 return process_lost_event(event, offset, head);
1353 1796
1797 case PERF_EVENT_READ:
1798 return process_read_event(event, offset, head);
1799
1354 /* 1800 /*
1355 * We dont process them right now but they are fine: 1801 * We dont process them right now but they are fine:
1356 */ 1802 */
@@ -1366,13 +1812,28 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
1366 return 0; 1812 return 0;
1367} 1813}
1368 1814
1369static struct perf_file_header file_header; 1815static u64 perf_header__sample_type(void)
1816{
1817 u64 sample_type = 0;
1818 int i;
1819
1820 for (i = 0; i < header->attrs; i++) {
1821 struct perf_header_attr *attr = header->attr[i];
1822
1823 if (!sample_type)
1824 sample_type = attr->attr.sample_type;
1825 else if (sample_type != attr->attr.sample_type)
1826 die("non matching sample_type");
1827 }
1828
1829 return sample_type;
1830}
1370 1831
1371static int __cmd_report(void) 1832static int __cmd_report(void)
1372{ 1833{
1373 int ret, rc = EXIT_FAILURE; 1834 int ret, rc = EXIT_FAILURE;
1374 unsigned long offset = 0; 1835 unsigned long offset = 0;
1375 unsigned long head = sizeof(file_header); 1836 unsigned long head, shift;
1376 struct stat stat; 1837 struct stat stat;
1377 event_t *event; 1838 event_t *event;
1378 uint32_t size; 1839 uint32_t size;
@@ -1400,15 +1861,31 @@ static int __cmd_report(void)
1400 exit(0); 1861 exit(0);
1401 } 1862 }
1402 1863
1403 if (read(input, &file_header, sizeof(file_header)) == -1) { 1864 header = perf_header__read(input);
1404 perror("failed to read file headers"); 1865 head = header->data_offset;
1405 exit(-1);
1406 }
1407 1866
1408 if (sort__has_parent && 1867 sample_type = perf_header__sample_type();
1409 !(file_header.sample_type & PERF_SAMPLE_CALLCHAIN)) { 1868
1410 fprintf(stderr, "selected --sort parent, but no callchain data\n"); 1869 if (!(sample_type & PERF_SAMPLE_CALLCHAIN)) {
1411 exit(-1); 1870 if (sort__has_parent) {
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 }
1412 } 1889 }
1413 1890
1414 if (load_kernel() < 0) { 1891 if (load_kernel() < 0) {
@@ -1426,6 +1903,11 @@ static int __cmd_report(void)
1426 cwd = NULL; 1903 cwd = NULL;
1427 cwdlen = 0; 1904 cwdlen = 0;
1428 } 1905 }
1906
1907 shift = page_size * (head / page_size);
1908 offset += shift;
1909 head -= shift;
1910
1429remap: 1911remap:
1430 buf = (char *)mmap(NULL, page_size * mmap_window, PROT_READ, 1912 buf = (char *)mmap(NULL, page_size * mmap_window, PROT_READ,
1431 MAP_SHARED, input, offset); 1913 MAP_SHARED, input, offset);
@@ -1442,9 +1924,10 @@ more:
1442 size = 8; 1924 size = 8;
1443 1925
1444 if (head + event->header.size >= page_size * mmap_window) { 1926 if (head + event->header.size >= page_size * mmap_window) {
1445 unsigned long shift = page_size * (head / page_size);
1446 int ret; 1927 int ret;
1447 1928
1929 shift = page_size * (head / page_size);
1930
1448 ret = munmap(buf, page_size * mmap_window); 1931 ret = munmap(buf, page_size * mmap_window);
1449 assert(ret == 0); 1932 assert(ret == 0);
1450 1933
@@ -1482,10 +1965,10 @@ more:
1482 1965
1483 head += size; 1966 head += size;
1484 1967
1485 if (offset + head >= sizeof(file_header) + file_header.data_size) 1968 if (offset + head >= header->data_offset + header->data_size)
1486 goto done; 1969 goto done;
1487 1970
1488 if (offset + head < stat.st_size) 1971 if (offset + head < (unsigned long)stat.st_size)
1489 goto more; 1972 goto more;
1490 1973
1491done: 1974done:
@@ -1509,12 +1992,65 @@ done:
1509 dsos__fprintf(stdout); 1992 dsos__fprintf(stdout);
1510 1993
1511 collapse__resort(); 1994 collapse__resort();
1512 output__resort(); 1995 output__resort(total);
1513 output__fprintf(stdout, total); 1996 output__fprintf(stdout, total);
1514 1997
1515 return rc; 1998 return rc;
1516} 1999}
1517 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
1518static const char * const report_usage[] = { 2054static const char * const report_usage[] = {
1519 "perf report [<options>] <command>", 2055 "perf report [<options>] <command>",
1520 NULL 2056 NULL
@@ -1528,6 +2064,10 @@ static const struct option options[] = {
1528 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 2064 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
1529 "dump raw trace in ASCII"), 2065 "dump raw trace in ASCII"),
1530 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"),
1531 OPT_STRING('s', "sort", &sort_order, "key[,key2...]", 2071 OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
1532 "sort by key(s): pid, comm, dso, symbol, parent"), 2072 "sort by key(s): pid, comm, dso, symbol, parent"),
1533 OPT_BOOLEAN('P', "full-paths", &full_paths, 2073 OPT_BOOLEAN('P', "full-paths", &full_paths,
@@ -1536,6 +2076,21 @@ static const struct option options[] = {
1536 "regex filter to identify parent, see: '--sort parent'"), 2076 "regex filter to identify parent, see: '--sort parent'"),
1537 OPT_BOOLEAN('x', "exclude-other", &exclude_other, 2077 OPT_BOOLEAN('x', "exclude-other", &exclude_other,
1538 "Only display entries with parent-match"), 2078 "Only display entries with parent-match"),
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),
2082 OPT_STRING('d', "dsos", &dso_list_str, "dso[,dso...]",
2083 "only consider symbols in these dsos"),
2084 OPT_STRING('C', "comms", &comm_list_str, "comm[,comm...]",
2085 "only consider symbols in these comms"),
2086 OPT_STRING('S', "symbols", &sym_list_str, "symbol[,symbol...]",
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."),
1539 OPT_END() 2094 OPT_END()
1540}; 2095};
1541 2096
@@ -1554,7 +2109,26 @@ static void setup_sorting(void)
1554 free(str); 2109 free(str);
1555} 2110}
1556 2111
1557int cmd_report(int argc, const char **argv, const char *prefix) 2112static void setup_list(struct strlist **list, const char *list_str,
2113 struct sort_entry *se, const char *list_name,
2114 FILE *fp)
2115{
2116 if (list_str) {
2117 *list = strlist__new(true, list_str);
2118 if (!*list) {
2119 fprintf(stderr, "problems parsing %s list\n",
2120 list_name);
2121 exit(129);
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 }
2128 }
2129}
2130
2131int cmd_report(int argc, const char **argv, const char *prefix __used)
1558{ 2132{
1559 symbol__init(); 2133 symbol__init();
1560 2134
@@ -1564,9 +2138,10 @@ int cmd_report(int argc, const char **argv, const char *prefix)
1564 2138
1565 setup_sorting(); 2139 setup_sorting();
1566 2140
1567 if (parent_pattern != default_parent_pattern) 2141 if (parent_pattern != default_parent_pattern) {
1568 sort_dimension__add("parent"); 2142 sort_dimension__add("parent");
1569 else 2143 sort_parent.elide = 1;
2144 } else
1570 exclude_other = 0; 2145 exclude_other = 0;
1571 2146
1572 /* 2147 /*
@@ -1577,5 +2152,15 @@ int cmd_report(int argc, const char **argv, const char *prefix)
1577 2152
1578 setup_pager(); 2153 setup_pager();
1579 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
1580 return __cmd_report(); 2165 return __cmd_report();
1581} 2166}
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 6d3eeac1ea25..b4b06c7903e1 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -32,6 +32,7 @@
32 * Wu Fengguang <fengguang.wu@intel.com> 32 * Wu Fengguang <fengguang.wu@intel.com>
33 * Mike Galbraith <efault@gmx.de> 33 * Mike Galbraith <efault@gmx.de>
34 * Paul Mackerras <paulus@samba.org> 34 * Paul Mackerras <paulus@samba.org>
35 * Jaswinder Singh Rajput <jaswinder@kernel.org>
35 * 36 *
36 * Released under the GPL v2. (and only v2, not any later version) 37 * Released under the GPL v2. (and only v2, not any later version)
37 */ 38 */
@@ -45,7 +46,7 @@
45#include <sys/prctl.h> 46#include <sys/prctl.h>
46#include <math.h> 47#include <math.h>
47 48
48static struct perf_counter_attr default_attrs[MAX_COUNTERS] = { 49static struct perf_counter_attr default_attrs[] = {
49 50
50 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK }, 51 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK },
51 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CONTEXT_SWITCHES}, 52 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CONTEXT_SWITCHES},
@@ -59,42 +60,28 @@ static struct perf_counter_attr default_attrs[MAX_COUNTERS] = {
59 60
60}; 61};
61 62
63#define MAX_RUN 100
64
62static int system_wide = 0; 65static int system_wide = 0;
63static int inherit = 1;
64static int verbose = 0; 66static int verbose = 0;
67static unsigned int nr_cpus = 0;
68static int run_idx = 0;
65 69
66static int fd[MAX_NR_CPUS][MAX_COUNTERS]; 70static int run_count = 1;
67 71static int inherit = 1;
68static int target_pid = -1;
69static int nr_cpus = 0;
70static unsigned int page_size;
71
72static int scale = 1; 72static int scale = 1;
73static int target_pid = -1;
74static int null_run = 0;
73 75
74static const unsigned int default_count[] = { 76static int fd[MAX_NR_CPUS][MAX_COUNTERS];
75 1000000,
76 1000000,
77 10000,
78 10000,
79 1000000,
80 10000,
81};
82
83#define MAX_RUN 100
84
85static int run_count = 1;
86static int run_idx = 0;
87
88static u64 event_res[MAX_RUN][MAX_COUNTERS][3];
89static u64 event_scaled[MAX_RUN][MAX_COUNTERS];
90
91//static u64 event_hist[MAX_RUN][MAX_COUNTERS][3];
92
93 77
94static u64 runtime_nsecs[MAX_RUN]; 78static u64 runtime_nsecs[MAX_RUN];
95static u64 walltime_nsecs[MAX_RUN]; 79static u64 walltime_nsecs[MAX_RUN];
96static u64 runtime_cycles[MAX_RUN]; 80static u64 runtime_cycles[MAX_RUN];
97 81
82static u64 event_res[MAX_RUN][MAX_COUNTERS][3];
83static u64 event_scaled[MAX_RUN][MAX_COUNTERS];
84
98static u64 event_res_avg[MAX_COUNTERS][3]; 85static u64 event_res_avg[MAX_COUNTERS][3];
99static u64 event_res_noise[MAX_COUNTERS][3]; 86static u64 event_res_noise[MAX_COUNTERS][3];
100 87
@@ -109,7 +96,14 @@ static u64 walltime_nsecs_noise;
109static u64 runtime_cycles_avg; 96static u64 runtime_cycles_avg;
110static u64 runtime_cycles_noise; 97static u64 runtime_cycles_noise;
111 98
112static void create_perf_stat_counter(int counter) 99#define MATCH_EVENT(t, c, counter) \
100 (attrs[counter].type == PERF_TYPE_##t && \
101 attrs[counter].config == PERF_COUNT_##c)
102
103#define ERR_PERF_OPEN \
104"Error: counter %d, sys_perf_counter_open() syscall returned with %d (%s)\n"
105
106static void create_perf_stat_counter(int counter, int pid)
113{ 107{
114 struct perf_counter_attr *attr = attrs + counter; 108 struct perf_counter_attr *attr = attrs + counter;
115 109
@@ -118,21 +112,23 @@ static void create_perf_stat_counter(int counter)
118 PERF_FORMAT_TOTAL_TIME_RUNNING; 112 PERF_FORMAT_TOTAL_TIME_RUNNING;
119 113
120 if (system_wide) { 114 if (system_wide) {
121 int cpu; 115 unsigned int cpu;
122 for (cpu = 0; cpu < nr_cpus; cpu ++) { 116
117 for (cpu = 0; cpu < nr_cpus; cpu++) {
123 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);
124 if (fd[cpu][counter] < 0 && verbose) { 119 if (fd[cpu][counter] < 0 && verbose)
125 printf("Error: counter %d, sys_perf_counter_open() syscall returned with %d (%s)\n", counter, fd[cpu][counter], strerror(errno)); 120 fprintf(stderr, ERR_PERF_OPEN, counter,
126 } 121 fd[cpu][counter], strerror(errno));
127 } 122 }
128 } else { 123 } else {
129 attr->inherit = inherit; 124 attr->inherit = inherit;
130 attr->disabled = 1; 125 attr->disabled = 1;
131 126 attr->enable_on_exec = 1;
132 fd[0][counter] = sys_perf_counter_open(attr, 0, -1, -1, 0); 127
133 if (fd[0][counter] < 0 && verbose) { 128 fd[0][counter] = sys_perf_counter_open(attr, pid, -1, -1, 0);
134 printf("Error: counter %d, sys_perf_counter_open() syscall returned with %d (%s)\n", counter, fd[0][counter], strerror(errno)); 129 if (fd[0][counter] < 0 && verbose)
135 } 130 fprintf(stderr, ERR_PERF_OPEN, counter,
131 fd[0][counter], strerror(errno));
136 } 132 }
137} 133}
138 134
@@ -141,13 +137,8 @@ static void create_perf_stat_counter(int counter)
141 */ 137 */
142static inline int nsec_counter(int counter) 138static inline int nsec_counter(int counter)
143{ 139{
144 if (attrs[counter].type != PERF_TYPE_SOFTWARE) 140 if (MATCH_EVENT(SOFTWARE, SW_CPU_CLOCK, counter) ||
145 return 0; 141 MATCH_EVENT(SOFTWARE, SW_TASK_CLOCK, counter))
146
147 if (attrs[counter].config == PERF_COUNT_SW_CPU_CLOCK)
148 return 1;
149
150 if (attrs[counter].config == PERF_COUNT_SW_TASK_CLOCK)
151 return 1; 142 return 1;
152 143
153 return 0; 144 return 0;
@@ -159,8 +150,8 @@ static inline int nsec_counter(int counter)
159static void read_counter(int counter) 150static void read_counter(int counter)
160{ 151{
161 u64 *count, single_count[3]; 152 u64 *count, single_count[3];
162 ssize_t res; 153 unsigned int cpu;
163 int cpu, nv; 154 size_t res, nv;
164 int scaled; 155 int scaled;
165 156
166 count = event_res[run_idx][counter]; 157 count = event_res[run_idx][counter];
@@ -168,12 +159,13 @@ static void read_counter(int counter)
168 count[0] = count[1] = count[2] = 0; 159 count[0] = count[1] = count[2] = 0;
169 160
170 nv = scale ? 3 : 1; 161 nv = scale ? 3 : 1;
171 for (cpu = 0; cpu < nr_cpus; cpu ++) { 162 for (cpu = 0; cpu < nr_cpus; cpu++) {
172 if (fd[cpu][counter] < 0) 163 if (fd[cpu][counter] < 0)
173 continue; 164 continue;
174 165
175 res = read(fd[cpu][counter], single_count, nv * sizeof(u64)); 166 res = read(fd[cpu][counter], single_count, nv * sizeof(u64));
176 assert(res == nv * sizeof(u64)); 167 assert(res == nv * sizeof(u64));
168
177 close(fd[cpu][counter]); 169 close(fd[cpu][counter]);
178 fd[cpu][counter] = -1; 170 fd[cpu][counter] = -1;
179 171
@@ -201,46 +193,81 @@ static void read_counter(int counter)
201 /* 193 /*
202 * Save the full runtime - to allow normalization during printout: 194 * Save the full runtime - to allow normalization during printout:
203 */ 195 */
204 if (attrs[counter].type == PERF_TYPE_SOFTWARE && 196 if (MATCH_EVENT(SOFTWARE, SW_TASK_CLOCK, counter))
205 attrs[counter].config == PERF_COUNT_SW_TASK_CLOCK)
206 runtime_nsecs[run_idx] = count[0]; 197 runtime_nsecs[run_idx] = count[0];
207 if (attrs[counter].type == PERF_TYPE_HARDWARE && 198 if (MATCH_EVENT(HARDWARE, HW_CPU_CYCLES, counter))
208 attrs[counter].config == PERF_COUNT_HW_CPU_CYCLES)
209 runtime_cycles[run_idx] = count[0]; 199 runtime_cycles[run_idx] = count[0];
210} 200}
211 201
212static int run_perf_stat(int argc, const char **argv) 202static int run_perf_stat(int argc __used, const char **argv)
213{ 203{
214 unsigned long long t0, t1; 204 unsigned long long t0, t1;
215 int status = 0; 205 int status = 0;
216 int counter; 206 int counter;
217 int pid; 207 int pid;
208 int child_ready_pipe[2], go_pipe[2];
209 char buf;
218 210
219 if (!system_wide) 211 if (!system_wide)
220 nr_cpus = 1; 212 nr_cpus = 1;
221 213
222 for (counter = 0; counter < nr_counters; counter++) 214 if (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0) {
223 create_perf_stat_counter(counter); 215 perror("failed to create pipes");
224 216 exit(1);
225 /* 217 }
226 * Enable counters and exec the command:
227 */
228 t0 = rdclock();
229 prctl(PR_TASK_PERF_COUNTERS_ENABLE);
230 218
231 if ((pid = fork()) < 0) 219 if ((pid = fork()) < 0)
232 perror("failed to fork"); 220 perror("failed to fork");
233 221
234 if (!pid) { 222 if (!pid) {
235 if (execvp(argv[0], (char **)argv)) { 223 close(child_ready_pipe[0]);
236 perror(argv[0]); 224 close(go_pipe[1]);
237 exit(-1); 225 fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC);
238 } 226
227 /*
228 * Do a dummy execvp to get the PLT entry resolved,
229 * so we avoid the resolver overhead on the real
230 * execvp call.
231 */
232 execvp("", (char **)argv);
233
234 /*
235 * Tell the parent we're ready to go
236 */
237 close(child_ready_pipe[1]);
238
239 /*
240 * Wait until the parent tells us to go.
241 */
242 if (read(go_pipe[0], &buf, 1) == -1)
243 perror("unable to read pipe");
244
245 execvp(argv[0], (char **)argv);
246
247 perror(argv[0]);
248 exit(-1);
239 } 249 }
240 250
251 /*
252 * Wait for the child to be ready to exec.
253 */
254 close(child_ready_pipe[1]);
255 close(go_pipe[0]);
256 if (read(child_ready_pipe[0], &buf, 1) == -1)
257 perror("unable to read pipe");
258 close(child_ready_pipe[0]);
259
260 for (counter = 0; counter < nr_counters; counter++)
261 create_perf_stat_counter(counter, pid);
262
263 /*
264 * Enable counters and exec the command:
265 */
266 t0 = rdclock();
267
268 close(go_pipe[1]);
241 wait(&status); 269 wait(&status);
242 270
243 prctl(PR_TASK_PERF_COUNTERS_DISABLE);
244 t1 = rdclock(); 271 t1 = rdclock();
245 272
246 walltime_nsecs[run_idx] = t1 - t0; 273 walltime_nsecs[run_idx] = t1 - t0;
@@ -262,11 +289,9 @@ static void nsec_printout(int counter, u64 *count, u64 *noise)
262{ 289{
263 double msecs = (double)count[0] / 1000000; 290 double msecs = (double)count[0] / 1000000;
264 291
265 fprintf(stderr, " %14.6f %-20s", msecs, event_name(counter)); 292 fprintf(stderr, " %14.6f %-24s", msecs, event_name(counter));
266
267 if (attrs[counter].type == PERF_TYPE_SOFTWARE &&
268 attrs[counter].config == PERF_COUNT_SW_TASK_CLOCK) {
269 293
294 if (MATCH_EVENT(SOFTWARE, SW_TASK_CLOCK, counter)) {
270 if (walltime_nsecs_avg) 295 if (walltime_nsecs_avg)
271 fprintf(stderr, " # %10.3f CPUs ", 296 fprintf(stderr, " # %10.3f CPUs ",
272 (double)count[0] / (double)walltime_nsecs_avg); 297 (double)count[0] / (double)walltime_nsecs_avg);
@@ -276,12 +301,10 @@ static void nsec_printout(int counter, u64 *count, u64 *noise)
276 301
277static void abs_printout(int counter, u64 *count, u64 *noise) 302static void abs_printout(int counter, u64 *count, u64 *noise)
278{ 303{
279 fprintf(stderr, " %14Ld %-20s", count[0], event_name(counter)); 304 fprintf(stderr, " %14Ld %-24s", count[0], event_name(counter));
280 305
281 if (runtime_cycles_avg && 306 if (runtime_cycles_avg &&
282 attrs[counter].type == PERF_TYPE_HARDWARE && 307 MATCH_EVENT(HARDWARE, HW_INSTRUCTIONS, counter)) {
283 attrs[counter].config == PERF_COUNT_HW_INSTRUCTIONS) {
284
285 fprintf(stderr, " # %10.3f IPC ", 308 fprintf(stderr, " # %10.3f IPC ",
286 (double)count[0] / (double)runtime_cycles_avg); 309 (double)count[0] / (double)runtime_cycles_avg);
287 } else { 310 } else {
@@ -306,7 +329,7 @@ static void print_counter(int counter)
306 scaled = event_scaled_avg[counter]; 329 scaled = event_scaled_avg[counter];
307 330
308 if (scaled == -1) { 331 if (scaled == -1) {
309 fprintf(stderr, " %14s %-20s\n", 332 fprintf(stderr, " %14s %-24s\n",
310 "<not counted>", event_name(counter)); 333 "<not counted>", event_name(counter));
311 return; 334 return;
312 } 335 }
@@ -364,8 +387,11 @@ static void calc_avg(void)
364 event_res_avg[j]+1, event_res[i][j]+1); 387 event_res_avg[j]+1, event_res[i][j]+1);
365 update_avg("counter/2", j, 388 update_avg("counter/2", j,
366 event_res_avg[j]+2, event_res[i][j]+2); 389 event_res_avg[j]+2, event_res[i][j]+2);
367 update_avg("scaled", j, 390 if (event_scaled[i][j] != (u64)-1)
368 event_scaled_avg + j, event_scaled[i]+j); 391 update_avg("scaled", j,
392 event_scaled_avg + j, event_scaled[i]+j);
393 else
394 event_scaled_avg[j] = -1;
369 } 395 }
370 } 396 }
371 runtime_nsecs_avg /= run_count; 397 runtime_nsecs_avg /= run_count;
@@ -429,11 +455,14 @@ static void print_stat(int argc, const char **argv)
429 for (counter = 0; counter < nr_counters; counter++) 455 for (counter = 0; counter < nr_counters; counter++)
430 print_counter(counter); 456 print_counter(counter);
431 457
432
433 fprintf(stderr, "\n"); 458 fprintf(stderr, "\n");
434 fprintf(stderr, " %14.9f seconds time elapsed.\n", 459 fprintf(stderr, " %14.9f seconds time elapsed",
435 (double)walltime_nsecs_avg/1e9); 460 (double)walltime_nsecs_avg/1e9);
436 fprintf(stderr, "\n"); 461 if (run_count > 1) {
462 fprintf(stderr, " ( +- %7.3f%% )",
463 100.0*(double)walltime_nsecs_noise/(double)walltime_nsecs_avg);
464 }
465 fprintf(stderr, "\n\n");
437} 466}
438 467
439static volatile int signr = -1; 468static volatile int signr = -1;
@@ -466,36 +495,38 @@ static const struct option options[] = {
466 OPT_INTEGER('p', "pid", &target_pid, 495 OPT_INTEGER('p', "pid", &target_pid,
467 "stat events on existing pid"), 496 "stat events on existing pid"),
468 OPT_BOOLEAN('a', "all-cpus", &system_wide, 497 OPT_BOOLEAN('a', "all-cpus", &system_wide,
469 "system-wide collection from all CPUs"), 498 "system-wide collection from all CPUs"),
470 OPT_BOOLEAN('S', "scale", &scale, 499 OPT_BOOLEAN('c', "scale", &scale,
471 "scale/normalize counters"), 500 "scale/normalize counters"),
472 OPT_BOOLEAN('v', "verbose", &verbose, 501 OPT_BOOLEAN('v', "verbose", &verbose,
473 "be more verbose (show counter open errors, etc)"), 502 "be more verbose (show counter open errors, etc)"),
474 OPT_INTEGER('r', "repeat", &run_count, 503 OPT_INTEGER('r', "repeat", &run_count,
475 "repeat command and print average + stddev (max: 100)"), 504 "repeat command and print average + stddev (max: 100)"),
505 OPT_BOOLEAN('n', "null", &null_run,
506 "null run - dont start any counters"),
476 OPT_END() 507 OPT_END()
477}; 508};
478 509
479int cmd_stat(int argc, const char **argv, const char *prefix) 510int cmd_stat(int argc, const char **argv, const char *prefix __used)
480{ 511{
481 int status; 512 int status;
482 513
483 page_size = sysconf(_SC_PAGE_SIZE); 514 argc = parse_options(argc, argv, options, stat_usage,
484 515 PARSE_OPT_STOP_AT_NON_OPTION);
485 memcpy(attrs, default_attrs, sizeof(attrs));
486
487 argc = parse_options(argc, argv, options, stat_usage, 0);
488 if (!argc) 516 if (!argc)
489 usage_with_options(stat_usage, options); 517 usage_with_options(stat_usage, options);
490 if (run_count <= 0 || run_count > MAX_RUN) 518 if (run_count <= 0 || run_count > MAX_RUN)
491 usage_with_options(stat_usage, options); 519 usage_with_options(stat_usage, options);
492 520
493 if (!nr_counters) 521 /* Set attrs and nr_counters if no event is selected and !null_run */
494 nr_counters = 8; 522 if (!null_run && !nr_counters) {
523 memcpy(attrs, default_attrs, sizeof(default_attrs));
524 nr_counters = ARRAY_SIZE(default_attrs);
525 }
495 526
496 nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); 527 nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
497 assert(nr_cpus <= MAX_NR_CPUS); 528 assert(nr_cpus <= MAX_NR_CPUS);
498 assert(nr_cpus >= 0); 529 assert((int)nr_cpus >= 0);
499 530
500 /* 531 /*
501 * We dont want to block the signals - that would cause 532 * We dont want to block the signals - that would cause
@@ -511,7 +542,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix)
511 status = 0; 542 status = 0;
512 for (run_idx = 0; run_idx < run_count; run_idx++) { 543 for (run_idx = 0; run_idx < run_count; run_idx++) {
513 if (run_count != 1 && verbose) 544 if (run_count != 1 && verbose)
514 fprintf(stderr, "[ perf stat: executing run #%d ... ]\n", run_idx+1); 545 fprintf(stderr, "[ perf stat: executing run #%d ... ]\n", run_idx + 1);
515 status = run_perf_stat(argc, argv); 546 status = run_perf_stat(argc, argv);
516 } 547 }
517 548
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 5352b5e352ed..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);
@@ -392,11 +868,11 @@ static void record_ip(u64 ip, int counter)
392 samples--; 868 samples--;
393} 869}
394 870
395static void process_event(u64 ip, int counter) 871static void process_event(u64 ip, int counter, int user)
396{ 872{
397 samples++; 873 samples++;
398 874
399 if (ip < min_ip || ip > max_ip) { 875 if (user) {
400 userspace_samples++; 876 userspace_samples++;
401 return; 877 return;
402 } 878 }
@@ -407,7 +883,7 @@ static void process_event(u64 ip, int counter)
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
@@ -509,9 +985,10 @@ static void mmap_read_counter(struct mmap_data *md)
509 985
510 old += size; 986 old += size;
511 987
512 if (event->header.misc & PERF_EVENT_MISC_OVERFLOW) { 988 if (event->header.type == PERF_EVENT_SAMPLE) {
513 if (event->header.type & PERF_SAMPLE_IP) 989 int user =
514 process_event(event->ip.ip, md->counter); 990 (event->header.misc & PERF_EVENT_MISC_CPUMODE_MASK) == PERF_EVENT_MISC_USER;
991 process_event(event->ip.ip, md->counter, user);
515 } 992 }
516 } 993 }
517 994
@@ -537,7 +1014,7 @@ int group_fd;
537static void start_counter(int i, int counter) 1014static void start_counter(int i, int counter)
538{ 1015{
539 struct perf_counter_attr *attr; 1016 struct perf_counter_attr *attr;
540 unsigned int cpu; 1017 int cpu;
541 1018
542 cpu = profile_cpu; 1019 cpu = profile_cpu;
543 if (target_pid == -1 && profile_cpu == -1) 1020 if (target_pid == -1 && profile_cpu == -1)
@@ -547,6 +1024,7 @@ static void start_counter(int i, int counter)
547 1024
548 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID; 1025 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID;
549 attr->freq = freq; 1026 attr->freq = freq;
1027 attr->inherit = (cpu < 0) && inherit;
550 1028
551try_again: 1029try_again:
552 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);
@@ -660,6 +1138,7 @@ static const struct option options[] = {
660 "system-wide collection from all CPUs"), 1138 "system-wide collection from all CPUs"),
661 OPT_INTEGER('C', "CPU", &profile_cpu, 1139 OPT_INTEGER('C', "CPU", &profile_cpu,
662 "CPU to profile on"), 1140 "CPU to profile on"),
1141 OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"),
663 OPT_INTEGER('m', "mmap-pages", &mmap_pages, 1142 OPT_INTEGER('m', "mmap-pages", &mmap_pages,
664 "number of mmap data pages"), 1143 "number of mmap data pages"),
665 OPT_INTEGER('r', "realtime", &realtime_prio, 1144 OPT_INTEGER('r', "realtime", &realtime_prio,
@@ -672,9 +1151,11 @@ static const struct option options[] = {
672 "only display functions with more events than this"), 1151 "only display functions with more events than this"),
673 OPT_BOOLEAN('g', "group", &group, 1152 OPT_BOOLEAN('g', "group", &group,
674 "put the counters into a counter group"), 1153 "put the counters into a counter group"),
675 OPT_STRING('s', "sym-filter", &sym_filter, "pattern", 1154 OPT_BOOLEAN('i', "inherit", &inherit,
676 "only display symbols matchig this pattern"), 1155 "child tasks inherit counters"),
677 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,
678 "zero history across updates"), 1159 "zero history across updates"),
679 OPT_INTEGER('F', "freq", &freq, 1160 OPT_INTEGER('F', "freq", &freq,
680 "profile at this frequency"), 1161 "profile at this frequency"),
@@ -685,10 +1166,12 @@ static const struct option options[] = {
685 OPT_END() 1166 OPT_END()
686}; 1167};
687 1168
688int cmd_top(int argc, const char **argv, const char *prefix) 1169int cmd_top(int argc, const char **argv, const char *prefix __used)
689{ 1170{
690 int counter; 1171 int counter;
691 1172
1173 symbol__init();
1174
692 page_size = sysconf(_SC_PAGE_SIZE); 1175 page_size = sysconf(_SC_PAGE_SIZE);
693 1176
694 argc = parse_options(argc, argv, options, top_usage, 0); 1177 argc = parse_options(argc, argv, options, top_usage, 0);
@@ -714,6 +1197,7 @@ int cmd_top(int argc, const char **argv, const char *prefix)
714 delay_secs = 1; 1197 delay_secs = 1;
715 1198
716 parse_symbols(); 1199 parse_symbols();
1200 parse_source(sym_filter_entry);
717 1201
718 /* 1202 /*
719 * 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 ceb68aa51f7f..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");
@@ -19,13 +25,29 @@
19#define cpu_relax() asm volatile("" ::: "memory"); 25#define cpu_relax() asm volatile("" ::: "memory");
20#endif 26#endif
21 27
28#ifdef __sh__
29#include "../../arch/sh/include/asm/unistd.h"
30#if defined(__SH4A__) || defined(__SH5__)
31# define rmb() asm volatile("synco" ::: "memory")
32#else
33# define rmb() asm volatile("" ::: "memory")
34#endif
35#define cpu_relax() asm volatile("" ::: "memory")
36#endif
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
22#include <time.h> 44#include <time.h>
23#include <unistd.h> 45#include <unistd.h>
24#include <sys/types.h> 46#include <sys/types.h>
25#include <sys/syscall.h> 47#include <sys/syscall.h>
26 48
27#include "../../include/linux/perf_counter.h" 49#include "../../include/linux/perf_counter.h"
28#include "types.h" 50#include "util/types.h"
29 51
30/* 52/*
31 * prctl(PR_TASK_PERF_COUNTERS_DISABLE) will (cheaply) disable all 53 * prctl(PR_TASK_PERF_COUNTERS_DISABLE) will (cheaply) disable all
@@ -52,6 +74,8 @@ static inline unsigned long long rdclock(void)
52#define __user 74#define __user
53#define asmlinkage 75#define asmlinkage
54 76
77#define __used __attribute__((__unused__))
78
55#define unlikely(x) __builtin_expect(!!(x), 0) 79#define unlikely(x) __builtin_expect(!!(x), 0)
56#define min(x, y) ({ \ 80#define min(x, y) ({ \
57 typeof(x) _min1 = (x); \ 81 typeof(x) _min1 = (x); \
@@ -72,10 +96,9 @@ sys_perf_counter_open(struct perf_counter_attr *attr,
72#define MAX_COUNTERS 256 96#define MAX_COUNTERS 256
73#define MAX_NR_CPUS 256 97#define MAX_NR_CPUS 256
74 98
75struct perf_file_header { 99struct ip_callchain {
76 u64 version; 100 u64 nr;
77 u64 sample_type; 101 u64 ips[0];
78 u64 data_size;
79}; 102};
80 103
81#endif 104#endif
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
new file mode 100644
index 000000000000..011473411642
--- /dev/null
+++ b/tools/perf/util/callchain.c
@@ -0,0 +1,343 @@
1/*
2 * Copyright (C) 2009, Frederic Weisbecker <fweisbec@gmail.com>
3 *
4 * Handle the callchains from the stream in an ad-hoc radix tree and then
5 * sort them in an rbtree.
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 *
10 */
11
12#include <stdlib.h>
13#include <stdio.h>
14#include <stdbool.h>
15#include <errno.h>
16#include <math.h>
17
18#include "callchain.h"
19
20#define chain_for_each_child(child, parent) \
21 list_for_each_entry(child, &parent->children, brothers)
22
23static void
24rb_insert_callchain(struct rb_root *root, struct callchain_node *chain,
25 enum chain_mode mode)
26{
27 struct rb_node **p = &root->rb_node;
28 struct rb_node *parent = NULL;
29 struct callchain_node *rnode;
30 u64 chain_cumul = cumul_hits(chain);
31
32 while (*p) {
33 u64 rnode_cumul;
34
35 parent = *p;
36 rnode = rb_entry(parent, struct callchain_node, rb_node);
37 rnode_cumul = cumul_hits(rnode);
38
39 switch (mode) {
40 case CHAIN_FLAT:
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 }
56 }
57
58 rb_link_node(&chain->rb_node, parent, p);
59 rb_insert_color(&chain->rb_node, root);
60}
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
75/*
76 * Once we get every callchains from the stream, we can now
77 * sort them by hit
78 */
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)
111{
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}
125
126static void
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}
133
134int register_callchain_param(struct callchain_param *param)
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;
150}
151
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)
158{
159 struct callchain_node *new;
160
161 new = malloc(sizeof(*new));
162 if (!new) {
163 perror("not enough memory to create child for code path tree");
164 return NULL;
165 }
166 new->parent = parent;
167 INIT_LIST_HEAD(&new->children);
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 }
179 list_add_tail(&new->brothers, &parent->children);
180
181 return new;
182}
183
184/*
185 * Fill the node with callchain values
186 */
187static void
188fill_node(struct callchain_node *node, struct ip_callchain *chain,
189 int start, struct symbol **syms)
190{
191 unsigned int i;
192
193 for (i = start; i < chain->nr; i++) {
194 struct callchain_list *call;
195
196 call = malloc(sizeof(*call));
197 if (!call) {
198 perror("not enough memory for the code path tree");
199 return;
200 }
201 call->ip = chain->ips[i];
202 call->sym = syms[i];
203 list_add_tail(&call->list, &node->val);
204 }
205 node->val_nr = chain->nr - start;
206 if (!node->val_nr)
207 printf("Warning: empty node in callchain tree\n");
208}
209
210static void
211add_child(struct callchain_node *parent, struct ip_callchain *chain,
212 int start, struct symbol **syms)
213{
214 struct callchain_node *new;
215
216 new = create_child(parent, false);
217 fill_node(new, chain, start, syms);
218
219 new->children_hit = 0;
220 new->hit = 1;
221}
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 */
228static void
229split_add_child(struct callchain_node *parent, struct ip_callchain *chain,
230 struct callchain_list *to_split, int idx_parents, int idx_local,
231 struct symbol **syms)
232{
233 struct callchain_node *new;
234 struct list_head *old_tail;
235 unsigned int idx_total = idx_parents + idx_local;
236
237 /* split */
238 new = create_child(parent, true);
239
240 /* split the callchain and move a part to the new child */
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 }
263}
264
265static int
266__append_chain(struct callchain_node *root, struct ip_callchain *chain,
267 unsigned int start, struct symbol **syms);
268
269static void
270__append_chain_children(struct callchain_node *root, struct ip_callchain *chain,
271 struct symbol **syms, unsigned int start)
272{
273 struct callchain_node *rnode;
274
275 /* lookup in childrens */
276 chain_for_each_child(rnode, root) {
277 unsigned int ret = __append_chain(rnode, chain, start, syms);
278
279 if (!ret)
280 goto inc_children_hit;
281 }
282 /* nothing in children, add to the current node */
283 add_child(root, chain, start, syms);
284
285inc_children_hit:
286 root->children_hit++;
287}
288
289static int
290__append_chain(struct callchain_node *root, struct ip_callchain *chain,
291 unsigned int start, struct symbol **syms)
292{
293 struct callchain_list *cnode;
294 unsigned int i = start;
295 bool found = false;
296
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 */
302 list_for_each_entry(cnode, &root->val, list) {
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])
309 break;
310 if (!found)
311 found = true;
312 i++;
313 }
314
315 /* matches not, relay on the parent */
316 if (!found)
317 return -1;
318
319 /* we match only a part of the node. Split it and add the new chain */
320 if (i - start < root->val_nr) {
321 split_add_child(root, chain, cnode, start, i - start, syms);
322 return 0;
323 }
324
325 /* we match 100% of the path, increment the hit */
326 if (i - start == root->val_nr && i == chain->nr) {
327 root->hit++;
328 return 0;
329 }
330
331 /* We match the node and still have a part remaining */
332 __append_chain_children(root, chain, syms, i);
333
334 return 0;
335}
336
337void append_chain(struct callchain_node *root, struct ip_callchain *chain,
338 struct symbol **syms)
339{
340 if (!chain->nr)
341 return;
342 __append_chain_children(root, chain, syms, 0);
343}
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
new file mode 100644
index 000000000000..a926ae4f5a16
--- /dev/null
+++ b/tools/perf/util/callchain.h
@@ -0,0 +1,60 @@
1#ifndef __PERF_CALLCHAIN_H
2#define __PERF_CALLCHAIN_H
3
4#include "../perf.h"
5#include <linux/list.h>
6#include <linux/rbtree.h>
7#include "symbol.h"
8
9enum chain_mode {
10 CHAIN_NONE,
11 CHAIN_FLAT,
12 CHAIN_GRAPH_ABS,
13 CHAIN_GRAPH_REL
14};
15
16struct callchain_node {
17 struct callchain_node *parent;
18 struct list_head brothers;
19 struct list_head children;
20 struct list_head val;
21 struct rb_node rb_node; /* to sort nodes in an rbtree */
22 struct rb_root rb_root; /* sorted tree of children */
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;
37};
38
39struct callchain_list {
40 u64 ip;
41 struct symbol *sym;
42 struct list_head list;
43};
44
45static inline void callchain_init(struct callchain_node *node)
46{
47 INIT_LIST_HEAD(&node->brothers);
48 INIT_LIST_HEAD(&node->children);
49 INIT_LIST_HEAD(&node->val);
50}
51
52static inline u64 cumul_hits(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);
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
new file mode 100644
index 000000000000..b92a457ca32e
--- /dev/null
+++ b/tools/perf/util/header.c
@@ -0,0 +1,245 @@
1#include <sys/types.h>
2#include <unistd.h>
3#include <stdio.h>
4#include <stdlib.h>
5
6#include "util.h"
7#include "header.h"
8
9/*
10 *
11 */
12
13struct perf_header_attr *perf_header_attr__new(struct perf_counter_attr *attr)
14{
15 struct perf_header_attr *self = malloc(sizeof(*self));
16
17 if (!self)
18 die("nomem");
19
20 self->attr = *attr;
21 self->ids = 0;
22 self->size = 1;
23 self->id = malloc(sizeof(u64));
24
25 if (!self->id)
26 die("nomem");
27
28 return self;
29}
30
31void perf_header_attr__add_id(struct perf_header_attr *self, u64 id)
32{
33 int pos = self->ids;
34
35 self->ids++;
36 if (self->ids > self->size) {
37 self->size *= 2;
38 self->id = realloc(self->id, self->size * sizeof(u64));
39 if (!self->id)
40 die("nomem");
41 }
42 self->id[pos] = id;
43}
44
45/*
46 *
47 */
48
49struct perf_header *perf_header__new(void)
50{
51 struct perf_header *self = malloc(sizeof(*self));
52
53 if (!self)
54 die("nomem");
55
56 self->frozen = 0;
57
58 self->attrs = 0;
59 self->size = 1;
60 self->attr = malloc(sizeof(void *));
61
62 if (!self->attr)
63 die("nomem");
64
65 self->data_offset = 0;
66 self->data_size = 0;
67
68 return self;
69}
70
71void perf_header__add_attr(struct perf_header *self,
72 struct perf_header_attr *attr)
73{
74 int pos = self->attrs;
75
76 if (self->frozen)
77 die("frozen");
78
79 self->attrs++;
80 if (self->attrs > self->size) {
81 self->size *= 2;
82 self->attr = realloc(self->attr, self->size * sizeof(void *));
83 if (!self->attr)
84 die("nomem");
85 }
86 self->attr[pos] = attr;
87}
88
89static const char *__perf_magic = "PERFFILE";
90
91#define PERF_MAGIC (*(u64 *)__perf_magic)
92
93struct perf_file_section {
94 u64 offset;
95 u64 size;
96};
97
98struct perf_file_attr {
99 struct perf_counter_attr attr;
100 struct perf_file_section ids;
101};
102
103struct perf_file_header {
104 u64 magic;
105 u64 size;
106 u64 attr_size;
107 struct perf_file_section attrs;
108 struct perf_file_section data;
109};
110
111static void do_write(int fd, void *buf, size_t size)
112{
113 while (size) {
114 int ret = write(fd, buf, size);
115
116 if (ret < 0)
117 die("failed to write");
118
119 size -= ret;
120 buf += ret;
121 }
122}
123
124void perf_header__write(struct perf_header *self, int fd)
125{
126 struct perf_file_header f_header;
127 struct perf_file_attr f_attr;
128 struct perf_header_attr *attr;
129 int i;
130
131 lseek(fd, sizeof(f_header), SEEK_SET);
132
133
134 for (i = 0; i < self->attrs; i++) {
135 attr = self->attr[i];
136
137 attr->id_offset = lseek(fd, 0, SEEK_CUR);
138 do_write(fd, attr->id, attr->ids * sizeof(u64));
139 }
140
141
142 self->attr_offset = lseek(fd, 0, SEEK_CUR);
143
144 for (i = 0; i < self->attrs; i++) {
145 attr = self->attr[i];
146
147 f_attr = (struct perf_file_attr){
148 .attr = attr->attr,
149 .ids = {
150 .offset = attr->id_offset,
151 .size = attr->ids * sizeof(u64),
152 }
153 };
154 do_write(fd, &f_attr, sizeof(f_attr));
155 }
156
157
158 self->data_offset = lseek(fd, 0, SEEK_CUR);
159
160 f_header = (struct perf_file_header){
161 .magic = PERF_MAGIC,
162 .size = sizeof(f_header),
163 .attr_size = sizeof(f_attr),
164 .attrs = {
165 .offset = self->attr_offset,
166 .size = self->attrs * sizeof(f_attr),
167 },
168 .data = {
169 .offset = self->data_offset,
170 .size = self->data_size,
171 },
172 };
173
174 lseek(fd, 0, SEEK_SET);
175 do_write(fd, &f_header, sizeof(f_header));
176 lseek(fd, self->data_offset + self->data_size, SEEK_SET);
177
178 self->frozen = 1;
179}
180
181static void do_read(int fd, void *buf, size_t size)
182{
183 while (size) {
184 int ret = read(fd, buf, size);
185
186 if (ret < 0)
187 die("failed to read");
188 if (ret == 0)
189 die("failed to read: missing data");
190
191 size -= ret;
192 buf += ret;
193 }
194}
195
196struct perf_header *perf_header__read(int fd)
197{
198 struct perf_header *self = perf_header__new();
199 struct perf_file_header f_header;
200 struct perf_file_attr f_attr;
201 u64 f_id;
202
203 int nr_attrs, nr_ids, i, j;
204
205 lseek(fd, 0, SEEK_SET);
206 do_read(fd, &f_header, sizeof(f_header));
207
208 if (f_header.magic != PERF_MAGIC ||
209 f_header.size != sizeof(f_header) ||
210 f_header.attr_size != sizeof(f_attr))
211 die("incompatible file format");
212
213 nr_attrs = f_header.attrs.size / sizeof(f_attr);
214 lseek(fd, f_header.attrs.offset, SEEK_SET);
215
216 for (i = 0; i < nr_attrs; i++) {
217 struct perf_header_attr *attr;
218 off_t tmp;
219
220 do_read(fd, &f_attr, sizeof(f_attr));
221 tmp = lseek(fd, 0, SEEK_CUR);
222
223 attr = perf_header_attr__new(&f_attr.attr);
224
225 nr_ids = f_attr.ids.size / sizeof(u64);
226 lseek(fd, f_attr.ids.offset, SEEK_SET);
227
228 for (j = 0; j < nr_ids; j++) {
229 do_read(fd, &f_id, sizeof(f_id));
230
231 perf_header_attr__add_id(attr, f_id);
232 }
233 perf_header__add_attr(self, attr);
234 lseek(fd, tmp, SEEK_SET);
235 }
236
237 self->data_offset = f_header.data.offset;
238 self->data_size = f_header.data.size;
239
240 lseek(fd, self->data_offset + self->data_size, SEEK_SET);
241
242 self->frozen = 1;
243
244 return self;
245}
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
new file mode 100644
index 000000000000..bf280449fcfd
--- /dev/null
+++ b/tools/perf/util/header.h
@@ -0,0 +1,37 @@
1#ifndef _PERF_HEADER_H
2#define _PERF_HEADER_H
3
4#include "../../../include/linux/perf_counter.h"
5#include <sys/types.h>
6#include "types.h"
7
8struct perf_header_attr {
9 struct perf_counter_attr attr;
10 int ids, size;
11 u64 *id;
12 off_t id_offset;
13};
14
15struct perf_header {
16 int frozen;
17 int attrs, size;
18 struct perf_header_attr **attr;
19 s64 attr_offset;
20 u64 data_offset;
21 u64 data_size;
22};
23
24struct perf_header *perf_header__read(int fd);
25void perf_header__write(struct perf_header *self, int fd);
26
27void perf_header__add_attr(struct perf_header *self,
28 struct perf_header_attr *attr);
29
30struct perf_header_attr *
31perf_header_attr__new(struct perf_counter_attr *attr);
32void perf_header_attr__add_id(struct perf_header_attr *self, u64 id);
33
34
35struct perf_header *perf_header__new(void);
36
37#endif /* _PERF_HEADER_H */
diff --git a/tools/perf/util/help.c b/tools/perf/util/help.c
index 6653f7dd1d78..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)
@@ -126,21 +128,6 @@ static int is_executable(const char *name)
126 !S_ISREG(st.st_mode)) 128 !S_ISREG(st.st_mode))
127 return 0; 129 return 0;
128 130
129#ifdef __MINGW32__
130 /* cannot trust the executable bit, peek into the file instead */
131 char buf[3] = { 0 };
132 int n;
133 int fd = open(name, O_RDONLY);
134 st.st_mode &= ~S_IXUSR;
135 if (fd >= 0) {
136 n = read(fd, buf, 2);
137 if (n == 2)
138 /* DOS executables start with "MZ" */
139 if (!strcmp(buf, "#!") || !strcmp(buf, "MZ"))
140 st.st_mode |= S_IXUSR;
141 close(fd);
142 }
143#endif
144 return st.st_mode & S_IXUSR; 131 return st.st_mode & S_IXUSR;
145} 132}
146 133
@@ -223,7 +210,7 @@ void load_command_list(const char *prefix,
223void list_commands(const char *title, struct cmdnames *main_cmds, 210void list_commands(const char *title, struct cmdnames *main_cmds,
224 struct cmdnames *other_cmds) 211 struct cmdnames *other_cmds)
225{ 212{
226 int i, longest = 0; 213 unsigned int i, longest = 0;
227 214
228 for (i = 0; i < main_cmds->cnt; i++) 215 for (i = 0; i < main_cmds->cnt; i++)
229 if (longest < main_cmds->names[i]->len) 216 if (longest < main_cmds->names[i]->len)
@@ -254,7 +241,8 @@ void list_commands(const char *title, struct cmdnames *main_cmds,
254 241
255int is_in_cmdlist(struct cmdnames *c, const char *s) 242int is_in_cmdlist(struct cmdnames *c, const char *s)
256{ 243{
257 int i; 244 unsigned int i;
245
258 for (i = 0; i < c->cnt; i++) 246 for (i = 0; i < c->cnt; i++)
259 if (!strcmp(s, c->names[i]->name)) 247 if (!strcmp(s, c->names[i]->name))
260 return 1; 248 return 1;
@@ -286,7 +274,8 @@ static int levenshtein_compare(const void *p1, const void *p2)
286 274
287static void add_cmd_list(struct cmdnames *cmds, struct cmdnames *old) 275static void add_cmd_list(struct cmdnames *cmds, struct cmdnames *old)
288{ 276{
289 int i; 277 unsigned int i;
278
290 ALLOC_GROW(cmds->names, cmds->cnt + old->cnt, cmds->alloc); 279 ALLOC_GROW(cmds->names, cmds->cnt + old->cnt, cmds->alloc);
291 280
292 for (i = 0; i < old->cnt; i++) 281 for (i = 0; i < old->cnt; i++)
@@ -298,7 +287,7 @@ static void add_cmd_list(struct cmdnames *cmds, struct cmdnames *old)
298 287
299const char *help_unknown_cmd(const char *cmd) 288const char *help_unknown_cmd(const char *cmd)
300{ 289{
301 int i, n = 0, best_similarity = 0; 290 unsigned int i, n = 0, best_similarity = 0;
302 struct cmdnames main_cmds, other_cmds; 291 struct cmdnames main_cmds, other_cmds;
303 292
304 memset(&main_cmds, 0, sizeof(main_cmds)); 293 memset(&main_cmds, 0, sizeof(main_cmds));
@@ -360,7 +349,7 @@ const char *help_unknown_cmd(const char *cmd)
360 exit(1); 349 exit(1);
361} 350}
362 351
363int cmd_version(int argc, const char **argv, const char *prefix) 352int cmd_version(int argc __used, const char **argv __used, const char *prefix __used)
364{ 353{
365 printf("perf version %s\n", perf_version_string); 354 printf("perf version %s\n", perf_version_string);
366 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/pager.c b/tools/perf/util/pager.c
index a28bccae5458..1915de20dcac 100644
--- a/tools/perf/util/pager.c
+++ b/tools/perf/util/pager.c
@@ -9,7 +9,6 @@
9 9
10static int spawned_pager; 10static int spawned_pager;
11 11
12#ifndef __MINGW32__
13static void pager_preexec(void) 12static void pager_preexec(void)
14{ 13{
15 /* 14 /*
@@ -24,7 +23,6 @@ static void pager_preexec(void)
24 23
25 setenv("LESS", "FRSX", 0); 24 setenv("LESS", "FRSX", 0);
26} 25}
27#endif
28 26
29static const char *pager_argv[] = { "sh", "-c", NULL, NULL }; 27static const char *pager_argv[] = { "sh", "-c", NULL, NULL };
30static struct child_process pager_process; 28static struct child_process pager_process;
@@ -70,9 +68,8 @@ void setup_pager(void)
70 pager_argv[2] = pager; 68 pager_argv[2] = pager;
71 pager_process.argv = pager_argv; 69 pager_process.argv = pager_argv;
72 pager_process.in = -1; 70 pager_process.in = -1;
73#ifndef __MINGW32__
74 pager_process.preexec_cb = pager_preexec; 71 pager_process.preexec_cb = pager_preexec;
75#endif 72
76 if (start_command(&pager_process)) 73 if (start_command(&pager_process))
77 return; 74 return;
78 75
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 35d04da38d6a..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
@@ -16,32 +17,30 @@ struct event_symbol {
16 u8 type; 17 u8 type;
17 u64 config; 18 u64 config;
18 char *symbol; 19 char *symbol;
20 char *alias;
19}; 21};
20 22
21#define C(x, y) .type = PERF_TYPE_##x, .config = PERF_COUNT_##y 23char debugfs_path[MAXPATHLEN];
22#define CR(x, y) .type = PERF_TYPE_##x, .config = y 24
25#define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x
26#define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x
23 27
24static struct event_symbol event_symbols[] = { 28static struct event_symbol event_symbols[] = {
25 { C(HARDWARE, HW_CPU_CYCLES), "cpu-cycles", }, 29 { CHW(CPU_CYCLES), "cpu-cycles", "cycles" },
26 { C(HARDWARE, HW_CPU_CYCLES), "cycles", }, 30 { CHW(INSTRUCTIONS), "instructions", "" },
27 { C(HARDWARE, HW_INSTRUCTIONS), "instructions", }, 31 { CHW(CACHE_REFERENCES), "cache-references", "" },
28 { C(HARDWARE, HW_CACHE_REFERENCES), "cache-references", }, 32 { CHW(CACHE_MISSES), "cache-misses", "" },
29 { C(HARDWARE, HW_CACHE_MISSES), "cache-misses", }, 33 { CHW(BRANCH_INSTRUCTIONS), "branch-instructions", "branches" },
30 { C(HARDWARE, HW_BRANCH_INSTRUCTIONS),"branch-instructions", }, 34 { CHW(BRANCH_MISSES), "branch-misses", "" },
31 { C(HARDWARE, HW_BRANCH_INSTRUCTIONS),"branches", }, 35 { CHW(BUS_CYCLES), "bus-cycles", "" },
32 { C(HARDWARE, HW_BRANCH_MISSES), "branch-misses", }, 36
33 { C(HARDWARE, HW_BUS_CYCLES), "bus-cycles", }, 37 { CSW(CPU_CLOCK), "cpu-clock", "" },
34 38 { CSW(TASK_CLOCK), "task-clock", "" },
35 { C(SOFTWARE, SW_CPU_CLOCK), "cpu-clock", }, 39 { CSW(PAGE_FAULTS), "page-faults", "faults" },
36 { C(SOFTWARE, SW_TASK_CLOCK), "task-clock", }, 40 { CSW(PAGE_FAULTS_MIN), "minor-faults", "" },
37 { C(SOFTWARE, SW_PAGE_FAULTS), "page-faults", }, 41 { CSW(PAGE_FAULTS_MAJ), "major-faults", "" },
38 { C(SOFTWARE, SW_PAGE_FAULTS), "faults", }, 42 { CSW(CONTEXT_SWITCHES), "context-switches", "cs" },
39 { C(SOFTWARE, SW_PAGE_FAULTS_MIN), "minor-faults", }, 43 { CSW(CPU_MIGRATIONS), "cpu-migrations", "migrations" },
40 { C(SOFTWARE, SW_PAGE_FAULTS_MAJ), "major-faults", },
41 { C(SOFTWARE, SW_CONTEXT_SWITCHES), "context-switches", },
42 { C(SOFTWARE, SW_CONTEXT_SWITCHES), "cs", },
43 { C(SOFTWARE, SW_CPU_MIGRATIONS), "cpu-migrations", },
44 { C(SOFTWARE, SW_CPU_MIGRATIONS), "migrations", },
45}; 44};
46 45
47#define __PERF_COUNTER_FIELD(config, name) \ 46#define __PERF_COUNTER_FIELD(config, name) \
@@ -74,33 +73,181 @@ static char *sw_event_names[] = {
74 73
75#define MAX_ALIASES 8 74#define MAX_ALIASES 8
76 75
77static char *hw_cache [][MAX_ALIASES] = { 76static char *hw_cache[][MAX_ALIASES] = {
78 { "L1-data" , "l1-d", "l1d" }, 77 { "L1-dcache", "l1-d", "l1d", "L1-data", },
79 { "L1-instruction" , "l1-i", "l1i" }, 78 { "L1-icache", "l1-i", "l1i", "L1-instruction", },
80 { "L2" , "l2" }, 79 { "LLC", "L2" },
81 { "Data-TLB" , "dtlb", "d-tlb" }, 80 { "dTLB", "d-tlb", "Data-TLB", },
82 { "Instruction-TLB" , "itlb", "i-tlb" }, 81 { "iTLB", "i-tlb", "Instruction-TLB", },
83 { "Branch" , "bpu" , "btb", "bpc" }, 82 { "branch", "branches", "bpu", "btb", "bpc", },
84}; 83};
85 84
86static char *hw_cache_op [][MAX_ALIASES] = { 85static char *hw_cache_op[][MAX_ALIASES] = {
87 { "Load" , "read" }, 86 { "load", "loads", "read", },
88 { "Store" , "write" }, 87 { "store", "stores", "write", },
89 { "Prefetch" , "speculative-read", "speculative-load" }, 88 { "prefetch", "prefetches", "speculative-read", "speculative-load", },
90}; 89};
91 90
92static char *hw_cache_result [][MAX_ALIASES] = { 91static char *hw_cache_result[][MAX_ALIASES] = {
93 { "Reference" , "ops", "access" }, 92 { "refs", "Reference", "ops", "access", },
94 { "Miss" }, 93 { "misses", "miss", },
95}; 94};
96 95
96#define C(x) PERF_COUNT_HW_CACHE_##x
97#define CACHE_READ (1 << C(OP_READ))
98#define CACHE_WRITE (1 << C(OP_WRITE))
99#define CACHE_PREFETCH (1 << C(OP_PREFETCH))
100#define COP(x) (1 << x)
101
102/*
103 * cache operartion stat
104 * L1I : Read and prefetch only
105 * ITLB and BPU : Read-only
106 */
107static unsigned long hw_cache_stat[C(MAX)] = {
108 [C(L1D)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
109 [C(L1I)] = (CACHE_READ | CACHE_PREFETCH),
110 [C(LL)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
111 [C(DTLB)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
112 [C(ITLB)] = (CACHE_READ),
113 [C(BPU)] = (CACHE_READ),
114};
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
214static int is_cache_op_valid(u8 cache_type, u8 cache_op)
215{
216 if (hw_cache_stat[cache_type] & COP(cache_op))
217 return 1; /* valid */
218 else
219 return 0; /* invalid */
220}
221
222static char *event_cache_name(u8 cache_type, u8 cache_op, u8 cache_result)
223{
224 static char name[50];
225
226 if (cache_result) {
227 sprintf(name, "%s-%s-%s", hw_cache[cache_type][0],
228 hw_cache_op[cache_op][0],
229 hw_cache_result[cache_result][0]);
230 } else {
231 sprintf(name, "%s-%s", hw_cache[cache_type][0],
232 hw_cache_op[cache_op][1]);
233 }
234
235 return name;
236}
237
97char *event_name(int counter) 238char *event_name(int counter)
98{ 239{
99 u64 config = attrs[counter].config; 240 u64 config = attrs[counter].config;
100 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{
101 static char buf[32]; 248 static char buf[32];
102 249
103 if (attrs[counter].type == PERF_TYPE_RAW) { 250 if (type == PERF_TYPE_RAW) {
104 sprintf(buf, "raw 0x%llx", config); 251 sprintf(buf, "raw 0x%llx", config);
105 return buf; 252 return buf;
106 } 253 }
@@ -113,7 +260,6 @@ char *event_name(int counter)
113 260
114 case PERF_TYPE_HW_CACHE: { 261 case PERF_TYPE_HW_CACHE: {
115 u8 cache_type, cache_op, cache_result; 262 u8 cache_type, cache_op, cache_result;
116 static char name[100];
117 263
118 cache_type = (config >> 0) & 0xff; 264 cache_type = (config >> 0) & 0xff;
119 if (cache_type > PERF_COUNT_HW_CACHE_MAX) 265 if (cache_type > PERF_COUNT_HW_CACHE_MAX)
@@ -127,12 +273,10 @@ char *event_name(int counter)
127 if (cache_result > PERF_COUNT_HW_CACHE_RESULT_MAX) 273 if (cache_result > PERF_COUNT_HW_CACHE_RESULT_MAX)
128 return "unknown-ext-hardware-cache-result"; 274 return "unknown-ext-hardware-cache-result";
129 275
130 sprintf(name, "%s-Cache-%s-%ses", 276 if (!is_cache_op_valid(cache_type, cache_op))
131 hw_cache[cache_type][0], 277 return "invalid-cache";
132 hw_cache_op[cache_op][0],
133 hw_cache_result[cache_result][0]);
134 278
135 return name; 279 return event_cache_name(cache_type, cache_op, cache_result);
136 } 280 }
137 281
138 case PERF_TYPE_SOFTWARE: 282 case PERF_TYPE_SOFTWARE:
@@ -140,6 +284,9 @@ char *event_name(int counter)
140 return sw_event_names[config]; 284 return sw_event_names[config];
141 return "unknown-software"; 285 return "unknown-software";
142 286
287 case PERF_TYPE_TRACEPOINT:
288 return tracepoint_id_to_name(config);
289
143 default: 290 default:
144 break; 291 break;
145 } 292 }
@@ -147,43 +294,74 @@ char *event_name(int counter)
147 return "unknown"; 294 return "unknown";
148} 295}
149 296
150static 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)
151{ 298{
152 int i, j; 299 int i, j;
300 int n, longest = -1;
153 301
154 for (i = 0; i < size; i++) { 302 for (i = 0; i < size; i++) {
155 for (j = 0; j < MAX_ALIASES; j++) { 303 for (j = 0; j < MAX_ALIASES && names[i][j]; j++) {
156 if (!names[i][j]) 304 n = strlen(names[i][j]);
157 break; 305 if (n > longest && !strncasecmp(*str, names[i][j], n))
158 if (strcasestr(str, names[i][j])) 306 longest = n;
159 return i; 307 }
308 if (longest > 0) {
309 *str += longest;
310 return i;
160 } 311 }
161 } 312 }
162 313
163 return -1; 314 return -1;
164} 315}
165 316
166static int parse_generic_hw_symbols(const char *str, struct perf_counter_attr *attr) 317static int
318parse_generic_hw_event(const char **str, struct perf_counter_attr *attr)
167{ 319{
168 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;
169 322
170 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);
171 /* 324 /*
172 * No fallback - if we cannot get a clear cache type 325 * No fallback - if we cannot get a clear cache type
173 * then bail out: 326 * then bail out:
174 */ 327 */
175 if (cache_type == -1) 328 if (cache_type == -1)
176 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 }
177 358
178 cache_op = parse_aliases(str, hw_cache_op, PERF_COUNT_HW_CACHE_OP_MAX);
179 /* 359 /*
180 * Fall back to reads: 360 * Fall back to reads:
181 */ 361 */
182 if (cache_op == -1) 362 if (cache_op == -1)
183 cache_op = PERF_COUNT_HW_CACHE_OP_READ; 363 cache_op = PERF_COUNT_HW_CACHE_OP_READ;
184 364
185 cache_result = parse_aliases(str, hw_cache_result,
186 PERF_COUNT_HW_CACHE_RESULT_MAX);
187 /* 365 /*
188 * Fall back to accesses: 366 * Fall back to accesses:
189 */ 367 */
@@ -193,82 +371,212 @@ static int parse_generic_hw_symbols(const char *str, struct perf_counter_attr *a
193 attr->config = cache_type | (cache_op << 8) | (cache_result << 16); 371 attr->config = cache_type | (cache_op << 8) | (cache_result << 16);
194 attr->type = PERF_TYPE_HW_CACHE; 372 attr->type = PERF_TYPE_HW_CACHE;
195 373
196 return 0; 374 *str = s;
375 return 1;
197} 376}
198 377
199/* 378static int parse_tracepoint_event(const char **strp,
200 * Each event can have multiple symbolic names. 379 struct perf_counter_attr *attr)
201 * Symbolic names are (almost) exactly matched.
202 */
203static int parse_event_symbols(const char *str, struct perf_counter_attr *attr)
204{ 380{
205 u64 config, id; 381 const char *evt_name;
206 int type; 382 char *flags;
207 unsigned int i; 383 char sys_name[MAX_EVENT_LENGTH];
208 const char *sep, *pstr; 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;
209 392
210 if (str[0] == 'r' && hex2u64(str + 1, &config) > 0) { 393 evt_name = strchr(*strp, ':');
211 attr->type = PERF_TYPE_RAW; 394 if (!evt_name)
212 attr->config = config; 395 return 0;
213 396
397 sys_length = evt_name - *strp;
398 if (sys_length >= MAX_EVENT_LENGTH)
214 return 0; 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;
215 } 411 }
216 412
217 pstr = str; 413 evt_length = strlen(evt_name);
218 sep = strchr(pstr, ':'); 414 if (evt_length >= MAX_EVENT_LENGTH)
219 if (sep) { 415 return 0;
220 type = atoi(pstr);
221 pstr = sep + 1;
222 id = atoi(pstr);
223 sep = strchr(pstr, ':');
224 if (sep) {
225 pstr = sep + 1;
226 if (strchr(pstr, 'k'))
227 attr->exclude_user = 1;
228 if (strchr(pstr, 'u'))
229 attr->exclude_kernel = 1;
230 }
231 attr->type = type;
232 attr->config = id;
233 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);
234 return 0; 425 return 0;
235 } 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;
433}
236 434
237 for (i = 0; i < ARRAY_SIZE(event_symbols); i++) { 435static int check_events(const char *str, unsigned int i)
238 if (!strncmp(str, event_symbols[i].symbol, 436{
239 strlen(event_symbols[i].symbol))) { 437 int n;
438
439 n = strlen(event_symbols[i].symbol);
440 if (!strncmp(str, event_symbols[i].symbol, n))
441 return n;
442
443 n = strlen(event_symbols[i].alias);
444 if (n)
445 if (!strncmp(str, event_symbols[i].alias, n))
446 return n;
447 return 0;
448}
449
450static int
451parse_symbolic_event(const char **strp, struct perf_counter_attr *attr)
452{
453 const char *str = *strp;
454 unsigned int i;
455 int n;
240 456
457 for (i = 0; i < ARRAY_SIZE(event_symbols); i++) {
458 n = check_events(str, i);
459 if (n > 0) {
241 attr->type = event_symbols[i].type; 460 attr->type = event_symbols[i].type;
242 attr->config = event_symbols[i].config; 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;
474
475 if (*str != 'r')
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;
483 }
484 return 0;
485}
243 486
244 return 0; 487static int
488parse_numeric_event(const char **strp, struct perf_counter_attr *attr)
489{
490 const char *str = *strp;
491 char *endp;
492 unsigned long type;
493 u64 config;
494
495 type = strtoul(str, &endp, 0);
496 if (endp > str && type < PERF_TYPE_MAX && *endp == ':') {
497 str = endp + 1;
498 config = strtoul(str, &endp, 0);
499 if (endp > str) {
500 attr->type = type;
501 attr->config = config;
502 *strp = endp;
503 return 1;
245 } 504 }
246 } 505 }
506 return 0;
507}
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++ != ':')
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;
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}
537
538/*
539 * Each event can have multiple symbolic names.
540 * Symbolic names are (almost) exactly matched.
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;
247 550
248 return parse_generic_hw_symbols(str, attr); 551 parse_event_modifier(str, attr);
552
553 return 1;
249} 554}
250 555
251int 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)
252{ 557{
253 struct perf_counter_attr attr; 558 struct perf_counter_attr attr;
254 int ret;
255 559
256 memset(&attr, 0, sizeof(attr)); 560 for (;;) {
257again: 561 if (nr_counters == MAX_COUNTERS)
258 if (nr_counters == MAX_COUNTERS) 562 return -1;
259 return -1; 563
564 memset(&attr, 0, sizeof(attr));
565 if (!parse_event_symbols(&str, &attr))
566 return -1;
260 567
261 ret = parse_event_symbols(str, &attr); 568 if (!(*str == 0 || *str == ',' || isspace(*str)))
262 if (ret < 0) 569 return -1;
263 return ret;
264 570
265 attrs[nr_counters] = attr; 571 attrs[nr_counters] = attr;
266 nr_counters++; 572 nr_counters++;
267 573
268 str = strstr(str, ","); 574 if (*str == 0)
269 if (str) { 575 break;
270 str++; 576 if (*str == ',')
271 goto again; 577 ++str;
578 while (isspace(*str))
579 ++str;
272 } 580 }
273 581
274 return 0; 582 return 0;
@@ -283,34 +591,92 @@ static const char * const event_type_descriptors[] = {
283}; 591};
284 592
285/* 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/*
286 * Print the help text for the event symbols: 630 * Print the help text for the event symbols:
287 */ 631 */
288void print_events(void) 632void print_events(void)
289{ 633{
290 struct event_symbol *syms = event_symbols; 634 struct event_symbol *syms = event_symbols;
291 unsigned int i, type, prev_type = -1; 635 unsigned int i, type, op, prev_type = -1;
636 char name[40];
292 637
293 fprintf(stderr, "\n"); 638 fprintf(stderr, "\n");
294 fprintf(stderr, "List of pre-defined events (to be used in -e):\n"); 639 fprintf(stderr, "List of pre-defined events (to be used in -e):\n");
295 640
296 for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) { 641 for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
297 type = syms->type + 1; 642 type = syms->type + 1;
298 if (type > ARRAY_SIZE(event_type_descriptors)) 643 if (type >= ARRAY_SIZE(event_type_descriptors))
299 type = 0; 644 type = 0;
300 645
301 if (type != prev_type) 646 if (type != prev_type)
302 fprintf(stderr, "\n"); 647 fprintf(stderr, "\n");
303 648
304 fprintf(stderr, " %-30s [%s]\n", syms->symbol, 649 if (strlen(syms->alias))
650 sprintf(name, "%s OR %s", syms->symbol, syms->alias);
651 else
652 strcpy(name, syms->symbol);
653 fprintf(stderr, " %-40s [%s]\n", name,
305 event_type_descriptors[type]); 654 event_type_descriptors[type]);
306 655
307 prev_type = type; 656 prev_type = type;
308 } 657 }
309 658
310 fprintf(stderr, "\n"); 659 fprintf(stderr, "\n");
311 fprintf(stderr, " %-30s [raw hardware event descriptor]\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");
675 fprintf(stderr, " %-40s [raw hardware event descriptor]\n",
312 "rNNN"); 676 "rNNN");
313 fprintf(stderr, "\n"); 677 fprintf(stderr, "\n");
314 678
679 print_tracepoint_events();
680
315 exit(129); 681 exit(129);
316} 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/run-command.c b/tools/perf/util/run-command.c
index b2f5e854f40a..a3935343091a 100644
--- a/tools/perf/util/run-command.c
+++ b/tools/perf/util/run-command.c
@@ -65,7 +65,6 @@ int start_command(struct child_process *cmd)
65 cmd->err = fderr[0]; 65 cmd->err = fderr[0];
66 } 66 }
67 67
68#ifndef __MINGW32__
69 fflush(NULL); 68 fflush(NULL);
70 cmd->pid = fork(); 69 cmd->pid = fork();
71 if (!cmd->pid) { 70 if (!cmd->pid) {
@@ -118,71 +117,6 @@ int start_command(struct child_process *cmd)
118 } 117 }
119 exit(127); 118 exit(127);
120 } 119 }
121#else
122 int s0 = -1, s1 = -1, s2 = -1; /* backups of stdin, stdout, stderr */
123 const char **sargv = cmd->argv;
124 char **env = environ;
125
126 if (cmd->no_stdin) {
127 s0 = dup(0);
128 dup_devnull(0);
129 } else if (need_in) {
130 s0 = dup(0);
131 dup2(fdin[0], 0);
132 } else if (cmd->in) {
133 s0 = dup(0);
134 dup2(cmd->in, 0);
135 }
136
137 if (cmd->no_stderr) {
138 s2 = dup(2);
139 dup_devnull(2);
140 } else if (need_err) {
141 s2 = dup(2);
142 dup2(fderr[1], 2);
143 }
144
145 if (cmd->no_stdout) {
146 s1 = dup(1);
147 dup_devnull(1);
148 } else if (cmd->stdout_to_stderr) {
149 s1 = dup(1);
150 dup2(2, 1);
151 } else if (need_out) {
152 s1 = dup(1);
153 dup2(fdout[1], 1);
154 } else if (cmd->out > 1) {
155 s1 = dup(1);
156 dup2(cmd->out, 1);
157 }
158
159 if (cmd->dir)
160 die("chdir in start_command() not implemented");
161 if (cmd->env) {
162 env = copy_environ();
163 for (; *cmd->env; cmd->env++)
164 env = env_setenv(env, *cmd->env);
165 }
166
167 if (cmd->perf_cmd) {
168 cmd->argv = prepare_perf_cmd(cmd->argv);
169 }
170
171 cmd->pid = mingw_spawnvpe(cmd->argv[0], cmd->argv, env);
172
173 if (cmd->env)
174 free_environ(env);
175 if (cmd->perf_cmd)
176 free(cmd->argv);
177
178 cmd->argv = sargv;
179 if (s0 >= 0)
180 dup2(s0, 0), close(s0);
181 if (s1 >= 0)
182 dup2(s1, 1), close(s1);
183 if (s2 >= 0)
184 dup2(s2, 2), close(s2);
185#endif
186 120
187 if (cmd->pid < 0) { 121 if (cmd->pid < 0) {
188 int err = errno; 122 int err = errno;
@@ -288,14 +222,6 @@ int run_command_v_opt_cd_env(const char **argv, int opt, const char *dir, const
288 return run_command(&cmd); 222 return run_command(&cmd);
289} 223}
290 224
291#ifdef __MINGW32__
292static __stdcall unsigned run_thread(void *data)
293{
294 struct async *async = data;
295 return async->proc(async->fd_for_proc, async->data);
296}
297#endif
298
299int start_async(struct async *async) 225int start_async(struct async *async)
300{ 226{
301 int pipe_out[2]; 227 int pipe_out[2];
@@ -304,7 +230,6 @@ int start_async(struct async *async)
304 return error("cannot create pipe: %s", strerror(errno)); 230 return error("cannot create pipe: %s", strerror(errno));
305 async->out = pipe_out[0]; 231 async->out = pipe_out[0];
306 232
307#ifndef __MINGW32__
308 /* Flush stdio before fork() to avoid cloning buffers */ 233 /* Flush stdio before fork() to avoid cloning buffers */
309 fflush(NULL); 234 fflush(NULL);
310 235
@@ -319,33 +244,17 @@ int start_async(struct async *async)
319 exit(!!async->proc(pipe_out[1], async->data)); 244 exit(!!async->proc(pipe_out[1], async->data));
320 } 245 }
321 close(pipe_out[1]); 246 close(pipe_out[1]);
322#else 247
323 async->fd_for_proc = pipe_out[1];
324 async->tid = (HANDLE) _beginthreadex(NULL, 0, run_thread, async, 0, NULL);
325 if (!async->tid) {
326 error("cannot create thread: %s", strerror(errno));
327 close_pair(pipe_out);
328 return -1;
329 }
330#endif
331 return 0; 248 return 0;
332} 249}
333 250
334int finish_async(struct async *async) 251int finish_async(struct async *async)
335{ 252{
336#ifndef __MINGW32__
337 int ret = 0; 253 int ret = 0;
338 254
339 if (wait_or_whine(async->pid)) 255 if (wait_or_whine(async->pid))
340 ret = error("waitpid (async) failed"); 256 ret = error("waitpid (async) failed");
341#else 257
342 DWORD ret = 0;
343 if (WaitForSingleObject(async->tid, INFINITE) != WAIT_OBJECT_0)
344 ret = error("waiting for thread failed: %lu", GetLastError());
345 else if (!GetExitCodeThread(async->tid, &ret))
346 ret = error("cannot get thread exit code: %lu", GetLastError());
347 CloseHandle(async->tid);
348#endif
349 return ret; 258 return ret;
350} 259}
351 260
diff --git a/tools/perf/util/run-command.h b/tools/perf/util/run-command.h
index 328289f23669..cc1837deba88 100644
--- a/tools/perf/util/run-command.h
+++ b/tools/perf/util/run-command.h
@@ -79,12 +79,7 @@ struct async {
79 int (*proc)(int fd, void *data); 79 int (*proc)(int fd, void *data);
80 void *data; 80 void *data;
81 int out; /* caller reads from here and closes it */ 81 int out; /* caller reads from here and closes it */
82#ifndef __MINGW32__
83 pid_t pid; 82 pid_t pid;
84#else
85 HANDLE tid;
86 int fd_for_proc;
87#endif
88}; 83};
89 84
90int start_async(struct async *async); 85int start_async(struct async *async);
diff --git a/tools/perf/util/strbuf.c b/tools/perf/util/strbuf.c
index eaba09306802..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}
@@ -259,12 +260,12 @@ size_t strbuf_fread(struct strbuf *sb, size_t size, FILE *f)
259 res = fread(sb->buf + sb->len, 1, size, f); 260 res = fread(sb->buf + sb->len, 1, size, f);
260 if (res > 0) 261 if (res > 0)
261 strbuf_setlen(sb, sb->len + res); 262 strbuf_setlen(sb, sb->len + res);
262 else if (res < 0 && oldalloc == 0) 263 else if (oldalloc == 0)
263 strbuf_release(sb); 264 strbuf_release(sb);
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 37b03255b425..bf39dfadfd24 100644
--- a/tools/perf/util/string.h
+++ b/tools/perf/util/string.h
@@ -1,8 +1,11 @@
1#ifndef _PERF_STRING_H_ 1#ifndef _PERF_STRING_H_
2#define _PERF_STRING_H_ 2#define _PERF_STRING_H_
3 3
4#include "../types.h" 4#include "types.h"
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
new file mode 100644
index 000000000000..7ad38171dc2b
--- /dev/null
+++ b/tools/perf/util/strlist.c
@@ -0,0 +1,200 @@
1/*
2 * (c) 2009 Arnaldo Carvalho de Melo <acme@redhat.com>
3 *
4 * Licensed under the GPLv2.
5 */
6
7#include "strlist.h"
8#include <errno.h>
9#include <stdio.h>
10#include <stdlib.h>
11#include <string.h>
12
13static struct str_node *str_node__new(const char *s, bool dupstr)
14{
15 struct str_node *self = malloc(sizeof(*self));
16
17 if (self != NULL) {
18 if (dupstr) {
19 s = strdup(s);
20 if (s == NULL)
21 goto out_delete;
22 }
23 self->s = s;
24 }
25
26 return self;
27
28out_delete:
29 free(self);
30 return NULL;
31}
32
33static void str_node__delete(struct str_node *self, bool dupstr)
34{
35 if (dupstr)
36 free((void *)self->s);
37 free(self);
38}
39
40int strlist__add(struct strlist *self, const char *new_entry)
41{
42 struct rb_node **p = &self->entries.rb_node;
43 struct rb_node *parent = NULL;
44 struct str_node *sn;
45
46 while (*p != NULL) {
47 int rc;
48
49 parent = *p;
50 sn = rb_entry(parent, struct str_node, rb_node);
51 rc = strcmp(sn->s, new_entry);
52
53 if (rc > 0)
54 p = &(*p)->rb_left;
55 else if (rc < 0)
56 p = &(*p)->rb_right;
57 else
58 return -EEXIST;
59 }
60
61 sn = str_node__new(new_entry, self->dupstr);
62 if (sn == NULL)
63 return -ENOMEM;
64
65 rb_link_node(&sn->rb_node, parent, p);
66 rb_insert_color(&sn->rb_node, &self->entries);
67 ++self->nr_entries;
68
69 return 0;
70}
71
72int strlist__load(struct strlist *self, const char *filename)
73{
74 char entry[1024];
75 int err;
76 FILE *fp = fopen(filename, "r");
77
78 if (fp == NULL)
79 return errno;
80
81 while (fgets(entry, sizeof(entry), fp) != NULL) {
82 const size_t len = strlen(entry);
83
84 if (len == 0)
85 continue;
86 entry[len - 1] = '\0';
87
88 err = strlist__add(self, entry);
89 if (err != 0)
90 goto out;
91 }
92
93 err = 0;
94out:
95 fclose(fp);
96 return err;
97}
98
99void strlist__remove(struct strlist *self, struct str_node *sn)
100{
101 rb_erase(&sn->rb_node, &self->entries);
102 str_node__delete(sn, self->dupstr);
103}
104
105bool strlist__has_entry(struct strlist *self, const char *entry)
106{
107 struct rb_node **p = &self->entries.rb_node;
108 struct rb_node *parent = NULL;
109
110 while (*p != NULL) {
111 struct str_node *sn;
112 int rc;
113
114 parent = *p;
115 sn = rb_entry(parent, struct str_node, rb_node);
116 rc = strcmp(sn->s, entry);
117
118 if (rc > 0)
119 p = &(*p)->rb_left;
120 else if (rc < 0)
121 p = &(*p)->rb_right;
122 else
123 return true;
124 }
125
126 return false;
127}
128
129static int strlist__parse_list_entry(struct strlist *self, const char *s)
130{
131 if (strncmp(s, "file://", 7) == 0)
132 return strlist__load(self, s + 7);
133
134 return strlist__add(self, s);
135}
136
137int strlist__parse_list(struct strlist *self, const char *s)
138{
139 char *sep;
140 int err;
141
142 while ((sep = strchr(s, ',')) != NULL) {
143 *sep = '\0';
144 err = strlist__parse_list_entry(self, s);
145 *sep = ',';
146 if (err != 0)
147 return err;
148 s = sep + 1;
149 }
150
151 return *s ? strlist__parse_list_entry(self, s) : 0;
152}
153
154struct strlist *strlist__new(bool dupstr, const char *slist)
155{
156 struct strlist *self = malloc(sizeof(*self));
157
158 if (self != NULL) {
159 self->entries = RB_ROOT;
160 self->dupstr = dupstr;
161 self->nr_entries = 0;
162 if (slist && strlist__parse_list(self, slist) != 0)
163 goto out_error;
164 }
165
166 return self;
167out_error:
168 free(self);
169 return NULL;
170}
171
172void strlist__delete(struct strlist *self)
173{
174 if (self != NULL) {
175 struct str_node *pos;
176 struct rb_node *next = rb_first(&self->entries);
177
178 while (next) {
179 pos = rb_entry(next, struct str_node, rb_node);
180 next = rb_next(&pos->rb_node);
181 strlist__remove(self, pos);
182 }
183 self->entries = RB_ROOT;
184 free(self);
185 }
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
new file mode 100644
index 000000000000..921818e44a54
--- /dev/null
+++ b/tools/perf/util/strlist.h
@@ -0,0 +1,39 @@
1#ifndef STRLIST_H_
2#define STRLIST_H_
3
4#include <linux/rbtree.h>
5#include <stdbool.h>
6
7struct str_node {
8 struct rb_node rb_node;
9 const char *s;
10};
11
12struct strlist {
13 struct rb_root entries;
14 unsigned int nr_entries;
15 bool dupstr;
16};
17
18struct strlist *strlist__new(bool dupstr, const char *slist);
19void strlist__delete(struct strlist *self);
20
21void strlist__remove(struct strlist *self, struct str_node *sn);
22int strlist__load(struct strlist *self, const char *filename);
23int strlist__add(struct strlist *self, const char *str);
24
25struct str_node *strlist__entry(const struct strlist *self, unsigned int idx);
26bool strlist__has_entry(struct strlist *self, const char *entry);
27
28static inline bool strlist__empty(const struct strlist *self)
29{
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;
36}
37
38int strlist__parse_list(struct strlist *self, const char *s);
39#endif /* STRLIST_H_ */
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 86e14375e74e..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,15 +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));
579 if (!kernel) {
580 self->adjust_symbols = (ehdr.e_type == ET_EXEC ||
581 elf_section_by_name(elf, &ehdr, &shdr,
582 ".gnu.prelink_undo",
583 NULL) != NULL);
584 } else self->adjust_symbols = 0;
523 585
524 elf_symtab__for_each_symbol(syms, nr_syms, index, sym) { 586 elf_symtab__for_each_symbol(syms, nr_syms, index, sym) {
525 struct symbol *f; 587 struct symbol *f;
588 const char *name;
589 char *demangled;
526 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;
527 594
528 if (!elf_sym__is_function(&sym)) 595 if (!is_label && !elf_sym__is_function(&sym))
529 continue; 596 continue;
530 597
531 sec = elf_getscn(elf, sym.st_shndx); 598 sec = elf_getscn(elf, sym.st_shndx);
@@ -533,19 +600,51 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
533 goto out_elf_end; 600 goto out_elf_end;
534 601
535 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);
536 obj_start = sym.st_value; 608 obj_start = sym.st_value;
537 609
538 sym.st_value -= shdr.sh_addr - shdr.sh_offset; 610 if (self->adjust_symbols) {
611 if (verbose >= 2)
612 printf("adjusting symbol: st_value: %Lx sh_addr: %Lx sh_offset: %Lx\n",
613 (u64)sym.st_value, (u64)shdr.sh_addr, (u64)shdr.sh_offset);
614
615 sym.st_value -= shdr.sh_addr - shdr.sh_offset;
616 }
617
618 if (mod) {
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;
539 637
540 f = symbol__new(sym.st_value, sym.st_size, 638 f = symbol__new(sym.st_value, sym.st_size, name,
541 elf_sym__name(&sym, symstrs),
542 self->sym_priv_size, obj_start, verbose); 639 self->sym_priv_size, obj_start, verbose);
640 free(demangled);
543 if (!f) 641 if (!f)
544 goto out_elf_end; 642 goto out_elf_end;
545 643
546 if (filter && filter(self, f)) 644 if (filter && filter(self, f))
547 symbol__delete(f, self->sym_priv_size); 645 symbol__delete(f, self->sym_priv_size);
548 else { 646 else {
647 f->module = mod;
549 dso__insert_symbol(self, f); 648 dso__insert_symbol(self, f);
550 nr++; 649 nr++;
551 } 650 }
@@ -558,42 +657,135 @@ out_close:
558 return err; 657 return err;
559} 658}
560 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
561int dso__load(struct dso *self, symbol_filter_t filter, int verbose) 735int dso__load(struct dso *self, symbol_filter_t filter, int verbose)
562{ 736{
563 int size = strlen(self->name) + sizeof("/usr/lib/debug%s.debug"); 737 int size = PATH_MAX;
564 char *name = malloc(size); 738 char *name = malloc(size), *build_id = NULL;
565 int variant = 0;
566 int ret = -1; 739 int ret = -1;
567 int fd; 740 int fd;
568 741
569 if (!name) 742 if (!name)
570 return -1; 743 return -1;
571 744
572 if (strncmp(self->name, "/tmp/perf-", 10) == 0) 745 self->adjust_symbols = 0;
573 return dso__load_perf_map(self, filter, verbose); 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 }
753
754 self->origin = DSO__ORIG_FEDORA - 1;
574 755
575more: 756more:
576 do { 757 do {
577 switch (variant) { 758 self->origin++;
578 case 0: /* Fedora */ 759 switch (self->origin) {
760 case DSO__ORIG_FEDORA:
579 snprintf(name, size, "/usr/lib/debug%s.debug", self->name); 761 snprintf(name, size, "/usr/lib/debug%s.debug", self->name);
580 break; 762 break;
581 case 1: /* Ubuntu */ 763 case DSO__ORIG_UBUNTU:
582 snprintf(name, size, "/usr/lib/debug%s", self->name); 764 snprintf(name, size, "/usr/lib/debug%s", self->name);
583 break; 765 break;
584 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:
585 snprintf(name, size, "%s", self->name); 778 snprintf(name, size, "%s", self->name);
586 break; 779 break;
587 780
588 default: 781 default:
589 goto out; 782 goto out;
590 } 783 }
591 variant++;
592 784
593 fd = open(name, O_RDONLY); 785 fd = open(name, O_RDONLY);
594 } while (fd < 0); 786 } while (fd < 0);
595 787
596 ret = dso__load_sym(self, fd, name, filter, verbose); 788 ret = dso__load_sym(self, fd, name, filter, verbose, NULL);
597 close(fd); 789 close(fd);
598 790
599 /* 791 /*
@@ -602,11 +794,98 @@ more:
602 if (!ret) 794 if (!ret)
603 goto more; 795 goto more;
604 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 }
605out: 802out:
606 free(name); 803 free(name);
804 if (ret < 0 && strstr(self->name, " (deleted)") != NULL)
805 return 0;
607 return ret; 806 return ret;
608} 807}
609 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
610static int dso__load_vmlinux(struct dso *self, const char *vmlinux, 889static int dso__load_vmlinux(struct dso *self, const char *vmlinux,
611 symbol_filter_t filter, int verbose) 890 symbol_filter_t filter, int verbose)
612{ 891{
@@ -615,23 +894,33 @@ static int dso__load_vmlinux(struct dso *self, const char *vmlinux,
615 if (fd < 0) 894 if (fd < 0)
616 return -1; 895 return -1;
617 896
618 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
619 close(fd); 902 close(fd);
620 903
621 return err; 904 return err;
622} 905}
623 906
624int dso__load_kernel(struct dso *self, const char *vmlinux, 907int dso__load_kernel(struct dso *self, const char *vmlinux,
625 symbol_filter_t filter, int verbose) 908 symbol_filter_t filter, int verbose, int modules)
626{ 909{
627 int err = -1; 910 int err = -1;
628 911
629 if (vmlinux) 912 if (vmlinux) {
630 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 }
631 917
632 if (err) 918 if (err <= 0)
633 err = dso__load_kallsyms(self, filter, verbose); 919 err = dso__load_kallsyms(self, filter, verbose);
634 920
921 if (err > 0)
922 self->origin = DSO__ORIG_KERNEL;
923
635 return err; 924 return err;
636} 925}
637 926
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index ea332e56e458..b53bf0125c1b 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -2,9 +2,34 @@
2#define _PERF_SYMBOL_ 1 2#define _PERF_SYMBOL_ 1
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};
@@ -20,8 +46,11 @@ struct symbol {
20struct dso { 46struct dso {
21 struct list_head node; 47 struct list_head node;
22 struct rb_root syms; 48 struct rb_root syms;
23 unsigned int sym_priv_size;
24 struct symbol *(*find_symbol)(struct dso *, u64 ip); 49 struct symbol *(*find_symbol)(struct dso *, u64 ip);
50 unsigned int sym_priv_size;
51 unsigned char adjust_symbols;
52 unsigned char slen_calculated;
53 unsigned char origin;
25 char name[0]; 54 char name[0];
26}; 55};
27 56
@@ -40,10 +69,12 @@ static inline void *dso__sym_priv(struct dso *self, struct symbol *sym)
40struct symbol *dso__find_symbol(struct dso *self, u64 ip); 69struct symbol *dso__find_symbol(struct dso *self, u64 ip);
41 70
42int dso__load_kernel(struct dso *self, const char *vmlinux, 71int dso__load_kernel(struct dso *self, const char *vmlinux,
43 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);
44int dso__load(struct dso *self, symbol_filter_t filter, int verbose); 74int dso__load(struct dso *self, symbol_filter_t filter, int verbose);
45 75
46size_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);
47 78
48void symbol__init(void); 79void symbol__init(void);
49#endif /* _PERF_SYMBOL_ */ 80#endif /* _PERF_SYMBOL_ */
diff --git a/tools/perf/types.h b/tools/perf/util/types.h
index 5e75f9005940..5e75f9005940 100644
--- a/tools/perf/types.h
+++ b/tools/perf/util/types.h
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index b8cfed776d81..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>
@@ -67,7 +68,6 @@
67#include <assert.h> 68#include <assert.h>
68#include <regex.h> 69#include <regex.h>
69#include <utime.h> 70#include <utime.h>
70#ifndef __MINGW32__
71#include <sys/wait.h> 71#include <sys/wait.h>
72#include <sys/poll.h> 72#include <sys/poll.h>
73#include <sys/socket.h> 73#include <sys/socket.h>
@@ -81,20 +81,7 @@
81#include <netdb.h> 81#include <netdb.h>
82#include <pwd.h> 82#include <pwd.h>
83#include <inttypes.h> 83#include <inttypes.h>
84#if defined(__CYGWIN__) 84#include "../../../include/linux/magic.h"
85#undef _XOPEN_SOURCE
86#include <grp.h>
87#define _XOPEN_SOURCE 600
88#include "compat/cygwin.h"
89#else
90#undef _ALL_SOURCE /* AIX 5.3L defines a struct list with _ALL_SOURCE. */
91#include <grp.h>
92#define _ALL_SOURCE 1
93#endif
94#else /* __MINGW32__ */
95/* pull in Windows compatibility stuff */
96#include "compat/mingw.h"
97#endif /* __MINGW32__ */
98 85
99#ifndef NO_ICONV 86#ifndef NO_ICONV
100#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)