aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/lib/traceevent/Makefile18
-rw-r--r--tools/perf/.gitignore1
-rw-r--r--tools/perf/Documentation/Makefile79
-rw-r--r--tools/perf/Documentation/perf-buildid-cache.txt13
-rw-r--r--tools/perf/Documentation/perf-kvm.txt4
-rw-r--r--tools/perf/Documentation/perf-lock.txt2
-rw-r--r--tools/perf/Documentation/perf-record.txt4
-rw-r--r--tools/perf/Documentation/perf-timechart.txt15
-rw-r--r--tools/perf/Documentation/perf-top.txt4
-rw-r--r--tools/perf/Documentation/perf-trace.txt27
-rw-r--r--tools/perf/Makefile848
-rw-r--r--tools/perf/Makefile.perf887
-rw-r--r--tools/perf/arch/x86/include/perf_regs.h6
-rw-r--r--tools/perf/arch/x86/util/unwind.c4
-rw-r--r--tools/perf/bash_completion106
-rw-r--r--tools/perf/bench/mem-memcpy-arch.h2
-rw-r--r--tools/perf/bench/mem-memcpy.c2
-rw-r--r--tools/perf/bench/mem-memset-arch.h2
-rw-r--r--tools/perf/bench/mem-memset.c2
-rw-r--r--tools/perf/bench/numa.c34
-rw-r--r--tools/perf/bench/sched-pipe.c115
-rw-r--r--tools/perf/builtin-annotate.c26
-rw-r--r--tools/perf/builtin-bench.c4
-rw-r--r--tools/perf/builtin-buildid-cache.c148
-rw-r--r--tools/perf/builtin-inject.c2
-rw-r--r--tools/perf/builtin-kvm.c5
-rw-r--r--tools/perf/builtin-lock.c124
-rw-r--r--tools/perf/builtin-probe.c14
-rw-r--r--tools/perf/builtin-record.c26
-rw-r--r--tools/perf/builtin-report.c16
-rw-r--r--tools/perf/builtin-stat.c29
-rw-r--r--tools/perf/builtin-top.c7
-rw-r--r--tools/perf/builtin-trace.c1108
-rw-r--r--tools/perf/config/Makefile358
-rw-r--r--tools/perf/config/feature-checks/Makefile144
-rw-r--r--tools/perf/config/feature-checks/test-all.c106
-rw-r--r--tools/perf/config/feature-checks/test-backtrace.c13
-rw-r--r--tools/perf/config/feature-checks/test-bionic.c6
-rw-r--r--tools/perf/config/feature-checks/test-cplus-demangle.c14
-rw-r--r--tools/perf/config/feature-checks/test-dwarf.c10
-rw-r--r--tools/perf/config/feature-checks/test-fortify-source.c6
-rw-r--r--tools/perf/config/feature-checks/test-glibc.c8
-rw-r--r--tools/perf/config/feature-checks/test-gtk2-infobar.c11
-rw-r--r--tools/perf/config/feature-checks/test-gtk2.c10
-rw-r--r--tools/perf/config/feature-checks/test-hello.c6
-rw-r--r--tools/perf/config/feature-checks/test-libaudit.c10
-rw-r--r--tools/perf/config/feature-checks/test-libbfd.c15
-rw-r--r--tools/perf/config/feature-checks/test-libelf-getphdrnum.c8
-rw-r--r--tools/perf/config/feature-checks/test-libelf-mmap.c8
-rw-r--r--tools/perf/config/feature-checks/test-libelf.c8
-rw-r--r--tools/perf/config/feature-checks/test-libnuma.c9
-rw-r--r--tools/perf/config/feature-checks/test-libperl.c9
-rw-r--r--tools/perf/config/feature-checks/test-libpython-version.c10
-rw-r--r--tools/perf/config/feature-checks/test-libpython.c8
-rw-r--r--tools/perf/config/feature-checks/test-libslang.c6
-rw-r--r--tools/perf/config/feature-checks/test-libunwind.c27
-rw-r--r--tools/perf/config/feature-checks/test-on-exit.c15
-rw-r--r--tools/perf/config/feature-checks/test-stackprotector-all.c6
-rw-r--r--tools/perf/config/feature-checks/test-stackprotector.c6
-rw-r--r--tools/perf/config/feature-checks/test-volatile-register-var.c6
-rw-r--r--tools/perf/config/feature-tests.mak246
-rw-r--r--tools/perf/config/utilities.mak17
-rw-r--r--tools/perf/perf.c14
-rw-r--r--tools/perf/tests/dso-data.c1
-rw-r--r--tools/perf/tests/perf-record.c12
-rw-r--r--tools/perf/tests/task-exit.c14
-rw-r--r--tools/perf/ui/browsers/annotate.c24
-rw-r--r--tools/perf/ui/gtk/annotate.c13
-rw-r--r--tools/perf/ui/gtk/browser.c2
-rw-r--r--tools/perf/ui/gtk/gtk.h20
-rw-r--r--tools/perf/ui/gtk/util.c4
-rw-r--r--tools/perf/ui/setup.c61
-rw-r--r--tools/perf/ui/ui.h14
-rwxr-xr-xtools/perf/util/PERF-VERSION-GEN2
-rw-r--r--tools/perf/util/annotate.c76
-rw-r--r--tools/perf/util/annotate.h26
-rw-r--r--tools/perf/util/cache.h3
-rw-r--r--tools/perf/util/dso.c50
-rw-r--r--tools/perf/util/dso.h3
-rw-r--r--tools/perf/util/event.h10
-rw-r--r--tools/perf/util/evlist.c82
-rw-r--r--tools/perf/util/evlist.h9
-rw-r--r--tools/perf/util/evsel.c3
-rwxr-xr-xtools/perf/util/generate-cmdlist.sh4
-rw-r--r--tools/perf/util/hist.c1
-rw-r--r--tools/perf/util/hist.h17
-rw-r--r--tools/perf/util/include/dwarf-regs.h2
-rw-r--r--tools/perf/util/include/linux/compiler.h19
-rw-r--r--tools/perf/util/intlist.c23
-rw-r--r--tools/perf/util/intlist.h2
-rw-r--r--tools/perf/util/machine.c113
-rw-r--r--tools/perf/util/machine.h5
-rw-r--r--tools/perf/util/map.c50
-rw-r--r--tools/perf/util/map.h7
-rw-r--r--tools/perf/util/parse-events.l63
-rw-r--r--tools/perf/util/path.c10
-rw-r--r--tools/perf/util/perf_regs.h4
-rw-r--r--tools/perf/util/probe-event.c4
-rw-r--r--tools/perf/util/probe-finder.h4
-rw-r--r--tools/perf/util/python.c8
-rw-r--r--tools/perf/util/rblist.c27
-rw-r--r--tools/perf/util/rblist.h1
-rw-r--r--tools/perf/util/session.c13
-rw-r--r--tools/perf/util/sort.c58
-rw-r--r--tools/perf/util/srcline.c265
-rw-r--r--tools/perf/util/symbol-elf.c607
-rw-r--r--tools/perf/util/symbol-minimal.c15
-rw-r--r--tools/perf/util/symbol.c449
-rw-r--r--tools/perf/util/symbol.h29
-rw-r--r--tools/perf/util/trace-event-parse.c36
-rw-r--r--tools/perf/util/trace-event.h9
-rw-r--r--tools/perf/util/unwind.h4
-rw-r--r--tools/perf/util/util.c47
-rw-r--r--tools/perf/util/util.h24
-rw-r--r--tools/scripts/Makefile.include23
115 files changed, 5144 insertions, 2032 deletions
diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile
index ca6cb779876a..fc1502098595 100644
--- a/tools/lib/traceevent/Makefile
+++ b/tools/lib/traceevent/Makefile
@@ -134,14 +134,14 @@ ifeq ($(VERBOSE),1)
134 print_install = 134 print_install =
135else 135else
136 Q = @ 136 Q = @
137 print_compile = echo ' CC '$(OBJ); 137 print_compile = echo ' CC '$(OBJ);
138 print_app_build = echo ' BUILD '$(OBJ); 138 print_app_build = echo ' BUILD '$(OBJ);
139 print_fpic_compile = echo ' CC FPIC '$(OBJ); 139 print_fpic_compile = echo ' CC FPIC '$(OBJ);
140 print_shared_lib_compile = echo ' BUILD SHARED LIB '$(OBJ); 140 print_shared_lib_compile = echo ' BUILD SHARED LIB '$(OBJ);
141 print_plugin_obj_compile = echo ' CC PLUGIN OBJ '$(OBJ); 141 print_plugin_obj_compile = echo ' BUILD PLUGIN OBJ '$(OBJ);
142 print_plugin_build = echo ' CC PLUGI '$(OBJ); 142 print_plugin_build = echo ' BUILD PLUGIN '$(OBJ);
143 print_static_lib_build = echo ' BUILD STATIC LIB '$(OBJ); 143 print_static_lib_build = echo ' BUILD STATIC LIB '$(OBJ);
144 print_install = echo ' INSTALL '$1' to $(DESTDIR_SQ)$2'; 144 print_install = echo ' INSTALL '$1' to $(DESTDIR_SQ)$2';
145endif 145endif
146 146
147do_fpic_compile = \ 147do_fpic_compile = \
@@ -268,7 +268,7 @@ TRACK_CFLAGS = $(subst ','\'',$(CFLAGS)):$(ARCH):$(CROSS_COMPILE)
268TRACEEVENT-CFLAGS: force 268TRACEEVENT-CFLAGS: force
269 @FLAGS='$(TRACK_CFLAGS)'; \ 269 @FLAGS='$(TRACK_CFLAGS)'; \
270 if test x"$$FLAGS" != x"`cat TRACEEVENT-CFLAGS 2>/dev/null`" ; then \ 270 if test x"$$FLAGS" != x"`cat TRACEEVENT-CFLAGS 2>/dev/null`" ; then \
271 echo 1>&2 " * new build flags or cross compiler"; \ 271 echo 1>&2 " FLAGS: * new build flags or cross compiler"; \
272 echo "$$FLAGS" >TRACEEVENT-CFLAGS; \ 272 echo "$$FLAGS" >TRACEEVENT-CFLAGS; \
273 fi 273 fi
274 274
diff --git a/tools/perf/.gitignore b/tools/perf/.gitignore
index 8f8fbc227a46..782d86e961b9 100644
--- a/tools/perf/.gitignore
+++ b/tools/perf/.gitignore
@@ -13,6 +13,7 @@ perf*.html
13common-cmds.h 13common-cmds.h
14perf.data 14perf.data
15perf.data.old 15perf.data.old
16output.svg
16perf-archive 17perf-archive
17tags 18tags
18TAGS 19TAGS
diff --git a/tools/perf/Documentation/Makefile b/tools/perf/Documentation/Makefile
index 5a37a7c84e69..3ba1c0b09908 100644
--- a/tools/perf/Documentation/Makefile
+++ b/tools/perf/Documentation/Makefile
@@ -145,16 +145,17 @@ endif
145 145
146ifneq ($(findstring $(MAKEFLAGS),s),s) 146ifneq ($(findstring $(MAKEFLAGS),s),s)
147ifneq ($(V),1) 147ifneq ($(V),1)
148 QUIET_ASCIIDOC = @echo ' ' ASCIIDOC $@; 148 QUIET_ASCIIDOC = @echo ' ASCIIDOC '$@;
149 QUIET_XMLTO = @echo ' ' XMLTO $@; 149 QUIET_XMLTO = @echo ' XMLTO '$@;
150 QUIET_DB2TEXI = @echo ' ' DB2TEXI $@; 150 QUIET_DB2TEXI = @echo ' DB2TEXI '$@;
151 QUIET_MAKEINFO = @echo ' ' MAKEINFO $@; 151 QUIET_MAKEINFO = @echo ' MAKEINFO '$@;
152 QUIET_DBLATEX = @echo ' ' DBLATEX $@; 152 QUIET_DBLATEX = @echo ' DBLATEX '$@;
153 QUIET_XSLTPROC = @echo ' ' XSLTPROC $@; 153 QUIET_XSLTPROC = @echo ' XSLTPROC '$@;
154 QUIET_GEN = @echo ' ' GEN $@; 154 QUIET_GEN = @echo ' GEN '$@;
155 QUIET_STDERR = 2> /dev/null 155 QUIET_STDERR = 2> /dev/null
156 QUIET_SUBDIR0 = +@subdir= 156 QUIET_SUBDIR0 = +@subdir=
157 QUIET_SUBDIR1 = ;$(NO_SUBDIR) echo ' ' SUBDIR $$subdir; \ 157 QUIET_SUBDIR1 = ;$(NO_SUBDIR) \
158 echo ' SUBDIR ' $$subdir; \
158 $(MAKE) $(PRINT_DIR) -C $$subdir 159 $(MAKE) $(PRINT_DIR) -C $$subdir
159 export V 160 export V
160endif 161endif
@@ -183,47 +184,43 @@ ifdef missing_tools
183endif 184endif
184 185
185do-install-man: man 186do-install-man: man
186 $(INSTALL) -d -m 755 $(DESTDIR)$(man1dir) 187 $(call QUIET_INSTALL, Documentation-man) \
187# $(INSTALL) -d -m 755 $(DESTDIR)$(man5dir) 188 $(INSTALL) -d -m 755 $(DESTDIR)$(man1dir); \
188# $(INSTALL) -d -m 755 $(DESTDIR)$(man7dir) 189# $(INSTALL) -d -m 755 $(DESTDIR)$(man5dir); \
189 $(INSTALL) -m 644 $(DOC_MAN1) $(DESTDIR)$(man1dir) 190# $(INSTALL) -d -m 755 $(DESTDIR)$(man7dir); \
190# $(INSTALL) -m 644 $(DOC_MAN5) $(DESTDIR)$(man5dir) 191 $(INSTALL) -m 644 $(DOC_MAN1) $(DESTDIR)$(man1dir); \
191# $(INSTALL) -m 644 $(DOC_MAN7) $(DESTDIR)$(man7dir) 192# $(INSTALL) -m 644 $(DOC_MAN5) $(DESTDIR)$(man5dir); \
193# $(INSTALL) -m 644 $(DOC_MAN7) $(DESTDIR)$(man7dir)
192 194
193install-man: check-man-tools man 195install-man: check-man-tools man
194 196
195try-install-man:
196ifdef missing_tools 197ifdef missing_tools
197 $(warning Please install $(missing_tools) to have the man pages installed) 198 DO_INSTALL_MAN = $(warning Please install $(missing_tools) to have the man pages installed)
198else 199else
199 $(MAKE) do-install-man 200 DO_INSTALL_MAN = do-install-man
200endif 201endif
201 202
203try-install-man: $(DO_INSTALL_MAN)
204
202install-info: info 205install-info: info
203 $(INSTALL) -d -m 755 $(DESTDIR)$(infodir) 206 $(call QUIET_INSTALL, Documentation-info) \
204 $(INSTALL) -m 644 $(OUTPUT)perf.info $(OUTPUT)perfman.info $(DESTDIR)$(infodir) 207 $(INSTALL) -d -m 755 $(DESTDIR)$(infodir); \
208 $(INSTALL) -m 644 $(OUTPUT)perf.info $(OUTPUT)perfman.info $(DESTDIR)$(infodir); \
205 if test -r $(DESTDIR)$(infodir)/dir; then \ 209 if test -r $(DESTDIR)$(infodir)/dir; then \
206 $(INSTALL_INFO) --info-dir=$(DESTDIR)$(infodir) perf.info ;\ 210 $(INSTALL_INFO) --info-dir=$(DESTDIR)$(infodir) perf.info ;\
207 $(INSTALL_INFO) --info-dir=$(DESTDIR)$(infodir) perfman.info ;\ 211 $(INSTALL_INFO) --info-dir=$(DESTDIR)$(infodir) perfman.info ;\
208 else \ 212 else \
209 echo "No directory found in $(DESTDIR)$(infodir)" >&2 ; \ 213 echo "No directory found in $(DESTDIR)$(infodir)" >&2 ; \
210 fi 214 fi
211 215
212install-pdf: pdf 216install-pdf: pdf
213 $(INSTALL) -d -m 755 $(DESTDIR)$(pdfdir) 217 $(call QUIET_INSTALL, Documentation-pdf) \
214 $(INSTALL) -m 644 $(OUTPUT)user-manual.pdf $(DESTDIR)$(pdfdir) 218 $(INSTALL) -d -m 755 $(DESTDIR)$(pdfdir); \
219 $(INSTALL) -m 644 $(OUTPUT)user-manual.pdf $(DESTDIR)$(pdfdir)
215 220
216#install-html: html 221#install-html: html
217# '$(SHELL_PATH_SQ)' ./install-webdoc.sh $(DESTDIR)$(htmldir) 222# '$(SHELL_PATH_SQ)' ./install-webdoc.sh $(DESTDIR)$(htmldir)
218 223
219ifneq ($(MAKECMDGOALS),clean)
220ifneq ($(MAKECMDGOALS),tags)
221$(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE
222 $(QUIET_SUBDIR0)../ $(QUIET_SUBDIR1) $(OUTPUT)PERF-VERSION-FILE
223
224-include $(OUTPUT)PERF-VERSION-FILE
225endif
226endif
227 224
228# 225#
229# Determine "include::" file references in asciidoc files. 226# Determine "include::" file references in asciidoc files.
@@ -253,15 +250,17 @@ $(OUTPUT)cmd-list.made: cmd-list.perl ../command-list.txt $(MAN1_TXT)
253 $(PERL_PATH) ./cmd-list.perl ../command-list.txt $(QUIET_STDERR) && \ 250 $(PERL_PATH) ./cmd-list.perl ../command-list.txt $(QUIET_STDERR) && \
254 date >$@ 251 date >$@
255 252
253CLEAN_FILES = \
254 $(MAN_XML) $(addsuffix +,$(MAN_XML)) \
255 $(MAN_HTML) $(addsuffix +,$(MAN_HTML)) \
256 $(DOC_HTML) $(DOC_MAN1) $(DOC_MAN5) $(DOC_MAN7) \
257 $(OUTPUT)*.texi $(OUTPUT)*.texi+ $(OUTPUT)*.texi++ \
258 $(OUTPUT)perf.info $(OUTPUT)perfman.info \
259 $(OUTPUT)howto-index.txt $(OUTPUT)howto/*.html $(OUTPUT)doc.dep \
260 $(OUTPUT)technical/api-*.html $(OUTPUT)technical/api-index.txt \
261 $(cmds_txt) $(OUTPUT)*.made
256clean: 262clean:
257 $(RM) $(MAN_XML) $(addsuffix +,$(MAN_XML)) 263 $(call QUIET_CLEAN, Documentation) $(RM) $(CLEAN_FILES)
258 $(RM) $(MAN_HTML) $(addsuffix +,$(MAN_HTML))
259 $(RM) $(DOC_HTML) $(DOC_MAN1) $(DOC_MAN5) $(DOC_MAN7)
260 $(RM) $(OUTPUT)*.texi $(OUTPUT)*.texi+ $(OUTPUT)*.texi++
261 $(RM) $(OUTPUT)perf.info $(OUTPUT)perfman.info
262 $(RM) $(OUTPUT)howto-index.txt $(OUTPUT)howto/*.html $(OUTPUT)doc.dep
263 $(RM) $(OUTPUT)technical/api-*.html $(OUTPUT)technical/api-index.txt
264 $(RM) $(cmds_txt) $(OUTPUT)*.made
265 264
266$(MAN_HTML): $(OUTPUT)%.html : %.txt 265$(MAN_HTML): $(OUTPUT)%.html : %.txt
267 $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \ 266 $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \
@@ -342,5 +341,3 @@ $(patsubst %.txt,%.html,$(wildcard howto/*.txt)): %.html : %.txt
342 341
343#quick-install-html: 342#quick-install-html:
344# '$(SHELL_PATH_SQ)' ./install-doc-quick.sh $(HTML_REF) $(DESTDIR)$(htmldir) 343# '$(SHELL_PATH_SQ)' ./install-doc-quick.sh $(HTML_REF) $(DESTDIR)$(htmldir)
345
346.PHONY: .FORCE-PERF-VERSION-FILE
diff --git a/tools/perf/Documentation/perf-buildid-cache.txt b/tools/perf/Documentation/perf-buildid-cache.txt
index e9a8349a7172..fd77d81ea748 100644
--- a/tools/perf/Documentation/perf-buildid-cache.txt
+++ b/tools/perf/Documentation/perf-buildid-cache.txt
@@ -21,6 +21,19 @@ OPTIONS
21-a:: 21-a::
22--add=:: 22--add=::
23 Add specified file to the cache. 23 Add specified file to the cache.
24-k::
25--kcore::
26 Add specified kcore file to the cache. For the current host that is
27 /proc/kcore which requires root permissions to read. Be aware that
28 running 'perf buildid-cache' as root may update root's build-id cache
29 not the user's. Use the -v option to see where the file is created.
30 Note that the copied file contains only code sections not the whole core
31 image. Note also that files "kallsyms" and "modules" must also be in the
32 same directory and are also copied. All 3 files are created with read
33 permissions for root only. kcore will not be added if there is already a
34 kcore in the cache (with the same build-id) that has the same modules at
35 the same addresses. Use the -v option to see if a copy of kcore is
36 actually made.
24-r:: 37-r::
25--remove=:: 38--remove=::
26 Remove specified file from the cache. 39 Remove specified file from the cache.
diff --git a/tools/perf/Documentation/perf-kvm.txt b/tools/perf/Documentation/perf-kvm.txt
index ac84db2d2334..6a06cefe9642 100644
--- a/tools/perf/Documentation/perf-kvm.txt
+++ b/tools/perf/Documentation/perf-kvm.txt
@@ -109,7 +109,9 @@ STAT LIVE OPTIONS
109 109
110-m:: 110-m::
111--mmap-pages=:: 111--mmap-pages=::
112 Number of mmap data pages. Must be a power of two. 112 Number of mmap data pages (must be a power of two) or size
113 specification with appended unit character - B/K/M/G. The
114 size is rounded up to have nearest pages power of two value.
113 115
114-a:: 116-a::
115--all-cpus:: 117--all-cpus::
diff --git a/tools/perf/Documentation/perf-lock.txt b/tools/perf/Documentation/perf-lock.txt
index c7f5f55634ac..ab25be28c9dc 100644
--- a/tools/perf/Documentation/perf-lock.txt
+++ b/tools/perf/Documentation/perf-lock.txt
@@ -48,7 +48,7 @@ REPORT OPTIONS
48-k:: 48-k::
49--key=<value>:: 49--key=<value>::
50 Sorting key. Possible values: acquired (default), contended, 50 Sorting key. Possible values: acquired (default), contended,
51 wait_total, wait_max, wait_min. 51 avg_wait, wait_total, wait_max, wait_min.
52 52
53INFO OPTIONS 53INFO OPTIONS
54------------ 54------------
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index f732eaa6a500..f10ab63576d7 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -87,7 +87,9 @@ OPTIONS
87 87
88-m:: 88-m::
89--mmap-pages=:: 89--mmap-pages=::
90 Number of mmap data pages. Must be a power of two. 90 Number of mmap data pages (must be a power of two) or size
91 specification with appended unit character - B/K/M/G. The
92 size is rounded up to have nearest pages power of two value.
91 93
92-g:: 94-g::
93--call-graph:: 95--call-graph::
diff --git a/tools/perf/Documentation/perf-timechart.txt b/tools/perf/Documentation/perf-timechart.txt
index 1632b0efc757..3ff8bd4f0b4d 100644
--- a/tools/perf/Documentation/perf-timechart.txt
+++ b/tools/perf/Documentation/perf-timechart.txt
@@ -8,7 +8,8 @@ perf-timechart - Tool to visualize total system behavior during a workload
8SYNOPSIS 8SYNOPSIS
9-------- 9--------
10[verse] 10[verse]
11'perf timechart' {record} 11'perf timechart' record <command>
12'perf timechart' [<options>]
12 13
13DESCRIPTION 14DESCRIPTION
14----------- 15-----------
@@ -41,6 +42,18 @@ OPTIONS
41--symfs=<directory>:: 42--symfs=<directory>::
42 Look for files with symbols relative to this directory. 43 Look for files with symbols relative to this directory.
43 44
45EXAMPLES
46--------
47
48$ perf timechart record git pull
49
50 [ perf record: Woken up 13 times to write data ]
51 [ perf record: Captured and wrote 4.253 MB perf.data (~185801 samples) ]
52
53$ perf timechart
54
55 Written 10.2 seconds of trace to output.svg.
56
44SEE ALSO 57SEE ALSO
45-------- 58--------
46linkperf:perf-record[1] 59linkperf:perf-record[1]
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt
index 6d70fbfe28a2..f65777c1f723 100644
--- a/tools/perf/Documentation/perf-top.txt
+++ b/tools/perf/Documentation/perf-top.txt
@@ -68,7 +68,9 @@ Default is to monitor all CPUS.
68 68
69-m <pages>:: 69-m <pages>::
70--mmap-pages=<pages>:: 70--mmap-pages=<pages>::
71 Number of mmapped data pages. 71 Number of mmap data pages (must be a power of two) or size
72 specification with appended unit character - B/K/M/G. The
73 size is rounded up to have nearest pages power of two value.
72 74
73-p <pid>:: 75-p <pid>::
74--pid=<pid>:: 76--pid=<pid>::
diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt
index daccd2c0a48f..54139c6457f8 100644
--- a/tools/perf/Documentation/perf-trace.txt
+++ b/tools/perf/Documentation/perf-trace.txt
@@ -9,6 +9,7 @@ SYNOPSIS
9-------- 9--------
10[verse] 10[verse]
11'perf trace' 11'perf trace'
12'perf trace record'
12 13
13DESCRIPTION 14DESCRIPTION
14----------- 15-----------
@@ -16,9 +17,14 @@ This command will show the events associated with the target, initially
16syscalls, but other system events like pagefaults, task lifetime events, 17syscalls, but other system events like pagefaults, task lifetime events,
17scheduling events, etc. 18scheduling events, etc.
18 19
19Initially this is a live mode only tool, but eventually will work with 20This is a live mode tool in addition to working with perf.data files like
20perf.data files like the other tools, allowing a detached 'record' from 21the other perf tools. Files can be generated using the 'perf record' command
21analysis phases. 22but the session needs to include the raw_syscalls events (-e 'raw_syscalls:*').
23Alernatively, the 'perf trace record' can be used as a shortcut to
24automatically include the raw_syscalls events when writing events to a file.
25
26The following options apply to perf trace; options to perf trace record are
27found in the perf record man page.
22 28
23OPTIONS 29OPTIONS
24------- 30-------
@@ -59,7 +65,9 @@ OPTIONS
59 65
60-m:: 66-m::
61--mmap-pages=:: 67--mmap-pages=::
62 Number of mmap data pages. Must be a power of two. 68 Number of mmap data pages (must be a power of two) or size
69 specification with appended unit character - B/K/M/G. The
70 size is rounded up to have nearest pages power of two value.
63 71
64-C:: 72-C::
65--cpu:: 73--cpu::
@@ -78,6 +86,17 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs.
78--input 86--input
79 Process events from a given perf data file. 87 Process events from a given perf data file.
80 88
89-T
90--time
91 Print full timestamp rather time relative to first sample.
92
93--comm::
94 Show process COMM right beside its ID, on by default, disable with --no-comm.
95
96--summary::
97 Show a summary of syscalls by thread with min, max, and average times (in
98 msec) and relative stddev.
99
81SEE ALSO 100SEE ALSO
82-------- 101--------
83linkperf:perf-record[1], linkperf:perf-script[1] 102linkperf:perf-record[1], linkperf:perf-script[1]
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 64c043b7a438..4835618a5608 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -1,819 +1,79 @@
1include ../scripts/Makefile.include
2
3# The default target of this Makefile is...
4all:
5
6include config/utilities.mak
7
8# Define V to have a more verbose compile.
9#
10# Define O to save output files in a separate directory.
11#
12# Define ARCH as name of target architecture if you want cross-builds.
13#
14# Define CROSS_COMPILE as prefix name of compiler if you want cross-builds.
15#
16# Define NO_LIBPERL to disable perl script extension.
17#
18# Define NO_LIBPYTHON to disable python script extension.
19#
20# Define PYTHON to point to the python binary if the default
21# `python' is not correct; for example: PYTHON=python2
22#
23# Define PYTHON_CONFIG to point to the python-config binary if
24# the default `$(PYTHON)-config' is not correct.
25# 1#
26# Define ASCIIDOC8 if you want to format documentation with AsciiDoc 8 2# This is a simple wrapper Makefile that calls the main Makefile.perf
3# with a -j option to do parallel builds
27# 4#
28# Define DOCBOOK_XSL_172 if you want to format man pages with DocBook XSL v1.72. 5# If you want to invoke the perf build in some non-standard way then
6# you can use the 'make -f Makefile.perf' method to invoke it.
29# 7#
30# Define LDFLAGS=-static to build a static binary. 8
31#
32# Define EXTRA_CFLAGS=-m64 or EXTRA_CFLAGS=-m32 as appropriate for cross-builds.
33#
34# Define NO_DWARF if you do not want debug-info analysis feature at all.
35#
36# Define WERROR=0 to disable treating any warnings as errors.
37#
38# Define NO_NEWT if you do not want TUI support. (deprecated)
39#
40# Define NO_SLANG if you do not want TUI support.
41#
42# Define NO_GTK2 if you do not want GTK+ GUI support.
43# 9#
44# Define NO_DEMANGLE if you do not want C++ symbol demangling. 10# Clear out the built-in rules GNU make defines by default (such as .o targets),
11# so that we pass through all targets to Makefile.perf:
45# 12#
46# Define NO_LIBELF if you do not want libelf dependency (e.g. cross-builds) 13.SUFFIXES:
14
47# 15#
48# Define NO_LIBUNWIND if you do not want libunwind dependency for dwarf 16# We don't want to pass along options like -j:
49# backtrace post unwind.
50# 17#
51# Define NO_BACKTRACE if you do not want stack backtrace debug feature 18unexport MAKEFLAGS
19
52# 20#
53# Define NO_LIBNUMA if you do not want numa perf benchmark 21# Do a parallel build with multiple jobs, based on the number of CPUs online
22# in this system: 'make -j8' on a 8-CPU system, etc.
54# 23#
55# Define NO_LIBAUDIT if you do not want libaudit support 24# (To override it, run 'make JOBS=1' and similar.)
56# 25#
57# Define NO_LIBBIONIC if you do not want bionic support 26ifeq ($(JOBS),)
58 27 JOBS := $(shell grep -c ^processor /proc/cpuinfo 2>/dev/null)
59ifeq ($(srctree),) 28 ifeq ($(JOBS),)
60srctree := $(patsubst %/,%,$(dir $(shell pwd))) 29 JOBS := 1
61srctree := $(patsubst %/,%,$(dir $(srctree))) 30 endif
62#$(info Determined 'srctree' to be $(srctree))
63endif
64
65ifneq ($(objtree),)
66#$(info Determined 'objtree' to be $(objtree))
67endif
68
69ifneq ($(OUTPUT),)
70#$(info Determined 'OUTPUT' to be $(OUTPUT))
71endif
72
73$(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE
74 @$(SHELL_PATH) util/PERF-VERSION-GEN $(OUTPUT)
75
76CC = $(CROSS_COMPILE)gcc
77AR = $(CROSS_COMPILE)ar
78
79RM = rm -f
80MKDIR = mkdir
81FIND = find
82INSTALL = install
83FLEX = flex
84BISON = bison
85STRIP = strip
86
87LK_DIR = $(srctree)/tools/lib/lk/
88TRACE_EVENT_DIR = $(srctree)/tools/lib/traceevent/
89
90# include config/Makefile by default and rule out
91# non-config cases
92config := 1
93
94NON_CONFIG_TARGETS := clean TAGS tags cscope help
95
96ifdef MAKECMDGOALS
97ifeq ($(filter-out $(NON_CONFIG_TARGETS),$(MAKECMDGOALS)),)
98 config := 0
99endif
100endif 31endif
101 32
102ifeq ($(config),1) 33#
103include config/Makefile 34# Only pass canonical directory names as the output directory:
35#
36ifneq ($(O),)
37 FULL_O := $(shell readlink -f $(O) || echo $(O))
104endif 38endif
105 39
106export prefix bindir sharedir sysconfdir 40#
107 41# Only accept the 'DEBUG' variable from the command line:
108# sparse is architecture-neutral, which means that we need to tell it 42#
109# explicitly what architecture to check for. Fix this up for yours.. 43ifeq ("$(origin DEBUG)", "command line")
110SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__ 44 ifeq ($(DEBUG),)
111 45 override DEBUG = 0
112# Guard against environment variables 46 else
113BUILTIN_OBJS = 47 SET_DEBUG = "DEBUG=$(DEBUG)"
114LIB_H = 48 endif
115LIB_OBJS =
116PYRF_OBJS =
117SCRIPT_SH =
118
119SCRIPT_SH += perf-archive.sh
120
121grep-libs = $(filter -l%,$(1))
122strip-libs = $(filter-out -l%,$(1))
123
124ifneq ($(OUTPUT),)
125 TE_PATH=$(OUTPUT)
126ifneq ($(subdir),)
127 LK_PATH=$(OUTPUT)/../lib/lk/
128else
129 LK_PATH=$(OUTPUT)
130endif
131else 49else
132 TE_PATH=$(TRACE_EVENT_DIR) 50 override DEBUG = 0
133 LK_PATH=$(LK_DIR)
134endif 51endif
135 52
136LIBTRACEEVENT = $(TE_PATH)libtraceevent.a 53define print_msg
137export LIBTRACEEVENT 54 @printf ' BUILD: Doing '\''make \033[33m-j'$(JOBS)'\033[m'\'' parallel build\n'
138 55endef
139LIBLK = $(LK_PATH)liblk.a
140export LIBLK
141
142# python extension build directories
143PYTHON_EXTBUILD := $(OUTPUT)python_ext_build/
144PYTHON_EXTBUILD_LIB := $(PYTHON_EXTBUILD)lib/
145PYTHON_EXTBUILD_TMP := $(PYTHON_EXTBUILD)tmp/
146export PYTHON_EXTBUILD_LIB PYTHON_EXTBUILD_TMP
147 56
148python-clean := rm -rf $(PYTHON_EXTBUILD) $(OUTPUT)python/perf.so 57define make
58 @$(MAKE) -f Makefile.perf --no-print-directory -j$(JOBS) O=$(FULL_O) $(SET_DEBUG) $@
59endef
149 60
150PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources)
151PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBLK)
152
153$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS)
154 $(QUIET_GEN)CFLAGS='$(CFLAGS)' $(PYTHON_WORD) util/setup.py \
155 --quiet build_ext; \
156 mkdir -p $(OUTPUT)python && \
157 cp $(PYTHON_EXTBUILD_LIB)perf.so $(OUTPUT)python/
158# 61#
159# No Perl scripts right now: 62# Needed if no target specified:
160# 63#
161 64all:
162SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) 65 $(print_msg)
66 $(make)
163 67
164# 68#
165# Single 'perf' binary right now: 69# The clean target is not really parallel, don't print the jobs info:
166# 70#
167PROGRAMS += $(OUTPUT)perf 71clean:
168 72 $(make)
169# what 'all' will build and 'install' will install, in perfexecdir
170ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS)
171
172# what 'all' will build but not install in perfexecdir
173OTHER_PROGRAMS = $(OUTPUT)perf
174
175# Set paths to tools early so that they can be used for version tests.
176ifndef SHELL_PATH
177 SHELL_PATH = /bin/sh
178endif
179ifndef PERL_PATH
180 PERL_PATH = /usr/bin/perl
181endif
182
183export PERL_PATH
184
185$(OUTPUT)util/parse-events-flex.c: util/parse-events.l $(OUTPUT)util/parse-events-bison.c
186 $(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) -t util/parse-events.l > $(OUTPUT)util/parse-events-flex.c
187
188$(OUTPUT)util/parse-events-bison.c: util/parse-events.y
189 $(QUIET_BISON)$(BISON) -v util/parse-events.y -d $(PARSER_DEBUG_BISON) -o $(OUTPUT)util/parse-events-bison.c -p parse_events_
190
191$(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c
192 $(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/pmu-flex.h -t util/pmu.l > $(OUTPUT)util/pmu-flex.c
193
194$(OUTPUT)util/pmu-bison.c: util/pmu.y
195 $(QUIET_BISON)$(BISON) -v util/pmu.y -d -o $(OUTPUT)util/pmu-bison.c -p perf_pmu_
196
197$(OUTPUT)util/parse-events.o: $(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-bison.c
198$(OUTPUT)util/pmu.o: $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-bison.c
199
200LIB_FILE=$(OUTPUT)libperf.a
201
202LIB_H += ../../include/uapi/linux/perf_event.h
203LIB_H += ../../include/linux/rbtree.h
204LIB_H += ../../include/linux/list.h
205LIB_H += ../../include/uapi/linux/const.h
206LIB_H += ../../include/linux/hash.h
207LIB_H += ../../include/linux/stringify.h
208LIB_H += util/include/linux/bitmap.h
209LIB_H += util/include/linux/bitops.h
210LIB_H += util/include/linux/compiler.h
211LIB_H += util/include/linux/const.h
212LIB_H += util/include/linux/ctype.h
213LIB_H += util/include/linux/kernel.h
214LIB_H += util/include/linux/list.h
215LIB_H += util/include/linux/export.h
216LIB_H += util/include/linux/magic.h
217LIB_H += util/include/linux/poison.h
218LIB_H += util/include/linux/prefetch.h
219LIB_H += util/include/linux/rbtree.h
220LIB_H += util/include/linux/rbtree_augmented.h
221LIB_H += util/include/linux/string.h
222LIB_H += util/include/linux/types.h
223LIB_H += util/include/linux/linkage.h
224LIB_H += util/include/asm/asm-offsets.h
225LIB_H += util/include/asm/bug.h
226LIB_H += util/include/asm/byteorder.h
227LIB_H += util/include/asm/hweight.h
228LIB_H += util/include/asm/swab.h
229LIB_H += util/include/asm/system.h
230LIB_H += util/include/asm/uaccess.h
231LIB_H += util/include/dwarf-regs.h
232LIB_H += util/include/asm/dwarf2.h
233LIB_H += util/include/asm/cpufeature.h
234LIB_H += util/include/asm/unistd_32.h
235LIB_H += util/include/asm/unistd_64.h
236LIB_H += perf.h
237LIB_H += util/annotate.h
238LIB_H += util/cache.h
239LIB_H += util/callchain.h
240LIB_H += util/build-id.h
241LIB_H += util/debug.h
242LIB_H += util/sysfs.h
243LIB_H += util/pmu.h
244LIB_H += util/event.h
245LIB_H += util/evsel.h
246LIB_H += util/evlist.h
247LIB_H += util/exec_cmd.h
248LIB_H += util/types.h
249LIB_H += util/levenshtein.h
250LIB_H += util/machine.h
251LIB_H += util/map.h
252LIB_H += util/parse-options.h
253LIB_H += util/parse-events.h
254LIB_H += util/quote.h
255LIB_H += util/util.h
256LIB_H += util/xyarray.h
257LIB_H += util/header.h
258LIB_H += util/help.h
259LIB_H += util/session.h
260LIB_H += util/strbuf.h
261LIB_H += util/strlist.h
262LIB_H += util/strfilter.h
263LIB_H += util/svghelper.h
264LIB_H += util/tool.h
265LIB_H += util/run-command.h
266LIB_H += util/sigchain.h
267LIB_H += util/dso.h
268LIB_H += util/symbol.h
269LIB_H += util/color.h
270LIB_H += util/values.h
271LIB_H += util/sort.h
272LIB_H += util/hist.h
273LIB_H += util/thread.h
274LIB_H += util/thread_map.h
275LIB_H += util/trace-event.h
276LIB_H += util/probe-finder.h
277LIB_H += util/dwarf-aux.h
278LIB_H += util/probe-event.h
279LIB_H += util/pstack.h
280LIB_H += util/cpumap.h
281LIB_H += util/top.h
282LIB_H += $(ARCH_INCLUDE)
283LIB_H += util/cgroup.h
284LIB_H += $(LIB_INCLUDE)traceevent/event-parse.h
285LIB_H += util/target.h
286LIB_H += util/rblist.h
287LIB_H += util/intlist.h
288LIB_H += util/perf_regs.h
289LIB_H += util/unwind.h
290LIB_H += util/vdso.h
291LIB_H += ui/helpline.h
292LIB_H += ui/progress.h
293LIB_H += ui/util.h
294LIB_H += ui/ui.h
295
296LIB_OBJS += $(OUTPUT)util/abspath.o
297LIB_OBJS += $(OUTPUT)util/alias.o
298LIB_OBJS += $(OUTPUT)util/annotate.o
299LIB_OBJS += $(OUTPUT)util/build-id.o
300LIB_OBJS += $(OUTPUT)util/config.o
301LIB_OBJS += $(OUTPUT)util/ctype.o
302LIB_OBJS += $(OUTPUT)util/sysfs.o
303LIB_OBJS += $(OUTPUT)util/pmu.o
304LIB_OBJS += $(OUTPUT)util/environment.o
305LIB_OBJS += $(OUTPUT)util/event.o
306LIB_OBJS += $(OUTPUT)util/evlist.o
307LIB_OBJS += $(OUTPUT)util/evsel.o
308LIB_OBJS += $(OUTPUT)util/exec_cmd.o
309LIB_OBJS += $(OUTPUT)util/help.o
310LIB_OBJS += $(OUTPUT)util/levenshtein.o
311LIB_OBJS += $(OUTPUT)util/parse-options.o
312LIB_OBJS += $(OUTPUT)util/parse-events.o
313LIB_OBJS += $(OUTPUT)util/path.o
314LIB_OBJS += $(OUTPUT)util/rbtree.o
315LIB_OBJS += $(OUTPUT)util/bitmap.o
316LIB_OBJS += $(OUTPUT)util/hweight.o
317LIB_OBJS += $(OUTPUT)util/run-command.o
318LIB_OBJS += $(OUTPUT)util/quote.o
319LIB_OBJS += $(OUTPUT)util/strbuf.o
320LIB_OBJS += $(OUTPUT)util/string.o
321LIB_OBJS += $(OUTPUT)util/strlist.o
322LIB_OBJS += $(OUTPUT)util/strfilter.o
323LIB_OBJS += $(OUTPUT)util/top.o
324LIB_OBJS += $(OUTPUT)util/usage.o
325LIB_OBJS += $(OUTPUT)util/wrapper.o
326LIB_OBJS += $(OUTPUT)util/sigchain.o
327LIB_OBJS += $(OUTPUT)util/dso.o
328LIB_OBJS += $(OUTPUT)util/symbol.o
329LIB_OBJS += $(OUTPUT)util/symbol-elf.o
330LIB_OBJS += $(OUTPUT)util/color.o
331LIB_OBJS += $(OUTPUT)util/pager.o
332LIB_OBJS += $(OUTPUT)util/header.o
333LIB_OBJS += $(OUTPUT)util/callchain.o
334LIB_OBJS += $(OUTPUT)util/values.o
335LIB_OBJS += $(OUTPUT)util/debug.o
336LIB_OBJS += $(OUTPUT)util/machine.o
337LIB_OBJS += $(OUTPUT)util/map.o
338LIB_OBJS += $(OUTPUT)util/pstack.o
339LIB_OBJS += $(OUTPUT)util/session.o
340LIB_OBJS += $(OUTPUT)util/thread.o
341LIB_OBJS += $(OUTPUT)util/thread_map.o
342LIB_OBJS += $(OUTPUT)util/trace-event-parse.o
343LIB_OBJS += $(OUTPUT)util/parse-events-flex.o
344LIB_OBJS += $(OUTPUT)util/parse-events-bison.o
345LIB_OBJS += $(OUTPUT)util/pmu-flex.o
346LIB_OBJS += $(OUTPUT)util/pmu-bison.o
347LIB_OBJS += $(OUTPUT)util/trace-event-read.o
348LIB_OBJS += $(OUTPUT)util/trace-event-info.o
349LIB_OBJS += $(OUTPUT)util/trace-event-scripting.o
350LIB_OBJS += $(OUTPUT)util/svghelper.o
351LIB_OBJS += $(OUTPUT)util/sort.o
352LIB_OBJS += $(OUTPUT)util/hist.o
353LIB_OBJS += $(OUTPUT)util/probe-event.o
354LIB_OBJS += $(OUTPUT)util/util.o
355LIB_OBJS += $(OUTPUT)util/xyarray.o
356LIB_OBJS += $(OUTPUT)util/cpumap.o
357LIB_OBJS += $(OUTPUT)util/cgroup.o
358LIB_OBJS += $(OUTPUT)util/target.o
359LIB_OBJS += $(OUTPUT)util/rblist.o
360LIB_OBJS += $(OUTPUT)util/intlist.o
361LIB_OBJS += $(OUTPUT)util/vdso.o
362LIB_OBJS += $(OUTPUT)util/stat.o
363LIB_OBJS += $(OUTPUT)util/record.o
364
365LIB_OBJS += $(OUTPUT)ui/setup.o
366LIB_OBJS += $(OUTPUT)ui/helpline.o
367LIB_OBJS += $(OUTPUT)ui/progress.o
368LIB_OBJS += $(OUTPUT)ui/util.o
369LIB_OBJS += $(OUTPUT)ui/hist.o
370LIB_OBJS += $(OUTPUT)ui/stdio/hist.o
371
372LIB_OBJS += $(OUTPUT)arch/common.o
373
374LIB_OBJS += $(OUTPUT)tests/parse-events.o
375LIB_OBJS += $(OUTPUT)tests/dso-data.o
376LIB_OBJS += $(OUTPUT)tests/attr.o
377LIB_OBJS += $(OUTPUT)tests/vmlinux-kallsyms.o
378LIB_OBJS += $(OUTPUT)tests/open-syscall.o
379LIB_OBJS += $(OUTPUT)tests/open-syscall-all-cpus.o
380LIB_OBJS += $(OUTPUT)tests/open-syscall-tp-fields.o
381LIB_OBJS += $(OUTPUT)tests/mmap-basic.o
382LIB_OBJS += $(OUTPUT)tests/perf-record.o
383LIB_OBJS += $(OUTPUT)tests/rdpmc.o
384LIB_OBJS += $(OUTPUT)tests/evsel-roundtrip-name.o
385LIB_OBJS += $(OUTPUT)tests/evsel-tp-sched.o
386LIB_OBJS += $(OUTPUT)tests/pmu.o
387LIB_OBJS += $(OUTPUT)tests/hists_link.o
388LIB_OBJS += $(OUTPUT)tests/python-use.o
389LIB_OBJS += $(OUTPUT)tests/bp_signal.o
390LIB_OBJS += $(OUTPUT)tests/bp_signal_overflow.o
391LIB_OBJS += $(OUTPUT)tests/task-exit.o
392LIB_OBJS += $(OUTPUT)tests/sw-clock.o
393ifeq ($(ARCH),x86)
394LIB_OBJS += $(OUTPUT)tests/perf-time-to-tsc.o
395endif
396LIB_OBJS += $(OUTPUT)tests/code-reading.o
397LIB_OBJS += $(OUTPUT)tests/sample-parsing.o
398LIB_OBJS += $(OUTPUT)tests/parse-no-sample-id-all.o
399
400BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
401BUILTIN_OBJS += $(OUTPUT)builtin-bench.o
402# Benchmark modules
403BUILTIN_OBJS += $(OUTPUT)bench/sched-messaging.o
404BUILTIN_OBJS += $(OUTPUT)bench/sched-pipe.o
405ifeq ($(RAW_ARCH),x86_64)
406BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy-x86-64-asm.o
407BUILTIN_OBJS += $(OUTPUT)bench/mem-memset-x86-64-asm.o
408endif
409BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o
410BUILTIN_OBJS += $(OUTPUT)bench/mem-memset.o
411
412BUILTIN_OBJS += $(OUTPUT)builtin-diff.o
413BUILTIN_OBJS += $(OUTPUT)builtin-evlist.o
414BUILTIN_OBJS += $(OUTPUT)builtin-help.o
415BUILTIN_OBJS += $(OUTPUT)builtin-sched.o
416BUILTIN_OBJS += $(OUTPUT)builtin-buildid-list.o
417BUILTIN_OBJS += $(OUTPUT)builtin-buildid-cache.o
418BUILTIN_OBJS += $(OUTPUT)builtin-list.o
419BUILTIN_OBJS += $(OUTPUT)builtin-record.o
420BUILTIN_OBJS += $(OUTPUT)builtin-report.o
421BUILTIN_OBJS += $(OUTPUT)builtin-stat.o
422BUILTIN_OBJS += $(OUTPUT)builtin-timechart.o
423BUILTIN_OBJS += $(OUTPUT)builtin-top.o
424BUILTIN_OBJS += $(OUTPUT)builtin-script.o
425BUILTIN_OBJS += $(OUTPUT)builtin-probe.o
426BUILTIN_OBJS += $(OUTPUT)builtin-kmem.o
427BUILTIN_OBJS += $(OUTPUT)builtin-lock.o
428BUILTIN_OBJS += $(OUTPUT)builtin-kvm.o
429BUILTIN_OBJS += $(OUTPUT)builtin-inject.o
430BUILTIN_OBJS += $(OUTPUT)tests/builtin-test.o
431BUILTIN_OBJS += $(OUTPUT)builtin-mem.o
432
433PERFLIBS = $(LIB_FILE) $(LIBLK) $(LIBTRACEEVENT)
434
435# We choose to avoid "if .. else if .. else .. endif endif"
436# because maintaining the nesting to match is a pain. If
437# we had "elif" things would have been much nicer...
438
439-include arch/$(ARCH)/Makefile
440
441ifneq ($(OUTPUT),)
442 CFLAGS += -I$(OUTPUT)
443endif
444
445ifdef NO_LIBELF
446EXTLIBS := $(filter-out -lelf,$(EXTLIBS))
447
448# Remove ELF/DWARF dependent codes
449LIB_OBJS := $(filter-out $(OUTPUT)util/symbol-elf.o,$(LIB_OBJS))
450LIB_OBJS := $(filter-out $(OUTPUT)util/dwarf-aux.o,$(LIB_OBJS))
451LIB_OBJS := $(filter-out $(OUTPUT)util/probe-event.o,$(LIB_OBJS))
452LIB_OBJS := $(filter-out $(OUTPUT)util/probe-finder.o,$(LIB_OBJS))
453
454BUILTIN_OBJS := $(filter-out $(OUTPUT)builtin-probe.o,$(BUILTIN_OBJS))
455
456# Use minimal symbol handling
457LIB_OBJS += $(OUTPUT)util/symbol-minimal.o
458
459else # NO_LIBELF
460ifndef NO_DWARF
461 LIB_OBJS += $(OUTPUT)util/probe-finder.o
462 LIB_OBJS += $(OUTPUT)util/dwarf-aux.o
463endif # NO_DWARF
464endif # NO_LIBELF
465
466ifndef NO_LIBUNWIND
467 LIB_OBJS += $(OUTPUT)util/unwind.o
468endif
469LIB_OBJS += $(OUTPUT)tests/keep-tracking.o
470
471ifndef NO_LIBAUDIT
472 BUILTIN_OBJS += $(OUTPUT)builtin-trace.o
473endif
474
475ifndef NO_SLANG
476 LIB_OBJS += $(OUTPUT)ui/browser.o
477 LIB_OBJS += $(OUTPUT)ui/browsers/annotate.o
478 LIB_OBJS += $(OUTPUT)ui/browsers/hists.o
479 LIB_OBJS += $(OUTPUT)ui/browsers/map.o
480 LIB_OBJS += $(OUTPUT)ui/browsers/scripts.o
481 LIB_OBJS += $(OUTPUT)ui/tui/setup.o
482 LIB_OBJS += $(OUTPUT)ui/tui/util.o
483 LIB_OBJS += $(OUTPUT)ui/tui/helpline.o
484 LIB_OBJS += $(OUTPUT)ui/tui/progress.o
485 LIB_H += ui/browser.h
486 LIB_H += ui/browsers/map.h
487 LIB_H += ui/keysyms.h
488 LIB_H += ui/libslang.h
489endif
490
491ifndef NO_GTK2
492 LIB_OBJS += $(OUTPUT)ui/gtk/browser.o
493 LIB_OBJS += $(OUTPUT)ui/gtk/hists.o
494 LIB_OBJS += $(OUTPUT)ui/gtk/setup.o
495 LIB_OBJS += $(OUTPUT)ui/gtk/util.o
496 LIB_OBJS += $(OUTPUT)ui/gtk/helpline.o
497 LIB_OBJS += $(OUTPUT)ui/gtk/progress.o
498 LIB_OBJS += $(OUTPUT)ui/gtk/annotate.o
499endif
500
501ifndef NO_LIBPERL
502 LIB_OBJS += $(OUTPUT)util/scripting-engines/trace-event-perl.o
503 LIB_OBJS += $(OUTPUT)scripts/perl/Perf-Trace-Util/Context.o
504endif
505
506ifndef NO_LIBPYTHON
507 LIB_OBJS += $(OUTPUT)util/scripting-engines/trace-event-python.o
508 LIB_OBJS += $(OUTPUT)scripts/python/Perf-Trace-Util/Context.o
509endif
510
511ifeq ($(NO_PERF_REGS),0)
512 ifeq ($(ARCH),x86)
513 LIB_H += arch/x86/include/perf_regs.h
514 endif
515endif
516
517ifndef NO_LIBNUMA
518 BUILTIN_OBJS += $(OUTPUT)bench/numa.o
519endif
520
521ifdef ASCIIDOC8
522 export ASCIIDOC8
523endif
524
525LIBS = -Wl,--whole-archive $(PERFLIBS) -Wl,--no-whole-archive -Wl,--start-group $(EXTLIBS) -Wl,--end-group
526
527export INSTALL SHELL_PATH
528
529### Build rules
530
531SHELL = $(SHELL_PATH)
532
533all: shell_compatibility_test $(ALL_PROGRAMS) $(LANG_BINDINGS) $(OTHER_PROGRAMS)
534
535please_set_SHELL_PATH_to_a_more_modern_shell:
536 @$$(:)
537
538shell_compatibility_test: please_set_SHELL_PATH_to_a_more_modern_shell
539
540strip: $(PROGRAMS) $(OUTPUT)perf
541 $(STRIP) $(STRIP_OPTS) $(PROGRAMS) $(OUTPUT)perf
542
543$(OUTPUT)perf.o: perf.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS
544 $(QUIET_CC)$(CC) -include $(OUTPUT)PERF-VERSION-FILE \
545 '-DPERF_HTML_PATH="$(htmldir_SQ)"' \
546 $(CFLAGS) -c $(filter %.c,$^) -o $@
547
548$(OUTPUT)perf: $(OUTPUT)perf.o $(BUILTIN_OBJS) $(PERFLIBS)
549 $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $(OUTPUT)perf.o \
550 $(BUILTIN_OBJS) $(LIBS) -o $@
551
552$(OUTPUT)builtin-help.o: builtin-help.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS
553 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
554 '-DPERF_HTML_PATH="$(htmldir_SQ)"' \
555 '-DPERF_MAN_PATH="$(mandir_SQ)"' \
556 '-DPERF_INFO_PATH="$(infodir_SQ)"' $<
557
558$(OUTPUT)builtin-timechart.o: builtin-timechart.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS
559 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
560 '-DPERF_HTML_PATH="$(htmldir_SQ)"' \
561 '-DPERF_MAN_PATH="$(mandir_SQ)"' \
562 '-DPERF_INFO_PATH="$(infodir_SQ)"' $<
563
564$(OUTPUT)common-cmds.h: util/generate-cmdlist.sh command-list.txt
565
566$(OUTPUT)common-cmds.h: $(wildcard Documentation/perf-*.txt)
567 $(QUIET_GEN). util/generate-cmdlist.sh > $@+ && mv $@+ $@
568
569$(SCRIPTS) : % : %.sh
570 $(QUIET_GEN)$(INSTALL) '$@.sh' '$(OUTPUT)$@'
571
572# These can record PERF_VERSION
573$(OUTPUT)perf.o perf.spec \
574 $(SCRIPTS) \
575 : $(OUTPUT)PERF-VERSION-FILE
576
577.SUFFIXES:
578.SUFFIXES: .o .c .S .s
579
580# These two need to be here so that when O= is not used they take precedence
581# over the general rule for .o
582
583$(OUTPUT)util/%-flex.o: $(OUTPUT)util/%-flex.c $(OUTPUT)PERF-CFLAGS
584 $(QUIET_CC)$(CC) -o $@ -c -Iutil/ $(CFLAGS) -w $<
585
586$(OUTPUT)util/%-bison.o: $(OUTPUT)util/%-bison.c $(OUTPUT)PERF-CFLAGS
587 $(QUIET_CC)$(CC) -o $@ -c -Iutil/ $(CFLAGS) -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w $<
588
589$(OUTPUT)%.o: %.c $(OUTPUT)PERF-CFLAGS
590 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $<
591$(OUTPUT)%.i: %.c $(OUTPUT)PERF-CFLAGS
592 $(QUIET_CC)$(CC) -o $@ -E $(CFLAGS) $<
593$(OUTPUT)%.s: %.c $(OUTPUT)PERF-CFLAGS
594 $(QUIET_CC)$(CC) -o $@ -S $(CFLAGS) $<
595$(OUTPUT)%.o: %.S
596 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $<
597$(OUTPUT)%.s: %.S
598 $(QUIET_CC)$(CC) -o $@ -E $(CFLAGS) $<
599
600$(OUTPUT)util/exec_cmd.o: util/exec_cmd.c $(OUTPUT)PERF-CFLAGS
601 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
602 '-DPERF_EXEC_PATH="$(perfexecdir_SQ)"' \
603 '-DPREFIX="$(prefix_SQ)"' \
604 $<
605
606$(OUTPUT)tests/attr.o: tests/attr.c $(OUTPUT)PERF-CFLAGS
607 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
608 '-DBINDIR="$(bindir_SQ)"' -DPYTHON='"$(PYTHON_WORD)"' \
609 $<
610
611$(OUTPUT)tests/python-use.o: tests/python-use.c $(OUTPUT)PERF-CFLAGS
612 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
613 -DPYTHONPATH='"$(OUTPUT)python"' \
614 -DPYTHON='"$(PYTHON_WORD)"' \
615 $<
616
617$(OUTPUT)util/config.o: util/config.c $(OUTPUT)PERF-CFLAGS
618 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
619
620$(OUTPUT)ui/browser.o: ui/browser.c $(OUTPUT)PERF-CFLAGS
621 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $<
622
623$(OUTPUT)ui/browsers/annotate.o: ui/browsers/annotate.c $(OUTPUT)PERF-CFLAGS
624 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $<
625 73
626$(OUTPUT)ui/browsers/hists.o: ui/browsers/hists.c $(OUTPUT)PERF-CFLAGS 74#
627 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $< 75# All other targets get passed through:
628 76#
629$(OUTPUT)ui/browsers/map.o: ui/browsers/map.c $(OUTPUT)PERF-CFLAGS 77%:
630 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $< 78 $(print_msg)
631 79 $(make)
632$(OUTPUT)ui/browsers/scripts.o: ui/browsers/scripts.c $(OUTPUT)PERF-CFLAGS
633 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $<
634
635$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS
636 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
637
638$(OUTPUT)util/parse-events.o: util/parse-events.c $(OUTPUT)PERF-CFLAGS
639 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-redundant-decls $<
640
641$(OUTPUT)util/scripting-engines/trace-event-perl.o: util/scripting-engines/trace-event-perl.c $(OUTPUT)PERF-CFLAGS
642 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow -Wno-undef -Wno-switch-default $<
643
644$(OUTPUT)scripts/perl/Perf-Trace-Util/Context.o: scripts/perl/Perf-Trace-Util/Context.c $(OUTPUT)PERF-CFLAGS
645 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs -Wno-undef -Wno-switch-default $<
646
647$(OUTPUT)util/scripting-engines/trace-event-python.o: util/scripting-engines/trace-event-python.c $(OUTPUT)PERF-CFLAGS
648 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow $<
649
650$(OUTPUT)scripts/python/Perf-Trace-Util/Context.o: scripts/python/Perf-Trace-Util/Context.c $(OUTPUT)PERF-CFLAGS
651 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs $<
652
653$(OUTPUT)perf-%: %.o $(PERFLIBS)
654 $(QUIET_LINK)$(CC) $(CFLAGS) -o $@ $(LDFLAGS) $(filter %.o,$^) $(LIBS)
655
656$(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H)
657$(patsubst perf-%,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h)
658
659# we compile into subdirectories. if the target directory is not the source directory, they might not exists. So
660# we depend the various files onto their directories.
661DIRECTORY_DEPS = $(LIB_OBJS) $(BUILTIN_OBJS) $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h
662$(DIRECTORY_DEPS): | $(sort $(dir $(DIRECTORY_DEPS)))
663# In the second step, we make a rule to actually create these directories
664$(sort $(dir $(DIRECTORY_DEPS))):
665 $(QUIET_MKDIR)$(MKDIR) -p $@ 2>/dev/null
666
667$(LIB_FILE): $(LIB_OBJS)
668 $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIB_OBJS)
669
670# libtraceevent.a
671$(LIBTRACEEVENT):
672 $(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(QUIET_SUBDIR1) O=$(OUTPUT) libtraceevent.a
673
674$(LIBTRACEEVENT)-clean:
675 $(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(QUIET_SUBDIR1) O=$(OUTPUT) clean
676
677# if subdir is set, we've been called from above so target has been built
678# already
679$(LIBLK):
680ifeq ($(subdir),)
681 $(QUIET_SUBDIR0)$(LK_DIR) $(QUIET_SUBDIR1) O=$(OUTPUT) liblk.a
682endif
683
684$(LIBLK)-clean:
685ifeq ($(subdir),)
686 $(QUIET_SUBDIR0)$(LK_DIR) $(QUIET_SUBDIR1) O=$(OUTPUT) clean
687endif
688
689help:
690 @echo 'Perf make targets:'
691 @echo ' doc - make *all* documentation (see below)'
692 @echo ' man - make manpage documentation (access with man <foo>)'
693 @echo ' html - make html documentation'
694 @echo ' info - make GNU info documentation (access with info <foo>)'
695 @echo ' pdf - make pdf documentation'
696 @echo ' TAGS - use etags to make tag information for source browsing'
697 @echo ' tags - use ctags to make tag information for source browsing'
698 @echo ' cscope - use cscope to make interactive browsing database'
699 @echo ''
700 @echo 'Perf install targets:'
701 @echo ' NOTE: documentation build requires asciidoc, xmlto packages to be installed'
702 @echo ' HINT: use "make prefix=<path> <install target>" to install to a particular'
703 @echo ' path like make prefix=/usr/local install install-doc'
704 @echo ' install - install compiled binaries'
705 @echo ' install-doc - install *all* documentation'
706 @echo ' install-man - install manpage documentation'
707 @echo ' install-html - install html documentation'
708 @echo ' install-info - install GNU info documentation'
709 @echo ' install-pdf - install pdf documentation'
710 @echo ''
711 @echo ' quick-install-doc - alias for quick-install-man'
712 @echo ' quick-install-man - install the documentation quickly'
713 @echo ' quick-install-html - install the html documentation quickly'
714 @echo ''
715 @echo 'Perf maintainer targets:'
716 @echo ' clean - clean all binary objects and build output'
717
718
719DOC_TARGETS := doc man html info pdf
720
721INSTALL_DOC_TARGETS := $(patsubst %,install-%,$(DOC_TARGETS)) try-install-man
722INSTALL_DOC_TARGETS += quick-install-doc quick-install-man quick-install-html
723
724# 'make doc' should call 'make -C Documentation all'
725$(DOC_TARGETS):
726 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) $(@:doc=all)
727
728TAGS:
729 $(RM) TAGS
730 $(FIND) . -name '*.[hcS]' -print | xargs etags -a
731
732tags:
733 $(RM) tags
734 $(FIND) . -name '*.[hcS]' -print | xargs ctags -a
735
736cscope:
737 $(RM) cscope*
738 $(FIND) . -name '*.[hcS]' -print | xargs cscope -b
739
740### Detect prefix changes
741TRACK_CFLAGS = $(subst ','\'',$(CFLAGS)):\
742 $(bindir_SQ):$(perfexecdir_SQ):$(template_dir_SQ):$(prefix_SQ)
743
744$(OUTPUT)PERF-CFLAGS: .FORCE-PERF-CFLAGS
745 @FLAGS='$(TRACK_CFLAGS)'; \
746 if test x"$$FLAGS" != x"`cat $(OUTPUT)PERF-CFLAGS 2>/dev/null`" ; then \
747 echo 1>&2 " * new build flags or prefix"; \
748 echo "$$FLAGS" >$(OUTPUT)PERF-CFLAGS; \
749 fi
750
751### Testing rules
752
753# GNU make supports exporting all variables by "export" without parameters.
754# However, the environment gets quite big, and some programs have problems
755# with that.
756
757check: $(OUTPUT)common-cmds.h
758 if sparse; \
759 then \
760 for i in *.c */*.c; \
761 do \
762 sparse $(CFLAGS) $(SPARSE_FLAGS) $$i || exit; \
763 done; \
764 else \
765 exit 1; \
766 fi
767
768### Installation rules
769
770install-bin: all
771 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)'
772 $(INSTALL) $(OUTPUT)perf '$(DESTDIR_SQ)$(bindir_SQ)'
773 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
774 $(INSTALL) $(OUTPUT)perf-archive -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
775ifndef NO_LIBPERL
776 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'
777 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/bin'
778 $(INSTALL) scripts/perl/Perf-Trace-Util/lib/Perf/Trace/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'
779 $(INSTALL) scripts/perl/*.pl -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl'
780 $(INSTALL) scripts/perl/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/bin'
781endif
782ifndef NO_LIBPYTHON
783 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/Perf-Trace-Util/lib/Perf/Trace'
784 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin'
785 $(INSTALL) scripts/python/Perf-Trace-Util/lib/Perf/Trace/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/Perf-Trace-Util/lib/Perf/Trace'
786 $(INSTALL) scripts/python/*.py -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python'
787 $(INSTALL) scripts/python/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin'
788endif
789 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d'
790 $(INSTALL) bash_completion '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d/perf'
791 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'
792 $(INSTALL) tests/attr.py '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'
793 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'
794 $(INSTALL) tests/attr/* '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'
795
796install: install-bin try-install-man
797
798install-python_ext:
799 $(PYTHON_WORD) util/setup.py --quiet install --root='/$(DESTDIR_SQ)'
800
801# 'make install-doc' should call 'make -C Documentation install'
802$(INSTALL_DOC_TARGETS):
803 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) $(@:-doc=)
804
805### Cleaning rules
806
807clean: $(LIBTRACEEVENT)-clean $(LIBLK)-clean
808 $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf.o $(LANG_BINDINGS)
809 $(RM) $(ALL_PROGRAMS) perf
810 $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope*
811 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean
812 $(RM) $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS
813 $(RM) $(OUTPUT)util/*-bison*
814 $(RM) $(OUTPUT)util/*-flex*
815 $(python-clean)
816
817.PHONY: all install clean strip $(LIBTRACEEVENT) $(LIBLK)
818.PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell
819.PHONY: .FORCE-PERF-VERSION-FILE TAGS tags cscope .FORCE-PERF-CFLAGS
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
new file mode 100644
index 000000000000..c873e039aafb
--- /dev/null
+++ b/tools/perf/Makefile.perf
@@ -0,0 +1,887 @@
1include ../scripts/Makefile.include
2
3# The default target of this Makefile is...
4all:
5
6include config/utilities.mak
7
8# Define V to have a more verbose compile.
9#
10# Define O to save output files in a separate directory.
11#
12# Define ARCH as name of target architecture if you want cross-builds.
13#
14# Define CROSS_COMPILE as prefix name of compiler if you want cross-builds.
15#
16# Define NO_LIBPERL to disable perl script extension.
17#
18# Define NO_LIBPYTHON to disable python script extension.
19#
20# Define PYTHON to point to the python binary if the default
21# `python' is not correct; for example: PYTHON=python2
22#
23# Define PYTHON_CONFIG to point to the python-config binary if
24# the default `$(PYTHON)-config' is not correct.
25#
26# Define ASCIIDOC8 if you want to format documentation with AsciiDoc 8
27#
28# Define DOCBOOK_XSL_172 if you want to format man pages with DocBook XSL v1.72.
29#
30# Define LDFLAGS=-static to build a static binary.
31#
32# Define EXTRA_CFLAGS=-m64 or EXTRA_CFLAGS=-m32 as appropriate for cross-builds.
33#
34# Define NO_DWARF if you do not want debug-info analysis feature at all.
35#
36# Define WERROR=0 to disable treating any warnings as errors.
37#
38# Define NO_NEWT if you do not want TUI support. (deprecated)
39#
40# Define NO_SLANG if you do not want TUI support.
41#
42# Define NO_GTK2 if you do not want GTK+ GUI support.
43#
44# Define NO_DEMANGLE if you do not want C++ symbol demangling.
45#
46# Define NO_LIBELF if you do not want libelf dependency (e.g. cross-builds)
47#
48# Define NO_LIBUNWIND if you do not want libunwind dependency for dwarf
49# backtrace post unwind.
50#
51# Define NO_BACKTRACE if you do not want stack backtrace debug feature
52#
53# Define NO_LIBNUMA if you do not want numa perf benchmark
54#
55# Define NO_LIBAUDIT if you do not want libaudit support
56#
57# Define NO_LIBBIONIC if you do not want bionic support
58
59ifeq ($(srctree),)
60srctree := $(patsubst %/,%,$(dir $(shell pwd)))
61srctree := $(patsubst %/,%,$(dir $(srctree)))
62#$(info Determined 'srctree' to be $(srctree))
63endif
64
65ifneq ($(objtree),)
66#$(info Determined 'objtree' to be $(objtree))
67endif
68
69ifneq ($(OUTPUT),)
70#$(info Determined 'OUTPUT' to be $(OUTPUT))
71endif
72
73$(OUTPUT)PERF-VERSION-FILE: ../../.git/HEAD
74 @$(SHELL_PATH) util/PERF-VERSION-GEN $(OUTPUT)
75 @touch $(OUTPUT)PERF-VERSION-FILE
76
77CC = $(CROSS_COMPILE)gcc
78AR = $(CROSS_COMPILE)ar
79
80RM = rm -f
81LN = ln -f
82MKDIR = mkdir
83FIND = find
84INSTALL = install
85FLEX = flex
86BISON = bison
87STRIP = strip
88
89LK_DIR = $(srctree)/tools/lib/lk/
90TRACE_EVENT_DIR = $(srctree)/tools/lib/traceevent/
91
92# include config/Makefile by default and rule out
93# non-config cases
94config := 1
95
96NON_CONFIG_TARGETS := clean TAGS tags cscope help
97
98ifdef MAKECMDGOALS
99ifeq ($(filter-out $(NON_CONFIG_TARGETS),$(MAKECMDGOALS)),)
100 config := 0
101endif
102endif
103
104ifeq ($(config),1)
105include config/Makefile
106endif
107
108export prefix bindir sharedir sysconfdir
109
110# sparse is architecture-neutral, which means that we need to tell it
111# explicitly what architecture to check for. Fix this up for yours..
112SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__
113
114# Guard against environment variables
115BUILTIN_OBJS =
116LIB_H =
117LIB_OBJS =
118GTK_OBJS =
119PYRF_OBJS =
120SCRIPT_SH =
121
122SCRIPT_SH += perf-archive.sh
123
124grep-libs = $(filter -l%,$(1))
125strip-libs = $(filter-out -l%,$(1))
126
127ifneq ($(OUTPUT),)
128 TE_PATH=$(OUTPUT)
129ifneq ($(subdir),)
130 LK_PATH=$(OUTPUT)/../lib/lk/
131else
132 LK_PATH=$(OUTPUT)
133endif
134else
135 TE_PATH=$(TRACE_EVENT_DIR)
136 LK_PATH=$(LK_DIR)
137endif
138
139LIBTRACEEVENT = $(TE_PATH)libtraceevent.a
140export LIBTRACEEVENT
141
142LIBLK = $(LK_PATH)liblk.a
143export LIBLK
144
145# python extension build directories
146PYTHON_EXTBUILD := $(OUTPUT)python_ext_build/
147PYTHON_EXTBUILD_LIB := $(PYTHON_EXTBUILD)lib/
148PYTHON_EXTBUILD_TMP := $(PYTHON_EXTBUILD)tmp/
149export PYTHON_EXTBUILD_LIB PYTHON_EXTBUILD_TMP
150
151python-clean := $(call QUIET_CLEAN, python) $(RM) -r $(PYTHON_EXTBUILD) $(OUTPUT)python/perf.so
152
153PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources)
154PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBLK)
155
156$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS)
157 $(QUIET_GEN)CFLAGS='$(CFLAGS)' $(PYTHON_WORD) util/setup.py \
158 --quiet build_ext; \
159 mkdir -p $(OUTPUT)python && \
160 cp $(PYTHON_EXTBUILD_LIB)perf.so $(OUTPUT)python/
161#
162# No Perl scripts right now:
163#
164
165SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH))
166
167#
168# Single 'perf' binary right now:
169#
170PROGRAMS += $(OUTPUT)perf
171
172# what 'all' will build and 'install' will install, in perfexecdir
173ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS)
174
175# what 'all' will build but not install in perfexecdir
176OTHER_PROGRAMS = $(OUTPUT)perf
177
178# Set paths to tools early so that they can be used for version tests.
179ifndef SHELL_PATH
180 SHELL_PATH = /bin/sh
181endif
182ifndef PERL_PATH
183 PERL_PATH = /usr/bin/perl
184endif
185
186export PERL_PATH
187
188$(OUTPUT)util/parse-events-flex.c: util/parse-events.l $(OUTPUT)util/parse-events-bison.c
189 $(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) -t util/parse-events.l > $(OUTPUT)util/parse-events-flex.c
190
191$(OUTPUT)util/parse-events-bison.c: util/parse-events.y
192 $(QUIET_BISON)$(BISON) -v util/parse-events.y -d $(PARSER_DEBUG_BISON) -o $(OUTPUT)util/parse-events-bison.c -p parse_events_
193
194$(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c
195 $(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/pmu-flex.h -t util/pmu.l > $(OUTPUT)util/pmu-flex.c
196
197$(OUTPUT)util/pmu-bison.c: util/pmu.y
198 $(QUIET_BISON)$(BISON) -v util/pmu.y -d -o $(OUTPUT)util/pmu-bison.c -p perf_pmu_
199
200$(OUTPUT)util/parse-events.o: $(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-bison.c
201$(OUTPUT)util/pmu.o: $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-bison.c
202
203LIB_FILE=$(OUTPUT)libperf.a
204
205LIB_H += ../../include/uapi/linux/perf_event.h
206LIB_H += ../../include/linux/rbtree.h
207LIB_H += ../../include/linux/list.h
208LIB_H += ../../include/uapi/linux/const.h
209LIB_H += ../../include/linux/hash.h
210LIB_H += ../../include/linux/stringify.h
211LIB_H += util/include/linux/bitmap.h
212LIB_H += util/include/linux/bitops.h
213LIB_H += util/include/linux/compiler.h
214LIB_H += util/include/linux/const.h
215LIB_H += util/include/linux/ctype.h
216LIB_H += util/include/linux/kernel.h
217LIB_H += util/include/linux/list.h
218LIB_H += util/include/linux/export.h
219LIB_H += util/include/linux/magic.h
220LIB_H += util/include/linux/poison.h
221LIB_H += util/include/linux/prefetch.h
222LIB_H += util/include/linux/rbtree.h
223LIB_H += util/include/linux/rbtree_augmented.h
224LIB_H += util/include/linux/string.h
225LIB_H += util/include/linux/types.h
226LIB_H += util/include/linux/linkage.h
227LIB_H += util/include/asm/asm-offsets.h
228LIB_H += util/include/asm/bug.h
229LIB_H += util/include/asm/byteorder.h
230LIB_H += util/include/asm/hweight.h
231LIB_H += util/include/asm/swab.h
232LIB_H += util/include/asm/system.h
233LIB_H += util/include/asm/uaccess.h
234LIB_H += util/include/dwarf-regs.h
235LIB_H += util/include/asm/dwarf2.h
236LIB_H += util/include/asm/cpufeature.h
237LIB_H += util/include/asm/unistd_32.h
238LIB_H += util/include/asm/unistd_64.h
239LIB_H += perf.h
240LIB_H += util/annotate.h
241LIB_H += util/cache.h
242LIB_H += util/callchain.h
243LIB_H += util/build-id.h
244LIB_H += util/debug.h
245LIB_H += util/sysfs.h
246LIB_H += util/pmu.h
247LIB_H += util/event.h
248LIB_H += util/evsel.h
249LIB_H += util/evlist.h
250LIB_H += util/exec_cmd.h
251LIB_H += util/types.h
252LIB_H += util/levenshtein.h
253LIB_H += util/machine.h
254LIB_H += util/map.h
255LIB_H += util/parse-options.h
256LIB_H += util/parse-events.h
257LIB_H += util/quote.h
258LIB_H += util/util.h
259LIB_H += util/xyarray.h
260LIB_H += util/header.h
261LIB_H += util/help.h
262LIB_H += util/session.h
263LIB_H += util/strbuf.h
264LIB_H += util/strlist.h
265LIB_H += util/strfilter.h
266LIB_H += util/svghelper.h
267LIB_H += util/tool.h
268LIB_H += util/run-command.h
269LIB_H += util/sigchain.h
270LIB_H += util/dso.h
271LIB_H += util/symbol.h
272LIB_H += util/color.h
273LIB_H += util/values.h
274LIB_H += util/sort.h
275LIB_H += util/hist.h
276LIB_H += util/thread.h
277LIB_H += util/thread_map.h
278LIB_H += util/trace-event.h
279LIB_H += util/probe-finder.h
280LIB_H += util/dwarf-aux.h
281LIB_H += util/probe-event.h
282LIB_H += util/pstack.h
283LIB_H += util/cpumap.h
284LIB_H += util/top.h
285LIB_H += $(ARCH_INCLUDE)
286LIB_H += util/cgroup.h
287LIB_H += $(LIB_INCLUDE)traceevent/event-parse.h
288LIB_H += util/target.h
289LIB_H += util/rblist.h
290LIB_H += util/intlist.h
291LIB_H += util/perf_regs.h
292LIB_H += util/unwind.h
293LIB_H += util/vdso.h
294LIB_H += ui/helpline.h
295LIB_H += ui/progress.h
296LIB_H += ui/util.h
297LIB_H += ui/ui.h
298
299LIB_OBJS += $(OUTPUT)util/abspath.o
300LIB_OBJS += $(OUTPUT)util/alias.o
301LIB_OBJS += $(OUTPUT)util/annotate.o
302LIB_OBJS += $(OUTPUT)util/build-id.o
303LIB_OBJS += $(OUTPUT)util/config.o
304LIB_OBJS += $(OUTPUT)util/ctype.o
305LIB_OBJS += $(OUTPUT)util/sysfs.o
306LIB_OBJS += $(OUTPUT)util/pmu.o
307LIB_OBJS += $(OUTPUT)util/environment.o
308LIB_OBJS += $(OUTPUT)util/event.o
309LIB_OBJS += $(OUTPUT)util/evlist.o
310LIB_OBJS += $(OUTPUT)util/evsel.o
311LIB_OBJS += $(OUTPUT)util/exec_cmd.o
312LIB_OBJS += $(OUTPUT)util/help.o
313LIB_OBJS += $(OUTPUT)util/levenshtein.o
314LIB_OBJS += $(OUTPUT)util/parse-options.o
315LIB_OBJS += $(OUTPUT)util/parse-events.o
316LIB_OBJS += $(OUTPUT)util/path.o
317LIB_OBJS += $(OUTPUT)util/rbtree.o
318LIB_OBJS += $(OUTPUT)util/bitmap.o
319LIB_OBJS += $(OUTPUT)util/hweight.o
320LIB_OBJS += $(OUTPUT)util/run-command.o
321LIB_OBJS += $(OUTPUT)util/quote.o
322LIB_OBJS += $(OUTPUT)util/strbuf.o
323LIB_OBJS += $(OUTPUT)util/string.o
324LIB_OBJS += $(OUTPUT)util/strlist.o
325LIB_OBJS += $(OUTPUT)util/strfilter.o
326LIB_OBJS += $(OUTPUT)util/top.o
327LIB_OBJS += $(OUTPUT)util/usage.o
328LIB_OBJS += $(OUTPUT)util/wrapper.o
329LIB_OBJS += $(OUTPUT)util/sigchain.o
330LIB_OBJS += $(OUTPUT)util/dso.o
331LIB_OBJS += $(OUTPUT)util/symbol.o
332LIB_OBJS += $(OUTPUT)util/symbol-elf.o
333LIB_OBJS += $(OUTPUT)util/color.o
334LIB_OBJS += $(OUTPUT)util/pager.o
335LIB_OBJS += $(OUTPUT)util/header.o
336LIB_OBJS += $(OUTPUT)util/callchain.o
337LIB_OBJS += $(OUTPUT)util/values.o
338LIB_OBJS += $(OUTPUT)util/debug.o
339LIB_OBJS += $(OUTPUT)util/machine.o
340LIB_OBJS += $(OUTPUT)util/map.o
341LIB_OBJS += $(OUTPUT)util/pstack.o
342LIB_OBJS += $(OUTPUT)util/session.o
343LIB_OBJS += $(OUTPUT)util/thread.o
344LIB_OBJS += $(OUTPUT)util/thread_map.o
345LIB_OBJS += $(OUTPUT)util/trace-event-parse.o
346LIB_OBJS += $(OUTPUT)util/parse-events-flex.o
347LIB_OBJS += $(OUTPUT)util/parse-events-bison.o
348LIB_OBJS += $(OUTPUT)util/pmu-flex.o
349LIB_OBJS += $(OUTPUT)util/pmu-bison.o
350LIB_OBJS += $(OUTPUT)util/trace-event-read.o
351LIB_OBJS += $(OUTPUT)util/trace-event-info.o
352LIB_OBJS += $(OUTPUT)util/trace-event-scripting.o
353LIB_OBJS += $(OUTPUT)util/svghelper.o
354LIB_OBJS += $(OUTPUT)util/sort.o
355LIB_OBJS += $(OUTPUT)util/hist.o
356LIB_OBJS += $(OUTPUT)util/probe-event.o
357LIB_OBJS += $(OUTPUT)util/util.o
358LIB_OBJS += $(OUTPUT)util/xyarray.o
359LIB_OBJS += $(OUTPUT)util/cpumap.o
360LIB_OBJS += $(OUTPUT)util/cgroup.o
361LIB_OBJS += $(OUTPUT)util/target.o
362LIB_OBJS += $(OUTPUT)util/rblist.o
363LIB_OBJS += $(OUTPUT)util/intlist.o
364LIB_OBJS += $(OUTPUT)util/vdso.o
365LIB_OBJS += $(OUTPUT)util/stat.o
366LIB_OBJS += $(OUTPUT)util/record.o
367LIB_OBJS += $(OUTPUT)util/srcline.o
368
369LIB_OBJS += $(OUTPUT)ui/setup.o
370LIB_OBJS += $(OUTPUT)ui/helpline.o
371LIB_OBJS += $(OUTPUT)ui/progress.o
372LIB_OBJS += $(OUTPUT)ui/util.o
373LIB_OBJS += $(OUTPUT)ui/hist.o
374LIB_OBJS += $(OUTPUT)ui/stdio/hist.o
375
376LIB_OBJS += $(OUTPUT)arch/common.o
377
378LIB_OBJS += $(OUTPUT)tests/parse-events.o
379LIB_OBJS += $(OUTPUT)tests/dso-data.o
380LIB_OBJS += $(OUTPUT)tests/attr.o
381LIB_OBJS += $(OUTPUT)tests/vmlinux-kallsyms.o
382LIB_OBJS += $(OUTPUT)tests/open-syscall.o
383LIB_OBJS += $(OUTPUT)tests/open-syscall-all-cpus.o
384LIB_OBJS += $(OUTPUT)tests/open-syscall-tp-fields.o
385LIB_OBJS += $(OUTPUT)tests/mmap-basic.o
386LIB_OBJS += $(OUTPUT)tests/perf-record.o
387LIB_OBJS += $(OUTPUT)tests/rdpmc.o
388LIB_OBJS += $(OUTPUT)tests/evsel-roundtrip-name.o
389LIB_OBJS += $(OUTPUT)tests/evsel-tp-sched.o
390LIB_OBJS += $(OUTPUT)tests/pmu.o
391LIB_OBJS += $(OUTPUT)tests/hists_link.o
392LIB_OBJS += $(OUTPUT)tests/python-use.o
393LIB_OBJS += $(OUTPUT)tests/bp_signal.o
394LIB_OBJS += $(OUTPUT)tests/bp_signal_overflow.o
395LIB_OBJS += $(OUTPUT)tests/task-exit.o
396LIB_OBJS += $(OUTPUT)tests/sw-clock.o
397ifeq ($(ARCH),x86)
398LIB_OBJS += $(OUTPUT)tests/perf-time-to-tsc.o
399endif
400LIB_OBJS += $(OUTPUT)tests/code-reading.o
401LIB_OBJS += $(OUTPUT)tests/sample-parsing.o
402LIB_OBJS += $(OUTPUT)tests/parse-no-sample-id-all.o
403
404BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
405BUILTIN_OBJS += $(OUTPUT)builtin-bench.o
406# Benchmark modules
407BUILTIN_OBJS += $(OUTPUT)bench/sched-messaging.o
408BUILTIN_OBJS += $(OUTPUT)bench/sched-pipe.o
409ifeq ($(RAW_ARCH),x86_64)
410BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy-x86-64-asm.o
411BUILTIN_OBJS += $(OUTPUT)bench/mem-memset-x86-64-asm.o
412endif
413BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o
414BUILTIN_OBJS += $(OUTPUT)bench/mem-memset.o
415
416BUILTIN_OBJS += $(OUTPUT)builtin-diff.o
417BUILTIN_OBJS += $(OUTPUT)builtin-evlist.o
418BUILTIN_OBJS += $(OUTPUT)builtin-help.o
419BUILTIN_OBJS += $(OUTPUT)builtin-sched.o
420BUILTIN_OBJS += $(OUTPUT)builtin-buildid-list.o
421BUILTIN_OBJS += $(OUTPUT)builtin-buildid-cache.o
422BUILTIN_OBJS += $(OUTPUT)builtin-list.o
423BUILTIN_OBJS += $(OUTPUT)builtin-record.o
424BUILTIN_OBJS += $(OUTPUT)builtin-report.o
425BUILTIN_OBJS += $(OUTPUT)builtin-stat.o
426BUILTIN_OBJS += $(OUTPUT)builtin-timechart.o
427BUILTIN_OBJS += $(OUTPUT)builtin-top.o
428BUILTIN_OBJS += $(OUTPUT)builtin-script.o
429BUILTIN_OBJS += $(OUTPUT)builtin-probe.o
430BUILTIN_OBJS += $(OUTPUT)builtin-kmem.o
431BUILTIN_OBJS += $(OUTPUT)builtin-lock.o
432BUILTIN_OBJS += $(OUTPUT)builtin-kvm.o
433BUILTIN_OBJS += $(OUTPUT)builtin-inject.o
434BUILTIN_OBJS += $(OUTPUT)tests/builtin-test.o
435BUILTIN_OBJS += $(OUTPUT)builtin-mem.o
436
437PERFLIBS = $(LIB_FILE) $(LIBLK) $(LIBTRACEEVENT)
438
439# We choose to avoid "if .. else if .. else .. endif endif"
440# because maintaining the nesting to match is a pain. If
441# we had "elif" things would have been much nicer...
442
443-include arch/$(ARCH)/Makefile
444
445ifneq ($(OUTPUT),)
446 CFLAGS += -I$(OUTPUT)
447endif
448
449ifdef NO_LIBELF
450EXTLIBS := $(filter-out -lelf,$(EXTLIBS))
451
452# Remove ELF/DWARF dependent codes
453LIB_OBJS := $(filter-out $(OUTPUT)util/symbol-elf.o,$(LIB_OBJS))
454LIB_OBJS := $(filter-out $(OUTPUT)util/dwarf-aux.o,$(LIB_OBJS))
455LIB_OBJS := $(filter-out $(OUTPUT)util/probe-event.o,$(LIB_OBJS))
456LIB_OBJS := $(filter-out $(OUTPUT)util/probe-finder.o,$(LIB_OBJS))
457
458BUILTIN_OBJS := $(filter-out $(OUTPUT)builtin-probe.o,$(BUILTIN_OBJS))
459
460# Use minimal symbol handling
461LIB_OBJS += $(OUTPUT)util/symbol-minimal.o
462
463else # NO_LIBELF
464ifndef NO_DWARF
465 LIB_OBJS += $(OUTPUT)util/probe-finder.o
466 LIB_OBJS += $(OUTPUT)util/dwarf-aux.o
467endif # NO_DWARF
468endif # NO_LIBELF
469
470ifndef NO_LIBUNWIND
471 LIB_OBJS += $(OUTPUT)util/unwind.o
472endif
473LIB_OBJS += $(OUTPUT)tests/keep-tracking.o
474
475ifndef NO_LIBAUDIT
476 BUILTIN_OBJS += $(OUTPUT)builtin-trace.o
477endif
478
479ifndef NO_SLANG
480 LIB_OBJS += $(OUTPUT)ui/browser.o
481 LIB_OBJS += $(OUTPUT)ui/browsers/annotate.o
482 LIB_OBJS += $(OUTPUT)ui/browsers/hists.o
483 LIB_OBJS += $(OUTPUT)ui/browsers/map.o
484 LIB_OBJS += $(OUTPUT)ui/browsers/scripts.o
485 LIB_OBJS += $(OUTPUT)ui/tui/setup.o
486 LIB_OBJS += $(OUTPUT)ui/tui/util.o
487 LIB_OBJS += $(OUTPUT)ui/tui/helpline.o
488 LIB_OBJS += $(OUTPUT)ui/tui/progress.o
489 LIB_H += ui/browser.h
490 LIB_H += ui/browsers/map.h
491 LIB_H += ui/keysyms.h
492 LIB_H += ui/libslang.h
493endif
494
495ifndef NO_GTK2
496 ALL_PROGRAMS += $(OUTPUT)libperf-gtk.so
497
498 GTK_OBJS += $(OUTPUT)ui/gtk/browser.o
499 GTK_OBJS += $(OUTPUT)ui/gtk/hists.o
500 GTK_OBJS += $(OUTPUT)ui/gtk/setup.o
501 GTK_OBJS += $(OUTPUT)ui/gtk/util.o
502 GTK_OBJS += $(OUTPUT)ui/gtk/helpline.o
503 GTK_OBJS += $(OUTPUT)ui/gtk/progress.o
504 GTK_OBJS += $(OUTPUT)ui/gtk/annotate.o
505
506install-gtk: $(OUTPUT)libperf-gtk.so
507 $(call QUIET_INSTALL, 'GTK UI') \
508 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(libdir_SQ)'; \
509 $(INSTALL) $(OUTPUT)libperf-gtk.so '$(DESTDIR_SQ)$(libdir_SQ)'
510endif
511
512ifndef NO_LIBPERL
513 LIB_OBJS += $(OUTPUT)util/scripting-engines/trace-event-perl.o
514 LIB_OBJS += $(OUTPUT)scripts/perl/Perf-Trace-Util/Context.o
515endif
516
517ifndef NO_LIBPYTHON
518 LIB_OBJS += $(OUTPUT)util/scripting-engines/trace-event-python.o
519 LIB_OBJS += $(OUTPUT)scripts/python/Perf-Trace-Util/Context.o
520endif
521
522ifeq ($(NO_PERF_REGS),0)
523 ifeq ($(ARCH),x86)
524 LIB_H += arch/x86/include/perf_regs.h
525 endif
526endif
527
528ifndef NO_LIBNUMA
529 BUILTIN_OBJS += $(OUTPUT)bench/numa.o
530endif
531
532ifdef ASCIIDOC8
533 export ASCIIDOC8
534endif
535
536LIBS = -Wl,--whole-archive $(PERFLIBS) -Wl,--no-whole-archive -Wl,--start-group $(EXTLIBS) -Wl,--end-group
537
538export INSTALL SHELL_PATH
539
540### Build rules
541
542SHELL = $(SHELL_PATH)
543
544all: shell_compatibility_test $(ALL_PROGRAMS) $(LANG_BINDINGS) $(OTHER_PROGRAMS)
545
546please_set_SHELL_PATH_to_a_more_modern_shell:
547 @$$(:)
548
549shell_compatibility_test: please_set_SHELL_PATH_to_a_more_modern_shell
550
551strip: $(PROGRAMS) $(OUTPUT)perf
552 $(STRIP) $(STRIP_OPTS) $(PROGRAMS) $(OUTPUT)perf
553
554$(OUTPUT)perf.o: perf.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS
555 $(QUIET_CC)$(CC) -include $(OUTPUT)PERF-VERSION-FILE \
556 '-DPERF_HTML_PATH="$(htmldir_SQ)"' \
557 $(CFLAGS) -c $(filter %.c,$^) -o $@
558
559$(OUTPUT)perf: $(OUTPUT)perf.o $(BUILTIN_OBJS) $(PERFLIBS)
560 $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $(OUTPUT)perf.o \
561 $(BUILTIN_OBJS) $(LIBS) -o $@
562
563$(GTK_OBJS): $(OUTPUT)%.o: %.c $(LIB_H)
564 $(QUIET_CC)$(CC) -o $@ -c -fPIC $(CFLAGS) $(GTK_CFLAGS) $<
565
566$(OUTPUT)libperf-gtk.so: $(GTK_OBJS) $(PERFLIBS)
567 $(QUIET_LINK)$(CC) -o $@ -shared $(ALL_LDFLAGS) $(filter %.o,$^) $(GTK_LIBS)
568
569$(OUTPUT)builtin-help.o: builtin-help.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS
570 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
571 '-DPERF_HTML_PATH="$(htmldir_SQ)"' \
572 '-DPERF_MAN_PATH="$(mandir_SQ)"' \
573 '-DPERF_INFO_PATH="$(infodir_SQ)"' $<
574
575$(OUTPUT)builtin-timechart.o: builtin-timechart.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS
576 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
577 '-DPERF_HTML_PATH="$(htmldir_SQ)"' \
578 '-DPERF_MAN_PATH="$(mandir_SQ)"' \
579 '-DPERF_INFO_PATH="$(infodir_SQ)"' $<
580
581$(OUTPUT)common-cmds.h: util/generate-cmdlist.sh command-list.txt
582
583$(OUTPUT)common-cmds.h: $(wildcard Documentation/perf-*.txt)
584 $(QUIET_GEN). util/generate-cmdlist.sh > $@+ && mv $@+ $@
585
586$(SCRIPTS) : % : %.sh
587 $(QUIET_GEN)$(INSTALL) '$@.sh' '$(OUTPUT)$@'
588
589# These can record PERF_VERSION
590$(OUTPUT)perf.o perf.spec \
591 $(SCRIPTS) \
592 : $(OUTPUT)PERF-VERSION-FILE
593
594.SUFFIXES:
595
596#
597# If a target does not match any of the later rules then prefix it by $(OUTPUT)
598# This makes targets like 'make O=/tmp/perf perf.o' work in a natural way.
599#
600ifneq ($(OUTPUT),)
601%.o: $(OUTPUT)%.o
602 @echo " # Redirected target $@ => $(OUTPUT)$@"
603util/%.o: $(OUTPUT)util/%.o
604 @echo " # Redirected target $@ => $(OUTPUT)$@"
605bench/%.o: $(OUTPUT)bench/%.o
606 @echo " # Redirected target $@ => $(OUTPUT)$@"
607tests/%.o: $(OUTPUT)tests/%.o
608 @echo " # Redirected target $@ => $(OUTPUT)$@"
609endif
610
611# These two need to be here so that when O= is not used they take precedence
612# over the general rule for .o
613
614$(OUTPUT)util/%-flex.o: $(OUTPUT)util/%-flex.c $(OUTPUT)PERF-CFLAGS
615 $(QUIET_CC)$(CC) -o $@ -c -Iutil/ $(CFLAGS) -w $<
616
617$(OUTPUT)util/%-bison.o: $(OUTPUT)util/%-bison.c $(OUTPUT)PERF-CFLAGS
618 $(QUIET_CC)$(CC) -o $@ -c -Iutil/ $(CFLAGS) -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w $<
619
620$(OUTPUT)%.o: %.c $(OUTPUT)PERF-CFLAGS
621 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $<
622$(OUTPUT)%.i: %.c $(OUTPUT)PERF-CFLAGS
623 $(QUIET_CC)$(CC) -o $@ -E $(CFLAGS) $<
624$(OUTPUT)%.s: %.c $(OUTPUT)PERF-CFLAGS
625 $(QUIET_CC)$(CC) -o $@ -S $(CFLAGS) $<
626$(OUTPUT)%.o: %.S
627 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $<
628$(OUTPUT)%.s: %.S
629 $(QUIET_CC)$(CC) -o $@ -E $(CFLAGS) $<
630
631$(OUTPUT)util/exec_cmd.o: util/exec_cmd.c $(OUTPUT)PERF-CFLAGS
632 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
633 '-DPERF_EXEC_PATH="$(perfexecdir_SQ)"' \
634 '-DPREFIX="$(prefix_SQ)"' \
635 $<
636
637$(OUTPUT)tests/attr.o: tests/attr.c $(OUTPUT)PERF-CFLAGS
638 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
639 '-DBINDIR="$(bindir_SQ)"' -DPYTHON='"$(PYTHON_WORD)"' \
640 $<
641
642$(OUTPUT)tests/python-use.o: tests/python-use.c $(OUTPUT)PERF-CFLAGS
643 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
644 -DPYTHONPATH='"$(OUTPUT)python"' \
645 -DPYTHON='"$(PYTHON_WORD)"' \
646 $<
647
648$(OUTPUT)util/config.o: util/config.c $(OUTPUT)PERF-CFLAGS
649 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
650
651$(OUTPUT)ui/setup.o: ui/setup.c $(OUTPUT)PERF-CFLAGS
652 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DLIBDIR='"$(libdir_SQ)"' $<
653
654$(OUTPUT)ui/browser.o: ui/browser.c $(OUTPUT)PERF-CFLAGS
655 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $<
656
657$(OUTPUT)ui/browsers/annotate.o: ui/browsers/annotate.c $(OUTPUT)PERF-CFLAGS
658 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $<
659
660$(OUTPUT)ui/browsers/hists.o: ui/browsers/hists.c $(OUTPUT)PERF-CFLAGS
661 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $<
662
663$(OUTPUT)ui/browsers/map.o: ui/browsers/map.c $(OUTPUT)PERF-CFLAGS
664 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $<
665
666$(OUTPUT)ui/browsers/scripts.o: ui/browsers/scripts.c $(OUTPUT)PERF-CFLAGS
667 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $<
668
669$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS
670 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
671
672$(OUTPUT)util/parse-events.o: util/parse-events.c $(OUTPUT)PERF-CFLAGS
673 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-redundant-decls $<
674
675$(OUTPUT)util/scripting-engines/trace-event-perl.o: util/scripting-engines/trace-event-perl.c $(OUTPUT)PERF-CFLAGS
676 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow -Wno-undef -Wno-switch-default $<
677
678$(OUTPUT)scripts/perl/Perf-Trace-Util/Context.o: scripts/perl/Perf-Trace-Util/Context.c $(OUTPUT)PERF-CFLAGS
679 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs -Wno-undef -Wno-switch-default $<
680
681$(OUTPUT)util/scripting-engines/trace-event-python.o: util/scripting-engines/trace-event-python.c $(OUTPUT)PERF-CFLAGS
682 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow $<
683
684$(OUTPUT)scripts/python/Perf-Trace-Util/Context.o: scripts/python/Perf-Trace-Util/Context.c $(OUTPUT)PERF-CFLAGS
685 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs $<
686
687$(OUTPUT)perf-%: %.o $(PERFLIBS)
688 $(QUIET_LINK)$(CC) $(CFLAGS) -o $@ $(LDFLAGS) $(filter %.o,$^) $(LIBS)
689
690$(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H)
691$(patsubst perf-%,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h)
692
693# we compile into subdirectories. if the target directory is not the source directory, they might not exists. So
694# we depend the various files onto their directories.
695DIRECTORY_DEPS = $(LIB_OBJS) $(BUILTIN_OBJS) $(GTK_OBJS)
696DIRECTORY_DEPS += $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h
697$(DIRECTORY_DEPS): | $(sort $(dir $(DIRECTORY_DEPS)))
698# In the second step, we make a rule to actually create these directories
699$(sort $(dir $(DIRECTORY_DEPS))):
700 $(QUIET_MKDIR)$(MKDIR) -p $@ 2>/dev/null
701
702$(LIB_FILE): $(LIB_OBJS)
703 $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIB_OBJS)
704
705# libtraceevent.a
706TE_SOURCES = $(wildcard $(TRACE_EVENT_DIR)*.[ch])
707
708$(LIBTRACEEVENT): $(TE_SOURCES)
709 $(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(QUIET_SUBDIR1) O=$(OUTPUT) libtraceevent.a
710
711$(LIBTRACEEVENT)-clean:
712 $(call QUIET_CLEAN, libtraceevent)
713 @$(MAKE) -C $(TRACE_EVENT_DIR) O=$(OUTPUT) clean >/dev/null
714
715LIBLK_SOURCES = $(wildcard $(LK_PATH)*.[ch])
716
717# if subdir is set, we've been called from above so target has been built
718# already
719$(LIBLK): $(LIBLK_SOURCES)
720ifeq ($(subdir),)
721 $(QUIET_SUBDIR0)$(LK_DIR) $(QUIET_SUBDIR1) O=$(OUTPUT) liblk.a
722endif
723
724$(LIBLK)-clean:
725ifeq ($(subdir),)
726 $(call QUIET_CLEAN, liblk)
727 @$(MAKE) -C $(LK_DIR) O=$(OUTPUT) clean >/dev/null
728endif
729
730help:
731 @echo 'Perf make targets:'
732 @echo ' doc - make *all* documentation (see below)'
733 @echo ' man - make manpage documentation (access with man <foo>)'
734 @echo ' html - make html documentation'
735 @echo ' info - make GNU info documentation (access with info <foo>)'
736 @echo ' pdf - make pdf documentation'
737 @echo ' TAGS - use etags to make tag information for source browsing'
738 @echo ' tags - use ctags to make tag information for source browsing'
739 @echo ' cscope - use cscope to make interactive browsing database'
740 @echo ''
741 @echo 'Perf install targets:'
742 @echo ' NOTE: documentation build requires asciidoc, xmlto packages to be installed'
743 @echo ' HINT: use "make prefix=<path> <install target>" to install to a particular'
744 @echo ' path like make prefix=/usr/local install install-doc'
745 @echo ' install - install compiled binaries'
746 @echo ' install-doc - install *all* documentation'
747 @echo ' install-man - install manpage documentation'
748 @echo ' install-html - install html documentation'
749 @echo ' install-info - install GNU info documentation'
750 @echo ' install-pdf - install pdf documentation'
751 @echo ''
752 @echo ' quick-install-doc - alias for quick-install-man'
753 @echo ' quick-install-man - install the documentation quickly'
754 @echo ' quick-install-html - install the html documentation quickly'
755 @echo ''
756 @echo 'Perf maintainer targets:'
757 @echo ' clean - clean all binary objects and build output'
758
759
760DOC_TARGETS := doc man html info pdf
761
762INSTALL_DOC_TARGETS := $(patsubst %,install-%,$(DOC_TARGETS)) try-install-man
763INSTALL_DOC_TARGETS += quick-install-doc quick-install-man quick-install-html
764
765# 'make doc' should call 'make -C Documentation all'
766$(DOC_TARGETS):
767 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) $(@:doc=all)
768
769TAGS:
770 $(RM) TAGS
771 $(FIND) . -name '*.[hcS]' -print | xargs etags -a
772
773tags:
774 $(RM) tags
775 $(FIND) . -name '*.[hcS]' -print | xargs ctags -a
776
777cscope:
778 $(RM) cscope*
779 $(FIND) . -name '*.[hcS]' -print | xargs cscope -b
780
781### Detect prefix changes
782TRACK_CFLAGS = $(subst ','\'',$(CFLAGS)):\
783 $(bindir_SQ):$(perfexecdir_SQ):$(template_dir_SQ):$(prefix_SQ)
784
785$(OUTPUT)PERF-CFLAGS: .FORCE-PERF-CFLAGS
786 @FLAGS='$(TRACK_CFLAGS)'; \
787 if test x"$$FLAGS" != x"`cat $(OUTPUT)PERF-CFLAGS 2>/dev/null`" ; then \
788 echo 1>&2 " FLAGS: * new build flags or prefix"; \
789 echo "$$FLAGS" >$(OUTPUT)PERF-CFLAGS; \
790 fi
791
792### Testing rules
793
794# GNU make supports exporting all variables by "export" without parameters.
795# However, the environment gets quite big, and some programs have problems
796# with that.
797
798check: $(OUTPUT)common-cmds.h
799 if sparse; \
800 then \
801 for i in *.c */*.c; \
802 do \
803 sparse $(CFLAGS) $(SPARSE_FLAGS) $$i || exit; \
804 done; \
805 else \
806 exit 1; \
807 fi
808
809### Installation rules
810
811install-gtk:
812
813install-bin: all install-gtk
814 $(call QUIET_INSTALL, binaries) \
815 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)'; \
816 $(INSTALL) $(OUTPUT)perf '$(DESTDIR_SQ)$(bindir_SQ)'; \
817 $(LN) '$(DESTDIR_SQ)$(bindir_SQ)/perf' '$(DESTDIR_SQ)$(bindir_SQ)/trace'
818 $(call QUIET_INSTALL, libexec) \
819 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
820 $(call QUIET_INSTALL, perf-archive) \
821 $(INSTALL) $(OUTPUT)perf-archive -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
822ifndef NO_LIBPERL
823 $(call QUIET_INSTALL, perl-scripts) \
824 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'; \
825 $(INSTALL) scripts/perl/Perf-Trace-Util/lib/Perf/Trace/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'; \
826 $(INSTALL) scripts/perl/*.pl -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl'; \
827 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/bin'; \
828 $(INSTALL) scripts/perl/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/bin'
829endif
830ifndef NO_LIBPYTHON
831 $(call QUIET_INSTALL, python-scripts) \
832 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/Perf-Trace-Util/lib/Perf/Trace'; \
833 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin'; \
834 $(INSTALL) scripts/python/Perf-Trace-Util/lib/Perf/Trace/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/Perf-Trace-Util/lib/Perf/Trace'; \
835 $(INSTALL) scripts/python/*.py -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python'; \
836 $(INSTALL) scripts/python/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin'
837endif
838 $(call QUIET_INSTALL, bash_completion-script) \
839 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d'; \
840 $(INSTALL) bash_completion '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d/perf'
841 $(call QUIET_INSTALL, tests) \
842 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'; \
843 $(INSTALL) tests/attr.py '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'; \
844 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'; \
845 $(INSTALL) tests/attr/* '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'
846
847install: install-bin try-install-man
848
849install-python_ext:
850 $(PYTHON_WORD) util/setup.py --quiet install --root='/$(DESTDIR_SQ)'
851
852# 'make install-doc' should call 'make -C Documentation install'
853$(INSTALL_DOC_TARGETS):
854 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) $(@:-doc=)
855
856### Cleaning rules
857
858#
859# This is here, not in config/Makefile, because config/Makefile does
860# not get included for the clean target:
861#
862config-clean:
863 $(call QUIET_CLEAN, config)
864 @$(MAKE) -C config/feature-checks clean >/dev/null
865
866clean: $(LIBTRACEEVENT)-clean $(LIBLK)-clean config-clean
867 $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf.o $(LANG_BINDINGS) $(GTK_OBJS)
868 $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf
869 $(call QUIET_CLEAN, core-gen) $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex*
870 $(call QUIET_CLEAN, Documentation)
871 @$(MAKE) -C Documentation O=$(OUTPUT) clean >/dev/null
872 $(python-clean)
873
874#
875# Trick: if ../../.git does not exist - we are building out of tree for example,
876# then force version regeneration:
877#
878ifeq ($(wildcard ../../.git/HEAD),)
879 GIT-HEAD-PHONY = ../../.git/HEAD
880else
881 GIT-HEAD-PHONY =
882endif
883
884.PHONY: all install clean config-clean strip install-gtk
885.PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell
886.PHONY: $(GIT-HEAD-PHONY) TAGS tags cscope .FORCE-PERF-CFLAGS
887
diff --git a/tools/perf/arch/x86/include/perf_regs.h b/tools/perf/arch/x86/include/perf_regs.h
index 7fcdcdbee917..e84ca76aae77 100644
--- a/tools/perf/arch/x86/include/perf_regs.h
+++ b/tools/perf/arch/x86/include/perf_regs.h
@@ -5,7 +5,7 @@
5#include "../../util/types.h" 5#include "../../util/types.h"
6#include <asm/perf_regs.h> 6#include <asm/perf_regs.h>
7 7
8#ifndef ARCH_X86_64 8#ifndef HAVE_ARCH_X86_64_SUPPORT
9#define PERF_REGS_MASK ((1ULL << PERF_REG_X86_32_MAX) - 1) 9#define PERF_REGS_MASK ((1ULL << PERF_REG_X86_32_MAX) - 1)
10#else 10#else
11#define REG_NOSUPPORT ((1ULL << PERF_REG_X86_DS) | \ 11#define REG_NOSUPPORT ((1ULL << PERF_REG_X86_DS) | \
@@ -52,7 +52,7 @@ static inline const char *perf_reg_name(int id)
52 return "FS"; 52 return "FS";
53 case PERF_REG_X86_GS: 53 case PERF_REG_X86_GS:
54 return "GS"; 54 return "GS";
55#ifdef ARCH_X86_64 55#ifdef HAVE_ARCH_X86_64_SUPPORT
56 case PERF_REG_X86_R8: 56 case PERF_REG_X86_R8:
57 return "R8"; 57 return "R8";
58 case PERF_REG_X86_R9: 58 case PERF_REG_X86_R9:
@@ -69,7 +69,7 @@ static inline const char *perf_reg_name(int id)
69 return "R14"; 69 return "R14";
70 case PERF_REG_X86_R15: 70 case PERF_REG_X86_R15:
71 return "R15"; 71 return "R15";
72#endif /* ARCH_X86_64 */ 72#endif /* HAVE_ARCH_X86_64_SUPPORT */
73 default: 73 default:
74 return NULL; 74 return NULL;
75 } 75 }
diff --git a/tools/perf/arch/x86/util/unwind.c b/tools/perf/arch/x86/util/unwind.c
index 78d956eff96f..456a88cf5b37 100644
--- a/tools/perf/arch/x86/util/unwind.c
+++ b/tools/perf/arch/x86/util/unwind.c
@@ -4,7 +4,7 @@
4#include "perf_regs.h" 4#include "perf_regs.h"
5#include "../../util/unwind.h" 5#include "../../util/unwind.h"
6 6
7#ifdef ARCH_X86_64 7#ifdef HAVE_ARCH_X86_64_SUPPORT
8int unwind__arch_reg_id(int regnum) 8int unwind__arch_reg_id(int regnum)
9{ 9{
10 int id; 10 int id;
@@ -108,4 +108,4 @@ int unwind__arch_reg_id(int regnum)
108 108
109 return id; 109 return id;
110} 110}
111#endif /* ARCH_X86_64 */ 111#endif /* HAVE_ARCH_X86_64_SUPPORT */
diff --git a/tools/perf/bash_completion b/tools/perf/bash_completion
index 56e6a12aab59..62e157db2e2b 100644
--- a/tools/perf/bash_completion
+++ b/tools/perf/bash_completion
@@ -1,17 +1,87 @@
1# perf completion 1# perf completion
2 2
3function_exists() 3# Taken from git.git's completion script.
4__my_reassemble_comp_words_by_ref()
4{ 5{
5 declare -F $1 > /dev/null 6 local exclude i j first
6 return $? 7 # Which word separators to exclude?
8 exclude="${1//[^$COMP_WORDBREAKS]}"
9 cword_=$COMP_CWORD
10 if [ -z "$exclude" ]; then
11 words_=("${COMP_WORDS[@]}")
12 return
13 fi
14 # List of word completion separators has shrunk;
15 # re-assemble words to complete.
16 for ((i=0, j=0; i < ${#COMP_WORDS[@]}; i++, j++)); do
17 # Append each nonempty word consisting of just
18 # word separator characters to the current word.
19 first=t
20 while
21 [ $i -gt 0 ] &&
22 [ -n "${COMP_WORDS[$i]}" ] &&
23 # word consists of excluded word separators
24 [ "${COMP_WORDS[$i]//[^$exclude]}" = "${COMP_WORDS[$i]}" ]
25 do
26 # Attach to the previous token,
27 # unless the previous token is the command name.
28 if [ $j -ge 2 ] && [ -n "$first" ]; then
29 ((j--))
30 fi
31 first=
32 words_[$j]=${words_[j]}${COMP_WORDS[i]}
33 if [ $i = $COMP_CWORD ]; then
34 cword_=$j
35 fi
36 if (($i < ${#COMP_WORDS[@]} - 1)); then
37 ((i++))
38 else
39 # Done.
40 return
41 fi
42 done
43 words_[$j]=${words_[j]}${COMP_WORDS[i]}
44 if [ $i = $COMP_CWORD ]; then
45 cword_=$j
46 fi
47 done
7} 48}
8 49
9function_exists __ltrim_colon_completions || 50type _get_comp_words_by_ref &>/dev/null ||
51_get_comp_words_by_ref()
52{
53 local exclude cur_ words_ cword_
54 if [ "$1" = "-n" ]; then
55 exclude=$2
56 shift 2
57 fi
58 __my_reassemble_comp_words_by_ref "$exclude"
59 cur_=${words_[cword_]}
60 while [ $# -gt 0 ]; do
61 case "$1" in
62 cur)
63 cur=$cur_
64 ;;
65 prev)
66 prev=${words_[$cword_-1]}
67 ;;
68 words)
69 words=("${words_[@]}")
70 ;;
71 cword)
72 cword=$cword_
73 ;;
74 esac
75 shift
76 done
77}
78
79type __ltrim_colon_completions &>/dev/null ||
10__ltrim_colon_completions() 80__ltrim_colon_completions()
11{ 81{
12 if [[ "$1" == *:* && "$COMP_WORDBREAKS" == *:* ]]; then 82 if [[ "$1" == *:* && "$COMP_WORDBREAKS" == *:* ]]; then
13 # Remove colon-word prefix from COMPREPLY items 83 # Remove colon-word prefix from COMPREPLY items
14 local colon_word=${1%${1##*:}} 84 local colon_word=${1%"${1##*:}"}
15 local i=${#COMPREPLY[*]} 85 local i=${#COMPREPLY[*]}
16 while [[ $((--i)) -ge 0 ]]; do 86 while [[ $((--i)) -ge 0 ]]; do
17 COMPREPLY[$i]=${COMPREPLY[$i]#"$colon_word"} 87 COMPREPLY[$i]=${COMPREPLY[$i]#"$colon_word"}
@@ -19,23 +89,18 @@ __ltrim_colon_completions()
19 fi 89 fi
20} 90}
21 91
22have perf && 92type perf &>/dev/null &&
23_perf() 93_perf()
24{ 94{
25 local cur prev cmd 95 local cur words cword prev cmd
26 96
27 COMPREPLY=() 97 COMPREPLY=()
28 if function_exists _get_comp_words_by_ref; then 98 _get_comp_words_by_ref -n =: cur words cword prev
29 _get_comp_words_by_ref -n : cur prev
30 else
31 cur=$(_get_cword :)
32 prev=${COMP_WORDS[COMP_CWORD-1]}
33 fi
34 99
35 cmd=${COMP_WORDS[0]} 100 cmd=${words[0]}
36 101
37 # List perf subcommands or long options 102 # List perf subcommands or long options
38 if [ $COMP_CWORD -eq 1 ]; then 103 if [ $cword -eq 1 ]; then
39 if [[ $cur == --* ]]; then 104 if [[ $cur == --* ]]; then
40 COMPREPLY=( $( compgen -W '--help --version \ 105 COMPREPLY=( $( compgen -W '--help --version \
41 --exec-path --html-path --paginate --no-pager \ 106 --exec-path --html-path --paginate --no-pager \
@@ -45,18 +110,17 @@ _perf()
45 COMPREPLY=( $( compgen -W '$cmds' -- "$cur" ) ) 110 COMPREPLY=( $( compgen -W '$cmds' -- "$cur" ) )
46 fi 111 fi
47 # List possible events for -e option 112 # List possible events for -e option
48 elif [[ $prev == "-e" && "${COMP_WORDS[1]}" == @(record|stat|top) ]]; then 113 elif [[ $prev == "-e" && "${words[1]}" == @(record|stat|top) ]]; then
49 evts=$($cmd list --raw-dump) 114 evts=$($cmd list --raw-dump)
50 COMPREPLY=( $( compgen -W '$evts' -- "$cur" ) ) 115 COMPREPLY=( $( compgen -W '$evts' -- "$cur" ) )
51 __ltrim_colon_completions $cur 116 __ltrim_colon_completions $cur
52 # List long option names 117 # List long option names
53 elif [[ $cur == --* ]]; then 118 elif [[ $cur == --* ]]; then
54 subcmd=${COMP_WORDS[1]} 119 subcmd=${words[1]}
55 opts=$($cmd $subcmd --list-opts) 120 opts=$($cmd $subcmd --list-opts)
56 COMPREPLY=( $( compgen -W '$opts' -- "$cur" ) ) 121 COMPREPLY=( $( compgen -W '$opts' -- "$cur" ) )
57 # Fall down to list regular files
58 else
59 _filedir
60 fi 122 fi
61} && 123} &&
62complete -F _perf perf 124
125complete -o bashdefault -o default -o nospace -F _perf perf 2>/dev/null \
126 || complete -o default -o nospace -F _perf perf
diff --git a/tools/perf/bench/mem-memcpy-arch.h b/tools/perf/bench/mem-memcpy-arch.h
index a72e36cb5394..57b4ed871459 100644
--- a/tools/perf/bench/mem-memcpy-arch.h
+++ b/tools/perf/bench/mem-memcpy-arch.h
@@ -1,5 +1,5 @@
1 1
2#ifdef ARCH_X86_64 2#ifdef HAVE_ARCH_X86_64_SUPPORT
3 3
4#define MEMCPY_FN(fn, name, desc) \ 4#define MEMCPY_FN(fn, name, desc) \
5 extern void *fn(void *, const void *, size_t); 5 extern void *fn(void *, const void *, size_t);
diff --git a/tools/perf/bench/mem-memcpy.c b/tools/perf/bench/mem-memcpy.c
index 8cdca43016b2..5ce71d3b72cf 100644
--- a/tools/perf/bench/mem-memcpy.c
+++ b/tools/perf/bench/mem-memcpy.c
@@ -58,7 +58,7 @@ struct routine routines[] = {
58 { "default", 58 { "default",
59 "Default memcpy() provided by glibc", 59 "Default memcpy() provided by glibc",
60 memcpy }, 60 memcpy },
61#ifdef ARCH_X86_64 61#ifdef HAVE_ARCH_X86_64_SUPPORT
62 62
63#define MEMCPY_FN(fn, name, desc) { name, desc, fn }, 63#define MEMCPY_FN(fn, name, desc) { name, desc, fn },
64#include "mem-memcpy-x86-64-asm-def.h" 64#include "mem-memcpy-x86-64-asm-def.h"
diff --git a/tools/perf/bench/mem-memset-arch.h b/tools/perf/bench/mem-memset-arch.h
index a040fa77665b..633800cb0dcb 100644
--- a/tools/perf/bench/mem-memset-arch.h
+++ b/tools/perf/bench/mem-memset-arch.h
@@ -1,5 +1,5 @@
1 1
2#ifdef ARCH_X86_64 2#ifdef HAVE_ARCH_X86_64_SUPPORT
3 3
4#define MEMSET_FN(fn, name, desc) \ 4#define MEMSET_FN(fn, name, desc) \
5 extern void *fn(void *, int, size_t); 5 extern void *fn(void *, int, size_t);
diff --git a/tools/perf/bench/mem-memset.c b/tools/perf/bench/mem-memset.c
index 4a2f12081964..9af79d2b18e5 100644
--- a/tools/perf/bench/mem-memset.c
+++ b/tools/perf/bench/mem-memset.c
@@ -58,7 +58,7 @@ static const struct routine routines[] = {
58 { "default", 58 { "default",
59 "Default memset() provided by glibc", 59 "Default memset() provided by glibc",
60 memset }, 60 memset },
61#ifdef ARCH_X86_64 61#ifdef HAVE_ARCH_X86_64_SUPPORT
62 62
63#define MEMSET_FN(fn, name, desc) { name, desc, fn }, 63#define MEMSET_FN(fn, name, desc) { name, desc, fn },
64#include "mem-memset-x86-64-asm-def.h" 64#include "mem-memset-x86-64-asm-def.h"
diff --git a/tools/perf/bench/numa.c b/tools/perf/bench/numa.c
index 30d1c3225b46..64fa01cfc34d 100644
--- a/tools/perf/bench/numa.c
+++ b/tools/perf/bench/numa.c
@@ -429,14 +429,14 @@ static int parse_cpu_list(const char *arg)
429 return 0; 429 return 0;
430} 430}
431 431
432static void parse_setup_cpu_list(void) 432static int parse_setup_cpu_list(void)
433{ 433{
434 struct thread_data *td; 434 struct thread_data *td;
435 char *str0, *str; 435 char *str0, *str;
436 int t; 436 int t;
437 437
438 if (!g->p.cpu_list_str) 438 if (!g->p.cpu_list_str)
439 return; 439 return 0;
440 440
441 dprintf("g->p.nr_tasks: %d\n", g->p.nr_tasks); 441 dprintf("g->p.nr_tasks: %d\n", g->p.nr_tasks);
442 442
@@ -500,8 +500,12 @@ static void parse_setup_cpu_list(void)
500 500
501 dprintf("CPUs: %d_%d-%d#%dx%d\n", bind_cpu_0, bind_len, bind_cpu_1, step, mul); 501 dprintf("CPUs: %d_%d-%d#%dx%d\n", bind_cpu_0, bind_len, bind_cpu_1, step, mul);
502 502
503 BUG_ON(bind_cpu_0 < 0 || bind_cpu_0 >= g->p.nr_cpus); 503 if (bind_cpu_0 >= g->p.nr_cpus || bind_cpu_1 >= g->p.nr_cpus) {
504 BUG_ON(bind_cpu_1 < 0 || bind_cpu_1 >= g->p.nr_cpus); 504 printf("\nTest not applicable, system has only %d CPUs.\n", g->p.nr_cpus);
505 return -1;
506 }
507
508 BUG_ON(bind_cpu_0 < 0 || bind_cpu_1 < 0);
505 BUG_ON(bind_cpu_0 > bind_cpu_1); 509 BUG_ON(bind_cpu_0 > bind_cpu_1);
506 510
507 for (bind_cpu = bind_cpu_0; bind_cpu <= bind_cpu_1; bind_cpu += step) { 511 for (bind_cpu = bind_cpu_0; bind_cpu <= bind_cpu_1; bind_cpu += step) {
@@ -541,6 +545,7 @@ out:
541 printf("# NOTE: %d tasks bound, %d tasks unbound\n", t, g->p.nr_tasks - t); 545 printf("# NOTE: %d tasks bound, %d tasks unbound\n", t, g->p.nr_tasks - t);
542 546
543 free(str0); 547 free(str0);
548 return 0;
544} 549}
545 550
546static int parse_cpus_opt(const struct option *opt __maybe_unused, 551static int parse_cpus_opt(const struct option *opt __maybe_unused,
@@ -561,14 +566,14 @@ static int parse_node_list(const char *arg)
561 return 0; 566 return 0;
562} 567}
563 568
564static void parse_setup_node_list(void) 569static int parse_setup_node_list(void)
565{ 570{
566 struct thread_data *td; 571 struct thread_data *td;
567 char *str0, *str; 572 char *str0, *str;
568 int t; 573 int t;
569 574
570 if (!g->p.node_list_str) 575 if (!g->p.node_list_str)
571 return; 576 return 0;
572 577
573 dprintf("g->p.nr_tasks: %d\n", g->p.nr_tasks); 578 dprintf("g->p.nr_tasks: %d\n", g->p.nr_tasks);
574 579
@@ -619,8 +624,12 @@ static void parse_setup_node_list(void)
619 624
620 dprintf("NODEs: %d-%d #%d\n", bind_node_0, bind_node_1, step); 625 dprintf("NODEs: %d-%d #%d\n", bind_node_0, bind_node_1, step);
621 626
622 BUG_ON(bind_node_0 < 0 || bind_node_0 >= g->p.nr_nodes); 627 if (bind_node_0 >= g->p.nr_nodes || bind_node_1 >= g->p.nr_nodes) {
623 BUG_ON(bind_node_1 < 0 || bind_node_1 >= g->p.nr_nodes); 628 printf("\nTest not applicable, system has only %d nodes.\n", g->p.nr_nodes);
629 return -1;
630 }
631
632 BUG_ON(bind_node_0 < 0 || bind_node_1 < 0);
624 BUG_ON(bind_node_0 > bind_node_1); 633 BUG_ON(bind_node_0 > bind_node_1);
625 634
626 for (bind_node = bind_node_0; bind_node <= bind_node_1; bind_node += step) { 635 for (bind_node = bind_node_0; bind_node <= bind_node_1; bind_node += step) {
@@ -651,6 +660,7 @@ out:
651 printf("# NOTE: %d tasks mem-bound, %d tasks unbound\n", t, g->p.nr_tasks - t); 660 printf("# NOTE: %d tasks mem-bound, %d tasks unbound\n", t, g->p.nr_tasks - t);
652 661
653 free(str0); 662 free(str0);
663 return 0;
654} 664}
655 665
656static int parse_nodes_opt(const struct option *opt __maybe_unused, 666static int parse_nodes_opt(const struct option *opt __maybe_unused,
@@ -1356,8 +1366,8 @@ static int init(void)
1356 init_thread_data(); 1366 init_thread_data();
1357 1367
1358 tprintf("#\n"); 1368 tprintf("#\n");
1359 parse_setup_cpu_list(); 1369 if (parse_setup_cpu_list() || parse_setup_node_list())
1360 parse_setup_node_list(); 1370 return -1;
1361 tprintf("#\n"); 1371 tprintf("#\n");
1362 1372
1363 print_summary(); 1373 print_summary();
@@ -1600,7 +1610,6 @@ static int run_bench_numa(const char *name, const char **argv)
1600 return 0; 1610 return 0;
1601 1611
1602err: 1612err:
1603 usage_with_options(numa_usage, options);
1604 return -1; 1613 return -1;
1605} 1614}
1606 1615
@@ -1701,8 +1710,7 @@ static int bench_all(void)
1701 BUG_ON(ret < 0); 1710 BUG_ON(ret < 0);
1702 1711
1703 for (i = 0; i < nr; i++) { 1712 for (i = 0; i < nr; i++) {
1704 if (run_bench_numa(tests[i][0], tests[i] + 1)) 1713 run_bench_numa(tests[i][0], tests[i] + 1);
1705 return -1;
1706 } 1714 }
1707 1715
1708 printf("\n"); 1716 printf("\n");
diff --git a/tools/perf/bench/sched-pipe.c b/tools/perf/bench/sched-pipe.c
index 69cfba8d4c6c..07a8d7646a15 100644
--- a/tools/perf/bench/sched-pipe.c
+++ b/tools/perf/bench/sched-pipe.c
@@ -7,9 +7,7 @@
7 * Based on pipe-test-1m.c by Ingo Molnar <mingo@redhat.com> 7 * Based on pipe-test-1m.c by Ingo Molnar <mingo@redhat.com>
8 * http://people.redhat.com/mingo/cfs-scheduler/tools/pipe-test-1m.c 8 * http://people.redhat.com/mingo/cfs-scheduler/tools/pipe-test-1m.c
9 * Ported to perf by Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp> 9 * Ported to perf by Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
10 *
11 */ 10 */
12
13#include "../perf.h" 11#include "../perf.h"
14#include "../util/util.h" 12#include "../util/util.h"
15#include "../util/parse-options.h" 13#include "../util/parse-options.h"
@@ -28,12 +26,24 @@
28#include <sys/time.h> 26#include <sys/time.h>
29#include <sys/types.h> 27#include <sys/types.h>
30 28
29#include <pthread.h>
30
31struct thread_data {
32 int nr;
33 int pipe_read;
34 int pipe_write;
35 pthread_t pthread;
36};
37
31#define LOOPS_DEFAULT 1000000 38#define LOOPS_DEFAULT 1000000
32static int loops = LOOPS_DEFAULT; 39static int loops = LOOPS_DEFAULT;
40
41/* Use processes by default: */
42static bool threaded;
33 43
34static const struct option options[] = { 44static const struct option options[] = {
35 OPT_INTEGER('l', "loop", &loops, 45 OPT_INTEGER('l', "loop", &loops, "Specify number of loops"),
36 "Specify number of loops"), 46 OPT_BOOLEAN('T', "threaded", &threaded, "Specify threads/process based task setup"),
37 OPT_END() 47 OPT_END()
38}; 48};
39 49
@@ -42,13 +52,37 @@ static const char * const bench_sched_pipe_usage[] = {
42 NULL 52 NULL
43}; 53};
44 54
45int bench_sched_pipe(int argc, const char **argv, 55static void *worker_thread(void *__tdata)
46 const char *prefix __maybe_unused)
47{ 56{
48 int pipe_1[2], pipe_2[2]; 57 struct thread_data *td = __tdata;
49 int m = 0, i; 58 int m = 0, i;
59 int ret;
60
61 for (i = 0; i < loops; i++) {
62 if (!td->nr) {
63 ret = read(td->pipe_read, &m, sizeof(int));
64 BUG_ON(ret != sizeof(int));
65 ret = write(td->pipe_write, &m, sizeof(int));
66 BUG_ON(ret != sizeof(int));
67 } else {
68 ret = write(td->pipe_write, &m, sizeof(int));
69 BUG_ON(ret != sizeof(int));
70 ret = read(td->pipe_read, &m, sizeof(int));
71 BUG_ON(ret != sizeof(int));
72 }
73 }
74
75 return NULL;
76}
77
78int bench_sched_pipe(int argc, const char **argv, const char *prefix __maybe_unused)
79{
80 struct thread_data threads[2], *td;
81 int pipe_1[2], pipe_2[2];
50 struct timeval start, stop, diff; 82 struct timeval start, stop, diff;
51 unsigned long long result_usec = 0; 83 unsigned long long result_usec = 0;
84 int nr_threads = 2;
85 int t;
52 86
53 /* 87 /*
54 * why does "ret" exist? 88 * why does "ret" exist?
@@ -58,43 +92,66 @@ int bench_sched_pipe(int argc, const char **argv,
58 int __maybe_unused ret, wait_stat; 92 int __maybe_unused ret, wait_stat;
59 pid_t pid, retpid __maybe_unused; 93 pid_t pid, retpid __maybe_unused;
60 94
61 argc = parse_options(argc, argv, options, 95 argc = parse_options(argc, argv, options, bench_sched_pipe_usage, 0);
62 bench_sched_pipe_usage, 0);
63 96
64 BUG_ON(pipe(pipe_1)); 97 BUG_ON(pipe(pipe_1));
65 BUG_ON(pipe(pipe_2)); 98 BUG_ON(pipe(pipe_2));
66 99
67 pid = fork();
68 assert(pid >= 0);
69
70 gettimeofday(&start, NULL); 100 gettimeofday(&start, NULL);
71 101
72 if (!pid) { 102 for (t = 0; t < nr_threads; t++) {
73 for (i = 0; i < loops; i++) { 103 td = threads + t;
74 ret = read(pipe_1[0], &m, sizeof(int)); 104
75 ret = write(pipe_2[1], &m, sizeof(int)); 105 td->nr = t;
76 } 106
77 } else { 107 if (t == 0) {
78 for (i = 0; i < loops; i++) { 108 td->pipe_read = pipe_1[0];
79 ret = write(pipe_1[1], &m, sizeof(int)); 109 td->pipe_write = pipe_2[1];
80 ret = read(pipe_2[0], &m, sizeof(int)); 110 } else {
111 td->pipe_write = pipe_1[1];
112 td->pipe_read = pipe_2[0];
81 } 113 }
82 } 114 }
83 115
84 gettimeofday(&stop, NULL);
85 timersub(&stop, &start, &diff);
86 116
87 if (pid) { 117 if (threaded) {
118
119 for (t = 0; t < nr_threads; t++) {
120 td = threads + t;
121
122 ret = pthread_create(&td->pthread, NULL, worker_thread, td);
123 BUG_ON(ret);
124 }
125
126 for (t = 0; t < nr_threads; t++) {
127 td = threads + t;
128
129 ret = pthread_join(td->pthread, NULL);
130 BUG_ON(ret);
131 }
132
133 } else {
134 pid = fork();
135 assert(pid >= 0);
136
137 if (!pid) {
138 worker_thread(threads + 0);
139 exit(0);
140 } else {
141 worker_thread(threads + 1);
142 }
143
88 retpid = waitpid(pid, &wait_stat, 0); 144 retpid = waitpid(pid, &wait_stat, 0);
89 assert((retpid == pid) && WIFEXITED(wait_stat)); 145 assert((retpid == pid) && WIFEXITED(wait_stat));
90 } else {
91 exit(0);
92 } 146 }
93 147
148 gettimeofday(&stop, NULL);
149 timersub(&stop, &start, &diff);
150
94 switch (bench_format) { 151 switch (bench_format) {
95 case BENCH_FORMAT_DEFAULT: 152 case BENCH_FORMAT_DEFAULT:
96 printf("# Executed %d pipe operations between two tasks\n\n", 153 printf("# Executed %d pipe operations between two %s\n\n",
97 loops); 154 loops, threaded ? "threads" : "processes");
98 155
99 result_usec = diff.tv_sec * 1000000; 156 result_usec = diff.tv_sec * 1000000;
100 result_usec += diff.tv_usec; 157 result_usec += diff.tv_usec;
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 0393d9800516..94f9a8e78117 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -30,6 +30,7 @@
30#include "util/tool.h" 30#include "util/tool.h"
31#include "arch/common.h" 31#include "arch/common.h"
32 32
33#include <dlfcn.h>
33#include <linux/bitmap.h> 34#include <linux/bitmap.h>
34 35
35struct perf_annotate { 36struct perf_annotate {
@@ -142,8 +143,18 @@ find_next:
142 143
143 if (use_browser == 2) { 144 if (use_browser == 2) {
144 int ret; 145 int ret;
146 int (*annotate)(struct hist_entry *he,
147 struct perf_evsel *evsel,
148 struct hist_browser_timer *hbt);
149
150 annotate = dlsym(perf_gtk_handle,
151 "hist_entry__gtk_annotate");
152 if (annotate == NULL) {
153 ui__error("GTK browser not found!\n");
154 return;
155 }
145 156
146 ret = hist_entry__gtk_annotate(he, evsel, NULL); 157 ret = annotate(he, evsel, NULL);
147 if (!ret || !ann->skip_missing) 158 if (!ret || !ann->skip_missing)
148 return; 159 return;
149 160
@@ -247,8 +258,17 @@ static int __cmd_annotate(struct perf_annotate *ann)
247 goto out_delete; 258 goto out_delete;
248 } 259 }
249 260
250 if (use_browser == 2) 261 if (use_browser == 2) {
251 perf_gtk__show_annotations(); 262 void (*show_annotations)(void);
263
264 show_annotations = dlsym(perf_gtk_handle,
265 "perf_gtk__show_annotations");
266 if (show_annotations == NULL) {
267 ui__error("GTK browser not found!\n");
268 goto out_delete;
269 }
270 show_annotations();
271 }
252 272
253out_delete: 273out_delete:
254 /* 274 /*
diff --git a/tools/perf/builtin-bench.c b/tools/perf/builtin-bench.c
index 77298bf892b8..33af80fa49cf 100644
--- a/tools/perf/builtin-bench.c
+++ b/tools/perf/builtin-bench.c
@@ -35,7 +35,7 @@ struct bench_suite {
35/* sentinel: easy for help */ 35/* sentinel: easy for help */
36#define suite_all { "all", "Test all benchmark suites", NULL } 36#define suite_all { "all", "Test all benchmark suites", NULL }
37 37
38#ifdef LIBNUMA_SUPPORT 38#ifdef HAVE_LIBNUMA_SUPPORT
39static struct bench_suite numa_suites[] = { 39static struct bench_suite numa_suites[] = {
40 { "mem", 40 { "mem",
41 "Benchmark for NUMA workloads", 41 "Benchmark for NUMA workloads",
@@ -80,7 +80,7 @@ struct bench_subsys {
80}; 80};
81 81
82static struct bench_subsys subsystems[] = { 82static struct bench_subsys subsystems[] = {
83#ifdef LIBNUMA_SUPPORT 83#ifdef HAVE_LIBNUMA_SUPPORT
84 { "numa", 84 { "numa",
85 "NUMA scheduling and MM behavior", 85 "NUMA scheduling and MM behavior",
86 numa_suites }, 86 numa_suites },
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c
index c96c8fa38243..8140b7b249fa 100644
--- a/tools/perf/builtin-buildid-cache.c
+++ b/tools/perf/builtin-buildid-cache.c
@@ -6,6 +6,11 @@
6 * Copyright (C) 2010, Red Hat Inc. 6 * Copyright (C) 2010, Red Hat Inc.
7 * Copyright (C) 2010, Arnaldo Carvalho de Melo <acme@redhat.com> 7 * Copyright (C) 2010, Arnaldo Carvalho de Melo <acme@redhat.com>
8 */ 8 */
9#include <sys/types.h>
10#include <sys/time.h>
11#include <time.h>
12#include <dirent.h>
13#include <unistd.h>
9#include "builtin.h" 14#include "builtin.h"
10#include "perf.h" 15#include "perf.h"
11#include "util/cache.h" 16#include "util/cache.h"
@@ -17,6 +22,140 @@
17#include "util/session.h" 22#include "util/session.h"
18#include "util/symbol.h" 23#include "util/symbol.h"
19 24
25static int build_id_cache__kcore_buildid(const char *proc_dir, char *sbuildid)
26{
27 char root_dir[PATH_MAX];
28 char notes[PATH_MAX];
29 u8 build_id[BUILD_ID_SIZE];
30 char *p;
31
32 strlcpy(root_dir, proc_dir, sizeof(root_dir));
33
34 p = strrchr(root_dir, '/');
35 if (!p)
36 return -1;
37 *p = '\0';
38
39 scnprintf(notes, sizeof(notes), "%s/sys/kernel/notes", root_dir);
40
41 if (sysfs__read_build_id(notes, build_id, sizeof(build_id)))
42 return -1;
43
44 build_id__sprintf(build_id, sizeof(build_id), sbuildid);
45
46 return 0;
47}
48
49static int build_id_cache__kcore_dir(char *dir, size_t sz)
50{
51 struct timeval tv;
52 struct tm tm;
53 char dt[32];
54
55 if (gettimeofday(&tv, NULL) || !localtime_r(&tv.tv_sec, &tm))
56 return -1;
57
58 if (!strftime(dt, sizeof(dt), "%Y%m%d%H%M%S", &tm))
59 return -1;
60
61 scnprintf(dir, sz, "%s%02u", dt, (unsigned)tv.tv_usec / 10000);
62
63 return 0;
64}
65
66static int build_id_cache__kcore_existing(const char *from_dir, char *to_dir,
67 size_t to_dir_sz)
68{
69 char from[PATH_MAX];
70 char to[PATH_MAX];
71 struct dirent *dent;
72 int ret = -1;
73 DIR *d;
74
75 d = opendir(to_dir);
76 if (!d)
77 return -1;
78
79 scnprintf(from, sizeof(from), "%s/modules", from_dir);
80
81 while (1) {
82 dent = readdir(d);
83 if (!dent)
84 break;
85 if (dent->d_type != DT_DIR)
86 continue;
87 scnprintf(to, sizeof(to), "%s/%s/modules", to_dir,
88 dent->d_name);
89 if (!compare_proc_modules(from, to)) {
90 scnprintf(to, sizeof(to), "%s/%s", to_dir,
91 dent->d_name);
92 strlcpy(to_dir, to, to_dir_sz);
93 ret = 0;
94 break;
95 }
96 }
97
98 closedir(d);
99
100 return ret;
101}
102
103static int build_id_cache__add_kcore(const char *filename, const char *debugdir)
104{
105 char dir[32], sbuildid[BUILD_ID_SIZE * 2 + 1];
106 char from_dir[PATH_MAX], to_dir[PATH_MAX];
107 char *p;
108
109 strlcpy(from_dir, filename, sizeof(from_dir));
110
111 p = strrchr(from_dir, '/');
112 if (!p || strcmp(p + 1, "kcore"))
113 return -1;
114 *p = '\0';
115
116 if (build_id_cache__kcore_buildid(from_dir, sbuildid))
117 return -1;
118
119 scnprintf(to_dir, sizeof(to_dir), "%s/[kernel.kcore]/%s",
120 debugdir, sbuildid);
121
122 if (!build_id_cache__kcore_existing(from_dir, to_dir, sizeof(to_dir))) {
123 pr_debug("same kcore found in %s\n", to_dir);
124 return 0;
125 }
126
127 if (build_id_cache__kcore_dir(dir, sizeof(dir)))
128 return -1;
129
130 scnprintf(to_dir, sizeof(to_dir), "%s/[kernel.kcore]/%s/%s",
131 debugdir, sbuildid, dir);
132
133 if (mkdir_p(to_dir, 0755))
134 return -1;
135
136 if (kcore_copy(from_dir, to_dir)) {
137 /* Remove YYYYmmddHHMMSShh directory */
138 if (!rmdir(to_dir)) {
139 p = strrchr(to_dir, '/');
140 if (p)
141 *p = '\0';
142 /* Try to remove buildid directory */
143 if (!rmdir(to_dir)) {
144 p = strrchr(to_dir, '/');
145 if (p)
146 *p = '\0';
147 /* Try to remove [kernel.kcore] directory */
148 rmdir(to_dir);
149 }
150 }
151 return -1;
152 }
153
154 pr_debug("kcore added to build-id cache directory %s\n", to_dir);
155
156 return 0;
157}
158
20static int build_id_cache__add_file(const char *filename, const char *debugdir) 159static int build_id_cache__add_file(const char *filename, const char *debugdir)
21{ 160{
22 char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 161 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
@@ -130,11 +269,14 @@ int cmd_buildid_cache(int argc, const char **argv,
130 char const *add_name_list_str = NULL, 269 char const *add_name_list_str = NULL,
131 *remove_name_list_str = NULL, 270 *remove_name_list_str = NULL,
132 *missing_filename = NULL, 271 *missing_filename = NULL,
133 *update_name_list_str = NULL; 272 *update_name_list_str = NULL,
273 *kcore_filename;
134 274
135 const struct option buildid_cache_options[] = { 275 const struct option buildid_cache_options[] = {
136 OPT_STRING('a', "add", &add_name_list_str, 276 OPT_STRING('a', "add", &add_name_list_str,
137 "file list", "file(s) to add"), 277 "file list", "file(s) to add"),
278 OPT_STRING('k', "kcore", &kcore_filename,
279 "file", "kcore file to add"),
138 OPT_STRING('r', "remove", &remove_name_list_str, "file list", 280 OPT_STRING('r', "remove", &remove_name_list_str, "file list",
139 "file(s) to remove"), 281 "file(s) to remove"),
140 OPT_STRING('M', "missing", &missing_filename, "file", 282 OPT_STRING('M', "missing", &missing_filename, "file",
@@ -217,5 +359,9 @@ int cmd_buildid_cache(int argc, const char **argv,
217 } 359 }
218 } 360 }
219 361
362 if (kcore_filename &&
363 build_id_cache__add_kcore(kcore_filename, debugdir))
364 pr_warning("Couldn't add %s\n", kcore_filename);
365
220 return ret; 366 return ret;
221} 367}
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index afe377b2884f..f51a9637f69b 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -231,7 +231,7 @@ static int perf_event__inject_buildid(struct perf_tool *tool,
231 * account this as unresolved. 231 * account this as unresolved.
232 */ 232 */
233 } else { 233 } else {
234#ifdef LIBELF_SUPPORT 234#ifdef HAVE_LIBELF_SUPPORT
235 pr_warning("no symbols found in %s, maybe " 235 pr_warning("no symbols found in %s, maybe "
236 "install a debug package?\n", 236 "install a debug package?\n",
237 al.map->dso->long_name); 237 al.map->dso->long_name);
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 935d52216c89..cfa0b7979914 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -1426,8 +1426,9 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
1426 const struct option live_options[] = { 1426 const struct option live_options[] = {
1427 OPT_STRING('p', "pid", &kvm->opts.target.pid, "pid", 1427 OPT_STRING('p', "pid", &kvm->opts.target.pid, "pid",
1428 "record events on existing process id"), 1428 "record events on existing process id"),
1429 OPT_UINTEGER('m', "mmap-pages", &kvm->opts.mmap_pages, 1429 OPT_CALLBACK('m', "mmap-pages", &kvm->opts.mmap_pages, "pages",
1430 "number of mmap data pages"), 1430 "number of mmap data pages",
1431 perf_evlist__parse_mmap_pages),
1431 OPT_INCR('v', "verbose", &verbose, 1432 OPT_INCR('v', "verbose", &verbose,
1432 "be more verbose (show counter open errors, etc)"), 1433 "be more verbose (show counter open errors, etc)"),
1433 OPT_BOOLEAN('a', "all-cpus", &kvm->opts.target.system_wide, 1434 OPT_BOOLEAN('a', "all-cpus", &kvm->opts.target.system_wide,
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index ee33ba2f05dd..6a9076f165f4 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -56,7 +56,9 @@ struct lock_stat {
56 56
57 unsigned int nr_readlock; 57 unsigned int nr_readlock;
58 unsigned int nr_trylock; 58 unsigned int nr_trylock;
59
59 /* these times are in nano sec. */ 60 /* these times are in nano sec. */
61 u64 avg_wait_time;
60 u64 wait_time_total; 62 u64 wait_time_total;
61 u64 wait_time_min; 63 u64 wait_time_min;
62 u64 wait_time_max; 64 u64 wait_time_max;
@@ -208,6 +210,7 @@ static struct thread_stat *thread_stat_findnew_first(u32 tid)
208 210
209SINGLE_KEY(nr_acquired) 211SINGLE_KEY(nr_acquired)
210SINGLE_KEY(nr_contended) 212SINGLE_KEY(nr_contended)
213SINGLE_KEY(avg_wait_time)
211SINGLE_KEY(wait_time_total) 214SINGLE_KEY(wait_time_total)
212SINGLE_KEY(wait_time_max) 215SINGLE_KEY(wait_time_max)
213 216
@@ -244,6 +247,7 @@ static struct rb_root result; /* place to store sorted data */
244struct lock_key keys[] = { 247struct lock_key keys[] = {
245 DEF_KEY_LOCK(acquired, nr_acquired), 248 DEF_KEY_LOCK(acquired, nr_acquired),
246 DEF_KEY_LOCK(contended, nr_contended), 249 DEF_KEY_LOCK(contended, nr_contended),
250 DEF_KEY_LOCK(avg_wait, avg_wait_time),
247 DEF_KEY_LOCK(wait_total, wait_time_total), 251 DEF_KEY_LOCK(wait_total, wait_time_total),
248 DEF_KEY_LOCK(wait_min, wait_time_min), 252 DEF_KEY_LOCK(wait_min, wait_time_min),
249 DEF_KEY_LOCK(wait_max, wait_time_max), 253 DEF_KEY_LOCK(wait_max, wait_time_max),
@@ -321,10 +325,12 @@ static struct lock_stat *lock_stat_findnew(void *addr, const char *name)
321 325
322 new->addr = addr; 326 new->addr = addr;
323 new->name = zalloc(sizeof(char) * strlen(name) + 1); 327 new->name = zalloc(sizeof(char) * strlen(name) + 1);
324 if (!new->name) 328 if (!new->name) {
329 free(new);
325 goto alloc_failed; 330 goto alloc_failed;
326 strcpy(new->name, name); 331 }
327 332
333 strcpy(new->name, name);
328 new->wait_time_min = ULLONG_MAX; 334 new->wait_time_min = ULLONG_MAX;
329 335
330 list_add(&new->hash_entry, entry); 336 list_add(&new->hash_entry, entry);
@@ -400,17 +406,17 @@ static int report_lock_acquire_event(struct perf_evsel *evsel,
400 406
401 ls = lock_stat_findnew(addr, name); 407 ls = lock_stat_findnew(addr, name);
402 if (!ls) 408 if (!ls)
403 return -1; 409 return -ENOMEM;
404 if (ls->discard) 410 if (ls->discard)
405 return 0; 411 return 0;
406 412
407 ts = thread_stat_findnew(sample->tid); 413 ts = thread_stat_findnew(sample->tid);
408 if (!ts) 414 if (!ts)
409 return -1; 415 return -ENOMEM;
410 416
411 seq = get_seq(ts, addr); 417 seq = get_seq(ts, addr);
412 if (!seq) 418 if (!seq)
413 return -1; 419 return -ENOMEM;
414 420
415 switch (seq->state) { 421 switch (seq->state) {
416 case SEQ_STATE_UNINITIALIZED: 422 case SEQ_STATE_UNINITIALIZED:
@@ -446,7 +452,6 @@ broken:
446 list_del(&seq->list); 452 list_del(&seq->list);
447 free(seq); 453 free(seq);
448 goto end; 454 goto end;
449 break;
450 default: 455 default:
451 BUG_ON("Unknown state of lock sequence found!\n"); 456 BUG_ON("Unknown state of lock sequence found!\n");
452 break; 457 break;
@@ -473,17 +478,17 @@ static int report_lock_acquired_event(struct perf_evsel *evsel,
473 478
474 ls = lock_stat_findnew(addr, name); 479 ls = lock_stat_findnew(addr, name);
475 if (!ls) 480 if (!ls)
476 return -1; 481 return -ENOMEM;
477 if (ls->discard) 482 if (ls->discard)
478 return 0; 483 return 0;
479 484
480 ts = thread_stat_findnew(sample->tid); 485 ts = thread_stat_findnew(sample->tid);
481 if (!ts) 486 if (!ts)
482 return -1; 487 return -ENOMEM;
483 488
484 seq = get_seq(ts, addr); 489 seq = get_seq(ts, addr);
485 if (!seq) 490 if (!seq)
486 return -1; 491 return -ENOMEM;
487 492
488 switch (seq->state) { 493 switch (seq->state) {
489 case SEQ_STATE_UNINITIALIZED: 494 case SEQ_STATE_UNINITIALIZED:
@@ -508,8 +513,6 @@ static int report_lock_acquired_event(struct perf_evsel *evsel,
508 list_del(&seq->list); 513 list_del(&seq->list);
509 free(seq); 514 free(seq);
510 goto end; 515 goto end;
511 break;
512
513 default: 516 default:
514 BUG_ON("Unknown state of lock sequence found!\n"); 517 BUG_ON("Unknown state of lock sequence found!\n");
515 break; 518 break;
@@ -517,6 +520,7 @@ static int report_lock_acquired_event(struct perf_evsel *evsel,
517 520
518 seq->state = SEQ_STATE_ACQUIRED; 521 seq->state = SEQ_STATE_ACQUIRED;
519 ls->nr_acquired++; 522 ls->nr_acquired++;
523 ls->avg_wait_time = ls->nr_contended ? ls->wait_time_total/ls->nr_contended : 0;
520 seq->prev_event_time = sample->time; 524 seq->prev_event_time = sample->time;
521end: 525end:
522 return 0; 526 return 0;
@@ -536,17 +540,17 @@ static int report_lock_contended_event(struct perf_evsel *evsel,
536 540
537 ls = lock_stat_findnew(addr, name); 541 ls = lock_stat_findnew(addr, name);
538 if (!ls) 542 if (!ls)
539 return -1; 543 return -ENOMEM;
540 if (ls->discard) 544 if (ls->discard)
541 return 0; 545 return 0;
542 546
543 ts = thread_stat_findnew(sample->tid); 547 ts = thread_stat_findnew(sample->tid);
544 if (!ts) 548 if (!ts)
545 return -1; 549 return -ENOMEM;
546 550
547 seq = get_seq(ts, addr); 551 seq = get_seq(ts, addr);
548 if (!seq) 552 if (!seq)
549 return -1; 553 return -ENOMEM;
550 554
551 switch (seq->state) { 555 switch (seq->state) {
552 case SEQ_STATE_UNINITIALIZED: 556 case SEQ_STATE_UNINITIALIZED:
@@ -564,7 +568,6 @@ static int report_lock_contended_event(struct perf_evsel *evsel,
564 list_del(&seq->list); 568 list_del(&seq->list);
565 free(seq); 569 free(seq);
566 goto end; 570 goto end;
567 break;
568 default: 571 default:
569 BUG_ON("Unknown state of lock sequence found!\n"); 572 BUG_ON("Unknown state of lock sequence found!\n");
570 break; 573 break;
@@ -572,6 +575,7 @@ static int report_lock_contended_event(struct perf_evsel *evsel,
572 575
573 seq->state = SEQ_STATE_CONTENDED; 576 seq->state = SEQ_STATE_CONTENDED;
574 ls->nr_contended++; 577 ls->nr_contended++;
578 ls->avg_wait_time = ls->wait_time_total/ls->nr_contended;
575 seq->prev_event_time = sample->time; 579 seq->prev_event_time = sample->time;
576end: 580end:
577 return 0; 581 return 0;
@@ -591,22 +595,21 @@ static int report_lock_release_event(struct perf_evsel *evsel,
591 595
592 ls = lock_stat_findnew(addr, name); 596 ls = lock_stat_findnew(addr, name);
593 if (!ls) 597 if (!ls)
594 return -1; 598 return -ENOMEM;
595 if (ls->discard) 599 if (ls->discard)
596 return 0; 600 return 0;
597 601
598 ts = thread_stat_findnew(sample->tid); 602 ts = thread_stat_findnew(sample->tid);
599 if (!ts) 603 if (!ts)
600 return -1; 604 return -ENOMEM;
601 605
602 seq = get_seq(ts, addr); 606 seq = get_seq(ts, addr);
603 if (!seq) 607 if (!seq)
604 return -1; 608 return -ENOMEM;
605 609
606 switch (seq->state) { 610 switch (seq->state) {
607 case SEQ_STATE_UNINITIALIZED: 611 case SEQ_STATE_UNINITIALIZED:
608 goto end; 612 goto end;
609 break;
610 case SEQ_STATE_ACQUIRED: 613 case SEQ_STATE_ACQUIRED:
611 break; 614 break;
612 case SEQ_STATE_READ_ACQUIRED: 615 case SEQ_STATE_READ_ACQUIRED:
@@ -624,7 +627,6 @@ static int report_lock_release_event(struct perf_evsel *evsel,
624 ls->discard = 1; 627 ls->discard = 1;
625 bad_hist[BROKEN_RELEASE]++; 628 bad_hist[BROKEN_RELEASE]++;
626 goto free_seq; 629 goto free_seq;
627 break;
628 default: 630 default:
629 BUG_ON("Unknown state of lock sequence found!\n"); 631 BUG_ON("Unknown state of lock sequence found!\n");
630 break; 632 break;
@@ -690,7 +692,7 @@ static void print_bad_events(int bad, int total)
690 692
691 pr_info("\n=== output for debug===\n\n"); 693 pr_info("\n=== output for debug===\n\n");
692 pr_info("bad: %d, total: %d\n", bad, total); 694 pr_info("bad: %d, total: %d\n", bad, total);
693 pr_info("bad rate: %f %%\n", (double)bad / (double)total * 100); 695 pr_info("bad rate: %.2f %%\n", (double)bad / (double)total * 100);
694 pr_info("histogram of events caused bad sequence\n"); 696 pr_info("histogram of events caused bad sequence\n");
695 for (i = 0; i < BROKEN_MAX; i++) 697 for (i = 0; i < BROKEN_MAX; i++)
696 pr_info(" %10s: %d\n", name[i], bad_hist[i]); 698 pr_info(" %10s: %d\n", name[i], bad_hist[i]);
@@ -707,6 +709,7 @@ static void print_result(void)
707 pr_info("%10s ", "acquired"); 709 pr_info("%10s ", "acquired");
708 pr_info("%10s ", "contended"); 710 pr_info("%10s ", "contended");
709 711
712 pr_info("%15s ", "avg wait (ns)");
710 pr_info("%15s ", "total wait (ns)"); 713 pr_info("%15s ", "total wait (ns)");
711 pr_info("%15s ", "max wait (ns)"); 714 pr_info("%15s ", "max wait (ns)");
712 pr_info("%15s ", "min wait (ns)"); 715 pr_info("%15s ", "min wait (ns)");
@@ -738,6 +741,7 @@ static void print_result(void)
738 pr_info("%10u ", st->nr_acquired); 741 pr_info("%10u ", st->nr_acquired);
739 pr_info("%10u ", st->nr_contended); 742 pr_info("%10u ", st->nr_contended);
740 743
744 pr_info("%15" PRIu64 " ", st->avg_wait_time);
741 pr_info("%15" PRIu64 " ", st->wait_time_total); 745 pr_info("%15" PRIu64 " ", st->wait_time_total);
742 pr_info("%15" PRIu64 " ", st->wait_time_max); 746 pr_info("%15" PRIu64 " ", st->wait_time_max);
743 pr_info("%15" PRIu64 " ", st->wait_time_min == ULLONG_MAX ? 747 pr_info("%15" PRIu64 " ", st->wait_time_min == ULLONG_MAX ?
@@ -822,6 +826,18 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
822 return 0; 826 return 0;
823} 827}
824 828
829static void sort_result(void)
830{
831 unsigned int i;
832 struct lock_stat *st;
833
834 for (i = 0; i < LOCKHASH_SIZE; i++) {
835 list_for_each_entry(st, &lockhash_table[i], hash_entry) {
836 insert_to_result(st, compare);
837 }
838 }
839}
840
825static const struct perf_evsel_str_handler lock_tracepoints[] = { 841static const struct perf_evsel_str_handler lock_tracepoints[] = {
826 { "lock:lock_acquire", perf_evsel__process_lock_acquire, }, /* CONFIG_LOCKDEP */ 842 { "lock:lock_acquire", perf_evsel__process_lock_acquire, }, /* CONFIG_LOCKDEP */
827 { "lock:lock_acquired", perf_evsel__process_lock_acquired, }, /* CONFIG_LOCKDEP, CONFIG_LOCK_STAT */ 843 { "lock:lock_acquired", perf_evsel__process_lock_acquired, }, /* CONFIG_LOCKDEP, CONFIG_LOCK_STAT */
@@ -829,51 +845,47 @@ static const struct perf_evsel_str_handler lock_tracepoints[] = {
829 { "lock:lock_release", perf_evsel__process_lock_release, }, /* CONFIG_LOCKDEP */ 845 { "lock:lock_release", perf_evsel__process_lock_release, }, /* CONFIG_LOCKDEP */
830}; 846};
831 847
832static int read_events(void) 848static int __cmd_report(bool display_info)
833{ 849{
850 int err = -EINVAL;
834 struct perf_tool eops = { 851 struct perf_tool eops = {
835 .sample = process_sample_event, 852 .sample = process_sample_event,
836 .comm = perf_event__process_comm, 853 .comm = perf_event__process_comm,
837 .ordered_samples = true, 854 .ordered_samples = true,
838 }; 855 };
856
839 session = perf_session__new(input_name, O_RDONLY, 0, false, &eops); 857 session = perf_session__new(input_name, O_RDONLY, 0, false, &eops);
840 if (!session) { 858 if (!session) {
841 pr_err("Initializing perf session failed\n"); 859 pr_err("Initializing perf session failed\n");
842 return -1; 860 return -ENOMEM;
843 } 861 }
844 862
863 if (!perf_session__has_traces(session, "lock record"))
864 goto out_delete;
865
845 if (perf_session__set_tracepoints_handlers(session, lock_tracepoints)) { 866 if (perf_session__set_tracepoints_handlers(session, lock_tracepoints)) {
846 pr_err("Initializing perf session tracepoint handlers failed\n"); 867 pr_err("Initializing perf session tracepoint handlers failed\n");
847 return -1; 868 goto out_delete;
848 } 869 }
849 870
850 return perf_session__process_events(session, &eops); 871 if (select_key())
851} 872 goto out_delete;
852 873
853static void sort_result(void) 874 err = perf_session__process_events(session, &eops);
854{ 875 if (err)
855 unsigned int i; 876 goto out_delete;
856 struct lock_stat *st;
857
858 for (i = 0; i < LOCKHASH_SIZE; i++) {
859 list_for_each_entry(st, &lockhash_table[i], hash_entry) {
860 insert_to_result(st, compare);
861 }
862 }
863}
864 877
865static int __cmd_report(void)
866{
867 setup_pager(); 878 setup_pager();
879 if (display_info) /* used for info subcommand */
880 err = dump_info();
881 else {
882 sort_result();
883 print_result();
884 }
868 885
869 if ((select_key() != 0) || 886out_delete:
870 (read_events() != 0)) 887 perf_session__delete(session);
871 return -1; 888 return err;
872
873 sort_result();
874 print_result();
875
876 return 0;
877} 889}
878 890
879static int __cmd_record(int argc, const char **argv) 891static int __cmd_record(int argc, const char **argv)
@@ -881,7 +893,7 @@ static int __cmd_record(int argc, const char **argv)
881 const char *record_args[] = { 893 const char *record_args[] = {
882 "record", "-R", "-m", "1024", "-c", "1", 894 "record", "-R", "-m", "1024", "-c", "1",
883 }; 895 };
884 unsigned int rec_argc, i, j; 896 unsigned int rec_argc, i, j, ret;
885 const char **rec_argv; 897 const char **rec_argv;
886 898
887 for (i = 0; i < ARRAY_SIZE(lock_tracepoints); i++) { 899 for (i = 0; i < ARRAY_SIZE(lock_tracepoints); i++) {
@@ -898,7 +910,7 @@ static int __cmd_record(int argc, const char **argv)
898 rec_argc += 2 * ARRAY_SIZE(lock_tracepoints); 910 rec_argc += 2 * ARRAY_SIZE(lock_tracepoints);
899 911
900 rec_argv = calloc(rec_argc + 1, sizeof(char *)); 912 rec_argv = calloc(rec_argc + 1, sizeof(char *));
901 if (rec_argv == NULL) 913 if (!rec_argv)
902 return -ENOMEM; 914 return -ENOMEM;
903 915
904 for (i = 0; i < ARRAY_SIZE(record_args); i++) 916 for (i = 0; i < ARRAY_SIZE(record_args); i++)
@@ -914,7 +926,9 @@ static int __cmd_record(int argc, const char **argv)
914 926
915 BUG_ON(i != rec_argc); 927 BUG_ON(i != rec_argc);
916 928
917 return cmd_record(i, rec_argv, NULL); 929 ret = cmd_record(i, rec_argv, NULL);
930 free(rec_argv);
931 return ret;
918} 932}
919 933
920int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused) 934int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused)
@@ -934,7 +948,7 @@ int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused)
934 }; 948 };
935 const struct option report_options[] = { 949 const struct option report_options[] = {
936 OPT_STRING('k', "key", &sort_key, "acquired", 950 OPT_STRING('k', "key", &sort_key, "acquired",
937 "key for sorting (acquired / contended / wait_total / wait_max / wait_min)"), 951 "key for sorting (acquired / contended / avg_wait / wait_total / wait_max / wait_min)"),
938 /* TODO: type */ 952 /* TODO: type */
939 OPT_END() 953 OPT_END()
940 }; 954 };
@@ -972,7 +986,7 @@ int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused)
972 if (argc) 986 if (argc)
973 usage_with_options(report_usage, report_options); 987 usage_with_options(report_usage, report_options);
974 } 988 }
975 __cmd_report(); 989 rc = __cmd_report(false);
976 } else if (!strcmp(argv[0], "script")) { 990 } else if (!strcmp(argv[0], "script")) {
977 /* Aliased to 'perf script' */ 991 /* Aliased to 'perf script' */
978 return cmd_script(argc, argv, prefix); 992 return cmd_script(argc, argv, prefix);
@@ -985,11 +999,7 @@ int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused)
985 } 999 }
986 /* recycling report_lock_ops */ 1000 /* recycling report_lock_ops */
987 trace_handler = &report_lock_ops; 1001 trace_handler = &report_lock_ops;
988 setup_pager(); 1002 rc = __cmd_report(true);
989 if (read_events() != 0)
990 rc = -1;
991 else
992 rc = dump_info();
993 } else { 1003 } else {
994 usage_with_options(lock_usage, lock_options); 1004 usage_with_options(lock_usage, lock_options);
995 } 1005 }
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index e8a66f9a6715..89acc17cf2a0 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -173,7 +173,7 @@ static int opt_set_target(const struct option *opt, const char *str,
173 if (str && !params.target) { 173 if (str && !params.target) {
174 if (!strcmp(opt->long_name, "exec")) 174 if (!strcmp(opt->long_name, "exec"))
175 params.uprobes = true; 175 params.uprobes = true;
176#ifdef DWARF_SUPPORT 176#ifdef HAVE_DWARF_SUPPORT
177 else if (!strcmp(opt->long_name, "module")) 177 else if (!strcmp(opt->long_name, "module"))
178 params.uprobes = false; 178 params.uprobes = false;
179#endif 179#endif
@@ -187,7 +187,7 @@ static int opt_set_target(const struct option *opt, const char *str,
187 return ret; 187 return ret;
188} 188}
189 189
190#ifdef DWARF_SUPPORT 190#ifdef HAVE_DWARF_SUPPORT
191static int opt_show_lines(const struct option *opt __maybe_unused, 191static int opt_show_lines(const struct option *opt __maybe_unused,
192 const char *str, int unset __maybe_unused) 192 const char *str, int unset __maybe_unused)
193{ 193{
@@ -257,7 +257,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
257 "perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]", 257 "perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]",
258 "perf probe [<options>] --del '[GROUP:]EVENT' ...", 258 "perf probe [<options>] --del '[GROUP:]EVENT' ...",
259 "perf probe --list", 259 "perf probe --list",
260#ifdef DWARF_SUPPORT 260#ifdef HAVE_DWARF_SUPPORT
261 "perf probe [<options>] --line 'LINEDESC'", 261 "perf probe [<options>] --line 'LINEDESC'",
262 "perf probe [<options>] --vars 'PROBEPOINT'", 262 "perf probe [<options>] --vars 'PROBEPOINT'",
263#endif 263#endif
@@ -271,7 +271,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
271 OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.", 271 OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.",
272 opt_del_probe_event), 272 opt_del_probe_event),
273 OPT_CALLBACK('a', "add", NULL, 273 OPT_CALLBACK('a', "add", NULL,
274#ifdef DWARF_SUPPORT 274#ifdef HAVE_DWARF_SUPPORT
275 "[EVENT=]FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT" 275 "[EVENT=]FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT"
276 " [[NAME=]ARG ...]", 276 " [[NAME=]ARG ...]",
277#else 277#else
@@ -283,7 +283,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
283 "\t\tFUNC:\tFunction name\n" 283 "\t\tFUNC:\tFunction name\n"
284 "\t\tOFF:\tOffset from function entry (in byte)\n" 284 "\t\tOFF:\tOffset from function entry (in byte)\n"
285 "\t\t%return:\tPut the probe at function return\n" 285 "\t\t%return:\tPut the probe at function return\n"
286#ifdef DWARF_SUPPORT 286#ifdef HAVE_DWARF_SUPPORT
287 "\t\tSRC:\tSource code path\n" 287 "\t\tSRC:\tSource code path\n"
288 "\t\tRL:\tRelative line number from function entry.\n" 288 "\t\tRL:\tRelative line number from function entry.\n"
289 "\t\tAL:\tAbsolute line number in file.\n" 289 "\t\tAL:\tAbsolute line number in file.\n"
@@ -296,7 +296,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
296 opt_add_probe_event), 296 opt_add_probe_event),
297 OPT_BOOLEAN('f', "force", &params.force_add, "forcibly add events" 297 OPT_BOOLEAN('f', "force", &params.force_add, "forcibly add events"
298 " with existing name"), 298 " with existing name"),
299#ifdef DWARF_SUPPORT 299#ifdef HAVE_DWARF_SUPPORT
300 OPT_CALLBACK('L', "line", NULL, 300 OPT_CALLBACK('L', "line", NULL,
301 "FUNC[:RLN[+NUM|-RLN2]]|SRC:ALN[+NUM|-ALN2]", 301 "FUNC[:RLN[+NUM|-RLN2]]|SRC:ALN[+NUM|-ALN2]",
302 "Show source code lines.", opt_show_lines), 302 "Show source code lines.", opt_show_lines),
@@ -408,7 +408,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
408 return ret; 408 return ret;
409 } 409 }
410 410
411#ifdef DWARF_SUPPORT 411#ifdef HAVE_DWARF_SUPPORT
412 if (params.show_lines && !params.uprobes) { 412 if (params.show_lines && !params.uprobes) {
413 if (params.mod_events) { 413 if (params.mod_events) {
414 pr_err(" Error: Don't use --line with" 414 pr_err(" Error: Don't use --line with"
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index a78db3f31b25..92ca5419073b 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -29,7 +29,7 @@
29#include <sched.h> 29#include <sched.h>
30#include <sys/mman.h> 30#include <sys/mman.h>
31 31
32#ifndef HAVE_ON_EXIT 32#ifndef HAVE_ON_EXIT_SUPPORT
33#ifndef ATEXIT_MAX 33#ifndef ATEXIT_MAX
34#define ATEXIT_MAX 32 34#define ATEXIT_MAX 32
35#endif 35#endif
@@ -70,7 +70,6 @@ struct perf_record {
70 struct perf_session *session; 70 struct perf_session *session;
71 const char *progname; 71 const char *progname;
72 int output; 72 int output;
73 unsigned int page_size;
74 int realtime_prio; 73 int realtime_prio;
75 bool no_buildid; 74 bool no_buildid;
76 bool no_buildid_cache; 75 bool no_buildid_cache;
@@ -119,7 +118,7 @@ static int perf_record__mmap_read(struct perf_record *rec,
119{ 118{
120 unsigned int head = perf_mmap__read_head(md); 119 unsigned int head = perf_mmap__read_head(md);
121 unsigned int old = md->prev; 120 unsigned int old = md->prev;
122 unsigned char *data = md->base + rec->page_size; 121 unsigned char *data = md->base + page_size;
123 unsigned long size; 122 unsigned long size;
124 void *buf; 123 void *buf;
125 int rc = 0; 124 int rc = 0;
@@ -234,10 +233,6 @@ try_again:
234 "or try again with a smaller value of -m/--mmap_pages.\n" 233 "or try again with a smaller value of -m/--mmap_pages.\n"
235 "(current value: %d)\n", opts->mmap_pages); 234 "(current value: %d)\n", opts->mmap_pages);
236 rc = -errno; 235 rc = -errno;
237 } else if (!is_power_of_2(opts->mmap_pages) &&
238 (opts->mmap_pages != UINT_MAX)) {
239 pr_err("--mmap_pages/-m value must be a power of two.");
240 rc = -EINVAL;
241 } else { 236 } else {
242 pr_err("failed to mmap with %d (%s)\n", errno, strerror(errno)); 237 pr_err("failed to mmap with %d (%s)\n", errno, strerror(errno));
243 rc = -errno; 238 rc = -errno;
@@ -360,8 +355,6 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
360 355
361 rec->progname = argv[0]; 356 rec->progname = argv[0];
362 357
363 rec->page_size = sysconf(_SC_PAGE_SIZE);
364
365 on_exit(perf_record__sig_exit, rec); 358 on_exit(perf_record__sig_exit, rec);
366 signal(SIGCHLD, sig_handler); 359 signal(SIGCHLD, sig_handler);
367 signal(SIGINT, sig_handler); 360 signal(SIGINT, sig_handler);
@@ -687,7 +680,7 @@ error:
687 return ret; 680 return ret;
688} 681}
689 682
690#ifdef LIBUNWIND_SUPPORT 683#ifdef HAVE_LIBUNWIND_SUPPORT
691static int get_stack_size(char *str, unsigned long *_size) 684static int get_stack_size(char *str, unsigned long *_size)
692{ 685{
693 char *endptr; 686 char *endptr;
@@ -713,7 +706,7 @@ static int get_stack_size(char *str, unsigned long *_size)
713 max_size, str); 706 max_size, str);
714 return -1; 707 return -1;
715} 708}
716#endif /* LIBUNWIND_SUPPORT */ 709#endif /* HAVE_LIBUNWIND_SUPPORT */
717 710
718int record_parse_callchain_opt(const struct option *opt, 711int record_parse_callchain_opt(const struct option *opt,
719 const char *arg, int unset) 712 const char *arg, int unset)
@@ -751,7 +744,7 @@ int record_parse_callchain_opt(const struct option *opt,
751 "needed for -g fp\n"); 744 "needed for -g fp\n");
752 break; 745 break;
753 746
754#ifdef LIBUNWIND_SUPPORT 747#ifdef HAVE_LIBUNWIND_SUPPORT
755 /* Dwarf style */ 748 /* Dwarf style */
756 } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) { 749 } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
757 const unsigned long default_stack_dump_size = 8192; 750 const unsigned long default_stack_dump_size = 8192;
@@ -771,7 +764,7 @@ int record_parse_callchain_opt(const struct option *opt,
771 if (!ret) 764 if (!ret)
772 pr_debug("callchain: stack dump size %d\n", 765 pr_debug("callchain: stack dump size %d\n",
773 opts->stack_dump_size); 766 opts->stack_dump_size);
774#endif /* LIBUNWIND_SUPPORT */ 767#endif /* HAVE_LIBUNWIND_SUPPORT */
775 } else { 768 } else {
776 pr_err("callchain: Unknown -g option " 769 pr_err("callchain: Unknown -g option "
777 "value: %s\n", arg); 770 "value: %s\n", arg);
@@ -818,7 +811,7 @@ static struct perf_record record = {
818 811
819#define CALLCHAIN_HELP "do call-graph (stack chain/backtrace) recording: " 812#define CALLCHAIN_HELP "do call-graph (stack chain/backtrace) recording: "
820 813
821#ifdef LIBUNWIND_SUPPORT 814#ifdef HAVE_LIBUNWIND_SUPPORT
822const char record_callchain_help[] = CALLCHAIN_HELP "[fp] dwarf"; 815const char record_callchain_help[] = CALLCHAIN_HELP "[fp] dwarf";
823#else 816#else
824const char record_callchain_help[] = CALLCHAIN_HELP "[fp]"; 817const char record_callchain_help[] = CALLCHAIN_HELP "[fp]";
@@ -857,8 +850,9 @@ const struct option record_options[] = {
857 OPT_BOOLEAN('i', "no-inherit", &record.opts.no_inherit, 850 OPT_BOOLEAN('i', "no-inherit", &record.opts.no_inherit,
858 "child tasks do not inherit counters"), 851 "child tasks do not inherit counters"),
859 OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), 852 OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"),
860 OPT_UINTEGER('m', "mmap-pages", &record.opts.mmap_pages, 853 OPT_CALLBACK('m', "mmap-pages", &record.opts.mmap_pages, "pages",
861 "number of mmap data pages"), 854 "number of mmap data pages",
855 perf_evlist__parse_mmap_pages),
862 OPT_BOOLEAN(0, "group", &record.opts.group, 856 OPT_BOOLEAN(0, "group", &record.opts.group,
863 "put the counters into a counter group"), 857 "put the counters into a counter group"),
864 OPT_CALLBACK_DEFAULT('g', "call-graph", &record.opts, 858 OPT_CALLBACK_DEFAULT('g', "call-graph", &record.opts,
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 06e1abe351dd..21b5c2f54c2a 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -35,6 +35,7 @@
35#include "util/hist.h" 35#include "util/hist.h"
36#include "arch/common.h" 36#include "arch/common.h"
37 37
38#include <dlfcn.h>
38#include <linux/bitmap.h> 39#include <linux/bitmap.h>
39 40
40struct perf_report { 41struct perf_report {
@@ -591,8 +592,19 @@ static int __cmd_report(struct perf_report *rep)
591 ret = 0; 592 ret = 0;
592 593
593 } else if (use_browser == 2) { 594 } else if (use_browser == 2) {
594 perf_evlist__gtk_browse_hists(session->evlist, help, 595 int (*hist_browser)(struct perf_evlist *,
595 NULL, rep->min_percent); 596 const char *,
597 struct hist_browser_timer *,
598 float min_pcnt);
599
600 hist_browser = dlsym(perf_gtk_handle,
601 "perf_evlist__gtk_browse_hists");
602 if (hist_browser == NULL) {
603 ui__error("GTK browser not found!\n");
604 return ret;
605 }
606 hist_browser(session->evlist, help, NULL,
607 rep->min_percent);
596 } 608 }
597 } else 609 } else
598 perf_evlist__tty_browse_hists(session->evlist, rep, help); 610 perf_evlist__tty_browse_hists(session->evlist, rep, help);
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 700b47849101..1a9c95d270aa 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -706,10 +706,13 @@ static void nsec_printout(int cpu, int nr, struct perf_evsel *evsel, double avg)
706{ 706{
707 double msecs = avg / 1e6; 707 double msecs = avg / 1e6;
708 const char *fmt = csv_output ? "%.6f%s%s" : "%18.6f%s%-25s"; 708 const char *fmt = csv_output ? "%.6f%s%s" : "%18.6f%s%-25s";
709 char name[25];
709 710
710 aggr_printout(evsel, cpu, nr); 711 aggr_printout(evsel, cpu, nr);
711 712
712 fprintf(output, fmt, msecs, csv_sep, perf_evsel__name(evsel)); 713 scnprintf(name, sizeof(name), "%s%s",
714 perf_evsel__name(evsel), csv_output ? "" : " (msec)");
715 fprintf(output, fmt, msecs, csv_sep, name);
713 716
714 if (evsel->cgrp) 717 if (evsel->cgrp)
715 fprintf(output, "%s%s", csv_sep, evsel->cgrp->name); 718 fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
@@ -930,11 +933,10 @@ static void abs_printout(int cpu, int nr, struct perf_evsel *evsel, double avg)
930 933
931 if (perf_evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)) { 934 if (perf_evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)) {
932 total = avg_stats(&runtime_cycles_stats[cpu]); 935 total = avg_stats(&runtime_cycles_stats[cpu]);
933 if (total) 936 if (total) {
934 ratio = avg / total; 937 ratio = avg / total;
935 938 fprintf(output, " # %5.2f insns per cycle ", ratio);
936 fprintf(output, " # %5.2f insns per cycle ", ratio); 939 }
937
938 total = avg_stats(&runtime_stalled_cycles_front_stats[cpu]); 940 total = avg_stats(&runtime_stalled_cycles_front_stats[cpu]);
939 total = max(total, avg_stats(&runtime_stalled_cycles_back_stats[cpu])); 941 total = max(total, avg_stats(&runtime_stalled_cycles_back_stats[cpu]));
940 942
@@ -997,10 +999,10 @@ static void abs_printout(int cpu, int nr, struct perf_evsel *evsel, double avg)
997 } else if (perf_evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)) { 999 } else if (perf_evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)) {
998 total = avg_stats(&runtime_nsecs_stats[cpu]); 1000 total = avg_stats(&runtime_nsecs_stats[cpu]);
999 1001
1000 if (total) 1002 if (total) {
1001 ratio = 1.0 * avg / total; 1003 ratio = avg / total;
1002 1004 fprintf(output, " # %8.3f GHz ", ratio);
1003 fprintf(output, " # %8.3f GHz ", ratio); 1005 }
1004 } else if (transaction_run && 1006 } else if (transaction_run &&
1005 perf_evsel__cmp(evsel, nth_evsel(T_CYCLES_IN_TX))) { 1007 perf_evsel__cmp(evsel, nth_evsel(T_CYCLES_IN_TX))) {
1006 total = avg_stats(&runtime_cycles_stats[cpu]); 1008 total = avg_stats(&runtime_cycles_stats[cpu]);
@@ -1230,7 +1232,11 @@ static void print_stat(int argc, const char **argv)
1230 if (!csv_output) { 1232 if (!csv_output) {
1231 fprintf(output, "\n"); 1233 fprintf(output, "\n");
1232 fprintf(output, " Performance counter stats for "); 1234 fprintf(output, " Performance counter stats for ");
1233 if (!perf_target__has_task(&target)) { 1235 if (target.system_wide)
1236 fprintf(output, "\'system wide");
1237 else if (target.cpu_list)
1238 fprintf(output, "\'CPU(s) %s", target.cpu_list);
1239 else if (!perf_target__has_task(&target)) {
1234 fprintf(output, "\'%s", argv[0]); 1240 fprintf(output, "\'%s", argv[0]);
1235 for (i = 1; i < argc; i++) 1241 for (i = 1; i < argc; i++)
1236 fprintf(output, " %s", argv[i]); 1242 fprintf(output, " %s", argv[i]);
@@ -1656,8 +1662,9 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
1656 } else if (big_num_opt == 0) /* User passed --no-big-num */ 1662 } else if (big_num_opt == 0) /* User passed --no-big-num */
1657 big_num = false; 1663 big_num = false;
1658 1664
1659 if (!argc && !perf_target__has_task(&target)) 1665 if (!argc && perf_target__none(&target))
1660 usage_with_options(stat_usage, options); 1666 usage_with_options(stat_usage, options);
1667
1661 if (run_count < 0) { 1668 if (run_count < 0) {
1662 usage_with_options(stat_usage, options); 1669 usage_with_options(stat_usage, options);
1663 } else if (run_count == 0) { 1670 } else if (run_count == 0) {
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index b3e0229ee38f..65c49b2f51c1 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -1073,10 +1073,13 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1073 "list of cpus to monitor"), 1073 "list of cpus to monitor"),
1074 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, 1074 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
1075 "file", "vmlinux pathname"), 1075 "file", "vmlinux pathname"),
1076 OPT_BOOLEAN(0, "ignore-vmlinux", &symbol_conf.ignore_vmlinux,
1077 "don't load vmlinux even if found"),
1076 OPT_BOOLEAN('K', "hide_kernel_symbols", &top.hide_kernel_symbols, 1078 OPT_BOOLEAN('K', "hide_kernel_symbols", &top.hide_kernel_symbols,
1077 "hide kernel symbols"), 1079 "hide kernel symbols"),
1078 OPT_UINTEGER('m', "mmap-pages", &opts->mmap_pages, 1080 OPT_CALLBACK('m', "mmap-pages", &opts->mmap_pages, "pages",
1079 "number of mmap data pages"), 1081 "number of mmap data pages",
1082 perf_evlist__parse_mmap_pages),
1080 OPT_INTEGER('r', "realtime", &top.realtime_prio, 1083 OPT_INTEGER('r', "realtime", &top.realtime_prio,
1081 "collect data with this RT SCHED_FIFO priority"), 1084 "collect data with this RT SCHED_FIFO priority"),
1082 OPT_INTEGER('d', "delay", &top.delay_secs, 1085 OPT_INTEGER('d', "delay", &top.delay_secs,
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 71aa3e35406b..d0f91fe755a3 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -10,9 +10,11 @@
10#include "util/strlist.h" 10#include "util/strlist.h"
11#include "util/intlist.h" 11#include "util/intlist.h"
12#include "util/thread_map.h" 12#include "util/thread_map.h"
13#include "util/stat.h"
13 14
14#include <libaudit.h> 15#include <libaudit.h>
15#include <stdlib.h> 16#include <stdlib.h>
17#include <sys/eventfd.h>
16#include <sys/mman.h> 18#include <sys/mman.h>
17#include <linux/futex.h> 19#include <linux/futex.h>
18 20
@@ -33,49 +35,96 @@
33# define MADV_UNMERGEABLE 13 35# define MADV_UNMERGEABLE 13
34#endif 36#endif
35 37
36static size_t syscall_arg__scnprintf_hex(char *bf, size_t size, 38struct syscall_arg {
37 unsigned long arg, 39 unsigned long val;
38 u8 arg_idx __maybe_unused, 40 struct thread *thread;
39 u8 *arg_mask __maybe_unused) 41 struct trace *trace;
42 void *parm;
43 u8 idx;
44 u8 mask;
45};
46
47struct strarray {
48 int offset;
49 int nr_entries;
50 const char **entries;
51};
52
53#define DEFINE_STRARRAY(array) struct strarray strarray__##array = { \
54 .nr_entries = ARRAY_SIZE(array), \
55 .entries = array, \
56}
57
58#define DEFINE_STRARRAY_OFFSET(array, off) struct strarray strarray__##array = { \
59 .offset = off, \
60 .nr_entries = ARRAY_SIZE(array), \
61 .entries = array, \
62}
63
64static size_t __syscall_arg__scnprintf_strarray(char *bf, size_t size,
65 const char *intfmt,
66 struct syscall_arg *arg)
40{ 67{
41 return scnprintf(bf, size, "%#lx", arg); 68 struct strarray *sa = arg->parm;
69 int idx = arg->val - sa->offset;
70
71 if (idx < 0 || idx >= sa->nr_entries)
72 return scnprintf(bf, size, intfmt, arg->val);
73
74 return scnprintf(bf, size, "%s", sa->entries[idx]);
42} 75}
43 76
44#define SCA_HEX syscall_arg__scnprintf_hex 77static size_t syscall_arg__scnprintf_strarray(char *bf, size_t size,
78 struct syscall_arg *arg)
79{
80 return __syscall_arg__scnprintf_strarray(bf, size, "%d", arg);
81}
45 82
46static size_t syscall_arg__scnprintf_whence(char *bf, size_t size, 83#define SCA_STRARRAY syscall_arg__scnprintf_strarray
47 unsigned long arg, 84
48 u8 arg_idx __maybe_unused, 85static size_t syscall_arg__scnprintf_strhexarray(char *bf, size_t size,
49 u8 *arg_mask __maybe_unused) 86 struct syscall_arg *arg)
50{ 87{
51 int whence = arg; 88 return __syscall_arg__scnprintf_strarray(bf, size, "%#x", arg);
89}
52 90
53 switch (whence) { 91#define SCA_STRHEXARRAY syscall_arg__scnprintf_strhexarray
54#define P_WHENCE(n) case SEEK_##n: return scnprintf(bf, size, #n) 92
55 P_WHENCE(SET); 93static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
56 P_WHENCE(CUR); 94 struct syscall_arg *arg);
57 P_WHENCE(END); 95
58#ifdef SEEK_DATA 96#define SCA_FD syscall_arg__scnprintf_fd
59 P_WHENCE(DATA); 97
60#endif 98static size_t syscall_arg__scnprintf_fd_at(char *bf, size_t size,
61#ifdef SEEK_HOLE 99 struct syscall_arg *arg)
62 P_WHENCE(HOLE); 100{
63#endif 101 int fd = arg->val;
64#undef P_WHENCE 102
65 default: break; 103 if (fd == AT_FDCWD)
66 } 104 return scnprintf(bf, size, "CWD");
67 105
68 return scnprintf(bf, size, "%#x", whence); 106 return syscall_arg__scnprintf_fd(bf, size, arg);
69} 107}
70 108
71#define SCA_WHENCE syscall_arg__scnprintf_whence 109#define SCA_FDAT syscall_arg__scnprintf_fd_at
110
111static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
112 struct syscall_arg *arg);
113
114#define SCA_CLOSE_FD syscall_arg__scnprintf_close_fd
115
116static size_t syscall_arg__scnprintf_hex(char *bf, size_t size,
117 struct syscall_arg *arg)
118{
119 return scnprintf(bf, size, "%#lx", arg->val);
120}
121
122#define SCA_HEX syscall_arg__scnprintf_hex
72 123
73static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size, 124static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size,
74 unsigned long arg, 125 struct syscall_arg *arg)
75 u8 arg_idx __maybe_unused,
76 u8 *arg_mask __maybe_unused)
77{ 126{
78 int printed = 0, prot = arg; 127 int printed = 0, prot = arg->val;
79 128
80 if (prot == PROT_NONE) 129 if (prot == PROT_NONE)
81 return scnprintf(bf, size, "NONE"); 130 return scnprintf(bf, size, "NONE");
@@ -104,10 +153,9 @@ static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size,
104#define SCA_MMAP_PROT syscall_arg__scnprintf_mmap_prot 153#define SCA_MMAP_PROT syscall_arg__scnprintf_mmap_prot
105 154
106static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size, 155static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size,
107 unsigned long arg, u8 arg_idx __maybe_unused, 156 struct syscall_arg *arg)
108 u8 *arg_mask __maybe_unused)
109{ 157{
110 int printed = 0, flags = arg; 158 int printed = 0, flags = arg->val;
111 159
112#define P_MMAP_FLAG(n) \ 160#define P_MMAP_FLAG(n) \
113 if (flags & MAP_##n) { \ 161 if (flags & MAP_##n) { \
@@ -148,10 +196,9 @@ static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size,
148#define SCA_MMAP_FLAGS syscall_arg__scnprintf_mmap_flags 196#define SCA_MMAP_FLAGS syscall_arg__scnprintf_mmap_flags
149 197
150static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size, 198static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size,
151 unsigned long arg, u8 arg_idx __maybe_unused, 199 struct syscall_arg *arg)
152 u8 *arg_mask __maybe_unused)
153{ 200{
154 int behavior = arg; 201 int behavior = arg->val;
155 202
156 switch (behavior) { 203 switch (behavior) {
157#define P_MADV_BHV(n) case MADV_##n: return scnprintf(bf, size, #n) 204#define P_MADV_BHV(n) case MADV_##n: return scnprintf(bf, size, #n)
@@ -190,8 +237,38 @@ static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size,
190 237
191#define SCA_MADV_BHV syscall_arg__scnprintf_madvise_behavior 238#define SCA_MADV_BHV syscall_arg__scnprintf_madvise_behavior
192 239
193static size_t syscall_arg__scnprintf_futex_op(char *bf, size_t size, unsigned long arg, 240static size_t syscall_arg__scnprintf_flock(char *bf, size_t size,
194 u8 arg_idx __maybe_unused, u8 *arg_mask) 241 struct syscall_arg *arg)
242{
243 int printed = 0, op = arg->val;
244
245 if (op == 0)
246 return scnprintf(bf, size, "NONE");
247#define P_CMD(cmd) \
248 if ((op & LOCK_##cmd) == LOCK_##cmd) { \
249 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #cmd); \
250 op &= ~LOCK_##cmd; \
251 }
252
253 P_CMD(SH);
254 P_CMD(EX);
255 P_CMD(NB);
256 P_CMD(UN);
257 P_CMD(MAND);
258 P_CMD(RW);
259 P_CMD(READ);
260 P_CMD(WRITE);
261#undef P_OP
262
263 if (op)
264 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", op);
265
266 return printed;
267}
268
269#define SCA_FLOCK syscall_arg__scnprintf_flock
270
271static size_t syscall_arg__scnprintf_futex_op(char *bf, size_t size, struct syscall_arg *arg)
195{ 272{
196 enum syscall_futex_args { 273 enum syscall_futex_args {
197 SCF_UADDR = (1 << 0), 274 SCF_UADDR = (1 << 0),
@@ -201,24 +278,24 @@ static size_t syscall_arg__scnprintf_futex_op(char *bf, size_t size, unsigned lo
201 SCF_UADDR2 = (1 << 4), 278 SCF_UADDR2 = (1 << 4),
202 SCF_VAL3 = (1 << 5), 279 SCF_VAL3 = (1 << 5),
203 }; 280 };
204 int op = arg; 281 int op = arg->val;
205 int cmd = op & FUTEX_CMD_MASK; 282 int cmd = op & FUTEX_CMD_MASK;
206 size_t printed = 0; 283 size_t printed = 0;
207 284
208 switch (cmd) { 285 switch (cmd) {
209#define P_FUTEX_OP(n) case FUTEX_##n: printed = scnprintf(bf, size, #n); 286#define P_FUTEX_OP(n) case FUTEX_##n: printed = scnprintf(bf, size, #n);
210 P_FUTEX_OP(WAIT); *arg_mask |= SCF_VAL3|SCF_UADDR2; break; 287 P_FUTEX_OP(WAIT); arg->mask |= SCF_VAL3|SCF_UADDR2; break;
211 P_FUTEX_OP(WAKE); *arg_mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break; 288 P_FUTEX_OP(WAKE); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
212 P_FUTEX_OP(FD); *arg_mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break; 289 P_FUTEX_OP(FD); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
213 P_FUTEX_OP(REQUEUE); *arg_mask |= SCF_VAL3|SCF_TIMEOUT; break; 290 P_FUTEX_OP(REQUEUE); arg->mask |= SCF_VAL3|SCF_TIMEOUT; break;
214 P_FUTEX_OP(CMP_REQUEUE); *arg_mask |= SCF_TIMEOUT; break; 291 P_FUTEX_OP(CMP_REQUEUE); arg->mask |= SCF_TIMEOUT; break;
215 P_FUTEX_OP(CMP_REQUEUE_PI); *arg_mask |= SCF_TIMEOUT; break; 292 P_FUTEX_OP(CMP_REQUEUE_PI); arg->mask |= SCF_TIMEOUT; break;
216 P_FUTEX_OP(WAKE_OP); break; 293 P_FUTEX_OP(WAKE_OP); break;
217 P_FUTEX_OP(LOCK_PI); *arg_mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break; 294 P_FUTEX_OP(LOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
218 P_FUTEX_OP(UNLOCK_PI); *arg_mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break; 295 P_FUTEX_OP(UNLOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
219 P_FUTEX_OP(TRYLOCK_PI); *arg_mask |= SCF_VAL3|SCF_UADDR2; break; 296 P_FUTEX_OP(TRYLOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2; break;
220 P_FUTEX_OP(WAIT_BITSET); *arg_mask |= SCF_UADDR2; break; 297 P_FUTEX_OP(WAIT_BITSET); arg->mask |= SCF_UADDR2; break;
221 P_FUTEX_OP(WAKE_BITSET); *arg_mask |= SCF_UADDR2; break; 298 P_FUTEX_OP(WAKE_BITSET); arg->mask |= SCF_UADDR2; break;
222 P_FUTEX_OP(WAIT_REQUEUE_PI); break; 299 P_FUTEX_OP(WAIT_REQUEUE_PI); break;
223 default: printed = scnprintf(bf, size, "%#x", cmd); break; 300 default: printed = scnprintf(bf, size, "%#x", cmd); break;
224 } 301 }
@@ -234,14 +311,194 @@ static size_t syscall_arg__scnprintf_futex_op(char *bf, size_t size, unsigned lo
234 311
235#define SCA_FUTEX_OP syscall_arg__scnprintf_futex_op 312#define SCA_FUTEX_OP syscall_arg__scnprintf_futex_op
236 313
314static const char *epoll_ctl_ops[] = { "ADD", "DEL", "MOD", };
315static DEFINE_STRARRAY_OFFSET(epoll_ctl_ops, 1);
316
317static const char *itimers[] = { "REAL", "VIRTUAL", "PROF", };
318static DEFINE_STRARRAY(itimers);
319
320static const char *whences[] = { "SET", "CUR", "END",
321#ifdef SEEK_DATA
322"DATA",
323#endif
324#ifdef SEEK_HOLE
325"HOLE",
326#endif
327};
328static DEFINE_STRARRAY(whences);
329
330static const char *fcntl_cmds[] = {
331 "DUPFD", "GETFD", "SETFD", "GETFL", "SETFL", "GETLK", "SETLK",
332 "SETLKW", "SETOWN", "GETOWN", "SETSIG", "GETSIG", "F_GETLK64",
333 "F_SETLK64", "F_SETLKW64", "F_SETOWN_EX", "F_GETOWN_EX",
334 "F_GETOWNER_UIDS",
335};
336static DEFINE_STRARRAY(fcntl_cmds);
337
338static const char *rlimit_resources[] = {
339 "CPU", "FSIZE", "DATA", "STACK", "CORE", "RSS", "NPROC", "NOFILE",
340 "MEMLOCK", "AS", "LOCKS", "SIGPENDING", "MSGQUEUE", "NICE", "RTPRIO",
341 "RTTIME",
342};
343static DEFINE_STRARRAY(rlimit_resources);
344
345static const char *sighow[] = { "BLOCK", "UNBLOCK", "SETMASK", };
346static DEFINE_STRARRAY(sighow);
347
348static const char *clockid[] = {
349 "REALTIME", "MONOTONIC", "PROCESS_CPUTIME_ID", "THREAD_CPUTIME_ID",
350 "MONOTONIC_RAW", "REALTIME_COARSE", "MONOTONIC_COARSE",
351};
352static DEFINE_STRARRAY(clockid);
353
354static const char *socket_families[] = {
355 "UNSPEC", "LOCAL", "INET", "AX25", "IPX", "APPLETALK", "NETROM",
356 "BRIDGE", "ATMPVC", "X25", "INET6", "ROSE", "DECnet", "NETBEUI",
357 "SECURITY", "KEY", "NETLINK", "PACKET", "ASH", "ECONET", "ATMSVC",
358 "RDS", "SNA", "IRDA", "PPPOX", "WANPIPE", "LLC", "IB", "CAN", "TIPC",
359 "BLUETOOTH", "IUCV", "RXRPC", "ISDN", "PHONET", "IEEE802154", "CAIF",
360 "ALG", "NFC", "VSOCK",
361};
362static DEFINE_STRARRAY(socket_families);
363
364#ifndef SOCK_TYPE_MASK
365#define SOCK_TYPE_MASK 0xf
366#endif
367
368static size_t syscall_arg__scnprintf_socket_type(char *bf, size_t size,
369 struct syscall_arg *arg)
370{
371 size_t printed;
372 int type = arg->val,
373 flags = type & ~SOCK_TYPE_MASK;
374
375 type &= SOCK_TYPE_MASK;
376 /*
377 * Can't use a strarray, MIPS may override for ABI reasons.
378 */
379 switch (type) {
380#define P_SK_TYPE(n) case SOCK_##n: printed = scnprintf(bf, size, #n); break;
381 P_SK_TYPE(STREAM);
382 P_SK_TYPE(DGRAM);
383 P_SK_TYPE(RAW);
384 P_SK_TYPE(RDM);
385 P_SK_TYPE(SEQPACKET);
386 P_SK_TYPE(DCCP);
387 P_SK_TYPE(PACKET);
388#undef P_SK_TYPE
389 default:
390 printed = scnprintf(bf, size, "%#x", type);
391 }
392
393#define P_SK_FLAG(n) \
394 if (flags & SOCK_##n) { \
395 printed += scnprintf(bf + printed, size - printed, "|%s", #n); \
396 flags &= ~SOCK_##n; \
397 }
398
399 P_SK_FLAG(CLOEXEC);
400 P_SK_FLAG(NONBLOCK);
401#undef P_SK_FLAG
402
403 if (flags)
404 printed += scnprintf(bf + printed, size - printed, "|%#x", flags);
405
406 return printed;
407}
408
409#define SCA_SK_TYPE syscall_arg__scnprintf_socket_type
410
411#ifndef MSG_PROBE
412#define MSG_PROBE 0x10
413#endif
414#ifndef MSG_WAITFORONE
415#define MSG_WAITFORONE 0x10000
416#endif
417#ifndef MSG_SENDPAGE_NOTLAST
418#define MSG_SENDPAGE_NOTLAST 0x20000
419#endif
420#ifndef MSG_FASTOPEN
421#define MSG_FASTOPEN 0x20000000
422#endif
423
424static size_t syscall_arg__scnprintf_msg_flags(char *bf, size_t size,
425 struct syscall_arg *arg)
426{
427 int printed = 0, flags = arg->val;
428
429 if (flags == 0)
430 return scnprintf(bf, size, "NONE");
431#define P_MSG_FLAG(n) \
432 if (flags & MSG_##n) { \
433 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
434 flags &= ~MSG_##n; \
435 }
436
437 P_MSG_FLAG(OOB);
438 P_MSG_FLAG(PEEK);
439 P_MSG_FLAG(DONTROUTE);
440 P_MSG_FLAG(TRYHARD);
441 P_MSG_FLAG(CTRUNC);
442 P_MSG_FLAG(PROBE);
443 P_MSG_FLAG(TRUNC);
444 P_MSG_FLAG(DONTWAIT);
445 P_MSG_FLAG(EOR);
446 P_MSG_FLAG(WAITALL);
447 P_MSG_FLAG(FIN);
448 P_MSG_FLAG(SYN);
449 P_MSG_FLAG(CONFIRM);
450 P_MSG_FLAG(RST);
451 P_MSG_FLAG(ERRQUEUE);
452 P_MSG_FLAG(NOSIGNAL);
453 P_MSG_FLAG(MORE);
454 P_MSG_FLAG(WAITFORONE);
455 P_MSG_FLAG(SENDPAGE_NOTLAST);
456 P_MSG_FLAG(FASTOPEN);
457 P_MSG_FLAG(CMSG_CLOEXEC);
458#undef P_MSG_FLAG
459
460 if (flags)
461 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
462
463 return printed;
464}
465
466#define SCA_MSG_FLAGS syscall_arg__scnprintf_msg_flags
467
468static size_t syscall_arg__scnprintf_access_mode(char *bf, size_t size,
469 struct syscall_arg *arg)
470{
471 size_t printed = 0;
472 int mode = arg->val;
473
474 if (mode == F_OK) /* 0 */
475 return scnprintf(bf, size, "F");
476#define P_MODE(n) \
477 if (mode & n##_OK) { \
478 printed += scnprintf(bf + printed, size - printed, "%s", #n); \
479 mode &= ~n##_OK; \
480 }
481
482 P_MODE(R);
483 P_MODE(W);
484 P_MODE(X);
485#undef P_MODE
486
487 if (mode)
488 printed += scnprintf(bf + printed, size - printed, "|%#x", mode);
489
490 return printed;
491}
492
493#define SCA_ACCMODE syscall_arg__scnprintf_access_mode
494
237static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size, 495static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
238 unsigned long arg, 496 struct syscall_arg *arg)
239 u8 arg_idx, u8 *arg_mask)
240{ 497{
241 int printed = 0, flags = arg; 498 int printed = 0, flags = arg->val;
242 499
243 if (!(flags & O_CREAT)) 500 if (!(flags & O_CREAT))
244 *arg_mask |= 1 << (arg_idx + 1); /* Mask the mode parm */ 501 arg->mask |= 1 << (arg->idx + 1); /* Mask the mode parm */
245 502
246 if (flags == 0) 503 if (flags == 0)
247 return scnprintf(bf, size, "RDONLY"); 504 return scnprintf(bf, size, "RDONLY");
@@ -291,32 +548,225 @@ static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
291 548
292#define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags 549#define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags
293 550
551static size_t syscall_arg__scnprintf_eventfd_flags(char *bf, size_t size,
552 struct syscall_arg *arg)
553{
554 int printed = 0, flags = arg->val;
555
556 if (flags == 0)
557 return scnprintf(bf, size, "NONE");
558#define P_FLAG(n) \
559 if (flags & EFD_##n) { \
560 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
561 flags &= ~EFD_##n; \
562 }
563
564 P_FLAG(SEMAPHORE);
565 P_FLAG(CLOEXEC);
566 P_FLAG(NONBLOCK);
567#undef P_FLAG
568
569 if (flags)
570 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
571
572 return printed;
573}
574
575#define SCA_EFD_FLAGS syscall_arg__scnprintf_eventfd_flags
576
577static size_t syscall_arg__scnprintf_pipe_flags(char *bf, size_t size,
578 struct syscall_arg *arg)
579{
580 int printed = 0, flags = arg->val;
581
582#define P_FLAG(n) \
583 if (flags & O_##n) { \
584 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
585 flags &= ~O_##n; \
586 }
587
588 P_FLAG(CLOEXEC);
589 P_FLAG(NONBLOCK);
590#undef P_FLAG
591
592 if (flags)
593 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
594
595 return printed;
596}
597
598#define SCA_PIPE_FLAGS syscall_arg__scnprintf_pipe_flags
599
600static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscall_arg *arg)
601{
602 int sig = arg->val;
603
604 switch (sig) {
605#define P_SIGNUM(n) case SIG##n: return scnprintf(bf, size, #n)
606 P_SIGNUM(HUP);
607 P_SIGNUM(INT);
608 P_SIGNUM(QUIT);
609 P_SIGNUM(ILL);
610 P_SIGNUM(TRAP);
611 P_SIGNUM(ABRT);
612 P_SIGNUM(BUS);
613 P_SIGNUM(FPE);
614 P_SIGNUM(KILL);
615 P_SIGNUM(USR1);
616 P_SIGNUM(SEGV);
617 P_SIGNUM(USR2);
618 P_SIGNUM(PIPE);
619 P_SIGNUM(ALRM);
620 P_SIGNUM(TERM);
621 P_SIGNUM(STKFLT);
622 P_SIGNUM(CHLD);
623 P_SIGNUM(CONT);
624 P_SIGNUM(STOP);
625 P_SIGNUM(TSTP);
626 P_SIGNUM(TTIN);
627 P_SIGNUM(TTOU);
628 P_SIGNUM(URG);
629 P_SIGNUM(XCPU);
630 P_SIGNUM(XFSZ);
631 P_SIGNUM(VTALRM);
632 P_SIGNUM(PROF);
633 P_SIGNUM(WINCH);
634 P_SIGNUM(IO);
635 P_SIGNUM(PWR);
636 P_SIGNUM(SYS);
637 default: break;
638 }
639
640 return scnprintf(bf, size, "%#x", sig);
641}
642
643#define SCA_SIGNUM syscall_arg__scnprintf_signum
644
645#define TCGETS 0x5401
646
647static const char *tioctls[] = {
648 "TCGETS", "TCSETS", "TCSETSW", "TCSETSF", "TCGETA", "TCSETA", "TCSETAW",
649 "TCSETAF", "TCSBRK", "TCXONC", "TCFLSH", "TIOCEXCL", "TIOCNXCL",
650 "TIOCSCTTY", "TIOCGPGRP", "TIOCSPGRP", "TIOCOUTQ", "TIOCSTI",
651 "TIOCGWINSZ", "TIOCSWINSZ", "TIOCMGET", "TIOCMBIS", "TIOCMBIC",
652 "TIOCMSET", "TIOCGSOFTCAR", "TIOCSSOFTCAR", "FIONREAD", "TIOCLINUX",
653 "TIOCCONS", "TIOCGSERIAL", "TIOCSSERIAL", "TIOCPKT", "FIONBIO",
654 "TIOCNOTTY", "TIOCSETD", "TIOCGETD", "TCSBRKP", [0x27] = "TIOCSBRK",
655 "TIOCCBRK", "TIOCGSID", "TCGETS2", "TCSETS2", "TCSETSW2", "TCSETSF2",
656 "TIOCGRS485", "TIOCSRS485", "TIOCGPTN", "TIOCSPTLCK",
657 "TIOCGDEV||TCGETX", "TCSETX", "TCSETXF", "TCSETXW", "TIOCSIG",
658 "TIOCVHANGUP", "TIOCGPKT", "TIOCGPTLCK", "TIOCGEXCL",
659 [0x50] = "FIONCLEX", "FIOCLEX", "FIOASYNC", "TIOCSERCONFIG",
660 "TIOCSERGWILD", "TIOCSERSWILD", "TIOCGLCKTRMIOS", "TIOCSLCKTRMIOS",
661 "TIOCSERGSTRUCT", "TIOCSERGETLSR", "TIOCSERGETMULTI", "TIOCSERSETMULTI",
662 "TIOCMIWAIT", "TIOCGICOUNT", [0x60] = "FIOQSIZE",
663};
664
665static DEFINE_STRARRAY_OFFSET(tioctls, 0x5401);
666
667#define STRARRAY(arg, name, array) \
668 .arg_scnprintf = { [arg] = SCA_STRARRAY, }, \
669 .arg_parm = { [arg] = &strarray__##array, }
670
294static struct syscall_fmt { 671static struct syscall_fmt {
295 const char *name; 672 const char *name;
296 const char *alias; 673 const char *alias;
297 size_t (*arg_scnprintf[6])(char *bf, size_t size, unsigned long arg, u8 arg_idx, u8 *arg_mask); 674 size_t (*arg_scnprintf[6])(char *bf, size_t size, struct syscall_arg *arg);
675 void *arg_parm[6];
298 bool errmsg; 676 bool errmsg;
299 bool timeout; 677 bool timeout;
300 bool hexret; 678 bool hexret;
301} syscall_fmts[] = { 679} syscall_fmts[] = {
302 { .name = "access", .errmsg = true, }, 680 { .name = "access", .errmsg = true,
681 .arg_scnprintf = { [1] = SCA_ACCMODE, /* mode */ }, },
303 { .name = "arch_prctl", .errmsg = true, .alias = "prctl", }, 682 { .name = "arch_prctl", .errmsg = true, .alias = "prctl", },
304 { .name = "brk", .hexret = true, 683 { .name = "brk", .hexret = true,
305 .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, }, 684 .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, },
306 { .name = "mmap", .hexret = true, }, 685 { .name = "clock_gettime", .errmsg = true, STRARRAY(0, clk_id, clockid), },
686 { .name = "close", .errmsg = true,
687 .arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, },
307 { .name = "connect", .errmsg = true, }, 688 { .name = "connect", .errmsg = true, },
308 { .name = "fstat", .errmsg = true, .alias = "newfstat", }, 689 { .name = "dup", .errmsg = true,
309 { .name = "fstatat", .errmsg = true, .alias = "newfstatat", }, 690 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
691 { .name = "dup2", .errmsg = true,
692 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
693 { .name = "dup3", .errmsg = true,
694 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
695 { .name = "epoll_ctl", .errmsg = true, STRARRAY(1, op, epoll_ctl_ops), },
696 { .name = "eventfd2", .errmsg = true,
697 .arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, },
698 { .name = "faccessat", .errmsg = true,
699 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
700 { .name = "fadvise64", .errmsg = true,
701 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
702 { .name = "fallocate", .errmsg = true,
703 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
704 { .name = "fchdir", .errmsg = true,
705 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
706 { .name = "fchmod", .errmsg = true,
707 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
708 { .name = "fchmodat", .errmsg = true,
709 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
710 { .name = "fchown", .errmsg = true,
711 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
712 { .name = "fchownat", .errmsg = true,
713 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
714 { .name = "fcntl", .errmsg = true,
715 .arg_scnprintf = { [0] = SCA_FD, /* fd */
716 [1] = SCA_STRARRAY, /* cmd */ },
717 .arg_parm = { [1] = &strarray__fcntl_cmds, /* cmd */ }, },
718 { .name = "fdatasync", .errmsg = true,
719 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
720 { .name = "flock", .errmsg = true,
721 .arg_scnprintf = { [0] = SCA_FD, /* fd */
722 [1] = SCA_FLOCK, /* cmd */ }, },
723 { .name = "fsetxattr", .errmsg = true,
724 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
725 { .name = "fstat", .errmsg = true, .alias = "newfstat",
726 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
727 { .name = "fstatat", .errmsg = true, .alias = "newfstatat",
728 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
729 { .name = "fstatfs", .errmsg = true,
730 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
731 { .name = "fsync", .errmsg = true,
732 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
733 { .name = "ftruncate", .errmsg = true,
734 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
310 { .name = "futex", .errmsg = true, 735 { .name = "futex", .errmsg = true,
311 .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, }, 736 .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, },
737 { .name = "futimesat", .errmsg = true,
738 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
739 { .name = "getdents", .errmsg = true,
740 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
741 { .name = "getdents64", .errmsg = true,
742 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
743 { .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), },
744 { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
312 { .name = "ioctl", .errmsg = true, 745 { .name = "ioctl", .errmsg = true,
313 .arg_scnprintf = { [2] = SCA_HEX, /* arg */ }, }, 746 .arg_scnprintf = { [0] = SCA_FD, /* fd */
747 [1] = SCA_STRHEXARRAY, /* cmd */
748 [2] = SCA_HEX, /* arg */ },
749 .arg_parm = { [1] = &strarray__tioctls, /* cmd */ }, },
750 { .name = "kill", .errmsg = true,
751 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
752 { .name = "linkat", .errmsg = true,
753 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
314 { .name = "lseek", .errmsg = true, 754 { .name = "lseek", .errmsg = true,
315 .arg_scnprintf = { [2] = SCA_WHENCE, /* whence */ }, }, 755 .arg_scnprintf = { [0] = SCA_FD, /* fd */
756 [2] = SCA_STRARRAY, /* whence */ },
757 .arg_parm = { [2] = &strarray__whences, /* whence */ }, },
316 { .name = "lstat", .errmsg = true, .alias = "newlstat", }, 758 { .name = "lstat", .errmsg = true, .alias = "newlstat", },
317 { .name = "madvise", .errmsg = true, 759 { .name = "madvise", .errmsg = true,
318 .arg_scnprintf = { [0] = SCA_HEX, /* start */ 760 .arg_scnprintf = { [0] = SCA_HEX, /* start */
319 [2] = SCA_MADV_BHV, /* behavior */ }, }, 761 [2] = SCA_MADV_BHV, /* behavior */ }, },
762 { .name = "mkdirat", .errmsg = true,
763 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
764 { .name = "mknodat", .errmsg = true,
765 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
766 { .name = "mlock", .errmsg = true,
767 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
768 { .name = "mlockall", .errmsg = true,
769 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
320 { .name = "mmap", .hexret = true, 770 { .name = "mmap", .hexret = true,
321 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ 771 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
322 [2] = SCA_MMAP_PROT, /* prot */ 772 [2] = SCA_MMAP_PROT, /* prot */
@@ -327,24 +777,91 @@ static struct syscall_fmt {
327 { .name = "mremap", .hexret = true, 777 { .name = "mremap", .hexret = true,
328 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ 778 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
329 [4] = SCA_HEX, /* new_addr */ }, }, 779 [4] = SCA_HEX, /* new_addr */ }, },
780 { .name = "munlock", .errmsg = true,
781 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
330 { .name = "munmap", .errmsg = true, 782 { .name = "munmap", .errmsg = true,
331 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, }, 783 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
784 { .name = "name_to_handle_at", .errmsg = true,
785 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
786 { .name = "newfstatat", .errmsg = true,
787 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
332 { .name = "open", .errmsg = true, 788 { .name = "open", .errmsg = true,
333 .arg_scnprintf = { [1] = SCA_OPEN_FLAGS, /* flags */ }, }, 789 .arg_scnprintf = { [1] = SCA_OPEN_FLAGS, /* flags */ }, },
334 { .name = "open_by_handle_at", .errmsg = true, 790 { .name = "open_by_handle_at", .errmsg = true,
335 .arg_scnprintf = { [2] = SCA_OPEN_FLAGS, /* flags */ }, }, 791 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
792 [2] = SCA_OPEN_FLAGS, /* flags */ }, },
336 { .name = "openat", .errmsg = true, 793 { .name = "openat", .errmsg = true,
337 .arg_scnprintf = { [2] = SCA_OPEN_FLAGS, /* flags */ }, }, 794 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
795 [2] = SCA_OPEN_FLAGS, /* flags */ }, },
796 { .name = "pipe2", .errmsg = true,
797 .arg_scnprintf = { [1] = SCA_PIPE_FLAGS, /* flags */ }, },
338 { .name = "poll", .errmsg = true, .timeout = true, }, 798 { .name = "poll", .errmsg = true, .timeout = true, },
339 { .name = "ppoll", .errmsg = true, .timeout = true, }, 799 { .name = "ppoll", .errmsg = true, .timeout = true, },
340 { .name = "pread", .errmsg = true, .alias = "pread64", }, 800 { .name = "pread", .errmsg = true, .alias = "pread64",
341 { .name = "pwrite", .errmsg = true, .alias = "pwrite64", }, 801 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
342 { .name = "read", .errmsg = true, }, 802 { .name = "preadv", .errmsg = true, .alias = "pread",
343 { .name = "recvfrom", .errmsg = true, }, 803 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
804 { .name = "prlimit64", .errmsg = true, STRARRAY(1, resource, rlimit_resources), },
805 { .name = "pwrite", .errmsg = true, .alias = "pwrite64",
806 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
807 { .name = "pwritev", .errmsg = true,
808 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
809 { .name = "read", .errmsg = true,
810 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
811 { .name = "readlinkat", .errmsg = true,
812 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
813 { .name = "readv", .errmsg = true,
814 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
815 { .name = "recvfrom", .errmsg = true,
816 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
817 { .name = "recvmmsg", .errmsg = true,
818 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
819 { .name = "recvmsg", .errmsg = true,
820 .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, },
821 { .name = "renameat", .errmsg = true,
822 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
823 { .name = "rt_sigaction", .errmsg = true,
824 .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, },
825 { .name = "rt_sigprocmask", .errmsg = true, STRARRAY(0, how, sighow), },
826 { .name = "rt_sigqueueinfo", .errmsg = true,
827 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
828 { .name = "rt_tgsigqueueinfo", .errmsg = true,
829 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
344 { .name = "select", .errmsg = true, .timeout = true, }, 830 { .name = "select", .errmsg = true, .timeout = true, },
345 { .name = "socket", .errmsg = true, }, 831 { .name = "sendmmsg", .errmsg = true,
832 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
833 { .name = "sendmsg", .errmsg = true,
834 .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, },
835 { .name = "sendto", .errmsg = true,
836 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
837 { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), },
838 { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
839 { .name = "shutdown", .errmsg = true,
840 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
841 { .name = "socket", .errmsg = true,
842 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
843 [1] = SCA_SK_TYPE, /* type */ },
844 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
845 { .name = "socketpair", .errmsg = true,
846 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
847 [1] = SCA_SK_TYPE, /* type */ },
848 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
346 { .name = "stat", .errmsg = true, .alias = "newstat", }, 849 { .name = "stat", .errmsg = true, .alias = "newstat", },
850 { .name = "symlinkat", .errmsg = true,
851 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
852 { .name = "tgkill", .errmsg = true,
853 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
854 { .name = "tkill", .errmsg = true,
855 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
347 { .name = "uname", .errmsg = true, .alias = "newuname", }, 856 { .name = "uname", .errmsg = true, .alias = "newuname", },
857 { .name = "unlinkat", .errmsg = true,
858 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
859 { .name = "utimensat", .errmsg = true,
860 .arg_scnprintf = { [0] = SCA_FDAT, /* dirfd */ }, },
861 { .name = "write", .errmsg = true,
862 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
863 { .name = "writev", .errmsg = true,
864 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
348}; 865};
349 866
350static int syscall_fmt__cmp(const void *name, const void *fmtp) 867static int syscall_fmt__cmp(const void *name, const void *fmtp)
@@ -364,8 +881,8 @@ struct syscall {
364 const char *name; 881 const char *name;
365 bool filtered; 882 bool filtered;
366 struct syscall_fmt *fmt; 883 struct syscall_fmt *fmt;
367 size_t (**arg_scnprintf)(char *bf, size_t size, 884 size_t (**arg_scnprintf)(char *bf, size_t size, struct syscall_arg *arg);
368 unsigned long arg, u8 arg_idx, u8 *args_mask); 885 void **arg_parm;
369}; 886};
370 887
371static size_t fprintf_duration(unsigned long t, FILE *fp) 888static size_t fprintf_duration(unsigned long t, FILE *fp)
@@ -389,11 +906,24 @@ struct thread_trace {
389 unsigned long nr_events; 906 unsigned long nr_events;
390 char *entry_str; 907 char *entry_str;
391 double runtime_ms; 908 double runtime_ms;
909 struct {
910 int max;
911 char **table;
912 } paths;
913
914 struct intlist *syscall_stats;
392}; 915};
393 916
394static struct thread_trace *thread_trace__new(void) 917static struct thread_trace *thread_trace__new(void)
395{ 918{
396 return zalloc(sizeof(struct thread_trace)); 919 struct thread_trace *ttrace = zalloc(sizeof(struct thread_trace));
920
921 if (ttrace)
922 ttrace->paths.max = -1;
923
924 ttrace->syscall_stats = intlist__new(NULL);
925
926 return ttrace;
397} 927}
398 928
399static struct thread_trace *thread__trace(struct thread *thread, FILE *fp) 929static struct thread_trace *thread__trace(struct thread *thread, FILE *fp)
@@ -427,20 +957,116 @@ struct trace {
427 struct syscall *table; 957 struct syscall *table;
428 } syscalls; 958 } syscalls;
429 struct perf_record_opts opts; 959 struct perf_record_opts opts;
430 struct machine host; 960 struct machine *host;
431 u64 base_time; 961 u64 base_time;
962 bool full_time;
432 FILE *output; 963 FILE *output;
433 unsigned long nr_events; 964 unsigned long nr_events;
434 struct strlist *ev_qualifier; 965 struct strlist *ev_qualifier;
435 bool not_ev_qualifier; 966 bool not_ev_qualifier;
967 bool live;
436 struct intlist *tid_list; 968 struct intlist *tid_list;
437 struct intlist *pid_list; 969 struct intlist *pid_list;
438 bool sched; 970 bool sched;
439 bool multiple_threads; 971 bool multiple_threads;
972 bool summary;
973 bool show_comm;
440 double duration_filter; 974 double duration_filter;
441 double runtime_ms; 975 double runtime_ms;
442}; 976};
443 977
978static int thread__read_fd_path(struct thread *thread, int fd)
979{
980 struct thread_trace *ttrace = thread->priv;
981 char linkname[PATH_MAX], pathname[PATH_MAX];
982 struct stat st;
983 int ret;
984
985 if (thread->pid_ == thread->tid) {
986 scnprintf(linkname, sizeof(linkname),
987 "/proc/%d/fd/%d", thread->pid_, fd);
988 } else {
989 scnprintf(linkname, sizeof(linkname),
990 "/proc/%d/task/%d/fd/%d", thread->pid_, thread->tid, fd);
991 }
992
993 if (lstat(linkname, &st) < 0 || st.st_size + 1 > (off_t)sizeof(pathname))
994 return -1;
995
996 ret = readlink(linkname, pathname, sizeof(pathname));
997
998 if (ret < 0 || ret > st.st_size)
999 return -1;
1000
1001 pathname[ret] = '\0';
1002
1003 if (fd > ttrace->paths.max) {
1004 char **npath = realloc(ttrace->paths.table, (fd + 1) * sizeof(char *));
1005
1006 if (npath == NULL)
1007 return -1;
1008
1009 if (ttrace->paths.max != -1) {
1010 memset(npath + ttrace->paths.max + 1, 0,
1011 (fd - ttrace->paths.max) * sizeof(char *));
1012 } else {
1013 memset(npath, 0, (fd + 1) * sizeof(char *));
1014 }
1015
1016 ttrace->paths.table = npath;
1017 ttrace->paths.max = fd;
1018 }
1019
1020 ttrace->paths.table[fd] = strdup(pathname);
1021
1022 return ttrace->paths.table[fd] != NULL ? 0 : -1;
1023}
1024
1025static const char *thread__fd_path(struct thread *thread, int fd, bool live)
1026{
1027 struct thread_trace *ttrace = thread->priv;
1028
1029 if (ttrace == NULL)
1030 return NULL;
1031
1032 if (fd < 0)
1033 return NULL;
1034
1035 if ((fd > ttrace->paths.max || ttrace->paths.table[fd] == NULL) &&
1036 (!live || thread__read_fd_path(thread, fd)))
1037 return NULL;
1038
1039 return ttrace->paths.table[fd];
1040}
1041
1042static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
1043 struct syscall_arg *arg)
1044{
1045 int fd = arg->val;
1046 size_t printed = scnprintf(bf, size, "%d", fd);
1047 const char *path = thread__fd_path(arg->thread, fd, arg->trace->live);
1048
1049 if (path)
1050 printed += scnprintf(bf + printed, size - printed, "<%s>", path);
1051
1052 return printed;
1053}
1054
1055static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
1056 struct syscall_arg *arg)
1057{
1058 int fd = arg->val;
1059 size_t printed = syscall_arg__scnprintf_fd(bf, size, arg);
1060 struct thread_trace *ttrace = arg->thread->priv;
1061
1062 if (ttrace && fd >= 0 && fd <= ttrace->paths.max) {
1063 free(ttrace->paths.table[fd]);
1064 ttrace->paths.table[fd] = NULL;
1065 }
1066
1067 return printed;
1068}
1069
444static bool trace__filter_duration(struct trace *trace, double t) 1070static bool trace__filter_duration(struct trace *trace, double t)
445{ 1071{
446 return t < (trace->duration_filter * NSEC_PER_MSEC); 1072 return t < (trace->duration_filter * NSEC_PER_MSEC);
@@ -466,8 +1092,11 @@ static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thre
466 size_t printed = trace__fprintf_tstamp(trace, tstamp, fp); 1092 size_t printed = trace__fprintf_tstamp(trace, tstamp, fp);
467 printed += fprintf_duration(duration, fp); 1093 printed += fprintf_duration(duration, fp);
468 1094
469 if (trace->multiple_threads) 1095 if (trace->multiple_threads) {
1096 if (trace->show_comm)
1097 printed += fprintf(fp, "%.14s/", thread->comm);
470 printed += fprintf(fp, "%d ", thread->tid); 1098 printed += fprintf(fp, "%d ", thread->tid);
1099 }
471 1100
472 return printed; 1101 return printed;
473} 1102}
@@ -506,16 +1135,17 @@ static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
506 if (err) 1135 if (err)
507 return err; 1136 return err;
508 1137
509 machine__init(&trace->host, "", HOST_KERNEL_ID); 1138 trace->host = machine__new_host();
510 machine__create_kernel_maps(&trace->host); 1139 if (trace->host == NULL)
1140 return -ENOMEM;
511 1141
512 if (perf_target__has_task(&trace->opts.target)) { 1142 if (perf_target__has_task(&trace->opts.target)) {
513 err = perf_event__synthesize_thread_map(&trace->tool, evlist->threads, 1143 err = perf_event__synthesize_thread_map(&trace->tool, evlist->threads,
514 trace__tool_process, 1144 trace__tool_process,
515 &trace->host); 1145 trace->host);
516 } else { 1146 } else {
517 err = perf_event__synthesize_threads(&trace->tool, trace__tool_process, 1147 err = perf_event__synthesize_threads(&trace->tool, trace__tool_process,
518 &trace->host); 1148 trace->host);
519 } 1149 }
520 1150
521 if (err) 1151 if (err)
@@ -533,6 +1163,9 @@ static int syscall__set_arg_fmts(struct syscall *sc)
533 if (sc->arg_scnprintf == NULL) 1163 if (sc->arg_scnprintf == NULL)
534 return -1; 1164 return -1;
535 1165
1166 if (sc->fmt)
1167 sc->arg_parm = sc->fmt->arg_parm;
1168
536 for (field = sc->tp_format->format.fields->next; field; field = field->next) { 1169 for (field = sc->tp_format->format.fields->next; field; field = field->next) {
537 if (sc->fmt && sc->fmt->arg_scnprintf[idx]) 1170 if (sc->fmt && sc->fmt->arg_scnprintf[idx])
538 sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx]; 1171 sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx];
@@ -603,32 +1236,52 @@ static int trace__read_syscall_info(struct trace *trace, int id)
603} 1236}
604 1237
605static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size, 1238static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
606 unsigned long *args) 1239 unsigned long *args, struct trace *trace,
1240 struct thread *thread)
607{ 1241{
608 int i = 0;
609 size_t printed = 0; 1242 size_t printed = 0;
610 1243
611 if (sc->tp_format != NULL) { 1244 if (sc->tp_format != NULL) {
612 struct format_field *field; 1245 struct format_field *field;
613 u8 mask = 0, bit = 1; 1246 u8 bit = 1;
1247 struct syscall_arg arg = {
1248 .idx = 0,
1249 .mask = 0,
1250 .trace = trace,
1251 .thread = thread,
1252 };
614 1253
615 for (field = sc->tp_format->format.fields->next; field; 1254 for (field = sc->tp_format->format.fields->next; field;
616 field = field->next, ++i, bit <<= 1) { 1255 field = field->next, ++arg.idx, bit <<= 1) {
617 if (mask & bit) 1256 if (arg.mask & bit)
1257 continue;
1258 /*
1259 * Suppress this argument if its value is zero and
1260 * and we don't have a string associated in an
1261 * strarray for it.
1262 */
1263 if (args[arg.idx] == 0 &&
1264 !(sc->arg_scnprintf &&
1265 sc->arg_scnprintf[arg.idx] == SCA_STRARRAY &&
1266 sc->arg_parm[arg.idx]))
618 continue; 1267 continue;
619 1268
620 printed += scnprintf(bf + printed, size - printed, 1269 printed += scnprintf(bf + printed, size - printed,
621 "%s%s: ", printed ? ", " : "", field->name); 1270 "%s%s: ", printed ? ", " : "", field->name);
622 1271 if (sc->arg_scnprintf && sc->arg_scnprintf[arg.idx]) {
623 if (sc->arg_scnprintf && sc->arg_scnprintf[i]) { 1272 arg.val = args[arg.idx];
624 printed += sc->arg_scnprintf[i](bf + printed, size - printed, 1273 if (sc->arg_parm)
625 args[i], i, &mask); 1274 arg.parm = sc->arg_parm[arg.idx];
1275 printed += sc->arg_scnprintf[arg.idx](bf + printed,
1276 size - printed, &arg);
626 } else { 1277 } else {
627 printed += scnprintf(bf + printed, size - printed, 1278 printed += scnprintf(bf + printed, size - printed,
628 "%ld", args[i]); 1279 "%ld", args[arg.idx]);
629 } 1280 }
630 } 1281 }
631 } else { 1282 } else {
1283 int i = 0;
1284
632 while (i < 6) { 1285 while (i < 6) {
633 printed += scnprintf(bf + printed, size - printed, 1286 printed += scnprintf(bf + printed, size - printed,
634 "%sarg%d: %ld", 1287 "%sarg%d: %ld",
@@ -644,10 +1297,8 @@ typedef int (*tracepoint_handler)(struct trace *trace, struct perf_evsel *evsel,
644 struct perf_sample *sample); 1297 struct perf_sample *sample);
645 1298
646static struct syscall *trace__syscall_info(struct trace *trace, 1299static struct syscall *trace__syscall_info(struct trace *trace,
647 struct perf_evsel *evsel, 1300 struct perf_evsel *evsel, int id)
648 struct perf_sample *sample)
649{ 1301{
650 int id = perf_evsel__intval(evsel, sample, "id");
651 1302
652 if (id < 0) { 1303 if (id < 0) {
653 1304
@@ -688,6 +1339,32 @@ out_cant_read:
688 return NULL; 1339 return NULL;
689} 1340}
690 1341
1342static void thread__update_stats(struct thread_trace *ttrace,
1343 int id, struct perf_sample *sample)
1344{
1345 struct int_node *inode;
1346 struct stats *stats;
1347 u64 duration = 0;
1348
1349 inode = intlist__findnew(ttrace->syscall_stats, id);
1350 if (inode == NULL)
1351 return;
1352
1353 stats = inode->priv;
1354 if (stats == NULL) {
1355 stats = malloc(sizeof(struct stats));
1356 if (stats == NULL)
1357 return;
1358 init_stats(stats);
1359 inode->priv = stats;
1360 }
1361
1362 if (ttrace->entry_time && sample->time > ttrace->entry_time)
1363 duration = sample->time - ttrace->entry_time;
1364
1365 update_stats(stats, duration);
1366}
1367
691static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel, 1368static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
692 struct perf_sample *sample) 1369 struct perf_sample *sample)
693{ 1370{
@@ -695,7 +1372,8 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
695 void *args; 1372 void *args;
696 size_t printed = 0; 1373 size_t printed = 0;
697 struct thread *thread; 1374 struct thread *thread;
698 struct syscall *sc = trace__syscall_info(trace, evsel, sample); 1375 int id = perf_evsel__intval(evsel, sample, "id");
1376 struct syscall *sc = trace__syscall_info(trace, evsel, id);
699 struct thread_trace *ttrace; 1377 struct thread_trace *ttrace;
700 1378
701 if (sc == NULL) 1379 if (sc == NULL)
@@ -704,8 +1382,7 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
704 if (sc->filtered) 1382 if (sc->filtered)
705 return 0; 1383 return 0;
706 1384
707 thread = machine__findnew_thread(&trace->host, sample->pid, 1385 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
708 sample->tid);
709 ttrace = thread__trace(thread, trace->output); 1386 ttrace = thread__trace(thread, trace->output);
710 if (ttrace == NULL) 1387 if (ttrace == NULL)
711 return -1; 1388 return -1;
@@ -728,7 +1405,8 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
728 msg = ttrace->entry_str; 1405 msg = ttrace->entry_str;
729 printed += scnprintf(msg + printed, 1024 - printed, "%s(", sc->name); 1406 printed += scnprintf(msg + printed, 1024 - printed, "%s(", sc->name);
730 1407
731 printed += syscall__scnprintf_args(sc, msg + printed, 1024 - printed, args); 1408 printed += syscall__scnprintf_args(sc, msg + printed, 1024 - printed,
1409 args, trace, thread);
732 1410
733 if (!strcmp(sc->name, "exit_group") || !strcmp(sc->name, "exit")) { 1411 if (!strcmp(sc->name, "exit_group") || !strcmp(sc->name, "exit")) {
734 if (!trace->duration_filter) { 1412 if (!trace->duration_filter) {
@@ -747,7 +1425,8 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
747 int ret; 1425 int ret;
748 u64 duration = 0; 1426 u64 duration = 0;
749 struct thread *thread; 1427 struct thread *thread;
750 struct syscall *sc = trace__syscall_info(trace, evsel, sample); 1428 int id = perf_evsel__intval(evsel, sample, "id");
1429 struct syscall *sc = trace__syscall_info(trace, evsel, id);
751 struct thread_trace *ttrace; 1430 struct thread_trace *ttrace;
752 1431
753 if (sc == NULL) 1432 if (sc == NULL)
@@ -756,12 +1435,14 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
756 if (sc->filtered) 1435 if (sc->filtered)
757 return 0; 1436 return 0;
758 1437
759 thread = machine__findnew_thread(&trace->host, sample->pid, 1438 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
760 sample->tid);
761 ttrace = thread__trace(thread, trace->output); 1439 ttrace = thread__trace(thread, trace->output);
762 if (ttrace == NULL) 1440 if (ttrace == NULL)
763 return -1; 1441 return -1;
764 1442
1443 if (trace->summary)
1444 thread__update_stats(ttrace, id, sample);
1445
765 ret = perf_evsel__intval(evsel, sample, "ret"); 1446 ret = perf_evsel__intval(evsel, sample, "ret");
766 1447
767 ttrace = thread->priv; 1448 ttrace = thread->priv;
@@ -813,7 +1494,7 @@ static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evs
813{ 1494{
814 u64 runtime = perf_evsel__intval(evsel, sample, "runtime"); 1495 u64 runtime = perf_evsel__intval(evsel, sample, "runtime");
815 double runtime_ms = (double)runtime / NSEC_PER_MSEC; 1496 double runtime_ms = (double)runtime / NSEC_PER_MSEC;
816 struct thread *thread = machine__findnew_thread(&trace->host, 1497 struct thread *thread = machine__findnew_thread(trace->host,
817 sample->pid, 1498 sample->pid,
818 sample->tid); 1499 sample->tid);
819 struct thread_trace *ttrace = thread__trace(thread, trace->output); 1500 struct thread_trace *ttrace = thread__trace(thread, trace->output);
@@ -861,7 +1542,7 @@ static int trace__process_sample(struct perf_tool *tool,
861 if (skip_sample(trace, sample)) 1542 if (skip_sample(trace, sample))
862 return 0; 1543 return 0;
863 1544
864 if (trace->base_time == 0) 1545 if (!trace->full_time && trace->base_time == 0)
865 trace->base_time = sample->time; 1546 trace->base_time = sample->time;
866 1547
867 if (handler) 1548 if (handler)
@@ -901,6 +1582,35 @@ static int parse_target_str(struct trace *trace)
901 return 0; 1582 return 0;
902} 1583}
903 1584
1585static int trace__record(int argc, const char **argv)
1586{
1587 unsigned int rec_argc, i, j;
1588 const char **rec_argv;
1589 const char * const record_args[] = {
1590 "record",
1591 "-R",
1592 "-m", "1024",
1593 "-c", "1",
1594 "-e", "raw_syscalls:sys_enter,raw_syscalls:sys_exit",
1595 };
1596
1597 rec_argc = ARRAY_SIZE(record_args) + argc;
1598 rec_argv = calloc(rec_argc + 1, sizeof(char *));
1599
1600 if (rec_argv == NULL)
1601 return -ENOMEM;
1602
1603 for (i = 0; i < ARRAY_SIZE(record_args); i++)
1604 rec_argv[i] = record_args[i];
1605
1606 for (j = 0; j < (unsigned int)argc; j++, i++)
1607 rec_argv[i] = argv[j];
1608
1609 return cmd_record(i, rec_argv, NULL);
1610}
1611
1612static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp);
1613
904static int trace__run(struct trace *trace, int argc, const char **argv) 1614static int trace__run(struct trace *trace, int argc, const char **argv)
905{ 1615{
906 struct perf_evlist *evlist = perf_evlist__new(); 1616 struct perf_evlist *evlist = perf_evlist__new();
@@ -909,23 +1619,21 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
909 unsigned long before; 1619 unsigned long before;
910 const bool forks = argc > 0; 1620 const bool forks = argc > 0;
911 1621
1622 trace->live = true;
1623
912 if (evlist == NULL) { 1624 if (evlist == NULL) {
913 fprintf(trace->output, "Not enough memory to run!\n"); 1625 fprintf(trace->output, "Not enough memory to run!\n");
914 goto out; 1626 goto out;
915 } 1627 }
916 1628
917 if (perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_enter", trace__sys_enter) || 1629 if (perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_enter", trace__sys_enter) ||
918 perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_exit", trace__sys_exit)) { 1630 perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_exit", trace__sys_exit))
919 fprintf(trace->output, "Couldn't read the raw_syscalls tracepoints information!\n"); 1631 goto out_error_tp;
920 goto out_delete_evlist;
921 }
922 1632
923 if (trace->sched && 1633 if (trace->sched &&
924 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime", 1634 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime",
925 trace__sched_stat_runtime)) { 1635 trace__sched_stat_runtime))
926 fprintf(trace->output, "Couldn't read the sched_stat_runtime tracepoint information!\n"); 1636 goto out_error_tp;
927 goto out_delete_evlist;
928 }
929 1637
930 err = perf_evlist__create_maps(evlist, &trace->opts.target); 1638 err = perf_evlist__create_maps(evlist, &trace->opts.target);
931 if (err < 0) { 1639 if (err < 0) {
@@ -990,11 +1698,11 @@ again:
990 continue; 1698 continue;
991 } 1699 }
992 1700
993 if (trace->base_time == 0) 1701 if (!trace->full_time && trace->base_time == 0)
994 trace->base_time = sample.time; 1702 trace->base_time = sample.time;
995 1703
996 if (type != PERF_RECORD_SAMPLE) { 1704 if (type != PERF_RECORD_SAMPLE) {
997 trace__process_event(trace, &trace->host, event); 1705 trace__process_event(trace, trace->host, event);
998 continue; 1706 continue;
999 } 1707 }
1000 1708
@@ -1032,6 +1740,9 @@ again:
1032 goto again; 1740 goto again;
1033 1741
1034out_unmap_evlist: 1742out_unmap_evlist:
1743 if (!err && trace->summary)
1744 trace__fprintf_thread_summary(trace, trace->output);
1745
1035 perf_evlist__munmap(evlist); 1746 perf_evlist__munmap(evlist);
1036out_close_evlist: 1747out_close_evlist:
1037 perf_evlist__close(evlist); 1748 perf_evlist__close(evlist);
@@ -1040,7 +1751,31 @@ out_delete_maps:
1040out_delete_evlist: 1751out_delete_evlist:
1041 perf_evlist__delete(evlist); 1752 perf_evlist__delete(evlist);
1042out: 1753out:
1754 trace->live = false;
1043 return err; 1755 return err;
1756out_error_tp:
1757 switch(errno) {
1758 case ENOENT:
1759 fputs("Error:\tUnable to find debugfs\n"
1760 "Hint:\tWas your kernel was compiled with debugfs support?\n"
1761 "Hint:\tIs the debugfs filesystem mounted?\n"
1762 "Hint:\tTry 'sudo mount -t debugfs nodev /sys/kernel/debug'\n",
1763 trace->output);
1764 break;
1765 case EACCES:
1766 fprintf(trace->output,
1767 "Error:\tNo permissions to read %s/tracing/events/raw_syscalls\n"
1768 "Hint:\tTry 'sudo mount -o remount,mode=755 %s'\n",
1769 debugfs_mountpoint, debugfs_mountpoint);
1770 break;
1771 default: {
1772 char bf[256];
1773 fprintf(trace->output, "Can't trace: %s\n",
1774 strerror_r(errno, bf, sizeof(bf)));
1775 }
1776 break;
1777 }
1778 goto out_delete_evlist;
1044} 1779}
1045 1780
1046static int trace__replay(struct trace *trace) 1781static int trace__replay(struct trace *trace)
@@ -1077,6 +1812,8 @@ static int trace__replay(struct trace *trace)
1077 if (session == NULL) 1812 if (session == NULL)
1078 return -ENOMEM; 1813 return -ENOMEM;
1079 1814
1815 trace->host = &session->machines.host;
1816
1080 err = perf_session__set_tracepoints_handlers(session, handlers); 1817 err = perf_session__set_tracepoints_handlers(session, handlers);
1081 if (err) 1818 if (err)
1082 goto out; 1819 goto out;
@@ -1101,6 +1838,9 @@ static int trace__replay(struct trace *trace)
1101 if (err) 1838 if (err)
1102 pr_err("Failed to process events, error %d", err); 1839 pr_err("Failed to process events, error %d", err);
1103 1840
1841 else if (trace->summary)
1842 trace__fprintf_thread_summary(trace, trace->output);
1843
1104out: 1844out:
1105 perf_session__delete(session); 1845 perf_session__delete(session);
1106 1846
@@ -1111,47 +1851,111 @@ static size_t trace__fprintf_threads_header(FILE *fp)
1111{ 1851{
1112 size_t printed; 1852 size_t printed;
1113 1853
1114 printed = fprintf(fp, "\n _____________________________________________________________________\n"); 1854 printed = fprintf(fp, "\n _____________________________________________________________________________\n");
1115 printed += fprintf(fp," __) Summary of events (__\n\n"); 1855 printed += fprintf(fp, " __) Summary of events (__\n\n");
1116 printed += fprintf(fp," [ task - pid ] [ events ] [ ratio ] [ runtime ]\n"); 1856 printed += fprintf(fp, " [ task - pid ] [ events ] [ ratio ] [ runtime ]\n");
1117 printed += fprintf(fp," _____________________________________________________________________\n\n"); 1857 printed += fprintf(fp, " syscall count min max avg stddev\n");
1858 printed += fprintf(fp, " msec msec msec %%\n");
1859 printed += fprintf(fp, " _____________________________________________________________________________\n\n");
1118 1860
1119 return printed; 1861 return printed;
1120} 1862}
1121 1863
1122static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp) 1864static size_t thread__dump_stats(struct thread_trace *ttrace,
1865 struct trace *trace, FILE *fp)
1123{ 1866{
1124 size_t printed = trace__fprintf_threads_header(fp); 1867 struct stats *stats;
1125 struct rb_node *nd; 1868 size_t printed = 0;
1126 1869 struct syscall *sc;
1127 for (nd = rb_first(&trace->host.threads); nd; nd = rb_next(nd)) { 1870 struct int_node *inode = intlist__first(ttrace->syscall_stats);
1128 struct thread *thread = rb_entry(nd, struct thread, rb_node); 1871
1129 struct thread_trace *ttrace = thread->priv; 1872 if (inode == NULL)
1130 const char *color; 1873 return 0;
1131 double ratio; 1874
1132 1875 printed += fprintf(fp, "\n");
1133 if (ttrace == NULL) 1876
1134 continue; 1877 /* each int_node is a syscall */
1135 1878 while (inode) {
1136 ratio = (double)ttrace->nr_events / trace->nr_events * 100.0; 1879 stats = inode->priv;
1137 1880 if (stats) {
1138 color = PERF_COLOR_NORMAL; 1881 double min = (double)(stats->min) / NSEC_PER_MSEC;
1139 if (ratio > 50.0) 1882 double max = (double)(stats->max) / NSEC_PER_MSEC;
1140 color = PERF_COLOR_RED; 1883 double avg = avg_stats(stats);
1141 else if (ratio > 25.0) 1884 double pct;
1142 color = PERF_COLOR_GREEN; 1885 u64 n = (u64) stats->n;
1143 else if (ratio > 5.0) 1886
1144 color = PERF_COLOR_YELLOW; 1887 pct = avg ? 100.0 * stddev_stats(stats)/avg : 0.0;
1145 1888 avg /= NSEC_PER_MSEC;
1146 printed += color_fprintf(fp, color, "%20s", thread->comm); 1889
1147 printed += fprintf(fp, " - %-5d :%11lu [", thread->tid, ttrace->nr_events); 1890 sc = &trace->syscalls.table[inode->i];
1148 printed += color_fprintf(fp, color, "%5.1f%%", ratio); 1891 printed += fprintf(fp, "%24s %14s : ", "", sc->name);
1149 printed += fprintf(fp, " ] %10.3f ms\n", ttrace->runtime_ms); 1892 printed += fprintf(fp, "%5" PRIu64 " %8.3f %8.3f",
1893 n, min, max);
1894 printed += fprintf(fp, " %8.3f %6.2f\n", avg, pct);
1895 }
1896
1897 inode = intlist__next(inode);
1150 } 1898 }
1151 1899
1900 printed += fprintf(fp, "\n\n");
1901
1152 return printed; 1902 return printed;
1153} 1903}
1154 1904
1905/* struct used to pass data to per-thread function */
1906struct summary_data {
1907 FILE *fp;
1908 struct trace *trace;
1909 size_t printed;
1910};
1911
1912static int trace__fprintf_one_thread(struct thread *thread, void *priv)
1913{
1914 struct summary_data *data = priv;
1915 FILE *fp = data->fp;
1916 size_t printed = data->printed;
1917 struct trace *trace = data->trace;
1918 struct thread_trace *ttrace = thread->priv;
1919 const char *color;
1920 double ratio;
1921
1922 if (ttrace == NULL)
1923 return 0;
1924
1925 ratio = (double)ttrace->nr_events / trace->nr_events * 100.0;
1926
1927 color = PERF_COLOR_NORMAL;
1928 if (ratio > 50.0)
1929 color = PERF_COLOR_RED;
1930 else if (ratio > 25.0)
1931 color = PERF_COLOR_GREEN;
1932 else if (ratio > 5.0)
1933 color = PERF_COLOR_YELLOW;
1934
1935 printed += color_fprintf(fp, color, "%20s", thread->comm);
1936 printed += fprintf(fp, " - %-5d :%11lu [", thread->tid, ttrace->nr_events);
1937 printed += color_fprintf(fp, color, "%5.1f%%", ratio);
1938 printed += fprintf(fp, " ] %10.3f ms\n", ttrace->runtime_ms);
1939 printed += thread__dump_stats(ttrace, trace, fp);
1940
1941 data->printed += printed;
1942
1943 return 0;
1944}
1945
1946static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp)
1947{
1948 struct summary_data data = {
1949 .fp = fp,
1950 .trace = trace
1951 };
1952 data.printed = trace__fprintf_threads_header(fp);
1953
1954 machine__for_each_thread(trace->host, trace__fprintf_one_thread, &data);
1955
1956 return data.printed;
1957}
1958
1155static int trace__set_duration(const struct option *opt, const char *str, 1959static int trace__set_duration(const struct option *opt, const char *str,
1156 int unset __maybe_unused) 1960 int unset __maybe_unused)
1157{ 1961{
@@ -1183,6 +1987,8 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
1183 const char * const trace_usage[] = { 1987 const char * const trace_usage[] = {
1184 "perf trace [<options>] [<command>]", 1988 "perf trace [<options>] [<command>]",
1185 "perf trace [<options>] -- <command> [<options>]", 1989 "perf trace [<options>] -- <command> [<options>]",
1990 "perf trace record [<options>] [<command>]",
1991 "perf trace record [<options>] -- <command> [<options>]",
1186 NULL 1992 NULL
1187 }; 1993 };
1188 struct trace trace = { 1994 struct trace trace = {
@@ -1201,10 +2007,13 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
1201 .mmap_pages = 1024, 2007 .mmap_pages = 1024,
1202 }, 2008 },
1203 .output = stdout, 2009 .output = stdout,
2010 .show_comm = true,
1204 }; 2011 };
1205 const char *output_name = NULL; 2012 const char *output_name = NULL;
1206 const char *ev_qualifier_str = NULL; 2013 const char *ev_qualifier_str = NULL;
1207 const struct option trace_options[] = { 2014 const struct option trace_options[] = {
2015 OPT_BOOLEAN(0, "comm", &trace.show_comm,
2016 "show the thread COMM next to its id"),
1208 OPT_STRING('e', "expr", &ev_qualifier_str, "expr", 2017 OPT_STRING('e', "expr", &ev_qualifier_str, "expr",
1209 "list of events to trace"), 2018 "list of events to trace"),
1210 OPT_STRING('o', "output", &output_name, "file", "output file name"), 2019 OPT_STRING('o', "output", &output_name, "file", "output file name"),
@@ -1219,8 +2028,9 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
1219 "list of cpus to monitor"), 2028 "list of cpus to monitor"),
1220 OPT_BOOLEAN(0, "no-inherit", &trace.opts.no_inherit, 2029 OPT_BOOLEAN(0, "no-inherit", &trace.opts.no_inherit,
1221 "child tasks do not inherit counters"), 2030 "child tasks do not inherit counters"),
1222 OPT_UINTEGER('m', "mmap-pages", &trace.opts.mmap_pages, 2031 OPT_CALLBACK('m', "mmap-pages", &trace.opts.mmap_pages, "pages",
1223 "number of mmap data pages"), 2032 "number of mmap data pages",
2033 perf_evlist__parse_mmap_pages),
1224 OPT_STRING('u', "uid", &trace.opts.target.uid_str, "user", 2034 OPT_STRING('u', "uid", &trace.opts.target.uid_str, "user",
1225 "user to profile"), 2035 "user to profile"),
1226 OPT_CALLBACK(0, "duration", &trace, "float", 2036 OPT_CALLBACK(0, "duration", &trace, "float",
@@ -1228,11 +2038,18 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
1228 trace__set_duration), 2038 trace__set_duration),
1229 OPT_BOOLEAN(0, "sched", &trace.sched, "show blocking scheduler events"), 2039 OPT_BOOLEAN(0, "sched", &trace.sched, "show blocking scheduler events"),
1230 OPT_INCR('v', "verbose", &verbose, "be more verbose"), 2040 OPT_INCR('v', "verbose", &verbose, "be more verbose"),
2041 OPT_BOOLEAN('T', "time", &trace.full_time,
2042 "Show full timestamp, not time relative to first start"),
2043 OPT_BOOLEAN(0, "summary", &trace.summary,
2044 "Show syscall summary with statistics"),
1231 OPT_END() 2045 OPT_END()
1232 }; 2046 };
1233 int err; 2047 int err;
1234 char bf[BUFSIZ]; 2048 char bf[BUFSIZ];
1235 2049
2050 if ((argc > 1) && (strcmp(argv[1], "record") == 0))
2051 return trace__record(argc-2, &argv[2]);
2052
1236 argc = parse_options(argc, argv, trace_options, trace_usage, 0); 2053 argc = parse_options(argc, argv, trace_options, trace_usage, 0);
1237 2054
1238 if (output_name != NULL) { 2055 if (output_name != NULL) {
@@ -1280,9 +2097,6 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
1280 else 2097 else
1281 err = trace__run(&trace, argc, argv); 2098 err = trace__run(&trace, argc, argv);
1282 2099
1283 if (trace.sched && !err)
1284 trace__fprintf_thread_summary(&trace, trace.output);
1285
1286out_close: 2100out_close:
1287 if (output_name != NULL) 2101 if (output_name != NULL)
1288 fclose(trace.output); 2102 fclose(trace.output);
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index 5f6f9b3271bb..c516d6ba6716 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -23,7 +23,7 @@ ifeq ($(ARCH),x86_64)
23 endif 23 endif
24 ifeq (${IS_X86_64}, 1) 24 ifeq (${IS_X86_64}, 1)
25 RAW_ARCH := x86_64 25 RAW_ARCH := x86_64
26 CFLAGS += -DARCH_X86_64 26 CFLAGS += -DHAVE_ARCH_X86_64_SUPPORT
27 ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S 27 ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S
28 endif 28 endif
29 NO_PERF_REGS := 0 29 NO_PERF_REGS := 0
@@ -31,7 +31,7 @@ ifeq ($(ARCH),x86_64)
31endif 31endif
32 32
33ifeq ($(NO_PERF_REGS),0) 33ifeq ($(NO_PERF_REGS),0)
34 CFLAGS += -DHAVE_PERF_REGS 34 CFLAGS += -DHAVE_PERF_REGS_SUPPORT
35endif 35endif
36 36
37ifeq ($(src-perf),) 37ifeq ($(src-perf),)
@@ -51,7 +51,6 @@ LIB_INCLUDE := $(srctree)/tools/lib/
51# include ARCH specific config 51# include ARCH specific config
52-include $(src-perf)/arch/$(ARCH)/Makefile 52-include $(src-perf)/arch/$(ARCH)/Makefile
53 53
54include $(src-perf)/config/feature-tests.mak
55include $(src-perf)/config/utilities.mak 54include $(src-perf)/config/utilities.mak
56 55
57ifeq ($(call get-executable,$(FLEX)),) 56ifeq ($(call get-executable,$(FLEX)),)
@@ -67,10 +66,7 @@ ifneq ($(WERROR),0)
67 CFLAGS += -Werror 66 CFLAGS += -Werror
68endif 67endif
69 68
70ifeq ("$(origin DEBUG)", "command line") 69ifeq ($(DEBUG),0)
71 PERF_DEBUG = $(DEBUG)
72endif
73ifndef PERF_DEBUG
74 CFLAGS += -O6 70 CFLAGS += -O6
75endif 71endif
76 72
@@ -89,20 +85,125 @@ CFLAGS += -std=gnu99
89 85
90EXTLIBS = -lelf -lpthread -lrt -lm -ldl 86EXTLIBS = -lelf -lpthread -lrt -lm -ldl
91 87
92ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -fstack-protector-all,-fstack-protector-all),y) 88ifneq ($(OUTPUT),)
93 CFLAGS += -fstack-protector-all 89 OUTPUT_FEATURES = $(OUTPUT)config/feature-checks/
90 $(shell mkdir -p $(OUTPUT_FEATURES))
94endif 91endif
95 92
96ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -Wstack-protector,-Wstack-protector),y) 93feature_check = $(eval $(feature_check_code))
97 CFLAGS += -Wstack-protector 94define feature_check_code
95 feature-$(1) := $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) LDFLAGS=$(LDFLAGS) -C config/feature-checks test-$1 >/dev/null 2>/dev/null && echo 1 || echo 0)
96endef
97
98feature_set = $(eval $(feature_set_code))
99define feature_set_code
100 feature-$(1) := 1
101endef
102
103#
104# Build the feature check binaries in parallel, ignore errors, ignore return value and suppress output:
105#
106
107#
108# Note that this is not a complete list of all feature tests, just
109# those that are typically built on a fully configured system.
110#
111# [ Feature tests not mentioned here have to be built explicitly in
112# the rule that uses them - an example for that is the 'bionic'
113# feature check. ]
114#
115CORE_FEATURE_TESTS = \
116 backtrace \
117 dwarf \
118 fortify-source \
119 glibc \
120 gtk2 \
121 gtk2-infobar \
122 libaudit \
123 libbfd \
124 libelf \
125 libelf-getphdrnum \
126 libelf-mmap \
127 libnuma \
128 libperl \
129 libpython \
130 libpython-version \
131 libslang \
132 libunwind \
133 on-exit \
134 stackprotector \
135 stackprotector-all
136
137#
138# So here we detect whether test-all was rebuilt, to be able
139# to skip the print-out of the long features list if the file
140# existed before and after it was built:
141#
142ifeq ($(wildcard $(OUTPUT)config/feature-checks/test-all),)
143 test-all-failed := 1
144else
145 test-all-failed := 0
146endif
147
148#
149# Special fast-path for the 'all features are available' case:
150#
151$(call feature_check,all,$(MSG))
152
153#
154# Just in case the build freshly failed, make sure we print the
155# feature matrix:
156#
157ifeq ($(feature-all), 0)
158 test-all-failed := 1
98endif 159endif
99 160
100ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -Wvolatile-register-var,-Wvolatile-register-var),y) 161ifeq ($(test-all-failed),1)
101 CFLAGS += -Wvolatile-register-var 162 $(info )
163 $(info Auto-detecting system features:)
102endif 164endif
103 165
104ifndef PERF_DEBUG 166ifeq ($(feature-all), 1)
105 ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -D_FORTIFY_SOURCE=2,-D_FORTIFY_SOURCE=2),y) 167 #
168 # test-all.c passed - just set all the core feature flags to 1:
169 #
170 $(foreach feat,$(CORE_FEATURE_TESTS),$(call feature_set,$(feat)))
171else
172 $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) LDFLAGS=$(LDFLAGS) -i -j -C config/feature-checks $(CORE_FEATURE_TESTS) >/dev/null 2>&1)
173 $(foreach feat,$(CORE_FEATURE_TESTS),$(call feature_check,$(feat)))
174endif
175
176#
177# Print the result of the feature test:
178#
179feature_print = $(eval $(feature_print_code)) $(info $(MSG))
180
181define feature_print_code
182 ifeq ($(feature-$(1)), 1)
183 MSG = $(shell printf '...%30s: [ \033[32mon\033[m ]' $(1))
184 else
185 MSG = $(shell printf '...%30s: [ \033[31mOFF\033[m ]' $(1))
186 endif
187endef
188
189#
190# Only print out our features if we rebuilt the testcases or if a test failed:
191#
192ifeq ($(test-all-failed), 1)
193 $(foreach feat,$(CORE_FEATURE_TESTS),$(call feature_print,$(feat)))
194 $(info )
195endif
196
197ifeq ($(feature-stackprotector-all), 1)
198 CFLAGS += -fstack-protector-all
199endif
200
201ifeq ($(feature-stackprotector), 1)
202 CFLAGS += -Wstack-protector
203endif
204
205ifeq ($(DEBUG),0)
206 ifeq ($(feature-fortify-source), 1)
106 CFLAGS += -D_FORTIFY_SOURCE=2 207 CFLAGS += -D_FORTIFY_SOURCE=2
107 endif 208 endif
108endif 209endif
@@ -128,84 +229,74 @@ CFLAGS += -I$(LIB_INCLUDE)
128CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE 229CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
129 230
130ifndef NO_BIONIC 231ifndef NO_BIONIC
131ifeq ($(call try-cc,$(SOURCE_BIONIC),$(CFLAGS),bionic),y) 232 $(feature_check,bionic)
132 BIONIC := 1 233 ifeq ($(feature-bionic), 1)
133 EXTLIBS := $(filter-out -lrt,$(EXTLIBS)) 234 BIONIC := 1
134 EXTLIBS := $(filter-out -lpthread,$(EXTLIBS)) 235 EXTLIBS := $(filter-out -lrt,$(EXTLIBS))
236 EXTLIBS := $(filter-out -lpthread,$(EXTLIBS))
237 endif
135endif 238endif
136endif # NO_BIONIC
137 239
138ifdef NO_LIBELF 240ifdef NO_LIBELF
139 NO_DWARF := 1 241 NO_DWARF := 1
140 NO_DEMANGLE := 1 242 NO_DEMANGLE := 1
141 NO_LIBUNWIND := 1 243 NO_LIBUNWIND := 1
142else 244else
143FLAGS_LIBELF=$(CFLAGS) $(LDFLAGS) $(EXTLIBS) 245 ifeq ($(feature-libelf), 0)
144ifneq ($(call try-cc,$(SOURCE_LIBELF),$(FLAGS_LIBELF),libelf),y) 246 ifeq ($(feature-glibc), 1)
145 FLAGS_GLIBC=$(CFLAGS) $(LDFLAGS) 247 LIBC_SUPPORT := 1
146 ifeq ($(call try-cc,$(SOURCE_GLIBC),$(FLAGS_GLIBC),glibc),y) 248 endif
147 LIBC_SUPPORT := 1 249 ifeq ($(BIONIC),1)
148 endif 250 LIBC_SUPPORT := 1
149 ifeq ($(BIONIC),1) 251 endif
150 LIBC_SUPPORT := 1 252 ifeq ($(LIBC_SUPPORT),1)
151 endif 253 msg := $(warning No libelf found, disables 'probe' tool, please install elfutils-libelf-devel/libelf-dev);
152 ifeq ($(LIBC_SUPPORT),1)
153 msg := $(warning No libelf found, disables 'probe' tool, please install elfutils-libelf-devel/libelf-dev);
154 254
155 NO_LIBELF := 1 255 NO_LIBELF := 1
156 NO_DWARF := 1 256 NO_DWARF := 1
157 NO_DEMANGLE := 1 257 NO_DEMANGLE := 1
258 else
259 msg := $(error No gnu/libc-version.h found, please install glibc-dev[el]/glibc-static);
260 endif
158 else 261 else
159 msg := $(error No gnu/libc-version.h found, please install glibc-dev[el]/glibc-static); 262 # for linking with debug library, run like:
160 endif 263 # make DEBUG=1 LIBDW_DIR=/opt/libdw/
161else 264 ifdef LIBDW_DIR
162 # for linking with debug library, run like: 265 LIBDW_CFLAGS := -I$(LIBDW_DIR)/include
163 # make DEBUG=1 LIBDW_DIR=/opt/libdw/ 266 LIBDW_LDFLAGS := -L$(LIBDW_DIR)/lib
164 ifdef LIBDW_DIR 267 endif
165 LIBDW_CFLAGS := -I$(LIBDW_DIR)/include
166 LIBDW_LDFLAGS := -L$(LIBDW_DIR)/lib
167 endif
168 268
169 FLAGS_DWARF=$(CFLAGS) $(LIBDW_CFLAGS) -ldw -lz -lelf $(LIBDW_LDFLAGS) $(LDFLAGS) $(EXTLIBS) 269 ifneq ($(feature-dwarf), 1)
170 ifneq ($(call try-cc,$(SOURCE_DWARF),$(FLAGS_DWARF),libdw),y) 270 msg := $(warning No libdw.h found or old libdw.h found or elfutils is older than 0.138, disables dwarf support. Please install new elfutils-devel/libdw-dev);
171 msg := $(warning No libdw.h found or old libdw.h found or elfutils is older than 0.138, disables dwarf support. Please install new elfutils-devel/libdw-dev); 271 NO_DWARF := 1
172 NO_DWARF := 1 272 endif # Dwarf support
173 endif # Dwarf support 273 endif # libelf support
174endif # SOURCE_LIBELF
175endif # NO_LIBELF 274endif # NO_LIBELF
176 275
177ifndef NO_LIBELF 276ifndef NO_LIBELF
178CFLAGS += -DLIBELF_SUPPORT 277 CFLAGS += -DHAVE_LIBELF_SUPPORT
179FLAGS_LIBELF=$(CFLAGS) $(LDFLAGS) $(EXTLIBS)
180ifeq ($(call try-cc,$(SOURCE_ELF_MMAP),$(FLAGS_LIBELF),-DLIBELF_MMAP),y)
181 CFLAGS += -DLIBELF_MMAP
182endif
183ifeq ($(call try-cc,$(SOURCE_ELF_GETPHDRNUM),$(FLAGS_LIBELF),-DHAVE_ELF_GETPHDRNUM),y)
184 CFLAGS += -DHAVE_ELF_GETPHDRNUM
185endif
186 278
187# include ARCH specific config 279 ifeq ($(feature-libelf-mmap), 1)
188-include $(src-perf)/arch/$(ARCH)/Makefile 280 CFLAGS += -DHAVE_LIBELF_MMAP_SUPPORT
281 endif
189 282
190ifndef NO_DWARF 283 ifeq ($(feature-libelf-getphdrnum), 1)
191ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined) 284 CFLAGS += -DHAVE_ELF_GETPHDRNUM_SUPPORT
192 msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled); 285 endif
193 NO_DWARF := 1
194else
195 CFLAGS += -DDWARF_SUPPORT $(LIBDW_CFLAGS)
196 LDFLAGS += $(LIBDW_LDFLAGS)
197 EXTLIBS += -lelf -ldw
198endif # PERF_HAVE_DWARF_REGS
199endif # NO_DWARF
200 286
201endif # NO_LIBELF 287 # include ARCH specific config
288 -include $(src-perf)/arch/$(ARCH)/Makefile
202 289
203ifndef NO_LIBELF 290 ifndef NO_DWARF
204CFLAGS += -DLIBELF_SUPPORT 291 ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined)
205FLAGS_LIBELF=$(CFLAGS) $(LDFLAGS) $(EXTLIBS) 292 msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled);
206ifeq ($(call try-cc,$(SOURCE_ELF_MMAP),$(FLAGS_LIBELF),-DLIBELF_MMAP),y) 293 NO_DWARF := 1
207 CFLAGS += -DLIBELF_MMAP 294 else
208endif # try-cc 295 CFLAGS += -DHAVE_DWARF_SUPPORT $(LIBDW_CFLAGS)
296 LDFLAGS += $(LIBDW_LDFLAGS)
297 EXTLIBS += -lelf -ldw
298 endif # PERF_HAVE_DWARF_REGS
299 endif # NO_DWARF
209endif # NO_LIBELF 300endif # NO_LIBELF
210 301
211# There's only x86 (both 32 and 64) support for CFI unwind so far 302# There's only x86 (both 32 and 64) support for CFI unwind so far
@@ -214,34 +305,35 @@ ifneq ($(ARCH),x86)
214endif 305endif
215 306
216ifndef NO_LIBUNWIND 307ifndef NO_LIBUNWIND
217# for linking with debug library, run like: 308 #
218# make DEBUG=1 LIBUNWIND_DIR=/opt/libunwind/ 309 # For linking with debug library, run like:
219ifdef LIBUNWIND_DIR 310 #
220 LIBUNWIND_CFLAGS := -I$(LIBUNWIND_DIR)/include 311 # make DEBUG=1 LIBUNWIND_DIR=/opt/libunwind/
221 LIBUNWIND_LDFLAGS := -L$(LIBUNWIND_DIR)/lib 312 #
222endif 313 ifdef LIBUNWIND_DIR
314 LIBUNWIND_CFLAGS := -I$(LIBUNWIND_DIR)/include
315 LIBUNWIND_LDFLAGS := -L$(LIBUNWIND_DIR)/lib
316 endif
223 317
224FLAGS_UNWIND=$(LIBUNWIND_CFLAGS) $(CFLAGS) $(LIBUNWIND_LDFLAGS) $(LDFLAGS) $(EXTLIBS) $(LIBUNWIND_LIBS) 318 ifneq ($(feature-libunwind), 1)
225ifneq ($(call try-cc,$(SOURCE_LIBUNWIND),$(FLAGS_UNWIND),libunwind),y) 319 msg := $(warning No libunwind found, disabling post unwind support. Please install libunwind-dev[el] >= 0.99);
226 msg := $(warning No libunwind found, disabling post unwind support. Please install libunwind-dev[el] >= 0.99); 320 NO_LIBUNWIND := 1
227 NO_LIBUNWIND := 1 321 endif
228endif # Libunwind support 322endif
229endif # NO_LIBUNWIND
230 323
231ifndef NO_LIBUNWIND 324ifndef NO_LIBUNWIND
232 CFLAGS += -DLIBUNWIND_SUPPORT 325 CFLAGS += -DHAVE_LIBUNWIND_SUPPORT
233 EXTLIBS += $(LIBUNWIND_LIBS) 326 EXTLIBS += $(LIBUNWIND_LIBS)
234 CFLAGS += $(LIBUNWIND_CFLAGS) 327 CFLAGS += $(LIBUNWIND_CFLAGS)
235 LDFLAGS += $(LIBUNWIND_LDFLAGS) 328 LDFLAGS += $(LIBUNWIND_LDFLAGS)
236endif # NO_LIBUNWIND 329endif
237 330
238ifndef NO_LIBAUDIT 331ifndef NO_LIBAUDIT
239 FLAGS_LIBAUDIT = $(CFLAGS) $(LDFLAGS) -laudit 332 ifneq ($(feature-libaudit), 1)
240 ifneq ($(call try-cc,$(SOURCE_LIBAUDIT),$(FLAGS_LIBAUDIT),libaudit),y)
241 msg := $(warning No libaudit.h found, disables 'trace' tool, please install audit-libs-devel or libaudit-dev); 333 msg := $(warning No libaudit.h found, disables 'trace' tool, please install audit-libs-devel or libaudit-dev);
242 NO_LIBAUDIT := 1 334 NO_LIBAUDIT := 1
243 else 335 else
244 CFLAGS += -DLIBAUDIT_SUPPORT 336 CFLAGS += -DHAVE_LIBAUDIT_SUPPORT
245 EXTLIBS += -laudit 337 EXTLIBS += -laudit
246 endif 338 endif
247endif 339endif
@@ -251,30 +343,30 @@ ifdef NO_NEWT
251endif 343endif
252 344
253ifndef NO_SLANG 345ifndef NO_SLANG
254 FLAGS_SLANG=$(CFLAGS) $(LDFLAGS) $(EXTLIBS) -I/usr/include/slang -lslang 346 ifneq ($(feature-libslang), 1)
255 ifneq ($(call try-cc,$(SOURCE_SLANG),$(FLAGS_SLANG),libslang),y)
256 msg := $(warning slang not found, disables TUI support. Please install slang-devel or libslang-dev); 347 msg := $(warning slang not found, disables TUI support. Please install slang-devel or libslang-dev);
257 NO_SLANG := 1 348 NO_SLANG := 1
258 else 349 else
259 # Fedora has /usr/include/slang/slang.h, but ubuntu /usr/include/slang.h 350 # Fedora has /usr/include/slang/slang.h, but ubuntu /usr/include/slang.h
260 CFLAGS += -I/usr/include/slang 351 CFLAGS += -I/usr/include/slang
261 CFLAGS += -DSLANG_SUPPORT 352 CFLAGS += -DHAVE_SLANG_SUPPORT
262 EXTLIBS += -lslang 353 EXTLIBS += -lslang
263 endif 354 endif
264endif 355endif
265 356
266ifndef NO_GTK2 357ifndef NO_GTK2
267 FLAGS_GTK2=$(CFLAGS) $(LDFLAGS) $(EXTLIBS) $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null) 358 FLAGS_GTK2=$(CFLAGS) $(LDFLAGS) $(EXTLIBS) $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null)
268 ifneq ($(call try-cc,$(SOURCE_GTK2),$(FLAGS_GTK2),gtk2),y) 359 ifneq ($(feature-gtk2), 1)
269 msg := $(warning GTK2 not found, disables GTK2 support. Please install gtk2-devel or libgtk2.0-dev); 360 msg := $(warning GTK2 not found, disables GTK2 support. Please install gtk2-devel or libgtk2.0-dev);
270 NO_GTK2 := 1 361 NO_GTK2 := 1
271 else 362 else
272 ifeq ($(call try-cc,$(SOURCE_GTK2_INFOBAR),$(FLAGS_GTK2),-DHAVE_GTK_INFO_BAR),y) 363 ifeq ($(feature-gtk2-infobar), 1)
273 CFLAGS += -DHAVE_GTK_INFO_BAR 364 GTK_CFLAGS := -DHAVE_GTK_INFO_BAR_SUPPORT
274 endif 365 endif
275 CFLAGS += -DGTK2_SUPPORT 366 CFLAGS += -DHAVE_GTK2_SUPPORT
276 CFLAGS += $(shell pkg-config --cflags gtk+-2.0 2>/dev/null) 367 GTK_CFLAGS += $(shell pkg-config --cflags gtk+-2.0 2>/dev/null)
277 EXTLIBS += $(shell pkg-config --libs gtk+-2.0 2>/dev/null) 368 GTK_LIBS := $(shell pkg-config --libs gtk+-2.0 2>/dev/null)
369 EXTLIBS += -ldl
278 endif 370 endif
279endif 371endif
280 372
@@ -290,7 +382,7 @@ else
290 PERL_EMBED_CCOPTS = `perl -MExtUtils::Embed -e ccopts 2>/dev/null` 382 PERL_EMBED_CCOPTS = `perl -MExtUtils::Embed -e ccopts 2>/dev/null`
291 FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS) 383 FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS)
292 384
293 ifneq ($(call try-cc,$(SOURCE_PERL_EMBED),$(FLAGS_PERL_EMBED),perl),y) 385 ifneq ($(feature-libperl), 1)
294 CFLAGS += -DNO_LIBPERL 386 CFLAGS += -DNO_LIBPERL
295 NO_LIBPERL := 1 387 NO_LIBPERL := 1
296 else 388 else
@@ -335,11 +427,11 @@ else
335 PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null) 427 PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null)
336 FLAGS_PYTHON_EMBED := $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS) 428 FLAGS_PYTHON_EMBED := $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS)
337 429
338 ifneq ($(call try-cc,$(SOURCE_PYTHON_EMBED),$(FLAGS_PYTHON_EMBED),python),y) 430 ifneq ($(feature-libpython), 1)
339 $(call disable-python,Python.h (for Python 2.x)) 431 $(call disable-python,Python.h (for Python 2.x))
340 else 432 else
341 433
342 ifneq ($(call try-cc,$(SOURCE_PYTHON_VERSION),$(FLAGS_PYTHON_EMBED),python version),y) 434 ifneq ($(feature-libpython-version), 1)
343 $(warning Python 3 is not yet supported; please set) 435 $(warning Python 3 is not yet supported; please set)
344 $(warning PYTHON and/or PYTHON_CONFIG appropriately.) 436 $(warning PYTHON and/or PYTHON_CONFIG appropriately.)
345 $(warning If you also have Python 2 installed, then) 437 $(warning If you also have Python 2 installed, then)
@@ -362,33 +454,30 @@ else
362 endif 454 endif
363endif 455endif
364 456
457ifeq ($(feature-libbfd), 1)
458 EXTLIBS += -lbfd
459endif
460
365ifdef NO_DEMANGLE 461ifdef NO_DEMANGLE
366 CFLAGS += -DNO_DEMANGLE 462 CFLAGS += -DNO_DEMANGLE
367else 463else
368 ifdef HAVE_CPLUS_DEMANGLE 464 ifdef HAVE_CPLUS_DEMANGLE_SUPPORT
369 EXTLIBS += -liberty 465 EXTLIBS += -liberty
370 CFLAGS += -DHAVE_CPLUS_DEMANGLE 466 CFLAGS += -DHAVE_CPLUS_DEMANGLE_SUPPORT
371 else 467 else
372 FLAGS_BFD=$(CFLAGS) $(LDFLAGS) $(EXTLIBS) -DPACKAGE='perf' -lbfd 468 ifneq ($(feature-libbfd), 1)
373 has_bfd := $(call try-cc,$(SOURCE_BFD),$(FLAGS_BFD),libbfd) 469 $(feature_check,liberty)
374 ifeq ($(has_bfd),y) 470 ifeq ($(feature-liberty), 1)
375 EXTLIBS += -lbfd
376 else
377 FLAGS_BFD_IBERTY=$(FLAGS_BFD) -liberty
378 has_bfd_iberty := $(call try-cc,$(SOURCE_BFD),$(FLAGS_BFD_IBERTY),liberty)
379 ifeq ($(has_bfd_iberty),y)
380 EXTLIBS += -lbfd -liberty 471 EXTLIBS += -lbfd -liberty
381 else 472 else
382 FLAGS_BFD_IBERTY_Z=$(FLAGS_BFD_IBERTY) -lz 473 $(feature_check,liberty-z)
383 has_bfd_iberty_z := $(call try-cc,$(SOURCE_BFD),$(FLAGS_BFD_IBERTY_Z),libz) 474 ifeq ($(feature-liberty-z), 1)
384 ifeq ($(has_bfd_iberty_z),y)
385 EXTLIBS += -lbfd -liberty -lz 475 EXTLIBS += -lbfd -liberty -lz
386 else 476 else
387 FLAGS_CPLUS_DEMANGLE=$(CFLAGS) $(LDFLAGS) $(EXTLIBS) -liberty 477 $(feature_check,cplus-demangle)
388 has_cplus_demangle := $(call try-cc,$(SOURCE_CPLUS_DEMANGLE),$(FLAGS_CPLUS_DEMANGLE),demangle) 478 ifeq ($(feature-cplus-demangle), 1)
389 ifeq ($(has_cplus_demangle),y)
390 EXTLIBS += -liberty 479 EXTLIBS += -liberty
391 CFLAGS += -DHAVE_CPLUS_DEMANGLE 480 CFLAGS += -DHAVE_CPLUS_DEMANGLE_SUPPORT
392 else 481 else
393 msg := $(warning No bfd.h/libbfd found, install binutils-dev[el]/zlib-static to gain symbol demangling) 482 msg := $(warning No bfd.h/libbfd found, install binutils-dev[el]/zlib-static to gain symbol demangling)
394 CFLAGS += -DNO_DEMANGLE 483 CFLAGS += -DNO_DEMANGLE
@@ -399,31 +488,28 @@ else
399 endif 488 endif
400endif 489endif
401 490
402ifndef NO_STRLCPY 491ifneq ($(filter -lbfd,$(EXTLIBS)),)
403 ifeq ($(call try-cc,$(SOURCE_STRLCPY),,-DHAVE_STRLCPY),y) 492 CFLAGS += -DHAVE_LIBBFD_SUPPORT
404 CFLAGS += -DHAVE_STRLCPY
405 endif
406endif 493endif
407 494
408ifndef NO_ON_EXIT 495ifndef NO_ON_EXIT
409 ifeq ($(call try-cc,$(SOURCE_ON_EXIT),,-DHAVE_ON_EXIT),y) 496 ifeq ($(feature-on-exit), 1)
410 CFLAGS += -DHAVE_ON_EXIT 497 CFLAGS += -DHAVE_ON_EXIT_SUPPORT
411 endif 498 endif
412endif 499endif
413 500
414ifndef NO_BACKTRACE 501ifndef NO_BACKTRACE
415 ifeq ($(call try-cc,$(SOURCE_BACKTRACE),,-DBACKTRACE_SUPPORT),y) 502 ifeq ($(feature-backtrace), 1)
416 CFLAGS += -DBACKTRACE_SUPPORT 503 CFLAGS += -DHAVE_BACKTRACE_SUPPORT
417 endif 504 endif
418endif 505endif
419 506
420ifndef NO_LIBNUMA 507ifndef NO_LIBNUMA
421 FLAGS_LIBNUMA = $(CFLAGS) $(LDFLAGS) -lnuma 508 ifeq ($(feature-libnuma), 0)
422 ifneq ($(call try-cc,$(SOURCE_LIBNUMA),$(FLAGS_LIBNUMA),libnuma),y)
423 msg := $(warning No numa.h found, disables 'perf bench numa mem' benchmark, please install numa-libs-devel or libnuma-dev); 509 msg := $(warning No numa.h found, disables 'perf bench numa mem' benchmark, please install numa-libs-devel or libnuma-dev);
424 NO_LIBNUMA := 1 510 NO_LIBNUMA := 1
425 else 511 else
426 CFLAGS += -DLIBNUMA_SUPPORT 512 CFLAGS += -DHAVE_LIBNUMA_SUPPORT
427 EXTLIBS += -lnuma 513 EXTLIBS += -lnuma
428 endif 514 endif
429endif 515endif
@@ -459,7 +545,12 @@ else
459sysconfdir = $(prefix)/etc 545sysconfdir = $(prefix)/etc
460ETC_PERFCONFIG = etc/perfconfig 546ETC_PERFCONFIG = etc/perfconfig
461endif 547endif
548ifeq ($(IS_X86_64),1)
549lib = lib64
550else
462lib = lib 551lib = lib
552endif
553libdir = $(prefix)/$(lib)
463 554
464# Shell quote (do not use $(call) to accommodate ancient setups); 555# Shell quote (do not use $(call) to accommodate ancient setups);
465ETC_PERFCONFIG_SQ = $(subst ','\'',$(ETC_PERFCONFIG)) 556ETC_PERFCONFIG_SQ = $(subst ','\'',$(ETC_PERFCONFIG))
@@ -472,6 +563,7 @@ template_dir_SQ = $(subst ','\'',$(template_dir))
472htmldir_SQ = $(subst ','\'',$(htmldir)) 563htmldir_SQ = $(subst ','\'',$(htmldir))
473prefix_SQ = $(subst ','\'',$(prefix)) 564prefix_SQ = $(subst ','\'',$(prefix))
474sysconfdir_SQ = $(subst ','\'',$(sysconfdir)) 565sysconfdir_SQ = $(subst ','\'',$(sysconfdir))
566libdir_SQ = $(subst ','\'',$(libdir))
475 567
476ifneq ($(filter /%,$(firstword $(perfexecdir))),) 568ifneq ($(filter /%,$(firstword $(perfexecdir))),)
477perfexec_instdir = $(perfexecdir) 569perfexec_instdir = $(perfexecdir)
diff --git a/tools/perf/config/feature-checks/Makefile b/tools/perf/config/feature-checks/Makefile
new file mode 100644
index 000000000000..452b67cc4d7b
--- /dev/null
+++ b/tools/perf/config/feature-checks/Makefile
@@ -0,0 +1,144 @@
1
2FILES= \
3 test-all \
4 test-backtrace \
5 test-bionic \
6 test-dwarf \
7 test-fortify-source \
8 test-glibc \
9 test-gtk2 \
10 test-gtk2-infobar \
11 test-hello \
12 test-libaudit \
13 test-libbfd \
14 test-liberty \
15 test-liberty-z \
16 test-cplus-demangle \
17 test-libelf \
18 test-libelf-getphdrnum \
19 test-libelf-mmap \
20 test-libnuma \
21 test-libperl \
22 test-libpython \
23 test-libpython-version \
24 test-libslang \
25 test-libunwind \
26 test-on-exit \
27 test-stackprotector-all \
28 test-stackprotector
29
30CC := $(CC) -MD
31
32all: $(FILES)
33
34BUILD = $(CC) $(LDFLAGS) -o $(OUTPUT)$@ $@.c
35
36###############################
37
38test-all:
39 $(BUILD) -Werror -fstack-protector -fstack-protector-all -O2 -Werror -D_FORTIFY_SOURCE=2 -ldw -lelf -lnuma -lunwind -lunwind-x86_64 -lelf -laudit -I/usr/include/slang -lslang $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null) $(FLAGS_PERL_EMBED) $(FLAGS_PYTHON_EMBED) -DPACKAGE='"perf"' -lbfd -ldl
40
41test-hello:
42 $(BUILD)
43
44test-stackprotector-all:
45 $(BUILD) -Werror -fstack-protector-all
46
47test-stackprotector:
48 $(BUILD) -Werror -fstack-protector -Wstack-protector
49
50test-fortify-source:
51 $(BUILD) -O2 -Werror -D_FORTIFY_SOURCE=2
52
53test-bionic:
54 $(BUILD)
55
56test-libelf:
57 $(BUILD) -lelf
58
59test-glibc:
60 $(BUILD)
61
62test-dwarf:
63 $(BUILD) -ldw
64
65test-libelf-mmap:
66 $(BUILD) -lelf
67
68test-libelf-getphdrnum:
69 $(BUILD) -lelf
70
71test-libnuma:
72 $(BUILD) -lnuma
73
74test-libunwind:
75 $(BUILD) -lunwind -lunwind-x86_64 -lelf
76
77test-libaudit:
78 $(BUILD) -laudit
79
80test-libslang:
81 $(BUILD) -I/usr/include/slang -lslang
82
83test-gtk2:
84 $(BUILD) $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null)
85
86test-gtk2-infobar:
87 $(BUILD) $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null)
88
89grep-libs = $(filter -l%,$(1))
90strip-libs = $(filter-out -l%,$(1))
91
92PERL_EMBED_LDOPTS = $(shell perl -MExtUtils::Embed -e ldopts 2>/dev/null)
93PERL_EMBED_LDFLAGS = $(call strip-libs,$(PERL_EMBED_LDOPTS))
94PERL_EMBED_LIBADD = $(call grep-libs,$(PERL_EMBED_LDOPTS))
95PERL_EMBED_CCOPTS = `perl -MExtUtils::Embed -e ccopts 2>/dev/null`
96FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS)
97
98test-libperl:
99 $(BUILD) $(FLAGS_PERL_EMBED)
100
101override PYTHON := python
102override PYTHON_CONFIG := python-config
103
104escape-for-shell-sq = $(subst ','\'',$(1))
105shell-sq = '$(escape-for-shell-sq)'
106
107PYTHON_CONFIG_SQ = $(call shell-sq,$(PYTHON_CONFIG))
108
109PYTHON_EMBED_LDOPTS = $(shell $(PYTHON_CONFIG_SQ) --ldflags 2>/dev/null)
110PYTHON_EMBED_LDFLAGS = $(call strip-libs,$(PYTHON_EMBED_LDOPTS))
111PYTHON_EMBED_LIBADD = $(call grep-libs,$(PYTHON_EMBED_LDOPTS))
112PYTHON_EMBED_CCOPTS = $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null)
113FLAGS_PYTHON_EMBED = $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS)
114
115test-libpython:
116 $(BUILD) $(FLAGS_PYTHON_EMBED)
117
118test-libpython-version:
119 $(BUILD) $(FLAGS_PYTHON_EMBED)
120
121test-libbfd:
122 $(BUILD) -DPACKAGE='"perf"' -lbfd -ldl
123
124test-liberty:
125 $(CC) -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty
126
127test-liberty-z:
128 $(CC) -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty -lz
129
130test-cplus-demangle:
131 $(BUILD) -liberty
132
133test-on-exit:
134 $(BUILD)
135
136test-backtrace:
137 $(BUILD)
138
139-include *.d
140
141###############################
142
143clean:
144 rm -f $(FILES) *.d
diff --git a/tools/perf/config/feature-checks/test-all.c b/tools/perf/config/feature-checks/test-all.c
new file mode 100644
index 000000000000..50d431892a0c
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-all.c
@@ -0,0 +1,106 @@
1/*
2 * test-all.c: Try to build all the main testcases at once.
3 *
4 * A well-configured system will have all the prereqs installed, so we can speed
5 * up auto-detection on such systems.
6 */
7
8/*
9 * Quirk: Python and Perl headers cannot be in arbitrary places, so keep
10 * these 3 testcases at the top:
11 */
12#define main main_test_libpython
13# include "test-libpython.c"
14#undef main
15
16#define main main_test_libpython_version
17# include "test-libpython-version.c"
18#undef main
19
20#define main main_test_libperl
21# include "test-libperl.c"
22#undef main
23
24#define main main_test_hello
25# include "test-hello.c"
26#undef main
27
28#define main main_test_libelf
29# include "test-libelf.c"
30#undef main
31
32#define main main_test_libelf_mmap
33# include "test-libelf-mmap.c"
34#undef main
35
36#define main main_test_glibc
37# include "test-glibc.c"
38#undef main
39
40#define main main_test_dwarf
41# include "test-dwarf.c"
42#undef main
43
44#define main main_test_libelf_getphdrnum
45# include "test-libelf-getphdrnum.c"
46#undef main
47
48#define main main_test_libunwind
49# include "test-libunwind.c"
50#undef main
51
52#define main main_test_libaudit
53# include "test-libaudit.c"
54#undef main
55
56#define main main_test_libslang
57# include "test-libslang.c"
58#undef main
59
60#define main main_test_gtk2
61# include "test-gtk2.c"
62#undef main
63
64#define main main_test_gtk2_infobar
65# include "test-gtk2-infobar.c"
66#undef main
67
68#define main main_test_libbfd
69# include "test-libbfd.c"
70#undef main
71
72#define main main_test_on_exit
73# include "test-on-exit.c"
74#undef main
75
76#define main main_test_backtrace
77# include "test-backtrace.c"
78#undef main
79
80#define main main_test_libnuma
81# include "test-libnuma.c"
82#undef main
83
84int main(int argc, char *argv[])
85{
86 main_test_libpython();
87 main_test_libpython_version();
88 main_test_libperl();
89 main_test_hello();
90 main_test_libelf();
91 main_test_libelf_mmap();
92 main_test_glibc();
93 main_test_dwarf();
94 main_test_libelf_getphdrnum();
95 main_test_libunwind();
96 main_test_libaudit();
97 main_test_libslang();
98 main_test_gtk2(argc, argv);
99 main_test_gtk2_infobar(argc, argv);
100 main_test_libbfd();
101 main_test_on_exit();
102 main_test_backtrace();
103 main_test_libnuma();
104
105 return 0;
106}
diff --git a/tools/perf/config/feature-checks/test-backtrace.c b/tools/perf/config/feature-checks/test-backtrace.c
new file mode 100644
index 000000000000..7124aa1dc8fb
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-backtrace.c
@@ -0,0 +1,13 @@
1#include <execinfo.h>
2#include <stdio.h>
3
4int main(void)
5{
6 void *backtrace_fns[10];
7 size_t entries;
8
9 entries = backtrace(backtrace_fns, 10);
10 backtrace_symbols_fd(backtrace_fns, entries, 1);
11
12 return 0;
13}
diff --git a/tools/perf/config/feature-checks/test-bionic.c b/tools/perf/config/feature-checks/test-bionic.c
new file mode 100644
index 000000000000..eac24e9513eb
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-bionic.c
@@ -0,0 +1,6 @@
1#include <android/api-level.h>
2
3int main(void)
4{
5 return __ANDROID_API__;
6}
diff --git a/tools/perf/config/feature-checks/test-cplus-demangle.c b/tools/perf/config/feature-checks/test-cplus-demangle.c
new file mode 100644
index 000000000000..610c686e0009
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-cplus-demangle.c
@@ -0,0 +1,14 @@
1extern int printf(const char *format, ...);
2extern char *cplus_demangle(const char *, int);
3
4int main(void)
5{
6 char symbol[4096] = "FieldName__9ClassNameFd";
7 char *tmp;
8
9 tmp = cplus_demangle(symbol, 0);
10
11 printf("demangled symbol: {%s}\n", tmp);
12
13 return 0;
14}
diff --git a/tools/perf/config/feature-checks/test-dwarf.c b/tools/perf/config/feature-checks/test-dwarf.c
new file mode 100644
index 000000000000..3fc1801ce4a9
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-dwarf.c
@@ -0,0 +1,10 @@
1#include <dwarf.h>
2#include <elfutils/libdw.h>
3#include <elfutils/version.h>
4
5int main(void)
6{
7 Dwarf *dbg = dwarf_begin(0, DWARF_C_READ);
8
9 return (long)dbg;
10}
diff --git a/tools/perf/config/feature-checks/test-fortify-source.c b/tools/perf/config/feature-checks/test-fortify-source.c
new file mode 100644
index 000000000000..c9f398d87868
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-fortify-source.c
@@ -0,0 +1,6 @@
1#include <stdio.h>
2
3int main(void)
4{
5 return puts("hi");
6}
diff --git a/tools/perf/config/feature-checks/test-glibc.c b/tools/perf/config/feature-checks/test-glibc.c
new file mode 100644
index 000000000000..b0820345cd98
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-glibc.c
@@ -0,0 +1,8 @@
1#include <gnu/libc-version.h>
2
3int main(void)
4{
5 const char *version = gnu_get_libc_version();
6
7 return (long)version;
8}
diff --git a/tools/perf/config/feature-checks/test-gtk2-infobar.c b/tools/perf/config/feature-checks/test-gtk2-infobar.c
new file mode 100644
index 000000000000..397b4646d066
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-gtk2-infobar.c
@@ -0,0 +1,11 @@
1#pragma GCC diagnostic ignored "-Wstrict-prototypes"
2#include <gtk/gtk.h>
3#pragma GCC diagnostic error "-Wstrict-prototypes"
4
5int main(int argc, char *argv[])
6{
7 gtk_init(&argc, &argv);
8 gtk_info_bar_new();
9
10 return 0;
11}
diff --git a/tools/perf/config/feature-checks/test-gtk2.c b/tools/perf/config/feature-checks/test-gtk2.c
new file mode 100644
index 000000000000..6bd80e509439
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-gtk2.c
@@ -0,0 +1,10 @@
1#pragma GCC diagnostic ignored "-Wstrict-prototypes"
2#include <gtk/gtk.h>
3#pragma GCC diagnostic error "-Wstrict-prototypes"
4
5int main(int argc, char *argv[])
6{
7 gtk_init(&argc, &argv);
8
9 return 0;
10}
diff --git a/tools/perf/config/feature-checks/test-hello.c b/tools/perf/config/feature-checks/test-hello.c
new file mode 100644
index 000000000000..c9f398d87868
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-hello.c
@@ -0,0 +1,6 @@
1#include <stdio.h>
2
3int main(void)
4{
5 return puts("hi");
6}
diff --git a/tools/perf/config/feature-checks/test-libaudit.c b/tools/perf/config/feature-checks/test-libaudit.c
new file mode 100644
index 000000000000..afc019f08641
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-libaudit.c
@@ -0,0 +1,10 @@
1#include <libaudit.h>
2
3extern int printf(const char *format, ...);
4
5int main(void)
6{
7 printf("error message: %s\n", audit_errno_to_name(0));
8
9 return audit_open();
10}
diff --git a/tools/perf/config/feature-checks/test-libbfd.c b/tools/perf/config/feature-checks/test-libbfd.c
new file mode 100644
index 000000000000..24059907e990
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-libbfd.c
@@ -0,0 +1,15 @@
1#include <bfd.h>
2
3extern int printf(const char *format, ...);
4
5int main(void)
6{
7 char symbol[4096] = "FieldName__9ClassNameFd";
8 char *tmp;
9
10 tmp = bfd_demangle(0, symbol, 0);
11
12 printf("demangled symbol: {%s}\n", tmp);
13
14 return 0;
15}
diff --git a/tools/perf/config/feature-checks/test-libelf-getphdrnum.c b/tools/perf/config/feature-checks/test-libelf-getphdrnum.c
new file mode 100644
index 000000000000..d710459306c3
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-libelf-getphdrnum.c
@@ -0,0 +1,8 @@
1#include <libelf.h>
2
3int main(void)
4{
5 size_t dst;
6
7 return elf_getphdrnum(0, &dst);
8}
diff --git a/tools/perf/config/feature-checks/test-libelf-mmap.c b/tools/perf/config/feature-checks/test-libelf-mmap.c
new file mode 100644
index 000000000000..564427d7ef18
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-libelf-mmap.c
@@ -0,0 +1,8 @@
1#include <libelf.h>
2
3int main(void)
4{
5 Elf *elf = elf_begin(0, ELF_C_READ_MMAP, 0);
6
7 return (long)elf;
8}
diff --git a/tools/perf/config/feature-checks/test-libelf.c b/tools/perf/config/feature-checks/test-libelf.c
new file mode 100644
index 000000000000..08db322d8957
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-libelf.c
@@ -0,0 +1,8 @@
1#include <libelf.h>
2
3int main(void)
4{
5 Elf *elf = elf_begin(0, ELF_C_READ, 0);
6
7 return (long)elf;
8}
diff --git a/tools/perf/config/feature-checks/test-libnuma.c b/tools/perf/config/feature-checks/test-libnuma.c
new file mode 100644
index 000000000000..4763d9cd587d
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-libnuma.c
@@ -0,0 +1,9 @@
1#include <numa.h>
2#include <numaif.h>
3
4int main(void)
5{
6 numa_available();
7
8 return 0;
9}
diff --git a/tools/perf/config/feature-checks/test-libperl.c b/tools/perf/config/feature-checks/test-libperl.c
new file mode 100644
index 000000000000..8871f6a0fdb4
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-libperl.c
@@ -0,0 +1,9 @@
1#include <EXTERN.h>
2#include <perl.h>
3
4int main(void)
5{
6 perl_alloc();
7
8 return 0;
9}
diff --git a/tools/perf/config/feature-checks/test-libpython-version.c b/tools/perf/config/feature-checks/test-libpython-version.c
new file mode 100644
index 000000000000..facea122d812
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-libpython-version.c
@@ -0,0 +1,10 @@
1#include <Python.h>
2
3#if PY_VERSION_HEX >= 0x03000000
4 #error
5#endif
6
7int main(void)
8{
9 return 0;
10}
diff --git a/tools/perf/config/feature-checks/test-libpython.c b/tools/perf/config/feature-checks/test-libpython.c
new file mode 100644
index 000000000000..b24b28ad6324
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-libpython.c
@@ -0,0 +1,8 @@
1#include <Python.h>
2
3int main(void)
4{
5 Py_Initialize();
6
7 return 0;
8}
diff --git a/tools/perf/config/feature-checks/test-libslang.c b/tools/perf/config/feature-checks/test-libslang.c
new file mode 100644
index 000000000000..22ff22ed94d1
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-libslang.c
@@ -0,0 +1,6 @@
1#include <slang.h>
2
3int main(void)
4{
5 return SLsmg_init_smg();
6}
diff --git a/tools/perf/config/feature-checks/test-libunwind.c b/tools/perf/config/feature-checks/test-libunwind.c
new file mode 100644
index 000000000000..43b9369bcab7
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-libunwind.c
@@ -0,0 +1,27 @@
1#include <libunwind.h>
2#include <stdlib.h>
3
4extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
5 unw_word_t ip,
6 unw_dyn_info_t *di,
7 unw_proc_info_t *pi,
8 int need_unwind_info, void *arg);
9
10
11#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table)
12
13static unw_accessors_t accessors;
14
15int main(void)
16{
17 unw_addr_space_t addr_space;
18
19 addr_space = unw_create_addr_space(&accessors, 0);
20 if (addr_space)
21 return 0;
22
23 unw_init_remote(NULL, addr_space, NULL);
24 dwarf_search_unwind_table(addr_space, 0, NULL, NULL, 0, NULL);
25
26 return 0;
27}
diff --git a/tools/perf/config/feature-checks/test-on-exit.c b/tools/perf/config/feature-checks/test-on-exit.c
new file mode 100644
index 000000000000..8f64ed3a58d9
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-on-exit.c
@@ -0,0 +1,15 @@
1#include <stdio.h>
2
3static void exit_fn(int status, void *__data)
4{
5 printf("exit status: %d, data: %d\n", status, *(int *)__data);
6}
7
8static int data = 123;
9
10int main(void)
11{
12 on_exit(exit_fn, &data);
13
14 return 321;
15}
diff --git a/tools/perf/config/feature-checks/test-stackprotector-all.c b/tools/perf/config/feature-checks/test-stackprotector-all.c
new file mode 100644
index 000000000000..c9f398d87868
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-stackprotector-all.c
@@ -0,0 +1,6 @@
1#include <stdio.h>
2
3int main(void)
4{
5 return puts("hi");
6}
diff --git a/tools/perf/config/feature-checks/test-stackprotector.c b/tools/perf/config/feature-checks/test-stackprotector.c
new file mode 100644
index 000000000000..c9f398d87868
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-stackprotector.c
@@ -0,0 +1,6 @@
1#include <stdio.h>
2
3int main(void)
4{
5 return puts("hi");
6}
diff --git a/tools/perf/config/feature-checks/test-volatile-register-var.c b/tools/perf/config/feature-checks/test-volatile-register-var.c
new file mode 100644
index 000000000000..c9f398d87868
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-volatile-register-var.c
@@ -0,0 +1,6 @@
1#include <stdio.h>
2
3int main(void)
4{
5 return puts("hi");
6}
diff --git a/tools/perf/config/feature-tests.mak b/tools/perf/config/feature-tests.mak
deleted file mode 100644
index f79305739ecc..000000000000
--- a/tools/perf/config/feature-tests.mak
+++ /dev/null
@@ -1,246 +0,0 @@
1define SOURCE_HELLO
2#include <stdio.h>
3int main(void)
4{
5 return puts(\"hi\");
6}
7endef
8
9ifndef NO_DWARF
10define SOURCE_DWARF
11#include <dwarf.h>
12#include <elfutils/libdw.h>
13#include <elfutils/version.h>
14#ifndef _ELFUTILS_PREREQ
15#error
16#endif
17
18int main(void)
19{
20 Dwarf *dbg = dwarf_begin(0, DWARF_C_READ);
21 return (long)dbg;
22}
23endef
24endif
25
26define SOURCE_LIBELF
27#include <libelf.h>
28
29int main(void)
30{
31 Elf *elf = elf_begin(0, ELF_C_READ, 0);
32 return (long)elf;
33}
34endef
35
36define SOURCE_GLIBC
37#include <gnu/libc-version.h>
38
39int main(void)
40{
41 const char *version = gnu_get_libc_version();
42 return (long)version;
43}
44endef
45
46define SOURCE_BIONIC
47#include <android/api-level.h>
48
49int main(void)
50{
51 return __ANDROID_API__;
52}
53endef
54
55define SOURCE_ELF_MMAP
56#include <libelf.h>
57int main(void)
58{
59 Elf *elf = elf_begin(0, ELF_C_READ_MMAP, 0);
60 return (long)elf;
61}
62endef
63
64define SOURCE_ELF_GETPHDRNUM
65#include <libelf.h>
66int main(void)
67{
68 size_t dst;
69 return elf_getphdrnum(0, &dst);
70}
71endef
72
73ifndef NO_SLANG
74define SOURCE_SLANG
75#include <slang.h>
76
77int main(void)
78{
79 return SLsmg_init_smg();
80}
81endef
82endif
83
84ifndef NO_GTK2
85define SOURCE_GTK2
86#pragma GCC diagnostic ignored \"-Wstrict-prototypes\"
87#include <gtk/gtk.h>
88#pragma GCC diagnostic error \"-Wstrict-prototypes\"
89
90int main(int argc, char *argv[])
91{
92 gtk_init(&argc, &argv);
93
94 return 0;
95}
96endef
97
98define SOURCE_GTK2_INFOBAR
99#pragma GCC diagnostic ignored \"-Wstrict-prototypes\"
100#include <gtk/gtk.h>
101#pragma GCC diagnostic error \"-Wstrict-prototypes\"
102
103int main(void)
104{
105 gtk_info_bar_new();
106
107 return 0;
108}
109endef
110endif
111
112ifndef NO_LIBPERL
113define SOURCE_PERL_EMBED
114#include <EXTERN.h>
115#include <perl.h>
116
117int main(void)
118{
119perl_alloc();
120return 0;
121}
122endef
123endif
124
125ifndef NO_LIBPYTHON
126define SOURCE_PYTHON_VERSION
127#include <Python.h>
128#if PY_VERSION_HEX >= 0x03000000
129 #error
130#endif
131int main(void)
132{
133 return 0;
134}
135endef
136define SOURCE_PYTHON_EMBED
137#include <Python.h>
138int main(void)
139{
140 Py_Initialize();
141 return 0;
142}
143endef
144endif
145
146define SOURCE_BFD
147#include <bfd.h>
148
149int main(void)
150{
151 bfd_demangle(0, 0, 0);
152 return 0;
153}
154endef
155
156define SOURCE_CPLUS_DEMANGLE
157extern char *cplus_demangle(const char *, int);
158
159int main(void)
160{
161 cplus_demangle(0, 0);
162 return 0;
163}
164endef
165
166define SOURCE_STRLCPY
167#include <stdlib.h>
168extern size_t strlcpy(char *dest, const char *src, size_t size);
169
170int main(void)
171{
172 strlcpy(NULL, NULL, 0);
173 return 0;
174}
175endef
176
177ifndef NO_LIBUNWIND
178define SOURCE_LIBUNWIND
179#include <libunwind.h>
180#include <stdlib.h>
181
182extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
183 unw_word_t ip,
184 unw_dyn_info_t *di,
185 unw_proc_info_t *pi,
186 int need_unwind_info, void *arg);
187
188
189#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table)
190
191int main(void)
192{
193 unw_addr_space_t addr_space;
194 addr_space = unw_create_addr_space(NULL, 0);
195 unw_init_remote(NULL, addr_space, NULL);
196 dwarf_search_unwind_table(addr_space, 0, NULL, NULL, 0, NULL);
197 return 0;
198}
199endef
200endif
201
202ifndef NO_BACKTRACE
203define SOURCE_BACKTRACE
204#include <execinfo.h>
205#include <stdio.h>
206
207int main(void)
208{
209 backtrace(NULL, 0);
210 backtrace_symbols(NULL, 0);
211 return 0;
212}
213endef
214endif
215
216ifndef NO_LIBAUDIT
217define SOURCE_LIBAUDIT
218#include <libaudit.h>
219
220int main(void)
221{
222 printf(\"error message: %s\", audit_errno_to_name(0));
223 return audit_open();
224}
225endef
226endif
227
228define SOURCE_ON_EXIT
229#include <stdio.h>
230
231int main(void)
232{
233 return on_exit(NULL, NULL);
234}
235endef
236
237define SOURCE_LIBNUMA
238#include <numa.h>
239#include <numaif.h>
240
241int main(void)
242{
243 numa_available();
244 return 0;
245}
246endef
diff --git a/tools/perf/config/utilities.mak b/tools/perf/config/utilities.mak
index 94d2d4f9c35d..f168debc5be2 100644
--- a/tools/perf/config/utilities.mak
+++ b/tools/perf/config/utilities.mak
@@ -179,16 +179,9 @@ _ge_attempt = $(if $(get-executable),$(get-executable),$(_gea_warn)$(call _gea_e
179_gea_warn = $(warning The path '$(1)' is not executable.) 179_gea_warn = $(warning The path '$(1)' is not executable.)
180_gea_err = $(if $(1),$(error Please set '$(1)' appropriately)) 180_gea_err = $(if $(1),$(error Please set '$(1)' appropriately))
181 181
182# try-cc 182ifneq ($(findstring $(MAKEFLAGS),s),s)
183# Usage: option = $(call try-cc, source-to-build, cc-options, msg) 183 ifneq ($(V),1)
184ifneq ($(V),1) 184 QUIET_CLEAN = @printf ' CLEAN %s\n' $1;
185TRY_CC_OUTPUT= > /dev/null 2>&1 185 QUIET_INSTALL = @printf ' INSTALL %s\n' $1;
186 endif
186endif 187endif
187TRY_CC_MSG=echo " CHK $(3)" 1>&2;
188
189try-cc = $(shell sh -c \
190 'TMP="$(OUTPUT)$(TMPOUT).$$$$"; \
191 $(TRY_CC_MSG) \
192 echo "$(1)" | \
193 $(CC) -x c - $(2) -o "$$TMP" $(TRY_CC_OUTPUT) && echo y; \
194 rm -f "$$TMP"')
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 85e1aed95204..8b38b4e80ec2 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -49,14 +49,14 @@ static struct cmd_struct commands[] = {
49 { "version", cmd_version, 0 }, 49 { "version", cmd_version, 0 },
50 { "script", cmd_script, 0 }, 50 { "script", cmd_script, 0 },
51 { "sched", cmd_sched, 0 }, 51 { "sched", cmd_sched, 0 },
52#ifdef LIBELF_SUPPORT 52#ifdef HAVE_LIBELF_SUPPORT
53 { "probe", cmd_probe, 0 }, 53 { "probe", cmd_probe, 0 },
54#endif 54#endif
55 { "kmem", cmd_kmem, 0 }, 55 { "kmem", cmd_kmem, 0 },
56 { "lock", cmd_lock, 0 }, 56 { "lock", cmd_lock, 0 },
57 { "kvm", cmd_kvm, 0 }, 57 { "kvm", cmd_kvm, 0 },
58 { "test", cmd_test, 0 }, 58 { "test", cmd_test, 0 },
59#ifdef LIBAUDIT_SUPPORT 59#ifdef HAVE_LIBAUDIT_SUPPORT
60 { "trace", cmd_trace, 0 }, 60 { "trace", cmd_trace, 0 },
61#endif 61#endif
62 { "inject", cmd_inject, 0 }, 62 { "inject", cmd_inject, 0 },
@@ -456,6 +456,7 @@ int main(int argc, const char **argv)
456{ 456{
457 const char *cmd; 457 const char *cmd;
458 458
459 /* The page_size is placed in util object. */
459 page_size = sysconf(_SC_PAGE_SIZE); 460 page_size = sysconf(_SC_PAGE_SIZE);
460 461
461 cmd = perf_extract_argv0_path(argv[0]); 462 cmd = perf_extract_argv0_path(argv[0]);
@@ -480,7 +481,14 @@ int main(int argc, const char **argv)
480 fprintf(stderr, "cannot handle %s internally", cmd); 481 fprintf(stderr, "cannot handle %s internally", cmd);
481 goto out; 482 goto out;
482 } 483 }
483 484#ifdef HAVE_LIBAUDIT_SUPPORT
485 if (!prefixcmp(cmd, "trace")) {
486 set_buildid_dir();
487 setup_path();
488 argv[0] = "trace";
489 return cmd_trace(argc, argv, NULL);
490 }
491#endif
484 /* Look for flags.. */ 492 /* Look for flags.. */
485 argv++; 493 argv++;
486 argc--; 494 argc--;
diff --git a/tools/perf/tests/dso-data.c b/tools/perf/tests/dso-data.c
index dffe0551acaa..9cc81a3eb9b4 100644
--- a/tools/perf/tests/dso-data.c
+++ b/tools/perf/tests/dso-data.c
@@ -35,6 +35,7 @@ static char *test_file(int size)
35 if (size != write(fd, buf, size)) 35 if (size != write(fd, buf, size))
36 templ = NULL; 36 templ = NULL;
37 37
38 free(buf);
38 close(fd); 39 close(fd);
39 return templ; 40 return templ;
40} 41}
diff --git a/tools/perf/tests/perf-record.c b/tools/perf/tests/perf-record.c
index b8a7056519ac..82ac71550091 100644
--- a/tools/perf/tests/perf-record.c
+++ b/tools/perf/tests/perf-record.c
@@ -45,7 +45,7 @@ int test__PERF_RECORD(void)
45 }; 45 };
46 cpu_set_t cpu_mask; 46 cpu_set_t cpu_mask;
47 size_t cpu_mask_size = sizeof(cpu_mask); 47 size_t cpu_mask_size = sizeof(cpu_mask);
48 struct perf_evlist *evlist = perf_evlist__new(); 48 struct perf_evlist *evlist = perf_evlist__new_default();
49 struct perf_evsel *evsel; 49 struct perf_evsel *evsel;
50 struct perf_sample sample; 50 struct perf_sample sample;
51 const char *cmd = "sleep"; 51 const char *cmd = "sleep";
@@ -66,16 +66,6 @@ int test__PERF_RECORD(void)
66 } 66 }
67 67
68 /* 68 /*
69 * We need at least one evsel in the evlist, use the default
70 * one: "cycles".
71 */
72 err = perf_evlist__add_default(evlist);
73 if (err < 0) {
74 pr_debug("Not enough memory to create evsel\n");
75 goto out_delete_evlist;
76 }
77
78 /*
79 * Create maps of threads and cpus to monitor. In this case 69 * Create maps of threads and cpus to monitor. In this case
80 * we start with all threads and cpus (-1, -1) but then in 70 * we start with all threads and cpus (-1, -1) but then in
81 * perf_evlist__prepare_workload we'll fill in the only thread 71 * perf_evlist__prepare_workload we'll fill in the only thread
diff --git a/tools/perf/tests/task-exit.c b/tools/perf/tests/task-exit.c
index 28fe5894b061..b07f8a14e15d 100644
--- a/tools/perf/tests/task-exit.c
+++ b/tools/perf/tests/task-exit.c
@@ -37,20 +37,11 @@ int test__task_exit(void)
37 signal(SIGCHLD, sig_handler); 37 signal(SIGCHLD, sig_handler);
38 signal(SIGUSR1, sig_handler); 38 signal(SIGUSR1, sig_handler);
39 39
40 evlist = perf_evlist__new(); 40 evlist = perf_evlist__new_default();
41 if (evlist == NULL) { 41 if (evlist == NULL) {
42 pr_debug("perf_evlist__new\n"); 42 pr_debug("perf_evlist__new_default\n");
43 return -1; 43 return -1;
44 } 44 }
45 /*
46 * We need at least one evsel in the evlist, use the default
47 * one: "cycles".
48 */
49 err = perf_evlist__add_default(evlist);
50 if (err < 0) {
51 pr_debug("Not enough memory to create evsel\n");
52 goto out_free_evlist;
53 }
54 45
55 /* 46 /*
56 * Create maps of threads and cpus to monitor. In this case 47 * Create maps of threads and cpus to monitor. In this case
@@ -117,7 +108,6 @@ out_close_evlist:
117 perf_evlist__close(evlist); 108 perf_evlist__close(evlist);
118out_delete_maps: 109out_delete_maps:
119 perf_evlist__delete_maps(evlist); 110 perf_evlist__delete_maps(evlist);
120out_free_evlist:
121 perf_evlist__delete(evlist); 111 perf_evlist__delete(evlist);
122 return err; 112 return err;
123} 113}
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index 08545ae46992..f0697a3aede0 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -442,35 +442,37 @@ static bool annotate_browser__callq(struct annotate_browser *browser,
442{ 442{
443 struct map_symbol *ms = browser->b.priv; 443 struct map_symbol *ms = browser->b.priv;
444 struct disasm_line *dl = browser->selection; 444 struct disasm_line *dl = browser->selection;
445 struct symbol *sym = ms->sym;
446 struct annotation *notes; 445 struct annotation *notes;
447 struct symbol *target; 446 struct addr_map_symbol target = {
448 u64 ip; 447 .map = ms->map,
448 .addr = map__objdump_2mem(ms->map, dl->ops.target.addr),
449 };
449 char title[SYM_TITLE_MAX_SIZE]; 450 char title[SYM_TITLE_MAX_SIZE];
450 451
451 if (!ins__is_call(dl->ins)) 452 if (!ins__is_call(dl->ins))
452 return false; 453 return false;
453 454
454 ip = ms->map->map_ip(ms->map, dl->ops.target.addr); 455 if (map_groups__find_ams(&target, NULL) ||
455 target = map__find_symbol(ms->map, ip, NULL); 456 map__rip_2objdump(target.map, target.map->map_ip(target.map,
456 if (target == NULL) { 457 target.addr)) !=
458 dl->ops.target.addr) {
457 ui_helpline__puts("The called function was not found."); 459 ui_helpline__puts("The called function was not found.");
458 return true; 460 return true;
459 } 461 }
460 462
461 notes = symbol__annotation(target); 463 notes = symbol__annotation(target.sym);
462 pthread_mutex_lock(&notes->lock); 464 pthread_mutex_lock(&notes->lock);
463 465
464 if (notes->src == NULL && symbol__alloc_hist(target) < 0) { 466 if (notes->src == NULL && symbol__alloc_hist(target.sym) < 0) {
465 pthread_mutex_unlock(&notes->lock); 467 pthread_mutex_unlock(&notes->lock);
466 ui__warning("Not enough memory for annotating '%s' symbol!\n", 468 ui__warning("Not enough memory for annotating '%s' symbol!\n",
467 target->name); 469 target.sym->name);
468 return true; 470 return true;
469 } 471 }
470 472
471 pthread_mutex_unlock(&notes->lock); 473 pthread_mutex_unlock(&notes->lock);
472 symbol__tui_annotate(target, ms->map, evsel, hbt); 474 symbol__tui_annotate(target.sym, target.map, evsel, hbt);
473 sym_title(sym, ms->map, title, sizeof(title)); 475 sym_title(ms->sym, ms->map, title, sizeof(title));
474 ui_browser__show_title(&browser->b, title); 476 ui_browser__show_title(&browser->b, title);
475 return true; 477 return true;
476} 478}
diff --git a/tools/perf/ui/gtk/annotate.c b/tools/perf/ui/gtk/annotate.c
index f538794615db..9c7ff8d31b27 100644
--- a/tools/perf/ui/gtk/annotate.c
+++ b/tools/perf/ui/gtk/annotate.c
@@ -154,9 +154,9 @@ static int perf_gtk__annotate_symbol(GtkWidget *window, struct symbol *sym,
154 return 0; 154 return 0;
155} 155}
156 156
157int symbol__gtk_annotate(struct symbol *sym, struct map *map, 157static int symbol__gtk_annotate(struct symbol *sym, struct map *map,
158 struct perf_evsel *evsel, 158 struct perf_evsel *evsel,
159 struct hist_browser_timer *hbt) 159 struct hist_browser_timer *hbt)
160{ 160{
161 GtkWidget *window; 161 GtkWidget *window;
162 GtkWidget *notebook; 162 GtkWidget *notebook;
@@ -226,6 +226,13 @@ int symbol__gtk_annotate(struct symbol *sym, struct map *map,
226 return 0; 226 return 0;
227} 227}
228 228
229int hist_entry__gtk_annotate(struct hist_entry *he,
230 struct perf_evsel *evsel,
231 struct hist_browser_timer *hbt)
232{
233 return symbol__gtk_annotate(he->ms.sym, he->ms.map, evsel, hbt);
234}
235
229void perf_gtk__show_annotations(void) 236void perf_gtk__show_annotations(void)
230{ 237{
231 GtkWidget *window; 238 GtkWidget *window;
diff --git a/tools/perf/ui/gtk/browser.c b/tools/perf/ui/gtk/browser.c
index c95012cdb438..c24d91221290 100644
--- a/tools/perf/ui/gtk/browser.c
+++ b/tools/perf/ui/gtk/browser.c
@@ -43,7 +43,7 @@ const char *perf_gtk__get_percent_color(double percent)
43 return NULL; 43 return NULL;
44} 44}
45 45
46#ifdef HAVE_GTK_INFO_BAR 46#ifdef HAVE_GTK_INFO_BAR_SUPPORT
47GtkWidget *perf_gtk__setup_info_bar(void) 47GtkWidget *perf_gtk__setup_info_bar(void)
48{ 48{
49 GtkWidget *info_bar; 49 GtkWidget *info_bar;
diff --git a/tools/perf/ui/gtk/gtk.h b/tools/perf/ui/gtk/gtk.h
index 3d96785ef155..8576cf194872 100644
--- a/tools/perf/ui/gtk/gtk.h
+++ b/tools/perf/ui/gtk/gtk.h
@@ -12,7 +12,7 @@ struct perf_gtk_context {
12 GtkWidget *main_window; 12 GtkWidget *main_window;
13 GtkWidget *notebook; 13 GtkWidget *notebook;
14 14
15#ifdef HAVE_GTK_INFO_BAR 15#ifdef HAVE_GTK_INFO_BAR_SUPPORT
16 GtkWidget *info_bar; 16 GtkWidget *info_bar;
17 GtkWidget *message_label; 17 GtkWidget *message_label;
18#endif 18#endif
@@ -20,6 +20,9 @@ struct perf_gtk_context {
20 guint statbar_ctx_id; 20 guint statbar_ctx_id;
21}; 21};
22 22
23int perf_gtk__init(void);
24void perf_gtk__exit(bool wait_for_ok);
25
23extern struct perf_gtk_context *pgctx; 26extern struct perf_gtk_context *pgctx;
24 27
25static inline bool perf_gtk__is_active_context(struct perf_gtk_context *ctx) 28static inline bool perf_gtk__is_active_context(struct perf_gtk_context *ctx)
@@ -39,7 +42,7 @@ void perf_gtk__resize_window(GtkWidget *window);
39const char *perf_gtk__get_percent_color(double percent); 42const char *perf_gtk__get_percent_color(double percent);
40GtkWidget *perf_gtk__setup_statusbar(void); 43GtkWidget *perf_gtk__setup_statusbar(void);
41 44
42#ifdef HAVE_GTK_INFO_BAR 45#ifdef HAVE_GTK_INFO_BAR_SUPPORT
43GtkWidget *perf_gtk__setup_info_bar(void); 46GtkWidget *perf_gtk__setup_info_bar(void);
44#else 47#else
45static inline GtkWidget *perf_gtk__setup_info_bar(void) 48static inline GtkWidget *perf_gtk__setup_info_bar(void)
@@ -48,4 +51,17 @@ static inline GtkWidget *perf_gtk__setup_info_bar(void)
48} 51}
49#endif 52#endif
50 53
54struct perf_evsel;
55struct perf_evlist;
56struct hist_entry;
57struct hist_browser_timer;
58
59int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, const char *help,
60 struct hist_browser_timer *hbt,
61 float min_pcnt);
62int hist_entry__gtk_annotate(struct hist_entry *he,
63 struct perf_evsel *evsel,
64 struct hist_browser_timer *hbt);
65void perf_gtk__show_annotations(void);
66
51#endif /* _PERF_GTK_H_ */ 67#endif /* _PERF_GTK_H_ */
diff --git a/tools/perf/ui/gtk/util.c b/tools/perf/ui/gtk/util.c
index c06942a41c78..696c1fbe4248 100644
--- a/tools/perf/ui/gtk/util.c
+++ b/tools/perf/ui/gtk/util.c
@@ -53,7 +53,7 @@ static int perf_gtk__error(const char *format, va_list args)
53 return 0; 53 return 0;
54} 54}
55 55
56#ifdef HAVE_GTK_INFO_BAR 56#ifdef HAVE_GTK_INFO_BAR_SUPPORT
57static int perf_gtk__warning_info_bar(const char *format, va_list args) 57static int perf_gtk__warning_info_bar(const char *format, va_list args)
58{ 58{
59 char *msg; 59 char *msg;
@@ -105,7 +105,7 @@ static int perf_gtk__warning_statusbar(const char *format, va_list args)
105 105
106struct perf_error_ops perf_gtk_eops = { 106struct perf_error_ops perf_gtk_eops = {
107 .error = perf_gtk__error, 107 .error = perf_gtk__error,
108#ifdef HAVE_GTK_INFO_BAR 108#ifdef HAVE_GTK_INFO_BAR_SUPPORT
109 .warning = perf_gtk__warning_info_bar, 109 .warning = perf_gtk__warning_info_bar,
110#else 110#else
111 .warning = perf_gtk__warning_statusbar, 111 .warning = perf_gtk__warning_statusbar,
diff --git a/tools/perf/ui/setup.c b/tools/perf/ui/setup.c
index 47d9a571f261..5df5140a9f29 100644
--- a/tools/perf/ui/setup.c
+++ b/tools/perf/ui/setup.c
@@ -1,10 +1,64 @@
1#include <pthread.h> 1#include <pthread.h>
2#include <dlfcn.h>
2 3
3#include "../util/cache.h" 4#include "../util/cache.h"
4#include "../util/debug.h" 5#include "../util/debug.h"
5#include "../util/hist.h" 6#include "../util/hist.h"
6 7
7pthread_mutex_t ui__lock = PTHREAD_MUTEX_INITIALIZER; 8pthread_mutex_t ui__lock = PTHREAD_MUTEX_INITIALIZER;
9void *perf_gtk_handle;
10
11#ifdef HAVE_GTK2_SUPPORT
12static int setup_gtk_browser(void)
13{
14 int (*perf_ui_init)(void);
15
16 if (perf_gtk_handle)
17 return 0;
18
19 perf_gtk_handle = dlopen(PERF_GTK_DSO, RTLD_LAZY);
20 if (perf_gtk_handle == NULL) {
21 char buf[PATH_MAX];
22 scnprintf(buf, sizeof(buf), "%s/%s", LIBDIR, PERF_GTK_DSO);
23 perf_gtk_handle = dlopen(buf, RTLD_LAZY);
24 }
25 if (perf_gtk_handle == NULL)
26 return -1;
27
28 perf_ui_init = dlsym(perf_gtk_handle, "perf_gtk__init");
29 if (perf_ui_init == NULL)
30 goto out_close;
31
32 if (perf_ui_init() == 0)
33 return 0;
34
35out_close:
36 dlclose(perf_gtk_handle);
37 return -1;
38}
39
40static void exit_gtk_browser(bool wait_for_ok)
41{
42 void (*perf_ui_exit)(bool);
43
44 if (perf_gtk_handle == NULL)
45 return;
46
47 perf_ui_exit = dlsym(perf_gtk_handle, "perf_gtk__exit");
48 if (perf_ui_exit == NULL)
49 goto out_close;
50
51 perf_ui_exit(wait_for_ok);
52
53out_close:
54 dlclose(perf_gtk_handle);
55
56 perf_gtk_handle = NULL;
57}
58#else
59static inline int setup_gtk_browser(void) { return -1; }
60static inline void exit_gtk_browser(bool wait_for_ok __maybe_unused) {}
61#endif
8 62
9void setup_browser(bool fallback_to_pager) 63void setup_browser(bool fallback_to_pager)
10{ 64{
@@ -17,8 +71,11 @@ void setup_browser(bool fallback_to_pager)
17 71
18 switch (use_browser) { 72 switch (use_browser) {
19 case 2: 73 case 2:
20 if (perf_gtk__init() == 0) 74 if (setup_gtk_browser() == 0)
21 break; 75 break;
76 printf("GTK browser requested but could not find %s\n",
77 PERF_GTK_DSO);
78 sleep(1);
22 /* fall through */ 79 /* fall through */
23 case 1: 80 case 1:
24 use_browser = 1; 81 use_browser = 1;
@@ -39,7 +96,7 @@ void exit_browser(bool wait_for_ok)
39{ 96{
40 switch (use_browser) { 97 switch (use_browser) {
41 case 2: 98 case 2:
42 perf_gtk__exit(wait_for_ok); 99 exit_gtk_browser(wait_for_ok);
43 break; 100 break;
44 101
45 case 1: 102 case 1:
diff --git a/tools/perf/ui/ui.h b/tools/perf/ui/ui.h
index 70cb0d4eb8aa..ab88383f8be8 100644
--- a/tools/perf/ui/ui.h
+++ b/tools/perf/ui/ui.h
@@ -6,13 +6,14 @@
6#include <linux/compiler.h> 6#include <linux/compiler.h>
7 7
8extern pthread_mutex_t ui__lock; 8extern pthread_mutex_t ui__lock;
9extern void *perf_gtk_handle;
9 10
10extern int use_browser; 11extern int use_browser;
11 12
12void setup_browser(bool fallback_to_pager); 13void setup_browser(bool fallback_to_pager);
13void exit_browser(bool wait_for_ok); 14void exit_browser(bool wait_for_ok);
14 15
15#ifdef SLANG_SUPPORT 16#ifdef HAVE_SLANG_SUPPORT
16int ui__init(void); 17int ui__init(void);
17void ui__exit(bool wait_for_ok); 18void ui__exit(bool wait_for_ok);
18#else 19#else
@@ -23,17 +24,6 @@ static inline int ui__init(void)
23static inline void ui__exit(bool wait_for_ok __maybe_unused) {} 24static inline void ui__exit(bool wait_for_ok __maybe_unused) {}
24#endif 25#endif
25 26
26#ifdef GTK2_SUPPORT
27int perf_gtk__init(void);
28void perf_gtk__exit(bool wait_for_ok);
29#else
30static inline int perf_gtk__init(void)
31{
32 return -1;
33}
34static inline void perf_gtk__exit(bool wait_for_ok __maybe_unused) {}
35#endif
36
37void ui__refresh_dimensions(bool force); 27void ui__refresh_dimensions(bool force);
38 28
39#endif /* _PERF_UI_H_ */ 29#endif /* _PERF_UI_H_ */
diff --git a/tools/perf/util/PERF-VERSION-GEN b/tools/perf/util/PERF-VERSION-GEN
index 15a77b7c0e36..ce7a804b2951 100755
--- a/tools/perf/util/PERF-VERSION-GEN
+++ b/tools/perf/util/PERF-VERSION-GEN
@@ -40,7 +40,7 @@ else
40 VC=unset 40 VC=unset
41fi 41fi
42test "$VN" = "$VC" || { 42test "$VN" = "$VC" || {
43 echo >&2 "PERF_VERSION = $VN" 43 echo >&2 " PERF_VERSION = $VN"
44 echo "#define PERF_VERSION \"$VN\"" >$GVF 44 echo "#define PERF_VERSION \"$VN\"" >$GVF
45} 45}
46 46
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 7eae5488ecea..cf6242c92ee2 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -825,20 +825,16 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
825 dl->ops.target.offset = dl->ops.target.addr - 825 dl->ops.target.offset = dl->ops.target.addr -
826 map__rip_2objdump(map, sym->start); 826 map__rip_2objdump(map, sym->start);
827 827
828 /* 828 /* kcore has no symbols, so add the call target name */
829 * kcore has no symbols, so add the call target name if it is on the
830 * same map.
831 */
832 if (dl->ins && ins__is_call(dl->ins) && !dl->ops.target.name) { 829 if (dl->ins && ins__is_call(dl->ins) && !dl->ops.target.name) {
833 struct symbol *s; 830 struct addr_map_symbol target = {
834 u64 ip = dl->ops.target.addr; 831 .map = map,
835 832 .addr = dl->ops.target.addr,
836 if (ip >= map->start && ip <= map->end) { 833 };
837 ip = map->map_ip(map, ip); 834
838 s = map__find_symbol(map, ip, NULL); 835 if (!map_groups__find_ams(&target, NULL) &&
839 if (s && s->start == ip) 836 target.sym->start == target.al_addr)
840 dl->ops.target.name = strdup(s->name); 837 dl->ops.target.name = strdup(target.sym->name);
841 }
842 } 838 }
843 839
844 disasm__add(&notes->src->source, dl); 840 disasm__add(&notes->src->source, dl);
@@ -879,6 +875,8 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize)
879 FILE *file; 875 FILE *file;
880 int err = 0; 876 int err = 0;
881 char symfs_filename[PATH_MAX]; 877 char symfs_filename[PATH_MAX];
878 struct kcore_extract kce;
879 bool delete_extract = false;
882 880
883 if (filename) { 881 if (filename) {
884 snprintf(symfs_filename, sizeof(symfs_filename), "%s%s", 882 snprintf(symfs_filename, sizeof(symfs_filename), "%s%s",
@@ -940,6 +938,23 @@ fallback:
940 pr_debug("annotating [%p] %30s : [%p] %30s\n", 938 pr_debug("annotating [%p] %30s : [%p] %30s\n",
941 dso, dso->long_name, sym, sym->name); 939 dso, dso->long_name, sym, sym->name);
942 940
941 if (dso__is_kcore(dso)) {
942 kce.kcore_filename = symfs_filename;
943 kce.addr = map__rip_2objdump(map, sym->start);
944 kce.offs = sym->start;
945 kce.len = sym->end + 1 - sym->start;
946 if (!kcore_extract__create(&kce)) {
947 delete_extract = true;
948 strlcpy(symfs_filename, kce.extract_filename,
949 sizeof(symfs_filename));
950 if (free_filename) {
951 free(filename);
952 free_filename = false;
953 }
954 filename = symfs_filename;
955 }
956 }
957
943 snprintf(command, sizeof(command), 958 snprintf(command, sizeof(command),
944 "%s %s%s --start-address=0x%016" PRIx64 959 "%s %s%s --start-address=0x%016" PRIx64
945 " --stop-address=0x%016" PRIx64 960 " --stop-address=0x%016" PRIx64
@@ -972,6 +987,8 @@ fallback:
972 987
973 pclose(file); 988 pclose(file);
974out_free_filename: 989out_free_filename:
990 if (delete_extract)
991 kcore_extract__delete(&kce);
975 if (free_filename) 992 if (free_filename)
976 free(filename); 993 free(filename);
977 return err; 994 return err;
@@ -1070,7 +1087,7 @@ static void symbol__free_source_line(struct symbol *sym, int len)
1070 (sizeof(src_line->p) * (src_line->nr_pcnt - 1)); 1087 (sizeof(src_line->p) * (src_line->nr_pcnt - 1));
1071 1088
1072 for (i = 0; i < len; i++) { 1089 for (i = 0; i < len; i++) {
1073 free(src_line->path); 1090 free_srcline(src_line->path);
1074 src_line = (void *)src_line + sizeof_src_line; 1091 src_line = (void *)src_line + sizeof_src_line;
1075 } 1092 }
1076 1093
@@ -1081,13 +1098,11 @@ static void symbol__free_source_line(struct symbol *sym, int len)
1081/* Get the filename:line for the colored entries */ 1098/* Get the filename:line for the colored entries */
1082static int symbol__get_source_line(struct symbol *sym, struct map *map, 1099static int symbol__get_source_line(struct symbol *sym, struct map *map,
1083 struct perf_evsel *evsel, 1100 struct perf_evsel *evsel,
1084 struct rb_root *root, int len, 1101 struct rb_root *root, int len)
1085 const char *filename)
1086{ 1102{
1087 u64 start; 1103 u64 start;
1088 int i, k; 1104 int i, k;
1089 int evidx = evsel->idx; 1105 int evidx = evsel->idx;
1090 char cmd[PATH_MAX * 2];
1091 struct source_line *src_line; 1106 struct source_line *src_line;
1092 struct annotation *notes = symbol__annotation(sym); 1107 struct annotation *notes = symbol__annotation(sym);
1093 struct sym_hist *h = annotation__histogram(notes, evidx); 1108 struct sym_hist *h = annotation__histogram(notes, evidx);
@@ -1115,10 +1130,7 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
1115 start = map__rip_2objdump(map, sym->start); 1130 start = map__rip_2objdump(map, sym->start);
1116 1131
1117 for (i = 0; i < len; i++) { 1132 for (i = 0; i < len; i++) {
1118 char *path = NULL;
1119 size_t line_len;
1120 u64 offset; 1133 u64 offset;
1121 FILE *fp;
1122 double percent_max = 0.0; 1134 double percent_max = 0.0;
1123 1135
1124 src_line->nr_pcnt = nr_pcnt; 1136 src_line->nr_pcnt = nr_pcnt;
@@ -1135,23 +1147,9 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
1135 goto next; 1147 goto next;
1136 1148
1137 offset = start + i; 1149 offset = start + i;
1138 sprintf(cmd, "addr2line -e %s %016" PRIx64, filename, offset); 1150 src_line->path = get_srcline(map->dso, offset);
1139 fp = popen(cmd, "r");
1140 if (!fp)
1141 goto next;
1142
1143 if (getline(&path, &line_len, fp) < 0 || !line_len)
1144 goto next_close;
1145
1146 src_line->path = malloc(sizeof(char) * line_len + 1);
1147 if (!src_line->path)
1148 goto next_close;
1149
1150 strcpy(src_line->path, path);
1151 insert_source_line(&tmp_root, src_line); 1151 insert_source_line(&tmp_root, src_line);
1152 1152
1153 next_close:
1154 pclose(fp);
1155 next: 1153 next:
1156 src_line = (void *)src_line + sizeof_src_line; 1154 src_line = (void *)src_line + sizeof_src_line;
1157 } 1155 }
@@ -1192,7 +1190,7 @@ static void print_summary(struct rb_root *root, const char *filename)
1192 1190
1193 path = src_line->path; 1191 path = src_line->path;
1194 color = get_percent_color(percent_max); 1192 color = get_percent_color(percent_max);
1195 color_fprintf(stdout, color, " %s", path); 1193 color_fprintf(stdout, color, " %s\n", path);
1196 1194
1197 node = rb_next(node); 1195 node = rb_next(node);
1198 } 1196 }
@@ -1356,7 +1354,6 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map,
1356 bool full_paths, int min_pcnt, int max_lines) 1354 bool full_paths, int min_pcnt, int max_lines)
1357{ 1355{
1358 struct dso *dso = map->dso; 1356 struct dso *dso = map->dso;
1359 const char *filename = dso->long_name;
1360 struct rb_root source_line = RB_ROOT; 1357 struct rb_root source_line = RB_ROOT;
1361 u64 len; 1358 u64 len;
1362 1359
@@ -1366,9 +1363,8 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map,
1366 len = symbol__size(sym); 1363 len = symbol__size(sym);
1367 1364
1368 if (print_lines) { 1365 if (print_lines) {
1369 symbol__get_source_line(sym, map, evsel, &source_line, 1366 symbol__get_source_line(sym, map, evsel, &source_line, len);
1370 len, filename); 1367 print_summary(&source_line, dso->long_name);
1371 print_summary(&source_line, filename);
1372 } 1368 }
1373 1369
1374 symbol__annotate_printf(sym, map, evsel, full_paths, 1370 symbol__annotate_printf(sym, map, evsel, full_paths,
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index af755156d278..834b7b57b788 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -150,7 +150,7 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map,
150 struct perf_evsel *evsel, bool print_lines, 150 struct perf_evsel *evsel, bool print_lines,
151 bool full_paths, int min_pcnt, int max_lines); 151 bool full_paths, int min_pcnt, int max_lines);
152 152
153#ifdef SLANG_SUPPORT 153#ifdef HAVE_SLANG_SUPPORT
154int symbol__tui_annotate(struct symbol *sym, struct map *map, 154int symbol__tui_annotate(struct symbol *sym, struct map *map,
155 struct perf_evsel *evsel, 155 struct perf_evsel *evsel,
156 struct hist_browser_timer *hbt); 156 struct hist_browser_timer *hbt);
@@ -165,30 +165,6 @@ static inline int symbol__tui_annotate(struct symbol *sym __maybe_unused,
165} 165}
166#endif 166#endif
167 167
168#ifdef GTK2_SUPPORT
169int symbol__gtk_annotate(struct symbol *sym, struct map *map,
170 struct perf_evsel *evsel,
171 struct hist_browser_timer *hbt);
172
173static inline int hist_entry__gtk_annotate(struct hist_entry *he,
174 struct perf_evsel *evsel,
175 struct hist_browser_timer *hbt)
176{
177 return symbol__gtk_annotate(he->ms.sym, he->ms.map, evsel, hbt);
178}
179
180void perf_gtk__show_annotations(void);
181#else
182static inline int hist_entry__gtk_annotate(struct hist_entry *he __maybe_unused,
183 struct perf_evsel *evsel __maybe_unused,
184 struct hist_browser_timer *hbt __maybe_unused)
185{
186 return 0;
187}
188
189static inline void perf_gtk__show_annotations(void) {}
190#endif
191
192extern const char *disassembler_style; 168extern const char *disassembler_style;
193 169
194#endif /* __PERF_ANNOTATE_H */ 170#endif /* __PERF_ANNOTATE_H */
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index 26e367239873..7b176dd02e1a 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -70,8 +70,7 @@ extern char *perf_path(const char *fmt, ...) __attribute__((format (printf, 1, 2
70extern char *perf_pathdup(const char *fmt, ...) 70extern char *perf_pathdup(const char *fmt, ...)
71 __attribute__((format (printf, 1, 2))); 71 __attribute__((format (printf, 1, 2)));
72 72
73#ifndef HAVE_STRLCPY 73/* Matches the libc/libbsd function attribute so we declare this unconditionally: */
74extern size_t strlcpy(char *dest, const char *src, size_t size); 74extern size_t strlcpy(char *dest, const char *src, size_t size);
75#endif
76 75
77#endif /* __PERF_CACHE_H */ 76#endif /* __PERF_CACHE_H */
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index e3c1ff8512c8..af4c687cc49b 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -7,19 +7,20 @@
7char dso__symtab_origin(const struct dso *dso) 7char dso__symtab_origin(const struct dso *dso)
8{ 8{
9 static const char origin[] = { 9 static const char origin[] = {
10 [DSO_BINARY_TYPE__KALLSYMS] = 'k', 10 [DSO_BINARY_TYPE__KALLSYMS] = 'k',
11 [DSO_BINARY_TYPE__VMLINUX] = 'v', 11 [DSO_BINARY_TYPE__VMLINUX] = 'v',
12 [DSO_BINARY_TYPE__JAVA_JIT] = 'j', 12 [DSO_BINARY_TYPE__JAVA_JIT] = 'j',
13 [DSO_BINARY_TYPE__DEBUGLINK] = 'l', 13 [DSO_BINARY_TYPE__DEBUGLINK] = 'l',
14 [DSO_BINARY_TYPE__BUILD_ID_CACHE] = 'B', 14 [DSO_BINARY_TYPE__BUILD_ID_CACHE] = 'B',
15 [DSO_BINARY_TYPE__FEDORA_DEBUGINFO] = 'f', 15 [DSO_BINARY_TYPE__FEDORA_DEBUGINFO] = 'f',
16 [DSO_BINARY_TYPE__UBUNTU_DEBUGINFO] = 'u', 16 [DSO_BINARY_TYPE__UBUNTU_DEBUGINFO] = 'u',
17 [DSO_BINARY_TYPE__BUILDID_DEBUGINFO] = 'b', 17 [DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO] = 'o',
18 [DSO_BINARY_TYPE__SYSTEM_PATH_DSO] = 'd', 18 [DSO_BINARY_TYPE__BUILDID_DEBUGINFO] = 'b',
19 [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE] = 'K', 19 [DSO_BINARY_TYPE__SYSTEM_PATH_DSO] = 'd',
20 [DSO_BINARY_TYPE__GUEST_KALLSYMS] = 'g', 20 [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE] = 'K',
21 [DSO_BINARY_TYPE__GUEST_KMODULE] = 'G', 21 [DSO_BINARY_TYPE__GUEST_KALLSYMS] = 'g',
22 [DSO_BINARY_TYPE__GUEST_VMLINUX] = 'V', 22 [DSO_BINARY_TYPE__GUEST_KMODULE] = 'G',
23 [DSO_BINARY_TYPE__GUEST_VMLINUX] = 'V',
23 }; 24 };
24 25
25 if (dso == NULL || dso->symtab_type == DSO_BINARY_TYPE__NOT_FOUND) 26 if (dso == NULL || dso->symtab_type == DSO_BINARY_TYPE__NOT_FOUND)
@@ -64,6 +65,28 @@ int dso__binary_type_file(struct dso *dso, enum dso_binary_type type,
64 symbol_conf.symfs, dso->long_name); 65 symbol_conf.symfs, dso->long_name);
65 break; 66 break;
66 67
68 case DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO:
69 {
70 char *last_slash;
71 size_t len;
72 size_t dir_size;
73
74 last_slash = dso->long_name + dso->long_name_len;
75 while (last_slash != dso->long_name && *last_slash != '/')
76 last_slash--;
77
78 len = scnprintf(file, size, "%s", symbol_conf.symfs);
79 dir_size = last_slash - dso->long_name + 2;
80 if (dir_size > (size - len)) {
81 ret = -1;
82 break;
83 }
84 len += scnprintf(file + len, dir_size, "%s", dso->long_name);
85 len += scnprintf(file + len , size - len, ".debug%s",
86 last_slash);
87 break;
88 }
89
67 case DSO_BINARY_TYPE__BUILDID_DEBUGINFO: 90 case DSO_BINARY_TYPE__BUILDID_DEBUGINFO:
68 if (!dso->has_build_id) { 91 if (!dso->has_build_id) {
69 ret = -1; 92 ret = -1;
@@ -427,6 +450,7 @@ struct dso *dso__new(const char *name)
427 dso->rel = 0; 450 dso->rel = 0;
428 dso->sorted_by_name = 0; 451 dso->sorted_by_name = 0;
429 dso->has_build_id = 0; 452 dso->has_build_id = 0;
453 dso->has_srcline = 1;
430 dso->kernel = DSO_TYPE_USER; 454 dso->kernel = DSO_TYPE_USER;
431 dso->needs_swap = DSO_SWAP__UNSET; 455 dso->needs_swap = DSO_SWAP__UNSET;
432 INIT_LIST_HEAD(&dso->node); 456 INIT_LIST_HEAD(&dso->node);
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index b793053335d6..9ac666abbe7e 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -6,6 +6,7 @@
6#include <stdbool.h> 6#include <stdbool.h>
7#include "types.h" 7#include "types.h"
8#include "map.h" 8#include "map.h"
9#include "build-id.h"
9 10
10enum dso_binary_type { 11enum dso_binary_type {
11 DSO_BINARY_TYPE__KALLSYMS = 0, 12 DSO_BINARY_TYPE__KALLSYMS = 0,
@@ -23,6 +24,7 @@ enum dso_binary_type {
23 DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE, 24 DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE,
24 DSO_BINARY_TYPE__KCORE, 25 DSO_BINARY_TYPE__KCORE,
25 DSO_BINARY_TYPE__GUEST_KCORE, 26 DSO_BINARY_TYPE__GUEST_KCORE,
27 DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,
26 DSO_BINARY_TYPE__NOT_FOUND, 28 DSO_BINARY_TYPE__NOT_FOUND,
27}; 29};
28 30
@@ -81,6 +83,7 @@ struct dso {
81 enum dso_binary_type data_type; 83 enum dso_binary_type data_type;
82 u8 adjust_symbols:1; 84 u8 adjust_symbols:1;
83 u8 has_build_id:1; 85 u8 has_build_id:1;
86 u8 has_srcline:1;
84 u8 hit:1; 87 u8 hit:1;
85 u8 annotate_warned:1; 88 u8 annotate_warned:1;
86 u8 sname_alloc:1; 89 u8 sname_alloc:1;
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 17d9e167a7b9..752709ccfb00 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -61,6 +61,12 @@ struct read_event {
61 u64 id; 61 u64 id;
62}; 62};
63 63
64struct throttle_event {
65 struct perf_event_header header;
66 u64 time;
67 u64 id;
68 u64 stream_id;
69};
64 70
65#define PERF_SAMPLE_MASK \ 71#define PERF_SAMPLE_MASK \
66 (PERF_SAMPLE_IP | PERF_SAMPLE_TID | \ 72 (PERF_SAMPLE_IP | PERF_SAMPLE_TID | \
@@ -69,6 +75,9 @@ struct read_event {
69 PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD | \ 75 PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD | \
70 PERF_SAMPLE_IDENTIFIER) 76 PERF_SAMPLE_IDENTIFIER)
71 77
78/* perf sample has 16 bits size limit */
79#define PERF_SAMPLE_MAX_SIZE (1 << 16)
80
72struct sample_event { 81struct sample_event {
73 struct perf_event_header header; 82 struct perf_event_header header;
74 u64 array[]; 83 u64 array[];
@@ -178,6 +187,7 @@ union perf_event {
178 struct fork_event fork; 187 struct fork_event fork;
179 struct lost_event lost; 188 struct lost_event lost;
180 struct read_event read; 189 struct read_event read;
190 struct throttle_event throttle;
181 struct sample_event sample; 191 struct sample_event sample;
182 struct attr_event attr; 192 struct attr_event attr;
183 struct event_type_event event_type; 193 struct event_type_event event_type;
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index f9f77bee0b1b..cb9523f50a37 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -18,6 +18,7 @@
18#include <unistd.h> 18#include <unistd.h>
19 19
20#include "parse-events.h" 20#include "parse-events.h"
21#include "parse-options.h"
21 22
22#include <sys/mman.h> 23#include <sys/mman.h>
23 24
@@ -49,6 +50,18 @@ struct perf_evlist *perf_evlist__new(void)
49 return evlist; 50 return evlist;
50} 51}
51 52
53struct perf_evlist *perf_evlist__new_default(void)
54{
55 struct perf_evlist *evlist = perf_evlist__new();
56
57 if (evlist && perf_evlist__add_default(evlist)) {
58 perf_evlist__delete(evlist);
59 evlist = NULL;
60 }
61
62 return evlist;
63}
64
52/** 65/**
53 * perf_evlist__set_id_pos - set the positions of event ids. 66 * perf_evlist__set_id_pos - set the positions of event ids.
54 * @evlist: selected event list 67 * @evlist: selected event list
@@ -527,7 +540,7 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
527 if ((old & md->mask) + size != ((old + size) & md->mask)) { 540 if ((old & md->mask) + size != ((old + size) & md->mask)) {
528 unsigned int offset = old; 541 unsigned int offset = old;
529 unsigned int len = min(sizeof(*event), size), cpy; 542 unsigned int len = min(sizeof(*event), size), cpy;
530 void *dst = &md->event_copy; 543 void *dst = md->event_copy;
531 544
532 do { 545 do {
533 cpy = min(md->mask + 1 - (offset & md->mask), len); 546 cpy = min(md->mask + 1 - (offset & md->mask), len);
@@ -537,7 +550,7 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
537 len -= cpy; 550 len -= cpy;
538 } while (len); 551 } while (len);
539 552
540 event = &md->event_copy; 553 event = (union perf_event *) md->event_copy;
541 } 554 }
542 555
543 old += size; 556 old += size;
@@ -672,6 +685,59 @@ out_unmap:
672 return -1; 685 return -1;
673} 686}
674 687
688static size_t perf_evlist__mmap_size(unsigned long pages)
689{
690 /* 512 kiB: default amount of unprivileged mlocked memory */
691 if (pages == UINT_MAX)
692 pages = (512 * 1024) / page_size;
693 else if (!is_power_of_2(pages))
694 return 0;
695
696 return (pages + 1) * page_size;
697}
698
699int perf_evlist__parse_mmap_pages(const struct option *opt, const char *str,
700 int unset __maybe_unused)
701{
702 unsigned int pages, val, *mmap_pages = opt->value;
703 size_t size;
704 static struct parse_tag tags[] = {
705 { .tag = 'B', .mult = 1 },
706 { .tag = 'K', .mult = 1 << 10 },
707 { .tag = 'M', .mult = 1 << 20 },
708 { .tag = 'G', .mult = 1 << 30 },
709 { .tag = 0 },
710 };
711
712 val = parse_tag_value(str, tags);
713 if (val != (unsigned int) -1) {
714 /* we got file size value */
715 pages = PERF_ALIGN(val, page_size) / page_size;
716 if (!is_power_of_2(pages)) {
717 pages = next_pow2(pages);
718 pr_info("rounding mmap pages size to %u (%u pages)\n",
719 pages * page_size, pages);
720 }
721 } else {
722 /* we got pages count value */
723 char *eptr;
724 pages = strtoul(str, &eptr, 10);
725 if (*eptr != '\0') {
726 pr_err("failed to parse --mmap_pages/-m value\n");
727 return -1;
728 }
729 }
730
731 size = perf_evlist__mmap_size(pages);
732 if (!size) {
733 pr_err("--mmap_pages/-m value must be a power of two.");
734 return -1;
735 }
736
737 *mmap_pages = pages;
738 return 0;
739}
740
675/** perf_evlist__mmap - Create per cpu maps to receive events 741/** perf_evlist__mmap - Create per cpu maps to receive events
676 * 742 *
677 * @evlist - list of events 743 * @evlist - list of events
@@ -695,14 +761,6 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
695 const struct thread_map *threads = evlist->threads; 761 const struct thread_map *threads = evlist->threads;
696 int prot = PROT_READ | (overwrite ? 0 : PROT_WRITE), mask; 762 int prot = PROT_READ | (overwrite ? 0 : PROT_WRITE), mask;
697 763
698 /* 512 kiB: default amount of unprivileged mlocked memory */
699 if (pages == UINT_MAX)
700 pages = (512 * 1024) / page_size;
701 else if (!is_power_of_2(pages))
702 return -EINVAL;
703
704 mask = pages * page_size - 1;
705
706 if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0) 764 if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0)
707 return -ENOMEM; 765 return -ENOMEM;
708 766
@@ -710,7 +768,9 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
710 return -ENOMEM; 768 return -ENOMEM;
711 769
712 evlist->overwrite = overwrite; 770 evlist->overwrite = overwrite;
713 evlist->mmap_len = (pages + 1) * page_size; 771 evlist->mmap_len = perf_evlist__mmap_size(pages);
772 pr_debug("mmap size %luB\n", evlist->mmap_len);
773 mask = evlist->mmap_len - page_size - 1;
714 774
715 list_for_each_entry(evsel, &evlist->entries, node) { 775 list_for_each_entry(evsel, &evlist->entries, node) {
716 if ((evsel->attr.read_format & PERF_FORMAT_ID) && 776 if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 880d7139d2fb..722618f84c53 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -21,7 +21,7 @@ struct perf_mmap {
21 void *base; 21 void *base;
22 int mask; 22 int mask;
23 unsigned int prev; 23 unsigned int prev;
24 union perf_event event_copy; 24 char event_copy[PERF_SAMPLE_MAX_SIZE];
25}; 25};
26 26
27struct perf_evlist { 27struct perf_evlist {
@@ -31,7 +31,7 @@ struct perf_evlist {
31 int nr_groups; 31 int nr_groups;
32 int nr_fds; 32 int nr_fds;
33 int nr_mmaps; 33 int nr_mmaps;
34 int mmap_len; 34 size_t mmap_len;
35 int id_pos; 35 int id_pos;
36 int is_pos; 36 int is_pos;
37 u64 combined_sample_type; 37 u64 combined_sample_type;
@@ -53,6 +53,7 @@ struct perf_evsel_str_handler {
53}; 53};
54 54
55struct perf_evlist *perf_evlist__new(void); 55struct perf_evlist *perf_evlist__new(void);
56struct perf_evlist *perf_evlist__new_default(void);
56void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus, 57void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus,
57 struct thread_map *threads); 58 struct thread_map *threads);
58void perf_evlist__exit(struct perf_evlist *evlist); 59void perf_evlist__exit(struct perf_evlist *evlist);
@@ -103,6 +104,10 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist,
103 bool want_signal); 104 bool want_signal);
104int perf_evlist__start_workload(struct perf_evlist *evlist); 105int perf_evlist__start_workload(struct perf_evlist *evlist);
105 106
107int perf_evlist__parse_mmap_pages(const struct option *opt,
108 const char *str,
109 int unset);
110
106int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages, 111int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
107 bool overwrite); 112 bool overwrite);
108void perf_evlist__munmap(struct perf_evlist *evlist); 113void perf_evlist__munmap(struct perf_evlist *evlist);
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index abe69af58b62..bfebc1ea3c51 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -1456,6 +1456,9 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
1456 array = (void *)array + sz; 1456 array = (void *)array + sz;
1457 OVERFLOW_CHECK_u64(array); 1457 OVERFLOW_CHECK_u64(array);
1458 data->user_stack.size = *array++; 1458 data->user_stack.size = *array++;
1459 if (WARN_ONCE(data->user_stack.size > sz,
1460 "user stack dump failure\n"))
1461 return -EFAULT;
1459 } 1462 }
1460 } 1463 }
1461 1464
diff --git a/tools/perf/util/generate-cmdlist.sh b/tools/perf/util/generate-cmdlist.sh
index 3ac38031d534..36a885d2cd22 100755
--- a/tools/perf/util/generate-cmdlist.sh
+++ b/tools/perf/util/generate-cmdlist.sh
@@ -22,7 +22,7 @@ do
22 }' "Documentation/perf-$cmd.txt" 22 }' "Documentation/perf-$cmd.txt"
23done 23done
24 24
25echo "#ifdef LIBELF_SUPPORT" 25echo "#ifdef HAVE_LIBELF_SUPPORT"
26sed -n -e 's/^perf-\([^ ]*\)[ ].* full.*/\1/p' command-list.txt | 26sed -n -e 's/^perf-\([^ ]*\)[ ].* full.*/\1/p' command-list.txt |
27sort | 27sort |
28while read cmd 28while read cmd
@@ -35,5 +35,5 @@ do
35 p 35 p
36 }' "Documentation/perf-$cmd.txt" 36 }' "Documentation/perf-$cmd.txt"
37done 37done
38echo "#endif /* LIBELF_SUPPORT */" 38echo "#endif /* HAVE_LIBELF_SUPPORT */"
39echo "};" 39echo "};"
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index f3278a388e9a..cca03831f41a 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -535,6 +535,7 @@ void hist_entry__free(struct hist_entry *he)
535{ 535{
536 free(he->branch_info); 536 free(he->branch_info);
537 free(he->mem_info); 537 free(he->mem_info);
538 free_srcline(he->srcline);
538 free(he); 539 free(he);
539} 540}
540 541
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 6a048c09cd64..20b175808cd3 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -187,7 +187,7 @@ struct hist_browser_timer {
187 int refresh; 187 int refresh;
188}; 188};
189 189
190#ifdef SLANG_SUPPORT 190#ifdef HAVE_SLANG_SUPPORT
191#include "../ui/keysyms.h" 191#include "../ui/keysyms.h"
192int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel, 192int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel,
193 struct hist_browser_timer *hbt); 193 struct hist_browser_timer *hbt);
@@ -228,20 +228,5 @@ static inline int script_browse(const char *script_opt __maybe_unused)
228#define K_SWITCH_INPUT_DATA -3000 228#define K_SWITCH_INPUT_DATA -3000
229#endif 229#endif
230 230
231#ifdef GTK2_SUPPORT
232int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, const char *help,
233 struct hist_browser_timer *hbt __maybe_unused,
234 float min_pcnt);
235#else
236static inline
237int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist __maybe_unused,
238 const char *help __maybe_unused,
239 struct hist_browser_timer *hbt __maybe_unused,
240 float min_pcnt __maybe_unused)
241{
242 return 0;
243}
244#endif
245
246unsigned int hists__sort_list_width(struct hists *self); 231unsigned int hists__sort_list_width(struct hists *self);
247#endif /* __PERF_HIST_H */ 232#endif /* __PERF_HIST_H */
diff --git a/tools/perf/util/include/dwarf-regs.h b/tools/perf/util/include/dwarf-regs.h
index cf6727e99c44..8f149655f497 100644
--- a/tools/perf/util/include/dwarf-regs.h
+++ b/tools/perf/util/include/dwarf-regs.h
@@ -1,7 +1,7 @@
1#ifndef _PERF_DWARF_REGS_H_ 1#ifndef _PERF_DWARF_REGS_H_
2#define _PERF_DWARF_REGS_H_ 2#define _PERF_DWARF_REGS_H_
3 3
4#ifdef DWARF_SUPPORT 4#ifdef HAVE_DWARF_SUPPORT
5const char *get_arch_regstr(unsigned int n); 5const char *get_arch_regstr(unsigned int n);
6#endif 6#endif
7 7
diff --git a/tools/perf/util/include/linux/compiler.h b/tools/perf/util/include/linux/compiler.h
index 96b919dae11c..b003ad7200b2 100644
--- a/tools/perf/util/include/linux/compiler.h
+++ b/tools/perf/util/include/linux/compiler.h
@@ -2,20 +2,29 @@
2#define _PERF_LINUX_COMPILER_H_ 2#define _PERF_LINUX_COMPILER_H_
3 3
4#ifndef __always_inline 4#ifndef __always_inline
5#define __always_inline inline 5# define __always_inline inline __attribute__((always_inline))
6#endif 6#endif
7
7#define __user 8#define __user
9
8#ifndef __attribute_const__ 10#ifndef __attribute_const__
9#define __attribute_const__ 11# define __attribute_const__
10#endif 12#endif
11 13
12#ifndef __maybe_unused 14#ifndef __maybe_unused
13#define __maybe_unused __attribute__((unused)) 15# define __maybe_unused __attribute__((unused))
16#endif
17
18#ifndef __packed
19# define __packed __attribute__((__packed__))
14#endif 20#endif
15#define __packed __attribute__((__packed__))
16 21
17#ifndef __force 22#ifndef __force
18#define __force 23# define __force
24#endif
25
26#ifndef __weak
27# define __weak __attribute__((weak))
19#endif 28#endif
20 29
21#endif 30#endif
diff --git a/tools/perf/util/intlist.c b/tools/perf/util/intlist.c
index 11a8d86f7fea..89715b64a315 100644
--- a/tools/perf/util/intlist.c
+++ b/tools/perf/util/intlist.c
@@ -20,6 +20,7 @@ static struct rb_node *intlist__node_new(struct rblist *rblist __maybe_unused,
20 20
21 if (node != NULL) { 21 if (node != NULL) {
22 node->i = i; 22 node->i = i;
23 node->priv = NULL;
23 rc = &node->rb_node; 24 rc = &node->rb_node;
24 } 25 }
25 26
@@ -57,22 +58,36 @@ void intlist__remove(struct intlist *ilist, struct int_node *node)
57 rblist__remove_node(&ilist->rblist, &node->rb_node); 58 rblist__remove_node(&ilist->rblist, &node->rb_node);
58} 59}
59 60
60struct int_node *intlist__find(struct intlist *ilist, int i) 61static struct int_node *__intlist__findnew(struct intlist *ilist,
62 int i, bool create)
61{ 63{
62 struct int_node *node; 64 struct int_node *node = NULL;
63 struct rb_node *rb_node; 65 struct rb_node *rb_node;
64 66
65 if (ilist == NULL) 67 if (ilist == NULL)
66 return NULL; 68 return NULL;
67 69
68 node = NULL; 70 if (create)
69 rb_node = rblist__find(&ilist->rblist, (void *)((long)i)); 71 rb_node = rblist__findnew(&ilist->rblist, (void *)((long)i));
72 else
73 rb_node = rblist__find(&ilist->rblist, (void *)((long)i));
74
70 if (rb_node) 75 if (rb_node)
71 node = container_of(rb_node, struct int_node, rb_node); 76 node = container_of(rb_node, struct int_node, rb_node);
72 77
73 return node; 78 return node;
74} 79}
75 80
81struct int_node *intlist__find(struct intlist *ilist, int i)
82{
83 return __intlist__findnew(ilist, i, false);
84}
85
86struct int_node *intlist__findnew(struct intlist *ilist, int i)
87{
88 return __intlist__findnew(ilist, i, true);
89}
90
76static int intlist__parse_list(struct intlist *ilist, const char *s) 91static int intlist__parse_list(struct intlist *ilist, const char *s)
77{ 92{
78 char *sep; 93 char *sep;
diff --git a/tools/perf/util/intlist.h b/tools/perf/util/intlist.h
index 62351dad848f..aa6877d36858 100644
--- a/tools/perf/util/intlist.h
+++ b/tools/perf/util/intlist.h
@@ -9,6 +9,7 @@
9struct int_node { 9struct int_node {
10 struct rb_node rb_node; 10 struct rb_node rb_node;
11 int i; 11 int i;
12 void *priv;
12}; 13};
13 14
14struct intlist { 15struct intlist {
@@ -23,6 +24,7 @@ int intlist__add(struct intlist *ilist, int i);
23 24
24struct int_node *intlist__entry(const struct intlist *ilist, unsigned int idx); 25struct int_node *intlist__entry(const struct intlist *ilist, unsigned int idx);
25struct int_node *intlist__find(struct intlist *ilist, int i); 26struct int_node *intlist__find(struct intlist *ilist, int i);
27struct int_node *intlist__findnew(struct intlist *ilist, int i);
26 28
27static inline bool intlist__has_entry(struct intlist *ilist, int i) 29static inline bool intlist__has_entry(struct intlist *ilist, int i)
28{ 30{
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 6188d2876a71..6b861aefd99a 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -46,6 +46,23 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
46 return 0; 46 return 0;
47} 47}
48 48
49struct machine *machine__new_host(void)
50{
51 struct machine *machine = malloc(sizeof(*machine));
52
53 if (machine != NULL) {
54 machine__init(machine, "", HOST_KERNEL_ID);
55
56 if (machine__create_kernel_maps(machine) < 0)
57 goto out_delete;
58 }
59
60 return machine;
61out_delete:
62 free(machine);
63 return NULL;
64}
65
49static void dsos__delete(struct list_head *dsos) 66static void dsos__delete(struct list_head *dsos)
50{ 67{
51 struct dso *pos, *n; 68 struct dso *pos, *n;
@@ -776,75 +793,44 @@ static int machine__set_modules_path(struct machine *machine)
776 return map_groups__set_modules_path_dir(&machine->kmaps, modules_path); 793 return map_groups__set_modules_path_dir(&machine->kmaps, modules_path);
777} 794}
778 795
779static int machine__create_modules(struct machine *machine) 796static int machine__create_module(void *arg, const char *name, u64 start)
780{ 797{
781 char *line = NULL; 798 struct machine *machine = arg;
782 size_t n;
783 FILE *file;
784 struct map *map; 799 struct map *map;
800
801 map = machine__new_module(machine, start, name);
802 if (map == NULL)
803 return -1;
804
805 dso__kernel_module_get_build_id(map->dso, machine->root_dir);
806
807 return 0;
808}
809
810static int machine__create_modules(struct machine *machine)
811{
785 const char *modules; 812 const char *modules;
786 char path[PATH_MAX]; 813 char path[PATH_MAX];
787 814
788 if (machine__is_default_guest(machine)) 815 if (machine__is_default_guest(machine)) {
789 modules = symbol_conf.default_guest_modules; 816 modules = symbol_conf.default_guest_modules;
790 else { 817 } else {
791 sprintf(path, "%s/proc/modules", machine->root_dir); 818 snprintf(path, PATH_MAX, "%s/proc/modules", machine->root_dir);
792 modules = path; 819 modules = path;
793 } 820 }
794 821
795 if (symbol__restricted_filename(modules, "/proc/modules")) 822 if (symbol__restricted_filename(modules, "/proc/modules"))
796 return -1; 823 return -1;
797 824
798 file = fopen(modules, "r"); 825 if (modules__parse(modules, machine, machine__create_module))
799 if (file == NULL)
800 return -1; 826 return -1;
801 827
802 while (!feof(file)) { 828 if (!machine__set_modules_path(machine))
803 char name[PATH_MAX]; 829 return 0;
804 u64 start;
805 char *sep;
806 int line_len;
807
808 line_len = getline(&line, &n, file);
809 if (line_len < 0)
810 break;
811
812 if (!line)
813 goto out_failure;
814
815 line[--line_len] = '\0'; /* \n */
816
817 sep = strrchr(line, 'x');
818 if (sep == NULL)
819 continue;
820
821 hex2u64(sep + 1, &start);
822
823 sep = strchr(line, ' ');
824 if (sep == NULL)
825 continue;
826
827 *sep = '\0';
828
829 snprintf(name, sizeof(name), "[%s]", line);
830 map = machine__new_module(machine, start, name);
831 if (map == NULL)
832 goto out_delete_line;
833 dso__kernel_module_get_build_id(map->dso, machine->root_dir);
834 }
835 830
836 free(line); 831 pr_debug("Problems setting modules path maps, continuing anyway...\n");
837 fclose(file);
838 832
839 if (machine__set_modules_path(machine) < 0) {
840 pr_debug("Problems setting modules path maps, continuing anyway...\n");
841 }
842 return 0; 833 return 0;
843
844out_delete_line:
845 free(line);
846out_failure:
847 return -1;
848} 834}
849 835
850int machine__create_kernel_maps(struct machine *machine) 836int machine__create_kernel_maps(struct machine *machine)
@@ -1376,3 +1362,26 @@ int machine__resolve_callchain(struct machine *machine,
1376 sample); 1362 sample);
1377 1363
1378} 1364}
1365
1366int machine__for_each_thread(struct machine *machine,
1367 int (*fn)(struct thread *thread, void *p),
1368 void *priv)
1369{
1370 struct rb_node *nd;
1371 struct thread *thread;
1372 int rc = 0;
1373
1374 for (nd = rb_first(&machine->threads); nd; nd = rb_next(nd)) {
1375 thread = rb_entry(nd, struct thread, rb_node);
1376 rc = fn(thread, priv);
1377 if (rc != 0)
1378 return rc;
1379 }
1380
1381 list_for_each_entry(thread, &machine->dead_threads, node) {
1382 rc = fn(thread, priv);
1383 if (rc != 0)
1384 return rc;
1385 }
1386 return rc;
1387}
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index 58a6be1fc739..d44c09bdc45e 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -74,6 +74,7 @@ char *machine__mmap_name(struct machine *machine, char *bf, size_t size);
74void machines__set_symbol_filter(struct machines *machines, 74void machines__set_symbol_filter(struct machines *machines,
75 symbol_filter_t symbol_filter); 75 symbol_filter_t symbol_filter);
76 76
77struct machine *machine__new_host(void);
77int machine__init(struct machine *machine, const char *root_dir, pid_t pid); 78int machine__init(struct machine *machine, const char *root_dir, pid_t pid);
78void machine__exit(struct machine *machine); 79void machine__exit(struct machine *machine);
79void machine__delete_dead_threads(struct machine *machine); 80void machine__delete_dead_threads(struct machine *machine);
@@ -165,4 +166,8 @@ void machines__destroy_kernel_maps(struct machines *machines);
165 166
166size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp); 167size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp);
167 168
169int machine__for_each_thread(struct machine *machine,
170 int (*fn)(struct thread *thread, void *p),
171 void *priv);
172
168#endif /* __PERF_MACHINE_H */ 173#endif /* __PERF_MACHINE_H */
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 4f6680d2043b..ef5bc913ca7a 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -172,7 +172,7 @@ int map__load(struct map *map, symbol_filter_t filter)
172 pr_warning(", continuing without symbols\n"); 172 pr_warning(", continuing without symbols\n");
173 return -1; 173 return -1;
174 } else if (nr == 0) { 174 } else if (nr == 0) {
175#ifdef LIBELF_SUPPORT 175#ifdef HAVE_LIBELF_SUPPORT
176 const size_t len = strlen(name); 176 const size_t len = strlen(name);
177 const size_t real_len = len - sizeof(DSO__DELETED); 177 const size_t real_len = len - sizeof(DSO__DELETED);
178 178
@@ -252,10 +252,16 @@ size_t map__fprintf_dsoname(struct map *map, FILE *fp)
252 return fprintf(fp, "%s", dsoname); 252 return fprintf(fp, "%s", dsoname);
253} 253}
254 254
255/* 255/**
256 * map__rip_2objdump - convert symbol start address to objdump address.
257 * @map: memory map
258 * @rip: symbol start address
259 *
256 * objdump wants/reports absolute IPs for ET_EXEC, and RIPs for ET_DYN. 260 * objdump wants/reports absolute IPs for ET_EXEC, and RIPs for ET_DYN.
257 * map->dso->adjust_symbols==1 for ET_EXEC-like cases except ET_REL which is 261 * map->dso->adjust_symbols==1 for ET_EXEC-like cases except ET_REL which is
258 * relative to section start. 262 * relative to section start.
263 *
264 * Return: Address suitable for passing to "objdump --start-address="
259 */ 265 */
260u64 map__rip_2objdump(struct map *map, u64 rip) 266u64 map__rip_2objdump(struct map *map, u64 rip)
261{ 267{
@@ -268,6 +274,29 @@ u64 map__rip_2objdump(struct map *map, u64 rip)
268 return map->unmap_ip(map, rip); 274 return map->unmap_ip(map, rip);
269} 275}
270 276
277/**
278 * map__objdump_2mem - convert objdump address to a memory address.
279 * @map: memory map
280 * @ip: objdump address
281 *
282 * Closely related to map__rip_2objdump(), this function takes an address from
283 * objdump and converts it to a memory address. Note this assumes that @map
284 * contains the address. To be sure the result is valid, check it forwards
285 * e.g. map__rip_2objdump(map->map_ip(map, map__objdump_2mem(map, ip))) == ip
286 *
287 * Return: Memory address.
288 */
289u64 map__objdump_2mem(struct map *map, u64 ip)
290{
291 if (!map->dso->adjust_symbols)
292 return map->unmap_ip(map, ip);
293
294 if (map->dso->rel)
295 return map->unmap_ip(map, ip + map->pgoff);
296
297 return ip;
298}
299
271void map_groups__init(struct map_groups *mg) 300void map_groups__init(struct map_groups *mg)
272{ 301{
273 int i; 302 int i;
@@ -371,6 +400,23 @@ struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg,
371 return NULL; 400 return NULL;
372} 401}
373 402
403int map_groups__find_ams(struct addr_map_symbol *ams, symbol_filter_t filter)
404{
405 if (ams->addr < ams->map->start || ams->addr > ams->map->end) {
406 if (ams->map->groups == NULL)
407 return -1;
408 ams->map = map_groups__find(ams->map->groups, ams->map->type,
409 ams->addr);
410 if (ams->map == NULL)
411 return -1;
412 }
413
414 ams->al_addr = ams->map->map_ip(ams->map, ams->addr);
415 ams->sym = map__find_symbol(ams->map, ams->al_addr, filter);
416
417 return ams->sym ? 0 : -1;
418}
419
374size_t __map_groups__fprintf_maps(struct map_groups *mg, 420size_t __map_groups__fprintf_maps(struct map_groups *mg,
375 enum map_type type, int verbose, FILE *fp) 421 enum map_type type, int verbose, FILE *fp)
376{ 422{
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index 4886ca280536..e4e259c3ba16 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -84,6 +84,9 @@ static inline u64 identity__map_ip(struct map *map __maybe_unused, u64 ip)
84/* rip/ip <-> addr suitable for passing to `objdump --start-address=` */ 84/* rip/ip <-> addr suitable for passing to `objdump --start-address=` */
85u64 map__rip_2objdump(struct map *map, u64 rip); 85u64 map__rip_2objdump(struct map *map, u64 rip);
86 86
87/* objdump address -> memory address */
88u64 map__objdump_2mem(struct map *map, u64 ip);
89
87struct symbol; 90struct symbol;
88 91
89typedef int (*symbol_filter_t)(struct map *map, struct symbol *sym); 92typedef int (*symbol_filter_t)(struct map *map, struct symbol *sym);
@@ -167,6 +170,10 @@ struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg,
167 struct map **mapp, 170 struct map **mapp,
168 symbol_filter_t filter); 171 symbol_filter_t filter);
169 172
173struct addr_map_symbol;
174
175int map_groups__find_ams(struct addr_map_symbol *ams, symbol_filter_t filter);
176
170static inline 177static inline
171struct symbol *map_groups__find_function_by_name(struct map_groups *mg, 178struct symbol *map_groups__find_function_by_name(struct map_groups *mg,
172 const char *name, struct map **mapp, 179 const char *name, struct map **mapp,
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 91346b753960..343299575b30 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -126,6 +126,37 @@ modifier_bp [rwx]{1,3}
126 126
127} 127}
128 128
129<config>{
130config { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG); }
131config1 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG1); }
132config2 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG2); }
133name { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NAME); }
134period { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); }
135branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); }
136, { return ','; }
137"/" { BEGIN(INITIAL); return '/'; }
138{name_minus} { return str(yyscanner, PE_NAME); }
139}
140
141<mem>{
142{modifier_bp} { return str(yyscanner, PE_MODIFIER_BP); }
143: { return ':'; }
144{num_dec} { return value(yyscanner, 10); }
145{num_hex} { return value(yyscanner, 16); }
146 /*
147 * We need to separate 'mem:' scanner part, in order to get specific
148 * modifier bits parsed out. Otherwise we would need to handle PE_NAME
149 * and we'd need to parse it manually. During the escape from <mem>
150 * state we need to put the escaping char back, so we dont miss it.
151 */
152. { unput(*yytext); BEGIN(INITIAL); }
153 /*
154 * We destroy the scanner after reaching EOF,
155 * but anyway just to be sure get back to INIT state.
156 */
157<<EOF>> { BEGIN(INITIAL); }
158}
159
129cpu-cycles|cycles { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES); } 160cpu-cycles|cycles { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES); }
130stalled-cycles-frontend|idle-cycles-frontend { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); } 161stalled-cycles-frontend|idle-cycles-frontend { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); }
131stalled-cycles-backend|idle-cycles-backend { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); } 162stalled-cycles-backend|idle-cycles-backend { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); }
@@ -162,18 +193,6 @@ speculative-read|speculative-load |
162refs|Reference|ops|access | 193refs|Reference|ops|access |
163misses|miss { return str(yyscanner, PE_NAME_CACHE_OP_RESULT); } 194misses|miss { return str(yyscanner, PE_NAME_CACHE_OP_RESULT); }
164 195
165<config>{
166config { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG); }
167config1 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG1); }
168config2 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG2); }
169name { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NAME); }
170period { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); }
171branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); }
172, { return ','; }
173"/" { BEGIN(INITIAL); return '/'; }
174{name_minus} { return str(yyscanner, PE_NAME); }
175}
176
177mem: { BEGIN(mem); return PE_PREFIX_MEM; } 196mem: { BEGIN(mem); return PE_PREFIX_MEM; }
178r{num_raw_hex} { return raw(yyscanner); } 197r{num_raw_hex} { return raw(yyscanner); }
179{num_dec} { return value(yyscanner, 10); } 198{num_dec} { return value(yyscanner, 10); }
@@ -189,25 +208,7 @@ r{num_raw_hex} { return raw(yyscanner); }
189"}" { return '}'; } 208"}" { return '}'; }
190= { return '='; } 209= { return '='; }
191\n { } 210\n { }
192 211. { }
193<mem>{
194{modifier_bp} { return str(yyscanner, PE_MODIFIER_BP); }
195: { return ':'; }
196{num_dec} { return value(yyscanner, 10); }
197{num_hex} { return value(yyscanner, 16); }
198 /*
199 * We need to separate 'mem:' scanner part, in order to get specific
200 * modifier bits parsed out. Otherwise we would need to handle PE_NAME
201 * and we'd need to parse it manually. During the escape from <mem>
202 * state we need to put the escaping char back, so we dont miss it.
203 */
204. { unput(*yytext); BEGIN(INITIAL); }
205 /*
206 * We destroy the scanner after reaching EOF,
207 * but anyway just to be sure get back to INIT state.
208 */
209<<EOF>> { BEGIN(INITIAL); }
210}
211 212
212%% 213%%
213 214
diff --git a/tools/perf/util/path.c b/tools/perf/util/path.c
index a8c49548ca48..5d13cb45b317 100644
--- a/tools/perf/util/path.c
+++ b/tools/perf/util/path.c
@@ -22,19 +22,23 @@ static const char *get_perf_dir(void)
22 return "."; 22 return ".";
23} 23}
24 24
25#ifndef HAVE_STRLCPY 25/*
26size_t strlcpy(char *dest, const char *src, size_t size) 26 * If libc has strlcpy() then that version will override this
27 * implementation:
28 */
29size_t __weak strlcpy(char *dest, const char *src, size_t size)
27{ 30{
28 size_t ret = strlen(src); 31 size_t ret = strlen(src);
29 32
30 if (size) { 33 if (size) {
31 size_t len = (ret >= size) ? size - 1 : ret; 34 size_t len = (ret >= size) ? size - 1 : ret;
35
32 memcpy(dest, src, len); 36 memcpy(dest, src, len);
33 dest[len] = '\0'; 37 dest[len] = '\0';
34 } 38 }
39
35 return ret; 40 return ret;
36} 41}
37#endif
38 42
39static char *get_pathname(void) 43static char *get_pathname(void)
40{ 44{
diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h
index 5a4f2b6f3738..a3d42cd74919 100644
--- a/tools/perf/util/perf_regs.h
+++ b/tools/perf/util/perf_regs.h
@@ -1,7 +1,7 @@
1#ifndef __PERF_REGS_H 1#ifndef __PERF_REGS_H
2#define __PERF_REGS_H 2#define __PERF_REGS_H
3 3
4#ifdef HAVE_PERF_REGS 4#ifdef HAVE_PERF_REGS_SUPPORT
5#include <perf_regs.h> 5#include <perf_regs.h>
6#else 6#else
7#define PERF_REGS_MASK 0 7#define PERF_REGS_MASK 0
@@ -10,5 +10,5 @@ static inline const char *perf_reg_name(int id __maybe_unused)
10{ 10{
11 return NULL; 11 return NULL;
12} 12}
13#endif /* HAVE_PERF_REGS */ 13#endif /* HAVE_PERF_REGS_SUPPORT */
14#endif /* __PERF_REGS_H */ 14#endif /* __PERF_REGS_H */
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index aa04bf9c9ad7..779b2dacd43f 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -201,7 +201,7 @@ static int convert_to_perf_probe_point(struct probe_trace_point *tp,
201 return 0; 201 return 0;
202} 202}
203 203
204#ifdef DWARF_SUPPORT 204#ifdef HAVE_DWARF_SUPPORT
205/* Open new debuginfo of given module */ 205/* Open new debuginfo of given module */
206static struct debuginfo *open_debuginfo(const char *module) 206static struct debuginfo *open_debuginfo(const char *module)
207{ 207{
@@ -630,7 +630,7 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
630 return ret; 630 return ret;
631} 631}
632 632
633#else /* !DWARF_SUPPORT */ 633#else /* !HAVE_DWARF_SUPPORT */
634 634
635static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp, 635static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
636 struct perf_probe_point *pp) 636 struct perf_probe_point *pp)
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
index 3b7d63018960..3f0c29dd6ac5 100644
--- a/tools/perf/util/probe-finder.h
+++ b/tools/perf/util/probe-finder.h
@@ -14,7 +14,7 @@ static inline int is_c_varname(const char *name)
14 return isalpha(name[0]) || name[0] == '_'; 14 return isalpha(name[0]) || name[0] == '_';
15} 15}
16 16
17#ifdef DWARF_SUPPORT 17#ifdef HAVE_DWARF_SUPPORT
18 18
19#include "dwarf-aux.h" 19#include "dwarf-aux.h"
20 20
@@ -105,6 +105,6 @@ struct line_finder {
105 int found; 105 int found;
106}; 106};
107 107
108#endif /* DWARF_SUPPORT */ 108#endif /* HAVE_DWARF_SUPPORT */
109 109
110#endif /*_PROBE_FINDER_H */ 110#endif /*_PROBE_FINDER_H */
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 71b5412bbbb9..06efd027b1db 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -33,13 +33,6 @@ int eprintf(int level, const char *fmt, ...)
33# define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size, 33# define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size,
34#endif 34#endif
35 35
36struct throttle_event {
37 struct perf_event_header header;
38 u64 time;
39 u64 id;
40 u64 stream_id;
41};
42
43PyMODINIT_FUNC initperf(void); 36PyMODINIT_FUNC initperf(void);
44 37
45#define member_def(type, member, ptype, help) \ 38#define member_def(type, member, ptype, help) \
@@ -1036,6 +1029,7 @@ PyMODINIT_FUNC initperf(void)
1036 pyrf_cpu_map__setup_types() < 0) 1029 pyrf_cpu_map__setup_types() < 0)
1037 return; 1030 return;
1038 1031
1032 /* The page_size is placed in util object. */
1039 page_size = sysconf(_SC_PAGE_SIZE); 1033 page_size = sysconf(_SC_PAGE_SIZE);
1040 1034
1041 Py_INCREF(&pyrf_evlist__type); 1035 Py_INCREF(&pyrf_evlist__type);
diff --git a/tools/perf/util/rblist.c b/tools/perf/util/rblist.c
index a16cdd2625ad..0dfe27d99458 100644
--- a/tools/perf/util/rblist.c
+++ b/tools/perf/util/rblist.c
@@ -48,10 +48,12 @@ void rblist__remove_node(struct rblist *rblist, struct rb_node *rb_node)
48 rblist->node_delete(rblist, rb_node); 48 rblist->node_delete(rblist, rb_node);
49} 49}
50 50
51struct rb_node *rblist__find(struct rblist *rblist, const void *entry) 51static struct rb_node *__rblist__findnew(struct rblist *rblist,
52 const void *entry,
53 bool create)
52{ 54{
53 struct rb_node **p = &rblist->entries.rb_node; 55 struct rb_node **p = &rblist->entries.rb_node;
54 struct rb_node *parent = NULL; 56 struct rb_node *parent = NULL, *new_node = NULL;
55 57
56 while (*p != NULL) { 58 while (*p != NULL) {
57 int rc; 59 int rc;
@@ -67,7 +69,26 @@ struct rb_node *rblist__find(struct rblist *rblist, const void *entry)
67 return parent; 69 return parent;
68 } 70 }
69 71
70 return NULL; 72 if (create) {
73 new_node = rblist->node_new(rblist, entry);
74 if (new_node) {
75 rb_link_node(new_node, parent, p);
76 rb_insert_color(new_node, &rblist->entries);
77 ++rblist->nr_entries;
78 }
79 }
80
81 return new_node;
82}
83
84struct rb_node *rblist__find(struct rblist *rblist, const void *entry)
85{
86 return __rblist__findnew(rblist, entry, false);
87}
88
89struct rb_node *rblist__findnew(struct rblist *rblist, const void *entry)
90{
91 return __rblist__findnew(rblist, entry, true);
71} 92}
72 93
73void rblist__init(struct rblist *rblist) 94void rblist__init(struct rblist *rblist)
diff --git a/tools/perf/util/rblist.h b/tools/perf/util/rblist.h
index 6d0cae5ae83d..ff9913b994c2 100644
--- a/tools/perf/util/rblist.h
+++ b/tools/perf/util/rblist.h
@@ -32,6 +32,7 @@ void rblist__delete(struct rblist *rblist);
32int rblist__add_node(struct rblist *rblist, const void *new_entry); 32int rblist__add_node(struct rblist *rblist, const void *new_entry);
33void rblist__remove_node(struct rblist *rblist, struct rb_node *rb_node); 33void rblist__remove_node(struct rblist *rblist, struct rb_node *rb_node);
34struct rb_node *rblist__find(struct rblist *rblist, const void *entry); 34struct rb_node *rblist__find(struct rblist *rblist, const void *entry);
35struct rb_node *rblist__findnew(struct rblist *rblist, const void *entry);
35struct rb_node *rblist__entry(const struct rblist *rblist, unsigned int idx); 36struct rb_node *rblist__entry(const struct rblist *rblist, unsigned int idx);
36 37
37static inline bool rblist__empty(const struct rblist *rblist) 38static inline bool rblist__empty(const struct rblist *rblist)
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index b97f468af955..d1e449534b33 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -397,6 +397,17 @@ static void perf_event__read_swap(union perf_event *event, bool sample_id_all)
397 swap_sample_id_all(event, &event->read + 1); 397 swap_sample_id_all(event, &event->read + 1);
398} 398}
399 399
400static void perf_event__throttle_swap(union perf_event *event,
401 bool sample_id_all)
402{
403 event->throttle.time = bswap_64(event->throttle.time);
404 event->throttle.id = bswap_64(event->throttle.id);
405 event->throttle.stream_id = bswap_64(event->throttle.stream_id);
406
407 if (sample_id_all)
408 swap_sample_id_all(event, &event->throttle + 1);
409}
410
400static u8 revbyte(u8 b) 411static u8 revbyte(u8 b)
401{ 412{
402 int rev = (b >> 4) | ((b & 0xf) << 4); 413 int rev = (b >> 4) | ((b & 0xf) << 4);
@@ -482,6 +493,8 @@ static perf_event__swap_op perf_event__swap_ops[] = {
482 [PERF_RECORD_EXIT] = perf_event__task_swap, 493 [PERF_RECORD_EXIT] = perf_event__task_swap,
483 [PERF_RECORD_LOST] = perf_event__all64_swap, 494 [PERF_RECORD_LOST] = perf_event__all64_swap,
484 [PERF_RECORD_READ] = perf_event__read_swap, 495 [PERF_RECORD_READ] = perf_event__read_swap,
496 [PERF_RECORD_THROTTLE] = perf_event__throttle_swap,
497 [PERF_RECORD_UNTHROTTLE] = perf_event__throttle_swap,
485 [PERF_RECORD_SAMPLE] = perf_event__all64_swap, 498 [PERF_RECORD_SAMPLE] = perf_event__all64_swap,
486 [PERF_RECORD_HEADER_ATTR] = perf_event__hdr_attr_swap, 499 [PERF_RECORD_HEADER_ATTR] = perf_event__hdr_attr_swap,
487 [PERF_RECORD_HEADER_EVENT_TYPE] = perf_event__event_type_swap, 500 [PERF_RECORD_HEADER_EVENT_TYPE] = perf_event__event_type_swap,
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index b4ecc0e4c908..32c56377e008 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -243,50 +243,32 @@ struct sort_entry sort_sym = {
243static int64_t 243static int64_t
244sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right) 244sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right)
245{ 245{
246 return (int64_t)(right->ip - left->ip); 246 if (!left->srcline) {
247 if (!left->ms.map)
248 left->srcline = SRCLINE_UNKNOWN;
249 else {
250 struct map *map = left->ms.map;
251 left->srcline = get_srcline(map->dso,
252 map__rip_2objdump(map, left->ip));
253 }
254 }
255 if (!right->srcline) {
256 if (!right->ms.map)
257 right->srcline = SRCLINE_UNKNOWN;
258 else {
259 struct map *map = right->ms.map;
260 right->srcline = get_srcline(map->dso,
261 map__rip_2objdump(map, right->ip));
262 }
263 }
264 return strcmp(left->srcline, right->srcline);
247} 265}
248 266
249static int hist_entry__srcline_snprintf(struct hist_entry *self, char *bf, 267static int hist_entry__srcline_snprintf(struct hist_entry *self, char *bf,
250 size_t size, 268 size_t size,
251 unsigned int width __maybe_unused) 269 unsigned int width __maybe_unused)
252{ 270{
253 FILE *fp = NULL; 271 return repsep_snprintf(bf, size, "%s", self->srcline);
254 char cmd[PATH_MAX + 2], *path = self->srcline, *nl;
255 size_t line_len;
256
257 if (path != NULL)
258 goto out_path;
259
260 if (!self->ms.map)
261 goto out_ip;
262
263 if (!strncmp(self->ms.map->dso->long_name, "/tmp/perf-", 10))
264 goto out_ip;
265
266 snprintf(cmd, sizeof(cmd), "addr2line -e %s %016" PRIx64,
267 self->ms.map->dso->long_name, self->ip);
268 fp = popen(cmd, "r");
269 if (!fp)
270 goto out_ip;
271
272 if (getline(&path, &line_len, fp) < 0 || !line_len)
273 goto out_ip;
274 self->srcline = strdup(path);
275 if (self->srcline == NULL)
276 goto out_ip;
277
278 nl = strchr(self->srcline, '\n');
279 if (nl != NULL)
280 *nl = '\0';
281 path = self->srcline;
282out_path:
283 if (fp)
284 pclose(fp);
285 return repsep_snprintf(bf, size, "%s", path);
286out_ip:
287 if (fp)
288 pclose(fp);
289 return repsep_snprintf(bf, size, "%-#*llx", BITS_PER_LONG / 4, self->ip);
290} 272}
291 273
292struct sort_entry sort_srcline = { 274struct sort_entry sort_srcline = {
diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c
new file mode 100644
index 000000000000..d11aefbc4b8d
--- /dev/null
+++ b/tools/perf/util/srcline.c
@@ -0,0 +1,265 @@
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4
5#include <linux/kernel.h>
6
7#include "util/dso.h"
8#include "util/util.h"
9#include "util/debug.h"
10
11#ifdef HAVE_LIBBFD_SUPPORT
12
13/*
14 * Implement addr2line using libbfd.
15 */
16#define PACKAGE "perf"
17#include <bfd.h>
18
19struct a2l_data {
20 const char *input;
21 unsigned long addr;
22
23 bool found;
24 const char *filename;
25 const char *funcname;
26 unsigned line;
27
28 bfd *abfd;
29 asymbol **syms;
30};
31
32static int bfd_error(const char *string)
33{
34 const char *errmsg;
35
36 errmsg = bfd_errmsg(bfd_get_error());
37 fflush(stdout);
38
39 if (string)
40 pr_debug("%s: %s\n", string, errmsg);
41 else
42 pr_debug("%s\n", errmsg);
43
44 return -1;
45}
46
47static int slurp_symtab(bfd *abfd, struct a2l_data *a2l)
48{
49 long storage;
50 long symcount;
51 asymbol **syms;
52 bfd_boolean dynamic = FALSE;
53
54 if ((bfd_get_file_flags(abfd) & HAS_SYMS) == 0)
55 return bfd_error(bfd_get_filename(abfd));
56
57 storage = bfd_get_symtab_upper_bound(abfd);
58 if (storage == 0L) {
59 storage = bfd_get_dynamic_symtab_upper_bound(abfd);
60 dynamic = TRUE;
61 }
62 if (storage < 0L)
63 return bfd_error(bfd_get_filename(abfd));
64
65 syms = malloc(storage);
66 if (dynamic)
67 symcount = bfd_canonicalize_dynamic_symtab(abfd, syms);
68 else
69 symcount = bfd_canonicalize_symtab(abfd, syms);
70
71 if (symcount < 0) {
72 free(syms);
73 return bfd_error(bfd_get_filename(abfd));
74 }
75
76 a2l->syms = syms;
77 return 0;
78}
79
80static void find_address_in_section(bfd *abfd, asection *section, void *data)
81{
82 bfd_vma pc, vma;
83 bfd_size_type size;
84 struct a2l_data *a2l = data;
85
86 if (a2l->found)
87 return;
88
89 if ((bfd_get_section_flags(abfd, section) & SEC_ALLOC) == 0)
90 return;
91
92 pc = a2l->addr;
93 vma = bfd_get_section_vma(abfd, section);
94 size = bfd_get_section_size(section);
95
96 if (pc < vma || pc >= vma + size)
97 return;
98
99 a2l->found = bfd_find_nearest_line(abfd, section, a2l->syms, pc - vma,
100 &a2l->filename, &a2l->funcname,
101 &a2l->line);
102}
103
104static struct a2l_data *addr2line_init(const char *path)
105{
106 bfd *abfd;
107 struct a2l_data *a2l = NULL;
108
109 abfd = bfd_openr(path, NULL);
110 if (abfd == NULL)
111 return NULL;
112
113 if (!bfd_check_format(abfd, bfd_object))
114 goto out;
115
116 a2l = zalloc(sizeof(*a2l));
117 if (a2l == NULL)
118 goto out;
119
120 a2l->abfd = abfd;
121 a2l->input = strdup(path);
122 if (a2l->input == NULL)
123 goto out;
124
125 if (slurp_symtab(abfd, a2l))
126 goto out;
127
128 return a2l;
129
130out:
131 if (a2l) {
132 free((void *)a2l->input);
133 free(a2l);
134 }
135 bfd_close(abfd);
136 return NULL;
137}
138
139static void addr2line_cleanup(struct a2l_data *a2l)
140{
141 if (a2l->abfd)
142 bfd_close(a2l->abfd);
143 free((void *)a2l->input);
144 free(a2l->syms);
145 free(a2l);
146}
147
148static int addr2line(const char *dso_name, unsigned long addr,
149 char **file, unsigned int *line)
150{
151 int ret = 0;
152 struct a2l_data *a2l;
153
154 a2l = addr2line_init(dso_name);
155 if (a2l == NULL) {
156 pr_warning("addr2line_init failed for %s\n", dso_name);
157 return 0;
158 }
159
160 a2l->addr = addr;
161 bfd_map_over_sections(a2l->abfd, find_address_in_section, a2l);
162
163 if (a2l->found && a2l->filename) {
164 *file = strdup(a2l->filename);
165 *line = a2l->line;
166
167 if (*file)
168 ret = 1;
169 }
170
171 addr2line_cleanup(a2l);
172 return ret;
173}
174
175#else /* HAVE_LIBBFD_SUPPORT */
176
177static int addr2line(const char *dso_name, unsigned long addr,
178 char **file, unsigned int *line_nr)
179{
180 FILE *fp;
181 char cmd[PATH_MAX];
182 char *filename = NULL;
183 size_t len;
184 char *sep;
185 int ret = 0;
186
187 scnprintf(cmd, sizeof(cmd), "addr2line -e %s %016"PRIx64,
188 dso_name, addr);
189
190 fp = popen(cmd, "r");
191 if (fp == NULL) {
192 pr_warning("popen failed for %s\n", dso_name);
193 return 0;
194 }
195
196 if (getline(&filename, &len, fp) < 0 || !len) {
197 pr_warning("addr2line has no output for %s\n", dso_name);
198 goto out;
199 }
200
201 sep = strchr(filename, '\n');
202 if (sep)
203 *sep = '\0';
204
205 if (!strcmp(filename, "??:0")) {
206 pr_debug("no debugging info in %s\n", dso_name);
207 free(filename);
208 goto out;
209 }
210
211 sep = strchr(filename, ':');
212 if (sep) {
213 *sep++ = '\0';
214 *file = filename;
215 *line_nr = strtoul(sep, NULL, 0);
216 ret = 1;
217 }
218out:
219 pclose(fp);
220 return ret;
221}
222#endif /* HAVE_LIBBFD_SUPPORT */
223
224char *get_srcline(struct dso *dso, unsigned long addr)
225{
226 char *file = NULL;
227 unsigned line = 0;
228 char *srcline;
229 char *dso_name = dso->long_name;
230 size_t size;
231
232 if (!dso->has_srcline)
233 return SRCLINE_UNKNOWN;
234
235 if (dso_name[0] == '[')
236 goto out;
237
238 if (!strncmp(dso_name, "/tmp/perf-", 10))
239 goto out;
240
241 if (!addr2line(dso_name, addr, &file, &line))
242 goto out;
243
244 /* just calculate actual length */
245 size = snprintf(NULL, 0, "%s:%u", file, line) + 1;
246
247 srcline = malloc(size);
248 if (srcline)
249 snprintf(srcline, size, "%s:%u", file, line);
250 else
251 srcline = SRCLINE_UNKNOWN;
252
253 free(file);
254 return srcline;
255
256out:
257 dso->has_srcline = 0;
258 return SRCLINE_UNKNOWN;
259}
260
261void free_srcline(char *srcline)
262{
263 if (srcline && strcmp(srcline, SRCLINE_UNKNOWN) != 0)
264 free(srcline);
265}
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index a9c829be5216..eed0b96302af 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -8,7 +8,7 @@
8#include "symbol.h" 8#include "symbol.h"
9#include "debug.h" 9#include "debug.h"
10 10
11#ifndef HAVE_ELF_GETPHDRNUM 11#ifndef HAVE_ELF_GETPHDRNUM_SUPPORT
12static int elf_getphdrnum(Elf *elf, size_t *dst) 12static int elf_getphdrnum(Elf *elf, size_t *dst)
13{ 13{
14 GElf_Ehdr gehdr; 14 GElf_Ehdr gehdr;
@@ -487,27 +487,27 @@ int filename__read_debuglink(const char *filename, char *debuglink,
487 487
488 ek = elf_kind(elf); 488 ek = elf_kind(elf);
489 if (ek != ELF_K_ELF) 489 if (ek != ELF_K_ELF)
490 goto out_close; 490 goto out_elf_end;
491 491
492 if (gelf_getehdr(elf, &ehdr) == NULL) { 492 if (gelf_getehdr(elf, &ehdr) == NULL) {
493 pr_err("%s: cannot get elf header.\n", __func__); 493 pr_err("%s: cannot get elf header.\n", __func__);
494 goto out_close; 494 goto out_elf_end;
495 } 495 }
496 496
497 sec = elf_section_by_name(elf, &ehdr, &shdr, 497 sec = elf_section_by_name(elf, &ehdr, &shdr,
498 ".gnu_debuglink", NULL); 498 ".gnu_debuglink", NULL);
499 if (sec == NULL) 499 if (sec == NULL)
500 goto out_close; 500 goto out_elf_end;
501 501
502 data = elf_getdata(sec, NULL); 502 data = elf_getdata(sec, NULL);
503 if (data == NULL) 503 if (data == NULL)
504 goto out_close; 504 goto out_elf_end;
505 505
506 /* the start of this section is a zero-terminated string */ 506 /* the start of this section is a zero-terminated string */
507 strncpy(debuglink, data->d_buf, size); 507 strncpy(debuglink, data->d_buf, size);
508 508
509out_elf_end:
509 elf_end(elf); 510 elf_end(elf);
510
511out_close: 511out_close:
512 close(fd); 512 close(fd);
513out: 513out:
@@ -1018,6 +1018,601 @@ int file__read_maps(int fd, bool exe, mapfn_t mapfn, void *data,
1018 return err; 1018 return err;
1019} 1019}
1020 1020
1021static int copy_bytes(int from, off_t from_offs, int to, off_t to_offs, u64 len)
1022{
1023 ssize_t r;
1024 size_t n;
1025 int err = -1;
1026 char *buf = malloc(page_size);
1027
1028 if (buf == NULL)
1029 return -1;
1030
1031 if (lseek(to, to_offs, SEEK_SET) != to_offs)
1032 goto out;
1033
1034 if (lseek(from, from_offs, SEEK_SET) != from_offs)
1035 goto out;
1036
1037 while (len) {
1038 n = page_size;
1039 if (len < n)
1040 n = len;
1041 /* Use read because mmap won't work on proc files */
1042 r = read(from, buf, n);
1043 if (r < 0)
1044 goto out;
1045 if (!r)
1046 break;
1047 n = r;
1048 r = write(to, buf, n);
1049 if (r < 0)
1050 goto out;
1051 if ((size_t)r != n)
1052 goto out;
1053 len -= n;
1054 }
1055
1056 err = 0;
1057out:
1058 free(buf);
1059 return err;
1060}
1061
1062struct kcore {
1063 int fd;
1064 int elfclass;
1065 Elf *elf;
1066 GElf_Ehdr ehdr;
1067};
1068
1069static int kcore__open(struct kcore *kcore, const char *filename)
1070{
1071 GElf_Ehdr *ehdr;
1072
1073 kcore->fd = open(filename, O_RDONLY);
1074 if (kcore->fd == -1)
1075 return -1;
1076
1077 kcore->elf = elf_begin(kcore->fd, ELF_C_READ, NULL);
1078 if (!kcore->elf)
1079 goto out_close;
1080
1081 kcore->elfclass = gelf_getclass(kcore->elf);
1082 if (kcore->elfclass == ELFCLASSNONE)
1083 goto out_end;
1084
1085 ehdr = gelf_getehdr(kcore->elf, &kcore->ehdr);
1086 if (!ehdr)
1087 goto out_end;
1088
1089 return 0;
1090
1091out_end:
1092 elf_end(kcore->elf);
1093out_close:
1094 close(kcore->fd);
1095 return -1;
1096}
1097
1098static int kcore__init(struct kcore *kcore, char *filename, int elfclass,
1099 bool temp)
1100{
1101 GElf_Ehdr *ehdr;
1102
1103 kcore->elfclass = elfclass;
1104
1105 if (temp)
1106 kcore->fd = mkstemp(filename);
1107 else
1108 kcore->fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0400);
1109 if (kcore->fd == -1)
1110 return -1;
1111
1112 kcore->elf = elf_begin(kcore->fd, ELF_C_WRITE, NULL);
1113 if (!kcore->elf)
1114 goto out_close;
1115
1116 if (!gelf_newehdr(kcore->elf, elfclass))
1117 goto out_end;
1118
1119 ehdr = gelf_getehdr(kcore->elf, &kcore->ehdr);
1120 if (!ehdr)
1121 goto out_end;
1122
1123 return 0;
1124
1125out_end:
1126 elf_end(kcore->elf);
1127out_close:
1128 close(kcore->fd);
1129 unlink(filename);
1130 return -1;
1131}
1132
1133static void kcore__close(struct kcore *kcore)
1134{
1135 elf_end(kcore->elf);
1136 close(kcore->fd);
1137}
1138
1139static int kcore__copy_hdr(struct kcore *from, struct kcore *to, size_t count)
1140{
1141 GElf_Ehdr *ehdr = &to->ehdr;
1142 GElf_Ehdr *kehdr = &from->ehdr;
1143
1144 memcpy(ehdr->e_ident, kehdr->e_ident, EI_NIDENT);
1145 ehdr->e_type = kehdr->e_type;
1146 ehdr->e_machine = kehdr->e_machine;
1147 ehdr->e_version = kehdr->e_version;
1148 ehdr->e_entry = 0;
1149 ehdr->e_shoff = 0;
1150 ehdr->e_flags = kehdr->e_flags;
1151 ehdr->e_phnum = count;
1152 ehdr->e_shentsize = 0;
1153 ehdr->e_shnum = 0;
1154 ehdr->e_shstrndx = 0;
1155
1156 if (from->elfclass == ELFCLASS32) {
1157 ehdr->e_phoff = sizeof(Elf32_Ehdr);
1158 ehdr->e_ehsize = sizeof(Elf32_Ehdr);
1159 ehdr->e_phentsize = sizeof(Elf32_Phdr);
1160 } else {
1161 ehdr->e_phoff = sizeof(Elf64_Ehdr);
1162 ehdr->e_ehsize = sizeof(Elf64_Ehdr);
1163 ehdr->e_phentsize = sizeof(Elf64_Phdr);
1164 }
1165
1166 if (!gelf_update_ehdr(to->elf, ehdr))
1167 return -1;
1168
1169 if (!gelf_newphdr(to->elf, count))
1170 return -1;
1171
1172 return 0;
1173}
1174
1175static int kcore__add_phdr(struct kcore *kcore, int idx, off_t offset,
1176 u64 addr, u64 len)
1177{
1178 GElf_Phdr gphdr;
1179 GElf_Phdr *phdr;
1180
1181 phdr = gelf_getphdr(kcore->elf, idx, &gphdr);
1182 if (!phdr)
1183 return -1;
1184
1185 phdr->p_type = PT_LOAD;
1186 phdr->p_flags = PF_R | PF_W | PF_X;
1187 phdr->p_offset = offset;
1188 phdr->p_vaddr = addr;
1189 phdr->p_paddr = 0;
1190 phdr->p_filesz = len;
1191 phdr->p_memsz = len;
1192 phdr->p_align = page_size;
1193
1194 if (!gelf_update_phdr(kcore->elf, idx, phdr))
1195 return -1;
1196
1197 return 0;
1198}
1199
1200static off_t kcore__write(struct kcore *kcore)
1201{
1202 return elf_update(kcore->elf, ELF_C_WRITE);
1203}
1204
1205struct phdr_data {
1206 off_t offset;
1207 u64 addr;
1208 u64 len;
1209};
1210
1211struct kcore_copy_info {
1212 u64 stext;
1213 u64 etext;
1214 u64 first_symbol;
1215 u64 last_symbol;
1216 u64 first_module;
1217 u64 last_module_symbol;
1218 struct phdr_data kernel_map;
1219 struct phdr_data modules_map;
1220};
1221
1222static int kcore_copy__process_kallsyms(void *arg, const char *name, char type,
1223 u64 start)
1224{
1225 struct kcore_copy_info *kci = arg;
1226
1227 if (!symbol_type__is_a(type, MAP__FUNCTION))
1228 return 0;
1229
1230 if (strchr(name, '[')) {
1231 if (start > kci->last_module_symbol)
1232 kci->last_module_symbol = start;
1233 return 0;
1234 }
1235
1236 if (!kci->first_symbol || start < kci->first_symbol)
1237 kci->first_symbol = start;
1238
1239 if (!kci->last_symbol || start > kci->last_symbol)
1240 kci->last_symbol = start;
1241
1242 if (!strcmp(name, "_stext")) {
1243 kci->stext = start;
1244 return 0;
1245 }
1246
1247 if (!strcmp(name, "_etext")) {
1248 kci->etext = start;
1249 return 0;
1250 }
1251
1252 return 0;
1253}
1254
1255static int kcore_copy__parse_kallsyms(struct kcore_copy_info *kci,
1256 const char *dir)
1257{
1258 char kallsyms_filename[PATH_MAX];
1259
1260 scnprintf(kallsyms_filename, PATH_MAX, "%s/kallsyms", dir);
1261
1262 if (symbol__restricted_filename(kallsyms_filename, "/proc/kallsyms"))
1263 return -1;
1264
1265 if (kallsyms__parse(kallsyms_filename, kci,
1266 kcore_copy__process_kallsyms) < 0)
1267 return -1;
1268
1269 return 0;
1270}
1271
1272static int kcore_copy__process_modules(void *arg,
1273 const char *name __maybe_unused,
1274 u64 start)
1275{
1276 struct kcore_copy_info *kci = arg;
1277
1278 if (!kci->first_module || start < kci->first_module)
1279 kci->first_module = start;
1280
1281 return 0;
1282}
1283
1284static int kcore_copy__parse_modules(struct kcore_copy_info *kci,
1285 const char *dir)
1286{
1287 char modules_filename[PATH_MAX];
1288
1289 scnprintf(modules_filename, PATH_MAX, "%s/modules", dir);
1290
1291 if (symbol__restricted_filename(modules_filename, "/proc/modules"))
1292 return -1;
1293
1294 if (modules__parse(modules_filename, kci,
1295 kcore_copy__process_modules) < 0)
1296 return -1;
1297
1298 return 0;
1299}
1300
1301static void kcore_copy__map(struct phdr_data *p, u64 start, u64 end, u64 pgoff,
1302 u64 s, u64 e)
1303{
1304 if (p->addr || s < start || s >= end)
1305 return;
1306
1307 p->addr = s;
1308 p->offset = (s - start) + pgoff;
1309 p->len = e < end ? e - s : end - s;
1310}
1311
1312static int kcore_copy__read_map(u64 start, u64 len, u64 pgoff, void *data)
1313{
1314 struct kcore_copy_info *kci = data;
1315 u64 end = start + len;
1316
1317 kcore_copy__map(&kci->kernel_map, start, end, pgoff, kci->stext,
1318 kci->etext);
1319
1320 kcore_copy__map(&kci->modules_map, start, end, pgoff, kci->first_module,
1321 kci->last_module_symbol);
1322
1323 return 0;
1324}
1325
1326static int kcore_copy__read_maps(struct kcore_copy_info *kci, Elf *elf)
1327{
1328 if (elf_read_maps(elf, true, kcore_copy__read_map, kci) < 0)
1329 return -1;
1330
1331 return 0;
1332}
1333
1334static int kcore_copy__calc_maps(struct kcore_copy_info *kci, const char *dir,
1335 Elf *elf)
1336{
1337 if (kcore_copy__parse_kallsyms(kci, dir))
1338 return -1;
1339
1340 if (kcore_copy__parse_modules(kci, dir))
1341 return -1;
1342
1343 if (kci->stext)
1344 kci->stext = round_down(kci->stext, page_size);
1345 else
1346 kci->stext = round_down(kci->first_symbol, page_size);
1347
1348 if (kci->etext) {
1349 kci->etext = round_up(kci->etext, page_size);
1350 } else if (kci->last_symbol) {
1351 kci->etext = round_up(kci->last_symbol, page_size);
1352 kci->etext += page_size;
1353 }
1354
1355 kci->first_module = round_down(kci->first_module, page_size);
1356
1357 if (kci->last_module_symbol) {
1358 kci->last_module_symbol = round_up(kci->last_module_symbol,
1359 page_size);
1360 kci->last_module_symbol += page_size;
1361 }
1362
1363 if (!kci->stext || !kci->etext)
1364 return -1;
1365
1366 if (kci->first_module && !kci->last_module_symbol)
1367 return -1;
1368
1369 return kcore_copy__read_maps(kci, elf);
1370}
1371
1372static int kcore_copy__copy_file(const char *from_dir, const char *to_dir,
1373 const char *name)
1374{
1375 char from_filename[PATH_MAX];
1376 char to_filename[PATH_MAX];
1377
1378 scnprintf(from_filename, PATH_MAX, "%s/%s", from_dir, name);
1379 scnprintf(to_filename, PATH_MAX, "%s/%s", to_dir, name);
1380
1381 return copyfile_mode(from_filename, to_filename, 0400);
1382}
1383
1384static int kcore_copy__unlink(const char *dir, const char *name)
1385{
1386 char filename[PATH_MAX];
1387
1388 scnprintf(filename, PATH_MAX, "%s/%s", dir, name);
1389
1390 return unlink(filename);
1391}
1392
1393static int kcore_copy__compare_fds(int from, int to)
1394{
1395 char *buf_from;
1396 char *buf_to;
1397 ssize_t ret;
1398 size_t len;
1399 int err = -1;
1400
1401 buf_from = malloc(page_size);
1402 buf_to = malloc(page_size);
1403 if (!buf_from || !buf_to)
1404 goto out;
1405
1406 while (1) {
1407 /* Use read because mmap won't work on proc files */
1408 ret = read(from, buf_from, page_size);
1409 if (ret < 0)
1410 goto out;
1411
1412 if (!ret)
1413 break;
1414
1415 len = ret;
1416
1417 if (readn(to, buf_to, len) != (int)len)
1418 goto out;
1419
1420 if (memcmp(buf_from, buf_to, len))
1421 goto out;
1422 }
1423
1424 err = 0;
1425out:
1426 free(buf_to);
1427 free(buf_from);
1428 return err;
1429}
1430
1431static int kcore_copy__compare_files(const char *from_filename,
1432 const char *to_filename)
1433{
1434 int from, to, err = -1;
1435
1436 from = open(from_filename, O_RDONLY);
1437 if (from < 0)
1438 return -1;
1439
1440 to = open(to_filename, O_RDONLY);
1441 if (to < 0)
1442 goto out_close_from;
1443
1444 err = kcore_copy__compare_fds(from, to);
1445
1446 close(to);
1447out_close_from:
1448 close(from);
1449 return err;
1450}
1451
1452static int kcore_copy__compare_file(const char *from_dir, const char *to_dir,
1453 const char *name)
1454{
1455 char from_filename[PATH_MAX];
1456 char to_filename[PATH_MAX];
1457
1458 scnprintf(from_filename, PATH_MAX, "%s/%s", from_dir, name);
1459 scnprintf(to_filename, PATH_MAX, "%s/%s", to_dir, name);
1460
1461 return kcore_copy__compare_files(from_filename, to_filename);
1462}
1463
1464/**
1465 * kcore_copy - copy kallsyms, modules and kcore from one directory to another.
1466 * @from_dir: from directory
1467 * @to_dir: to directory
1468 *
1469 * This function copies kallsyms, modules and kcore files from one directory to
1470 * another. kallsyms and modules are copied entirely. Only code segments are
1471 * copied from kcore. It is assumed that two segments suffice: one for the
1472 * kernel proper and one for all the modules. The code segments are determined
1473 * from kallsyms and modules files. The kernel map starts at _stext or the
1474 * lowest function symbol, and ends at _etext or the highest function symbol.
1475 * The module map starts at the lowest module address and ends at the highest
1476 * module symbol. Start addresses are rounded down to the nearest page. End
1477 * addresses are rounded up to the nearest page. An extra page is added to the
1478 * highest kernel symbol and highest module symbol to, hopefully, encompass that
1479 * symbol too. Because it contains only code sections, the resulting kcore is
1480 * unusual. One significant peculiarity is that the mapping (start -> pgoff)
1481 * is not the same for the kernel map and the modules map. That happens because
1482 * the data is copied adjacently whereas the original kcore has gaps. Finally,
1483 * kallsyms and modules files are compared with their copies to check that
1484 * modules have not been loaded or unloaded while the copies were taking place.
1485 *
1486 * Return: %0 on success, %-1 on failure.
1487 */
1488int kcore_copy(const char *from_dir, const char *to_dir)
1489{
1490 struct kcore kcore;
1491 struct kcore extract;
1492 size_t count = 2;
1493 int idx = 0, err = -1;
1494 off_t offset = page_size, sz, modules_offset = 0;
1495 struct kcore_copy_info kci = { .stext = 0, };
1496 char kcore_filename[PATH_MAX];
1497 char extract_filename[PATH_MAX];
1498
1499 if (kcore_copy__copy_file(from_dir, to_dir, "kallsyms"))
1500 return -1;
1501
1502 if (kcore_copy__copy_file(from_dir, to_dir, "modules"))
1503 goto out_unlink_kallsyms;
1504
1505 scnprintf(kcore_filename, PATH_MAX, "%s/kcore", from_dir);
1506 scnprintf(extract_filename, PATH_MAX, "%s/kcore", to_dir);
1507
1508 if (kcore__open(&kcore, kcore_filename))
1509 goto out_unlink_modules;
1510
1511 if (kcore_copy__calc_maps(&kci, from_dir, kcore.elf))
1512 goto out_kcore_close;
1513
1514 if (kcore__init(&extract, extract_filename, kcore.elfclass, false))
1515 goto out_kcore_close;
1516
1517 if (!kci.modules_map.addr)
1518 count -= 1;
1519
1520 if (kcore__copy_hdr(&kcore, &extract, count))
1521 goto out_extract_close;
1522
1523 if (kcore__add_phdr(&extract, idx++, offset, kci.kernel_map.addr,
1524 kci.kernel_map.len))
1525 goto out_extract_close;
1526
1527 if (kci.modules_map.addr) {
1528 modules_offset = offset + kci.kernel_map.len;
1529 if (kcore__add_phdr(&extract, idx, modules_offset,
1530 kci.modules_map.addr, kci.modules_map.len))
1531 goto out_extract_close;
1532 }
1533
1534 sz = kcore__write(&extract);
1535 if (sz < 0 || sz > offset)
1536 goto out_extract_close;
1537
1538 if (copy_bytes(kcore.fd, kci.kernel_map.offset, extract.fd, offset,
1539 kci.kernel_map.len))
1540 goto out_extract_close;
1541
1542 if (modules_offset && copy_bytes(kcore.fd, kci.modules_map.offset,
1543 extract.fd, modules_offset,
1544 kci.modules_map.len))
1545 goto out_extract_close;
1546
1547 if (kcore_copy__compare_file(from_dir, to_dir, "modules"))
1548 goto out_extract_close;
1549
1550 if (kcore_copy__compare_file(from_dir, to_dir, "kallsyms"))
1551 goto out_extract_close;
1552
1553 err = 0;
1554
1555out_extract_close:
1556 kcore__close(&extract);
1557 if (err)
1558 unlink(extract_filename);
1559out_kcore_close:
1560 kcore__close(&kcore);
1561out_unlink_modules:
1562 if (err)
1563 kcore_copy__unlink(to_dir, "modules");
1564out_unlink_kallsyms:
1565 if (err)
1566 kcore_copy__unlink(to_dir, "kallsyms");
1567
1568 return err;
1569}
1570
1571int kcore_extract__create(struct kcore_extract *kce)
1572{
1573 struct kcore kcore;
1574 struct kcore extract;
1575 size_t count = 1;
1576 int idx = 0, err = -1;
1577 off_t offset = page_size, sz;
1578
1579 if (kcore__open(&kcore, kce->kcore_filename))
1580 return -1;
1581
1582 strcpy(kce->extract_filename, PERF_KCORE_EXTRACT);
1583 if (kcore__init(&extract, kce->extract_filename, kcore.elfclass, true))
1584 goto out_kcore_close;
1585
1586 if (kcore__copy_hdr(&kcore, &extract, count))
1587 goto out_extract_close;
1588
1589 if (kcore__add_phdr(&extract, idx, offset, kce->addr, kce->len))
1590 goto out_extract_close;
1591
1592 sz = kcore__write(&extract);
1593 if (sz < 0 || sz > offset)
1594 goto out_extract_close;
1595
1596 if (copy_bytes(kcore.fd, kce->offs, extract.fd, offset, kce->len))
1597 goto out_extract_close;
1598
1599 err = 0;
1600
1601out_extract_close:
1602 kcore__close(&extract);
1603 if (err)
1604 unlink(kce->extract_filename);
1605out_kcore_close:
1606 kcore__close(&kcore);
1607
1608 return err;
1609}
1610
1611void kcore_extract__delete(struct kcore_extract *kce)
1612{
1613 unlink(kce->extract_filename);
1614}
1615
1021void symbol__elf_init(void) 1616void symbol__elf_init(void)
1022{ 1617{
1023 elf_version(EV_CURRENT); 1618 elf_version(EV_CURRENT);
diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c
index 3a802c300fc5..2d2dd0532b5a 100644
--- a/tools/perf/util/symbol-minimal.c
+++ b/tools/perf/util/symbol-minimal.c
@@ -308,6 +308,21 @@ int file__read_maps(int fd __maybe_unused, bool exe __maybe_unused,
308 return -1; 308 return -1;
309} 309}
310 310
311int kcore_extract__create(struct kcore_extract *kce __maybe_unused)
312{
313 return -1;
314}
315
316void kcore_extract__delete(struct kcore_extract *kce __maybe_unused)
317{
318}
319
320int kcore_copy(const char *from_dir __maybe_unused,
321 const char *to_dir __maybe_unused)
322{
323 return -1;
324}
325
311void symbol__elf_init(void) 326void symbol__elf_init(void)
312{ 327{
313} 328}
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 7eb0362f4ffd..c0c36965fff0 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -51,6 +51,7 @@ static enum dso_binary_type binary_type_symtab[] = {
51 DSO_BINARY_TYPE__SYSTEM_PATH_DSO, 51 DSO_BINARY_TYPE__SYSTEM_PATH_DSO,
52 DSO_BINARY_TYPE__GUEST_KMODULE, 52 DSO_BINARY_TYPE__GUEST_KMODULE,
53 DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE, 53 DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE,
54 DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,
54 DSO_BINARY_TYPE__NOT_FOUND, 55 DSO_BINARY_TYPE__NOT_FOUND,
55}; 56};
56 57
@@ -159,10 +160,12 @@ again:
159 160
160 if (choose_best_symbol(curr, next) == SYMBOL_A) { 161 if (choose_best_symbol(curr, next) == SYMBOL_A) {
161 rb_erase(&next->rb_node, symbols); 162 rb_erase(&next->rb_node, symbols);
163 symbol__delete(next);
162 goto again; 164 goto again;
163 } else { 165 } else {
164 nd = rb_next(&curr->rb_node); 166 nd = rb_next(&curr->rb_node);
165 rb_erase(&curr->rb_node, symbols); 167 rb_erase(&curr->rb_node, symbols);
168 symbol__delete(curr);
166 } 169 }
167 } 170 }
168} 171}
@@ -499,6 +502,64 @@ out_failure:
499 return -1; 502 return -1;
500} 503}
501 504
505int modules__parse(const char *filename, void *arg,
506 int (*process_module)(void *arg, const char *name,
507 u64 start))
508{
509 char *line = NULL;
510 size_t n;
511 FILE *file;
512 int err = 0;
513
514 file = fopen(filename, "r");
515 if (file == NULL)
516 return -1;
517
518 while (1) {
519 char name[PATH_MAX];
520 u64 start;
521 char *sep;
522 ssize_t line_len;
523
524 line_len = getline(&line, &n, file);
525 if (line_len < 0) {
526 if (feof(file))
527 break;
528 err = -1;
529 goto out;
530 }
531
532 if (!line) {
533 err = -1;
534 goto out;
535 }
536
537 line[--line_len] = '\0'; /* \n */
538
539 sep = strrchr(line, 'x');
540 if (sep == NULL)
541 continue;
542
543 hex2u64(sep + 1, &start);
544
545 sep = strchr(line, ' ');
546 if (sep == NULL)
547 continue;
548
549 *sep = '\0';
550
551 scnprintf(name, sizeof(name), "[%s]", line);
552
553 err = process_module(arg, name, start);
554 if (err)
555 break;
556 }
557out:
558 free(line);
559 fclose(file);
560 return err;
561}
562
502struct process_kallsyms_args { 563struct process_kallsyms_args {
503 struct map *map; 564 struct map *map;
504 struct dso *dso; 565 struct dso *dso;
@@ -739,51 +800,242 @@ bool symbol__restricted_filename(const char *filename,
739 return restricted; 800 return restricted;
740} 801}
741 802
742struct kcore_mapfn_data { 803struct module_info {
743 struct dso *dso; 804 struct rb_node rb_node;
744 enum map_type type; 805 char *name;
745 struct list_head maps; 806 u64 start;
746}; 807};
747 808
748static int kcore_mapfn(u64 start, u64 len, u64 pgoff, void *data) 809static void add_module(struct module_info *mi, struct rb_root *modules)
749{ 810{
750 struct kcore_mapfn_data *md = data; 811 struct rb_node **p = &modules->rb_node;
751 struct map *map; 812 struct rb_node *parent = NULL;
813 struct module_info *m;
752 814
753 map = map__new2(start, md->dso, md->type); 815 while (*p != NULL) {
754 if (map == NULL) 816 parent = *p;
817 m = rb_entry(parent, struct module_info, rb_node);
818 if (strcmp(mi->name, m->name) < 0)
819 p = &(*p)->rb_left;
820 else
821 p = &(*p)->rb_right;
822 }
823 rb_link_node(&mi->rb_node, parent, p);
824 rb_insert_color(&mi->rb_node, modules);
825}
826
827static void delete_modules(struct rb_root *modules)
828{
829 struct module_info *mi;
830 struct rb_node *next = rb_first(modules);
831
832 while (next) {
833 mi = rb_entry(next, struct module_info, rb_node);
834 next = rb_next(&mi->rb_node);
835 rb_erase(&mi->rb_node, modules);
836 free(mi->name);
837 free(mi);
838 }
839}
840
841static struct module_info *find_module(const char *name,
842 struct rb_root *modules)
843{
844 struct rb_node *n = modules->rb_node;
845
846 while (n) {
847 struct module_info *m;
848 int cmp;
849
850 m = rb_entry(n, struct module_info, rb_node);
851 cmp = strcmp(name, m->name);
852 if (cmp < 0)
853 n = n->rb_left;
854 else if (cmp > 0)
855 n = n->rb_right;
856 else
857 return m;
858 }
859
860 return NULL;
861}
862
863static int __read_proc_modules(void *arg, const char *name, u64 start)
864{
865 struct rb_root *modules = arg;
866 struct module_info *mi;
867
868 mi = zalloc(sizeof(struct module_info));
869 if (!mi)
755 return -ENOMEM; 870 return -ENOMEM;
756 871
757 map->end = map->start + len; 872 mi->name = strdup(name);
758 map->pgoff = pgoff; 873 mi->start = start;
759 874
760 list_add(&map->node, &md->maps); 875 if (!mi->name) {
876 free(mi);
877 return -ENOMEM;
878 }
879
880 add_module(mi, modules);
881
882 return 0;
883}
884
885static int read_proc_modules(const char *filename, struct rb_root *modules)
886{
887 if (symbol__restricted_filename(filename, "/proc/modules"))
888 return -1;
889
890 if (modules__parse(filename, modules, __read_proc_modules)) {
891 delete_modules(modules);
892 return -1;
893 }
761 894
762 return 0; 895 return 0;
763} 896}
764 897
898int compare_proc_modules(const char *from, const char *to)
899{
900 struct rb_root from_modules = RB_ROOT;
901 struct rb_root to_modules = RB_ROOT;
902 struct rb_node *from_node, *to_node;
903 struct module_info *from_m, *to_m;
904 int ret = -1;
905
906 if (read_proc_modules(from, &from_modules))
907 return -1;
908
909 if (read_proc_modules(to, &to_modules))
910 goto out_delete_from;
911
912 from_node = rb_first(&from_modules);
913 to_node = rb_first(&to_modules);
914 while (from_node) {
915 if (!to_node)
916 break;
917
918 from_m = rb_entry(from_node, struct module_info, rb_node);
919 to_m = rb_entry(to_node, struct module_info, rb_node);
920
921 if (from_m->start != to_m->start ||
922 strcmp(from_m->name, to_m->name))
923 break;
924
925 from_node = rb_next(from_node);
926 to_node = rb_next(to_node);
927 }
928
929 if (!from_node && !to_node)
930 ret = 0;
931
932 delete_modules(&to_modules);
933out_delete_from:
934 delete_modules(&from_modules);
935
936 return ret;
937}
938
939static int do_validate_kcore_modules(const char *filename, struct map *map,
940 struct map_groups *kmaps)
941{
942 struct rb_root modules = RB_ROOT;
943 struct map *old_map;
944 int err;
945
946 err = read_proc_modules(filename, &modules);
947 if (err)
948 return err;
949
950 old_map = map_groups__first(kmaps, map->type);
951 while (old_map) {
952 struct map *next = map_groups__next(old_map);
953 struct module_info *mi;
954
955 if (old_map == map || old_map->start == map->start) {
956 /* The kernel map */
957 old_map = next;
958 continue;
959 }
960
961 /* Module must be in memory at the same address */
962 mi = find_module(old_map->dso->short_name, &modules);
963 if (!mi || mi->start != old_map->start) {
964 err = -EINVAL;
965 goto out;
966 }
967
968 old_map = next;
969 }
970out:
971 delete_modules(&modules);
972 return err;
973}
974
765/* 975/*
766 * If kallsyms is referenced by name then we look for kcore in the same 976 * If kallsyms is referenced by name then we look for filename in the same
767 * directory. 977 * directory.
768 */ 978 */
769static bool kcore_filename_from_kallsyms_filename(char *kcore_filename, 979static bool filename_from_kallsyms_filename(char *filename,
770 const char *kallsyms_filename) 980 const char *base_name,
981 const char *kallsyms_filename)
771{ 982{
772 char *name; 983 char *name;
773 984
774 strcpy(kcore_filename, kallsyms_filename); 985 strcpy(filename, kallsyms_filename);
775 name = strrchr(kcore_filename, '/'); 986 name = strrchr(filename, '/');
776 if (!name) 987 if (!name)
777 return false; 988 return false;
778 989
779 if (!strcmp(name, "/kallsyms")) { 990 name += 1;
780 strcpy(name, "/kcore"); 991
992 if (!strcmp(name, "kallsyms")) {
993 strcpy(name, base_name);
781 return true; 994 return true;
782 } 995 }
783 996
784 return false; 997 return false;
785} 998}
786 999
1000static int validate_kcore_modules(const char *kallsyms_filename,
1001 struct map *map)
1002{
1003 struct map_groups *kmaps = map__kmap(map)->kmaps;
1004 char modules_filename[PATH_MAX];
1005
1006 if (!filename_from_kallsyms_filename(modules_filename, "modules",
1007 kallsyms_filename))
1008 return -EINVAL;
1009
1010 if (do_validate_kcore_modules(modules_filename, map, kmaps))
1011 return -EINVAL;
1012
1013 return 0;
1014}
1015
1016struct kcore_mapfn_data {
1017 struct dso *dso;
1018 enum map_type type;
1019 struct list_head maps;
1020};
1021
1022static int kcore_mapfn(u64 start, u64 len, u64 pgoff, void *data)
1023{
1024 struct kcore_mapfn_data *md = data;
1025 struct map *map;
1026
1027 map = map__new2(start, md->dso, md->type);
1028 if (map == NULL)
1029 return -ENOMEM;
1030
1031 map->end = map->start + len;
1032 map->pgoff = pgoff;
1033
1034 list_add(&map->node, &md->maps);
1035
1036 return 0;
1037}
1038
787static int dso__load_kcore(struct dso *dso, struct map *map, 1039static int dso__load_kcore(struct dso *dso, struct map *map,
788 const char *kallsyms_filename) 1040 const char *kallsyms_filename)
789{ 1041{
@@ -800,8 +1052,12 @@ static int dso__load_kcore(struct dso *dso, struct map *map,
800 if (map != machine->vmlinux_maps[map->type]) 1052 if (map != machine->vmlinux_maps[map->type])
801 return -EINVAL; 1053 return -EINVAL;
802 1054
803 if (!kcore_filename_from_kallsyms_filename(kcore_filename, 1055 if (!filename_from_kallsyms_filename(kcore_filename, "kcore",
804 kallsyms_filename)) 1056 kallsyms_filename))
1057 return -EINVAL;
1058
1059 /* All modules must be present at their original addresses */
1060 if (validate_kcore_modules(kallsyms_filename, map))
805 return -EINVAL; 1061 return -EINVAL;
806 1062
807 md.dso = dso; 1063 md.dso = dso;
@@ -1188,6 +1444,105 @@ out:
1188 return err; 1444 return err;
1189} 1445}
1190 1446
1447static int find_matching_kcore(struct map *map, char *dir, size_t dir_sz)
1448{
1449 char kallsyms_filename[PATH_MAX];
1450 struct dirent *dent;
1451 int ret = -1;
1452 DIR *d;
1453
1454 d = opendir(dir);
1455 if (!d)
1456 return -1;
1457
1458 while (1) {
1459 dent = readdir(d);
1460 if (!dent)
1461 break;
1462 if (dent->d_type != DT_DIR)
1463 continue;
1464 scnprintf(kallsyms_filename, sizeof(kallsyms_filename),
1465 "%s/%s/kallsyms", dir, dent->d_name);
1466 if (!validate_kcore_modules(kallsyms_filename, map)) {
1467 strlcpy(dir, kallsyms_filename, dir_sz);
1468 ret = 0;
1469 break;
1470 }
1471 }
1472
1473 closedir(d);
1474
1475 return ret;
1476}
1477
1478static char *dso__find_kallsyms(struct dso *dso, struct map *map)
1479{
1480 u8 host_build_id[BUILD_ID_SIZE];
1481 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
1482 bool is_host = false;
1483 char path[PATH_MAX];
1484
1485 if (!dso->has_build_id) {
1486 /*
1487 * Last resort, if we don't have a build-id and couldn't find
1488 * any vmlinux file, try the running kernel kallsyms table.
1489 */
1490 goto proc_kallsyms;
1491 }
1492
1493 if (sysfs__read_build_id("/sys/kernel/notes", host_build_id,
1494 sizeof(host_build_id)) == 0)
1495 is_host = dso__build_id_equal(dso, host_build_id);
1496
1497 build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
1498
1499 /* Use /proc/kallsyms if possible */
1500 if (is_host) {
1501 DIR *d;
1502 int fd;
1503
1504 /* If no cached kcore go with /proc/kallsyms */
1505 scnprintf(path, sizeof(path), "%s/[kernel.kcore]/%s",
1506 buildid_dir, sbuild_id);
1507 d = opendir(path);
1508 if (!d)
1509 goto proc_kallsyms;
1510 closedir(d);
1511
1512 /*
1513 * Do not check the build-id cache, until we know we cannot use
1514 * /proc/kcore.
1515 */
1516 fd = open("/proc/kcore", O_RDONLY);
1517 if (fd != -1) {
1518 close(fd);
1519 /* If module maps match go with /proc/kallsyms */
1520 if (!validate_kcore_modules("/proc/kallsyms", map))
1521 goto proc_kallsyms;
1522 }
1523
1524 /* Find kallsyms in build-id cache with kcore */
1525 if (!find_matching_kcore(map, path, sizeof(path)))
1526 return strdup(path);
1527
1528 goto proc_kallsyms;
1529 }
1530
1531 scnprintf(path, sizeof(path), "%s/[kernel.kallsyms]/%s",
1532 buildid_dir, sbuild_id);
1533
1534 if (access(path, F_OK)) {
1535 pr_err("No kallsyms or vmlinux with build-id %s was found\n",
1536 sbuild_id);
1537 return NULL;
1538 }
1539
1540 return strdup(path);
1541
1542proc_kallsyms:
1543 return strdup("/proc/kallsyms");
1544}
1545
1191static int dso__load_kernel_sym(struct dso *dso, struct map *map, 1546static int dso__load_kernel_sym(struct dso *dso, struct map *map,
1192 symbol_filter_t filter) 1547 symbol_filter_t filter)
1193{ 1548{
@@ -1214,7 +1569,7 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map,
1214 goto do_kallsyms; 1569 goto do_kallsyms;
1215 } 1570 }
1216 1571
1217 if (symbol_conf.vmlinux_name != NULL) { 1572 if (!symbol_conf.ignore_vmlinux && symbol_conf.vmlinux_name != NULL) {
1218 err = dso__load_vmlinux(dso, map, 1573 err = dso__load_vmlinux(dso, map,
1219 symbol_conf.vmlinux_name, filter); 1574 symbol_conf.vmlinux_name, filter);
1220 if (err > 0) { 1575 if (err > 0) {
@@ -1226,7 +1581,7 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map,
1226 return err; 1581 return err;
1227 } 1582 }
1228 1583
1229 if (vmlinux_path != NULL) { 1584 if (!symbol_conf.ignore_vmlinux && vmlinux_path != NULL) {
1230 err = dso__load_vmlinux_path(dso, map, filter); 1585 err = dso__load_vmlinux_path(dso, map, filter);
1231 if (err > 0) 1586 if (err > 0)
1232 return err; 1587 return err;
@@ -1236,51 +1591,11 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map,
1236 if (symbol_conf.symfs[0] != 0) 1591 if (symbol_conf.symfs[0] != 0)
1237 return -1; 1592 return -1;
1238 1593
1239 /* 1594 kallsyms_allocated_filename = dso__find_kallsyms(dso, map);
1240 * Say the kernel DSO was created when processing the build-id header table, 1595 if (!kallsyms_allocated_filename)
1241 * we have a build-id, so check if it is the same as the running kernel, 1596 return -1;
1242 * using it if it is.
1243 */
1244 if (dso->has_build_id) {
1245 u8 kallsyms_build_id[BUILD_ID_SIZE];
1246 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
1247
1248 if (sysfs__read_build_id("/sys/kernel/notes", kallsyms_build_id,
1249 sizeof(kallsyms_build_id)) == 0) {
1250 if (dso__build_id_equal(dso, kallsyms_build_id)) {
1251 kallsyms_filename = "/proc/kallsyms";
1252 goto do_kallsyms;
1253 }
1254 }
1255 /*
1256 * Now look if we have it on the build-id cache in
1257 * $HOME/.debug/[kernel.kallsyms].
1258 */
1259 build_id__sprintf(dso->build_id, sizeof(dso->build_id),
1260 sbuild_id);
1261
1262 if (asprintf(&kallsyms_allocated_filename,
1263 "%s/.debug/[kernel.kallsyms]/%s",
1264 getenv("HOME"), sbuild_id) == -1) {
1265 pr_err("Not enough memory for kallsyms file lookup\n");
1266 return -1;
1267 }
1268
1269 kallsyms_filename = kallsyms_allocated_filename;
1270 1597
1271 if (access(kallsyms_filename, F_OK)) { 1598 kallsyms_filename = kallsyms_allocated_filename;
1272 pr_err("No kallsyms or vmlinux with build-id %s "
1273 "was found\n", sbuild_id);
1274 free(kallsyms_allocated_filename);
1275 return -1;
1276 }
1277 } else {
1278 /*
1279 * Last resort, if we don't have a build-id and couldn't find
1280 * any vmlinux file, try the running kernel kallsyms table.
1281 */
1282 kallsyms_filename = "/proc/kallsyms";
1283 }
1284 1599
1285do_kallsyms: 1600do_kallsyms:
1286 err = dso__load_kallsyms(dso, kallsyms_filename, map, filter); 1601 err = dso__load_kallsyms(dso, kallsyms_filename, map, filter);
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index fd5b70ea2981..07de8fea2f48 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -13,7 +13,7 @@
13#include <libgen.h> 13#include <libgen.h>
14#include "build-id.h" 14#include "build-id.h"
15 15
16#ifdef LIBELF_SUPPORT 16#ifdef HAVE_LIBELF_SUPPORT
17#include <libelf.h> 17#include <libelf.h>
18#include <gelf.h> 18#include <gelf.h>
19#endif 19#endif
@@ -21,7 +21,7 @@
21 21
22#include "dso.h" 22#include "dso.h"
23 23
24#ifdef HAVE_CPLUS_DEMANGLE 24#ifdef HAVE_CPLUS_DEMANGLE_SUPPORT
25extern char *cplus_demangle(const char *, int); 25extern char *cplus_demangle(const char *, int);
26 26
27static inline char *bfd_demangle(void __maybe_unused *v, const char *c, int i) 27static inline char *bfd_demangle(void __maybe_unused *v, const char *c, int i)
@@ -46,7 +46,7 @@ static inline char *bfd_demangle(void __maybe_unused *v,
46 * libelf 0.8.x and earlier do not support ELF_C_READ_MMAP; 46 * libelf 0.8.x and earlier do not support ELF_C_READ_MMAP;
47 * for newer versions we can use mmap to reduce memory usage: 47 * for newer versions we can use mmap to reduce memory usage:
48 */ 48 */
49#ifdef LIBELF_MMAP 49#ifdef HAVE_LIBELF_MMAP_SUPPORT
50# define PERF_ELF_C_READ_MMAP ELF_C_READ_MMAP 50# define PERF_ELF_C_READ_MMAP ELF_C_READ_MMAP
51#else 51#else
52# define PERF_ELF_C_READ_MMAP ELF_C_READ 52# define PERF_ELF_C_READ_MMAP ELF_C_READ
@@ -85,6 +85,7 @@ struct symbol_conf {
85 unsigned short priv_size; 85 unsigned short priv_size;
86 unsigned short nr_events; 86 unsigned short nr_events;
87 bool try_vmlinux_path, 87 bool try_vmlinux_path,
88 ignore_vmlinux,
88 show_kernel_path, 89 show_kernel_path,
89 use_modules, 90 use_modules,
90 sort_by_name, 91 sort_by_name,
@@ -178,7 +179,7 @@ struct symsrc {
178 int fd; 179 int fd;
179 enum dso_binary_type type; 180 enum dso_binary_type type;
180 181
181#ifdef LIBELF_SUPPORT 182#ifdef HAVE_LIBELF_SUPPORT
182 Elf *elf; 183 Elf *elf;
183 GElf_Ehdr ehdr; 184 GElf_Ehdr ehdr;
184 185
@@ -222,6 +223,9 @@ int sysfs__read_build_id(const char *filename, void *bf, size_t size);
222int kallsyms__parse(const char *filename, void *arg, 223int kallsyms__parse(const char *filename, void *arg,
223 int (*process_symbol)(void *arg, const char *name, 224 int (*process_symbol)(void *arg, const char *name,
224 char type, u64 start)); 225 char type, u64 start));
226int modules__parse(const char *filename, void *arg,
227 int (*process_module)(void *arg, const char *name,
228 u64 start));
225int filename__read_debuglink(const char *filename, char *debuglink, 229int filename__read_debuglink(const char *filename, char *debuglink,
226 size_t size); 230 size_t size);
227 231
@@ -252,4 +256,21 @@ typedef int (*mapfn_t)(u64 start, u64 len, u64 pgoff, void *data);
252int file__read_maps(int fd, bool exe, mapfn_t mapfn, void *data, 256int file__read_maps(int fd, bool exe, mapfn_t mapfn, void *data,
253 bool *is_64_bit); 257 bool *is_64_bit);
254 258
259#define PERF_KCORE_EXTRACT "/tmp/perf-kcore-XXXXXX"
260
261struct kcore_extract {
262 char *kcore_filename;
263 u64 addr;
264 u64 offs;
265 u64 len;
266 char extract_filename[sizeof(PERF_KCORE_EXTRACT)];
267 int fd;
268};
269
270int kcore_extract__create(struct kcore_extract *kce);
271void kcore_extract__delete(struct kcore_extract *kce);
272
273int kcore_copy(const char *from_dir, const char *to_dir);
274int compare_proc_modules(const char *from, const char *to);
275
255#endif /* __PERF_SYMBOL */ 276#endif /* __PERF_SYMBOL */
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index e9e1c03f927d..6681f71f2f95 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -120,42 +120,6 @@ raw_field_value(struct event_format *event, const char *name, void *data)
120 return val; 120 return val;
121} 121}
122 122
123void *raw_field_ptr(struct event_format *event, const char *name, void *data)
124{
125 struct format_field *field;
126
127 field = pevent_find_any_field(event, name);
128 if (!field)
129 return NULL;
130
131 if (field->flags & FIELD_IS_DYNAMIC) {
132 int offset;
133
134 offset = *(int *)(data + field->offset);
135 offset &= 0xffff;
136
137 return data + offset;
138 }
139
140 return data + field->offset;
141}
142
143int trace_parse_common_type(struct pevent *pevent, void *data)
144{
145 struct pevent_record record;
146
147 record.data = data;
148 return pevent_data_type(pevent, &record);
149}
150
151int trace_parse_common_pid(struct pevent *pevent, void *data)
152{
153 struct pevent_record record;
154
155 record.data = data;
156 return pevent_data_pid(pevent, &record);
157}
158
159unsigned long long read_size(struct event_format *event, void *ptr, int size) 123unsigned long long read_size(struct event_format *event, void *ptr, int size)
160{ 124{
161 return pevent_read_number(event->pevent, ptr, size); 125 return pevent_read_number(event->pevent, ptr, size);
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index fafe1a40444a..04df63114109 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -11,8 +11,6 @@ union perf_event;
11struct perf_tool; 11struct perf_tool;
12struct thread; 12struct thread;
13 13
14extern struct pevent *perf_pevent;
15
16int bigendian(void); 14int bigendian(void);
17 15
18struct pevent *read_trace_init(int file_bigendian, int host_bigendian); 16struct pevent *read_trace_init(int file_bigendian, int host_bigendian);
@@ -23,26 +21,19 @@ int parse_ftrace_file(struct pevent *pevent, char *buf, unsigned long size);
23int parse_event_file(struct pevent *pevent, 21int parse_event_file(struct pevent *pevent,
24 char *buf, unsigned long size, char *sys); 22 char *buf, unsigned long size, char *sys);
25 23
26struct pevent_record *trace_peek_data(struct pevent *pevent, int cpu);
27
28unsigned long long 24unsigned long long
29raw_field_value(struct event_format *event, const char *name, void *data); 25raw_field_value(struct event_format *event, const char *name, void *data);
30void *raw_field_ptr(struct event_format *event, const char *name, void *data);
31 26
32void parse_proc_kallsyms(struct pevent *pevent, char *file, unsigned int size); 27void parse_proc_kallsyms(struct pevent *pevent, char *file, unsigned int size);
33void parse_ftrace_printk(struct pevent *pevent, char *file, unsigned int size); 28void parse_ftrace_printk(struct pevent *pevent, char *file, unsigned int size);
34 29
35ssize_t trace_report(int fd, struct pevent **pevent, bool repipe); 30ssize_t trace_report(int fd, struct pevent **pevent, bool repipe);
36 31
37int trace_parse_common_type(struct pevent *pevent, void *data);
38int trace_parse_common_pid(struct pevent *pevent, void *data);
39
40struct event_format *trace_find_next_event(struct pevent *pevent, 32struct event_format *trace_find_next_event(struct pevent *pevent,
41 struct event_format *event); 33 struct event_format *event);
42unsigned long long read_size(struct event_format *event, void *ptr, int size); 34unsigned long long read_size(struct event_format *event, void *ptr, int size);
43unsigned long long eval_flag(const char *flag); 35unsigned long long eval_flag(const char *flag);
44 36
45struct pevent_record *trace_read_data(struct pevent *pevent, int cpu);
46int read_tracing_data(int fd, struct list_head *pattrs); 37int read_tracing_data(int fd, struct list_head *pattrs);
47 38
48struct tracing_data { 39struct tracing_data {
diff --git a/tools/perf/util/unwind.h b/tools/perf/util/unwind.h
index cb6bc503a792..ec0c71a2ca2e 100644
--- a/tools/perf/util/unwind.h
+++ b/tools/perf/util/unwind.h
@@ -13,7 +13,7 @@ struct unwind_entry {
13 13
14typedef int (*unwind_entry_cb_t)(struct unwind_entry *entry, void *arg); 14typedef int (*unwind_entry_cb_t)(struct unwind_entry *entry, void *arg);
15 15
16#ifdef LIBUNWIND_SUPPORT 16#ifdef HAVE_LIBUNWIND_SUPPORT
17int unwind__get_entries(unwind_entry_cb_t cb, void *arg, 17int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
18 struct machine *machine, 18 struct machine *machine,
19 struct thread *thread, 19 struct thread *thread,
@@ -31,5 +31,5 @@ unwind__get_entries(unwind_entry_cb_t cb __maybe_unused,
31{ 31{
32 return 0; 32 return 0;
33} 33}
34#endif /* LIBUNWIND_SUPPORT */ 34#endif /* HAVE_LIBUNWIND_SUPPORT */
35#endif /* __UNWIND_H */ 35#endif /* __UNWIND_H */
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 6d17b18e915d..8dc8cf39f4ed 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -1,7 +1,7 @@
1#include "../perf.h" 1#include "../perf.h"
2#include "util.h" 2#include "util.h"
3#include <sys/mman.h> 3#include <sys/mman.h>
4#ifdef BACKTRACE_SUPPORT 4#ifdef HAVE_BACKTRACE_SUPPORT
5#include <execinfo.h> 5#include <execinfo.h>
6#endif 6#endif
7#include <stdio.h> 7#include <stdio.h>
@@ -55,17 +55,20 @@ int mkdir_p(char *path, mode_t mode)
55 return (stat(path, &st) && mkdir(path, mode)) ? -1 : 0; 55 return (stat(path, &st) && mkdir(path, mode)) ? -1 : 0;
56} 56}
57 57
58static int slow_copyfile(const char *from, const char *to) 58static int slow_copyfile(const char *from, const char *to, mode_t mode)
59{ 59{
60 int err = 0; 60 int err = -1;
61 char *line = NULL; 61 char *line = NULL;
62 size_t n; 62 size_t n;
63 FILE *from_fp = fopen(from, "r"), *to_fp; 63 FILE *from_fp = fopen(from, "r"), *to_fp;
64 mode_t old_umask;
64 65
65 if (from_fp == NULL) 66 if (from_fp == NULL)
66 goto out; 67 goto out;
67 68
69 old_umask = umask(mode ^ 0777);
68 to_fp = fopen(to, "w"); 70 to_fp = fopen(to, "w");
71 umask(old_umask);
69 if (to_fp == NULL) 72 if (to_fp == NULL)
70 goto out_fclose_from; 73 goto out_fclose_from;
71 74
@@ -82,7 +85,7 @@ out:
82 return err; 85 return err;
83} 86}
84 87
85int copyfile(const char *from, const char *to) 88int copyfile_mode(const char *from, const char *to, mode_t mode)
86{ 89{
87 int fromfd, tofd; 90 int fromfd, tofd;
88 struct stat st; 91 struct stat st;
@@ -93,13 +96,13 @@ int copyfile(const char *from, const char *to)
93 goto out; 96 goto out;
94 97
95 if (st.st_size == 0) /* /proc? do it slowly... */ 98 if (st.st_size == 0) /* /proc? do it slowly... */
96 return slow_copyfile(from, to); 99 return slow_copyfile(from, to, mode);
97 100
98 fromfd = open(from, O_RDONLY); 101 fromfd = open(from, O_RDONLY);
99 if (fromfd < 0) 102 if (fromfd < 0)
100 goto out; 103 goto out;
101 104
102 tofd = creat(to, 0755); 105 tofd = creat(to, mode);
103 if (tofd < 0) 106 if (tofd < 0)
104 goto out_close_from; 107 goto out_close_from;
105 108
@@ -121,6 +124,11 @@ out:
121 return err; 124 return err;
122} 125}
123 126
127int copyfile(const char *from, const char *to)
128{
129 return copyfile_mode(from, to, 0755);
130}
131
124unsigned long convert_unit(unsigned long value, char *unit) 132unsigned long convert_unit(unsigned long value, char *unit)
125{ 133{
126 *unit = ' '; 134 *unit = ' ';
@@ -204,7 +212,7 @@ int hex2u64(const char *ptr, u64 *long_val)
204} 212}
205 213
206/* Obtain a backtrace and print it to stdout. */ 214/* Obtain a backtrace and print it to stdout. */
207#ifdef BACKTRACE_SUPPORT 215#ifdef HAVE_BACKTRACE_SUPPORT
208void dump_stack(void) 216void dump_stack(void)
209{ 217{
210 void *array[16]; 218 void *array[16];
@@ -361,3 +369,28 @@ int parse_nsec_time(const char *str, u64 *ptime)
361 *ptime = time_sec * NSEC_PER_SEC + time_nsec; 369 *ptime = time_sec * NSEC_PER_SEC + time_nsec;
362 return 0; 370 return 0;
363} 371}
372
373unsigned long parse_tag_value(const char *str, struct parse_tag *tags)
374{
375 struct parse_tag *i = tags;
376
377 while (i->tag) {
378 char *s;
379
380 s = strchr(str, i->tag);
381 if (s) {
382 unsigned long int value;
383 char *endptr;
384
385 value = strtoul(str, &endptr, 10);
386 if (s != endptr)
387 break;
388
389 value *= i->mult;
390 return value;
391 }
392 i++;
393 }
394
395 return (unsigned long) -1;
396}
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index a53535949043..42dfba70fbfc 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -128,6 +128,8 @@ void put_tracing_file(char *file);
128#endif 128#endif
129#endif 129#endif
130 130
131#define PERF_GTK_DSO "libperf-gtk.so"
132
131/* General helper functions */ 133/* General helper functions */
132extern void usage(const char *err) NORETURN; 134extern void usage(const char *err) NORETURN;
133extern void die(const char *err, ...) NORETURN __attribute__((format (printf, 1, 2))); 135extern void die(const char *err, ...) NORETURN __attribute__((format (printf, 1, 2)));
@@ -241,6 +243,7 @@ static inline int sane_case(int x, int high)
241 243
242int mkdir_p(char *path, mode_t mode); 244int mkdir_p(char *path, mode_t mode);
243int copyfile(const char *from, const char *to); 245int copyfile(const char *from, const char *to);
246int copyfile_mode(const char *from, const char *to, mode_t mode);
244 247
245s64 perf_atoll(const char *str); 248s64 perf_atoll(const char *str);
246char **argv_split(const char *str, int *argcp); 249char **argv_split(const char *str, int *argcp);
@@ -270,6 +273,13 @@ bool is_power_of_2(unsigned long n)
270 return (n != 0 && ((n & (n - 1)) == 0)); 273 return (n != 0 && ((n & (n - 1)) == 0));
271} 274}
272 275
276static inline unsigned next_pow2(unsigned x)
277{
278 if (!x)
279 return 1;
280 return 1ULL << (32 - __builtin_clz(x - 1));
281}
282
273size_t hex_width(u64 v); 283size_t hex_width(u64 v);
274int hex2u64(const char *ptr, u64 *val); 284int hex2u64(const char *ptr, u64 *val);
275 285
@@ -281,4 +291,18 @@ void dump_stack(void);
281extern unsigned int page_size; 291extern unsigned int page_size;
282 292
283void get_term_dimensions(struct winsize *ws); 293void get_term_dimensions(struct winsize *ws);
294
295struct parse_tag {
296 char tag;
297 int mult;
298};
299
300unsigned long parse_tag_value(const char *str, struct parse_tag *tags);
301
302#define SRCLINE_UNKNOWN ((char *) "??:0")
303
304struct dso;
305
306char *get_srcline(struct dso *dso, unsigned long addr);
307void free_srcline(char *srcline);
284#endif /* GIT_COMPAT_UTIL_H */ 308#endif /* GIT_COMPAT_UTIL_H */
diff --git a/tools/scripts/Makefile.include b/tools/scripts/Makefile.include
index 0d0506d55c71..ee76544deecb 100644
--- a/tools/scripts/Makefile.include
+++ b/tools/scripts/Makefile.include
@@ -59,21 +59,22 @@ QUIET_SUBDIR0 = +$(MAKE) $(COMMAND_O) -C # space to separate -C and subdir
59QUIET_SUBDIR1 = 59QUIET_SUBDIR1 =
60 60
61ifneq ($(findstring $(MAKEFLAGS),s),s) 61ifneq ($(findstring $(MAKEFLAGS),s),s)
62ifneq ($(V),1) 62 ifneq ($(V),1)
63 QUIET_CC = @echo ' ' CC $@; 63 QUIET_CC = @echo ' CC '$@;
64 QUIET_AR = @echo ' ' AR $@; 64 QUIET_AR = @echo ' AR '$@;
65 QUIET_LINK = @echo ' ' LINK $@; 65 QUIET_LINK = @echo ' LINK '$@;
66 QUIET_MKDIR = @echo ' ' MKDIR $@; 66 QUIET_MKDIR = @echo ' MKDIR '$@;
67 QUIET_GEN = @echo ' ' GEN $@; 67 QUIET_GEN = @echo ' GEN '$@;
68 QUIET_SUBDIR0 = +@subdir= 68 QUIET_SUBDIR0 = +@subdir=
69 QUIET_SUBDIR1 = ;$(NO_SUBDIR) echo ' ' SUBDIR $$subdir; \ 69 QUIET_SUBDIR1 = ;$(NO_SUBDIR) \
70 echo ' SUBDIR '$$subdir; \
70 $(MAKE) $(PRINT_DIR) -C $$subdir 71 $(MAKE) $(PRINT_DIR) -C $$subdir
71 QUIET_FLEX = @echo ' ' FLEX $@; 72 QUIET_FLEX = @echo ' FLEX '$@;
72 QUIET_BISON = @echo ' ' BISON $@; 73 QUIET_BISON = @echo ' BISON '$@;
73 74
74 descend = \ 75 descend = \
75 +@echo ' ' DESCEND $(1); \ 76 +@echo ' DESCEND '$(1); \
76 mkdir -p $(OUTPUT)$(1) && \ 77 mkdir -p $(OUTPUT)$(1) && \
77 $(MAKE) $(COMMAND_O) subdir=$(if $(subdir),$(subdir)/$(1),$(1)) $(PRINT_DIR) -C $(1) $(2) 78 $(MAKE) $(COMMAND_O) subdir=$(if $(subdir),$(subdir)/$(1),$(1)) $(PRINT_DIR) -C $(1) $(2)
78endif 79 endif
79endif 80endif