aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/Documentation/Makefile29
-rw-r--r--tools/perf/Documentation/asciidoctor-extensions.rb29
-rw-r--r--tools/perf/Documentation/perf-buildid-cache.txt7
-rw-r--r--tools/perf/Documentation/perf-mem.txt41
-rw-r--r--tools/perf/Documentation/perf-stat.txt16
-rw-r--r--tools/perf/Documentation/perf.data-file-format.txt10
-rw-r--r--tools/perf/Makefile.config14
-rw-r--r--tools/perf/Makefile.perf10
-rw-r--r--tools/perf/arch/arm/tests/dwarf-unwind.c2
-rw-r--r--tools/perf/arch/arm64/tests/dwarf-unwind.c2
-rw-r--r--tools/perf/arch/powerpc/tests/dwarf-unwind.c2
-rw-r--r--tools/perf/arch/powerpc/util/skip-callchain-idx.c3
-rw-r--r--tools/perf/arch/s390/util/auxtrace.c1
-rw-r--r--tools/perf/arch/s390/util/header.c18
-rw-r--r--tools/perf/arch/x86/tests/dwarf-unwind.c2
-rw-r--r--tools/perf/arch/x86/util/Build2
-rw-r--r--tools/perf/arch/x86/util/event.c76
-rw-r--r--tools/perf/arch/x86/util/machine.c103
-rw-r--r--tools/perf/bench/numa.c2
-rw-r--r--tools/perf/builtin-annotate.c9
-rw-r--r--tools/perf/builtin-buildid-cache.c81
-rw-r--r--tools/perf/builtin-inject.c4
-rw-r--r--tools/perf/builtin-kallsyms.c2
-rw-r--r--tools/perf/builtin-kmem.c6
-rw-r--r--tools/perf/builtin-report.c27
-rw-r--r--tools/perf/builtin-script.c56
-rw-r--r--tools/perf/builtin-stat.c132
-rw-r--r--tools/perf/builtin-timechart.c8
-rw-r--r--tools/perf/builtin-top.c9
-rw-r--r--tools/perf/builtin-trace.c11
-rwxr-xr-xtools/perf/check-headers.sh30
-rw-r--r--tools/perf/examples/bpf/5sec.c49
-rw-r--r--tools/perf/examples/bpf/empty.c3
-rw-r--r--tools/perf/include/bpf/bpf.h13
-rw-r--r--tools/perf/perf.c24
-rw-r--r--tools/perf/pmu-events/arch/s390/mapfile.csv10
-rw-r--r--tools/perf/pmu-events/arch/x86/mapfile.csv1
-rw-r--r--tools/perf/tests/attr/test-record-group-sampling3
-rw-r--r--tools/perf/tests/builtin-test.c9
-rw-r--r--tools/perf/tests/code-reading.c5
-rw-r--r--tools/perf/tests/hists_common.c6
-rw-r--r--tools/perf/tests/mmap-thread-lookup.c7
-rw-r--r--tools/perf/tests/parse-events.c22
-rwxr-xr-xtools/perf/tests/shell/record+probe_libc_inet_pton.sh16
-rw-r--r--tools/perf/tests/topology.c30
-rw-r--r--tools/perf/tests/vmlinux-kallsyms.c20
-rwxr-xr-xtools/perf/trace/beauty/prctl_option.sh2
-rw-r--r--tools/perf/ui/browsers/annotate.c8
-rw-r--r--tools/perf/ui/browsers/map.c2
-rw-r--r--tools/perf/ui/stdio/hist.c3
-rw-r--r--tools/perf/util/Build2
-rw-r--r--tools/perf/util/annotate.c60
-rw-r--r--tools/perf/util/annotate.h11
-rw-r--r--tools/perf/util/auxtrace.c12
-rw-r--r--tools/perf/util/bpf-loader.c6
-rw-r--r--tools/perf/util/build-id.c4
-rw-r--r--tools/perf/util/config.c16
-rw-r--r--tools/perf/util/config.h1
-rw-r--r--tools/perf/util/cs-etm-decoder/cs-etm-decoder.c12
-rw-r--r--tools/perf/util/cs-etm.c32
-rw-r--r--tools/perf/util/db-export.c7
-rw-r--r--tools/perf/util/dso.c34
-rw-r--r--tools/perf/util/dso.h37
-rw-r--r--tools/perf/util/env.c31
-rw-r--r--tools/perf/util/env.h3
-rw-r--r--tools/perf/util/event.c73
-rw-r--r--tools/perf/util/event.h8
-rw-r--r--tools/perf/util/evlist.c15
-rw-r--r--tools/perf/util/evlist.h3
-rw-r--r--tools/perf/util/evsel.c20
-rw-r--r--tools/perf/util/evsel.h2
-rw-r--r--tools/perf/util/genelf.c2
-rw-r--r--tools/perf/util/intel-bts.c3
-rw-r--r--tools/perf/util/intel-pt-decoder/insn.h18
-rw-r--r--tools/perf/util/intel-pt.c8
-rw-r--r--tools/perf/util/llvm-utils.c19
-rw-r--r--tools/perf/util/machine.c383
-rw-r--r--tools/perf/util/machine.h72
-rw-r--r--tools/perf/util/map.c121
-rw-r--r--tools/perf/util/map.h74
-rw-r--r--tools/perf/util/parse-events.c205
-rw-r--r--tools/perf/util/parse-events.h7
-rw-r--r--tools/perf/util/parse-events.y8
-rw-r--r--tools/perf/util/pmu.c22
-rw-r--r--tools/perf/util/probe-event.c29
-rw-r--r--tools/perf/util/probe-file.c3
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c2
-rw-r--r--tools/perf/util/session.c13
-rw-r--r--tools/perf/util/sort.c10
-rw-r--r--tools/perf/util/sort.h4
-rw-r--r--tools/perf/util/srcline.c1
-rw-r--r--tools/perf/util/stat.h3
-rw-r--r--tools/perf/util/symbol-elf.c494
-rw-r--r--tools/perf/util/symbol-minimal.c3
-rw-r--r--tools/perf/util/symbol.c264
-rw-r--r--tools/perf/util/symbol.h24
-rw-r--r--tools/perf/util/symbol_fprintf.c4
-rw-r--r--tools/perf/util/thread.c35
-rw-r--r--tools/perf/util/thread.h13
-rw-r--r--tools/perf/util/trace-event-info.c11
-rw-r--r--tools/perf/util/trace-event.c8
-rw-r--r--tools/perf/util/unwind-libdw.c23
-rw-r--r--tools/perf/util/unwind-libunwind-local.c19
-rw-r--r--tools/perf/util/util.c34
-rw-r--r--tools/perf/util/util.h4
-rw-r--r--tools/perf/util/vdso.c6
106 files changed, 2208 insertions, 1107 deletions
diff --git a/tools/perf/Documentation/Makefile b/tools/perf/Documentation/Makefile
index db11478e30b4..42261a9b280e 100644
--- a/tools/perf/Documentation/Makefile
+++ b/tools/perf/Documentation/Makefile
@@ -47,7 +47,8 @@ man5dir=$(mandir)/man5
47man7dir=$(mandir)/man7 47man7dir=$(mandir)/man7
48 48
49ASCIIDOC=asciidoc 49ASCIIDOC=asciidoc
50ASCIIDOC_EXTRA = --unsafe 50ASCIIDOC_EXTRA = --unsafe -f asciidoc.conf
51ASCIIDOC_HTML = xhtml11
51MANPAGE_XSL = manpage-normal.xsl 52MANPAGE_XSL = manpage-normal.xsl
52XMLTO_EXTRA = 53XMLTO_EXTRA =
53INSTALL?=install 54INSTALL?=install
@@ -55,6 +56,14 @@ RM ?= rm -f
55DOC_REF = origin/man 56DOC_REF = origin/man
56HTML_REF = origin/html 57HTML_REF = origin/html
57 58
59ifdef USE_ASCIIDOCTOR
60ASCIIDOC = asciidoctor
61ASCIIDOC_EXTRA = -a compat-mode
62ASCIIDOC_EXTRA += -I. -rasciidoctor-extensions
63ASCIIDOC_EXTRA += -a mansource="perf" -a manmanual="perf Manual"
64ASCIIDOC_HTML = xhtml5
65endif
66
58infodir?=$(prefix)/share/info 67infodir?=$(prefix)/share/info
59MAKEINFO=makeinfo 68MAKEINFO=makeinfo
60INSTALL_INFO=install-info 69INSTALL_INFO=install-info
@@ -73,10 +82,12 @@ ifeq ($(_tmp_tool_path),)
73 missing_tools = $(ASCIIDOC) 82 missing_tools = $(ASCIIDOC)
74endif 83endif
75 84
85ifndef USE_ASCIIDOCTOR
76_tmp_tool_path := $(call get-executable,$(XMLTO)) 86_tmp_tool_path := $(call get-executable,$(XMLTO))
77ifeq ($(_tmp_tool_path),) 87ifeq ($(_tmp_tool_path),)
78 missing_tools += $(XMLTO) 88 missing_tools += $(XMLTO)
79endif 89endif
90endif
80 91
81# 92#
82# For asciidoc ... 93# For asciidoc ...
@@ -264,9 +275,17 @@ clean:
264 275
265$(MAN_HTML): $(OUTPUT)%.html : %.txt 276$(MAN_HTML): $(OUTPUT)%.html : %.txt
266 $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \ 277 $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \
267 $(ASCIIDOC) -b xhtml11 -d manpage -f asciidoc.conf \ 278 $(ASCIIDOC) -b $(ASCIIDOC_HTML) -d manpage \
279 $(ASCIIDOC_EXTRA) -aperf_version=$(PERF_VERSION) -o $@+ $< && \
280 mv $@+ $@
281
282ifdef USE_ASCIIDOCTOR
283$(OUTPUT)%.1 $(OUTPUT)%.5 $(OUTPUT)%.7 : $(OUTPUT)%.txt
284 $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \
285 $(ASCIIDOC) -b manpage -d manpage \
268 $(ASCIIDOC_EXTRA) -aperf_version=$(PERF_VERSION) -o $@+ $< && \ 286 $(ASCIIDOC_EXTRA) -aperf_version=$(PERF_VERSION) -o $@+ $< && \
269 mv $@+ $@ 287 mv $@+ $@
288endif
270 289
271$(OUTPUT)%.1 $(OUTPUT)%.5 $(OUTPUT)%.7 : $(OUTPUT)%.xml 290$(OUTPUT)%.1 $(OUTPUT)%.5 $(OUTPUT)%.7 : $(OUTPUT)%.xml
272 $(QUIET_XMLTO)$(RM) $@ && \ 291 $(QUIET_XMLTO)$(RM) $@ && \
@@ -274,7 +293,7 @@ $(OUTPUT)%.1 $(OUTPUT)%.5 $(OUTPUT)%.7 : $(OUTPUT)%.xml
274 293
275$(OUTPUT)%.xml : %.txt 294$(OUTPUT)%.xml : %.txt
276 $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \ 295 $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \
277 $(ASCIIDOC) -b docbook -d manpage -f asciidoc.conf \ 296 $(ASCIIDOC) -b docbook -d manpage \
278 $(ASCIIDOC_EXTRA) -aperf_version=$(PERF_VERSION) -o $@+ $< && \ 297 $(ASCIIDOC_EXTRA) -aperf_version=$(PERF_VERSION) -o $@+ $< && \
279 mv $@+ $@ 298 mv $@+ $@
280 299
@@ -321,13 +340,13 @@ howto-index.txt: howto-index.sh $(wildcard howto/*.txt)
321 mv $@+ $@ 340 mv $@+ $@
322 341
323$(patsubst %,%.html,$(ARTICLES)) : %.html : %.txt 342$(patsubst %,%.html,$(ARTICLES)) : %.html : %.txt
324 $(QUIET_ASCIIDOC)$(ASCIIDOC) -b xhtml11 $*.txt 343 $(QUIET_ASCIIDOC)$(ASCIIDOC) -b $(ASCIIDOC_HTML) $*.txt
325 344
326WEBDOC_DEST = /pub/software/tools/perf/docs 345WEBDOC_DEST = /pub/software/tools/perf/docs
327 346
328$(patsubst %.txt,%.html,$(wildcard howto/*.txt)): %.html : %.txt 347$(patsubst %.txt,%.html,$(wildcard howto/*.txt)): %.html : %.txt
329 $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \ 348 $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \
330 sed -e '1,/^$$/d' $< | $(ASCIIDOC) -b xhtml11 - >$@+ && \ 349 sed -e '1,/^$$/d' $< | $(ASCIIDOC) -b $(ASCIIDOC_HTML) - >$@+ && \
331 mv $@+ $@ 350 mv $@+ $@
332 351
333# UNIMPLEMENTED 352# UNIMPLEMENTED
diff --git a/tools/perf/Documentation/asciidoctor-extensions.rb b/tools/perf/Documentation/asciidoctor-extensions.rb
new file mode 100644
index 000000000000..d148fe95c0c4
--- /dev/null
+++ b/tools/perf/Documentation/asciidoctor-extensions.rb
@@ -0,0 +1,29 @@
1require 'asciidoctor'
2require 'asciidoctor/extensions'
3
4module Perf
5 module Documentation
6 class LinkPerfProcessor < Asciidoctor::Extensions::InlineMacroProcessor
7 use_dsl
8
9 named :chrome
10
11 def process(parent, target, attrs)
12 if parent.document.basebackend? 'html'
13 %(<a href="#{target}.html">#{target}(#{attrs[1]})</a>\n)
14 elsif parent.document.basebackend? 'manpage'
15 "#{target}(#{attrs[1]})"
16 elsif parent.document.basebackend? 'docbook'
17 "<citerefentry>\n" \
18 "<refentrytitle>#{target}</refentrytitle>" \
19 "<manvolnum>#{attrs[1]}</manvolnum>\n" \
20 "</citerefentry>\n"
21 end
22 end
23 end
24 end
25end
26
27Asciidoctor::Extensions.register do
28 inline_macro Perf::Documentation::LinkPerfProcessor, :linkperf
29end
diff --git a/tools/perf/Documentation/perf-buildid-cache.txt b/tools/perf/Documentation/perf-buildid-cache.txt
index 73c2650bd0db..f6de0952ff3c 100644
--- a/tools/perf/Documentation/perf-buildid-cache.txt
+++ b/tools/perf/Documentation/perf-buildid-cache.txt
@@ -48,6 +48,9 @@ OPTIONS
48--purge=:: 48--purge=::
49 Purge all cached binaries including older caches which have specified 49 Purge all cached binaries including older caches which have specified
50 path from the cache. 50 path from the cache.
51-P::
52--purge-all::
53 Purge all cached binaries. This will flush out entire cache.
51-M:: 54-M::
52--missing=:: 55--missing=::
53 List missing build ids in the cache for the specified file. 56 List missing build ids in the cache for the specified file.
@@ -59,7 +62,9 @@ OPTIONS
59 exactly same build-id, that is replaced by new one. It can be used 62 exactly same build-id, that is replaced by new one. It can be used
60 to update kallsyms and kernel dso to vmlinux in order to support 63 to update kallsyms and kernel dso to vmlinux in order to support
61 annotation. 64 annotation.
62 65-l::
66--list::
67 List all valid binaries from cache.
63-v:: 68-v::
64--verbose:: 69--verbose::
65 Be more verbose. 70 Be more verbose.
diff --git a/tools/perf/Documentation/perf-mem.txt b/tools/perf/Documentation/perf-mem.txt
index 8806ed5f3802..f8d2167cf3e7 100644
--- a/tools/perf/Documentation/perf-mem.txt
+++ b/tools/perf/Documentation/perf-mem.txt
@@ -28,29 +28,46 @@ OPTIONS
28<command>...:: 28<command>...::
29 Any command you can specify in a shell. 29 Any command you can specify in a shell.
30 30
31-i::
32--input=<file>::
33 Input file name.
34
31-f:: 35-f::
32--force:: 36--force::
33 Don't do ownership validation 37 Don't do ownership validation
34 38
35-t:: 39-t::
36--type=:: 40--type=<type>::
37 Select the memory operation type: load or store (default: load,store) 41 Select the memory operation type: load or store (default: load,store)
38 42
39-D:: 43-D::
40--dump-raw-samples=:: 44--dump-raw-samples::
41 Dump the raw decoded samples on the screen in a format that is easy to parse with 45 Dump the raw decoded samples on the screen in a format that is easy to parse with
42 one sample per line. 46 one sample per line.
43 47
44-x:: 48-x::
45--field-separator:: 49--field-separator=<separator>::
46 Specify the field separator used when dump raw samples (-D option). By default, 50 Specify the field separator used when dump raw samples (-D option). By default,
47 The separator is the space character. 51 The separator is the space character.
48 52
49-C:: 53-C::
50--cpu-list:: 54--cpu=<cpu>::
51 Restrict dump of raw samples to those provided via this option. Note that the same 55 Monitor only on the list of CPUs provided. Multiple CPUs can be provided as a
52 option can be passed in record mode. It will be interpreted the same way as perf 56 comma-separated list with no space: 0,1. Ranges of CPUs are specified with -: 0-2. Default
53 record. 57 is to monitor all CPUS.
58-U::
59--hide-unresolved::
60 Only display entries resolved to a symbol.
61
62-p::
63--phys-data::
64 Record/Report sample physical addresses
65
66RECORD OPTIONS
67--------------
68-e::
69--event <event>::
70 Event selector. Use 'perf mem record -e list' to list available events.
54 71
55-K:: 72-K::
56--all-kernel:: 73--all-kernel::
@@ -60,12 +77,12 @@ OPTIONS
60--all-user:: 77--all-user::
61 Configure all used events to run in user space. 78 Configure all used events to run in user space.
62 79
63--ldload:: 80-v::
64 Specify desired latency for loads event. 81--verbose::
82 Be more verbose (show counter open errors, etc)
65 83
66-p:: 84--ldlat <n>::
67--phys-data:: 85 Specify desired latency for loads event.
68 Record/Report sample physical addresses
69 86
70In addition, for report all perf report options are valid, and for record 87In addition, for report all perf report options are valid, and for record
71all perf record options. 88all perf record options.
diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index e6c3b4e555c2..3a822f308e6d 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -116,6 +116,22 @@ Do not aggregate counts across all monitored CPUs.
116print counts using a CSV-style output to make it easy to import directly into 116print counts using a CSV-style output to make it easy to import directly into
117spreadsheets. Columns are separated by the string specified in SEP. 117spreadsheets. Columns are separated by the string specified in SEP.
118 118
119--table:: Display time for each run (-r option), in a table format, e.g.:
120
121 $ perf stat --null -r 5 --table perf bench sched pipe
122
123 Performance counter stats for 'perf bench sched pipe' (5 runs):
124
125 # Table of individual measurements:
126 5.189 (-0.293) #
127 5.189 (-0.294) #
128 5.186 (-0.296) #
129 5.663 (+0.181) ##
130 6.186 (+0.703) ####
131
132 # Final result:
133 5.483 +- 0.198 seconds time elapsed ( +- 3.62% )
134
119-G name:: 135-G name::
120--cgroup name:: 136--cgroup name::
121monitor only in the container (cgroup) called "name". This option is available only 137monitor only in the container (cgroup) called "name". This option is available only
diff --git a/tools/perf/Documentation/perf.data-file-format.txt b/tools/perf/Documentation/perf.data-file-format.txt
index d00f0d51cab8..dfb218feaad9 100644
--- a/tools/perf/Documentation/perf.data-file-format.txt
+++ b/tools/perf/Documentation/perf.data-file-format.txt
@@ -111,8 +111,8 @@ A perf_header_string with the CPU architecture (uname -m)
111A structure defining the number of CPUs. 111A structure defining the number of CPUs.
112 112
113struct nr_cpus { 113struct nr_cpus {
114 uint32_t nr_cpus_online;
115 uint32_t nr_cpus_available; /* CPUs not yet onlined */ 114 uint32_t nr_cpus_available; /* CPUs not yet onlined */
115 uint32_t nr_cpus_online;
116}; 116};
117 117
118 HEADER_CPUDESC = 8, 118 HEADER_CPUDESC = 8,
@@ -153,10 +153,18 @@ struct {
153 HEADER_CPU_TOPOLOGY = 13, 153 HEADER_CPU_TOPOLOGY = 13,
154 154
155String lists defining the core and CPU threads topology. 155String lists defining the core and CPU threads topology.
156The string lists are followed by a variable length array
157which contains core_id and socket_id of each cpu.
158The number of entries can be determined by the size of the
159section minus the sizes of both string lists.
156 160
157struct { 161struct {
158 struct perf_header_string_list cores; /* Variable length */ 162 struct perf_header_string_list cores; /* Variable length */
159 struct perf_header_string_list threads; /* Variable length */ 163 struct perf_header_string_list threads; /* Variable length */
164 struct {
165 uint32_t core_id;
166 uint32_t socket_id;
167 } cpus[nr]; /* Variable length records */
160}; 168};
161 169
162Example: 170Example:
diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
index ae7dc46e8f8a..b5ac356ba323 100644
--- a/tools/perf/Makefile.config
+++ b/tools/perf/Makefile.config
@@ -885,6 +885,8 @@ endif
885 885
886# Among the variables below, these: 886# Among the variables below, these:
887# perfexecdir 887# perfexecdir
888# perf_include_dir
889# perf_examples_dir
888# template_dir 890# template_dir
889# mandir 891# mandir
890# infodir 892# infodir
@@ -904,6 +906,8 @@ bindir = $(abspath $(prefix)/$(bindir_relative))
904mandir = share/man 906mandir = share/man
905infodir = share/info 907infodir = share/info
906perfexecdir = libexec/perf-core 908perfexecdir = libexec/perf-core
909perf_include_dir = lib/include/perf
910perf_examples_dir = lib/examples/perf
907sharedir = $(prefix)/share 911sharedir = $(prefix)/share
908template_dir = share/perf-core/templates 912template_dir = share/perf-core/templates
909STRACE_GROUPS_DIR = share/perf-core/strace/groups 913STRACE_GROUPS_DIR = share/perf-core/strace/groups
@@ -934,6 +938,8 @@ bindir_SQ = $(subst ','\'',$(bindir))
934mandir_SQ = $(subst ','\'',$(mandir)) 938mandir_SQ = $(subst ','\'',$(mandir))
935infodir_SQ = $(subst ','\'',$(infodir)) 939infodir_SQ = $(subst ','\'',$(infodir))
936perfexecdir_SQ = $(subst ','\'',$(perfexecdir)) 940perfexecdir_SQ = $(subst ','\'',$(perfexecdir))
941perf_include_dir_SQ = $(subst ','\'',$(perf_include_dir))
942perf_examples_dir_SQ = $(subst ','\'',$(perf_examples_dir))
937template_dir_SQ = $(subst ','\'',$(template_dir)) 943template_dir_SQ = $(subst ','\'',$(template_dir))
938htmldir_SQ = $(subst ','\'',$(htmldir)) 944htmldir_SQ = $(subst ','\'',$(htmldir))
939tipdir_SQ = $(subst ','\'',$(tipdir)) 945tipdir_SQ = $(subst ','\'',$(tipdir))
@@ -944,14 +950,20 @@ srcdir_SQ = $(subst ','\'',$(srcdir))
944 950
945ifneq ($(filter /%,$(firstword $(perfexecdir))),) 951ifneq ($(filter /%,$(firstword $(perfexecdir))),)
946perfexec_instdir = $(perfexecdir) 952perfexec_instdir = $(perfexecdir)
953perf_include_instdir = $(perf_include_dir)
954perf_examples_instdir = $(perf_examples_dir)
947STRACE_GROUPS_INSTDIR = $(STRACE_GROUPS_DIR) 955STRACE_GROUPS_INSTDIR = $(STRACE_GROUPS_DIR)
948tip_instdir = $(tipdir) 956tip_instdir = $(tipdir)
949else 957else
950perfexec_instdir = $(prefix)/$(perfexecdir) 958perfexec_instdir = $(prefix)/$(perfexecdir)
959perf_include_instdir = $(prefix)/$(perf_include_dir)
960perf_examples_instdir = $(prefix)/$(perf_examples_dir)
951STRACE_GROUPS_INSTDIR = $(prefix)/$(STRACE_GROUPS_DIR) 961STRACE_GROUPS_INSTDIR = $(prefix)/$(STRACE_GROUPS_DIR)
952tip_instdir = $(prefix)/$(tipdir) 962tip_instdir = $(prefix)/$(tipdir)
953endif 963endif
954perfexec_instdir_SQ = $(subst ','\'',$(perfexec_instdir)) 964perfexec_instdir_SQ = $(subst ','\'',$(perfexec_instdir))
965perf_include_instdir_SQ = $(subst ','\'',$(perf_include_instdir))
966perf_examples_instdir_SQ = $(subst ','\'',$(perf_examples_instdir))
955STRACE_GROUPS_INSTDIR_SQ = $(subst ','\'',$(STRACE_GROUPS_INSTDIR)) 967STRACE_GROUPS_INSTDIR_SQ = $(subst ','\'',$(STRACE_GROUPS_INSTDIR))
956tip_instdir_SQ = $(subst ','\'',$(tip_instdir)) 968tip_instdir_SQ = $(subst ','\'',$(tip_instdir))
957 969
@@ -999,6 +1011,8 @@ $(call detected_var,ETC_PERFCONFIG_SQ)
999$(call detected_var,STRACE_GROUPS_DIR_SQ) 1011$(call detected_var,STRACE_GROUPS_DIR_SQ)
1000$(call detected_var,prefix_SQ) 1012$(call detected_var,prefix_SQ)
1001$(call detected_var,perfexecdir_SQ) 1013$(call detected_var,perfexecdir_SQ)
1014$(call detected_var,perf_include_dir_SQ)
1015$(call detected_var,perf_examples_dir_SQ)
1002$(call detected_var,tipdir_SQ) 1016$(call detected_var,tipdir_SQ)
1003$(call detected_var,srcdir_SQ) 1017$(call detected_var,srcdir_SQ)
1004$(call detected_var,LIBDIR) 1018$(call detected_var,LIBDIR)
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 83e453de36f8..ecc9fc952655 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -767,6 +767,16 @@ ifndef NO_JVMTI
767endif 767endif
768 $(call QUIET_INSTALL, libexec) \ 768 $(call QUIET_INSTALL, libexec) \
769 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)' 769 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
770ifndef NO_LIBBPF
771 $(call QUIET_INSTALL, lib) \
772 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perf_include_instdir_SQ)/bpf'
773 $(call QUIET_INSTALL, include/bpf) \
774 $(INSTALL) include/bpf/*.h '$(DESTDIR_SQ)$(perf_include_instdir_SQ)/bpf'
775 $(call QUIET_INSTALL, lib) \
776 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perf_examples_instdir_SQ)/bpf'
777 $(call QUIET_INSTALL, examples/bpf) \
778 $(INSTALL) examples/bpf/*.c '$(DESTDIR_SQ)$(perf_examples_instdir_SQ)/bpf'
779endif
770 $(call QUIET_INSTALL, perf-archive) \ 780 $(call QUIET_INSTALL, perf-archive) \
771 $(INSTALL) $(OUTPUT)perf-archive -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)' 781 $(INSTALL) $(OUTPUT)perf-archive -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
772 $(call QUIET_INSTALL, perf-with-kcore) \ 782 $(call QUIET_INSTALL, perf-with-kcore) \
diff --git a/tools/perf/arch/arm/tests/dwarf-unwind.c b/tools/perf/arch/arm/tests/dwarf-unwind.c
index 8cb347760233..9a0242e74cfc 100644
--- a/tools/perf/arch/arm/tests/dwarf-unwind.c
+++ b/tools/perf/arch/arm/tests/dwarf-unwind.c
@@ -25,7 +25,7 @@ static int sample_ustack(struct perf_sample *sample,
25 25
26 sp = (unsigned long) regs[PERF_REG_ARM_SP]; 26 sp = (unsigned long) regs[PERF_REG_ARM_SP];
27 27
28 map = map_groups__find(thread->mg, MAP__VARIABLE, (u64) sp); 28 map = map_groups__find(thread->mg, (u64)sp);
29 if (!map) { 29 if (!map) {
30 pr_debug("failed to get stack map\n"); 30 pr_debug("failed to get stack map\n");
31 free(buf); 31 free(buf);
diff --git a/tools/perf/arch/arm64/tests/dwarf-unwind.c b/tools/perf/arch/arm64/tests/dwarf-unwind.c
index e907f0f4c20c..5522ce384723 100644
--- a/tools/perf/arch/arm64/tests/dwarf-unwind.c
+++ b/tools/perf/arch/arm64/tests/dwarf-unwind.c
@@ -25,7 +25,7 @@ static int sample_ustack(struct perf_sample *sample,
25 25
26 sp = (unsigned long) regs[PERF_REG_ARM64_SP]; 26 sp = (unsigned long) regs[PERF_REG_ARM64_SP];
27 27
28 map = map_groups__find(thread->mg, MAP__VARIABLE, (u64) sp); 28 map = map_groups__find(thread->mg, (u64)sp);
29 if (!map) { 29 if (!map) {
30 pr_debug("failed to get stack map\n"); 30 pr_debug("failed to get stack map\n");
31 free(buf); 31 free(buf);
diff --git a/tools/perf/arch/powerpc/tests/dwarf-unwind.c b/tools/perf/arch/powerpc/tests/dwarf-unwind.c
index 30cbbd6d5be0..5f39efef0856 100644
--- a/tools/perf/arch/powerpc/tests/dwarf-unwind.c
+++ b/tools/perf/arch/powerpc/tests/dwarf-unwind.c
@@ -26,7 +26,7 @@ static int sample_ustack(struct perf_sample *sample,
26 26
27 sp = (unsigned long) regs[PERF_REG_POWERPC_R1]; 27 sp = (unsigned long) regs[PERF_REG_POWERPC_R1];
28 28
29 map = map_groups__find(thread->mg, MAP__VARIABLE, (u64) sp); 29 map = map_groups__find(thread->mg, (u64)sp);
30 if (!map) { 30 if (!map) {
31 pr_debug("failed to get stack map\n"); 31 pr_debug("failed to get stack map\n");
32 free(buf); 32 free(buf);
diff --git a/tools/perf/arch/powerpc/util/skip-callchain-idx.c b/tools/perf/arch/powerpc/util/skip-callchain-idx.c
index 0c370f81e002..3598b8b75d27 100644
--- a/tools/perf/arch/powerpc/util/skip-callchain-idx.c
+++ b/tools/perf/arch/powerpc/util/skip-callchain-idx.c
@@ -248,8 +248,7 @@ int arch_skip_callchain_idx(struct thread *thread, struct ip_callchain *chain)
248 248
249 ip = chain->ips[2]; 249 ip = chain->ips[2];
250 250
251 thread__find_addr_location(thread, PERF_RECORD_MISC_USER, 251 thread__find_symbol(thread, PERF_RECORD_MISC_USER, ip, &al);
252 MAP__FUNCTION, ip, &al);
253 252
254 if (al.map) 253 if (al.map)
255 dso = al.map->dso; 254 dso = al.map->dso;
diff --git a/tools/perf/arch/s390/util/auxtrace.c b/tools/perf/arch/s390/util/auxtrace.c
index 6cb48e4cffd9..3afe8256eff2 100644
--- a/tools/perf/arch/s390/util/auxtrace.c
+++ b/tools/perf/arch/s390/util/auxtrace.c
@@ -87,6 +87,7 @@ struct auxtrace_record *auxtrace_record__init(struct perf_evlist *evlist,
87 struct perf_evsel *pos; 87 struct perf_evsel *pos;
88 int diagnose = 0; 88 int diagnose = 0;
89 89
90 *err = 0;
90 if (evlist->nr_entries == 0) 91 if (evlist->nr_entries == 0)
91 return NULL; 92 return NULL;
92 93
diff --git a/tools/perf/arch/s390/util/header.c b/tools/perf/arch/s390/util/header.c
index a4c30f1c70be..163b92f33998 100644
--- a/tools/perf/arch/s390/util/header.c
+++ b/tools/perf/arch/s390/util/header.c
@@ -146,21 +146,3 @@ char *get_cpuid_str(struct perf_pmu *pmu __maybe_unused)
146 zfree(&buf); 146 zfree(&buf);
147 return buf; 147 return buf;
148} 148}
149
150/*
151 * Compare the cpuid string returned by get_cpuid() function
152 * with the name generated by the jevents file read from
153 * pmu-events/arch/s390/mapfile.csv.
154 *
155 * Parameter mapcpuid is the cpuid as stored in the
156 * pmu-events/arch/s390/mapfile.csv. This is just the type number.
157 * Parameter cpuid is the cpuid returned by function get_cpuid().
158 */
159int strcmp_cpuid_str(const char *mapcpuid, const char *cpuid)
160{
161 char *cp = strchr(cpuid, ',');
162
163 if (cp == NULL)
164 return -1;
165 return strncmp(cp + 1, mapcpuid, strlen(mapcpuid));
166}
diff --git a/tools/perf/arch/x86/tests/dwarf-unwind.c b/tools/perf/arch/x86/tests/dwarf-unwind.c
index 95036c7a59e8..7879df34569a 100644
--- a/tools/perf/arch/x86/tests/dwarf-unwind.c
+++ b/tools/perf/arch/x86/tests/dwarf-unwind.c
@@ -26,7 +26,7 @@ static int sample_ustack(struct perf_sample *sample,
26 26
27 sp = (unsigned long) regs[PERF_REG_X86_SP]; 27 sp = (unsigned long) regs[PERF_REG_X86_SP];
28 28
29 map = map_groups__find(thread->mg, MAP__VARIABLE, (u64) sp); 29 map = map_groups__find(thread->mg, (u64)sp);
30 if (!map) { 30 if (!map) {
31 pr_debug("failed to get stack map\n"); 31 pr_debug("failed to get stack map\n");
32 free(buf); 32 free(buf);
diff --git a/tools/perf/arch/x86/util/Build b/tools/perf/arch/x86/util/Build
index f95e6f46ef0d..844b8f335532 100644
--- a/tools/perf/arch/x86/util/Build
+++ b/tools/perf/arch/x86/util/Build
@@ -4,6 +4,8 @@ libperf-y += pmu.o
4libperf-y += kvm-stat.o 4libperf-y += kvm-stat.o
5libperf-y += perf_regs.o 5libperf-y += perf_regs.o
6libperf-y += group.o 6libperf-y += group.o
7libperf-y += machine.o
8libperf-y += event.o
7 9
8libperf-$(CONFIG_DWARF) += dwarf-regs.o 10libperf-$(CONFIG_DWARF) += dwarf-regs.o
9libperf-$(CONFIG_BPF_PROLOGUE) += dwarf-regs.o 11libperf-$(CONFIG_BPF_PROLOGUE) += dwarf-regs.o
diff --git a/tools/perf/arch/x86/util/event.c b/tools/perf/arch/x86/util/event.c
new file mode 100644
index 000000000000..675a0213044d
--- /dev/null
+++ b/tools/perf/arch/x86/util/event.c
@@ -0,0 +1,76 @@
1// SPDX-License-Identifier: GPL-2.0
2#include <linux/types.h>
3#include <linux/string.h>
4
5#include "../../util/machine.h"
6#include "../../util/tool.h"
7#include "../../util/map.h"
8#include "../../util/util.h"
9#include "../../util/debug.h"
10
11#if defined(__x86_64__)
12
13int perf_event__synthesize_extra_kmaps(struct perf_tool *tool,
14 perf_event__handler_t process,
15 struct machine *machine)
16{
17 int rc = 0;
18 struct map *pos;
19 struct map_groups *kmaps = &machine->kmaps;
20 struct maps *maps = &kmaps->maps;
21 union perf_event *event = zalloc(sizeof(event->mmap) +
22 machine->id_hdr_size);
23
24 if (!event) {
25 pr_debug("Not enough memory synthesizing mmap event "
26 "for extra kernel maps\n");
27 return -1;
28 }
29
30 for (pos = maps__first(maps); pos; pos = map__next(pos)) {
31 struct kmap *kmap;
32 size_t size;
33
34 if (!__map__is_extra_kernel_map(pos))
35 continue;
36
37 kmap = map__kmap(pos);
38
39 size = sizeof(event->mmap) - sizeof(event->mmap.filename) +
40 PERF_ALIGN(strlen(kmap->name) + 1, sizeof(u64)) +
41 machine->id_hdr_size;
42
43 memset(event, 0, size);
44
45 event->mmap.header.type = PERF_RECORD_MMAP;
46
47 /*
48 * kernel uses 0 for user space maps, see kernel/perf_event.c
49 * __perf_event_mmap
50 */
51 if (machine__is_host(machine))
52 event->header.misc = PERF_RECORD_MISC_KERNEL;
53 else
54 event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL;
55
56 event->mmap.header.size = size;
57
58 event->mmap.start = pos->start;
59 event->mmap.len = pos->end - pos->start;
60 event->mmap.pgoff = pos->pgoff;
61 event->mmap.pid = machine->pid;
62
63 strlcpy(event->mmap.filename, kmap->name, PATH_MAX);
64
65 if (perf_tool__process_synth_event(tool, event, machine,
66 process) != 0) {
67 rc = -1;
68 break;
69 }
70 }
71
72 free(event);
73 return rc;
74}
75
76#endif
diff --git a/tools/perf/arch/x86/util/machine.c b/tools/perf/arch/x86/util/machine.c
new file mode 100644
index 000000000000..4520ac53caa9
--- /dev/null
+++ b/tools/perf/arch/x86/util/machine.c
@@ -0,0 +1,103 @@
1// SPDX-License-Identifier: GPL-2.0
2#include <linux/types.h>
3#include <linux/string.h>
4#include <stdlib.h>
5
6#include "../../util/machine.h"
7#include "../../util/map.h"
8#include "../../util/symbol.h"
9#include "../../util/sane_ctype.h"
10
11#include <symbol/kallsyms.h>
12
13#if defined(__x86_64__)
14
15struct extra_kernel_map_info {
16 int cnt;
17 int max_cnt;
18 struct extra_kernel_map *maps;
19 bool get_entry_trampolines;
20 u64 entry_trampoline;
21};
22
23static int add_extra_kernel_map(struct extra_kernel_map_info *mi, u64 start,
24 u64 end, u64 pgoff, const char *name)
25{
26 if (mi->cnt >= mi->max_cnt) {
27 void *buf;
28 size_t sz;
29
30 mi->max_cnt = mi->max_cnt ? mi->max_cnt * 2 : 32;
31 sz = sizeof(struct extra_kernel_map) * mi->max_cnt;
32 buf = realloc(mi->maps, sz);
33 if (!buf)
34 return -1;
35 mi->maps = buf;
36 }
37
38 mi->maps[mi->cnt].start = start;
39 mi->maps[mi->cnt].end = end;
40 mi->maps[mi->cnt].pgoff = pgoff;
41 strlcpy(mi->maps[mi->cnt].name, name, KMAP_NAME_LEN);
42
43 mi->cnt += 1;
44
45 return 0;
46}
47
48static int find_extra_kernel_maps(void *arg, const char *name, char type,
49 u64 start)
50{
51 struct extra_kernel_map_info *mi = arg;
52
53 if (!mi->entry_trampoline && kallsyms2elf_binding(type) == STB_GLOBAL &&
54 !strcmp(name, "_entry_trampoline")) {
55 mi->entry_trampoline = start;
56 return 0;
57 }
58
59 if (is_entry_trampoline(name)) {
60 u64 end = start + page_size;
61
62 return add_extra_kernel_map(mi, start, end, 0, name);
63 }
64
65 return 0;
66}
67
68int machine__create_extra_kernel_maps(struct machine *machine,
69 struct dso *kernel)
70{
71 struct extra_kernel_map_info mi = { .cnt = 0, };
72 char filename[PATH_MAX];
73 int ret;
74 int i;
75
76 machine__get_kallsyms_filename(machine, filename, PATH_MAX);
77
78 if (symbol__restricted_filename(filename, "/proc/kallsyms"))
79 return 0;
80
81 ret = kallsyms__parse(filename, &mi, find_extra_kernel_maps);
82 if (ret)
83 goto out_free;
84
85 if (!mi.entry_trampoline)
86 goto out_free;
87
88 for (i = 0; i < mi.cnt; i++) {
89 struct extra_kernel_map *xm = &mi.maps[i];
90
91 xm->pgoff = mi.entry_trampoline;
92 ret = machine__create_extra_kernel_map(machine, kernel, xm);
93 if (ret)
94 goto out_free;
95 }
96
97 machine->trampolines_mapped = mi.cnt;
98out_free:
99 free(mi.maps);
100 return ret;
101}
102
103#endif
diff --git a/tools/perf/bench/numa.c b/tools/perf/bench/numa.c
index 944070e98a2c..63eb49082774 100644
--- a/tools/perf/bench/numa.c
+++ b/tools/perf/bench/numa.c
@@ -175,7 +175,7 @@ static const struct option options[] = {
175 OPT_UINTEGER('s', "nr_secs" , &p0.nr_secs, "max number of seconds to run (default: 5 secs)"), 175 OPT_UINTEGER('s', "nr_secs" , &p0.nr_secs, "max number of seconds to run (default: 5 secs)"),
176 OPT_UINTEGER('u', "usleep" , &p0.sleep_usecs, "usecs to sleep per loop iteration"), 176 OPT_UINTEGER('u', "usleep" , &p0.sleep_usecs, "usecs to sleep per loop iteration"),
177 177
178 OPT_BOOLEAN('R', "data_reads" , &p0.data_reads, "access the data via writes (can be mixed with -W)"), 178 OPT_BOOLEAN('R', "data_reads" , &p0.data_reads, "access the data via reads (can be mixed with -W)"),
179 OPT_BOOLEAN('W', "data_writes" , &p0.data_writes, "access the data via writes (can be mixed with -R)"), 179 OPT_BOOLEAN('W', "data_writes" , &p0.data_writes, "access the data via writes (can be mixed with -R)"),
180 OPT_BOOLEAN('B', "data_backwards", &p0.data_backwards, "access the data backwards as well"), 180 OPT_BOOLEAN('B', "data_backwards", &p0.data_backwards, "access the data backwards as well"),
181 OPT_BOOLEAN('Z', "data_zero_memset", &p0.data_zero_memset,"access the data via glibc bzero only"), 181 OPT_BOOLEAN('Z', "data_zero_memset", &p0.data_zero_memset,"access the data via glibc bzero only"),
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 51709a961496..da5704240239 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -45,6 +45,7 @@ struct perf_annotate {
45 bool print_line; 45 bool print_line;
46 bool skip_missing; 46 bool skip_missing;
47 bool has_br_stack; 47 bool has_br_stack;
48 bool group_set;
48 const char *sym_hist_filter; 49 const char *sym_hist_filter;
49 const char *cpu_list; 50 const char *cpu_list;
50 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); 51 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
@@ -228,7 +229,7 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,
228 */ 229 */
229 if (al->sym != NULL) { 230 if (al->sym != NULL) {
230 rb_erase(&al->sym->rb_node, 231 rb_erase(&al->sym->rb_node,
231 &al->map->dso->symbols[al->map->type]); 232 &al->map->dso->symbols);
232 symbol__delete(al->sym); 233 symbol__delete(al->sym);
233 dso__reset_find_symbol_cache(al->map->dso); 234 dso__reset_find_symbol_cache(al->map->dso);
234 } 235 }
@@ -508,6 +509,9 @@ int cmd_annotate(int argc, const char **argv)
508 "Don't shorten the displayed pathnames"), 509 "Don't shorten the displayed pathnames"),
509 OPT_BOOLEAN(0, "skip-missing", &annotate.skip_missing, 510 OPT_BOOLEAN(0, "skip-missing", &annotate.skip_missing,
510 "Skip symbols that cannot be annotated"), 511 "Skip symbols that cannot be annotated"),
512 OPT_BOOLEAN_SET(0, "group", &symbol_conf.event_group,
513 &annotate.group_set,
514 "Show event group information together"),
511 OPT_STRING('C', "cpu", &annotate.cpu_list, "cpu", "list of cpus to profile"), 515 OPT_STRING('C', "cpu", &annotate.cpu_list, "cpu", "list of cpus to profile"),
512 OPT_CALLBACK(0, "symfs", NULL, "directory", 516 OPT_CALLBACK(0, "symfs", NULL, "directory",
513 "Look for files with symbols relative to this directory", 517 "Look for files with symbols relative to this directory",
@@ -570,6 +574,9 @@ int cmd_annotate(int argc, const char **argv)
570 annotate.has_br_stack = perf_header__has_feat(&annotate.session->header, 574 annotate.has_br_stack = perf_header__has_feat(&annotate.session->header,
571 HEADER_BRANCH_STACK); 575 HEADER_BRANCH_STACK);
572 576
577 if (annotate.group_set)
578 perf_evlist__force_leader(annotate.session->evlist);
579
573 ret = symbol__annotation_init(); 580 ret = symbol__annotation_init();
574 if (ret < 0) 581 if (ret < 0)
575 goto out_delete; 582 goto out_delete;
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c
index 41db2cba77eb..115110a4796a 100644
--- a/tools/perf/builtin-buildid-cache.c
+++ b/tools/perf/builtin-buildid-cache.c
@@ -25,6 +25,7 @@
25#include "util/session.h" 25#include "util/session.h"
26#include "util/symbol.h" 26#include "util/symbol.h"
27#include "util/time-utils.h" 27#include "util/time-utils.h"
28#include "util/probe-file.h"
28 29
29static int build_id_cache__kcore_buildid(const char *proc_dir, char *sbuildid) 30static int build_id_cache__kcore_buildid(const char *proc_dir, char *sbuildid)
30{ 31{
@@ -239,6 +240,34 @@ out:
239 return err; 240 return err;
240} 241}
241 242
243static int build_id_cache__purge_all(void)
244{
245 struct strlist *list;
246 struct str_node *pos;
247 int err = 0;
248 char *buf;
249
250 list = build_id_cache__list_all(false);
251 if (!list) {
252 pr_debug("Failed to get buildids: -%d\n", errno);
253 return -EINVAL;
254 }
255
256 strlist__for_each_entry(pos, list) {
257 buf = build_id_cache__origname(pos->s);
258 err = build_id_cache__remove_s(pos->s);
259 pr_debug("Removing %s (%s): %s\n", buf, pos->s,
260 err ? "FAIL" : "Ok");
261 free(buf);
262 if (err)
263 break;
264 }
265 strlist__delete(list);
266
267 pr_debug("Purged all: %s\n", err ? "FAIL" : "Ok");
268 return err;
269}
270
242static bool dso__missing_buildid_cache(struct dso *dso, int parm __maybe_unused) 271static bool dso__missing_buildid_cache(struct dso *dso, int parm __maybe_unused)
243{ 272{
244 char filename[PATH_MAX]; 273 char filename[PATH_MAX];
@@ -297,6 +326,26 @@ static int build_id_cache__update_file(const char *filename, struct nsinfo *nsi)
297 return err; 326 return err;
298} 327}
299 328
329static int build_id_cache__show_all(void)
330{
331 struct strlist *bidlist;
332 struct str_node *nd;
333 char *buf;
334
335 bidlist = build_id_cache__list_all(true);
336 if (!bidlist) {
337 pr_debug("Failed to get buildids: -%d\n", errno);
338 return -1;
339 }
340 strlist__for_each_entry(nd, bidlist) {
341 buf = build_id_cache__origname(nd->s);
342 fprintf(stdout, "%s %s\n", nd->s, buf);
343 free(buf);
344 }
345 strlist__delete(bidlist);
346 return 0;
347}
348
300int cmd_buildid_cache(int argc, const char **argv) 349int cmd_buildid_cache(int argc, const char **argv)
301{ 350{
302 struct strlist *list; 351 struct strlist *list;
@@ -304,6 +353,9 @@ int cmd_buildid_cache(int argc, const char **argv)
304 int ret = 0; 353 int ret = 0;
305 int ns_id = -1; 354 int ns_id = -1;
306 bool force = false; 355 bool force = false;
356 bool list_files = false;
357 bool opts_flag = false;
358 bool purge_all = false;
307 char const *add_name_list_str = NULL, 359 char const *add_name_list_str = NULL,
308 *remove_name_list_str = NULL, 360 *remove_name_list_str = NULL,
309 *purge_name_list_str = NULL, 361 *purge_name_list_str = NULL,
@@ -327,6 +379,8 @@ int cmd_buildid_cache(int argc, const char **argv)
327 "file(s) to remove"), 379 "file(s) to remove"),
328 OPT_STRING('p', "purge", &purge_name_list_str, "file list", 380 OPT_STRING('p', "purge", &purge_name_list_str, "file list",
329 "file(s) to remove (remove old caches too)"), 381 "file(s) to remove (remove old caches too)"),
382 OPT_BOOLEAN('P', "purge-all", &purge_all, "purge all cached files"),
383 OPT_BOOLEAN('l', "list", &list_files, "list all cached files"),
330 OPT_STRING('M', "missing", &missing_filename, "file", 384 OPT_STRING('M', "missing", &missing_filename, "file",
331 "to find missing build ids in the cache"), 385 "to find missing build ids in the cache"),
332 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"), 386 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
@@ -344,11 +398,20 @@ int cmd_buildid_cache(int argc, const char **argv)
344 argc = parse_options(argc, argv, buildid_cache_options, 398 argc = parse_options(argc, argv, buildid_cache_options,
345 buildid_cache_usage, 0); 399 buildid_cache_usage, 0);
346 400
347 if (argc || (!add_name_list_str && !kcore_filename && 401 opts_flag = add_name_list_str || kcore_filename ||
348 !remove_name_list_str && !purge_name_list_str && 402 remove_name_list_str || purge_name_list_str ||
349 !missing_filename && !update_name_list_str)) 403 missing_filename || update_name_list_str ||
404 purge_all;
405
406 if (argc || !(list_files || opts_flag))
350 usage_with_options(buildid_cache_usage, buildid_cache_options); 407 usage_with_options(buildid_cache_usage, buildid_cache_options);
351 408
409 /* -l is exclusive. It can not be used with other options. */
410 if (list_files && opts_flag) {
411 usage_with_options_msg(buildid_cache_usage,
412 buildid_cache_options, "-l is exclusive.\n");
413 }
414
352 if (ns_id > 0) 415 if (ns_id > 0)
353 nsi = nsinfo__new(ns_id); 416 nsi = nsinfo__new(ns_id);
354 417
@@ -366,6 +429,11 @@ int cmd_buildid_cache(int argc, const char **argv)
366 429
367 setup_pager(); 430 setup_pager();
368 431
432 if (list_files) {
433 ret = build_id_cache__show_all();
434 goto out;
435 }
436
369 if (add_name_list_str) { 437 if (add_name_list_str) {
370 list = strlist__new(add_name_list_str, NULL); 438 list = strlist__new(add_name_list_str, NULL);
371 if (list) { 439 if (list) {
@@ -420,6 +488,13 @@ int cmd_buildid_cache(int argc, const char **argv)
420 } 488 }
421 } 489 }
422 490
491 if (purge_all) {
492 if (build_id_cache__purge_all()) {
493 pr_warning("Couldn't remove some caches. Error: %s.\n",
494 str_error_r(errno, sbuf, sizeof(sbuf)));
495 }
496 }
497
423 if (missing_filename) 498 if (missing_filename)
424 ret = build_id_cache__fprintf_missing(session, stdout); 499 ret = build_id_cache__fprintf_missing(session, stdout);
425 500
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 40fe919bbcf3..a3b346359ba0 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -440,9 +440,7 @@ static int perf_event__inject_buildid(struct perf_tool *tool,
440 goto repipe; 440 goto repipe;
441 } 441 }
442 442
443 thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, sample->ip, &al); 443 if (thread__find_map(thread, sample->cpumode, sample->ip, &al)) {
444
445 if (al.map != NULL) {
446 if (!al.map->dso->hit) { 444 if (!al.map->dso->hit) {
447 al.map->dso->hit = 1; 445 al.map->dso->hit = 1;
448 if (map__load(al.map) >= 0) { 446 if (map__load(al.map) >= 0) {
diff --git a/tools/perf/builtin-kallsyms.c b/tools/perf/builtin-kallsyms.c
index bcfb363112d3..90d1a2305b72 100644
--- a/tools/perf/builtin-kallsyms.c
+++ b/tools/perf/builtin-kallsyms.c
@@ -27,7 +27,7 @@ static int __cmd_kallsyms(int argc, const char **argv)
27 27
28 for (i = 0; i < argc; ++i) { 28 for (i = 0; i < argc; ++i) {
29 struct map *map; 29 struct map *map;
30 struct symbol *symbol = machine__find_kernel_function_by_name(machine, argv[i], &map); 30 struct symbol *symbol = machine__find_kernel_symbol_by_name(machine, argv[i], &map);
31 31
32 if (symbol == NULL) { 32 if (symbol == NULL) {
33 printf("%s: not found\n", argv[i]); 33 printf("%s: not found\n", argv[i]);
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index ae11e4c3516a..54d3f21b0e62 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -1004,7 +1004,7 @@ static void __print_slab_result(struct rb_root *root,
1004 if (is_caller) { 1004 if (is_caller) {
1005 addr = data->call_site; 1005 addr = data->call_site;
1006 if (!raw_ip) 1006 if (!raw_ip)
1007 sym = machine__find_kernel_function(machine, addr, &map); 1007 sym = machine__find_kernel_symbol(machine, addr, &map);
1008 } else 1008 } else
1009 addr = data->ptr; 1009 addr = data->ptr;
1010 1010
@@ -1068,7 +1068,7 @@ static void __print_page_alloc_result(struct perf_session *session, int n_lines)
1068 char *caller = buf; 1068 char *caller = buf;
1069 1069
1070 data = rb_entry(next, struct page_stat, node); 1070 data = rb_entry(next, struct page_stat, node);
1071 sym = machine__find_kernel_function(machine, data->callsite, &map); 1071 sym = machine__find_kernel_symbol(machine, data->callsite, &map);
1072 if (sym) 1072 if (sym)
1073 caller = sym->name; 1073 caller = sym->name;
1074 else 1074 else
@@ -1110,7 +1110,7 @@ static void __print_page_caller_result(struct perf_session *session, int n_lines
1110 char *caller = buf; 1110 char *caller = buf;
1111 1111
1112 data = rb_entry(next, struct page_stat, node); 1112 data = rb_entry(next, struct page_stat, node);
1113 sym = machine__find_kernel_function(machine, data->callsite, &map); 1113 sym = machine__find_kernel_symbol(machine, data->callsite, &map);
1114 if (sym) 1114 if (sym)
1115 caller = sym->name; 1115 caller = sym->name;
1116 else 1116 else
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 0f198f6d9b77..ad978e3ee2b8 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -194,20 +194,11 @@ out:
194 return err; 194 return err;
195} 195}
196 196
197/*
198 * Events in data file are not collect in groups, but we still want
199 * the group display. Set the artificial group and set the leader's
200 * forced_leader flag to notify the display code.
201 */
202static void setup_forced_leader(struct report *report, 197static void setup_forced_leader(struct report *report,
203 struct perf_evlist *evlist) 198 struct perf_evlist *evlist)
204{ 199{
205 if (report->group_set && !evlist->nr_groups) { 200 if (report->group_set)
206 struct perf_evsel *leader = perf_evlist__first(evlist); 201 perf_evlist__force_leader(evlist);
207
208 perf_evlist__set_leader(evlist);
209 leader->forced_leader = true;
210 }
211} 202}
212 203
213static int process_feature_event(struct perf_tool *tool, 204static int process_feature_event(struct perf_tool *tool,
@@ -523,12 +514,9 @@ static void report__warn_kptr_restrict(const struct report *rep)
523 "As no suitable kallsyms nor vmlinux was found, kernel samples\n" 514 "As no suitable kallsyms nor vmlinux was found, kernel samples\n"
524 "can't be resolved."; 515 "can't be resolved.";
525 516
526 if (kernel_map) { 517 if (kernel_map && map__has_symbols(kernel_map)) {
527 const struct dso *kdso = kernel_map->dso; 518 desc = "If some relocation was applied (e.g. "
528 if (!RB_EMPTY_ROOT(&kdso->symbols[MAP__FUNCTION])) { 519 "kexec) symbols may be misresolved.";
529 desc = "If some relocation was applied (e.g. "
530 "kexec) symbols may be misresolved.";
531 }
532 } 520 }
533 521
534 ui__warning( 522 ui__warning(
@@ -718,10 +706,7 @@ static size_t maps__fprintf_task(struct maps *maps, int indent, FILE *fp)
718 706
719static int map_groups__fprintf_task(struct map_groups *mg, int indent, FILE *fp) 707static int map_groups__fprintf_task(struct map_groups *mg, int indent, FILE *fp)
720{ 708{
721 int printed = 0, i; 709 return maps__fprintf_task(&mg->maps, indent, fp);
722 for (i = 0; i < MAP__NR_TYPES; ++i)
723 printed += maps__fprintf_task(&mg->maps[i], indent, fp);
724 return printed;
725} 710}
726 711
727static void task__print_level(struct task *task, FILE *fp, int level) 712static void task__print_level(struct task *task, FILE *fp, int level)
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index e0a9845b6cbc..cefc8813e91e 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -153,8 +153,8 @@ static struct {
153 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | 153 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
154 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | 154 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
155 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP | 155 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
156 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO | 156 PERF_OUTPUT_SYM | PERF_OUTPUT_SYMOFFSET |
157 PERF_OUTPUT_PERIOD, 157 PERF_OUTPUT_DSO | PERF_OUTPUT_PERIOD,
158 158
159 .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT, 159 .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,
160 }, 160 },
@@ -165,8 +165,9 @@ static struct {
165 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | 165 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
166 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | 166 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
167 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP | 167 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
168 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO | 168 PERF_OUTPUT_SYM | PERF_OUTPUT_SYMOFFSET |
169 PERF_OUTPUT_PERIOD | PERF_OUTPUT_BPF_OUTPUT, 169 PERF_OUTPUT_DSO | PERF_OUTPUT_PERIOD |
170 PERF_OUTPUT_BPF_OUTPUT,
170 171
171 .invalid_fields = PERF_OUTPUT_TRACE, 172 .invalid_fields = PERF_OUTPUT_TRACE,
172 }, 173 },
@@ -185,10 +186,10 @@ static struct {
185 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | 186 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
186 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | 187 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
187 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP | 188 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
188 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO | 189 PERF_OUTPUT_SYM | PERF_OUTPUT_SYMOFFSET |
189 PERF_OUTPUT_PERIOD | PERF_OUTPUT_ADDR | 190 PERF_OUTPUT_DSO | PERF_OUTPUT_PERIOD |
190 PERF_OUTPUT_DATA_SRC | PERF_OUTPUT_WEIGHT | 191 PERF_OUTPUT_ADDR | PERF_OUTPUT_DATA_SRC |
191 PERF_OUTPUT_PHYS_ADDR, 192 PERF_OUTPUT_WEIGHT | PERF_OUTPUT_PHYS_ADDR,
192 193
193 .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT, 194 .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,
194 }, 195 },
@@ -199,8 +200,8 @@ static struct {
199 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | 200 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
200 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | 201 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
201 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP | 202 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
202 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO | 203 PERF_OUTPUT_SYM | PERF_OUTPUT_SYMOFFSET |
203 PERF_OUTPUT_PERIOD, 204 PERF_OUTPUT_DSO | PERF_OUTPUT_PERIOD,
204 205
205 .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT, 206 .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,
206 }, 207 },
@@ -211,8 +212,8 @@ static struct {
211 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | 212 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
212 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | 213 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
213 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP | 214 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
214 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO | 215 PERF_OUTPUT_SYM | PERF_OUTPUT_SYMOFFSET |
215 PERF_OUTPUT_SYNTH, 216 PERF_OUTPUT_DSO | PERF_OUTPUT_SYNTH,
216 217
217 .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT, 218 .invalid_fields = PERF_OUTPUT_TRACE | PERF_OUTPUT_BPF_OUTPUT,
218 }, 219 },
@@ -544,6 +545,7 @@ static int perf_session__check_output_opt(struct perf_session *session)
544 if (attr->sample_type & PERF_SAMPLE_CALLCHAIN) { 545 if (attr->sample_type & PERF_SAMPLE_CALLCHAIN) {
545 output[j].fields |= PERF_OUTPUT_IP; 546 output[j].fields |= PERF_OUTPUT_IP;
546 output[j].fields |= PERF_OUTPUT_SYM; 547 output[j].fields |= PERF_OUTPUT_SYM;
548 output[j].fields |= PERF_OUTPUT_SYMOFFSET;
547 output[j].fields |= PERF_OUTPUT_DSO; 549 output[j].fields |= PERF_OUTPUT_DSO;
548 set_print_ip_opts(attr); 550 set_print_ip_opts(attr);
549 goto out; 551 goto out;
@@ -717,8 +719,8 @@ static int perf_sample__fprintf_brstack(struct perf_sample *sample,
717 if (PRINT_FIELD(DSO)) { 719 if (PRINT_FIELD(DSO)) {
718 memset(&alf, 0, sizeof(alf)); 720 memset(&alf, 0, sizeof(alf));
719 memset(&alt, 0, sizeof(alt)); 721 memset(&alt, 0, sizeof(alt));
720 thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, from, &alf); 722 thread__find_map(thread, sample->cpumode, from, &alf);
721 thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, to, &alt); 723 thread__find_map(thread, sample->cpumode, to, &alt);
722 } 724 }
723 725
724 printed += fprintf(fp, " 0x%"PRIx64, from); 726 printed += fprintf(fp, " 0x%"PRIx64, from);
@@ -764,13 +766,8 @@ static int perf_sample__fprintf_brstacksym(struct perf_sample *sample,
764 from = br->entries[i].from; 766 from = br->entries[i].from;
765 to = br->entries[i].to; 767 to = br->entries[i].to;
766 768
767 thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, from, &alf); 769 thread__find_symbol(thread, sample->cpumode, from, &alf);
768 if (alf.map) 770 thread__find_symbol(thread, sample->cpumode, to, &alt);
769 alf.sym = map__find_symbol(alf.map, alf.addr);
770
771 thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, to, &alt);
772 if (alt.map)
773 alt.sym = map__find_symbol(alt.map, alt.addr);
774 771
775 printed += symbol__fprintf_symname_offs(alf.sym, &alf, fp); 772 printed += symbol__fprintf_symname_offs(alf.sym, &alf, fp);
776 if (PRINT_FIELD(DSO)) { 773 if (PRINT_FIELD(DSO)) {
@@ -814,12 +811,12 @@ static int perf_sample__fprintf_brstackoff(struct perf_sample *sample,
814 from = br->entries[i].from; 811 from = br->entries[i].from;
815 to = br->entries[i].to; 812 to = br->entries[i].to;
816 813
817 thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, from, &alf); 814 if (thread__find_map(thread, sample->cpumode, from, &alf) &&
818 if (alf.map && !alf.map->dso->adjust_symbols) 815 !alf.map->dso->adjust_symbols)
819 from = map__map_ip(alf.map, from); 816 from = map__map_ip(alf.map, from);
820 817
821 thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, to, &alt); 818 if (thread__find_map(thread, sample->cpumode, to, &alt) &&
822 if (alt.map && !alt.map->dso->adjust_symbols) 819 !alt.map->dso->adjust_symbols)
823 to = map__map_ip(alt.map, to); 820 to = map__map_ip(alt.map, to);
824 821
825 printed += fprintf(fp, " 0x%"PRIx64, from); 822 printed += fprintf(fp, " 0x%"PRIx64, from);
@@ -882,8 +879,7 @@ static int grab_bb(u8 *buffer, u64 start, u64 end,
882 return 0; 879 return 0;
883 } 880 }
884 881
885 thread__find_addr_map(thread, *cpumode, MAP__FUNCTION, start, &al); 882 if (!thread__find_map(thread, *cpumode, start, &al) || !al.map->dso) {
886 if (!al.map || !al.map->dso) {
887 pr_debug("\tcannot resolve %" PRIx64 "-%" PRIx64 "\n", start, end); 883 pr_debug("\tcannot resolve %" PRIx64 "-%" PRIx64 "\n", start, end);
888 return 0; 884 return 0;
889 } 885 }
@@ -933,10 +929,8 @@ static int ip__fprintf_sym(uint64_t addr, struct thread *thread,
933 929
934 memset(&al, 0, sizeof(al)); 930 memset(&al, 0, sizeof(al));
935 931
936 thread__find_addr_map(thread, cpumode, MAP__FUNCTION, addr, &al); 932 thread__find_map(thread, cpumode, addr, &al);
937 if (!al.map) 933
938 thread__find_addr_map(thread, cpumode, MAP__VARIABLE,
939 addr, &al);
940 if ((*lastsym) && al.addr >= (*lastsym)->start && al.addr < (*lastsym)->end) 934 if ((*lastsym) && al.addr >= (*lastsym)->start && al.addr < (*lastsym)->end)
941 return 0; 935 return 0;
942 936
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 147a27e8c937..a4f662a462c6 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -164,6 +164,7 @@ static bool forever = false;
164static bool metric_only = false; 164static bool metric_only = false;
165static bool force_metric_only = false; 165static bool force_metric_only = false;
166static bool no_merge = false; 166static bool no_merge = false;
167static bool walltime_run_table = false;
167static struct timespec ref_time; 168static struct timespec ref_time;
168static struct cpu_map *aggr_map; 169static struct cpu_map *aggr_map;
169static aggr_get_id_t aggr_get_id; 170static aggr_get_id_t aggr_get_id;
@@ -172,6 +173,8 @@ static bool interval_count;
172static const char *output_name; 173static const char *output_name;
173static int output_fd; 174static int output_fd;
174static int print_free_counters_hint; 175static int print_free_counters_hint;
176static int print_mixed_hw_group_error;
177static u64 *walltime_run;
175 178
176struct perf_stat { 179struct perf_stat {
177 bool record; 180 bool record;
@@ -568,7 +571,7 @@ static struct perf_evsel *perf_evsel__reset_weak_group(struct perf_evsel *evsel)
568 return leader; 571 return leader;
569} 572}
570 573
571static int __run_perf_stat(int argc, const char **argv) 574static int __run_perf_stat(int argc, const char **argv, int run_idx)
572{ 575{
573 int interval = stat_config.interval; 576 int interval = stat_config.interval;
574 int times = stat_config.times; 577 int times = stat_config.times;
@@ -751,6 +754,9 @@ try_again:
751 754
752 t1 = rdclock(); 755 t1 = rdclock();
753 756
757 if (walltime_run_table)
758 walltime_run[run_idx] = t1 - t0;
759
754 update_stats(&walltime_nsecs_stats, t1 - t0); 760 update_stats(&walltime_nsecs_stats, t1 - t0);
755 761
756 /* 762 /*
@@ -765,7 +771,7 @@ try_again:
765 return WEXITSTATUS(status); 771 return WEXITSTATUS(status);
766} 772}
767 773
768static int run_perf_stat(int argc, const char **argv) 774static int run_perf_stat(int argc, const char **argv, int run_idx)
769{ 775{
770 int ret; 776 int ret;
771 777
@@ -778,7 +784,7 @@ static int run_perf_stat(int argc, const char **argv)
778 if (sync_run) 784 if (sync_run)
779 sync(); 785 sync();
780 786
781 ret = __run_perf_stat(argc, argv); 787 ret = __run_perf_stat(argc, argv, run_idx);
782 if (ret) 788 if (ret)
783 return ret; 789 return ret;
784 790
@@ -1126,6 +1132,30 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
1126 fprintf(output, "%s%s", csv_sep, evsel->cgrp->name); 1132 fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
1127} 1133}
1128 1134
1135static bool is_mixed_hw_group(struct perf_evsel *counter)
1136{
1137 struct perf_evlist *evlist = counter->evlist;
1138 u32 pmu_type = counter->attr.type;
1139 struct perf_evsel *pos;
1140
1141 if (counter->nr_members < 2)
1142 return false;
1143
1144 evlist__for_each_entry(evlist, pos) {
1145 /* software events can be part of any hardware group */
1146 if (pos->attr.type == PERF_TYPE_SOFTWARE)
1147 continue;
1148 if (pmu_type == PERF_TYPE_SOFTWARE) {
1149 pmu_type = pos->attr.type;
1150 continue;
1151 }
1152 if (pmu_type != pos->attr.type)
1153 return true;
1154 }
1155
1156 return false;
1157}
1158
1129static void printout(int id, int nr, struct perf_evsel *counter, double uval, 1159static void printout(int id, int nr, struct perf_evsel *counter, double uval,
1130 char *prefix, u64 run, u64 ena, double noise, 1160 char *prefix, u64 run, u64 ena, double noise,
1131 struct runtime_stat *st) 1161 struct runtime_stat *st)
@@ -1178,8 +1208,11 @@ static void printout(int id, int nr, struct perf_evsel *counter, double uval,
1178 counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED, 1208 counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
1179 csv_sep); 1209 csv_sep);
1180 1210
1181 if (counter->supported) 1211 if (counter->supported) {
1182 print_free_counters_hint = 1; 1212 print_free_counters_hint = 1;
1213 if (is_mixed_hw_group(counter))
1214 print_mixed_hw_group_error = 1;
1215 }
1183 1216
1184 fprintf(stat_config.output, "%-*s%s", 1217 fprintf(stat_config.output, "%-*s%s",
1185 csv_output ? 0 : unit_width, 1218 csv_output ? 0 : unit_width,
@@ -1256,7 +1289,8 @@ static void uniquify_event_name(struct perf_evsel *counter)
1256 char *new_name; 1289 char *new_name;
1257 char *config; 1290 char *config;
1258 1291
1259 if (!counter->pmu_name || !strncmp(counter->name, counter->pmu_name, 1292 if (counter->uniquified_name ||
1293 !counter->pmu_name || !strncmp(counter->name, counter->pmu_name,
1260 strlen(counter->pmu_name))) 1294 strlen(counter->pmu_name)))
1261 return; 1295 return;
1262 1296
@@ -1274,6 +1308,8 @@ static void uniquify_event_name(struct perf_evsel *counter)
1274 counter->name = new_name; 1308 counter->name = new_name;
1275 } 1309 }
1276 } 1310 }
1311
1312 counter->uniquified_name = true;
1277} 1313}
1278 1314
1279static void collect_all_aliases(struct perf_evsel *counter, 1315static void collect_all_aliases(struct perf_evsel *counter,
@@ -1733,19 +1769,67 @@ static void print_header(int argc, const char **argv)
1733 } 1769 }
1734} 1770}
1735 1771
1772static int get_precision(double num)
1773{
1774 if (num > 1)
1775 return 0;
1776
1777 return lround(ceil(-log10(num)));
1778}
1779
1780static void print_table(FILE *output, int precision, double avg)
1781{
1782 char tmp[64];
1783 int idx, indent = 0;
1784
1785 scnprintf(tmp, 64, " %17.*f", precision, avg);
1786 while (tmp[indent] == ' ')
1787 indent++;
1788
1789 fprintf(output, "%*s# Table of individual measurements:\n", indent, "");
1790
1791 for (idx = 0; idx < run_count; idx++) {
1792 double run = (double) walltime_run[idx] / NSEC_PER_SEC;
1793 int h, n = 1 + abs((int) (100.0 * (run - avg)/run) / 5);
1794
1795 fprintf(output, " %17.*f (%+.*f) ",
1796 precision, run, precision, run - avg);
1797
1798 for (h = 0; h < n; h++)
1799 fprintf(output, "#");
1800
1801 fprintf(output, "\n");
1802 }
1803
1804 fprintf(output, "\n%*s# Final result:\n", indent, "");
1805}
1806
1736static void print_footer(void) 1807static void print_footer(void)
1737{ 1808{
1809 double avg = avg_stats(&walltime_nsecs_stats) / NSEC_PER_SEC;
1738 FILE *output = stat_config.output; 1810 FILE *output = stat_config.output;
1739 int n; 1811 int n;
1740 1812
1741 if (!null_run) 1813 if (!null_run)
1742 fprintf(output, "\n"); 1814 fprintf(output, "\n");
1743 fprintf(output, " %17.9f seconds time elapsed", 1815
1744 avg_stats(&walltime_nsecs_stats) / NSEC_PER_SEC); 1816 if (run_count == 1) {
1745 if (run_count > 1) { 1817 fprintf(output, " %17.9f seconds time elapsed", avg);
1746 fprintf(output, " "); 1818 } else {
1747 print_noise_pct(stddev_stats(&walltime_nsecs_stats), 1819 double sd = stddev_stats(&walltime_nsecs_stats) / NSEC_PER_SEC;
1748 avg_stats(&walltime_nsecs_stats)); 1820 /*
1821 * Display at most 2 more significant
1822 * digits than the stddev inaccuracy.
1823 */
1824 int precision = get_precision(sd) + 2;
1825
1826 if (walltime_run_table)
1827 print_table(output, precision, avg);
1828
1829 fprintf(output, " %17.*f +- %.*f seconds time elapsed",
1830 precision, avg, precision, sd);
1831
1832 print_noise_pct(sd, avg);
1749 } 1833 }
1750 fprintf(output, "\n\n"); 1834 fprintf(output, "\n\n");
1751 1835
@@ -1757,6 +1841,11 @@ static void print_footer(void)
1757" echo 0 > /proc/sys/kernel/nmi_watchdog\n" 1841" echo 0 > /proc/sys/kernel/nmi_watchdog\n"
1758" perf stat ...\n" 1842" perf stat ...\n"
1759" echo 1 > /proc/sys/kernel/nmi_watchdog\n"); 1843" echo 1 > /proc/sys/kernel/nmi_watchdog\n");
1844
1845 if (print_mixed_hw_group_error)
1846 fprintf(output,
1847 "The events in group usually have to be from "
1848 "the same PMU. Try reorganizing the group.\n");
1760} 1849}
1761 1850
1762static void print_counters(struct timespec *ts, int argc, const char **argv) 1851static void print_counters(struct timespec *ts, int argc, const char **argv)
@@ -1916,6 +2005,8 @@ static const struct option stat_options[] = {
1916 "be more verbose (show counter open errors, etc)"), 2005 "be more verbose (show counter open errors, etc)"),
1917 OPT_INTEGER('r', "repeat", &run_count, 2006 OPT_INTEGER('r', "repeat", &run_count,
1918 "repeat command and print average + stddev (max: 100, forever: 0)"), 2007 "repeat command and print average + stddev (max: 100, forever: 0)"),
2008 OPT_BOOLEAN(0, "table", &walltime_run_table,
2009 "display details about each run (only with -r option)"),
1919 OPT_BOOLEAN('n', "null", &null_run, 2010 OPT_BOOLEAN('n', "null", &null_run,
1920 "null run - dont start any counters"), 2011 "null run - dont start any counters"),
1921 OPT_INCR('d', "detailed", &detailed_run, 2012 OPT_INCR('d', "detailed", &detailed_run,
@@ -2807,6 +2898,13 @@ int cmd_stat(int argc, const char **argv)
2807 goto out; 2898 goto out;
2808 } 2899 }
2809 2900
2901 if (walltime_run_table && run_count <= 1) {
2902 fprintf(stderr, "--table is only supported with -r\n");
2903 parse_options_usage(stat_usage, stat_options, "r", 1);
2904 parse_options_usage(NULL, stat_options, "table", 0);
2905 goto out;
2906 }
2907
2810 if (output_fd < 0) { 2908 if (output_fd < 0) {
2811 fprintf(stderr, "argument to --log-fd must be a > 0\n"); 2909 fprintf(stderr, "argument to --log-fd must be a > 0\n");
2812 parse_options_usage(stat_usage, stat_options, "log-fd", 0); 2910 parse_options_usage(stat_usage, stat_options, "log-fd", 0);
@@ -2861,6 +2959,14 @@ int cmd_stat(int argc, const char **argv)
2861 run_count = 1; 2959 run_count = 1;
2862 } 2960 }
2863 2961
2962 if (walltime_run_table) {
2963 walltime_run = zalloc(run_count * sizeof(walltime_run[0]));
2964 if (!walltime_run) {
2965 pr_err("failed to setup -r option");
2966 goto out;
2967 }
2968 }
2969
2864 if ((stat_config.aggr_mode == AGGR_THREAD) && 2970 if ((stat_config.aggr_mode == AGGR_THREAD) &&
2865 !target__has_task(&target)) { 2971 !target__has_task(&target)) {
2866 if (!target.system_wide || target.cpu_list) { 2972 if (!target.system_wide || target.cpu_list) {
@@ -2976,7 +3082,7 @@ int cmd_stat(int argc, const char **argv)
2976 fprintf(output, "[ perf stat: executing run #%d ... ]\n", 3082 fprintf(output, "[ perf stat: executing run #%d ... ]\n",
2977 run_idx + 1); 3083 run_idx + 1);
2978 3084
2979 status = run_perf_stat(argc, argv); 3085 status = run_perf_stat(argc, argv, run_idx);
2980 if (forever && status != -1) { 3086 if (forever && status != -1) {
2981 print_counters(NULL, argc, argv); 3087 print_counters(NULL, argc, argv);
2982 perf_stat__reset_stats(); 3088 perf_stat__reset_stats();
@@ -3024,6 +3130,8 @@ int cmd_stat(int argc, const char **argv)
3024 perf_stat__exit_aggr_mode(); 3130 perf_stat__exit_aggr_mode();
3025 perf_evlist__free_stats(evsel_list); 3131 perf_evlist__free_stats(evsel_list);
3026out: 3132out:
3133 free(walltime_run);
3134
3027 if (smi_cost && smi_reset) 3135 if (smi_cost && smi_reset)
3028 sysfs__write_int(FREEZE_ON_SMI_PATH, 0); 3136 sysfs__write_int(FREEZE_ON_SMI_PATH, 0);
3029 3137
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 813698a9b8c7..a827919c6263 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -533,12 +533,8 @@ static const char *cat_backtrace(union perf_event *event,
533 } 533 }
534 534
535 tal.filtered = 0; 535 tal.filtered = 0;
536 thread__find_addr_location(al.thread, cpumode, 536 if (thread__find_symbol(al.thread, cpumode, ip, &tal))
537 MAP__FUNCTION, ip, &tal); 537 fprintf(f, "..... %016" PRIx64 " %s\n", ip, tal.sym->name);
538
539 if (tal.sym)
540 fprintf(f, "..... %016" PRIx64 " %s\n", ip,
541 tal.sym->name);
542 else 538 else
543 fprintf(f, "..... %016" PRIx64 "\n", ip); 539 fprintf(f, "..... %016" PRIx64 "\n", ip);
544 } 540 }
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index f39bd60d2708..7a349fcd3864 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -742,7 +742,7 @@ static void perf_event__process_sample(struct perf_tool *tool,
742"Kernel address maps (/proc/{kallsyms,modules}) are restricted.\n\n" 742"Kernel address maps (/proc/{kallsyms,modules}) are restricted.\n\n"
743"Check /proc/sys/kernel/kptr_restrict.\n\n" 743"Check /proc/sys/kernel/kptr_restrict.\n\n"
744"Kernel%s samples will not be resolved.\n", 744"Kernel%s samples will not be resolved.\n",
745 al.map && !RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION]) ? 745 al.map && map__has_symbols(al.map) ?
746 " modules" : ""); 746 " modules" : "");
747 if (use_browser <= 0) 747 if (use_browser <= 0)
748 sleep(5); 748 sleep(5);
@@ -750,7 +750,7 @@ static void perf_event__process_sample(struct perf_tool *tool,
750 machine->kptr_restrict_warned = true; 750 machine->kptr_restrict_warned = true;
751 } 751 }
752 752
753 if (al.sym == NULL) { 753 if (al.sym == NULL && al.map != NULL) {
754 const char *msg = "Kernel samples will not be resolved.\n"; 754 const char *msg = "Kernel samples will not be resolved.\n";
755 /* 755 /*
756 * As we do lazy loading of symtabs we only will know if the 756 * As we do lazy loading of symtabs we only will know if the
@@ -764,8 +764,7 @@ static void perf_event__process_sample(struct perf_tool *tool,
764 * invalid --vmlinux ;-) 764 * invalid --vmlinux ;-)
765 */ 765 */
766 if (!machine->kptr_restrict_warned && !top->vmlinux_warned && 766 if (!machine->kptr_restrict_warned && !top->vmlinux_warned &&
767 al.map == machine->vmlinux_maps[MAP__FUNCTION] && 767 __map__is_kernel(al.map) && map__has_symbols(al.map)) {
768 RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION])) {
769 if (symbol_conf.vmlinux_name) { 768 if (symbol_conf.vmlinux_name) {
770 char serr[256]; 769 char serr[256];
771 dso__strerror_load(al.map->dso, serr, sizeof(serr)); 770 dso__strerror_load(al.map->dso, serr, sizeof(serr));
@@ -1265,7 +1264,7 @@ int cmd_top(int argc, const char **argv)
1265 .proc_map_timeout = 500, 1264 .proc_map_timeout = 500,
1266 .overwrite = 1, 1265 .overwrite = 1,
1267 }, 1266 },
1268 .max_stack = sysctl_perf_event_max_stack, 1267 .max_stack = sysctl__max_stack(),
1269 .sym_pcnt_filter = 5, 1268 .sym_pcnt_filter = 5,
1270 .nr_threads_synthesize = UINT_MAX, 1269 .nr_threads_synthesize = UINT_MAX,
1271 }; 1270 };
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 3ad17ee89403..560aed7da36a 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -2024,8 +2024,7 @@ static int trace__pgfault(struct trace *trace,
2024 if (trace->summary_only) 2024 if (trace->summary_only)
2025 goto out; 2025 goto out;
2026 2026
2027 thread__find_addr_location(thread, sample->cpumode, MAP__FUNCTION, 2027 thread__find_symbol(thread, sample->cpumode, sample->ip, &al);
2028 sample->ip, &al);
2029 2028
2030 trace__fprintf_entry_head(trace, thread, 0, true, sample->time, trace->output); 2029 trace__fprintf_entry_head(trace, thread, 0, true, sample->time, trace->output);
2031 2030
@@ -2037,12 +2036,10 @@ static int trace__pgfault(struct trace *trace,
2037 2036
2038 fprintf(trace->output, "] => "); 2037 fprintf(trace->output, "] => ");
2039 2038
2040 thread__find_addr_location(thread, sample->cpumode, MAP__VARIABLE, 2039 thread__find_symbol(thread, sample->cpumode, sample->addr, &al);
2041 sample->addr, &al);
2042 2040
2043 if (!al.map) { 2041 if (!al.map) {
2044 thread__find_addr_location(thread, sample->cpumode, 2042 thread__find_symbol(thread, sample->cpumode, sample->addr, &al);
2045 MAP__FUNCTION, sample->addr, &al);
2046 2043
2047 if (al.map) 2044 if (al.map)
2048 map_type = 'x'; 2045 map_type = 'x';
@@ -3165,7 +3162,7 @@ int cmd_trace(int argc, const char **argv)
3165 mmap_pages_user_set = false; 3162 mmap_pages_user_set = false;
3166 3163
3167 if (trace.max_stack == UINT_MAX) { 3164 if (trace.max_stack == UINT_MAX) {
3168 trace.max_stack = input_name ? PERF_MAX_STACK_DEPTH : sysctl_perf_event_max_stack; 3165 trace.max_stack = input_name ? PERF_MAX_STACK_DEPTH : sysctl__max_stack();
3169 max_stack_user_set = false; 3166 max_stack_user_set = false;
3170 } 3167 }
3171 3168
diff --git a/tools/perf/check-headers.sh b/tools/perf/check-headers.sh
index 9aff89bc7535..10f333e2e825 100755
--- a/tools/perf/check-headers.sh
+++ b/tools/perf/check-headers.sh
@@ -55,22 +55,26 @@ include/uapi/asm-generic/ioctls.h
55include/uapi/asm-generic/mman-common.h 55include/uapi/asm-generic/mman-common.h
56' 56'
57 57
58check () { 58check_2 () {
59 file=$1 59 file1=$1
60 file2=$2
60 61
61 shift 62 shift
62 opts= 63 shift
63 while [ -n "$*" ]; do
64 opts="$opts \"$1\""
65 shift
66 done
67 64
68 cmd="diff $opts ../$file ../../$file > /dev/null" 65 cmd="diff $* $file1 $file2 > /dev/null"
69 66
70 test -f ../../$file && 67 test -f $file2 &&
71 eval $cmd || echo "Warning: Kernel ABI header at 'tools/$file' differs from latest version at '$file'" >&2 68 eval $cmd || echo "Warning: Kernel ABI header at 'tools/$file' differs from latest version at '$file'" >&2
72} 69}
73 70
71check () {
72 file=$1
73
74 shift
75
76 check_2 ../$file ../../$file $*
77}
74 78
75# Check if we have the kernel headers (tools/perf/../../include), else 79# Check if we have the kernel headers (tools/perf/../../include), else
76# we're probably on a detached tarball, so no point in trying to check 80# we're probably on a detached tarball, so no point in trying to check
@@ -83,7 +87,7 @@ for i in $HEADERS; do
83done 87done
84 88
85# diff with extra ignore lines 89# diff with extra ignore lines
86check arch/x86/lib/memcpy_64.S -I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>" 90check arch/x86/lib/memcpy_64.S '-I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>"'
87check arch/x86/lib/memset_64.S -I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>" 91check arch/x86/lib/memset_64.S '-I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>"'
88check include/uapi/asm-generic/mman.h -I "^#include <\(uapi/\)*asm-generic/mman-common.h>" 92check include/uapi/asm-generic/mman.h '-I "^#include <\(uapi/\)*asm-generic/mman-common.h>"'
89check include/uapi/linux/mman.h -I "^#include <\(uapi/\)*asm/mman.h>" 93check include/uapi/linux/mman.h '-I "^#include <\(uapi/\)*asm/mman.h>"'
diff --git a/tools/perf/examples/bpf/5sec.c b/tools/perf/examples/bpf/5sec.c
new file mode 100644
index 000000000000..b9c203219691
--- /dev/null
+++ b/tools/perf/examples/bpf/5sec.c
@@ -0,0 +1,49 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 Description:
4
5 . Disable strace like syscall tracing (--no-syscalls), or try tracing
6 just some (-e *sleep).
7
8 . Attach a filter function to a kernel function, returning when it should
9 be considered, i.e. appear on the output.
10
11 . Run it system wide, so that any sleep of >= 5 seconds and < than 6
12 seconds gets caught.
13
14 . Ask for callgraphs using DWARF info, so that userspace can be unwound
15
16 . While this is running, run something like "sleep 5s".
17
18 . If we decide to add tv_nsec as well, then it becomes:
19
20 int probe(hrtimer_nanosleep, rqtp->tv_sec rqtp->tv_nsec)(void *ctx, int err, long sec, long nsec)
21
22 I.e. add where it comes from (rqtp->tv_nsec) and where it will be
23 accessible in the function body (nsec)
24
25 # perf trace --no-syscalls -e tools/perf/examples/bpf/5sec.c/call-graph=dwarf/
26 0.000 perf_bpf_probe:func:(ffffffff9811b5f0) tv_sec=5
27 hrtimer_nanosleep ([kernel.kallsyms])
28 __x64_sys_nanosleep ([kernel.kallsyms])
29 do_syscall_64 ([kernel.kallsyms])
30 entry_SYSCALL_64 ([kernel.kallsyms])
31 __GI___nanosleep (/usr/lib64/libc-2.26.so)
32 rpl_nanosleep (/usr/bin/sleep)
33 xnanosleep (/usr/bin/sleep)
34 main (/usr/bin/sleep)
35 __libc_start_main (/usr/lib64/libc-2.26.so)
36 _start (/usr/bin/sleep)
37 ^C#
38
39 Copyright (C) 2018 Red Hat, Inc., Arnaldo Carvalho de Melo <acme@redhat.com>
40*/
41
42#include <bpf.h>
43
44int probe(hrtimer_nanosleep, rqtp->tv_sec)(void *ctx, int err, long sec)
45{
46 return sec == 5;
47}
48
49license(GPL);
diff --git a/tools/perf/examples/bpf/empty.c b/tools/perf/examples/bpf/empty.c
new file mode 100644
index 000000000000..3776d26db9e7
--- /dev/null
+++ b/tools/perf/examples/bpf/empty.c
@@ -0,0 +1,3 @@
1#include <bpf.h>
2
3license(GPL);
diff --git a/tools/perf/include/bpf/bpf.h b/tools/perf/include/bpf/bpf.h
new file mode 100644
index 000000000000..dd764ad5efdf
--- /dev/null
+++ b/tools/perf/include/bpf/bpf.h
@@ -0,0 +1,13 @@
1// SPDX-License-Identifier: GPL-2.0
2#ifndef _PERF_BPF_H
3#define _PERF_BPF_H
4#define SEC(NAME) __attribute__((section(NAME), used))
5
6#define probe(function, vars) \
7 SEC(#function "=" #function " " #vars) function
8
9#define license(name) \
10char _license[] SEC("license") = #name; \
11int _version SEC("version") = LINUX_VERSION_CODE;
12
13#endif /* _PERF_BPF_H */
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 20a08cb32332..51c81509a315 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -238,7 +238,7 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
238 (*argc)--; 238 (*argc)--;
239 } else if (strstarts(cmd, CMD_DEBUGFS_DIR)) { 239 } else if (strstarts(cmd, CMD_DEBUGFS_DIR)) {
240 tracing_path_set(cmd + strlen(CMD_DEBUGFS_DIR)); 240 tracing_path_set(cmd + strlen(CMD_DEBUGFS_DIR));
241 fprintf(stderr, "dir: %s\n", tracing_path); 241 fprintf(stderr, "dir: %s\n", tracing_path_mount());
242 if (envchanged) 242 if (envchanged)
243 *envchanged = 1; 243 *envchanged = 1;
244 } else if (!strcmp(cmd, "--list-cmds")) { 244 } else if (!strcmp(cmd, "--list-cmds")) {
@@ -421,22 +421,11 @@ void pthread__unblock_sigwinch(void)
421 pthread_sigmask(SIG_UNBLOCK, &set, NULL); 421 pthread_sigmask(SIG_UNBLOCK, &set, NULL);
422} 422}
423 423
424#ifdef _SC_LEVEL1_DCACHE_LINESIZE
425#define cache_line_size(cacheline_sizep) *cacheline_sizep = sysconf(_SC_LEVEL1_DCACHE_LINESIZE)
426#else
427static void cache_line_size(int *cacheline_sizep)
428{
429 if (sysfs__read_int("devices/system/cpu/cpu0/cache/index0/coherency_line_size", cacheline_sizep))
430 pr_debug("cannot determine cache line size");
431}
432#endif
433
434int main(int argc, const char **argv) 424int main(int argc, const char **argv)
435{ 425{
436 int err; 426 int err;
437 const char *cmd; 427 const char *cmd;
438 char sbuf[STRERR_BUFSIZE]; 428 char sbuf[STRERR_BUFSIZE];
439 int value;
440 429
441 /* libsubcmd init */ 430 /* libsubcmd init */
442 exec_cmd_init("perf", PREFIX, PERF_EXEC_PATH, EXEC_PATH_ENVIRONMENT); 431 exec_cmd_init("perf", PREFIX, PERF_EXEC_PATH, EXEC_PATH_ENVIRONMENT);
@@ -444,13 +433,6 @@ int main(int argc, const char **argv)
444 433
445 /* The page_size is placed in util object. */ 434 /* The page_size is placed in util object. */
446 page_size = sysconf(_SC_PAGE_SIZE); 435 page_size = sysconf(_SC_PAGE_SIZE);
447 cache_line_size(&cacheline_size);
448
449 if (sysctl__read_int("kernel/perf_event_max_stack", &value) == 0)
450 sysctl_perf_event_max_stack = value;
451
452 if (sysctl__read_int("kernel/perf_event_max_contexts_per_stack", &value) == 0)
453 sysctl_perf_event_max_contexts_per_stack = value;
454 436
455 cmd = extract_argv0_path(argv[0]); 437 cmd = extract_argv0_path(argv[0]);
456 if (!cmd) 438 if (!cmd)
@@ -458,15 +440,11 @@ int main(int argc, const char **argv)
458 440
459 srandom(time(NULL)); 441 srandom(time(NULL));
460 442
461 perf_config__init();
462 err = perf_config(perf_default_config, NULL); 443 err = perf_config(perf_default_config, NULL);
463 if (err) 444 if (err)
464 return err; 445 return err;
465 set_buildid_dir(NULL); 446 set_buildid_dir(NULL);
466 447
467 /* get debugfs/tracefs mount point from /proc/mounts */
468 tracing_path_mount();
469
470 /* 448 /*
471 * "perf-xxxx" is the same as "perf xxxx", but we obviously: 449 * "perf-xxxx" is the same as "perf xxxx", but we obviously:
472 * 450 *
diff --git a/tools/perf/pmu-events/arch/s390/mapfile.csv b/tools/perf/pmu-events/arch/s390/mapfile.csv
index ca7682748a4b..78bcf7f8e206 100644
--- a/tools/perf/pmu-events/arch/s390/mapfile.csv
+++ b/tools/perf/pmu-events/arch/s390/mapfile.csv
@@ -1,6 +1,6 @@
1Family-model,Version,Filename,EventType 1Family-model,Version,Filename,EventType
2209[78],1,cf_z10,core 2^IBM.209[78].*[13]\.[1-5].[[:xdigit:]]+$,1,cf_z10,core
3281[78],1,cf_z196,core 3^IBM.281[78].*[13]\.[1-5].[[:xdigit:]]+$,1,cf_z196,core
4282[78],1,cf_zec12,core 4^IBM.282[78].*[13]\.[1-5].[[:xdigit:]]+$,1,cf_zec12,core
5296[45],1,cf_z13,core 5^IBM.296[45].*[13]\.[1-5].[[:xdigit:]]+$,1,cf_z13,core
63906,3,cf_z14,core 6^IBM.390[67].*[13]\.[1-5].[[:xdigit:]]+$,3,cf_z14,core
diff --git a/tools/perf/pmu-events/arch/x86/mapfile.csv b/tools/perf/pmu-events/arch/x86/mapfile.csv
index 93656f2fd53a..7e3cce3bcf3b 100644
--- a/tools/perf/pmu-events/arch/x86/mapfile.csv
+++ b/tools/perf/pmu-events/arch/x86/mapfile.csv
@@ -29,7 +29,6 @@ GenuineIntel-6-4D,v13,silvermont,core
29GenuineIntel-6-4C,v13,silvermont,core 29GenuineIntel-6-4C,v13,silvermont,core
30GenuineIntel-6-2A,v15,sandybridge,core 30GenuineIntel-6-2A,v15,sandybridge,core
31GenuineIntel-6-2C,v2,westmereep-dp,core 31GenuineIntel-6-2C,v2,westmereep-dp,core
32GenuineIntel-6-2C,v2,westmereep-dp,core
33GenuineIntel-6-25,v2,westmereep-sp,core 32GenuineIntel-6-25,v2,westmereep-sp,core
34GenuineIntel-6-2F,v2,westmereex,core 33GenuineIntel-6-2F,v2,westmereex,core
35GenuineIntel-6-55,v1,skylakex,core 34GenuineIntel-6-55,v1,skylakex,core
diff --git a/tools/perf/tests/attr/test-record-group-sampling b/tools/perf/tests/attr/test-record-group-sampling
index f906b793196f..8a33ca4f9e1f 100644
--- a/tools/perf/tests/attr/test-record-group-sampling
+++ b/tools/perf/tests/attr/test-record-group-sampling
@@ -35,3 +35,6 @@ inherit=0
35# sampling disabled 35# sampling disabled
36sample_freq=0 36sample_freq=0
37sample_period=0 37sample_period=0
38freq=0
39write_backward=0
40sample_id_all=0
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index cac8f8889bc3..2bde505e2e7e 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -654,6 +654,15 @@ static int perf_test__list(int argc, const char **argv)
654 continue; 654 continue;
655 655
656 pr_info("%2d: %s\n", i, t->desc); 656 pr_info("%2d: %s\n", i, t->desc);
657
658 if (t->subtest.get_nr) {
659 int subn = t->subtest.get_nr();
660 int subi;
661
662 for (subi = 0; subi < subn; subi++)
663 pr_info("%2d:%1d: %s\n", i, subi + 1,
664 t->subtest.get_desc(subi));
665 }
657 } 666 }
658 667
659 perf_test__list_shell(argc, argv, i); 668 perf_test__list_shell(argc, argv, i);
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c
index 99936352df4f..afa4ce21ba7c 100644
--- a/tools/perf/tests/code-reading.c
+++ b/tools/perf/tests/code-reading.c
@@ -236,14 +236,13 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode,
236 236
237 pr_debug("Reading object code for memory address: %#"PRIx64"\n", addr); 237 pr_debug("Reading object code for memory address: %#"PRIx64"\n", addr);
238 238
239 thread__find_addr_map(thread, cpumode, MAP__FUNCTION, addr, &al); 239 if (!thread__find_map(thread, cpumode, addr, &al) || !al.map->dso) {
240 if (!al.map || !al.map->dso) {
241 if (cpumode == PERF_RECORD_MISC_HYPERVISOR) { 240 if (cpumode == PERF_RECORD_MISC_HYPERVISOR) {
242 pr_debug("Hypervisor address can not be resolved - skipping\n"); 241 pr_debug("Hypervisor address can not be resolved - skipping\n");
243 return 0; 242 return 0;
244 } 243 }
245 244
246 pr_debug("thread__find_addr_map failed\n"); 245 pr_debug("thread__find_map failed\n");
247 return -1; 246 return -1;
248 } 247 }
249 248
diff --git a/tools/perf/tests/hists_common.c b/tools/perf/tests/hists_common.c
index f7c5b613d667..b889a28fd80b 100644
--- a/tools/perf/tests/hists_common.c
+++ b/tools/perf/tests/hists_common.c
@@ -131,20 +131,20 @@ struct machine *setup_fake_machine(struct machines *machines)
131 goto out; 131 goto out;
132 132
133 /* emulate dso__load() */ 133 /* emulate dso__load() */
134 dso__set_loaded(dso, MAP__FUNCTION); 134 dso__set_loaded(dso);
135 135
136 for (k = 0; k < fake_symbols[i].nr_syms; k++) { 136 for (k = 0; k < fake_symbols[i].nr_syms; k++) {
137 struct symbol *sym; 137 struct symbol *sym;
138 struct fake_sym *fsym = &fake_symbols[i].syms[k]; 138 struct fake_sym *fsym = &fake_symbols[i].syms[k];
139 139
140 sym = symbol__new(fsym->start, fsym->length, 140 sym = symbol__new(fsym->start, fsym->length,
141 STB_GLOBAL, fsym->name); 141 STB_GLOBAL, STT_FUNC, fsym->name);
142 if (sym == NULL) { 142 if (sym == NULL) {
143 dso__put(dso); 143 dso__put(dso);
144 goto out; 144 goto out;
145 } 145 }
146 146
147 symbols__insert(&dso->symbols[MAP__FUNCTION], sym); 147 symbols__insert(&dso->symbols, sym);
148 } 148 }
149 149
150 dso__put(dso); 150 dso__put(dso);
diff --git a/tools/perf/tests/mmap-thread-lookup.c b/tools/perf/tests/mmap-thread-lookup.c
index 868d82b501f4..b1af2499a3c9 100644
--- a/tools/perf/tests/mmap-thread-lookup.c
+++ b/tools/perf/tests/mmap-thread-lookup.c
@@ -188,9 +188,8 @@ static int mmap_events(synth_cb synth)
188 188
189 pr_debug("looking for map %p\n", td->map); 189 pr_debug("looking for map %p\n", td->map);
190 190
191 thread__find_addr_map(thread, 191 thread__find_map(thread, PERF_RECORD_MISC_USER,
192 PERF_RECORD_MISC_USER, MAP__FUNCTION, 192 (unsigned long) (td->map + 1), &al);
193 (unsigned long) (td->map + 1), &al);
194 193
195 thread__put(thread); 194 thread__put(thread);
196 195
@@ -218,7 +217,7 @@ static int mmap_events(synth_cb synth)
218 * perf_event__synthesize_threads (global) 217 * perf_event__synthesize_threads (global)
219 * 218 *
220 * We test we can find all memory maps via: 219 * We test we can find all memory maps via:
221 * thread__find_addr_map 220 * thread__find_map
222 * 221 *
223 * by using all thread objects. 222 * by using all thread objects.
224 */ 223 */
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c
index 18b06444f230..b9ebe15afb13 100644
--- a/tools/perf/tests/parse-events.c
+++ b/tools/perf/tests/parse-events.c
@@ -1309,18 +1309,26 @@ static int test__checkevent_config_cache(struct perf_evlist *evlist)
1309 return 0; 1309 return 0;
1310} 1310}
1311 1311
1312static int test__intel_pt(struct perf_evlist *evlist)
1313{
1314 struct perf_evsel *evsel = perf_evlist__first(evlist);
1315
1316 TEST_ASSERT_VAL("wrong name setting", strcmp(evsel->name, "intel_pt//u") == 0);
1317 return 0;
1318}
1319
1312static int count_tracepoints(void) 1320static int count_tracepoints(void)
1313{ 1321{
1314 struct dirent *events_ent; 1322 struct dirent *events_ent;
1315 DIR *events_dir; 1323 DIR *events_dir;
1316 int cnt = 0; 1324 int cnt = 0;
1317 1325
1318 events_dir = opendir(tracing_events_path); 1326 events_dir = tracing_events__opendir();
1319 1327
1320 TEST_ASSERT_VAL("Can't open events dir", events_dir); 1328 TEST_ASSERT_VAL("Can't open events dir", events_dir);
1321 1329
1322 while ((events_ent = readdir(events_dir))) { 1330 while ((events_ent = readdir(events_dir))) {
1323 char sys_path[PATH_MAX]; 1331 char *sys_path;
1324 struct dirent *sys_ent; 1332 struct dirent *sys_ent;
1325 DIR *sys_dir; 1333 DIR *sys_dir;
1326 1334
@@ -1331,8 +1339,8 @@ static int count_tracepoints(void)
1331 || !strcmp(events_ent->d_name, "header_page")) 1339 || !strcmp(events_ent->d_name, "header_page"))
1332 continue; 1340 continue;
1333 1341
1334 scnprintf(sys_path, PATH_MAX, "%s/%s", 1342 sys_path = get_events_file(events_ent->d_name);
1335 tracing_events_path, events_ent->d_name); 1343 TEST_ASSERT_VAL("Can't get sys path", sys_path);
1336 1344
1337 sys_dir = opendir(sys_path); 1345 sys_dir = opendir(sys_path);
1338 TEST_ASSERT_VAL("Can't open sys dir", sys_dir); 1346 TEST_ASSERT_VAL("Can't open sys dir", sys_dir);
@@ -1348,6 +1356,7 @@ static int count_tracepoints(void)
1348 } 1356 }
1349 1357
1350 closedir(sys_dir); 1358 closedir(sys_dir);
1359 put_events_file(sys_path);
1351 } 1360 }
1352 1361
1353 closedir(events_dir); 1362 closedir(events_dir);
@@ -1637,6 +1646,11 @@ static struct evlist_test test__events[] = {
1637 .check = test__checkevent_config_cache, 1646 .check = test__checkevent_config_cache,
1638 .id = 51, 1647 .id = 51,
1639 }, 1648 },
1649 {
1650 .name = "intel_pt//u",
1651 .check = test__intel_pt,
1652 .id = 52,
1653 },
1640}; 1654};
1641 1655
1642static struct evlist_test test__events_pmu[] = { 1656static struct evlist_test test__events_pmu[] = {
diff --git a/tools/perf/tests/shell/record+probe_libc_inet_pton.sh b/tools/perf/tests/shell/record+probe_libc_inet_pton.sh
index 1ecc1f0ff84a..650b208f700f 100755
--- a/tools/perf/tests/shell/record+probe_libc_inet_pton.sh
+++ b/tools/perf/tests/shell/record+probe_libc_inet_pton.sh
@@ -16,20 +16,18 @@ nm -g $libc 2>/dev/null | fgrep -q inet_pton || exit 254
16trace_libc_inet_pton_backtrace() { 16trace_libc_inet_pton_backtrace() {
17 idx=0 17 idx=0
18 expected[0]="ping[][0-9 \.:]+probe_libc:inet_pton: \([[:xdigit:]]+\)" 18 expected[0]="ping[][0-9 \.:]+probe_libc:inet_pton: \([[:xdigit:]]+\)"
19 expected[1]=".*inet_pton[[:space:]]\($libc\)$" 19 expected[1]=".*inet_pton\+0x[[:xdigit:]]+[[:space:]]\($libc|inlined\)$"
20 case "$(uname -m)" in 20 case "$(uname -m)" in
21 s390x) 21 s390x)
22 eventattr='call-graph=dwarf' 22 eventattr='call-graph=dwarf,max-stack=4'
23 expected[2]="gaih_inet.*[[:space:]]\($libc|inlined\)$" 23 expected[2]="gaih_inet.*\+0x[[:xdigit:]]+[[:space:]]\($libc|inlined\)$"
24 expected[3]="__GI_getaddrinfo[[:space:]]\($libc|inlined\)$" 24 expected[3]="(__GI_)?getaddrinfo\+0x[[:xdigit:]]+[[:space:]]\($libc|inlined\)$"
25 expected[4]="main[[:space:]]\(.*/bin/ping.*\)$" 25 expected[4]="main\+0x[[:xdigit:]]+[[:space:]]\(.*/bin/ping.*\)$"
26 expected[5]="__libc_start_main[[:space:]]\($libc\)$"
27 expected[6]="_start[[:space:]]\(.*/bin/ping.*\)$"
28 ;; 26 ;;
29 *) 27 *)
30 eventattr='max-stack=3' 28 eventattr='max-stack=3'
31 expected[2]="getaddrinfo[[:space:]]\($libc\)$" 29 expected[2]="getaddrinfo\+0x[[:xdigit:]]+[[:space:]]\($libc\)$"
32 expected[3]=".*\(.*/bin/ping.*\)$" 30 expected[3]=".*\+0x[[:xdigit:]]+[[:space:]]\(.*/bin/ping.*\)$"
33 ;; 31 ;;
34 esac 32 esac
35 33
diff --git a/tools/perf/tests/topology.c b/tools/perf/tests/topology.c
index 17cb1bb3448c..40e30a26b23c 100644
--- a/tools/perf/tests/topology.c
+++ b/tools/perf/tests/topology.c
@@ -70,6 +70,27 @@ static int check_cpu_topology(char *path, struct cpu_map *map)
70 session = perf_session__new(&data, false, NULL); 70 session = perf_session__new(&data, false, NULL);
71 TEST_ASSERT_VAL("can't get session", session); 71 TEST_ASSERT_VAL("can't get session", session);
72 72
73 /* On platforms with large numbers of CPUs process_cpu_topology()
74 * might issue an error while reading the perf.data file section
75 * HEADER_CPU_TOPOLOGY and the cpu_topology_map pointed to by member
76 * cpu is a NULL pointer.
77 * Example: On s390
78 * CPU 0 is on core_id 0 and physical_package_id 6
79 * CPU 1 is on core_id 1 and physical_package_id 3
80 *
81 * Core_id and physical_package_id are platform and architecture
82 * dependend and might have higher numbers than the CPU id.
83 * This actually depends on the configuration.
84 *
85 * In this case process_cpu_topology() prints error message:
86 * "socket_id number is too big. You may need to upgrade the
87 * perf tool."
88 *
89 * This is the reason why this test might be skipped.
90 */
91 if (!session->header.env.cpu)
92 return TEST_SKIP;
93
73 for (i = 0; i < session->header.env.nr_cpus_avail; i++) { 94 for (i = 0; i < session->header.env.nr_cpus_avail; i++) {
74 if (!cpu_map__has(map, i)) 95 if (!cpu_map__has(map, i))
75 continue; 96 continue;
@@ -95,7 +116,7 @@ int test__session_topology(struct test *test __maybe_unused, int subtest __maybe
95{ 116{
96 char path[PATH_MAX]; 117 char path[PATH_MAX];
97 struct cpu_map *map; 118 struct cpu_map *map;
98 int ret = -1; 119 int ret = TEST_FAIL;
99 120
100 TEST_ASSERT_VAL("can't get templ file", !get_temp(path)); 121 TEST_ASSERT_VAL("can't get templ file", !get_temp(path));
101 122
@@ -110,12 +131,9 @@ int test__session_topology(struct test *test __maybe_unused, int subtest __maybe
110 goto free_path; 131 goto free_path;
111 } 132 }
112 133
113 if (check_cpu_topology(path, map)) 134 ret = check_cpu_topology(path, map);
114 goto free_map;
115 ret = 0;
116
117free_map:
118 cpu_map__put(map); 135 cpu_map__put(map);
136
119free_path: 137free_path:
120 unlink(path); 138 unlink(path);
121 return ret; 139 return ret;
diff --git a/tools/perf/tests/vmlinux-kallsyms.c b/tools/perf/tests/vmlinux-kallsyms.c
index 1e5adb65632a..7691980b7df1 100644
--- a/tools/perf/tests/vmlinux-kallsyms.c
+++ b/tools/perf/tests/vmlinux-kallsyms.c
@@ -19,8 +19,7 @@ int test__vmlinux_matches_kallsyms(struct test *test __maybe_unused, int subtest
19 struct symbol *sym; 19 struct symbol *sym;
20 struct map *kallsyms_map, *vmlinux_map, *map; 20 struct map *kallsyms_map, *vmlinux_map, *map;
21 struct machine kallsyms, vmlinux; 21 struct machine kallsyms, vmlinux;
22 enum map_type type = MAP__FUNCTION; 22 struct maps *maps = machine__kernel_maps(&vmlinux);
23 struct maps *maps = &vmlinux.kmaps.maps[type];
24 u64 mem_start, mem_end; 23 u64 mem_start, mem_end;
25 bool header_printed; 24 bool header_printed;
26 25
@@ -56,7 +55,7 @@ int test__vmlinux_matches_kallsyms(struct test *test __maybe_unused, int subtest
56 * be compacted against the list of modules found in the "vmlinux" 55 * be compacted against the list of modules found in the "vmlinux"
57 * code and with the one got from /proc/modules from the "kallsyms" code. 56 * code and with the one got from /proc/modules from the "kallsyms" code.
58 */ 57 */
59 if (machine__load_kallsyms(&kallsyms, "/proc/kallsyms", type) <= 0) { 58 if (machine__load_kallsyms(&kallsyms, "/proc/kallsyms") <= 0) {
60 pr_debug("dso__load_kallsyms "); 59 pr_debug("dso__load_kallsyms ");
61 goto out; 60 goto out;
62 } 61 }
@@ -94,7 +93,7 @@ int test__vmlinux_matches_kallsyms(struct test *test __maybe_unused, int subtest
94 * maps__reloc_vmlinux will notice and set proper ->[un]map_ip routines 93 * maps__reloc_vmlinux will notice and set proper ->[un]map_ip routines
95 * to fixup the symbols. 94 * to fixup the symbols.
96 */ 95 */
97 if (machine__load_vmlinux_path(&vmlinux, type) <= 0) { 96 if (machine__load_vmlinux_path(&vmlinux) <= 0) {
98 pr_debug("Couldn't find a vmlinux that matches the kernel running on this machine, skipping test\n"); 97 pr_debug("Couldn't find a vmlinux that matches the kernel running on this machine, skipping test\n");
99 err = TEST_SKIP; 98 err = TEST_SKIP;
100 goto out; 99 goto out;
@@ -108,7 +107,7 @@ int test__vmlinux_matches_kallsyms(struct test *test __maybe_unused, int subtest
108 * in the kallsyms dso. For the ones that are in both, check its names and 107 * in the kallsyms dso. For the ones that are in both, check its names and
109 * end addresses too. 108 * end addresses too.
110 */ 109 */
111 for (nd = rb_first(&vmlinux_map->dso->symbols[type]); nd; nd = rb_next(nd)) { 110 map__for_each_symbol(vmlinux_map, sym, nd) {
112 struct symbol *pair, *first_pair; 111 struct symbol *pair, *first_pair;
113 112
114 sym = rb_entry(nd, struct symbol, rb_node); 113 sym = rb_entry(nd, struct symbol, rb_node);
@@ -119,8 +118,7 @@ int test__vmlinux_matches_kallsyms(struct test *test __maybe_unused, int subtest
119 mem_start = vmlinux_map->unmap_ip(vmlinux_map, sym->start); 118 mem_start = vmlinux_map->unmap_ip(vmlinux_map, sym->start);
120 mem_end = vmlinux_map->unmap_ip(vmlinux_map, sym->end); 119 mem_end = vmlinux_map->unmap_ip(vmlinux_map, sym->end);
121 120
122 first_pair = machine__find_kernel_symbol(&kallsyms, type, 121 first_pair = machine__find_kernel_symbol(&kallsyms, mem_start, NULL);
123 mem_start, NULL);
124 pair = first_pair; 122 pair = first_pair;
125 123
126 if (pair && UM(pair->start) == mem_start) { 124 if (pair && UM(pair->start) == mem_start) {
@@ -149,7 +147,7 @@ next_pair:
149 */ 147 */
150 continue; 148 continue;
151 } else { 149 } else {
152 pair = machine__find_kernel_symbol_by_name(&kallsyms, type, sym->name, NULL); 150 pair = machine__find_kernel_symbol_by_name(&kallsyms, sym->name, NULL);
153 if (pair) { 151 if (pair) {
154 if (UM(pair->start) == mem_start) 152 if (UM(pair->start) == mem_start)
155 goto next_pair; 153 goto next_pair;
@@ -183,7 +181,7 @@ next_pair:
183 * so use the short name, less descriptive but the same ("[kernel]" in 181 * so use the short name, less descriptive but the same ("[kernel]" in
184 * both cases. 182 * both cases.
185 */ 183 */
186 pair = map_groups__find_by_name(&kallsyms.kmaps, type, 184 pair = map_groups__find_by_name(&kallsyms.kmaps,
187 (map->dso->kernel ? 185 (map->dso->kernel ?
188 map->dso->short_name : 186 map->dso->short_name :
189 map->dso->name)); 187 map->dso->name));
@@ -206,7 +204,7 @@ next_pair:
206 mem_start = vmlinux_map->unmap_ip(vmlinux_map, map->start); 204 mem_start = vmlinux_map->unmap_ip(vmlinux_map, map->start);
207 mem_end = vmlinux_map->unmap_ip(vmlinux_map, map->end); 205 mem_end = vmlinux_map->unmap_ip(vmlinux_map, map->end);
208 206
209 pair = map_groups__find(&kallsyms.kmaps, type, mem_start); 207 pair = map_groups__find(&kallsyms.kmaps, mem_start);
210 if (pair == NULL || pair->priv) 208 if (pair == NULL || pair->priv)
211 continue; 209 continue;
212 210
@@ -228,7 +226,7 @@ next_pair:
228 226
229 header_printed = false; 227 header_printed = false;
230 228
231 maps = &kallsyms.kmaps.maps[type]; 229 maps = machine__kernel_maps(&kallsyms);
232 230
233 for (map = maps__first(maps); map; map = map__next(map)) { 231 for (map = maps__first(maps); map; map = map__next(map)) {
234 if (!map->priv) { 232 if (!map->priv) {
diff --git a/tools/perf/trace/beauty/prctl_option.sh b/tools/perf/trace/beauty/prctl_option.sh
index 0be4138fbe71..f24722146ebe 100755
--- a/tools/perf/trace/beauty/prctl_option.sh
+++ b/tools/perf/trace/beauty/prctl_option.sh
@@ -1,6 +1,6 @@
1#!/bin/sh 1#!/bin/sh
2 2
3header_dir=$1 3[ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/
4 4
5printf "static const char *prctl_options[] = {\n" 5printf "static const char *prctl_options[] = {\n"
6regex='^#define[[:space:]]+PR_([GS]ET\w+)[[:space:]]*([[:xdigit:]]+).*' 6regex='^#define[[:space:]]+PR_([GS]ET\w+)[[:space:]]*([[:xdigit:]]+).*'
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index 3781d74088a7..8be40fa903aa 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -695,6 +695,7 @@ static int annotate_browser__run(struct annotate_browser *browser,
695 "O Bump offset level (jump targets -> +call -> all -> cycle thru)\n" 695 "O Bump offset level (jump targets -> +call -> all -> cycle thru)\n"
696 "s Toggle source code view\n" 696 "s Toggle source code view\n"
697 "t Circulate percent, total period, samples view\n" 697 "t Circulate percent, total period, samples view\n"
698 "c Show min/max cycle\n"
698 "/ Search string\n" 699 "/ Search string\n"
699 "k Toggle line numbers\n" 700 "k Toggle line numbers\n"
700 "P Print to [symbol_name].annotation file.\n" 701 "P Print to [symbol_name].annotation file.\n"
@@ -791,6 +792,13 @@ show_sup_ins:
791 notes->options->show_total_period = true; 792 notes->options->show_total_period = true;
792 annotation__update_column_widths(notes); 793 annotation__update_column_widths(notes);
793 continue; 794 continue;
795 case 'c':
796 if (notes->options->show_minmax_cycle)
797 notes->options->show_minmax_cycle = false;
798 else
799 notes->options->show_minmax_cycle = true;
800 annotation__update_column_widths(notes);
801 continue;
794 case K_LEFT: 802 case K_LEFT:
795 case K_ESC: 803 case K_ESC:
796 case 'q': 804 case 'q':
diff --git a/tools/perf/ui/browsers/map.c b/tools/perf/ui/browsers/map.c
index e03fa75f108a..5b8b8c637686 100644
--- a/tools/perf/ui/browsers/map.c
+++ b/tools/perf/ui/browsers/map.c
@@ -104,7 +104,7 @@ int map__browse(struct map *map)
104{ 104{
105 struct map_browser mb = { 105 struct map_browser mb = {
106 .b = { 106 .b = {
107 .entries = &map->dso->symbols[map->type], 107 .entries = &map->dso->symbols,
108 .refresh = ui_browser__rb_tree_refresh, 108 .refresh = ui_browser__rb_tree_refresh,
109 .seek = ui_browser__rb_tree_seek, 109 .seek = ui_browser__rb_tree_seek,
110 .write = map_browser__write, 110 .write = map_browser__write,
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index 6832fcb2e6ff..c1eb476da91b 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -819,8 +819,7 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
819 } 819 }
820 820
821 if (h->ms.map == NULL && verbose > 1) { 821 if (h->ms.map == NULL && verbose > 1) {
822 __map_groups__fprintf_maps(h->thread->mg, 822 map_groups__fprintf(h->thread->mg, fp);
823 MAP__FUNCTION, fp);
824 fprintf(fp, "%.10s end\n", graph_dotted_line); 823 fprintf(fp, "%.10s end\n", graph_dotted_line);
825 } 824 }
826 } 825 }
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index 8052373bcd6a..5d4c45b76895 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -152,6 +152,8 @@ libperf-y += perf-hooks.o
152libperf-$(CONFIG_CXX) += c++/ 152libperf-$(CONFIG_CXX) += c++/
153 153
154CFLAGS_config.o += -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))" 154CFLAGS_config.o += -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))"
155CFLAGS_llvm-utils.o += -DPERF_INCLUDE_DIR="BUILD_STR($(perf_include_dir_SQ))"
156
155# avoid compiler warnings in 32-bit mode 157# avoid compiler warnings in 32-bit mode
156CFLAGS_genelf_debug.o += -Wno-packed 158CFLAGS_genelf_debug.o += -Wno-packed
157 159
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 536ee148bff8..71897689dacf 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -760,6 +760,15 @@ static int __symbol__account_cycles(struct annotation *notes,
760 ch[offset].num_aggr++; 760 ch[offset].num_aggr++;
761 ch[offset].cycles_aggr += cycles; 761 ch[offset].cycles_aggr += cycles;
762 762
763 if (cycles > ch[offset].cycles_max)
764 ch[offset].cycles_max = cycles;
765
766 if (ch[offset].cycles_min) {
767 if (cycles && cycles < ch[offset].cycles_min)
768 ch[offset].cycles_min = cycles;
769 } else
770 ch[offset].cycles_min = cycles;
771
763 if (!have_start && ch[offset].have_start) 772 if (!have_start && ch[offset].have_start)
764 return 0; 773 return 0;
765 if (ch[offset].num) { 774 if (ch[offset].num) {
@@ -953,8 +962,11 @@ void annotation__compute_ipc(struct annotation *notes, size_t size)
953 if (ch->have_start) 962 if (ch->have_start)
954 annotation__count_and_fill(notes, ch->start, offset, ch); 963 annotation__count_and_fill(notes, ch->start, offset, ch);
955 al = notes->offsets[offset]; 964 al = notes->offsets[offset];
956 if (al && ch->num_aggr) 965 if (al && ch->num_aggr) {
957 al->cycles = ch->cycles_aggr / ch->num_aggr; 966 al->cycles = ch->cycles_aggr / ch->num_aggr;
967 al->cycles_max = ch->cycles_max;
968 al->cycles_min = ch->cycles_min;
969 }
958 notes->have_cycles = true; 970 notes->have_cycles = true;
959 } 971 }
960 } 972 }
@@ -1263,6 +1275,9 @@ annotation_line__print(struct annotation_line *al, struct symbol *sym, u64 start
1263 max_percent = sample->percent; 1275 max_percent = sample->percent;
1264 } 1276 }
1265 1277
1278 if (al->samples_nr > nr_percent)
1279 nr_percent = al->samples_nr;
1280
1266 if (max_percent < min_pcnt) 1281 if (max_percent < min_pcnt)
1267 return -1; 1282 return -1;
1268 1283
@@ -1950,6 +1965,7 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,
1950 u64 len; 1965 u64 len;
1951 int width = symbol_conf.show_total_period ? 12 : 8; 1966 int width = symbol_conf.show_total_period ? 12 : 8;
1952 int graph_dotted_len; 1967 int graph_dotted_len;
1968 char buf[512];
1953 1969
1954 filename = strdup(dso->long_name); 1970 filename = strdup(dso->long_name);
1955 if (!filename) 1971 if (!filename)
@@ -1962,8 +1978,11 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,
1962 1978
1963 len = symbol__size(sym); 1979 len = symbol__size(sym);
1964 1980
1965 if (perf_evsel__is_group_event(evsel)) 1981 if (perf_evsel__is_group_event(evsel)) {
1966 width *= evsel->nr_members; 1982 width *= evsel->nr_members;
1983 perf_evsel__group_desc(evsel, buf, sizeof(buf));
1984 evsel_name = buf;
1985 }
1967 1986
1968 graph_dotted_len = printf(" %-*.*s| Source code & Disassembly of %s for %s (%" PRIu64 " samples)\n", 1987 graph_dotted_len = printf(" %-*.*s| Source code & Disassembly of %s for %s (%" PRIu64 " samples)\n",
1969 width, width, symbol_conf.show_total_period ? "Period" : 1988 width, width, symbol_conf.show_total_period ? "Period" :
@@ -2483,13 +2502,38 @@ static void __annotation_line__write(struct annotation_line *al, struct annotati
2483 else 2502 else
2484 obj__printf(obj, "%*s ", ANNOTATION__IPC_WIDTH - 1, "IPC"); 2503 obj__printf(obj, "%*s ", ANNOTATION__IPC_WIDTH - 1, "IPC");
2485 2504
2486 if (al->cycles) 2505 if (!notes->options->show_minmax_cycle) {
2487 obj__printf(obj, "%*" PRIu64 " ", 2506 if (al->cycles)
2507 obj__printf(obj, "%*" PRIu64 " ",
2488 ANNOTATION__CYCLES_WIDTH - 1, al->cycles); 2508 ANNOTATION__CYCLES_WIDTH - 1, al->cycles);
2489 else if (!show_title) 2509 else if (!show_title)
2490 obj__printf(obj, "%*s", ANNOTATION__CYCLES_WIDTH, " "); 2510 obj__printf(obj, "%*s",
2491 else 2511 ANNOTATION__CYCLES_WIDTH, " ");
2492 obj__printf(obj, "%*s ", ANNOTATION__CYCLES_WIDTH - 1, "Cycle"); 2512 else
2513 obj__printf(obj, "%*s ",
2514 ANNOTATION__CYCLES_WIDTH - 1,
2515 "Cycle");
2516 } else {
2517 if (al->cycles) {
2518 char str[32];
2519
2520 scnprintf(str, sizeof(str),
2521 "%" PRIu64 "(%" PRIu64 "/%" PRIu64 ")",
2522 al->cycles, al->cycles_min,
2523 al->cycles_max);
2524
2525 obj__printf(obj, "%*s ",
2526 ANNOTATION__MINMAX_CYCLES_WIDTH - 1,
2527 str);
2528 } else if (!show_title)
2529 obj__printf(obj, "%*s",
2530 ANNOTATION__MINMAX_CYCLES_WIDTH,
2531 " ");
2532 else
2533 obj__printf(obj, "%*s ",
2534 ANNOTATION__MINMAX_CYCLES_WIDTH - 1,
2535 "Cycle(min/max)");
2536 }
2493 } 2537 }
2494 2538
2495 obj__printf(obj, " "); 2539 obj__printf(obj, " ");
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index f28a9e43421d..5080b6dd98b8 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -61,6 +61,7 @@ bool ins__is_fused(struct arch *arch, const char *ins1, const char *ins2);
61 61
62#define ANNOTATION__IPC_WIDTH 6 62#define ANNOTATION__IPC_WIDTH 6
63#define ANNOTATION__CYCLES_WIDTH 6 63#define ANNOTATION__CYCLES_WIDTH 6
64#define ANNOTATION__MINMAX_CYCLES_WIDTH 19
64 65
65struct annotation_options { 66struct annotation_options {
66 bool hide_src_code, 67 bool hide_src_code,
@@ -69,7 +70,8 @@ struct annotation_options {
69 show_linenr, 70 show_linenr,
70 show_nr_jumps, 71 show_nr_jumps,
71 show_nr_samples, 72 show_nr_samples,
72 show_total_period; 73 show_total_period,
74 show_minmax_cycle;
73 u8 offset_level; 75 u8 offset_level;
74}; 76};
75 77
@@ -105,6 +107,8 @@ struct annotation_line {
105 int jump_sources; 107 int jump_sources;
106 float ipc; 108 float ipc;
107 u64 cycles; 109 u64 cycles;
110 u64 cycles_max;
111 u64 cycles_min;
108 size_t privsize; 112 size_t privsize;
109 char *path; 113 char *path;
110 u32 idx; 114 u32 idx;
@@ -186,6 +190,8 @@ struct cyc_hist {
186 u64 start; 190 u64 start;
187 u64 cycles; 191 u64 cycles;
188 u64 cycles_aggr; 192 u64 cycles_aggr;
193 u64 cycles_max;
194 u64 cycles_min;
189 u32 num; 195 u32 num;
190 u32 num_aggr; 196 u32 num_aggr;
191 u8 have_start; 197 u8 have_start;
@@ -239,6 +245,9 @@ struct annotation {
239 245
240static inline int annotation__cycles_width(struct annotation *notes) 246static inline int annotation__cycles_width(struct annotation *notes)
241{ 247{
248 if (notes->have_cycles && notes->options->show_minmax_cycle)
249 return ANNOTATION__IPC_WIDTH + ANNOTATION__MINMAX_CYCLES_WIDTH;
250
242 return notes->have_cycles ? ANNOTATION__IPC_WIDTH + ANNOTATION__CYCLES_WIDTH : 0; 251 return notes->have_cycles ? ANNOTATION__IPC_WIDTH + ANNOTATION__CYCLES_WIDTH : 0;
243} 252}
244 253
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index 857de69a5361..d056447520a2 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -1679,7 +1679,7 @@ struct sym_args {
1679static bool kern_sym_match(struct sym_args *args, const char *name, char type) 1679static bool kern_sym_match(struct sym_args *args, const char *name, char type)
1680{ 1680{
1681 /* A function with the same name, and global or the n'th found or any */ 1681 /* A function with the same name, and global or the n'th found or any */
1682 return symbol_type__is_a(type, MAP__FUNCTION) && 1682 return kallsyms__is_function(type) &&
1683 !strcmp(name, args->name) && 1683 !strcmp(name, args->name) &&
1684 ((args->global && isupper(type)) || 1684 ((args->global && isupper(type)) ||
1685 (args->selected && ++(args->cnt) == args->idx) || 1685 (args->selected && ++(args->cnt) == args->idx) ||
@@ -1784,7 +1784,7 @@ static int find_entire_kern_cb(void *arg, const char *name __maybe_unused,
1784{ 1784{
1785 struct sym_args *args = arg; 1785 struct sym_args *args = arg;
1786 1786
1787 if (!symbol_type__is_a(type, MAP__FUNCTION)) 1787 if (!kallsyms__is_function(type))
1788 return 0; 1788 return 0;
1789 1789
1790 if (!args->started) { 1790 if (!args->started) {
@@ -1915,7 +1915,7 @@ static void print_duplicate_syms(struct dso *dso, const char *sym_name)
1915 1915
1916 pr_err("Multiple symbols with name '%s'\n", sym_name); 1916 pr_err("Multiple symbols with name '%s'\n", sym_name);
1917 1917
1918 sym = dso__first_symbol(dso, MAP__FUNCTION); 1918 sym = dso__first_symbol(dso);
1919 while (sym) { 1919 while (sym) {
1920 if (dso_sym_match(sym, sym_name, &cnt, -1)) { 1920 if (dso_sym_match(sym, sym_name, &cnt, -1)) {
1921 pr_err("#%d\t0x%"PRIx64"\t%c\t%s\n", 1921 pr_err("#%d\t0x%"PRIx64"\t%c\t%s\n",
@@ -1945,7 +1945,7 @@ static int find_dso_sym(struct dso *dso, const char *sym_name, u64 *start,
1945 *start = 0; 1945 *start = 0;
1946 *size = 0; 1946 *size = 0;
1947 1947
1948 sym = dso__first_symbol(dso, MAP__FUNCTION); 1948 sym = dso__first_symbol(dso);
1949 while (sym) { 1949 while (sym) {
1950 if (*start) { 1950 if (*start) {
1951 if (!*size) 1951 if (!*size)
@@ -1972,8 +1972,8 @@ static int find_dso_sym(struct dso *dso, const char *sym_name, u64 *start,
1972 1972
1973static int addr_filter__entire_dso(struct addr_filter *filt, struct dso *dso) 1973static int addr_filter__entire_dso(struct addr_filter *filt, struct dso *dso)
1974{ 1974{
1975 struct symbol *first_sym = dso__first_symbol(dso, MAP__FUNCTION); 1975 struct symbol *first_sym = dso__first_symbol(dso);
1976 struct symbol *last_sym = dso__last_symbol(dso, MAP__FUNCTION); 1976 struct symbol *last_sym = dso__last_symbol(dso);
1977 1977
1978 if (!first_sym || !last_sym) { 1978 if (!first_sym || !last_sym) {
1979 pr_err("Failed to determine filter for %s\nNo symbols found.\n", 1979 pr_err("Failed to determine filter for %s\nNo symbols found.\n",
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index af7ad814b2c3..cee658733e2c 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -66,7 +66,7 @@ bpf__prepare_load_buffer(void *obj_buf, size_t obj_buf_sz, const char *name)
66 } 66 }
67 67
68 obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, name); 68 obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, name);
69 if (IS_ERR(obj)) { 69 if (IS_ERR_OR_NULL(obj)) {
70 pr_debug("bpf: failed to load buffer\n"); 70 pr_debug("bpf: failed to load buffer\n");
71 return ERR_PTR(-EINVAL); 71 return ERR_PTR(-EINVAL);
72 } 72 }
@@ -102,14 +102,14 @@ struct bpf_object *bpf__prepare_load(const char *filename, bool source)
102 pr_debug("bpf: successfull builtin compilation\n"); 102 pr_debug("bpf: successfull builtin compilation\n");
103 obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, filename); 103 obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, filename);
104 104
105 if (!IS_ERR(obj) && llvm_param.dump_obj) 105 if (!IS_ERR_OR_NULL(obj) && llvm_param.dump_obj)
106 llvm__dump_obj(filename, obj_buf, obj_buf_sz); 106 llvm__dump_obj(filename, obj_buf, obj_buf_sz);
107 107
108 free(obj_buf); 108 free(obj_buf);
109 } else 109 } else
110 obj = bpf_object__open(filename); 110 obj = bpf_object__open(filename);
111 111
112 if (IS_ERR(obj)) { 112 if (IS_ERR_OR_NULL(obj)) {
113 pr_debug("bpf: failed to load %s\n", filename); 113 pr_debug("bpf: failed to load %s\n", filename);
114 return obj; 114 return obj;
115 } 115 }
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 537eadd81914..04b1d53e4bf9 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -47,9 +47,7 @@ int build_id__mark_dso_hit(struct perf_tool *tool __maybe_unused,
47 return -1; 47 return -1;
48 } 48 }
49 49
50 thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, sample->ip, &al); 50 if (thread__find_map(thread, sample->cpumode, sample->ip, &al))
51
52 if (al.map != NULL)
53 al.map->dso->hit = 1; 51 al.map->dso->hit = 1;
54 52
55 thread__put(thread); 53 thread__put(thread);
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
index 84eb9393c7db..5ac157056cdf 100644
--- a/tools/perf/util/config.c
+++ b/tools/perf/util/config.c
@@ -707,6 +707,14 @@ struct perf_config_set *perf_config_set__new(void)
707 return set; 707 return set;
708} 708}
709 709
710static int perf_config__init(void)
711{
712 if (config_set == NULL)
713 config_set = perf_config_set__new();
714
715 return config_set == NULL;
716}
717
710int perf_config(config_fn_t fn, void *data) 718int perf_config(config_fn_t fn, void *data)
711{ 719{
712 int ret = 0; 720 int ret = 0;
@@ -714,7 +722,7 @@ int perf_config(config_fn_t fn, void *data)
714 struct perf_config_section *section; 722 struct perf_config_section *section;
715 struct perf_config_item *item; 723 struct perf_config_item *item;
716 724
717 if (config_set == NULL) 725 if (config_set == NULL && perf_config__init())
718 return -1; 726 return -1;
719 727
720 perf_config_set__for_each_entry(config_set, section, item) { 728 perf_config_set__for_each_entry(config_set, section, item) {
@@ -735,12 +743,6 @@ int perf_config(config_fn_t fn, void *data)
735 return ret; 743 return ret;
736} 744}
737 745
738void perf_config__init(void)
739{
740 if (config_set == NULL)
741 config_set = perf_config_set__new();
742}
743
744void perf_config__exit(void) 746void perf_config__exit(void)
745{ 747{
746 perf_config_set__delete(config_set); 748 perf_config_set__delete(config_set);
diff --git a/tools/perf/util/config.h b/tools/perf/util/config.h
index baf82bf227ac..bd0a5897c76a 100644
--- a/tools/perf/util/config.h
+++ b/tools/perf/util/config.h
@@ -38,7 +38,6 @@ struct perf_config_set *perf_config_set__new(void);
38void perf_config_set__delete(struct perf_config_set *set); 38void perf_config_set__delete(struct perf_config_set *set);
39int perf_config_set__collect(struct perf_config_set *set, const char *file_name, 39int perf_config_set__collect(struct perf_config_set *set, const char *file_name,
40 const char *var, const char *value); 40 const char *var, const char *value);
41void perf_config__init(void);
42void perf_config__exit(void); 41void perf_config__exit(void);
43void perf_config__refresh(void); 42void perf_config__refresh(void);
44 43
diff --git a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c
index c8b98fa22997..4d5fc374e730 100644
--- a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c
+++ b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c
@@ -96,11 +96,19 @@ int cs_etm_decoder__get_packet(struct cs_etm_decoder *decoder,
96 /* Nothing to do, might as well just return */ 96 /* Nothing to do, might as well just return */
97 if (decoder->packet_count == 0) 97 if (decoder->packet_count == 0)
98 return 0; 98 return 0;
99 /*
100 * The queueing process in function cs_etm_decoder__buffer_packet()
101 * increments the tail *before* using it. This is somewhat counter
102 * intuitive but it has the advantage of centralizing tail management
103 * at a single location. Because of that we need to follow the same
104 * heuristic with the head, i.e we increment it before using its
105 * value. Otherwise the first element of the packet queue is not
106 * used.
107 */
108 decoder->head = (decoder->head + 1) & (MAX_BUFFER - 1);
99 109
100 *packet = decoder->packet_buffer[decoder->head]; 110 *packet = decoder->packet_buffer[decoder->head];
101 111
102 decoder->head = (decoder->head + 1) & (MAX_BUFFER - 1);
103
104 decoder->packet_count--; 112 decoder->packet_count--;
105 113
106 return 1; 114 return 1;
diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c
index 40020b1ca54f..822ba915d144 100644
--- a/tools/perf/util/cs-etm.c
+++ b/tools/perf/util/cs-etm.c
@@ -239,6 +239,7 @@ static void cs_etm__free(struct perf_session *session)
239 for (i = 0; i < aux->num_cpu; i++) 239 for (i = 0; i < aux->num_cpu; i++)
240 zfree(&aux->metadata[i]); 240 zfree(&aux->metadata[i]);
241 241
242 thread__zput(aux->unknown_thread);
242 zfree(&aux->metadata); 243 zfree(&aux->metadata);
243 zfree(&aux); 244 zfree(&aux);
244} 245}
@@ -269,9 +270,7 @@ static u32 cs_etm__mem_access(struct cs_etm_queue *etmq, u64 address,
269 thread = etmq->etm->unknown_thread; 270 thread = etmq->etm->unknown_thread;
270 } 271 }
271 272
272 thread__find_addr_map(thread, cpumode, MAP__FUNCTION, address, &al); 273 if (!thread__find_map(thread, cpumode, address, &al) || !al.map->dso)
273
274 if (!al.map || !al.map->dso)
275 return 0; 274 return 0;
276 275
277 if (al.map->dso->data.status == DSO_DATA_STATUS_ERROR && 276 if (al.map->dso->data.status == DSO_DATA_STATUS_ERROR &&
@@ -612,8 +611,8 @@ cs_etm__get_trace(struct cs_etm_buffer *buff, struct cs_etm_queue *etmq)
612 return buff->len; 611 return buff->len;
613} 612}
614 613
615static void cs_etm__set_pid_tid_cpu(struct cs_etm_auxtrace *etm, 614static void cs_etm__set_pid_tid_cpu(struct cs_etm_auxtrace *etm,
616 struct auxtrace_queue *queue) 615 struct auxtrace_queue *queue)
617{ 616{
618 struct cs_etm_queue *etmq = queue->priv; 617 struct cs_etm_queue *etmq = queue->priv;
619 618
@@ -1357,6 +1356,23 @@ int cs_etm__process_auxtrace_info(union perf_event *event,
1357 etm->auxtrace.free = cs_etm__free; 1356 etm->auxtrace.free = cs_etm__free;
1358 session->auxtrace = &etm->auxtrace; 1357 session->auxtrace = &etm->auxtrace;
1359 1358
1359 etm->unknown_thread = thread__new(999999999, 999999999);
1360 if (!etm->unknown_thread)
1361 goto err_free_queues;
1362
1363 /*
1364 * Initialize list node so that at thread__zput() we can avoid
1365 * segmentation fault at list_del_init().
1366 */
1367 INIT_LIST_HEAD(&etm->unknown_thread->node);
1368
1369 err = thread__set_comm(etm->unknown_thread, "unknown", 0);
1370 if (err)
1371 goto err_delete_thread;
1372
1373 if (thread__init_map_groups(etm->unknown_thread, etm->machine))
1374 goto err_delete_thread;
1375
1360 if (dump_trace) { 1376 if (dump_trace) {
1361 cs_etm__print_auxtrace_info(auxtrace_info->priv, num_cpu); 1377 cs_etm__print_auxtrace_info(auxtrace_info->priv, num_cpu);
1362 return 0; 1378 return 0;
@@ -1371,16 +1387,18 @@ int cs_etm__process_auxtrace_info(union perf_event *event,
1371 1387
1372 err = cs_etm__synth_events(etm, session); 1388 err = cs_etm__synth_events(etm, session);
1373 if (err) 1389 if (err)
1374 goto err_free_queues; 1390 goto err_delete_thread;
1375 1391
1376 err = auxtrace_queues__process_index(&etm->queues, session); 1392 err = auxtrace_queues__process_index(&etm->queues, session);
1377 if (err) 1393 if (err)
1378 goto err_free_queues; 1394 goto err_delete_thread;
1379 1395
1380 etm->data_queued = etm->queues.populated; 1396 etm->data_queued = etm->queues.populated;
1381 1397
1382 return 0; 1398 return 0;
1383 1399
1400err_delete_thread:
1401 thread__zput(etm->unknown_thread);
1384err_free_queues: 1402err_free_queues:
1385 auxtrace_queues__free(&etm->queues); 1403 auxtrace_queues__free(&etm->queues);
1386 session->auxtrace = NULL; 1404 session->auxtrace = NULL;
diff --git a/tools/perf/util/db-export.c b/tools/perf/util/db-export.c
index b0c2b5c5d337..7123746edcf4 100644
--- a/tools/perf/util/db-export.c
+++ b/tools/perf/util/db-export.c
@@ -247,9 +247,9 @@ static int db_ids_from_al(struct db_export *dbe, struct addr_location *al,
247 *dso_db_id = dso->db_id; 247 *dso_db_id = dso->db_id;
248 248
249 if (!al->sym) { 249 if (!al->sym) {
250 al->sym = symbol__new(al->addr, 0, 0, "unknown"); 250 al->sym = symbol__new(al->addr, 0, 0, 0, "unknown");
251 if (al->sym) 251 if (al->sym)
252 dso__insert_symbol(dso, al->map->type, al->sym); 252 dso__insert_symbol(dso, al->sym);
253 } 253 }
254 254
255 if (al->sym) { 255 if (al->sym) {
@@ -315,8 +315,7 @@ static struct call_path *call_path_from_sample(struct db_export *dbe,
315 al.addr = node->ip; 315 al.addr = node->ip;
316 316
317 if (al.map && !al.sym) 317 if (al.map && !al.sym)
318 al.sym = dso__find_symbol(al.map->dso, MAP__FUNCTION, 318 al.sym = dso__find_symbol(al.map->dso, al.addr);
319 al.addr);
320 319
321 db_ids_from_al(dbe, &al, &dso_db_id, &sym_db_id, &offset); 320 db_ids_from_al(dbe, &al, &dso_db_id, &sym_db_id, &offset);
322 321
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 36ef45b2e89d..cdfc2e5f55f5 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -1014,7 +1014,7 @@ struct map *dso__new_map(const char *name)
1014 struct dso *dso = dso__new(name); 1014 struct dso *dso = dso__new(name);
1015 1015
1016 if (dso) 1016 if (dso)
1017 map = map__new2(0, dso, MAP__FUNCTION); 1017 map = map__new2(0, dso);
1018 1018
1019 return map; 1019 return map;
1020} 1020}
@@ -1176,19 +1176,19 @@ int dso__name_len(const struct dso *dso)
1176 return dso->short_name_len; 1176 return dso->short_name_len;
1177} 1177}
1178 1178
1179bool dso__loaded(const struct dso *dso, enum map_type type) 1179bool dso__loaded(const struct dso *dso)
1180{ 1180{
1181 return dso->loaded & (1 << type); 1181 return dso->loaded;
1182} 1182}
1183 1183
1184bool dso__sorted_by_name(const struct dso *dso, enum map_type type) 1184bool dso__sorted_by_name(const struct dso *dso)
1185{ 1185{
1186 return dso->sorted_by_name & (1 << type); 1186 return dso->sorted_by_name;
1187} 1187}
1188 1188
1189void dso__set_sorted_by_name(struct dso *dso, enum map_type type) 1189void dso__set_sorted_by_name(struct dso *dso)
1190{ 1190{
1191 dso->sorted_by_name |= (1 << type); 1191 dso->sorted_by_name = true;
1192} 1192}
1193 1193
1194struct dso *dso__new(const char *name) 1194struct dso *dso__new(const char *name)
@@ -1196,12 +1196,10 @@ struct dso *dso__new(const char *name)
1196 struct dso *dso = calloc(1, sizeof(*dso) + strlen(name) + 1); 1196 struct dso *dso = calloc(1, sizeof(*dso) + strlen(name) + 1);
1197 1197
1198 if (dso != NULL) { 1198 if (dso != NULL) {
1199 int i;
1200 strcpy(dso->name, name); 1199 strcpy(dso->name, name);
1201 dso__set_long_name(dso, dso->name, false); 1200 dso__set_long_name(dso, dso->name, false);
1202 dso__set_short_name(dso, dso->name, false); 1201 dso__set_short_name(dso, dso->name, false);
1203 for (i = 0; i < MAP__NR_TYPES; ++i) 1202 dso->symbols = dso->symbol_names = RB_ROOT;
1204 dso->symbols[i] = dso->symbol_names[i] = RB_ROOT;
1205 dso->data.cache = RB_ROOT; 1203 dso->data.cache = RB_ROOT;
1206 dso->inlined_nodes = RB_ROOT; 1204 dso->inlined_nodes = RB_ROOT;
1207 dso->srclines = RB_ROOT; 1205 dso->srclines = RB_ROOT;
@@ -1231,8 +1229,6 @@ struct dso *dso__new(const char *name)
1231 1229
1232void dso__delete(struct dso *dso) 1230void dso__delete(struct dso *dso)
1233{ 1231{
1234 int i;
1235
1236 if (!RB_EMPTY_NODE(&dso->rb_node)) 1232 if (!RB_EMPTY_NODE(&dso->rb_node))
1237 pr_err("DSO %s is still in rbtree when being deleted!\n", 1233 pr_err("DSO %s is still in rbtree when being deleted!\n",
1238 dso->long_name); 1234 dso->long_name);
@@ -1240,8 +1236,7 @@ void dso__delete(struct dso *dso)
1240 /* free inlines first, as they reference symbols */ 1236 /* free inlines first, as they reference symbols */
1241 inlines__tree_delete(&dso->inlined_nodes); 1237 inlines__tree_delete(&dso->inlined_nodes);
1242 srcline__tree_delete(&dso->srclines); 1238 srcline__tree_delete(&dso->srclines);
1243 for (i = 0; i < MAP__NR_TYPES; ++i) 1239 symbols__delete(&dso->symbols);
1244 symbols__delete(&dso->symbols[i]);
1245 1240
1246 if (dso->short_name_allocated) { 1241 if (dso->short_name_allocated) {
1247 zfree((char **)&dso->short_name); 1242 zfree((char **)&dso->short_name);
@@ -1451,9 +1446,7 @@ size_t __dsos__fprintf(struct list_head *head, FILE *fp)
1451 size_t ret = 0; 1446 size_t ret = 0;
1452 1447
1453 list_for_each_entry(pos, head, node) { 1448 list_for_each_entry(pos, head, node) {
1454 int i; 1449 ret += dso__fprintf(pos, fp);
1455 for (i = 0; i < MAP__NR_TYPES; ++i)
1456 ret += dso__fprintf(pos, i, fp);
1457 } 1450 }
1458 1451
1459 return ret; 1452 return ret;
@@ -1467,18 +1460,17 @@ size_t dso__fprintf_buildid(struct dso *dso, FILE *fp)
1467 return fprintf(fp, "%s", sbuild_id); 1460 return fprintf(fp, "%s", sbuild_id);
1468} 1461}
1469 1462
1470size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp) 1463size_t dso__fprintf(struct dso *dso, FILE *fp)
1471{ 1464{
1472 struct rb_node *nd; 1465 struct rb_node *nd;
1473 size_t ret = fprintf(fp, "dso: %s (", dso->short_name); 1466 size_t ret = fprintf(fp, "dso: %s (", dso->short_name);
1474 1467
1475 if (dso->short_name != dso->long_name) 1468 if (dso->short_name != dso->long_name)
1476 ret += fprintf(fp, "%s, ", dso->long_name); 1469 ret += fprintf(fp, "%s, ", dso->long_name);
1477 ret += fprintf(fp, "%s, %sloaded, ", map_type__name[type], 1470 ret += fprintf(fp, "%sloaded, ", dso__loaded(dso) ? "" : "NOT ");
1478 dso__loaded(dso, type) ? "" : "NOT ");
1479 ret += dso__fprintf_buildid(dso, fp); 1471 ret += dso__fprintf_buildid(dso, fp);
1480 ret += fprintf(fp, ")\n"); 1472 ret += fprintf(fp, ")\n");
1481 for (nd = rb_first(&dso->symbols[type]); nd; nd = rb_next(nd)) { 1473 for (nd = rb_first(&dso->symbols); nd; nd = rb_next(nd)) {
1482 struct symbol *pos = rb_entry(nd, struct symbol, rb_node); 1474 struct symbol *pos = rb_entry(nd, struct symbol, rb_node);
1483 ret += symbol__fprintf(pos, fp); 1475 ret += symbol__fprintf(pos, fp);
1484 } 1476 }
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index c229dbe0277a..ef69de2e69ea 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -140,14 +140,14 @@ struct dso {
140 struct list_head node; 140 struct list_head node;
141 struct rb_node rb_node; /* rbtree node sorted by long name */ 141 struct rb_node rb_node; /* rbtree node sorted by long name */
142 struct rb_root *root; /* root of rbtree that rb_node is in */ 142 struct rb_root *root; /* root of rbtree that rb_node is in */
143 struct rb_root symbols[MAP__NR_TYPES]; 143 struct rb_root symbols;
144 struct rb_root symbol_names[MAP__NR_TYPES]; 144 struct rb_root symbol_names;
145 struct rb_root inlined_nodes; 145 struct rb_root inlined_nodes;
146 struct rb_root srclines; 146 struct rb_root srclines;
147 struct { 147 struct {
148 u64 addr; 148 u64 addr;
149 struct symbol *symbol; 149 struct symbol *symbol;
150 } last_find_result[MAP__NR_TYPES]; 150 } last_find_result;
151 void *a2l; 151 void *a2l;
152 char *symsrc_filename; 152 char *symsrc_filename;
153 unsigned int a2l_fails; 153 unsigned int a2l_fails;
@@ -164,8 +164,8 @@ struct dso {
164 u8 short_name_allocated:1; 164 u8 short_name_allocated:1;
165 u8 long_name_allocated:1; 165 u8 long_name_allocated:1;
166 u8 is_64_bit:1; 166 u8 is_64_bit:1;
167 u8 sorted_by_name; 167 bool sorted_by_name;
168 u8 loaded; 168 bool loaded;
169 u8 rel; 169 u8 rel;
170 u8 build_id[BUILD_ID_SIZE]; 170 u8 build_id[BUILD_ID_SIZE];
171 u64 text_offset; 171 u64 text_offset;
@@ -202,14 +202,13 @@ struct dso {
202 * @dso: the 'struct dso *' in which symbols itereated 202 * @dso: the 'struct dso *' in which symbols itereated
203 * @pos: the 'struct symbol *' to use as a loop cursor 203 * @pos: the 'struct symbol *' to use as a loop cursor
204 * @n: the 'struct rb_node *' to use as a temporary storage 204 * @n: the 'struct rb_node *' to use as a temporary storage
205 * @type: the 'enum map_type' type of symbols
206 */ 205 */
207#define dso__for_each_symbol(dso, pos, n, type) \ 206#define dso__for_each_symbol(dso, pos, n) \
208 symbols__for_each_entry(&(dso)->symbols[(type)], pos, n) 207 symbols__for_each_entry(&(dso)->symbols, pos, n)
209 208
210static inline void dso__set_loaded(struct dso *dso, enum map_type type) 209static inline void dso__set_loaded(struct dso *dso)
211{ 210{
212 dso->loaded |= (1 << type); 211 dso->loaded = true;
213} 212}
214 213
215struct dso *dso__new(const char *name); 214struct dso *dso__new(const char *name);
@@ -231,11 +230,16 @@ static inline void __dso__zput(struct dso **dso)
231 230
232#define dso__zput(dso) __dso__zput(&dso) 231#define dso__zput(dso) __dso__zput(&dso)
233 232
234bool dso__loaded(const struct dso *dso, enum map_type type); 233bool dso__loaded(const struct dso *dso);
235 234
236bool dso__sorted_by_name(const struct dso *dso, enum map_type type); 235static inline bool dso__has_symbols(const struct dso *dso)
237void dso__set_sorted_by_name(struct dso *dso, enum map_type type); 236{
238void dso__sort_by_name(struct dso *dso, enum map_type type); 237 return !RB_EMPTY_ROOT(&dso->symbols);
238}
239
240bool dso__sorted_by_name(const struct dso *dso);
241void dso__set_sorted_by_name(struct dso *dso);
242void dso__sort_by_name(struct dso *dso);
239 243
240void dso__set_build_id(struct dso *dso, void *build_id); 244void dso__set_build_id(struct dso *dso, void *build_id);
241bool dso__build_id_equal(const struct dso *dso, u8 *build_id); 245bool dso__build_id_equal(const struct dso *dso, u8 *build_id);
@@ -349,9 +353,8 @@ size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp,
349size_t __dsos__fprintf(struct list_head *head, FILE *fp); 353size_t __dsos__fprintf(struct list_head *head, FILE *fp);
350 354
351size_t dso__fprintf_buildid(struct dso *dso, FILE *fp); 355size_t dso__fprintf_buildid(struct dso *dso, FILE *fp);
352size_t dso__fprintf_symbols_by_name(struct dso *dso, 356size_t dso__fprintf_symbols_by_name(struct dso *dso, FILE *fp);
353 enum map_type type, FILE *fp); 357size_t dso__fprintf(struct dso *dso, FILE *fp);
354size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp);
355 358
356static inline bool dso__is_vmlinux(struct dso *dso) 359static inline bool dso__is_vmlinux(struct dso *dso)
357{ 360{
diff --git a/tools/perf/util/env.c b/tools/perf/util/env.c
index 4c842762e3f2..59f38c7693f8 100644
--- a/tools/perf/util/env.c
+++ b/tools/perf/util/env.c
@@ -93,6 +93,37 @@ int perf_env__read_cpu_topology_map(struct perf_env *env)
93 return 0; 93 return 0;
94} 94}
95 95
96static int perf_env__read_arch(struct perf_env *env)
97{
98 struct utsname uts;
99
100 if (env->arch)
101 return 0;
102
103 if (!uname(&uts))
104 env->arch = strdup(uts.machine);
105
106 return env->arch ? 0 : -ENOMEM;
107}
108
109static int perf_env__read_nr_cpus_avail(struct perf_env *env)
110{
111 if (env->nr_cpus_avail == 0)
112 env->nr_cpus_avail = cpu__max_present_cpu();
113
114 return env->nr_cpus_avail ? 0 : -ENOENT;
115}
116
117const char *perf_env__raw_arch(struct perf_env *env)
118{
119 return env && !perf_env__read_arch(env) ? env->arch : "unknown";
120}
121
122int perf_env__nr_cpus_avail(struct perf_env *env)
123{
124 return env && !perf_env__read_nr_cpus_avail(env) ? env->nr_cpus_avail : 0;
125}
126
96void cpu_cache_level__free(struct cpu_cache_level *cache) 127void cpu_cache_level__free(struct cpu_cache_level *cache)
97{ 128{
98 free(cache->type); 129 free(cache->type);
diff --git a/tools/perf/util/env.h b/tools/perf/util/env.h
index c4ef2e523367..1f3ccc368530 100644
--- a/tools/perf/util/env.h
+++ b/tools/perf/util/env.h
@@ -76,4 +76,7 @@ int perf_env__read_cpu_topology_map(struct perf_env *env);
76void cpu_cache_level__free(struct cpu_cache_level *cache); 76void cpu_cache_level__free(struct cpu_cache_level *cache);
77 77
78const char *perf_env__arch(struct perf_env *env); 78const char *perf_env__arch(struct perf_env *env);
79const char *perf_env__raw_arch(struct perf_env *env);
80int perf_env__nr_cpus_avail(struct perf_env *env);
81
79#endif /* __PERF_ENV_H */ 82#endif /* __PERF_ENV_H */
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 98ff3a6a3d50..0c8ecf0c78a4 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -88,10 +88,10 @@ static const char *perf_ns__name(unsigned int id)
88 return perf_ns__names[id]; 88 return perf_ns__names[id];
89} 89}
90 90
91static int perf_tool__process_synth_event(struct perf_tool *tool, 91int perf_tool__process_synth_event(struct perf_tool *tool,
92 union perf_event *event, 92 union perf_event *event,
93 struct machine *machine, 93 struct machine *machine,
94 perf_event__handler_t process) 94 perf_event__handler_t process)
95{ 95{
96 struct perf_sample synth_sample = { 96 struct perf_sample synth_sample = {
97 .pid = -1, 97 .pid = -1,
@@ -464,8 +464,7 @@ int perf_event__synthesize_modules(struct perf_tool *tool,
464{ 464{
465 int rc = 0; 465 int rc = 0;
466 struct map *pos; 466 struct map *pos;
467 struct map_groups *kmaps = &machine->kmaps; 467 struct maps *maps = machine__kernel_maps(machine);
468 struct maps *maps = &kmaps->maps[MAP__FUNCTION];
469 union perf_event *event = zalloc((sizeof(event->mmap) + 468 union perf_event *event = zalloc((sizeof(event->mmap) +
470 machine->id_hdr_size)); 469 machine->id_hdr_size));
471 if (event == NULL) { 470 if (event == NULL) {
@@ -488,7 +487,7 @@ int perf_event__synthesize_modules(struct perf_tool *tool,
488 for (pos = maps__first(maps); pos; pos = map__next(pos)) { 487 for (pos = maps__first(maps); pos; pos = map__next(pos)) {
489 size_t size; 488 size_t size;
490 489
491 if (__map__is_kernel(pos)) 490 if (!__map__is_kmodule(pos))
492 continue; 491 continue;
493 492
494 size = PERF_ALIGN(pos->dso->long_name_len + 1, sizeof(u64)); 493 size = PERF_ALIGN(pos->dso->long_name_len + 1, sizeof(u64));
@@ -869,7 +868,7 @@ static int find_symbol_cb(void *arg, const char *name, char type,
869 * Must be a function or at least an alias, as in PARISC64, where "_text" is 868 * Must be a function or at least an alias, as in PARISC64, where "_text" is
870 * an 'A' to the same address as "_stext". 869 * an 'A' to the same address as "_stext".
871 */ 870 */
872 if (!(symbol_type__is_a(type, MAP__FUNCTION) || 871 if (!(kallsyms__is_function(type) ||
873 type == 'A') || strcmp(name, args->name)) 872 type == 'A') || strcmp(name, args->name))
874 return 0; 873 return 0;
875 874
@@ -889,9 +888,16 @@ int kallsyms__get_function_start(const char *kallsyms_filename,
889 return 0; 888 return 0;
890} 889}
891 890
892int perf_event__synthesize_kernel_mmap(struct perf_tool *tool, 891int __weak perf_event__synthesize_extra_kmaps(struct perf_tool *tool __maybe_unused,
893 perf_event__handler_t process, 892 perf_event__handler_t process __maybe_unused,
894 struct machine *machine) 893 struct machine *machine __maybe_unused)
894{
895 return 0;
896}
897
898static int __perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
899 perf_event__handler_t process,
900 struct machine *machine)
895{ 901{
896 size_t size; 902 size_t size;
897 struct map *map = machine__kernel_map(machine); 903 struct map *map = machine__kernel_map(machine);
@@ -944,6 +950,19 @@ int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
944 return err; 950 return err;
945} 951}
946 952
953int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
954 perf_event__handler_t process,
955 struct machine *machine)
956{
957 int err;
958
959 err = __perf_event__synthesize_kernel_mmap(tool, process, machine);
960 if (err < 0)
961 return err;
962
963 return perf_event__synthesize_extra_kmaps(tool, process, machine);
964}
965
947int perf_event__synthesize_thread_map2(struct perf_tool *tool, 966int perf_event__synthesize_thread_map2(struct perf_tool *tool,
948 struct thread_map *threads, 967 struct thread_map *threads,
949 perf_event__handler_t process, 968 perf_event__handler_t process,
@@ -1489,9 +1508,8 @@ int perf_event__process(struct perf_tool *tool __maybe_unused,
1489 return machine__process_event(machine, event, sample); 1508 return machine__process_event(machine, event, sample);
1490} 1509}
1491 1510
1492void thread__find_addr_map(struct thread *thread, u8 cpumode, 1511struct map *thread__find_map(struct thread *thread, u8 cpumode, u64 addr,
1493 enum map_type type, u64 addr, 1512 struct addr_location *al)
1494 struct addr_location *al)
1495{ 1513{
1496 struct map_groups *mg = thread->mg; 1514 struct map_groups *mg = thread->mg;
1497 struct machine *machine = mg->machine; 1515 struct machine *machine = mg->machine;
@@ -1505,7 +1523,7 @@ void thread__find_addr_map(struct thread *thread, u8 cpumode,
1505 1523
1506 if (machine == NULL) { 1524 if (machine == NULL) {
1507 al->map = NULL; 1525 al->map = NULL;
1508 return; 1526 return NULL;
1509 } 1527 }
1510 1528
1511 if (cpumode == PERF_RECORD_MISC_KERNEL && perf_host) { 1529 if (cpumode == PERF_RECORD_MISC_KERNEL && perf_host) {
@@ -1533,10 +1551,10 @@ void thread__find_addr_map(struct thread *thread, u8 cpumode,
1533 !perf_host) 1551 !perf_host)
1534 al->filtered |= (1 << HIST_FILTER__HOST); 1552 al->filtered |= (1 << HIST_FILTER__HOST);
1535 1553
1536 return; 1554 return NULL;
1537 } 1555 }
1538try_again: 1556try_again:
1539 al->map = map_groups__find(mg, type, al->addr); 1557 al->map = map_groups__find(mg, al->addr);
1540 if (al->map == NULL) { 1558 if (al->map == NULL) {
1541 /* 1559 /*
1542 * If this is outside of all known maps, and is a negative 1560 * If this is outside of all known maps, and is a negative
@@ -1563,17 +1581,17 @@ try_again:
1563 map__load(al->map); 1581 map__load(al->map);
1564 al->addr = al->map->map_ip(al->map, al->addr); 1582 al->addr = al->map->map_ip(al->map, al->addr);
1565 } 1583 }
1584
1585 return al->map;
1566} 1586}
1567 1587
1568void thread__find_addr_location(struct thread *thread, 1588struct symbol *thread__find_symbol(struct thread *thread, u8 cpumode,
1569 u8 cpumode, enum map_type type, u64 addr, 1589 u64 addr, struct addr_location *al)
1570 struct addr_location *al)
1571{ 1590{
1572 thread__find_addr_map(thread, cpumode, type, addr, al); 1591 al->sym = NULL;
1573 if (al->map != NULL) 1592 if (thread__find_map(thread, cpumode, addr, al))
1574 al->sym = map__find_symbol(al->map, al->addr); 1593 al->sym = map__find_symbol(al->map, al->addr);
1575 else 1594 return al->sym;
1576 al->sym = NULL;
1577} 1595}
1578 1596
1579/* 1597/*
@@ -1590,7 +1608,7 @@ int machine__resolve(struct machine *machine, struct addr_location *al,
1590 return -1; 1608 return -1;
1591 1609
1592 dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread), thread->tid); 1610 dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread), thread->tid);
1593 thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, sample->ip, al); 1611 thread__find_map(thread, sample->cpumode, sample->ip, al);
1594 dump_printf(" ...... dso: %s\n", 1612 dump_printf(" ...... dso: %s\n",
1595 al->map ? al->map->dso->long_name : 1613 al->map ? al->map->dso->long_name :
1596 al->level == 'H' ? "[hypervisor]" : "<not found>"); 1614 al->level == 'H' ? "[hypervisor]" : "<not found>");
@@ -1669,10 +1687,7 @@ bool sample_addr_correlates_sym(struct perf_event_attr *attr)
1669void thread__resolve(struct thread *thread, struct addr_location *al, 1687void thread__resolve(struct thread *thread, struct addr_location *al,
1670 struct perf_sample *sample) 1688 struct perf_sample *sample)
1671{ 1689{
1672 thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, sample->addr, al); 1690 thread__find_map(thread, sample->cpumode, sample->addr, al);
1673 if (!al->map)
1674 thread__find_addr_map(thread, sample->cpumode, MAP__VARIABLE,
1675 sample->addr, al);
1676 1691
1677 al->cpu = sample->cpu; 1692 al->cpu = sample->cpu;
1678 al->sym = NULL; 1693 al->sym = NULL;
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 0f794744919c..bfa60bcafbde 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -750,6 +750,10 @@ int perf_event__process_exit(struct perf_tool *tool,
750 union perf_event *event, 750 union perf_event *event,
751 struct perf_sample *sample, 751 struct perf_sample *sample,
752 struct machine *machine); 752 struct machine *machine);
753int perf_tool__process_synth_event(struct perf_tool *tool,
754 union perf_event *event,
755 struct machine *machine,
756 perf_event__handler_t process);
753int perf_event__process(struct perf_tool *tool, 757int perf_event__process(struct perf_tool *tool,
754 union perf_event *event, 758 union perf_event *event,
755 struct perf_sample *sample, 759 struct perf_sample *sample,
@@ -796,6 +800,10 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool,
796 bool mmap_data, 800 bool mmap_data,
797 unsigned int proc_map_timeout); 801 unsigned int proc_map_timeout);
798 802
803int perf_event__synthesize_extra_kmaps(struct perf_tool *tool,
804 perf_event__handler_t process,
805 struct machine *machine);
806
799size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp); 807size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp);
800size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp); 808size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp);
801size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp); 809size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp);
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index a59281d64368..e7a4b31a84fb 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -1795,3 +1795,18 @@ bool perf_evlist__exclude_kernel(struct perf_evlist *evlist)
1795 1795
1796 return true; 1796 return true;
1797} 1797}
1798
1799/*
1800 * Events in data file are not collect in groups, but we still want
1801 * the group display. Set the artificial group and set the leader's
1802 * forced_leader flag to notify the display code.
1803 */
1804void perf_evlist__force_leader(struct perf_evlist *evlist)
1805{
1806 if (!evlist->nr_groups) {
1807 struct perf_evsel *leader = perf_evlist__first(evlist);
1808
1809 perf_evlist__set_leader(evlist);
1810 leader->forced_leader = true;
1811 }
1812}
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 6c41b2f78713..dc66436add98 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -309,4 +309,7 @@ struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist,
309 union perf_event *event); 309 union perf_event *event);
310 310
311bool perf_evlist__exclude_kernel(struct perf_evlist *evlist); 311bool perf_evlist__exclude_kernel(struct perf_evlist *evlist);
312
313void perf_evlist__force_leader(struct perf_evlist *evlist);
314
312#endif /* __PERF_EVLIST_H */ 315#endif /* __PERF_EVLIST_H */
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 3e87486c28fe..150db5ed7400 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -930,8 +930,11 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts,
930 * than leader in case leader 'leads' the sampling. 930 * than leader in case leader 'leads' the sampling.
931 */ 931 */
932 if ((leader != evsel) && leader->sample_read) { 932 if ((leader != evsel) && leader->sample_read) {
933 attr->sample_freq = 0; 933 attr->freq = 0;
934 attr->sample_period = 0; 934 attr->sample_freq = 0;
935 attr->sample_period = 0;
936 attr->write_backward = 0;
937 attr->sample_id_all = 0;
935 } 938 }
936 939
937 if (opts->no_samples) 940 if (opts->no_samples)
@@ -1922,7 +1925,8 @@ try_fallback:
1922 goto fallback_missing_features; 1925 goto fallback_missing_features;
1923 } else if (!perf_missing_features.group_read && 1926 } else if (!perf_missing_features.group_read &&
1924 evsel->attr.inherit && 1927 evsel->attr.inherit &&
1925 (evsel->attr.read_format & PERF_FORMAT_GROUP)) { 1928 (evsel->attr.read_format & PERF_FORMAT_GROUP) &&
1929 perf_evsel__is_group_leader(evsel)) {
1926 perf_missing_features.group_read = true; 1930 perf_missing_features.group_read = true;
1927 pr_debug2("switching off group read\n"); 1931 pr_debug2("switching off group read\n");
1928 goto fallback_missing_features; 1932 goto fallback_missing_features;
@@ -2754,8 +2758,14 @@ bool perf_evsel__fallback(struct perf_evsel *evsel, int err,
2754 (paranoid = perf_event_paranoid()) > 1) { 2758 (paranoid = perf_event_paranoid()) > 1) {
2755 const char *name = perf_evsel__name(evsel); 2759 const char *name = perf_evsel__name(evsel);
2756 char *new_name; 2760 char *new_name;
2761 const char *sep = ":";
2757 2762
2758 if (asprintf(&new_name, "%s%su", name, strchr(name, ':') ? "" : ":") < 0) 2763 /* Is there already the separator in the name. */
2764 if (strchr(name, '/') ||
2765 strchr(name, ':'))
2766 sep = "";
2767
2768 if (asprintf(&new_name, "%s%su", name, sep) < 0)
2759 return false; 2769 return false;
2760 2770
2761 if (evsel->name) 2771 if (evsel->name)
@@ -2852,7 +2862,7 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
2852 return scnprintf(msg, size, 2862 return scnprintf(msg, size,
2853 "Not enough memory to setup event with callchain.\n" 2863 "Not enough memory to setup event with callchain.\n"
2854 "Hint: Try tweaking /proc/sys/kernel/perf_event_max_stack\n" 2864 "Hint: Try tweaking /proc/sys/kernel/perf_event_max_stack\n"
2855 "Hint: Current value: %d", sysctl_perf_event_max_stack); 2865 "Hint: Current value: %d", sysctl__max_stack());
2856 break; 2866 break;
2857 case ENODEV: 2867 case ENODEV:
2858 if (target->cpu_list) 2868 if (target->cpu_list)
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index d3ee3af618ef..b13f5f234c8f 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -115,6 +115,7 @@ struct perf_evsel {
115 unsigned int sample_size; 115 unsigned int sample_size;
116 int id_pos; 116 int id_pos;
117 int is_pos; 117 int is_pos;
118 bool uniquified_name;
118 bool snapshot; 119 bool snapshot;
119 bool supported; 120 bool supported;
120 bool needs_swap; 121 bool needs_swap;
@@ -126,6 +127,7 @@ struct perf_evsel {
126 bool precise_max; 127 bool precise_max;
127 bool ignore_missing_thread; 128 bool ignore_missing_thread;
128 bool forced_leader; 129 bool forced_leader;
130 bool use_uncore_alias;
129 /* parse modifier helper */ 131 /* parse modifier helper */
130 int exclude_GH; 132 int exclude_GH;
131 int nr_members; 133 int nr_members;
diff --git a/tools/perf/util/genelf.c b/tools/perf/util/genelf.c
index c540d47583e7..aafbe54fd3fa 100644
--- a/tools/perf/util/genelf.c
+++ b/tools/perf/util/genelf.c
@@ -114,7 +114,7 @@ gen_build_id(struct buildid_note *note,
114 114
115 fd = open("/dev/urandom", O_RDONLY); 115 fd = open("/dev/urandom", O_RDONLY);
116 if (fd == -1) 116 if (fd == -1)
117 err(1, "cannot access /dev/urandom for builid"); 117 err(1, "cannot access /dev/urandom for buildid");
118 118
119 sret = read(fd, note->build_id, sz); 119 sret = read(fd, note->build_id, sz);
120 120
diff --git a/tools/perf/util/intel-bts.c b/tools/perf/util/intel-bts.c
index 72db2744876d..7f0c83b6332b 100644
--- a/tools/perf/util/intel-bts.c
+++ b/tools/perf/util/intel-bts.c
@@ -335,8 +335,7 @@ static int intel_bts_get_next_insn(struct intel_bts_queue *btsq, u64 ip)
335 if (!thread) 335 if (!thread)
336 return -1; 336 return -1;
337 337
338 thread__find_addr_map(thread, cpumode, MAP__FUNCTION, ip, &al); 338 if (!thread__find_map(thread, cpumode, ip, &al) || !al.map->dso)
339 if (!al.map || !al.map->dso)
340 goto out_put; 339 goto out_put;
341 340
342 len = dso__data_read_addr(al.map->dso, al.map, machine, ip, buf, 341 len = dso__data_read_addr(al.map->dso, al.map, machine, ip, buf,
diff --git a/tools/perf/util/intel-pt-decoder/insn.h b/tools/perf/util/intel-pt-decoder/insn.h
index e23578c7b1be..2669c9f748e4 100644
--- a/tools/perf/util/intel-pt-decoder/insn.h
+++ b/tools/perf/util/intel-pt-decoder/insn.h
@@ -208,4 +208,22 @@ static inline int insn_offset_immediate(struct insn *insn)
208 return insn_offset_displacement(insn) + insn->displacement.nbytes; 208 return insn_offset_displacement(insn) + insn->displacement.nbytes;
209} 209}
210 210
211#define POP_SS_OPCODE 0x1f
212#define MOV_SREG_OPCODE 0x8e
213
214/*
215 * Intel SDM Vol.3A 6.8.3 states;
216 * "Any single-step trap that would be delivered following the MOV to SS
217 * instruction or POP to SS instruction (because EFLAGS.TF is 1) is
218 * suppressed."
219 * This function returns true if @insn is MOV SS or POP SS. On these
220 * instructions, single stepping is suppressed.
221 */
222static inline int insn_masking_exception(struct insn *insn)
223{
224 return insn->opcode.bytes[0] == POP_SS_OPCODE ||
225 (insn->opcode.bytes[0] == MOV_SREG_OPCODE &&
226 X86_MODRM_REG(insn->modrm.bytes[0]) == 2);
227}
228
211#endif /* _ASM_X86_INSN_H */ 229#endif /* _ASM_X86_INSN_H */
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index 0effaff57020..492986a25ef6 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -442,8 +442,7 @@ static int intel_pt_walk_next_insn(struct intel_pt_insn *intel_pt_insn,
442 } 442 }
443 443
444 while (1) { 444 while (1) {
445 thread__find_addr_map(thread, cpumode, MAP__FUNCTION, *ip, &al); 445 if (!thread__find_map(thread, cpumode, *ip, &al) || !al.map->dso)
446 if (!al.map || !al.map->dso)
447 return -EINVAL; 446 return -EINVAL;
448 447
449 if (al.map->dso->data.status == DSO_DATA_STATUS_ERROR && 448 if (al.map->dso->data.status == DSO_DATA_STATUS_ERROR &&
@@ -596,8 +595,7 @@ static int __intel_pt_pgd_ip(uint64_t ip, void *data)
596 if (!thread) 595 if (!thread)
597 return -EINVAL; 596 return -EINVAL;
598 597
599 thread__find_addr_map(thread, cpumode, MAP__FUNCTION, ip, &al); 598 if (!thread__find_map(thread, cpumode, ip, &al) || !al.map->dso)
600 if (!al.map || !al.map->dso)
601 return -EINVAL; 599 return -EINVAL;
602 600
603 offset = al.map->map_ip(al.map, ip); 601 offset = al.map->map_ip(al.map, ip);
@@ -1565,7 +1563,7 @@ static u64 intel_pt_switch_ip(struct intel_pt *pt, u64 *ptss_ip)
1565 if (map__load(map)) 1563 if (map__load(map))
1566 return 0; 1564 return 0;
1567 1565
1568 start = dso__first_symbol(map->dso, MAP__FUNCTION); 1566 start = dso__first_symbol(map->dso);
1569 1567
1570 for (sym = start; sym; sym = dso__next_symbol(sym)) { 1568 for (sym = start; sym; sym = dso__next_symbol(sym)) {
1571 if (sym->binding == STB_GLOBAL && 1569 if (sym->binding == STB_GLOBAL &&
diff --git a/tools/perf/util/llvm-utils.c b/tools/perf/util/llvm-utils.c
index 1cca0a2fa641..976e658e38dc 100644
--- a/tools/perf/util/llvm-utils.c
+++ b/tools/perf/util/llvm-utils.c
@@ -14,11 +14,12 @@
14#include "config.h" 14#include "config.h"
15#include "util.h" 15#include "util.h"
16#include <sys/wait.h> 16#include <sys/wait.h>
17#include <subcmd/exec-cmd.h>
17 18
18#define CLANG_BPF_CMD_DEFAULT_TEMPLATE \ 19#define CLANG_BPF_CMD_DEFAULT_TEMPLATE \
19 "$CLANG_EXEC -D__KERNEL__ -D__NR_CPUS__=$NR_CPUS "\ 20 "$CLANG_EXEC -D__KERNEL__ -D__NR_CPUS__=$NR_CPUS "\
20 "-DLINUX_VERSION_CODE=$LINUX_VERSION_CODE " \ 21 "-DLINUX_VERSION_CODE=$LINUX_VERSION_CODE " \
21 "$CLANG_OPTIONS $KERNEL_INC_OPTIONS " \ 22 "$CLANG_OPTIONS $KERNEL_INC_OPTIONS $PERF_BPF_INC_OPTIONS " \
22 "-Wno-unused-value -Wno-pointer-sign " \ 23 "-Wno-unused-value -Wno-pointer-sign " \
23 "-working-directory $WORKING_DIR " \ 24 "-working-directory $WORKING_DIR " \
24 "-c \"$CLANG_SOURCE\" -target bpf -O2 -o -" 25 "-c \"$CLANG_SOURCE\" -target bpf -O2 -o -"
@@ -212,7 +213,7 @@ version_notice(void)
212" \t\thttp://llvm.org/apt\n\n" 213" \t\thttp://llvm.org/apt\n\n"
213" \tIf you are using old version of clang, change 'clang-bpf-cmd-template'\n" 214" \tIf you are using old version of clang, change 'clang-bpf-cmd-template'\n"
214" \toption in [llvm] section of ~/.perfconfig to:\n\n" 215" \toption in [llvm] section of ~/.perfconfig to:\n\n"
215" \t \"$CLANG_EXEC $CLANG_OPTIONS $KERNEL_INC_OPTIONS \\\n" 216" \t \"$CLANG_EXEC $CLANG_OPTIONS $KERNEL_INC_OPTIONS $PERF_BPF_INC_OPTIONS \\\n"
216" \t -working-directory $WORKING_DIR -c $CLANG_SOURCE \\\n" 217" \t -working-directory $WORKING_DIR -c $CLANG_SOURCE \\\n"
217" \t -emit-llvm -o - | /path/to/llc -march=bpf -filetype=obj -o -\"\n" 218" \t -emit-llvm -o - | /path/to/llc -march=bpf -filetype=obj -o -\"\n"
218" \t(Replace /path/to/llc with path to your llc)\n\n" 219" \t(Replace /path/to/llc with path to your llc)\n\n"
@@ -431,9 +432,11 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
431 const char *clang_opt = llvm_param.clang_opt; 432 const char *clang_opt = llvm_param.clang_opt;
432 char clang_path[PATH_MAX], abspath[PATH_MAX], nr_cpus_avail_str[64]; 433 char clang_path[PATH_MAX], abspath[PATH_MAX], nr_cpus_avail_str[64];
433 char serr[STRERR_BUFSIZE]; 434 char serr[STRERR_BUFSIZE];
434 char *kbuild_dir = NULL, *kbuild_include_opts = NULL; 435 char *kbuild_dir = NULL, *kbuild_include_opts = NULL,
436 *perf_bpf_include_opts = NULL;
435 const char *template = llvm_param.clang_bpf_cmd_template; 437 const char *template = llvm_param.clang_bpf_cmd_template;
436 char *command_echo, *command_out; 438 char *command_echo = NULL, *command_out;
439 char *perf_include_dir = system_path(PERF_INCLUDE_DIR);
437 440
438 if (path[0] != '-' && realpath(path, abspath) == NULL) { 441 if (path[0] != '-' && realpath(path, abspath) == NULL) {
439 err = errno; 442 err = errno;
@@ -471,12 +474,14 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
471 474
472 snprintf(linux_version_code_str, sizeof(linux_version_code_str), 475 snprintf(linux_version_code_str, sizeof(linux_version_code_str),
473 "0x%x", kernel_version); 476 "0x%x", kernel_version);
474 477 if (asprintf(&perf_bpf_include_opts, "-I%s/bpf", perf_include_dir) < 0)
478 goto errout;
475 force_set_env("NR_CPUS", nr_cpus_avail_str); 479 force_set_env("NR_CPUS", nr_cpus_avail_str);
476 force_set_env("LINUX_VERSION_CODE", linux_version_code_str); 480 force_set_env("LINUX_VERSION_CODE", linux_version_code_str);
477 force_set_env("CLANG_EXEC", clang_path); 481 force_set_env("CLANG_EXEC", clang_path);
478 force_set_env("CLANG_OPTIONS", clang_opt); 482 force_set_env("CLANG_OPTIONS", clang_opt);
479 force_set_env("KERNEL_INC_OPTIONS", kbuild_include_opts); 483 force_set_env("KERNEL_INC_OPTIONS", kbuild_include_opts);
484 force_set_env("PERF_BPF_INC_OPTIONS", perf_bpf_include_opts);
480 force_set_env("WORKING_DIR", kbuild_dir ? : "."); 485 force_set_env("WORKING_DIR", kbuild_dir ? : ".");
481 486
482 /* 487 /*
@@ -512,6 +517,8 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
512 free(command_out); 517 free(command_out);
513 free(kbuild_dir); 518 free(kbuild_dir);
514 free(kbuild_include_opts); 519 free(kbuild_include_opts);
520 free(perf_bpf_include_opts);
521 free(perf_include_dir);
515 522
516 if (!p_obj_buf) 523 if (!p_obj_buf)
517 free(obj_buf); 524 free(obj_buf);
@@ -526,6 +533,8 @@ errout:
526 free(kbuild_dir); 533 free(kbuild_dir);
527 free(kbuild_include_opts); 534 free(kbuild_include_opts);
528 free(obj_buf); 535 free(obj_buf);
536 free(perf_bpf_include_opts);
537 free(perf_include_dir);
529 if (p_obj_buf) 538 if (p_obj_buf)
530 *p_obj_buf = NULL; 539 *p_obj_buf = NULL;
531 if (p_obj_buf_sz) 540 if (p_obj_buf_sz)
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 2eca8478e24f..e7b4a8b513f2 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -24,6 +24,7 @@
24 24
25#include "sane_ctype.h" 25#include "sane_ctype.h"
26#include <symbol/kallsyms.h> 26#include <symbol/kallsyms.h>
27#include <linux/mman.h>
27 28
28static void __machine__remove_thread(struct machine *machine, struct thread *th, bool lock); 29static void __machine__remove_thread(struct machine *machine, struct thread *th, bool lock);
29 30
@@ -81,8 +82,7 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
81 machine->kptr_restrict_warned = false; 82 machine->kptr_restrict_warned = false;
82 machine->comm_exec = false; 83 machine->comm_exec = false;
83 machine->kernel_start = 0; 84 machine->kernel_start = 0;
84 85 machine->vmlinux_map = NULL;
85 memset(machine->vmlinux_maps, 0, sizeof(machine->vmlinux_maps));
86 86
87 machine->root_dir = strdup(root_dir); 87 machine->root_dir = strdup(root_dir);
88 if (machine->root_dir == NULL) 88 if (machine->root_dir == NULL)
@@ -137,13 +137,11 @@ struct machine *machine__new_kallsyms(void)
137 struct machine *machine = machine__new_host(); 137 struct machine *machine = machine__new_host();
138 /* 138 /*
139 * FIXME: 139 * FIXME:
140 * 1) MAP__FUNCTION will go away when we stop loading separate maps for 140 * 1) We should switch to machine__load_kallsyms(), i.e. not explicitely
141 * functions and data objects.
142 * 2) We should switch to machine__load_kallsyms(), i.e. not explicitely
143 * ask for not using the kcore parsing code, once this one is fixed 141 * ask for not using the kcore parsing code, once this one is fixed
144 * to create a map per module. 142 * to create a map per module.
145 */ 143 */
146 if (machine && machine__load_kallsyms(machine, "/proc/kallsyms", MAP__FUNCTION) <= 0) { 144 if (machine && machine__load_kallsyms(machine, "/proc/kallsyms") <= 0) {
147 machine__delete(machine); 145 machine__delete(machine);
148 machine = NULL; 146 machine = NULL;
149 } 147 }
@@ -673,8 +671,7 @@ struct map *machine__findnew_module_map(struct machine *machine, u64 start,
673 if (kmod_path__parse_name(&m, filename)) 671 if (kmod_path__parse_name(&m, filename))
674 return NULL; 672 return NULL;
675 673
676 map = map_groups__find_by_name(&machine->kmaps, MAP__FUNCTION, 674 map = map_groups__find_by_name(&machine->kmaps, m.name);
677 m.name);
678 if (map) { 675 if (map) {
679 /* 676 /*
680 * If the map's dso is an offline module, give dso__load() 677 * If the map's dso is an offline module, give dso__load()
@@ -689,7 +686,7 @@ struct map *machine__findnew_module_map(struct machine *machine, u64 start,
689 if (dso == NULL) 686 if (dso == NULL)
690 goto out; 687 goto out;
691 688
692 map = map__new2(start, dso, MAP__FUNCTION); 689 map = map__new2(start, dso);
693 if (map == NULL) 690 if (map == NULL)
694 goto out; 691 goto out;
695 692
@@ -810,8 +807,8 @@ struct process_args {
810 u64 start; 807 u64 start;
811}; 808};
812 809
813static void machine__get_kallsyms_filename(struct machine *machine, char *buf, 810void machine__get_kallsyms_filename(struct machine *machine, char *buf,
814 size_t bufsz) 811 size_t bufsz)
815{ 812{
816 if (machine__is_default_guest(machine)) 813 if (machine__is_default_guest(machine))
817 scnprintf(buf, bufsz, "%s", symbol_conf.default_guest_kallsyms); 814 scnprintf(buf, bufsz, "%s", symbol_conf.default_guest_kallsyms);
@@ -854,65 +851,171 @@ static int machine__get_running_kernel_start(struct machine *machine,
854 return 0; 851 return 0;
855} 852}
856 853
854int machine__create_extra_kernel_map(struct machine *machine,
855 struct dso *kernel,
856 struct extra_kernel_map *xm)
857{
858 struct kmap *kmap;
859 struct map *map;
860
861 map = map__new2(xm->start, kernel);
862 if (!map)
863 return -1;
864
865 map->end = xm->end;
866 map->pgoff = xm->pgoff;
867
868 kmap = map__kmap(map);
869
870 kmap->kmaps = &machine->kmaps;
871 strlcpy(kmap->name, xm->name, KMAP_NAME_LEN);
872
873 map_groups__insert(&machine->kmaps, map);
874
875 pr_debug2("Added extra kernel map %s %" PRIx64 "-%" PRIx64 "\n",
876 kmap->name, map->start, map->end);
877
878 map__put(map);
879
880 return 0;
881}
882
883static u64 find_entry_trampoline(struct dso *dso)
884{
885 /* Duplicates are removed so lookup all aliases */
886 const char *syms[] = {
887 "_entry_trampoline",
888 "__entry_trampoline_start",
889 "entry_SYSCALL_64_trampoline",
890 };
891 struct symbol *sym = dso__first_symbol(dso);
892 unsigned int i;
893
894 for (; sym; sym = dso__next_symbol(sym)) {
895 if (sym->binding != STB_GLOBAL)
896 continue;
897 for (i = 0; i < ARRAY_SIZE(syms); i++) {
898 if (!strcmp(sym->name, syms[i]))
899 return sym->start;
900 }
901 }
902
903 return 0;
904}
905
906/*
907 * These values can be used for kernels that do not have symbols for the entry
908 * trampolines in kallsyms.
909 */
910#define X86_64_CPU_ENTRY_AREA_PER_CPU 0xfffffe0000000000ULL
911#define X86_64_CPU_ENTRY_AREA_SIZE 0x2c000
912#define X86_64_ENTRY_TRAMPOLINE 0x6000
913
914/* Map x86_64 PTI entry trampolines */
915int machine__map_x86_64_entry_trampolines(struct machine *machine,
916 struct dso *kernel)
917{
918 struct map_groups *kmaps = &machine->kmaps;
919 struct maps *maps = &kmaps->maps;
920 int nr_cpus_avail, cpu;
921 bool found = false;
922 struct map *map;
923 u64 pgoff;
924
925 /*
926 * In the vmlinux case, pgoff is a virtual address which must now be
927 * mapped to a vmlinux offset.
928 */
929 for (map = maps__first(maps); map; map = map__next(map)) {
930 struct kmap *kmap = __map__kmap(map);
931 struct map *dest_map;
932
933 if (!kmap || !is_entry_trampoline(kmap->name))
934 continue;
935
936 dest_map = map_groups__find(kmaps, map->pgoff);
937 if (dest_map != map)
938 map->pgoff = dest_map->map_ip(dest_map, map->pgoff);
939 found = true;
940 }
941 if (found || machine->trampolines_mapped)
942 return 0;
943
944 pgoff = find_entry_trampoline(kernel);
945 if (!pgoff)
946 return 0;
947
948 nr_cpus_avail = machine__nr_cpus_avail(machine);
949
950 /* Add a 1 page map for each CPU's entry trampoline */
951 for (cpu = 0; cpu < nr_cpus_avail; cpu++) {
952 u64 va = X86_64_CPU_ENTRY_AREA_PER_CPU +
953 cpu * X86_64_CPU_ENTRY_AREA_SIZE +
954 X86_64_ENTRY_TRAMPOLINE;
955 struct extra_kernel_map xm = {
956 .start = va,
957 .end = va + page_size,
958 .pgoff = pgoff,
959 };
960
961 strlcpy(xm.name, ENTRY_TRAMPOLINE_NAME, KMAP_NAME_LEN);
962
963 if (machine__create_extra_kernel_map(machine, kernel, &xm) < 0)
964 return -1;
965 }
966
967 machine->trampolines_mapped = nr_cpus_avail;
968
969 return 0;
970}
971
972int __weak machine__create_extra_kernel_maps(struct machine *machine __maybe_unused,
973 struct dso *kernel __maybe_unused)
974{
975 return 0;
976}
977
857static int 978static int
858__machine__create_kernel_maps(struct machine *machine, struct dso *kernel) 979__machine__create_kernel_maps(struct machine *machine, struct dso *kernel)
859{ 980{
860 int type; 981 struct kmap *kmap;
982 struct map *map;
861 983
862 /* In case of renewal the kernel map, destroy previous one */ 984 /* In case of renewal the kernel map, destroy previous one */
863 machine__destroy_kernel_maps(machine); 985 machine__destroy_kernel_maps(machine);
864 986
865 for (type = 0; type < MAP__NR_TYPES; ++type) { 987 machine->vmlinux_map = map__new2(0, kernel);
866 struct kmap *kmap; 988 if (machine->vmlinux_map == NULL)
867 struct map *map; 989 return -1;
868
869 machine->vmlinux_maps[type] = map__new2(0, kernel, type);
870 if (machine->vmlinux_maps[type] == NULL)
871 return -1;
872 990
873 machine->vmlinux_maps[type]->map_ip = 991 machine->vmlinux_map->map_ip = machine->vmlinux_map->unmap_ip = identity__map_ip;
874 machine->vmlinux_maps[type]->unmap_ip = 992 map = machine__kernel_map(machine);
875 identity__map_ip; 993 kmap = map__kmap(map);
876 map = __machine__kernel_map(machine, type); 994 if (!kmap)
877 kmap = map__kmap(map); 995 return -1;
878 if (!kmap)
879 return -1;
880 996
881 kmap->kmaps = &machine->kmaps; 997 kmap->kmaps = &machine->kmaps;
882 map_groups__insert(&machine->kmaps, map); 998 map_groups__insert(&machine->kmaps, map);
883 }
884 999
885 return 0; 1000 return 0;
886} 1001}
887 1002
888void machine__destroy_kernel_maps(struct machine *machine) 1003void machine__destroy_kernel_maps(struct machine *machine)
889{ 1004{
890 int type; 1005 struct kmap *kmap;
891 1006 struct map *map = machine__kernel_map(machine);
892 for (type = 0; type < MAP__NR_TYPES; ++type) {
893 struct kmap *kmap;
894 struct map *map = __machine__kernel_map(machine, type);
895
896 if (map == NULL)
897 continue;
898 1007
899 kmap = map__kmap(map); 1008 if (map == NULL)
900 map_groups__remove(&machine->kmaps, map); 1009 return;
901 if (kmap && kmap->ref_reloc_sym) {
902 /*
903 * ref_reloc_sym is shared among all maps, so free just
904 * on one of them.
905 */
906 if (type == MAP__FUNCTION) {
907 zfree((char **)&kmap->ref_reloc_sym->name);
908 zfree(&kmap->ref_reloc_sym);
909 } else
910 kmap->ref_reloc_sym = NULL;
911 }
912 1010
913 map__put(machine->vmlinux_maps[type]); 1011 kmap = map__kmap(map);
914 machine->vmlinux_maps[type] = NULL; 1012 map_groups__remove(&machine->kmaps, map);
1013 if (kmap && kmap->ref_reloc_sym) {
1014 zfree((char **)&kmap->ref_reloc_sym->name);
1015 zfree(&kmap->ref_reloc_sym);
915 } 1016 }
1017
1018 map__zput(machine->vmlinux_map);
916} 1019}
917 1020
918int machines__create_guest_kernel_maps(struct machines *machines) 1021int machines__create_guest_kernel_maps(struct machines *machines)
@@ -989,43 +1092,35 @@ int machines__create_kernel_maps(struct machines *machines, pid_t pid)
989 return machine__create_kernel_maps(machine); 1092 return machine__create_kernel_maps(machine);
990} 1093}
991 1094
992int machine__load_kallsyms(struct machine *machine, const char *filename, 1095int machine__load_kallsyms(struct machine *machine, const char *filename)
993 enum map_type type)
994{ 1096{
995 struct map *map = machine__kernel_map(machine); 1097 struct map *map = machine__kernel_map(machine);
996 int ret = __dso__load_kallsyms(map->dso, filename, map, true); 1098 int ret = __dso__load_kallsyms(map->dso, filename, map, true);
997 1099
998 if (ret > 0) { 1100 if (ret > 0) {
999 dso__set_loaded(map->dso, type); 1101 dso__set_loaded(map->dso);
1000 /* 1102 /*
1001 * Since /proc/kallsyms will have multiple sessions for the 1103 * Since /proc/kallsyms will have multiple sessions for the
1002 * kernel, with modules between them, fixup the end of all 1104 * kernel, with modules between them, fixup the end of all
1003 * sections. 1105 * sections.
1004 */ 1106 */
1005 __map_groups__fixup_end(&machine->kmaps, type); 1107 map_groups__fixup_end(&machine->kmaps);
1006 } 1108 }
1007 1109
1008 return ret; 1110 return ret;
1009} 1111}
1010 1112
1011int machine__load_vmlinux_path(struct machine *machine, enum map_type type) 1113int machine__load_vmlinux_path(struct machine *machine)
1012{ 1114{
1013 struct map *map = machine__kernel_map(machine); 1115 struct map *map = machine__kernel_map(machine);
1014 int ret = dso__load_vmlinux_path(map->dso, map); 1116 int ret = dso__load_vmlinux_path(map->dso, map);
1015 1117
1016 if (ret > 0) 1118 if (ret > 0)
1017 dso__set_loaded(map->dso, type); 1119 dso__set_loaded(map->dso);
1018 1120
1019 return ret; 1121 return ret;
1020} 1122}
1021 1123
1022static void map_groups__fixup_end(struct map_groups *mg)
1023{
1024 int i;
1025 for (i = 0; i < MAP__NR_TYPES; ++i)
1026 __map_groups__fixup_end(mg, i);
1027}
1028
1029static char *get_kernel_version(const char *root_dir) 1124static char *get_kernel_version(const char *root_dir)
1030{ 1125{
1031 char version[PATH_MAX]; 1126 char version[PATH_MAX];
@@ -1062,10 +1157,9 @@ static bool is_kmod_dso(struct dso *dso)
1062static int map_groups__set_module_path(struct map_groups *mg, const char *path, 1157static int map_groups__set_module_path(struct map_groups *mg, const char *path,
1063 struct kmod_path *m) 1158 struct kmod_path *m)
1064{ 1159{
1065 struct map *map;
1066 char *long_name; 1160 char *long_name;
1161 struct map *map = map_groups__find_by_name(mg, m->name);
1067 1162
1068 map = map_groups__find_by_name(mg, MAP__FUNCTION, m->name);
1069 if (map == NULL) 1163 if (map == NULL)
1070 return 0; 1164 return 0;
1071 1165
@@ -1214,25 +1308,21 @@ static int machine__create_modules(struct machine *machine)
1214static void machine__set_kernel_mmap(struct machine *machine, 1308static void machine__set_kernel_mmap(struct machine *machine,
1215 u64 start, u64 end) 1309 u64 start, u64 end)
1216{ 1310{
1217 int i; 1311 machine->vmlinux_map->start = start;
1218 1312 machine->vmlinux_map->end = end;
1219 for (i = 0; i < MAP__NR_TYPES; i++) { 1313 /*
1220 machine->vmlinux_maps[i]->start = start; 1314 * Be a bit paranoid here, some perf.data file came with
1221 machine->vmlinux_maps[i]->end = end; 1315 * a zero sized synthesized MMAP event for the kernel.
1222 1316 */
1223 /* 1317 if (start == 0 && end == 0)
1224 * Be a bit paranoid here, some perf.data file came with 1318 machine->vmlinux_map->end = ~0ULL;
1225 * a zero sized synthesized MMAP event for the kernel.
1226 */
1227 if (start == 0 && end == 0)
1228 machine->vmlinux_maps[i]->end = ~0ULL;
1229 }
1230} 1319}
1231 1320
1232int machine__create_kernel_maps(struct machine *machine) 1321int machine__create_kernel_maps(struct machine *machine)
1233{ 1322{
1234 struct dso *kernel = machine__get_kernel(machine); 1323 struct dso *kernel = machine__get_kernel(machine);
1235 const char *name = NULL; 1324 const char *name = NULL;
1325 struct map *map;
1236 u64 addr = 0; 1326 u64 addr = 0;
1237 int ret; 1327 int ret;
1238 1328
@@ -1240,9 +1330,8 @@ int machine__create_kernel_maps(struct machine *machine)
1240 return -1; 1330 return -1;
1241 1331
1242 ret = __machine__create_kernel_maps(machine, kernel); 1332 ret = __machine__create_kernel_maps(machine, kernel);
1243 dso__put(kernel);
1244 if (ret < 0) 1333 if (ret < 0)
1245 return -1; 1334 goto out_put;
1246 1335
1247 if (symbol_conf.use_modules && machine__create_modules(machine) < 0) { 1336 if (symbol_conf.use_modules && machine__create_modules(machine) < 0) {
1248 if (machine__is_host(machine)) 1337 if (machine__is_host(machine))
@@ -1255,18 +1344,35 @@ int machine__create_kernel_maps(struct machine *machine)
1255 1344
1256 if (!machine__get_running_kernel_start(machine, &name, &addr)) { 1345 if (!machine__get_running_kernel_start(machine, &name, &addr)) {
1257 if (name && 1346 if (name &&
1258 maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, name, addr)) { 1347 map__set_kallsyms_ref_reloc_sym(machine->vmlinux_map, name, addr)) {
1259 machine__destroy_kernel_maps(machine); 1348 machine__destroy_kernel_maps(machine);
1260 return -1; 1349 ret = -1;
1350 goto out_put;
1261 } 1351 }
1262 machine__set_kernel_mmap(machine, addr, 0); 1352
1353 /* we have a real start address now, so re-order the kmaps */
1354 map = machine__kernel_map(machine);
1355
1356 map__get(map);
1357 map_groups__remove(&machine->kmaps, map);
1358
1359 /* assume it's the last in the kmaps */
1360 machine__set_kernel_mmap(machine, addr, ~0ULL);
1361
1362 map_groups__insert(&machine->kmaps, map);
1363 map__put(map);
1263 } 1364 }
1264 1365
1265 /* 1366 if (machine__create_extra_kernel_maps(machine, kernel))
1266 * Now that we have all the maps created, just set the ->end of them: 1367 pr_debug("Problems creating extra kernel maps, continuing anyway...\n");
1267 */ 1368
1268 map_groups__fixup_end(&machine->kmaps); 1369 /* update end address of the kernel map using adjacent module address */
1269 return 0; 1370 map = map__next(machine__kernel_map(machine));
1371 if (map)
1372 machine__set_kernel_mmap(machine, addr, map->start);
1373out_put:
1374 dso__put(kernel);
1375 return ret;
1270} 1376}
1271 1377
1272static bool machine__uses_kcore(struct machine *machine) 1378static bool machine__uses_kcore(struct machine *machine)
@@ -1281,6 +1387,32 @@ static bool machine__uses_kcore(struct machine *machine)
1281 return false; 1387 return false;
1282} 1388}
1283 1389
1390static bool perf_event__is_extra_kernel_mmap(struct machine *machine,
1391 union perf_event *event)
1392{
1393 return machine__is(machine, "x86_64") &&
1394 is_entry_trampoline(event->mmap.filename);
1395}
1396
1397static int machine__process_extra_kernel_map(struct machine *machine,
1398 union perf_event *event)
1399{
1400 struct map *kernel_map = machine__kernel_map(machine);
1401 struct dso *kernel = kernel_map ? kernel_map->dso : NULL;
1402 struct extra_kernel_map xm = {
1403 .start = event->mmap.start,
1404 .end = event->mmap.start + event->mmap.len,
1405 .pgoff = event->mmap.pgoff,
1406 };
1407
1408 if (kernel == NULL)
1409 return -1;
1410
1411 strlcpy(xm.name, event->mmap.filename, KMAP_NAME_LEN);
1412
1413 return machine__create_extra_kernel_map(machine, kernel, &xm);
1414}
1415
1284static int machine__process_kernel_mmap_event(struct machine *machine, 1416static int machine__process_kernel_mmap_event(struct machine *machine,
1285 union perf_event *event) 1417 union perf_event *event)
1286{ 1418{
@@ -1373,9 +1505,9 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
1373 * time /proc/sys/kernel/kptr_restrict was non zero. 1505 * time /proc/sys/kernel/kptr_restrict was non zero.
1374 */ 1506 */
1375 if (event->mmap.pgoff != 0) { 1507 if (event->mmap.pgoff != 0) {
1376 maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, 1508 map__set_kallsyms_ref_reloc_sym(machine->vmlinux_map,
1377 symbol_name, 1509 symbol_name,
1378 event->mmap.pgoff); 1510 event->mmap.pgoff);
1379 } 1511 }
1380 1512
1381 if (machine__is_default_guest(machine)) { 1513 if (machine__is_default_guest(machine)) {
@@ -1384,6 +1516,8 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
1384 */ 1516 */
1385 dso__load(kernel, machine__kernel_map(machine)); 1517 dso__load(kernel, machine__kernel_map(machine));
1386 } 1518 }
1519 } else if (perf_event__is_extra_kernel_mmap(machine, event)) {
1520 return machine__process_extra_kernel_map(machine, event);
1387 } 1521 }
1388 return 0; 1522 return 0;
1389out_problem: 1523out_problem:
@@ -1396,7 +1530,6 @@ int machine__process_mmap2_event(struct machine *machine,
1396{ 1530{
1397 struct thread *thread; 1531 struct thread *thread;
1398 struct map *map; 1532 struct map *map;
1399 enum map_type type;
1400 int ret = 0; 1533 int ret = 0;
1401 1534
1402 if (dump_trace) 1535 if (dump_trace)
@@ -1415,11 +1548,6 @@ int machine__process_mmap2_event(struct machine *machine,
1415 if (thread == NULL) 1548 if (thread == NULL)
1416 goto out_problem; 1549 goto out_problem;
1417 1550
1418 if (event->header.misc & PERF_RECORD_MISC_MMAP_DATA)
1419 type = MAP__VARIABLE;
1420 else
1421 type = MAP__FUNCTION;
1422
1423 map = map__new(machine, event->mmap2.start, 1551 map = map__new(machine, event->mmap2.start,
1424 event->mmap2.len, event->mmap2.pgoff, 1552 event->mmap2.len, event->mmap2.pgoff,
1425 event->mmap2.maj, 1553 event->mmap2.maj,
@@ -1427,7 +1555,7 @@ int machine__process_mmap2_event(struct machine *machine,
1427 event->mmap2.ino_generation, 1555 event->mmap2.ino_generation,
1428 event->mmap2.prot, 1556 event->mmap2.prot,
1429 event->mmap2.flags, 1557 event->mmap2.flags,
1430 event->mmap2.filename, type, thread); 1558 event->mmap2.filename, thread);
1431 1559
1432 if (map == NULL) 1560 if (map == NULL)
1433 goto out_problem_map; 1561 goto out_problem_map;
@@ -1454,7 +1582,7 @@ int machine__process_mmap_event(struct machine *machine, union perf_event *event
1454{ 1582{
1455 struct thread *thread; 1583 struct thread *thread;
1456 struct map *map; 1584 struct map *map;
1457 enum map_type type; 1585 u32 prot = 0;
1458 int ret = 0; 1586 int ret = 0;
1459 1587
1460 if (dump_trace) 1588 if (dump_trace)
@@ -1473,16 +1601,14 @@ int machine__process_mmap_event(struct machine *machine, union perf_event *event
1473 if (thread == NULL) 1601 if (thread == NULL)
1474 goto out_problem; 1602 goto out_problem;
1475 1603
1476 if (event->header.misc & PERF_RECORD_MISC_MMAP_DATA) 1604 if (!(event->header.misc & PERF_RECORD_MISC_MMAP_DATA))
1477 type = MAP__VARIABLE; 1605 prot = PROT_EXEC;
1478 else
1479 type = MAP__FUNCTION;
1480 1606
1481 map = map__new(machine, event->mmap.start, 1607 map = map__new(machine, event->mmap.start,
1482 event->mmap.len, event->mmap.pgoff, 1608 event->mmap.len, event->mmap.pgoff,
1483 0, 0, 0, 0, 0, 0, 1609 0, 0, 0, 0, prot, 0,
1484 event->mmap.filename, 1610 event->mmap.filename,
1485 type, thread); 1611 thread);
1486 1612
1487 if (map == NULL) 1613 if (map == NULL)
1488 goto out_problem_map; 1614 goto out_problem_map;
@@ -1658,7 +1784,7 @@ static void ip__resolve_ams(struct thread *thread,
1658 * Thus, we have to try consecutively until we find a match 1784 * Thus, we have to try consecutively until we find a match
1659 * or else, the symbol is unknown 1785 * or else, the symbol is unknown
1660 */ 1786 */
1661 thread__find_cpumode_addr_location(thread, MAP__FUNCTION, ip, &al); 1787 thread__find_cpumode_addr_location(thread, ip, &al);
1662 1788
1663 ams->addr = ip; 1789 ams->addr = ip;
1664 ams->al_addr = al.addr; 1790 ams->al_addr = al.addr;
@@ -1675,15 +1801,7 @@ static void ip__resolve_data(struct thread *thread,
1675 1801
1676 memset(&al, 0, sizeof(al)); 1802 memset(&al, 0, sizeof(al));
1677 1803
1678 thread__find_addr_location(thread, m, MAP__VARIABLE, addr, &al); 1804 thread__find_symbol(thread, m, addr, &al);
1679 if (al.map == NULL) {
1680 /*
1681 * some shared data regions have execute bit set which puts
1682 * their mapping in the MAP__FUNCTION type array.
1683 * Check there as a fallback option before dropping the sample.
1684 */
1685 thread__find_addr_location(thread, m, MAP__FUNCTION, addr, &al);
1686 }
1687 1805
1688 ams->addr = addr; 1806 ams->addr = addr;
1689 ams->al_addr = al.addr; 1807 ams->al_addr = al.addr;
@@ -1752,8 +1870,7 @@ static int add_callchain_ip(struct thread *thread,
1752 al.filtered = 0; 1870 al.filtered = 0;
1753 al.sym = NULL; 1871 al.sym = NULL;
1754 if (!cpumode) { 1872 if (!cpumode) {
1755 thread__find_cpumode_addr_location(thread, MAP__FUNCTION, 1873 thread__find_cpumode_addr_location(thread, ip, &al);
1756 ip, &al);
1757 } else { 1874 } else {
1758 if (ip >= PERF_CONTEXT_MAX) { 1875 if (ip >= PERF_CONTEXT_MAX) {
1759 switch (ip) { 1876 switch (ip) {
@@ -1778,8 +1895,7 @@ static int add_callchain_ip(struct thread *thread,
1778 } 1895 }
1779 return 0; 1896 return 0;
1780 } 1897 }
1781 thread__find_addr_location(thread, *cpumode, MAP__FUNCTION, 1898 thread__find_symbol(thread, *cpumode, ip, &al);
1782 ip, &al);
1783 } 1899 }
1784 1900
1785 if (al.sym != NULL) { 1901 if (al.sym != NULL) {
@@ -1804,7 +1920,7 @@ static int add_callchain_ip(struct thread *thread,
1804 } 1920 }
1805 1921
1806 srcline = callchain_srcline(al.map, al.sym, al.addr); 1922 srcline = callchain_srcline(al.map, al.sym, al.addr);
1807 return callchain_cursor_append(cursor, al.addr, al.map, al.sym, 1923 return callchain_cursor_append(cursor, ip, al.map, al.sym,
1808 branch, flags, nr_loop_iter, 1924 branch, flags, nr_loop_iter,
1809 iter_cycles, branch_from, srcline); 1925 iter_cycles, branch_from, srcline);
1810} 1926}
@@ -2336,6 +2452,20 @@ int machine__set_current_tid(struct machine *machine, int cpu, pid_t pid,
2336 return 0; 2452 return 0;
2337} 2453}
2338 2454
2455/*
2456 * Compares the raw arch string. N.B. see instead perf_env__arch() if a
2457 * normalized arch is needed.
2458 */
2459bool machine__is(struct machine *machine, const char *arch)
2460{
2461 return machine && !strcmp(perf_env__raw_arch(machine->env), arch);
2462}
2463
2464int machine__nr_cpus_avail(struct machine *machine)
2465{
2466 return machine ? perf_env__nr_cpus_avail(machine->env) : 0;
2467}
2468
2339int machine__get_kernel_start(struct machine *machine) 2469int machine__get_kernel_start(struct machine *machine)
2340{ 2470{
2341 struct map *map = machine__kernel_map(machine); 2471 struct map *map = machine__kernel_map(machine);
@@ -2352,7 +2482,12 @@ int machine__get_kernel_start(struct machine *machine)
2352 machine->kernel_start = 1ULL << 63; 2482 machine->kernel_start = 1ULL << 63;
2353 if (map) { 2483 if (map) {
2354 err = map__load(map); 2484 err = map__load(map);
2355 if (!err) 2485 /*
2486 * On x86_64, PTI entry trampolines are less than the
2487 * start of kernel text, but still above 2^63. So leave
2488 * kernel_start = 1ULL << 63 for x86_64.
2489 */
2490 if (!err && !machine__is(machine, "x86_64"))
2356 machine->kernel_start = map->start; 2491 machine->kernel_start = map->start;
2357 } 2492 }
2358 return err; 2493 return err;
@@ -2367,7 +2502,7 @@ char *machine__resolve_kernel_addr(void *vmachine, unsigned long long *addrp, ch
2367{ 2502{
2368 struct machine *machine = vmachine; 2503 struct machine *machine = vmachine;
2369 struct map *map; 2504 struct map *map;
2370 struct symbol *sym = map_groups__find_symbol(&machine->kmaps, MAP__FUNCTION, *addrp, &map); 2505 struct symbol *sym = machine__find_kernel_symbol(machine, *addrp, &map);
2371 2506
2372 if (sym == NULL) 2507 if (sym == NULL)
2373 return NULL; 2508 return NULL;
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index 66cc200ef86f..1de7660d93e9 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -49,13 +49,14 @@ struct machine {
49 struct perf_env *env; 49 struct perf_env *env;
50 struct dsos dsos; 50 struct dsos dsos;
51 struct map_groups kmaps; 51 struct map_groups kmaps;
52 struct map *vmlinux_maps[MAP__NR_TYPES]; 52 struct map *vmlinux_map;
53 u64 kernel_start; 53 u64 kernel_start;
54 pid_t *current_tid; 54 pid_t *current_tid;
55 union { /* Tool specific area */ 55 union { /* Tool specific area */
56 void *priv; 56 void *priv;
57 u64 db_id; 57 u64 db_id;
58 }; 58 };
59 bool trampolines_mapped;
59}; 60};
60 61
61static inline struct threads *machine__threads(struct machine *machine, pid_t tid) 62static inline struct threads *machine__threads(struct machine *machine, pid_t tid)
@@ -64,16 +65,22 @@ static inline struct threads *machine__threads(struct machine *machine, pid_t ti
64 return &machine->threads[(unsigned int)tid % THREADS__TABLE_SIZE]; 65 return &machine->threads[(unsigned int)tid % THREADS__TABLE_SIZE];
65} 66}
66 67
68/*
69 * The main kernel (vmlinux) map
70 */
67static inline 71static inline
68struct map *__machine__kernel_map(struct machine *machine, enum map_type type) 72struct map *machine__kernel_map(struct machine *machine)
69{ 73{
70 return machine->vmlinux_maps[type]; 74 return machine->vmlinux_map;
71} 75}
72 76
77/*
78 * kernel (the one returned by machine__kernel_map()) plus kernel modules maps
79 */
73static inline 80static inline
74struct map *machine__kernel_map(struct machine *machine) 81struct maps *machine__kernel_maps(struct machine *machine)
75{ 82{
76 return __machine__kernel_map(machine, MAP__FUNCTION); 83 return &machine->kmaps.maps;
77} 84}
78 85
79int machine__get_kernel_start(struct machine *machine); 86int machine__get_kernel_start(struct machine *machine);
@@ -182,6 +189,9 @@ static inline bool machine__is_host(struct machine *machine)
182 return machine ? machine->pid == HOST_KERNEL_ID : false; 189 return machine ? machine->pid == HOST_KERNEL_ID : false;
183} 190}
184 191
192bool machine__is(struct machine *machine, const char *arch);
193int machine__nr_cpus_avail(struct machine *machine);
194
185struct thread *__machine__findnew_thread(struct machine *machine, pid_t pid, pid_t tid); 195struct thread *__machine__findnew_thread(struct machine *machine, pid_t pid, pid_t tid);
186struct thread *machine__findnew_thread(struct machine *machine, pid_t pid, pid_t tid); 196struct thread *machine__findnew_thread(struct machine *machine, pid_t pid, pid_t tid);
187 197
@@ -190,44 +200,27 @@ struct dso *machine__findnew_dso(struct machine *machine, const char *filename);
190size_t machine__fprintf(struct machine *machine, FILE *fp); 200size_t machine__fprintf(struct machine *machine, FILE *fp);
191 201
192static inline 202static inline
193struct symbol *machine__find_kernel_symbol(struct machine *machine, 203struct symbol *machine__find_kernel_symbol(struct machine *machine, u64 addr,
194 enum map_type type, u64 addr,
195 struct map **mapp) 204 struct map **mapp)
196{ 205{
197 return map_groups__find_symbol(&machine->kmaps, type, addr, mapp); 206 return map_groups__find_symbol(&machine->kmaps, addr, mapp);
198} 207}
199 208
200static inline 209static inline
201struct symbol *machine__find_kernel_symbol_by_name(struct machine *machine, 210struct symbol *machine__find_kernel_symbol_by_name(struct machine *machine,
202 enum map_type type, const char *name, 211 const char *name,
203 struct map **mapp) 212 struct map **mapp)
204{ 213{
205 return map_groups__find_symbol_by_name(&machine->kmaps, type, name, mapp); 214 return map_groups__find_symbol_by_name(&machine->kmaps, name, mapp);
206}
207
208static inline
209struct symbol *machine__find_kernel_function(struct machine *machine, u64 addr,
210 struct map **mapp)
211{
212 return machine__find_kernel_symbol(machine, MAP__FUNCTION, addr,
213 mapp);
214}
215
216static inline
217struct symbol *machine__find_kernel_function_by_name(struct machine *machine,
218 const char *name,
219 struct map **mapp)
220{
221 return map_groups__find_function_by_name(&machine->kmaps, name, mapp);
222} 215}
223 216
224struct map *machine__findnew_module_map(struct machine *machine, u64 start, 217struct map *machine__findnew_module_map(struct machine *machine, u64 start,
225 const char *filename); 218 const char *filename);
226int arch__fix_module_text_start(u64 *start, const char *name); 219int arch__fix_module_text_start(u64 *start, const char *name);
227 220
228int machine__load_kallsyms(struct machine *machine, const char *filename, 221int machine__load_kallsyms(struct machine *machine, const char *filename);
229 enum map_type type); 222
230int machine__load_vmlinux_path(struct machine *machine, enum map_type type); 223int machine__load_vmlinux_path(struct machine *machine);
231 224
232size_t machine__fprintf_dsos_buildid(struct machine *machine, FILE *fp, 225size_t machine__fprintf_dsos_buildid(struct machine *machine, FILE *fp,
233 bool (skip)(struct dso *dso, int parm), int parm); 226 bool (skip)(struct dso *dso, int parm), int parm);
@@ -276,4 +269,25 @@ int machine__set_current_tid(struct machine *machine, int cpu, pid_t pid,
276 */ 269 */
277char *machine__resolve_kernel_addr(void *vmachine, unsigned long long *addrp, char **modp); 270char *machine__resolve_kernel_addr(void *vmachine, unsigned long long *addrp, char **modp);
278 271
272void machine__get_kallsyms_filename(struct machine *machine, char *buf,
273 size_t bufsz);
274
275int machine__create_extra_kernel_maps(struct machine *machine,
276 struct dso *kernel);
277
278/* Kernel-space maps for symbols that are outside the main kernel map and module maps */
279struct extra_kernel_map {
280 u64 start;
281 u64 end;
282 u64 pgoff;
283 char name[KMAP_NAME_LEN];
284};
285
286int machine__create_extra_kernel_map(struct machine *machine,
287 struct dso *kernel,
288 struct extra_kernel_map *xm);
289
290int machine__map_x86_64_entry_trampolines(struct machine *machine,
291 struct dso *kernel);
292
279#endif /* __PERF_MACHINE_H */ 293#endif /* __PERF_MACHINE_H */
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 8fe57031e1a8..6ae97eda370b 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -22,11 +22,6 @@
22 22
23static void __maps__insert(struct maps *maps, struct map *map); 23static void __maps__insert(struct maps *maps, struct map *map);
24 24
25const char *map_type__name[MAP__NR_TYPES] = {
26 [MAP__FUNCTION] = "Functions",
27 [MAP__VARIABLE] = "Variables",
28};
29
30static inline int is_anon_memory(const char *filename, u32 flags) 25static inline int is_anon_memory(const char *filename, u32 flags)
31{ 26{
32 return flags & MAP_HUGETLB || 27 return flags & MAP_HUGETLB ||
@@ -129,10 +124,8 @@ static inline bool replace_android_lib(const char *filename, char *newfilename)
129 return false; 124 return false;
130} 125}
131 126
132void map__init(struct map *map, enum map_type type, 127void map__init(struct map *map, u64 start, u64 end, u64 pgoff, struct dso *dso)
133 u64 start, u64 end, u64 pgoff, struct dso *dso)
134{ 128{
135 map->type = type;
136 map->start = start; 129 map->start = start;
137 map->end = end; 130 map->end = end;
138 map->pgoff = pgoff; 131 map->pgoff = pgoff;
@@ -149,7 +142,7 @@ void map__init(struct map *map, enum map_type type,
149struct map *map__new(struct machine *machine, u64 start, u64 len, 142struct map *map__new(struct machine *machine, u64 start, u64 len,
150 u64 pgoff, u32 d_maj, u32 d_min, u64 ino, 143 u64 pgoff, u32 d_maj, u32 d_min, u64 ino,
151 u64 ino_gen, u32 prot, u32 flags, char *filename, 144 u64 ino_gen, u32 prot, u32 flags, char *filename,
152 enum map_type type, struct thread *thread) 145 struct thread *thread)
153{ 146{
154 struct map *map = malloc(sizeof(*map)); 147 struct map *map = malloc(sizeof(*map));
155 struct nsinfo *nsi = NULL; 148 struct nsinfo *nsi = NULL;
@@ -173,7 +166,7 @@ struct map *map__new(struct machine *machine, u64 start, u64 len,
173 map->flags = flags; 166 map->flags = flags;
174 nsi = nsinfo__get(thread->nsinfo); 167 nsi = nsinfo__get(thread->nsinfo);
175 168
176 if ((anon || no_dso) && nsi && type == MAP__FUNCTION) { 169 if ((anon || no_dso) && nsi && (prot & PROT_EXEC)) {
177 snprintf(newfilename, sizeof(newfilename), 170 snprintf(newfilename, sizeof(newfilename),
178 "/tmp/perf-%d.map", nsi->pid); 171 "/tmp/perf-%d.map", nsi->pid);
179 filename = newfilename; 172 filename = newfilename;
@@ -203,7 +196,7 @@ struct map *map__new(struct machine *machine, u64 start, u64 len,
203 if (dso == NULL) 196 if (dso == NULL)
204 goto out_delete; 197 goto out_delete;
205 198
206 map__init(map, type, start, start + len, pgoff, dso); 199 map__init(map, start, start + len, pgoff, dso);
207 200
208 if (anon || no_dso) { 201 if (anon || no_dso) {
209 map->map_ip = map->unmap_ip = identity__map_ip; 202 map->map_ip = map->unmap_ip = identity__map_ip;
@@ -213,8 +206,8 @@ struct map *map__new(struct machine *machine, u64 start, u64 len,
213 * functions still return NULL, and we avoid the 206 * functions still return NULL, and we avoid the
214 * unnecessary map__load warning. 207 * unnecessary map__load warning.
215 */ 208 */
216 if (type != MAP__FUNCTION) 209 if (!(prot & PROT_EXEC))
217 dso__set_loaded(dso, map->type); 210 dso__set_loaded(dso);
218 } 211 }
219 dso->nsinfo = nsi; 212 dso->nsinfo = nsi;
220 dso__put(dso); 213 dso__put(dso);
@@ -231,7 +224,7 @@ out_delete:
231 * they are loaded) and for vmlinux, where only after we load all the 224 * they are loaded) and for vmlinux, where only after we load all the
232 * symbols we'll know where it starts and ends. 225 * symbols we'll know where it starts and ends.
233 */ 226 */
234struct map *map__new2(u64 start, struct dso *dso, enum map_type type) 227struct map *map__new2(u64 start, struct dso *dso)
235{ 228{
236 struct map *map = calloc(1, (sizeof(*map) + 229 struct map *map = calloc(1, (sizeof(*map) +
237 (dso->kernel ? sizeof(struct kmap) : 0))); 230 (dso->kernel ? sizeof(struct kmap) : 0)));
@@ -239,7 +232,7 @@ struct map *map__new2(u64 start, struct dso *dso, enum map_type type)
239 /* 232 /*
240 * ->end will be filled after we load all the symbols 233 * ->end will be filled after we load all the symbols
241 */ 234 */
242 map__init(map, type, start, 0, 0, dso); 235 map__init(map, start, 0, 0, dso);
243 } 236 }
244 237
245 return map; 238 return map;
@@ -256,7 +249,19 @@ struct map *map__new2(u64 start, struct dso *dso, enum map_type type)
256 */ 249 */
257bool __map__is_kernel(const struct map *map) 250bool __map__is_kernel(const struct map *map)
258{ 251{
259 return __machine__kernel_map(map->groups->machine, map->type) == map; 252 return machine__kernel_map(map->groups->machine) == map;
253}
254
255bool __map__is_extra_kernel_map(const struct map *map)
256{
257 struct kmap *kmap = __map__kmap((struct map *)map);
258
259 return kmap && kmap->name[0];
260}
261
262bool map__has_symbols(const struct map *map)
263{
264 return dso__has_symbols(map->dso);
260} 265}
261 266
262static void map__exit(struct map *map) 267static void map__exit(struct map *map)
@@ -279,7 +284,7 @@ void map__put(struct map *map)
279 284
280void map__fixup_start(struct map *map) 285void map__fixup_start(struct map *map)
281{ 286{
282 struct rb_root *symbols = &map->dso->symbols[map->type]; 287 struct rb_root *symbols = &map->dso->symbols;
283 struct rb_node *nd = rb_first(symbols); 288 struct rb_node *nd = rb_first(symbols);
284 if (nd != NULL) { 289 if (nd != NULL) {
285 struct symbol *sym = rb_entry(nd, struct symbol, rb_node); 290 struct symbol *sym = rb_entry(nd, struct symbol, rb_node);
@@ -289,7 +294,7 @@ void map__fixup_start(struct map *map)
289 294
290void map__fixup_end(struct map *map) 295void map__fixup_end(struct map *map)
291{ 296{
292 struct rb_root *symbols = &map->dso->symbols[map->type]; 297 struct rb_root *symbols = &map->dso->symbols;
293 struct rb_node *nd = rb_last(symbols); 298 struct rb_node *nd = rb_last(symbols);
294 if (nd != NULL) { 299 if (nd != NULL) {
295 struct symbol *sym = rb_entry(nd, struct symbol, rb_node); 300 struct symbol *sym = rb_entry(nd, struct symbol, rb_node);
@@ -304,7 +309,7 @@ int map__load(struct map *map)
304 const char *name = map->dso->long_name; 309 const char *name = map->dso->long_name;
305 int nr; 310 int nr;
306 311
307 if (dso__loaded(map->dso, map->type)) 312 if (dso__loaded(map->dso))
308 return 0; 313 return 0;
309 314
310 nr = dso__load(map->dso, map); 315 nr = dso__load(map->dso, map);
@@ -348,7 +353,7 @@ struct symbol *map__find_symbol(struct map *map, u64 addr)
348 if (map__load(map) < 0) 353 if (map__load(map) < 0)
349 return NULL; 354 return NULL;
350 355
351 return dso__find_symbol(map->dso, map->type, addr); 356 return dso__find_symbol(map->dso, addr);
352} 357}
353 358
354struct symbol *map__find_symbol_by_name(struct map *map, const char *name) 359struct symbol *map__find_symbol_by_name(struct map *map, const char *name)
@@ -356,10 +361,10 @@ struct symbol *map__find_symbol_by_name(struct map *map, const char *name)
356 if (map__load(map) < 0) 361 if (map__load(map) < 0)
357 return NULL; 362 return NULL;
358 363
359 if (!dso__sorted_by_name(map->dso, map->type)) 364 if (!dso__sorted_by_name(map->dso))
360 dso__sort_by_name(map->dso, map->type); 365 dso__sort_by_name(map->dso);
361 366
362 return dso__find_symbol_by_name(map->dso, map->type, name); 367 return dso__find_symbol_by_name(map->dso, name);
363} 368}
364 369
365struct map *map__clone(struct map *from) 370struct map *map__clone(struct map *from)
@@ -494,10 +499,7 @@ static void maps__init(struct maps *maps)
494 499
495void map_groups__init(struct map_groups *mg, struct machine *machine) 500void map_groups__init(struct map_groups *mg, struct machine *machine)
496{ 501{
497 int i; 502 maps__init(&mg->maps);
498 for (i = 0; i < MAP__NR_TYPES; ++i) {
499 maps__init(&mg->maps[i]);
500 }
501 mg->machine = machine; 503 mg->machine = machine;
502 refcount_set(&mg->refcnt, 1); 504 refcount_set(&mg->refcnt, 1);
503} 505}
@@ -525,22 +527,12 @@ static void maps__exit(struct maps *maps)
525 527
526void map_groups__exit(struct map_groups *mg) 528void map_groups__exit(struct map_groups *mg)
527{ 529{
528 int i; 530 maps__exit(&mg->maps);
529
530 for (i = 0; i < MAP__NR_TYPES; ++i)
531 maps__exit(&mg->maps[i]);
532} 531}
533 532
534bool map_groups__empty(struct map_groups *mg) 533bool map_groups__empty(struct map_groups *mg)
535{ 534{
536 int i; 535 return !maps__first(&mg->maps);
537
538 for (i = 0; i < MAP__NR_TYPES; ++i) {
539 if (maps__first(&mg->maps[i]))
540 return false;
541 }
542
543 return true;
544} 536}
545 537
546struct map_groups *map_groups__new(struct machine *machine) 538struct map_groups *map_groups__new(struct machine *machine)
@@ -566,10 +558,9 @@ void map_groups__put(struct map_groups *mg)
566} 558}
567 559
568struct symbol *map_groups__find_symbol(struct map_groups *mg, 560struct symbol *map_groups__find_symbol(struct map_groups *mg,
569 enum map_type type, u64 addr, 561 u64 addr, struct map **mapp)
570 struct map **mapp)
571{ 562{
572 struct map *map = map_groups__find(mg, type, addr); 563 struct map *map = map_groups__find(mg, addr);
573 564
574 /* Ensure map is loaded before using map->map_ip */ 565 /* Ensure map is loaded before using map->map_ip */
575 if (map != NULL && map__load(map) >= 0) { 566 if (map != NULL && map__load(map) >= 0) {
@@ -608,13 +599,10 @@ out:
608} 599}
609 600
610struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg, 601struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg,
611 enum map_type type,
612 const char *name, 602 const char *name,
613 struct map **mapp) 603 struct map **mapp)
614{ 604{
615 struct symbol *sym = maps__find_symbol_by_name(&mg->maps[type], name, mapp); 605 return maps__find_symbol_by_name(&mg->maps, name, mapp);
616
617 return sym;
618} 606}
619 607
620int map_groups__find_ams(struct addr_map_symbol *ams) 608int map_groups__find_ams(struct addr_map_symbol *ams)
@@ -622,8 +610,7 @@ int map_groups__find_ams(struct addr_map_symbol *ams)
622 if (ams->addr < ams->map->start || ams->addr >= ams->map->end) { 610 if (ams->addr < ams->map->start || ams->addr >= ams->map->end) {
623 if (ams->map->groups == NULL) 611 if (ams->map->groups == NULL)
624 return -1; 612 return -1;
625 ams->map = map_groups__find(ams->map->groups, ams->map->type, 613 ams->map = map_groups__find(ams->map->groups, ams->addr);
626 ams->addr);
627 if (ams->map == NULL) 614 if (ams->map == NULL)
628 return -1; 615 return -1;
629 } 616 }
@@ -646,7 +633,7 @@ static size_t maps__fprintf(struct maps *maps, FILE *fp)
646 printed += fprintf(fp, "Map:"); 633 printed += fprintf(fp, "Map:");
647 printed += map__fprintf(pos, fp); 634 printed += map__fprintf(pos, fp);
648 if (verbose > 2) { 635 if (verbose > 2) {
649 printed += dso__fprintf(pos->dso, pos->type, fp); 636 printed += dso__fprintf(pos->dso, fp);
650 printed += fprintf(fp, "--\n"); 637 printed += fprintf(fp, "--\n");
651 } 638 }
652 } 639 }
@@ -656,24 +643,14 @@ static size_t maps__fprintf(struct maps *maps, FILE *fp)
656 return printed; 643 return printed;
657} 644}
658 645
659size_t __map_groups__fprintf_maps(struct map_groups *mg, enum map_type type,
660 FILE *fp)
661{
662 size_t printed = fprintf(fp, "%s:\n", map_type__name[type]);
663 return printed += maps__fprintf(&mg->maps[type], fp);
664}
665
666size_t map_groups__fprintf(struct map_groups *mg, FILE *fp) 646size_t map_groups__fprintf(struct map_groups *mg, FILE *fp)
667{ 647{
668 size_t printed = 0, i; 648 return maps__fprintf(&mg->maps, fp);
669 for (i = 0; i < MAP__NR_TYPES; ++i)
670 printed += __map_groups__fprintf_maps(mg, i, fp);
671 return printed;
672} 649}
673 650
674static void __map_groups__insert(struct map_groups *mg, struct map *map) 651static void __map_groups__insert(struct map_groups *mg, struct map *map)
675{ 652{
676 __maps__insert(&mg->maps[map->type], map); 653 __maps__insert(&mg->maps, map);
677 map->groups = mg; 654 map->groups = mg;
678} 655}
679 656
@@ -758,19 +735,18 @@ out:
758int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map, 735int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map,
759 FILE *fp) 736 FILE *fp)
760{ 737{
761 return maps__fixup_overlappings(&mg->maps[map->type], map, fp); 738 return maps__fixup_overlappings(&mg->maps, map, fp);
762} 739}
763 740
764/* 741/*
765 * XXX This should not really _copy_ te maps, but refcount them. 742 * XXX This should not really _copy_ te maps, but refcount them.
766 */ 743 */
767int map_groups__clone(struct thread *thread, 744int map_groups__clone(struct thread *thread, struct map_groups *parent)
768 struct map_groups *parent, enum map_type type)
769{ 745{
770 struct map_groups *mg = thread->mg; 746 struct map_groups *mg = thread->mg;
771 int err = -ENOMEM; 747 int err = -ENOMEM;
772 struct map *map; 748 struct map *map;
773 struct maps *maps = &parent->maps[type]; 749 struct maps *maps = &parent->maps;
774 750
775 down_read(&maps->lock); 751 down_read(&maps->lock);
776 752
@@ -877,15 +853,22 @@ struct map *map__next(struct map *map)
877 return NULL; 853 return NULL;
878} 854}
879 855
880struct kmap *map__kmap(struct map *map) 856struct kmap *__map__kmap(struct map *map)
881{ 857{
882 if (!map->dso || !map->dso->kernel) { 858 if (!map->dso || !map->dso->kernel)
883 pr_err("Internal error: map__kmap with a non-kernel map\n");
884 return NULL; 859 return NULL;
885 }
886 return (struct kmap *)(map + 1); 860 return (struct kmap *)(map + 1);
887} 861}
888 862
863struct kmap *map__kmap(struct map *map)
864{
865 struct kmap *kmap = __map__kmap(map);
866
867 if (!kmap)
868 pr_err("Internal error: map__kmap with a non-kernel map\n");
869 return kmap;
870}
871
889struct map_groups *map__kmaps(struct map *map) 872struct map_groups *map__kmaps(struct map *map)
890{ 873{
891 struct kmap *kmap = map__kmap(map); 874 struct kmap *kmap = map__kmap(map);
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index 0e9bbe01b0ab..97e2a063bd65 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -8,19 +8,11 @@
8#include <linux/rbtree.h> 8#include <linux/rbtree.h>
9#include <pthread.h> 9#include <pthread.h>
10#include <stdio.h> 10#include <stdio.h>
11#include <string.h>
11#include <stdbool.h> 12#include <stdbool.h>
12#include <linux/types.h> 13#include <linux/types.h>
13#include "rwsem.h" 14#include "rwsem.h"
14 15
15enum map_type {
16 MAP__FUNCTION = 0,
17 MAP__VARIABLE,
18};
19
20#define MAP__NR_TYPES (MAP__VARIABLE + 1)
21
22extern const char *map_type__name[MAP__NR_TYPES];
23
24struct dso; 16struct dso;
25struct ip_callchain; 17struct ip_callchain;
26struct ref_reloc_sym; 18struct ref_reloc_sym;
@@ -35,7 +27,6 @@ struct map {
35 }; 27 };
36 u64 start; 28 u64 start;
37 u64 end; 29 u64 end;
38 u8 /* enum map_type */ type;
39 bool erange_warned; 30 bool erange_warned;
40 u32 priv; 31 u32 priv;
41 u32 prot; 32 u32 prot;
@@ -56,9 +47,12 @@ struct map {
56 refcount_t refcnt; 47 refcount_t refcnt;
57}; 48};
58 49
50#define KMAP_NAME_LEN 256
51
59struct kmap { 52struct kmap {
60 struct ref_reloc_sym *ref_reloc_sym; 53 struct ref_reloc_sym *ref_reloc_sym;
61 struct map_groups *kmaps; 54 struct map_groups *kmaps;
55 char name[KMAP_NAME_LEN];
62}; 56};
63 57
64struct maps { 58struct maps {
@@ -67,7 +61,7 @@ struct maps {
67}; 61};
68 62
69struct map_groups { 63struct map_groups {
70 struct maps maps[MAP__NR_TYPES]; 64 struct maps maps;
71 struct machine *machine; 65 struct machine *machine;
72 refcount_t refcnt; 66 refcount_t refcnt;
73}; 67};
@@ -85,6 +79,7 @@ static inline struct map_groups *map_groups__get(struct map_groups *mg)
85 79
86void map_groups__put(struct map_groups *mg); 80void map_groups__put(struct map_groups *mg);
87 81
82struct kmap *__map__kmap(struct map *map);
88struct kmap *map__kmap(struct map *map); 83struct kmap *map__kmap(struct map *map);
89struct map_groups *map__kmaps(struct map *map); 84struct map_groups *map__kmaps(struct map *map);
90 85
@@ -125,7 +120,7 @@ struct thread;
125 * Note: caller must ensure map->dso is not NULL (map is loaded). 120 * Note: caller must ensure map->dso is not NULL (map is loaded).
126 */ 121 */
127#define map__for_each_symbol(map, pos, n) \ 122#define map__for_each_symbol(map, pos, n) \
128 dso__for_each_symbol(map->dso, pos, n, map->type) 123 dso__for_each_symbol(map->dso, pos, n)
129 124
130/* map__for_each_symbol_with_name - iterate over the symbols in the given map 125/* map__for_each_symbol_with_name - iterate over the symbols in the given map
131 * that have the given name 126 * that have the given name
@@ -144,13 +139,13 @@ struct thread;
144#define map__for_each_symbol_by_name(map, sym_name, pos) \ 139#define map__for_each_symbol_by_name(map, sym_name, pos) \
145 __map__for_each_symbol_by_name(map, sym_name, (pos)) 140 __map__for_each_symbol_by_name(map, sym_name, (pos))
146 141
147void map__init(struct map *map, enum map_type type, 142void map__init(struct map *map,
148 u64 start, u64 end, u64 pgoff, struct dso *dso); 143 u64 start, u64 end, u64 pgoff, struct dso *dso);
149struct map *map__new(struct machine *machine, u64 start, u64 len, 144struct map *map__new(struct machine *machine, u64 start, u64 len,
150 u64 pgoff, u32 d_maj, u32 d_min, u64 ino, 145 u64 pgoff, u32 d_maj, u32 d_min, u64 ino,
151 u64 ino_gen, u32 prot, u32 flags, 146 u64 ino_gen, u32 prot, u32 flags,
152 char *filename, enum map_type type, struct thread *thread); 147 char *filename, struct thread *thread);
153struct map *map__new2(u64 start, struct dso *dso, enum map_type type); 148struct map *map__new2(u64 start, struct dso *dso);
154void map__delete(struct map *map); 149void map__delete(struct map *map);
155struct map *map__clone(struct map *map); 150struct map *map__clone(struct map *map);
156 151
@@ -185,8 +180,6 @@ void map__fixup_end(struct map *map);
185 180
186void map__reloc_vmlinux(struct map *map); 181void map__reloc_vmlinux(struct map *map);
187 182
188size_t __map_groups__fprintf_maps(struct map_groups *mg, enum map_type type,
189 FILE *fp);
190void maps__insert(struct maps *maps, struct map *map); 183void maps__insert(struct maps *maps, struct map *map);
191void maps__remove(struct maps *maps, struct map *map); 184void maps__remove(struct maps *maps, struct map *map);
192struct map *maps__find(struct maps *maps, u64 addr); 185struct map *maps__find(struct maps *maps, u64 addr);
@@ -197,34 +190,29 @@ struct symbol *maps__find_symbol_by_name(struct maps *maps, const char *name,
197void map_groups__init(struct map_groups *mg, struct machine *machine); 190void map_groups__init(struct map_groups *mg, struct machine *machine);
198void map_groups__exit(struct map_groups *mg); 191void map_groups__exit(struct map_groups *mg);
199int map_groups__clone(struct thread *thread, 192int map_groups__clone(struct thread *thread,
200 struct map_groups *parent, enum map_type type); 193 struct map_groups *parent);
201size_t map_groups__fprintf(struct map_groups *mg, FILE *fp); 194size_t map_groups__fprintf(struct map_groups *mg, FILE *fp);
202 195
203int maps__set_kallsyms_ref_reloc_sym(struct map **maps, const char *symbol_name, 196int map__set_kallsyms_ref_reloc_sym(struct map *map, const char *symbol_name,
204 u64 addr); 197 u64 addr);
205 198
206static inline void map_groups__insert(struct map_groups *mg, struct map *map) 199static inline void map_groups__insert(struct map_groups *mg, struct map *map)
207{ 200{
208 maps__insert(&mg->maps[map->type], map); 201 maps__insert(&mg->maps, map);
209 map->groups = mg; 202 map->groups = mg;
210} 203}
211 204
212static inline void map_groups__remove(struct map_groups *mg, struct map *map) 205static inline void map_groups__remove(struct map_groups *mg, struct map *map)
213{ 206{
214 maps__remove(&mg->maps[map->type], map); 207 maps__remove(&mg->maps, map);
215} 208}
216 209
217static inline struct map *map_groups__find(struct map_groups *mg, 210static inline struct map *map_groups__find(struct map_groups *mg, u64 addr)
218 enum map_type type, u64 addr)
219{ 211{
220 return maps__find(&mg->maps[type], addr); 212 return maps__find(&mg->maps, addr);
221} 213}
222 214
223static inline struct map *map_groups__first(struct map_groups *mg, 215struct map *map_groups__first(struct map_groups *mg);
224 enum map_type type)
225{
226 return maps__first(&mg->maps[type]);
227}
228 216
229static inline struct map *map_groups__next(struct map *map) 217static inline struct map *map_groups__next(struct map *map)
230{ 218{
@@ -232,11 +220,9 @@ static inline struct map *map_groups__next(struct map *map)
232} 220}
233 221
234struct symbol *map_groups__find_symbol(struct map_groups *mg, 222struct symbol *map_groups__find_symbol(struct map_groups *mg,
235 enum map_type type, u64 addr, 223 u64 addr, struct map **mapp);
236 struct map **mapp);
237 224
238struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg, 225struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg,
239 enum map_type type,
240 const char *name, 226 const char *name,
241 struct map **mapp); 227 struct map **mapp);
242 228
@@ -244,24 +230,26 @@ struct addr_map_symbol;
244 230
245int map_groups__find_ams(struct addr_map_symbol *ams); 231int map_groups__find_ams(struct addr_map_symbol *ams);
246 232
247static inline
248struct symbol *map_groups__find_function_by_name(struct map_groups *mg,
249 const char *name, struct map **mapp)
250{
251 return map_groups__find_symbol_by_name(mg, MAP__FUNCTION, name, mapp);
252}
253
254int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map, 233int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map,
255 FILE *fp); 234 FILE *fp);
256 235
257struct map *map_groups__find_by_name(struct map_groups *mg, 236struct map *map_groups__find_by_name(struct map_groups *mg, const char *name);
258 enum map_type type, const char *name);
259 237
260bool __map__is_kernel(const struct map *map); 238bool __map__is_kernel(const struct map *map);
239bool __map__is_extra_kernel_map(const struct map *map);
261 240
262static inline bool __map__is_kmodule(const struct map *map) 241static inline bool __map__is_kmodule(const struct map *map)
263{ 242{
264 return !__map__is_kernel(map); 243 return !__map__is_kernel(map) && !__map__is_extra_kernel_map(map);
244}
245
246bool map__has_symbols(const struct map *map);
247
248#define ENTRY_TRAMPOLINE_NAME "__entry_SYSCALL_64_trampoline"
249
250static inline bool is_entry_trampoline(const char *name)
251{
252 return !strcmp(name, ENTRY_TRAMPOLINE_NAME);
265} 253}
266 254
267#endif /* __PERF_MAP_H */ 255#endif /* __PERF_MAP_H */
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 2fb0272146d8..15eec49e71a1 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -156,13 +156,12 @@ struct event_symbol event_symbols_sw[PERF_COUNT_SW_MAX] = {
156 (strcmp(sys_dirent->d_name, ".")) && \ 156 (strcmp(sys_dirent->d_name, ".")) && \
157 (strcmp(sys_dirent->d_name, ".."))) 157 (strcmp(sys_dirent->d_name, "..")))
158 158
159static int tp_event_has_id(struct dirent *sys_dir, struct dirent *evt_dir) 159static int tp_event_has_id(const char *dir_path, struct dirent *evt_dir)
160{ 160{
161 char evt_path[MAXPATHLEN]; 161 char evt_path[MAXPATHLEN];
162 int fd; 162 int fd;
163 163
164 snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", tracing_events_path, 164 snprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path, evt_dir->d_name);
165 sys_dir->d_name, evt_dir->d_name);
166 fd = open(evt_path, O_RDONLY); 165 fd = open(evt_path, O_RDONLY);
167 if (fd < 0) 166 if (fd < 0)
168 return -EINVAL; 167 return -EINVAL;
@@ -171,12 +170,12 @@ static int tp_event_has_id(struct dirent *sys_dir, struct dirent *evt_dir)
171 return 0; 170 return 0;
172} 171}
173 172
174#define for_each_event(sys_dirent, evt_dir, evt_dirent) \ 173#define for_each_event(dir_path, evt_dir, evt_dirent) \
175 while ((evt_dirent = readdir(evt_dir)) != NULL) \ 174 while ((evt_dirent = readdir(evt_dir)) != NULL) \
176 if (evt_dirent->d_type == DT_DIR && \ 175 if (evt_dirent->d_type == DT_DIR && \
177 (strcmp(evt_dirent->d_name, ".")) && \ 176 (strcmp(evt_dirent->d_name, ".")) && \
178 (strcmp(evt_dirent->d_name, "..")) && \ 177 (strcmp(evt_dirent->d_name, "..")) && \
179 (!tp_event_has_id(sys_dirent, evt_dirent))) 178 (!tp_event_has_id(dir_path, evt_dirent)))
180 179
181#define MAX_EVENT_LENGTH 512 180#define MAX_EVENT_LENGTH 512
182 181
@@ -190,21 +189,21 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config)
190 int fd; 189 int fd;
191 u64 id; 190 u64 id;
192 char evt_path[MAXPATHLEN]; 191 char evt_path[MAXPATHLEN];
193 char dir_path[MAXPATHLEN]; 192 char *dir_path;
194 193
195 sys_dir = opendir(tracing_events_path); 194 sys_dir = tracing_events__opendir();
196 if (!sys_dir) 195 if (!sys_dir)
197 return NULL; 196 return NULL;
198 197
199 for_each_subsystem(sys_dir, sys_dirent) { 198 for_each_subsystem(sys_dir, sys_dirent) {
200 199 dir_path = get_events_file(sys_dirent->d_name);
201 snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path, 200 if (!dir_path)
202 sys_dirent->d_name); 201 continue;
203 evt_dir = opendir(dir_path); 202 evt_dir = opendir(dir_path);
204 if (!evt_dir) 203 if (!evt_dir)
205 continue; 204 goto next;
206 205
207 for_each_event(sys_dirent, evt_dir, evt_dirent) { 206 for_each_event(dir_path, evt_dir, evt_dirent) {
208 207
209 scnprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path, 208 scnprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path,
210 evt_dirent->d_name); 209 evt_dirent->d_name);
@@ -218,6 +217,7 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config)
218 close(fd); 217 close(fd);
219 id = atoll(id_buf); 218 id = atoll(id_buf);
220 if (id == config) { 219 if (id == config) {
220 put_events_file(dir_path);
221 closedir(evt_dir); 221 closedir(evt_dir);
222 closedir(sys_dir); 222 closedir(sys_dir);
223 path = zalloc(sizeof(*path)); 223 path = zalloc(sizeof(*path));
@@ -242,6 +242,8 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config)
242 } 242 }
243 } 243 }
244 closedir(evt_dir); 244 closedir(evt_dir);
245next:
246 put_events_file(dir_path);
245 } 247 }
246 248
247 closedir(sys_dir); 249 closedir(sys_dir);
@@ -512,14 +514,19 @@ static int add_tracepoint_multi_event(struct list_head *list, int *idx,
512 struct parse_events_error *err, 514 struct parse_events_error *err,
513 struct list_head *head_config) 515 struct list_head *head_config)
514{ 516{
515 char evt_path[MAXPATHLEN]; 517 char *evt_path;
516 struct dirent *evt_ent; 518 struct dirent *evt_ent;
517 DIR *evt_dir; 519 DIR *evt_dir;
518 int ret = 0, found = 0; 520 int ret = 0, found = 0;
519 521
520 snprintf(evt_path, MAXPATHLEN, "%s/%s", tracing_events_path, sys_name); 522 evt_path = get_events_file(sys_name);
523 if (!evt_path) {
524 tracepoint_error(err, errno, sys_name, evt_name);
525 return -1;
526 }
521 evt_dir = opendir(evt_path); 527 evt_dir = opendir(evt_path);
522 if (!evt_dir) { 528 if (!evt_dir) {
529 put_events_file(evt_path);
523 tracepoint_error(err, errno, sys_name, evt_name); 530 tracepoint_error(err, errno, sys_name, evt_name);
524 return -1; 531 return -1;
525 } 532 }
@@ -545,6 +552,7 @@ static int add_tracepoint_multi_event(struct list_head *list, int *idx,
545 ret = -1; 552 ret = -1;
546 } 553 }
547 554
555 put_events_file(evt_path);
548 closedir(evt_dir); 556 closedir(evt_dir);
549 return ret; 557 return ret;
550} 558}
@@ -570,7 +578,7 @@ static int add_tracepoint_multi_sys(struct list_head *list, int *idx,
570 DIR *events_dir; 578 DIR *events_dir;
571 int ret = 0; 579 int ret = 0;
572 580
573 events_dir = opendir(tracing_events_path); 581 events_dir = tracing_events__opendir();
574 if (!events_dir) { 582 if (!events_dir) {
575 tracepoint_error(err, errno, sys_name, evt_name); 583 tracepoint_error(err, errno, sys_name, evt_name);
576 return -1; 584 return -1;
@@ -1219,13 +1227,16 @@ int parse_events_add_numeric(struct parse_events_state *parse_state,
1219 1227
1220int parse_events_add_pmu(struct parse_events_state *parse_state, 1228int parse_events_add_pmu(struct parse_events_state *parse_state,
1221 struct list_head *list, char *name, 1229 struct list_head *list, char *name,
1222 struct list_head *head_config, bool auto_merge_stats) 1230 struct list_head *head_config,
1231 bool auto_merge_stats,
1232 bool use_alias)
1223{ 1233{
1224 struct perf_event_attr attr; 1234 struct perf_event_attr attr;
1225 struct perf_pmu_info info; 1235 struct perf_pmu_info info;
1226 struct perf_pmu *pmu; 1236 struct perf_pmu *pmu;
1227 struct perf_evsel *evsel; 1237 struct perf_evsel *evsel;
1228 struct parse_events_error *err = parse_state->error; 1238 struct parse_events_error *err = parse_state->error;
1239 bool use_uncore_alias;
1229 LIST_HEAD(config_terms); 1240 LIST_HEAD(config_terms);
1230 1241
1231 pmu = perf_pmu__find(name); 1242 pmu = perf_pmu__find(name);
@@ -1244,11 +1255,14 @@ int parse_events_add_pmu(struct parse_events_state *parse_state,
1244 memset(&attr, 0, sizeof(attr)); 1255 memset(&attr, 0, sizeof(attr));
1245 } 1256 }
1246 1257
1258 use_uncore_alias = (pmu->is_uncore && use_alias);
1259
1247 if (!head_config) { 1260 if (!head_config) {
1248 attr.type = pmu->type; 1261 attr.type = pmu->type;
1249 evsel = __add_event(list, &parse_state->idx, &attr, NULL, pmu, NULL, auto_merge_stats); 1262 evsel = __add_event(list, &parse_state->idx, &attr, NULL, pmu, NULL, auto_merge_stats);
1250 if (evsel) { 1263 if (evsel) {
1251 evsel->pmu_name = name; 1264 evsel->pmu_name = name;
1265 evsel->use_uncore_alias = use_uncore_alias;
1252 return 0; 1266 return 0;
1253 } else { 1267 } else {
1254 return -ENOMEM; 1268 return -ENOMEM;
@@ -1282,6 +1296,7 @@ int parse_events_add_pmu(struct parse_events_state *parse_state,
1282 evsel->metric_expr = info.metric_expr; 1296 evsel->metric_expr = info.metric_expr;
1283 evsel->metric_name = info.metric_name; 1297 evsel->metric_name = info.metric_name;
1284 evsel->pmu_name = name; 1298 evsel->pmu_name = name;
1299 evsel->use_uncore_alias = use_uncore_alias;
1285 } 1300 }
1286 1301
1287 return evsel ? 0 : -ENOMEM; 1302 return evsel ? 0 : -ENOMEM;
@@ -1317,7 +1332,8 @@ int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
1317 list_add_tail(&term->list, head); 1332 list_add_tail(&term->list, head);
1318 1333
1319 if (!parse_events_add_pmu(parse_state, list, 1334 if (!parse_events_add_pmu(parse_state, list,
1320 pmu->name, head, true)) { 1335 pmu->name, head,
1336 true, true)) {
1321 pr_debug("%s -> %s/%s/\n", str, 1337 pr_debug("%s -> %s/%s/\n", str,
1322 pmu->name, alias->str); 1338 pmu->name, alias->str);
1323 ok++; 1339 ok++;
@@ -1339,7 +1355,120 @@ int parse_events__modifier_group(struct list_head *list,
1339 return parse_events__modifier_event(list, event_mod, true); 1355 return parse_events__modifier_event(list, event_mod, true);
1340} 1356}
1341 1357
1342void parse_events__set_leader(char *name, struct list_head *list) 1358/*
1359 * Check if the two uncore PMUs are from the same uncore block
1360 * The format of the uncore PMU name is uncore_#blockname_#pmuidx
1361 */
1362static bool is_same_uncore_block(const char *pmu_name_a, const char *pmu_name_b)
1363{
1364 char *end_a, *end_b;
1365
1366 end_a = strrchr(pmu_name_a, '_');
1367 end_b = strrchr(pmu_name_b, '_');
1368
1369 if (!end_a || !end_b)
1370 return false;
1371
1372 if ((end_a - pmu_name_a) != (end_b - pmu_name_b))
1373 return false;
1374
1375 return (strncmp(pmu_name_a, pmu_name_b, end_a - pmu_name_a) == 0);
1376}
1377
1378static int
1379parse_events__set_leader_for_uncore_aliase(char *name, struct list_head *list,
1380 struct parse_events_state *parse_state)
1381{
1382 struct perf_evsel *evsel, *leader;
1383 uintptr_t *leaders;
1384 bool is_leader = true;
1385 int i, nr_pmu = 0, total_members, ret = 0;
1386
1387 leader = list_first_entry(list, struct perf_evsel, node);
1388 evsel = list_last_entry(list, struct perf_evsel, node);
1389 total_members = evsel->idx - leader->idx + 1;
1390
1391 leaders = calloc(total_members, sizeof(uintptr_t));
1392 if (WARN_ON(!leaders))
1393 return 0;
1394
1395 /*
1396 * Going through the whole group and doing sanity check.
1397 * All members must use alias, and be from the same uncore block.
1398 * Also, storing the leader events in an array.
1399 */
1400 __evlist__for_each_entry(list, evsel) {
1401
1402 /* Only split the uncore group which members use alias */
1403 if (!evsel->use_uncore_alias)
1404 goto out;
1405
1406 /* The events must be from the same uncore block */
1407 if (!is_same_uncore_block(leader->pmu_name, evsel->pmu_name))
1408 goto out;
1409
1410 if (!is_leader)
1411 continue;
1412 /*
1413 * If the event's PMU name starts to repeat, it must be a new
1414 * event. That can be used to distinguish the leader from
1415 * other members, even they have the same event name.
1416 */
1417 if ((leader != evsel) && (leader->pmu_name == evsel->pmu_name)) {
1418 is_leader = false;
1419 continue;
1420 }
1421 /* The name is always alias name */
1422 WARN_ON(strcmp(leader->name, evsel->name));
1423
1424 /* Store the leader event for each PMU */
1425 leaders[nr_pmu++] = (uintptr_t) evsel;
1426 }
1427
1428 /* only one event alias */
1429 if (nr_pmu == total_members) {
1430 parse_state->nr_groups--;
1431 goto handled;
1432 }
1433
1434 /*
1435 * An uncore event alias is a joint name which means the same event
1436 * runs on all PMUs of a block.
1437 * Perf doesn't support mixed events from different PMUs in the same
1438 * group. The big group has to be split into multiple small groups
1439 * which only include the events from the same PMU.
1440 *
1441 * Here the uncore event aliases must be from the same uncore block.
1442 * The number of PMUs must be same for each alias. The number of new
1443 * small groups equals to the number of PMUs.
1444 * Setting the leader event for corresponding members in each group.
1445 */
1446 i = 0;
1447 __evlist__for_each_entry(list, evsel) {
1448 if (i >= nr_pmu)
1449 i = 0;
1450 evsel->leader = (struct perf_evsel *) leaders[i++];
1451 }
1452
1453 /* The number of members and group name are same for each group */
1454 for (i = 0; i < nr_pmu; i++) {
1455 evsel = (struct perf_evsel *) leaders[i];
1456 evsel->nr_members = total_members / nr_pmu;
1457 evsel->group_name = name ? strdup(name) : NULL;
1458 }
1459
1460 /* Take the new small groups into account */
1461 parse_state->nr_groups += nr_pmu - 1;
1462
1463handled:
1464 ret = 1;
1465out:
1466 free(leaders);
1467 return ret;
1468}
1469
1470void parse_events__set_leader(char *name, struct list_head *list,
1471 struct parse_events_state *parse_state)
1343{ 1472{
1344 struct perf_evsel *leader; 1473 struct perf_evsel *leader;
1345 1474
@@ -1348,6 +1477,9 @@ void parse_events__set_leader(char *name, struct list_head *list)
1348 return; 1477 return;
1349 } 1478 }
1350 1479
1480 if (parse_events__set_leader_for_uncore_aliase(name, list, parse_state))
1481 return;
1482
1351 __perf_evlist__set_leader(list); 1483 __perf_evlist__set_leader(list);
1352 leader = list_entry(list->next, struct perf_evsel, node); 1484 leader = list_entry(list->next, struct perf_evsel, node);
1353 leader->group_name = name ? strdup(name) : NULL; 1485 leader->group_name = name ? strdup(name) : NULL;
@@ -1715,7 +1847,7 @@ int parse_events(struct perf_evlist *evlist, const char *str,
1715 struct perf_evsel *last; 1847 struct perf_evsel *last;
1716 1848
1717 if (list_empty(&parse_state.list)) { 1849 if (list_empty(&parse_state.list)) {
1718 WARN_ONCE(true, "WARNING: event parser found nothing"); 1850 WARN_ONCE(true, "WARNING: event parser found nothing\n");
1719 return -1; 1851 return -1;
1720 } 1852 }
1721 1853
@@ -1968,13 +2100,13 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
1968 DIR *sys_dir, *evt_dir; 2100 DIR *sys_dir, *evt_dir;
1969 struct dirent *sys_dirent, *evt_dirent; 2101 struct dirent *sys_dirent, *evt_dirent;
1970 char evt_path[MAXPATHLEN]; 2102 char evt_path[MAXPATHLEN];
1971 char dir_path[MAXPATHLEN]; 2103 char *dir_path;
1972 char **evt_list = NULL; 2104 char **evt_list = NULL;
1973 unsigned int evt_i = 0, evt_num = 0; 2105 unsigned int evt_i = 0, evt_num = 0;
1974 bool evt_num_known = false; 2106 bool evt_num_known = false;
1975 2107
1976restart: 2108restart:
1977 sys_dir = opendir(tracing_events_path); 2109 sys_dir = tracing_events__opendir();
1978 if (!sys_dir) 2110 if (!sys_dir)
1979 return; 2111 return;
1980 2112
@@ -1989,13 +2121,14 @@ restart:
1989 !strglobmatch(sys_dirent->d_name, subsys_glob)) 2121 !strglobmatch(sys_dirent->d_name, subsys_glob))
1990 continue; 2122 continue;
1991 2123
1992 snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path, 2124 dir_path = get_events_file(sys_dirent->d_name);
1993 sys_dirent->d_name); 2125 if (!dir_path)
2126 continue;
1994 evt_dir = opendir(dir_path); 2127 evt_dir = opendir(dir_path);
1995 if (!evt_dir) 2128 if (!evt_dir)
1996 continue; 2129 goto next;
1997 2130
1998 for_each_event(sys_dirent, evt_dir, evt_dirent) { 2131 for_each_event(dir_path, evt_dir, evt_dirent) {
1999 if (event_glob != NULL && 2132 if (event_glob != NULL &&
2000 !strglobmatch(evt_dirent->d_name, event_glob)) 2133 !strglobmatch(evt_dirent->d_name, event_glob))
2001 continue; 2134 continue;
@@ -2009,11 +2142,15 @@ restart:
2009 sys_dirent->d_name, evt_dirent->d_name); 2142 sys_dirent->d_name, evt_dirent->d_name);
2010 2143
2011 evt_list[evt_i] = strdup(evt_path); 2144 evt_list[evt_i] = strdup(evt_path);
2012 if (evt_list[evt_i] == NULL) 2145 if (evt_list[evt_i] == NULL) {
2146 put_events_file(dir_path);
2013 goto out_close_evt_dir; 2147 goto out_close_evt_dir;
2148 }
2014 evt_i++; 2149 evt_i++;
2015 } 2150 }
2016 closedir(evt_dir); 2151 closedir(evt_dir);
2152next:
2153 put_events_file(dir_path);
2017 } 2154 }
2018 closedir(sys_dir); 2155 closedir(sys_dir);
2019 2156
@@ -2061,21 +2198,21 @@ int is_valid_tracepoint(const char *event_string)
2061 DIR *sys_dir, *evt_dir; 2198 DIR *sys_dir, *evt_dir;
2062 struct dirent *sys_dirent, *evt_dirent; 2199 struct dirent *sys_dirent, *evt_dirent;
2063 char evt_path[MAXPATHLEN]; 2200 char evt_path[MAXPATHLEN];
2064 char dir_path[MAXPATHLEN]; 2201 char *dir_path;
2065 2202
2066 sys_dir = opendir(tracing_events_path); 2203 sys_dir = tracing_events__opendir();
2067 if (!sys_dir) 2204 if (!sys_dir)
2068 return 0; 2205 return 0;
2069 2206
2070 for_each_subsystem(sys_dir, sys_dirent) { 2207 for_each_subsystem(sys_dir, sys_dirent) {
2071 2208 dir_path = get_events_file(sys_dirent->d_name);
2072 snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path, 2209 if (!dir_path)
2073 sys_dirent->d_name); 2210 continue;
2074 evt_dir = opendir(dir_path); 2211 evt_dir = opendir(dir_path);
2075 if (!evt_dir) 2212 if (!evt_dir)
2076 continue; 2213 goto next;
2077 2214
2078 for_each_event(sys_dirent, evt_dir, evt_dirent) { 2215 for_each_event(dir_path, evt_dir, evt_dirent) {
2079 snprintf(evt_path, MAXPATHLEN, "%s:%s", 2216 snprintf(evt_path, MAXPATHLEN, "%s:%s",
2080 sys_dirent->d_name, evt_dirent->d_name); 2217 sys_dirent->d_name, evt_dirent->d_name);
2081 if (!strcmp(evt_path, event_string)) { 2218 if (!strcmp(evt_path, event_string)) {
@@ -2085,6 +2222,8 @@ int is_valid_tracepoint(const char *event_string)
2085 } 2222 }
2086 } 2223 }
2087 closedir(evt_dir); 2224 closedir(evt_dir);
2225next:
2226 put_events_file(dir_path);
2088 } 2227 }
2089 closedir(sys_dir); 2228 closedir(sys_dir);
2090 return 0; 2229 return 0;
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index 5015cfd58277..4473dac27aee 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -167,7 +167,9 @@ int parse_events_add_breakpoint(struct list_head *list, int *idx,
167 void *ptr, char *type, u64 len); 167 void *ptr, char *type, u64 len);
168int parse_events_add_pmu(struct parse_events_state *parse_state, 168int parse_events_add_pmu(struct parse_events_state *parse_state,
169 struct list_head *list, char *name, 169 struct list_head *list, char *name,
170 struct list_head *head_config, bool auto_merge_stats); 170 struct list_head *head_config,
171 bool auto_merge_stats,
172 bool use_alias);
171 173
172int parse_events_multi_pmu_add(struct parse_events_state *parse_state, 174int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
173 char *str, 175 char *str,
@@ -178,7 +180,8 @@ int parse_events_copy_term_list(struct list_head *old,
178 180
179enum perf_pmu_event_symbol_type 181enum perf_pmu_event_symbol_type
180perf_pmu__parse_check(const char *name); 182perf_pmu__parse_check(const char *name);
181void parse_events__set_leader(char *name, struct list_head *list); 183void parse_events__set_leader(char *name, struct list_head *list,
184 struct parse_events_state *parse_state);
182void parse_events_update_lists(struct list_head *list_event, 185void parse_events_update_lists(struct list_head *list_event,
183 struct list_head *list_all); 186 struct list_head *list_all);
184void parse_events_evlist_error(struct parse_events_state *parse_state, 187void parse_events_evlist_error(struct parse_events_state *parse_state,
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 7afeb80cc39e..e37608a87dba 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -161,7 +161,7 @@ PE_NAME '{' events '}'
161 struct list_head *list = $3; 161 struct list_head *list = $3;
162 162
163 inc_group_count(list, _parse_state); 163 inc_group_count(list, _parse_state);
164 parse_events__set_leader($1, list); 164 parse_events__set_leader($1, list, _parse_state);
165 $$ = list; 165 $$ = list;
166} 166}
167| 167|
@@ -170,7 +170,7 @@ PE_NAME '{' events '}'
170 struct list_head *list = $2; 170 struct list_head *list = $2;
171 171
172 inc_group_count(list, _parse_state); 172 inc_group_count(list, _parse_state);
173 parse_events__set_leader(NULL, list); 173 parse_events__set_leader(NULL, list, _parse_state);
174 $$ = list; 174 $$ = list;
175} 175}
176 176
@@ -232,7 +232,7 @@ PE_NAME opt_event_config
232 YYABORT; 232 YYABORT;
233 233
234 ALLOC_LIST(list); 234 ALLOC_LIST(list);
235 if (parse_events_add_pmu(_parse_state, list, $1, $2, false)) { 235 if (parse_events_add_pmu(_parse_state, list, $1, $2, false, false)) {
236 struct perf_pmu *pmu = NULL; 236 struct perf_pmu *pmu = NULL;
237 int ok = 0; 237 int ok = 0;
238 char *pattern; 238 char *pattern;
@@ -251,7 +251,7 @@ PE_NAME opt_event_config
251 free(pattern); 251 free(pattern);
252 YYABORT; 252 YYABORT;
253 } 253 }
254 if (!parse_events_add_pmu(_parse_state, list, pmu->name, terms, true)) 254 if (!parse_events_add_pmu(_parse_state, list, pmu->name, terms, true, false))
255 ok++; 255 ok++;
256 parse_events_terms__delete(terms); 256 parse_events_terms__delete(terms);
257 } 257 }
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 61a5e5027338..d2fb597c9a8c 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -539,9 +539,10 @@ static bool pmu_is_uncore(const char *name)
539 539
540/* 540/*
541 * PMU CORE devices have different name other than cpu in sysfs on some 541 * PMU CORE devices have different name other than cpu in sysfs on some
542 * platforms. looking for possible sysfs files to identify as core device. 542 * platforms.
543 * Looking for possible sysfs files to identify the arm core device.
543 */ 544 */
544static int is_pmu_core(const char *name) 545static int is_arm_pmu_core(const char *name)
545{ 546{
546 struct stat st; 547 struct stat st;
547 char path[PATH_MAX]; 548 char path[PATH_MAX];
@@ -550,12 +551,6 @@ static int is_pmu_core(const char *name)
550 if (!sysfs) 551 if (!sysfs)
551 return 0; 552 return 0;
552 553
553 /* Look for cpu sysfs (x86 and others) */
554 scnprintf(path, PATH_MAX, "%s/bus/event_source/devices/cpu", sysfs);
555 if ((stat(path, &st) == 0) &&
556 (strncmp(name, "cpu", strlen("cpu")) == 0))
557 return 1;
558
559 /* Look for cpu sysfs (specific to arm) */ 554 /* Look for cpu sysfs (specific to arm) */
560 scnprintf(path, PATH_MAX, "%s/bus/event_source/devices/%s/cpus", 555 scnprintf(path, PATH_MAX, "%s/bus/event_source/devices/%s/cpus",
561 sysfs, name); 556 sysfs, name);
@@ -586,7 +581,7 @@ char * __weak get_cpuid_str(struct perf_pmu *pmu __maybe_unused)
586 * cpuid string generated on this platform. 581 * cpuid string generated on this platform.
587 * Otherwise return non-zero. 582 * Otherwise return non-zero.
588 */ 583 */
589int __weak strcmp_cpuid_str(const char *mapcpuid, const char *cpuid) 584int strcmp_cpuid_str(const char *mapcpuid, const char *cpuid)
590{ 585{
591 regex_t re; 586 regex_t re;
592 regmatch_t pmatch[1]; 587 regmatch_t pmatch[1];
@@ -668,6 +663,7 @@ static void pmu_add_cpu_aliases(struct list_head *head, struct perf_pmu *pmu)
668 struct pmu_events_map *map; 663 struct pmu_events_map *map;
669 struct pmu_event *pe; 664 struct pmu_event *pe;
670 const char *name = pmu->name; 665 const char *name = pmu->name;
666 const char *pname;
671 667
672 map = perf_pmu__find_map(pmu); 668 map = perf_pmu__find_map(pmu);
673 if (!map) 669 if (!map)
@@ -686,11 +682,9 @@ static void pmu_add_cpu_aliases(struct list_head *head, struct perf_pmu *pmu)
686 break; 682 break;
687 } 683 }
688 684
689 if (!is_pmu_core(name)) { 685 if (!is_arm_pmu_core(name)) {
690 /* check for uncore devices */ 686 pname = pe->pmu ? pe->pmu : "cpu";
691 if (pe->pmu == NULL) 687 if (strncmp(pname, name, strlen(pname)))
692 continue;
693 if (strncmp(pe->pmu, name, strlen(pe->pmu)))
694 continue; 688 continue;
695 } 689 }
696 690
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index e1dbc9821617..3094f11e7d81 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -111,17 +111,6 @@ void exit_probe_symbol_maps(void)
111 symbol__exit(); 111 symbol__exit();
112} 112}
113 113
114static struct symbol *__find_kernel_function_by_name(const char *name,
115 struct map **mapp)
116{
117 return machine__find_kernel_function_by_name(host_machine, name, mapp);
118}
119
120static struct symbol *__find_kernel_function(u64 addr, struct map **mapp)
121{
122 return machine__find_kernel_function(host_machine, addr, mapp);
123}
124
125static struct ref_reloc_sym *kernel_get_ref_reloc_sym(void) 114static struct ref_reloc_sym *kernel_get_ref_reloc_sym(void)
126{ 115{
127 /* kmap->ref_reloc_sym should be set if host_machine is initialized */ 116 /* kmap->ref_reloc_sym should be set if host_machine is initialized */
@@ -149,7 +138,7 @@ static int kernel_get_symbol_address_by_name(const char *name, u64 *addr,
149 if (reloc_sym && strcmp(name, reloc_sym->name) == 0) 138 if (reloc_sym && strcmp(name, reloc_sym->name) == 0)
150 *addr = (reloc) ? reloc_sym->addr : reloc_sym->unrelocated_addr; 139 *addr = (reloc) ? reloc_sym->addr : reloc_sym->unrelocated_addr;
151 else { 140 else {
152 sym = __find_kernel_function_by_name(name, &map); 141 sym = machine__find_kernel_symbol_by_name(host_machine, name, &map);
153 if (!sym) 142 if (!sym)
154 return -ENOENT; 143 return -ENOENT;
155 *addr = map->unmap_ip(map, sym->start) - 144 *addr = map->unmap_ip(map, sym->start) -
@@ -161,8 +150,7 @@ static int kernel_get_symbol_address_by_name(const char *name, u64 *addr,
161 150
162static struct map *kernel_get_module_map(const char *module) 151static struct map *kernel_get_module_map(const char *module)
163{ 152{
164 struct map_groups *grp = &host_machine->kmaps; 153 struct maps *maps = machine__kernel_maps(host_machine);
165 struct maps *maps = &grp->maps[MAP__FUNCTION];
166 struct map *pos; 154 struct map *pos;
167 155
168 /* A file path -- this is an offline module */ 156 /* A file path -- this is an offline module */
@@ -341,7 +329,7 @@ static int kernel_get_module_dso(const char *module, struct dso **pdso)
341 char module_name[128]; 329 char module_name[128];
342 330
343 snprintf(module_name, sizeof(module_name), "[%s]", module); 331 snprintf(module_name, sizeof(module_name), "[%s]", module);
344 map = map_groups__find_by_name(&host_machine->kmaps, MAP__FUNCTION, module_name); 332 map = map_groups__find_by_name(&host_machine->kmaps, module_name);
345 if (map) { 333 if (map) {
346 dso = map->dso; 334 dso = map->dso;
347 goto found; 335 goto found;
@@ -2098,7 +2086,7 @@ static int find_perf_probe_point_from_map(struct probe_trace_point *tp,
2098 } 2086 }
2099 if (addr) { 2087 if (addr) {
2100 addr += tp->offset; 2088 addr += tp->offset;
2101 sym = __find_kernel_function(addr, &map); 2089 sym = machine__find_kernel_symbol(host_machine, addr, &map);
2102 } 2090 }
2103 } 2091 }
2104 2092
@@ -3504,19 +3492,18 @@ int show_available_funcs(const char *target, struct nsinfo *nsi,
3504 (target) ? : "kernel"); 3492 (target) ? : "kernel");
3505 goto end; 3493 goto end;
3506 } 3494 }
3507 if (!dso__sorted_by_name(map->dso, map->type)) 3495 if (!dso__sorted_by_name(map->dso))
3508 dso__sort_by_name(map->dso, map->type); 3496 dso__sort_by_name(map->dso);
3509 3497
3510 /* Show all (filtered) symbols */ 3498 /* Show all (filtered) symbols */
3511 setup_pager(); 3499 setup_pager();
3512 3500
3513 for (nd = rb_first(&map->dso->symbol_names[map->type]); nd; nd = rb_next(nd)) { 3501 for (nd = rb_first(&map->dso->symbol_names); nd; nd = rb_next(nd)) {
3514 struct symbol_name_rb_node *pos = rb_entry(nd, struct symbol_name_rb_node, rb_node); 3502 struct symbol_name_rb_node *pos = rb_entry(nd, struct symbol_name_rb_node, rb_node);
3515 3503
3516 if (strfilter__compare(_filter, pos->sym.name)) 3504 if (strfilter__compare(_filter, pos->sym.name))
3517 printf("%s\n", pos->sym.name); 3505 printf("%s\n", pos->sym.name);
3518 } 3506 }
3519
3520end: 3507end:
3521 map__put(map); 3508 map__put(map);
3522 exit_probe_symbol_maps(); 3509 exit_probe_symbol_maps();
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index 4ae1123c6794..b76088fadf3d 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -84,8 +84,7 @@ int open_trace_file(const char *trace_file, bool readwrite)
84 char buf[PATH_MAX]; 84 char buf[PATH_MAX];
85 int ret; 85 int ret;
86 86
87 ret = e_snprintf(buf, PATH_MAX, "%s/%s", 87 ret = e_snprintf(buf, PATH_MAX, "%s/%s", tracing_path_mount(), trace_file);
88 tracing_path, trace_file);
89 if (ret >= 0) { 88 if (ret >= 0) {
90 pr_debug("Opening %s write=%d\n", buf, readwrite); 89 pr_debug("Opening %s write=%d\n", buf, readwrite);
91 if (readwrite && !probe_event_dry_run) 90 if (readwrite && !probe_event_dry_run)
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 10dd5fce082b..7f8afacd08ee 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -531,6 +531,8 @@ static PyObject *get_perf_sample_dict(struct perf_sample *sample,
531 PyLong_FromUnsignedLongLong(sample->period)); 531 PyLong_FromUnsignedLongLong(sample->period));
532 pydict_set_item_string_decref(dict_sample, "phys_addr", 532 pydict_set_item_string_decref(dict_sample, "phys_addr",
533 PyLong_FromUnsignedLongLong(sample->phys_addr)); 533 PyLong_FromUnsignedLongLong(sample->phys_addr));
534 pydict_set_item_string_decref(dict_sample, "addr",
535 PyLong_FromUnsignedLongLong(sample->addr));
534 set_sample_read_in_dict(dict_sample, sample, evsel); 536 set_sample_read_in_dict(dict_sample, sample, evsel);
535 pydict_set_item_string_decref(dict, "sample", dict_sample); 537 pydict_set_item_string_decref(dict, "sample", dict_sample);
536 538
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index f4a7a437ee87..b998bb475589 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1973,12 +1973,11 @@ bool perf_session__has_traces(struct perf_session *session, const char *msg)
1973 return false; 1973 return false;
1974} 1974}
1975 1975
1976int maps__set_kallsyms_ref_reloc_sym(struct map **maps, 1976int map__set_kallsyms_ref_reloc_sym(struct map *map, const char *symbol_name, u64 addr)
1977 const char *symbol_name, u64 addr)
1978{ 1977{
1979 char *bracket; 1978 char *bracket;
1980 int i;
1981 struct ref_reloc_sym *ref; 1979 struct ref_reloc_sym *ref;
1980 struct kmap *kmap;
1982 1981
1983 ref = zalloc(sizeof(struct ref_reloc_sym)); 1982 ref = zalloc(sizeof(struct ref_reloc_sym));
1984 if (ref == NULL) 1983 if (ref == NULL)
@@ -1996,13 +1995,9 @@ int maps__set_kallsyms_ref_reloc_sym(struct map **maps,
1996 1995
1997 ref->addr = addr; 1996 ref->addr = addr;
1998 1997
1999 for (i = 0; i < MAP__NR_TYPES; ++i) { 1998 kmap = map__kmap(map);
2000 struct kmap *kmap = map__kmap(maps[i]); 1999 if (kmap)
2001
2002 if (!kmap)
2003 continue;
2004 kmap->ref_reloc_sym = ref; 2000 kmap->ref_reloc_sym = ref;
2005 }
2006 2001
2007 return 0; 2002 return 0;
2008} 2003}
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 26a68dfd8a4f..4058ade352a5 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -2,7 +2,7 @@
2#include <errno.h> 2#include <errno.h>
3#include <inttypes.h> 3#include <inttypes.h>
4#include <regex.h> 4#include <regex.h>
5#include <sys/mman.h> 5#include <linux/mman.h>
6#include "sort.h" 6#include "sort.h"
7#include "hist.h" 7#include "hist.h"
8#include "comm.h" 8#include "comm.h"
@@ -282,7 +282,7 @@ static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym,
282 282
283 ret += repsep_snprintf(bf + ret, size - ret, "[%c] ", level); 283 ret += repsep_snprintf(bf + ret, size - ret, "[%c] ", level);
284 if (sym && map) { 284 if (sym && map) {
285 if (map->type == MAP__VARIABLE) { 285 if (sym->type == STT_OBJECT) {
286 ret += repsep_snprintf(bf + ret, size - ret, "%s", sym->name); 286 ret += repsep_snprintf(bf + ret, size - ret, "%s", sym->name);
287 ret += repsep_snprintf(bf + ret, size - ret, "+0x%llx", 287 ret += repsep_snprintf(bf + ret, size - ret, "+0x%llx",
288 ip - map->unmap_ip(map, sym->start)); 288 ip - map->unmap_ip(map, sym->start));
@@ -1211,7 +1211,7 @@ static int hist_entry__dcacheline_snprintf(struct hist_entry *he, char *bf,
1211 1211
1212 /* print [s] for shared data mmaps */ 1212 /* print [s] for shared data mmaps */
1213 if ((he->cpumode != PERF_RECORD_MISC_KERNEL) && 1213 if ((he->cpumode != PERF_RECORD_MISC_KERNEL) &&
1214 map && (map->type == MAP__VARIABLE) && 1214 map && !(map->prot & PROT_EXEC) &&
1215 (map->flags & MAP_SHARED) && 1215 (map->flags & MAP_SHARED) &&
1216 (map->maj || map->min || map->ino || 1216 (map->maj || map->min || map->ino ||
1217 map->ino_generation)) 1217 map->ino_generation))
@@ -2582,7 +2582,7 @@ int sort_dimension__add(struct perf_hpp_list *list, const char *tok,
2582 if (sort__mode != SORT_MODE__MEMORY) 2582 if (sort__mode != SORT_MODE__MEMORY)
2583 return -EINVAL; 2583 return -EINVAL;
2584 2584
2585 if (sd->entry == &sort_mem_dcacheline && cacheline_size == 0) 2585 if (sd->entry == &sort_mem_dcacheline && cacheline_size() == 0)
2586 return -EINVAL; 2586 return -EINVAL;
2587 2587
2588 if (sd->entry == &sort_mem_daddr_sym) 2588 if (sd->entry == &sort_mem_daddr_sym)
@@ -2628,7 +2628,7 @@ static int setup_sort_list(struct perf_hpp_list *list, char *str,
2628 if (*tok) { 2628 if (*tok) {
2629 ret = sort_dimension__add(list, tok, evlist, level); 2629 ret = sort_dimension__add(list, tok, evlist, level);
2630 if (ret == -EINVAL) { 2630 if (ret == -EINVAL) {
2631 if (!cacheline_size && !strncasecmp(tok, "dcacheline", strlen(tok))) 2631 if (!cacheline_size() && !strncasecmp(tok, "dcacheline", strlen(tok)))
2632 pr_err("The \"dcacheline\" --sort key needs to know the cacheline size and it couldn't be determined on this system"); 2632 pr_err("The \"dcacheline\" --sort key needs to know the cacheline size and it couldn't be determined on this system");
2633 else 2633 else
2634 pr_err("Invalid --sort key: `%s'", tok); 2634 pr_err("Invalid --sort key: `%s'", tok);
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 035b62e2c60b..9e6896293bbd 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -186,13 +186,13 @@ static inline float hist_entry__get_percent_limit(struct hist_entry *he)
186static inline u64 cl_address(u64 address) 186static inline u64 cl_address(u64 address)
187{ 187{
188 /* return the cacheline of the address */ 188 /* return the cacheline of the address */
189 return (address & ~(cacheline_size - 1)); 189 return (address & ~(cacheline_size() - 1));
190} 190}
191 191
192static inline u64 cl_offset(u64 address) 192static inline u64 cl_offset(u64 address)
193{ 193{
194 /* return the cacheline of the address */ 194 /* return the cacheline of the address */
195 return (address & (cacheline_size - 1)); 195 return (address & (cacheline_size() - 1));
196} 196}
197 197
198enum sort_mode { 198enum sort_mode {
diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c
index 3c21fd059b64..09d6746e6ec8 100644
--- a/tools/perf/util/srcline.c
+++ b/tools/perf/util/srcline.c
@@ -103,6 +103,7 @@ static struct symbol *new_inline_sym(struct dso *dso,
103 inline_sym = symbol__new(base_sym ? base_sym->start : 0, 103 inline_sym = symbol__new(base_sym ? base_sym->start : 0,
104 base_sym ? base_sym->end : 0, 104 base_sym ? base_sym->end : 0,
105 base_sym ? base_sym->binding : 0, 105 base_sym ? base_sym->binding : 0,
106 base_sym ? base_sym->type : 0,
106 funcname); 107 funcname);
107 if (inline_sym) 108 if (inline_sym)
108 inline_sym->inlined = 1; 109 inline_sym->inlined = 1;
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 8f56ba4fd258..36efb986f7fc 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -7,8 +7,7 @@
7#include "xyarray.h" 7#include "xyarray.h"
8#include "rblist.h" 8#include "rblist.h"
9 9
10struct stats 10struct stats {
11{
12 double n, mean, M2; 11 double n, mean, M2;
13 u64 max, min; 12 u64 max, min;
14}; 13};
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 2de770511e70..29770ea61768 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -114,16 +114,9 @@ static inline int elf_sym__is_label(const GElf_Sym *sym)
114 sym->st_shndx != SHN_ABS; 114 sym->st_shndx != SHN_ABS;
115} 115}
116 116
117static bool elf_sym__is_a(GElf_Sym *sym, enum map_type type) 117static bool elf_sym__filter(GElf_Sym *sym)
118{ 118{
119 switch (type) { 119 return elf_sym__is_function(sym) || elf_sym__is_object(sym);
120 case MAP__FUNCTION:
121 return elf_sym__is_function(sym);
122 case MAP__VARIABLE:
123 return elf_sym__is_object(sym);
124 default:
125 return false;
126 }
127} 120}
128 121
129static inline const char *elf_sym__name(const GElf_Sym *sym, 122static inline const char *elf_sym__name(const GElf_Sym *sym,
@@ -150,17 +143,10 @@ static inline bool elf_sec__is_data(const GElf_Shdr *shdr,
150 return strstr(elf_sec__name(shdr, secstrs), "data") != NULL; 143 return strstr(elf_sec__name(shdr, secstrs), "data") != NULL;
151} 144}
152 145
153static bool elf_sec__is_a(GElf_Shdr *shdr, Elf_Data *secstrs, 146static bool elf_sec__filter(GElf_Shdr *shdr, Elf_Data *secstrs)
154 enum map_type type)
155{ 147{
156 switch (type) { 148 return elf_sec__is_text(shdr, secstrs) ||
157 case MAP__FUNCTION: 149 elf_sec__is_data(shdr, secstrs);
158 return elf_sec__is_text(shdr, secstrs);
159 case MAP__VARIABLE:
160 return elf_sec__is_data(shdr, secstrs);
161 default:
162 return false;
163 }
164} 150}
165 151
166static size_t elf_addr_to_index(Elf *elf, GElf_Addr addr) 152static size_t elf_addr_to_index(Elf *elf, GElf_Addr addr)
@@ -256,7 +242,7 @@ static char *demangle_sym(struct dso *dso, int kmodule, const char *elf_name)
256 * And always look at the original dso, not at debuginfo packages, that 242 * And always look at the original dso, not at debuginfo packages, that
257 * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS). 243 * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS).
258 */ 244 */
259int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, struct map *map) 245int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss)
260{ 246{
261 uint32_t nr_rel_entries, idx; 247 uint32_t nr_rel_entries, idx;
262 GElf_Sym sym; 248 GElf_Sym sym;
@@ -364,12 +350,12 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, struct map *
364 free(demangled); 350 free(demangled);
365 351
366 f = symbol__new(plt_offset, plt_entry_size, 352 f = symbol__new(plt_offset, plt_entry_size,
367 STB_GLOBAL, sympltname); 353 STB_GLOBAL, STT_FUNC, sympltname);
368 if (!f) 354 if (!f)
369 goto out_elf_end; 355 goto out_elf_end;
370 356
371 plt_offset += plt_entry_size; 357 plt_offset += plt_entry_size;
372 symbols__insert(&dso->symbols[map->type], f); 358 symbols__insert(&dso->symbols, f);
373 ++nr; 359 ++nr;
374 } 360 }
375 } else if (shdr_rel_plt.sh_type == SHT_REL) { 361 } else if (shdr_rel_plt.sh_type == SHT_REL) {
@@ -390,12 +376,12 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, struct map *
390 free(demangled); 376 free(demangled);
391 377
392 f = symbol__new(plt_offset, plt_entry_size, 378 f = symbol__new(plt_offset, plt_entry_size,
393 STB_GLOBAL, sympltname); 379 STB_GLOBAL, STT_FUNC, sympltname);
394 if (!f) 380 if (!f)
395 goto out_elf_end; 381 goto out_elf_end;
396 382
397 plt_offset += plt_entry_size; 383 plt_offset += plt_entry_size;
398 symbols__insert(&dso->symbols[map->type], f); 384 symbols__insert(&dso->symbols, f);
399 ++nr; 385 ++nr;
400 } 386 }
401 } 387 }
@@ -811,6 +797,110 @@ static u64 ref_reloc(struct kmap *kmap)
811void __weak arch__sym_update(struct symbol *s __maybe_unused, 797void __weak arch__sym_update(struct symbol *s __maybe_unused,
812 GElf_Sym *sym __maybe_unused) { } 798 GElf_Sym *sym __maybe_unused) { }
813 799
800static int dso__process_kernel_symbol(struct dso *dso, struct map *map,
801 GElf_Sym *sym, GElf_Shdr *shdr,
802 struct map_groups *kmaps, struct kmap *kmap,
803 struct dso **curr_dsop, struct map **curr_mapp,
804 const char *section_name,
805 bool adjust_kernel_syms, bool kmodule, bool *remap_kernel)
806{
807 struct dso *curr_dso = *curr_dsop;
808 struct map *curr_map;
809 char dso_name[PATH_MAX];
810
811 /* Adjust symbol to map to file offset */
812 if (adjust_kernel_syms)
813 sym->st_value -= shdr->sh_addr - shdr->sh_offset;
814
815 if (strcmp(section_name, (curr_dso->short_name + dso->short_name_len)) == 0)
816 return 0;
817
818 if (strcmp(section_name, ".text") == 0) {
819 /*
820 * The initial kernel mapping is based on
821 * kallsyms and identity maps. Overwrite it to
822 * map to the kernel dso.
823 */
824 if (*remap_kernel && dso->kernel) {
825 *remap_kernel = false;
826 map->start = shdr->sh_addr + ref_reloc(kmap);
827 map->end = map->start + shdr->sh_size;
828 map->pgoff = shdr->sh_offset;
829 map->map_ip = map__map_ip;
830 map->unmap_ip = map__unmap_ip;
831 /* Ensure maps are correctly ordered */
832 if (kmaps) {
833 map__get(map);
834 map_groups__remove(kmaps, map);
835 map_groups__insert(kmaps, map);
836 map__put(map);
837 }
838 }
839
840 /*
841 * The initial module mapping is based on
842 * /proc/modules mapped to offset zero.
843 * Overwrite it to map to the module dso.
844 */
845 if (*remap_kernel && kmodule) {
846 *remap_kernel = false;
847 map->pgoff = shdr->sh_offset;
848 }
849
850 *curr_mapp = map;
851 *curr_dsop = dso;
852 return 0;
853 }
854
855 if (!kmap)
856 return 0;
857
858 snprintf(dso_name, sizeof(dso_name), "%s%s", dso->short_name, section_name);
859
860 curr_map = map_groups__find_by_name(kmaps, dso_name);
861 if (curr_map == NULL) {
862 u64 start = sym->st_value;
863
864 if (kmodule)
865 start += map->start + shdr->sh_offset;
866
867 curr_dso = dso__new(dso_name);
868 if (curr_dso == NULL)
869 return -1;
870 curr_dso->kernel = dso->kernel;
871 curr_dso->long_name = dso->long_name;
872 curr_dso->long_name_len = dso->long_name_len;
873 curr_map = map__new2(start, curr_dso);
874 dso__put(curr_dso);
875 if (curr_map == NULL)
876 return -1;
877
878 if (adjust_kernel_syms) {
879 curr_map->start = shdr->sh_addr + ref_reloc(kmap);
880 curr_map->end = curr_map->start + shdr->sh_size;
881 curr_map->pgoff = shdr->sh_offset;
882 } else {
883 curr_map->map_ip = curr_map->unmap_ip = identity__map_ip;
884 }
885 curr_dso->symtab_type = dso->symtab_type;
886 map_groups__insert(kmaps, curr_map);
887 /*
888 * Add it before we drop the referece to curr_map, i.e. while
889 * we still are sure to have a reference to this DSO via
890 * *curr_map->dso.
891 */
892 dsos__add(&map->groups->machine->dsos, curr_dso);
893 /* kmaps already got it */
894 map__put(curr_map);
895 dso__set_loaded(curr_dso);
896 *curr_mapp = curr_map;
897 *curr_dsop = curr_dso;
898 } else
899 *curr_dsop = curr_map->dso;
900
901 return 0;
902}
903
814int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss, 904int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss,
815 struct symsrc *runtime_ss, int kmodule) 905 struct symsrc *runtime_ss, int kmodule)
816{ 906{
@@ -844,7 +934,7 @@ int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss,
844 * have the wrong values for the dso maps, so remove them. 934 * have the wrong values for the dso maps, so remove them.
845 */ 935 */
846 if (kmodule && syms_ss->symtab) 936 if (kmodule && syms_ss->symtab)
847 symbols__delete(&dso->symbols[map->type]); 937 symbols__delete(&dso->symbols);
848 938
849 if (!syms_ss->symtab) { 939 if (!syms_ss->symtab) {
850 /* 940 /*
@@ -921,10 +1011,10 @@ int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss,
921 1011
922 dso->adjust_symbols = runtime_ss->adjust_symbols || ref_reloc(kmap); 1012 dso->adjust_symbols = runtime_ss->adjust_symbols || ref_reloc(kmap);
923 /* 1013 /*
924 * Initial kernel and module mappings do not map to the dso. For 1014 * Initial kernel and module mappings do not map to the dso.
925 * function mappings, flag the fixups. 1015 * Flag the fixups.
926 */ 1016 */
927 if (map->type == MAP__FUNCTION && (dso->kernel || kmodule)) { 1017 if (dso->kernel || kmodule) {
928 remap_kernel = true; 1018 remap_kernel = true;
929 adjust_kernel_syms = dso->adjust_symbols; 1019 adjust_kernel_syms = dso->adjust_symbols;
930 } 1020 }
@@ -936,7 +1026,7 @@ int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss,
936 const char *section_name; 1026 const char *section_name;
937 bool used_opd = false; 1027 bool used_opd = false;
938 1028
939 if (!is_label && !elf_sym__is_a(&sym, map->type)) 1029 if (!is_label && !elf_sym__filter(&sym))
940 continue; 1030 continue;
941 1031
942 /* Reject ARM ELF "mapping symbols": these aren't unique and 1032 /* Reject ARM ELF "mapping symbols": these aren't unique and
@@ -974,7 +1064,7 @@ int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss,
974 1064
975 gelf_getshdr(sec, &shdr); 1065 gelf_getshdr(sec, &shdr);
976 1066
977 if (is_label && !elf_sec__is_a(&shdr, secstrs, map->type)) 1067 if (is_label && !elf_sec__filter(&shdr, secstrs))
978 continue; 1068 continue;
979 1069
980 section_name = elf_sec__name(&shdr, secstrs); 1070 section_name = elf_sec__name(&shdr, secstrs);
@@ -982,134 +1072,37 @@ int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss,
982 /* On ARM, symbols for thumb functions have 1 added to 1072 /* On ARM, symbols for thumb functions have 1 added to
983 * the symbol address as a flag - remove it */ 1073 * the symbol address as a flag - remove it */
984 if ((ehdr.e_machine == EM_ARM) && 1074 if ((ehdr.e_machine == EM_ARM) &&
985 (map->type == MAP__FUNCTION) && 1075 (GELF_ST_TYPE(sym.st_info) == STT_FUNC) &&
986 (sym.st_value & 1)) 1076 (sym.st_value & 1))
987 --sym.st_value; 1077 --sym.st_value;
988 1078
989 if (dso->kernel || kmodule) { 1079 if (dso->kernel || kmodule) {
990 char dso_name[PATH_MAX]; 1080 if (dso__process_kernel_symbol(dso, map, &sym, &shdr, kmaps, kmap, &curr_dso, &curr_map,
991 1081 section_name, adjust_kernel_syms, kmodule, &remap_kernel))
992 /* Adjust symbol to map to file offset */ 1082 goto out_elf_end;
993 if (adjust_kernel_syms) 1083 } else if ((used_opd && runtime_ss->adjust_symbols) ||
994 sym.st_value -= shdr.sh_addr - shdr.sh_offset; 1084 (!used_opd && syms_ss->adjust_symbols)) {
995
996 if (strcmp(section_name,
997 (curr_dso->short_name +
998 dso->short_name_len)) == 0)
999 goto new_symbol;
1000
1001 if (strcmp(section_name, ".text") == 0) {
1002 /*
1003 * The initial kernel mapping is based on
1004 * kallsyms and identity maps. Overwrite it to
1005 * map to the kernel dso.
1006 */
1007 if (remap_kernel && dso->kernel) {
1008 remap_kernel = false;
1009 map->start = shdr.sh_addr +
1010 ref_reloc(kmap);
1011 map->end = map->start + shdr.sh_size;
1012 map->pgoff = shdr.sh_offset;
1013 map->map_ip = map__map_ip;
1014 map->unmap_ip = map__unmap_ip;
1015 /* Ensure maps are correctly ordered */
1016 if (kmaps) {
1017 map__get(map);
1018 map_groups__remove(kmaps, map);
1019 map_groups__insert(kmaps, map);
1020 map__put(map);
1021 }
1022 }
1023
1024 /*
1025 * The initial module mapping is based on
1026 * /proc/modules mapped to offset zero.
1027 * Overwrite it to map to the module dso.
1028 */
1029 if (remap_kernel && kmodule) {
1030 remap_kernel = false;
1031 map->pgoff = shdr.sh_offset;
1032 }
1033
1034 curr_map = map;
1035 curr_dso = dso;
1036 goto new_symbol;
1037 }
1038
1039 if (!kmap)
1040 goto new_symbol;
1041
1042 snprintf(dso_name, sizeof(dso_name),
1043 "%s%s", dso->short_name, section_name);
1044
1045 curr_map = map_groups__find_by_name(kmaps, map->type, dso_name);
1046 if (curr_map == NULL) {
1047 u64 start = sym.st_value;
1048
1049 if (kmodule)
1050 start += map->start + shdr.sh_offset;
1051
1052 curr_dso = dso__new(dso_name);
1053 if (curr_dso == NULL)
1054 goto out_elf_end;
1055 curr_dso->kernel = dso->kernel;
1056 curr_dso->long_name = dso->long_name;
1057 curr_dso->long_name_len = dso->long_name_len;
1058 curr_map = map__new2(start, curr_dso,
1059 map->type);
1060 dso__put(curr_dso);
1061 if (curr_map == NULL) {
1062 goto out_elf_end;
1063 }
1064 if (adjust_kernel_syms) {
1065 curr_map->start = shdr.sh_addr +
1066 ref_reloc(kmap);
1067 curr_map->end = curr_map->start +
1068 shdr.sh_size;
1069 curr_map->pgoff = shdr.sh_offset;
1070 } else {
1071 curr_map->map_ip = identity__map_ip;
1072 curr_map->unmap_ip = identity__map_ip;
1073 }
1074 curr_dso->symtab_type = dso->symtab_type;
1075 map_groups__insert(kmaps, curr_map);
1076 /*
1077 * Add it before we drop the referece to curr_map,
1078 * i.e. while we still are sure to have a reference
1079 * to this DSO via curr_map->dso.
1080 */
1081 dsos__add(&map->groups->machine->dsos, curr_dso);
1082 /* kmaps already got it */
1083 map__put(curr_map);
1084 dso__set_loaded(curr_dso, map->type);
1085 } else
1086 curr_dso = curr_map->dso;
1087
1088 goto new_symbol;
1089 }
1090
1091 if ((used_opd && runtime_ss->adjust_symbols)
1092 || (!used_opd && syms_ss->adjust_symbols)) {
1093 pr_debug4("%s: adjusting symbol: st_value: %#" PRIx64 " " 1085 pr_debug4("%s: adjusting symbol: st_value: %#" PRIx64 " "
1094 "sh_addr: %#" PRIx64 " sh_offset: %#" PRIx64 "\n", __func__, 1086 "sh_addr: %#" PRIx64 " sh_offset: %#" PRIx64 "\n", __func__,
1095 (u64)sym.st_value, (u64)shdr.sh_addr, 1087 (u64)sym.st_value, (u64)shdr.sh_addr,
1096 (u64)shdr.sh_offset); 1088 (u64)shdr.sh_offset);
1097 sym.st_value -= shdr.sh_addr - shdr.sh_offset; 1089 sym.st_value -= shdr.sh_addr - shdr.sh_offset;
1098 } 1090 }
1099new_symbol: 1091
1100 demangled = demangle_sym(dso, kmodule, elf_name); 1092 demangled = demangle_sym(dso, kmodule, elf_name);
1101 if (demangled != NULL) 1093 if (demangled != NULL)
1102 elf_name = demangled; 1094 elf_name = demangled;
1103 1095
1104 f = symbol__new(sym.st_value, sym.st_size, 1096 f = symbol__new(sym.st_value, sym.st_size,
1105 GELF_ST_BIND(sym.st_info), elf_name); 1097 GELF_ST_BIND(sym.st_info),
1098 GELF_ST_TYPE(sym.st_info), elf_name);
1106 free(demangled); 1099 free(demangled);
1107 if (!f) 1100 if (!f)
1108 goto out_elf_end; 1101 goto out_elf_end;
1109 1102
1110 arch__sym_update(f, &sym); 1103 arch__sym_update(f, &sym);
1111 1104
1112 __symbols__insert(&curr_dso->symbols[curr_map->type], f, dso->kernel); 1105 __symbols__insert(&curr_dso->symbols, f, dso->kernel);
1113 nr++; 1106 nr++;
1114 } 1107 }
1115 1108
@@ -1117,14 +1110,14 @@ new_symbol:
1117 * For misannotated, zeroed, ASM function sizes. 1110 * For misannotated, zeroed, ASM function sizes.
1118 */ 1111 */
1119 if (nr > 0) { 1112 if (nr > 0) {
1120 symbols__fixup_end(&dso->symbols[map->type]); 1113 symbols__fixup_end(&dso->symbols);
1121 symbols__fixup_duplicate(&dso->symbols[map->type]); 1114 symbols__fixup_duplicate(&dso->symbols);
1122 if (kmap) { 1115 if (kmap) {
1123 /* 1116 /*
1124 * We need to fixup this here too because we create new 1117 * We need to fixup this here too because we create new
1125 * maps here, for things like vsyscall sections. 1118 * maps here, for things like vsyscall sections.
1126 */ 1119 */
1127 __map_groups__fixup_end(kmaps, map->type); 1120 map_groups__fixup_end(kmaps);
1128 } 1121 }
1129 } 1122 }
1130 err = nr; 1123 err = nr;
@@ -1393,8 +1386,16 @@ static off_t kcore__write(struct kcore *kcore)
1393 1386
1394struct phdr_data { 1387struct phdr_data {
1395 off_t offset; 1388 off_t offset;
1389 off_t rel;
1396 u64 addr; 1390 u64 addr;
1397 u64 len; 1391 u64 len;
1392 struct list_head node;
1393 struct phdr_data *remaps;
1394};
1395
1396struct sym_data {
1397 u64 addr;
1398 struct list_head node;
1398}; 1399};
1399 1400
1400struct kcore_copy_info { 1401struct kcore_copy_info {
@@ -1404,16 +1405,78 @@ struct kcore_copy_info {
1404 u64 last_symbol; 1405 u64 last_symbol;
1405 u64 first_module; 1406 u64 first_module;
1406 u64 last_module_symbol; 1407 u64 last_module_symbol;
1407 struct phdr_data kernel_map; 1408 size_t phnum;
1408 struct phdr_data modules_map; 1409 struct list_head phdrs;
1410 struct list_head syms;
1409}; 1411};
1410 1412
1413#define kcore_copy__for_each_phdr(k, p) \
1414 list_for_each_entry((p), &(k)->phdrs, node)
1415
1416static struct phdr_data *phdr_data__new(u64 addr, u64 len, off_t offset)
1417{
1418 struct phdr_data *p = zalloc(sizeof(*p));
1419
1420 if (p) {
1421 p->addr = addr;
1422 p->len = len;
1423 p->offset = offset;
1424 }
1425
1426 return p;
1427}
1428
1429static struct phdr_data *kcore_copy_info__addnew(struct kcore_copy_info *kci,
1430 u64 addr, u64 len,
1431 off_t offset)
1432{
1433 struct phdr_data *p = phdr_data__new(addr, len, offset);
1434
1435 if (p)
1436 list_add_tail(&p->node, &kci->phdrs);
1437
1438 return p;
1439}
1440
1441static void kcore_copy__free_phdrs(struct kcore_copy_info *kci)
1442{
1443 struct phdr_data *p, *tmp;
1444
1445 list_for_each_entry_safe(p, tmp, &kci->phdrs, node) {
1446 list_del(&p->node);
1447 free(p);
1448 }
1449}
1450
1451static struct sym_data *kcore_copy__new_sym(struct kcore_copy_info *kci,
1452 u64 addr)
1453{
1454 struct sym_data *s = zalloc(sizeof(*s));
1455
1456 if (s) {
1457 s->addr = addr;
1458 list_add_tail(&s->node, &kci->syms);
1459 }
1460
1461 return s;
1462}
1463
1464static void kcore_copy__free_syms(struct kcore_copy_info *kci)
1465{
1466 struct sym_data *s, *tmp;
1467
1468 list_for_each_entry_safe(s, tmp, &kci->syms, node) {
1469 list_del(&s->node);
1470 free(s);
1471 }
1472}
1473
1411static int kcore_copy__process_kallsyms(void *arg, const char *name, char type, 1474static int kcore_copy__process_kallsyms(void *arg, const char *name, char type,
1412 u64 start) 1475 u64 start)
1413{ 1476{
1414 struct kcore_copy_info *kci = arg; 1477 struct kcore_copy_info *kci = arg;
1415 1478
1416 if (!symbol_type__is_a(type, MAP__FUNCTION)) 1479 if (!kallsyms__is_function(type))
1417 return 0; 1480 return 0;
1418 1481
1419 if (strchr(name, '[')) { 1482 if (strchr(name, '[')) {
@@ -1438,6 +1501,9 @@ static int kcore_copy__process_kallsyms(void *arg, const char *name, char type,
1438 return 0; 1501 return 0;
1439 } 1502 }
1440 1503
1504 if (is_entry_trampoline(name) && !kcore_copy__new_sym(kci, start))
1505 return -1;
1506
1441 return 0; 1507 return 0;
1442} 1508}
1443 1509
@@ -1487,27 +1553,39 @@ static int kcore_copy__parse_modules(struct kcore_copy_info *kci,
1487 return 0; 1553 return 0;
1488} 1554}
1489 1555
1490static void kcore_copy__map(struct phdr_data *p, u64 start, u64 end, u64 pgoff, 1556static int kcore_copy__map(struct kcore_copy_info *kci, u64 start, u64 end,
1491 u64 s, u64 e) 1557 u64 pgoff, u64 s, u64 e)
1492{ 1558{
1493 if (p->addr || s < start || s >= end) 1559 u64 len, offset;
1494 return; 1560
1561 if (s < start || s >= end)
1562 return 0;
1495 1563
1496 p->addr = s; 1564 offset = (s - start) + pgoff;
1497 p->offset = (s - start) + pgoff; 1565 len = e < end ? e - s : end - s;
1498 p->len = e < end ? e - s : end - s; 1566
1567 return kcore_copy_info__addnew(kci, s, len, offset) ? 0 : -1;
1499} 1568}
1500 1569
1501static int kcore_copy__read_map(u64 start, u64 len, u64 pgoff, void *data) 1570static int kcore_copy__read_map(u64 start, u64 len, u64 pgoff, void *data)
1502{ 1571{
1503 struct kcore_copy_info *kci = data; 1572 struct kcore_copy_info *kci = data;
1504 u64 end = start + len; 1573 u64 end = start + len;
1574 struct sym_data *sdat;
1505 1575
1506 kcore_copy__map(&kci->kernel_map, start, end, pgoff, kci->stext, 1576 if (kcore_copy__map(kci, start, end, pgoff, kci->stext, kci->etext))
1507 kci->etext); 1577 return -1;
1508 1578
1509 kcore_copy__map(&kci->modules_map, start, end, pgoff, kci->first_module, 1579 if (kcore_copy__map(kci, start, end, pgoff, kci->first_module,
1510 kci->last_module_symbol); 1580 kci->last_module_symbol))
1581 return -1;
1582
1583 list_for_each_entry(sdat, &kci->syms, node) {
1584 u64 s = round_down(sdat->addr, page_size);
1585
1586 if (kcore_copy__map(kci, start, end, pgoff, s, s + len))
1587 return -1;
1588 }
1511 1589
1512 return 0; 1590 return 0;
1513} 1591}
@@ -1520,6 +1598,64 @@ static int kcore_copy__read_maps(struct kcore_copy_info *kci, Elf *elf)
1520 return 0; 1598 return 0;
1521} 1599}
1522 1600
1601static void kcore_copy__find_remaps(struct kcore_copy_info *kci)
1602{
1603 struct phdr_data *p, *k = NULL;
1604 u64 kend;
1605
1606 if (!kci->stext)
1607 return;
1608
1609 /* Find phdr that corresponds to the kernel map (contains stext) */
1610 kcore_copy__for_each_phdr(kci, p) {
1611 u64 pend = p->addr + p->len - 1;
1612
1613 if (p->addr <= kci->stext && pend >= kci->stext) {
1614 k = p;
1615 break;
1616 }
1617 }
1618
1619 if (!k)
1620 return;
1621
1622 kend = k->offset + k->len;
1623
1624 /* Find phdrs that remap the kernel */
1625 kcore_copy__for_each_phdr(kci, p) {
1626 u64 pend = p->offset + p->len;
1627
1628 if (p == k)
1629 continue;
1630
1631 if (p->offset >= k->offset && pend <= kend)
1632 p->remaps = k;
1633 }
1634}
1635
1636static void kcore_copy__layout(struct kcore_copy_info *kci)
1637{
1638 struct phdr_data *p;
1639 off_t rel = 0;
1640
1641 kcore_copy__find_remaps(kci);
1642
1643 kcore_copy__for_each_phdr(kci, p) {
1644 if (!p->remaps) {
1645 p->rel = rel;
1646 rel += p->len;
1647 }
1648 kci->phnum += 1;
1649 }
1650
1651 kcore_copy__for_each_phdr(kci, p) {
1652 struct phdr_data *k = p->remaps;
1653
1654 if (k)
1655 p->rel = p->offset - k->offset + k->rel;
1656 }
1657}
1658
1523static int kcore_copy__calc_maps(struct kcore_copy_info *kci, const char *dir, 1659static int kcore_copy__calc_maps(struct kcore_copy_info *kci, const char *dir,
1524 Elf *elf) 1660 Elf *elf)
1525{ 1661{
@@ -1555,7 +1691,12 @@ static int kcore_copy__calc_maps(struct kcore_copy_info *kci, const char *dir,
1555 if (kci->first_module && !kci->last_module_symbol) 1691 if (kci->first_module && !kci->last_module_symbol)
1556 return -1; 1692 return -1;
1557 1693
1558 return kcore_copy__read_maps(kci, elf); 1694 if (kcore_copy__read_maps(kci, elf))
1695 return -1;
1696
1697 kcore_copy__layout(kci);
1698
1699 return 0;
1559} 1700}
1560 1701
1561static int kcore_copy__copy_file(const char *from_dir, const char *to_dir, 1702static int kcore_copy__copy_file(const char *from_dir, const char *to_dir,
@@ -1678,12 +1819,15 @@ int kcore_copy(const char *from_dir, const char *to_dir)
1678{ 1819{
1679 struct kcore kcore; 1820 struct kcore kcore;
1680 struct kcore extract; 1821 struct kcore extract;
1681 size_t count = 2;
1682 int idx = 0, err = -1; 1822 int idx = 0, err = -1;
1683 off_t offset = page_size, sz, modules_offset = 0; 1823 off_t offset, sz;
1684 struct kcore_copy_info kci = { .stext = 0, }; 1824 struct kcore_copy_info kci = { .stext = 0, };
1685 char kcore_filename[PATH_MAX]; 1825 char kcore_filename[PATH_MAX];
1686 char extract_filename[PATH_MAX]; 1826 char extract_filename[PATH_MAX];
1827 struct phdr_data *p;
1828
1829 INIT_LIST_HEAD(&kci.phdrs);
1830 INIT_LIST_HEAD(&kci.syms);
1687 1831
1688 if (kcore_copy__copy_file(from_dir, to_dir, "kallsyms")) 1832 if (kcore_copy__copy_file(from_dir, to_dir, "kallsyms"))
1689 return -1; 1833 return -1;
@@ -1703,20 +1847,17 @@ int kcore_copy(const char *from_dir, const char *to_dir)
1703 if (kcore__init(&extract, extract_filename, kcore.elfclass, false)) 1847 if (kcore__init(&extract, extract_filename, kcore.elfclass, false))
1704 goto out_kcore_close; 1848 goto out_kcore_close;
1705 1849
1706 if (!kci.modules_map.addr) 1850 if (kcore__copy_hdr(&kcore, &extract, kci.phnum))
1707 count -= 1;
1708
1709 if (kcore__copy_hdr(&kcore, &extract, count))
1710 goto out_extract_close; 1851 goto out_extract_close;
1711 1852
1712 if (kcore__add_phdr(&extract, idx++, offset, kci.kernel_map.addr, 1853 offset = gelf_fsize(extract.elf, ELF_T_EHDR, 1, EV_CURRENT) +
1713 kci.kernel_map.len)) 1854 gelf_fsize(extract.elf, ELF_T_PHDR, kci.phnum, EV_CURRENT);
1714 goto out_extract_close; 1855 offset = round_up(offset, page_size);
1856
1857 kcore_copy__for_each_phdr(&kci, p) {
1858 off_t offs = p->rel + offset;
1715 1859
1716 if (kci.modules_map.addr) { 1860 if (kcore__add_phdr(&extract, idx++, offs, p->addr, p->len))
1717 modules_offset = offset + kci.kernel_map.len;
1718 if (kcore__add_phdr(&extract, idx, modules_offset,
1719 kci.modules_map.addr, kci.modules_map.len))
1720 goto out_extract_close; 1861 goto out_extract_close;
1721 } 1862 }
1722 1863
@@ -1724,14 +1865,14 @@ int kcore_copy(const char *from_dir, const char *to_dir)
1724 if (sz < 0 || sz > offset) 1865 if (sz < 0 || sz > offset)
1725 goto out_extract_close; 1866 goto out_extract_close;
1726 1867
1727 if (copy_bytes(kcore.fd, kci.kernel_map.offset, extract.fd, offset, 1868 kcore_copy__for_each_phdr(&kci, p) {
1728 kci.kernel_map.len)) 1869 off_t offs = p->rel + offset;
1729 goto out_extract_close;
1730 1870
1731 if (modules_offset && copy_bytes(kcore.fd, kci.modules_map.offset, 1871 if (p->remaps)
1732 extract.fd, modules_offset, 1872 continue;
1733 kci.modules_map.len)) 1873 if (copy_bytes(kcore.fd, p->offset, extract.fd, offs, p->len))
1734 goto out_extract_close; 1874 goto out_extract_close;
1875 }
1735 1876
1736 if (kcore_copy__compare_file(from_dir, to_dir, "modules")) 1877 if (kcore_copy__compare_file(from_dir, to_dir, "modules"))
1737 goto out_extract_close; 1878 goto out_extract_close;
@@ -1754,6 +1895,9 @@ out_unlink_kallsyms:
1754 if (err) 1895 if (err)
1755 kcore_copy__unlink(to_dir, "kallsyms"); 1896 kcore_copy__unlink(to_dir, "kallsyms");
1756 1897
1898 kcore_copy__free_phdrs(&kci);
1899 kcore_copy__free_syms(&kci);
1900
1757 return err; 1901 return err;
1758} 1902}
1759 1903
diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c
index ff48d0d49584..7119df77dc0b 100644
--- a/tools/perf/util/symbol-minimal.c
+++ b/tools/perf/util/symbol-minimal.c
@@ -288,8 +288,7 @@ void symsrc__destroy(struct symsrc *ss)
288} 288}
289 289
290int dso__synthesize_plt_symbols(struct dso *dso __maybe_unused, 290int dso__synthesize_plt_symbols(struct dso *dso __maybe_unused,
291 struct symsrc *ss __maybe_unused, 291 struct symsrc *ss __maybe_unused)
292 struct map *map __maybe_unused)
293{ 292{
294 return 0; 293 return 0;
295} 294}
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 1466814ebada..8c84437f2a10 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -5,6 +5,7 @@
5#include <stdio.h> 5#include <stdio.h>
6#include <string.h> 6#include <string.h>
7#include <linux/kernel.h> 7#include <linux/kernel.h>
8#include <linux/mman.h>
8#include <sys/types.h> 9#include <sys/types.h>
9#include <sys/stat.h> 10#include <sys/stat.h>
10#include <sys/param.h> 11#include <sys/param.h>
@@ -70,18 +71,10 @@ static enum dso_binary_type binary_type_symtab[] = {
70 71
71#define DSO_BINARY_TYPE__SYMTAB_CNT ARRAY_SIZE(binary_type_symtab) 72#define DSO_BINARY_TYPE__SYMTAB_CNT ARRAY_SIZE(binary_type_symtab)
72 73
73bool symbol_type__is_a(char symbol_type, enum map_type map_type) 74static bool symbol_type__filter(char symbol_type)
74{ 75{
75 symbol_type = toupper(symbol_type); 76 symbol_type = toupper(symbol_type);
76 77 return symbol_type == 'T' || symbol_type == 'W' || symbol_type == 'D';
77 switch (map_type) {
78 case MAP__FUNCTION:
79 return symbol_type == 'T' || symbol_type == 'W';
80 case MAP__VARIABLE:
81 return symbol_type == 'D';
82 default:
83 return false;
84 }
85} 78}
86 79
87static int prefix_underscores_count(const char *str) 80static int prefix_underscores_count(const char *str)
@@ -228,9 +221,9 @@ void symbols__fixup_end(struct rb_root *symbols)
228 curr->end = roundup(curr->start, 4096) + 4096; 221 curr->end = roundup(curr->start, 4096) + 4096;
229} 222}
230 223
231void __map_groups__fixup_end(struct map_groups *mg, enum map_type type) 224void map_groups__fixup_end(struct map_groups *mg)
232{ 225{
233 struct maps *maps = &mg->maps[type]; 226 struct maps *maps = &mg->maps;
234 struct map *next, *curr; 227 struct map *next, *curr;
235 228
236 down_write(&maps->lock); 229 down_write(&maps->lock);
@@ -256,7 +249,7 @@ out_unlock:
256 up_write(&maps->lock); 249 up_write(&maps->lock);
257} 250}
258 251
259struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name) 252struct symbol *symbol__new(u64 start, u64 len, u8 binding, u8 type, const char *name)
260{ 253{
261 size_t namelen = strlen(name) + 1; 254 size_t namelen = strlen(name) + 1;
262 struct symbol *sym = calloc(1, (symbol_conf.priv_size + 255 struct symbol *sym = calloc(1, (symbol_conf.priv_size +
@@ -274,6 +267,7 @@ struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name)
274 267
275 sym->start = start; 268 sym->start = start;
276 sym->end = len ? start + len : start; 269 sym->end = len ? start + len : start;
270 sym->type = type;
277 sym->binding = binding; 271 sym->binding = binding;
278 sym->namelen = namelen - 1; 272 sym->namelen = namelen - 1;
279 273
@@ -484,45 +478,40 @@ static struct symbol *symbols__find_by_name(struct rb_root *symbols,
484 478
485void dso__reset_find_symbol_cache(struct dso *dso) 479void dso__reset_find_symbol_cache(struct dso *dso)
486{ 480{
487 enum map_type type; 481 dso->last_find_result.addr = 0;
488 482 dso->last_find_result.symbol = NULL;
489 for (type = MAP__FUNCTION; type <= MAP__VARIABLE; ++type) {
490 dso->last_find_result[type].addr = 0;
491 dso->last_find_result[type].symbol = NULL;
492 }
493} 483}
494 484
495void dso__insert_symbol(struct dso *dso, enum map_type type, struct symbol *sym) 485void dso__insert_symbol(struct dso *dso, struct symbol *sym)
496{ 486{
497 __symbols__insert(&dso->symbols[type], sym, dso->kernel); 487 __symbols__insert(&dso->symbols, sym, dso->kernel);
498 488
499 /* update the symbol cache if necessary */ 489 /* update the symbol cache if necessary */
500 if (dso->last_find_result[type].addr >= sym->start && 490 if (dso->last_find_result.addr >= sym->start &&
501 (dso->last_find_result[type].addr < sym->end || 491 (dso->last_find_result.addr < sym->end ||
502 sym->start == sym->end)) { 492 sym->start == sym->end)) {
503 dso->last_find_result[type].symbol = sym; 493 dso->last_find_result.symbol = sym;
504 } 494 }
505} 495}
506 496
507struct symbol *dso__find_symbol(struct dso *dso, 497struct symbol *dso__find_symbol(struct dso *dso, u64 addr)
508 enum map_type type, u64 addr)
509{ 498{
510 if (dso->last_find_result[type].addr != addr || dso->last_find_result[type].symbol == NULL) { 499 if (dso->last_find_result.addr != addr || dso->last_find_result.symbol == NULL) {
511 dso->last_find_result[type].addr = addr; 500 dso->last_find_result.addr = addr;
512 dso->last_find_result[type].symbol = symbols__find(&dso->symbols[type], addr); 501 dso->last_find_result.symbol = symbols__find(&dso->symbols, addr);
513 } 502 }
514 503
515 return dso->last_find_result[type].symbol; 504 return dso->last_find_result.symbol;
516} 505}
517 506
518struct symbol *dso__first_symbol(struct dso *dso, enum map_type type) 507struct symbol *dso__first_symbol(struct dso *dso)
519{ 508{
520 return symbols__first(&dso->symbols[type]); 509 return symbols__first(&dso->symbols);
521} 510}
522 511
523struct symbol *dso__last_symbol(struct dso *dso, enum map_type type) 512struct symbol *dso__last_symbol(struct dso *dso)
524{ 513{
525 return symbols__last(&dso->symbols[type]); 514 return symbols__last(&dso->symbols);
526} 515}
527 516
528struct symbol *dso__next_symbol(struct symbol *sym) 517struct symbol *dso__next_symbol(struct symbol *sym)
@@ -539,24 +528,22 @@ struct symbol *symbol__next_by_name(struct symbol *sym)
539} 528}
540 529
541 /* 530 /*
542 * Teturns first symbol that matched with @name. 531 * Returns first symbol that matched with @name.
543 */ 532 */
544struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, 533struct symbol *dso__find_symbol_by_name(struct dso *dso, const char *name)
545 const char *name)
546{ 534{
547 struct symbol *s = symbols__find_by_name(&dso->symbol_names[type], name, 535 struct symbol *s = symbols__find_by_name(&dso->symbol_names, name,
548 SYMBOL_TAG_INCLUDE__NONE); 536 SYMBOL_TAG_INCLUDE__NONE);
549 if (!s) 537 if (!s)
550 s = symbols__find_by_name(&dso->symbol_names[type], name, 538 s = symbols__find_by_name(&dso->symbol_names, name,
551 SYMBOL_TAG_INCLUDE__DEFAULT_ONLY); 539 SYMBOL_TAG_INCLUDE__DEFAULT_ONLY);
552 return s; 540 return s;
553} 541}
554 542
555void dso__sort_by_name(struct dso *dso, enum map_type type) 543void dso__sort_by_name(struct dso *dso)
556{ 544{
557 dso__set_sorted_by_name(dso, type); 545 dso__set_sorted_by_name(dso);
558 return symbols__sort_by_name(&dso->symbol_names[type], 546 return symbols__sort_by_name(&dso->symbol_names, &dso->symbols);
559 &dso->symbols[type]);
560} 547}
561 548
562int modules__parse(const char *filename, void *arg, 549int modules__parse(const char *filename, void *arg,
@@ -621,11 +608,6 @@ out:
621 return err; 608 return err;
622} 609}
623 610
624struct process_kallsyms_args {
625 struct map *map;
626 struct dso *dso;
627};
628
629/* 611/*
630 * These are symbols in the kernel image, so make sure that 612 * These are symbols in the kernel image, so make sure that
631 * sym is from a kernel DSO. 613 * sym is from a kernel DSO.
@@ -661,10 +643,10 @@ static int map__process_kallsym_symbol(void *arg, const char *name,
661 char type, u64 start) 643 char type, u64 start)
662{ 644{
663 struct symbol *sym; 645 struct symbol *sym;
664 struct process_kallsyms_args *a = arg; 646 struct dso *dso = arg;
665 struct rb_root *root = &a->dso->symbols[a->map->type]; 647 struct rb_root *root = &dso->symbols;
666 648
667 if (!symbol_type__is_a(type, a->map->type)) 649 if (!symbol_type__filter(type))
668 return 0; 650 return 0;
669 651
670 /* 652 /*
@@ -672,7 +654,7 @@ static int map__process_kallsym_symbol(void *arg, const char *name,
672 * symbols, setting length to 0, and rely on 654 * symbols, setting length to 0, and rely on
673 * symbols__fixup_end() to fix it up. 655 * symbols__fixup_end() to fix it up.
674 */ 656 */
675 sym = symbol__new(start, 0, kallsyms2elf_binding(type), name); 657 sym = symbol__new(start, 0, kallsyms2elf_binding(type), kallsyms2elf_type(type), name);
676 if (sym == NULL) 658 if (sym == NULL)
677 return -ENOMEM; 659 return -ENOMEM;
678 /* 660 /*
@@ -689,21 +671,18 @@ static int map__process_kallsym_symbol(void *arg, const char *name,
689 * so that we can in the next step set the symbol ->end address and then 671 * so that we can in the next step set the symbol ->end address and then
690 * call kernel_maps__split_kallsyms. 672 * call kernel_maps__split_kallsyms.
691 */ 673 */
692static int dso__load_all_kallsyms(struct dso *dso, const char *filename, 674static int dso__load_all_kallsyms(struct dso *dso, const char *filename)
693 struct map *map)
694{ 675{
695 struct process_kallsyms_args args = { .map = map, .dso = dso, }; 676 return kallsyms__parse(filename, dso, map__process_kallsym_symbol);
696 return kallsyms__parse(filename, &args, map__process_kallsym_symbol);
697} 677}
698 678
699static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map) 679static int map_groups__split_kallsyms_for_kcore(struct map_groups *kmaps, struct dso *dso)
700{ 680{
701 struct map_groups *kmaps = map__kmaps(map);
702 struct map *curr_map; 681 struct map *curr_map;
703 struct symbol *pos; 682 struct symbol *pos;
704 int count = 0; 683 int count = 0;
705 struct rb_root old_root = dso->symbols[map->type]; 684 struct rb_root old_root = dso->symbols;
706 struct rb_root *root = &dso->symbols[map->type]; 685 struct rb_root *root = &dso->symbols;
707 struct rb_node *next = rb_first(root); 686 struct rb_node *next = rb_first(root);
708 687
709 if (!kmaps) 688 if (!kmaps)
@@ -723,7 +702,7 @@ static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map)
723 if (module) 702 if (module)
724 *module = '\0'; 703 *module = '\0';
725 704
726 curr_map = map_groups__find(kmaps, map->type, pos->start); 705 curr_map = map_groups__find(kmaps, pos->start);
727 706
728 if (!curr_map) { 707 if (!curr_map) {
729 symbol__delete(pos); 708 symbol__delete(pos);
@@ -733,7 +712,7 @@ static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map)
733 pos->start -= curr_map->start - curr_map->pgoff; 712 pos->start -= curr_map->start - curr_map->pgoff;
734 if (pos->end) 713 if (pos->end)
735 pos->end -= curr_map->start - curr_map->pgoff; 714 pos->end -= curr_map->start - curr_map->pgoff;
736 symbols__insert(&curr_map->dso->symbols[curr_map->type], pos); 715 symbols__insert(&curr_map->dso->symbols, pos);
737 ++count; 716 ++count;
738 } 717 }
739 718
@@ -748,22 +727,25 @@ static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map)
748 * kernel range is broken in several maps, named [kernel].N, as we don't have 727 * kernel range is broken in several maps, named [kernel].N, as we don't have
749 * the original ELF section names vmlinux have. 728 * the original ELF section names vmlinux have.
750 */ 729 */
751static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta) 730static int map_groups__split_kallsyms(struct map_groups *kmaps, struct dso *dso, u64 delta,
731 struct map *initial_map)
752{ 732{
753 struct map_groups *kmaps = map__kmaps(map);
754 struct machine *machine; 733 struct machine *machine;
755 struct map *curr_map = map; 734 struct map *curr_map = initial_map;
756 struct symbol *pos; 735 struct symbol *pos;
757 int count = 0, moved = 0; 736 int count = 0, moved = 0;
758 struct rb_root *root = &dso->symbols[map->type]; 737 struct rb_root *root = &dso->symbols;
759 struct rb_node *next = rb_first(root); 738 struct rb_node *next = rb_first(root);
760 int kernel_range = 0; 739 int kernel_range = 0;
740 bool x86_64;
761 741
762 if (!kmaps) 742 if (!kmaps)
763 return -1; 743 return -1;
764 744
765 machine = kmaps->machine; 745 machine = kmaps->machine;
766 746
747 x86_64 = machine__is(machine, "x86_64");
748
767 while (next) { 749 while (next) {
768 char *module; 750 char *module;
769 751
@@ -778,7 +760,7 @@ static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta)
778 *module++ = '\0'; 760 *module++ = '\0';
779 761
780 if (strcmp(curr_map->dso->short_name, module)) { 762 if (strcmp(curr_map->dso->short_name, module)) {
781 if (curr_map != map && 763 if (curr_map != initial_map &&
782 dso->kernel == DSO_TYPE_GUEST_KERNEL && 764 dso->kernel == DSO_TYPE_GUEST_KERNEL &&
783 machine__is_default_guest(machine)) { 765 machine__is_default_guest(machine)) {
784 /* 766 /*
@@ -788,18 +770,16 @@ static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta)
788 * symbols are in its kmap. Mark it as 770 * symbols are in its kmap. Mark it as
789 * loaded. 771 * loaded.
790 */ 772 */
791 dso__set_loaded(curr_map->dso, 773 dso__set_loaded(curr_map->dso);
792 curr_map->type);
793 } 774 }
794 775
795 curr_map = map_groups__find_by_name(kmaps, 776 curr_map = map_groups__find_by_name(kmaps, module);
796 map->type, module);
797 if (curr_map == NULL) { 777 if (curr_map == NULL) {
798 pr_debug("%s/proc/{kallsyms,modules} " 778 pr_debug("%s/proc/{kallsyms,modules} "
799 "inconsistency while looking " 779 "inconsistency while looking "
800 "for \"%s\" module!\n", 780 "for \"%s\" module!\n",
801 machine->root_dir, module); 781 machine->root_dir, module);
802 curr_map = map; 782 curr_map = initial_map;
803 goto discard_symbol; 783 goto discard_symbol;
804 } 784 }
805 785
@@ -809,11 +789,21 @@ static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta)
809 } 789 }
810 /* 790 /*
811 * So that we look just like we get from .ko files, 791 * So that we look just like we get from .ko files,
812 * i.e. not prelinked, relative to map->start. 792 * i.e. not prelinked, relative to initial_map->start.
813 */ 793 */
814 pos->start = curr_map->map_ip(curr_map, pos->start); 794 pos->start = curr_map->map_ip(curr_map, pos->start);
815 pos->end = curr_map->map_ip(curr_map, pos->end); 795 pos->end = curr_map->map_ip(curr_map, pos->end);
816 } else if (curr_map != map) { 796 } else if (x86_64 && is_entry_trampoline(pos->name)) {
797 /*
798 * These symbols are not needed anymore since the
799 * trampoline maps refer to the text section and it's
800 * symbols instead. Avoid having to deal with
801 * relocations, and the assumption that the first symbol
802 * is the start of kernel text, by simply removing the
803 * symbols at this point.
804 */
805 goto discard_symbol;
806 } else if (curr_map != initial_map) {
817 char dso_name[PATH_MAX]; 807 char dso_name[PATH_MAX];
818 struct dso *ndso; 808 struct dso *ndso;
819 809
@@ -824,7 +814,7 @@ static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta)
824 } 814 }
825 815
826 if (count == 0) { 816 if (count == 0) {
827 curr_map = map; 817 curr_map = initial_map;
828 goto add_symbol; 818 goto add_symbol;
829 } 819 }
830 820
@@ -843,7 +833,7 @@ static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta)
843 833
844 ndso->kernel = dso->kernel; 834 ndso->kernel = dso->kernel;
845 835
846 curr_map = map__new2(pos->start, ndso, map->type); 836 curr_map = map__new2(pos->start, ndso);
847 if (curr_map == NULL) { 837 if (curr_map == NULL) {
848 dso__put(ndso); 838 dso__put(ndso);
849 return -1; 839 return -1;
@@ -858,9 +848,9 @@ static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta)
858 pos->end -= delta; 848 pos->end -= delta;
859 } 849 }
860add_symbol: 850add_symbol:
861 if (curr_map != map) { 851 if (curr_map != initial_map) {
862 rb_erase(&pos->rb_node, root); 852 rb_erase(&pos->rb_node, root);
863 symbols__insert(&curr_map->dso->symbols[curr_map->type], pos); 853 symbols__insert(&curr_map->dso->symbols, pos);
864 ++moved; 854 ++moved;
865 } else 855 } else
866 ++count; 856 ++count;
@@ -871,10 +861,10 @@ discard_symbol:
871 symbol__delete(pos); 861 symbol__delete(pos);
872 } 862 }
873 863
874 if (curr_map != map && 864 if (curr_map != initial_map &&
875 dso->kernel == DSO_TYPE_GUEST_KERNEL && 865 dso->kernel == DSO_TYPE_GUEST_KERNEL &&
876 machine__is_default_guest(kmaps->machine)) { 866 machine__is_default_guest(kmaps->machine)) {
877 dso__set_loaded(curr_map->dso, curr_map->type); 867 dso__set_loaded(curr_map->dso);
878 } 868 }
879 869
880 return count + moved; 870 return count + moved;
@@ -1035,7 +1025,12 @@ out_delete_from:
1035 return ret; 1025 return ret;
1036} 1026}
1037 1027
1038static int do_validate_kcore_modules(const char *filename, struct map *map, 1028struct map *map_groups__first(struct map_groups *mg)
1029{
1030 return maps__first(&mg->maps);
1031}
1032
1033static int do_validate_kcore_modules(const char *filename,
1039 struct map_groups *kmaps) 1034 struct map_groups *kmaps)
1040{ 1035{
1041 struct rb_root modules = RB_ROOT; 1036 struct rb_root modules = RB_ROOT;
@@ -1046,13 +1041,12 @@ static int do_validate_kcore_modules(const char *filename, struct map *map,
1046 if (err) 1041 if (err)
1047 return err; 1042 return err;
1048 1043
1049 old_map = map_groups__first(kmaps, map->type); 1044 old_map = map_groups__first(kmaps);
1050 while (old_map) { 1045 while (old_map) {
1051 struct map *next = map_groups__next(old_map); 1046 struct map *next = map_groups__next(old_map);
1052 struct module_info *mi; 1047 struct module_info *mi;
1053 1048
1054 if (old_map == map || old_map->start == map->start) { 1049 if (!__map__is_kmodule(old_map)) {
1055 /* The kernel map */
1056 old_map = next; 1050 old_map = next;
1057 continue; 1051 continue;
1058 } 1052 }
@@ -1109,7 +1103,7 @@ static int validate_kcore_modules(const char *kallsyms_filename,
1109 kallsyms_filename)) 1103 kallsyms_filename))
1110 return -EINVAL; 1104 return -EINVAL;
1111 1105
1112 if (do_validate_kcore_modules(modules_filename, map, kmaps)) 1106 if (do_validate_kcore_modules(modules_filename, kmaps))
1113 return -EINVAL; 1107 return -EINVAL;
1114 1108
1115 return 0; 1109 return 0;
@@ -1138,7 +1132,6 @@ static int validate_kcore_addresses(const char *kallsyms_filename,
1138 1132
1139struct kcore_mapfn_data { 1133struct kcore_mapfn_data {
1140 struct dso *dso; 1134 struct dso *dso;
1141 enum map_type type;
1142 struct list_head maps; 1135 struct list_head maps;
1143}; 1136};
1144 1137
@@ -1147,7 +1140,7 @@ static int kcore_mapfn(u64 start, u64 len, u64 pgoff, void *data)
1147 struct kcore_mapfn_data *md = data; 1140 struct kcore_mapfn_data *md = data;
1148 struct map *map; 1141 struct map *map;
1149 1142
1150 map = map__new2(start, md->dso, md->type); 1143 map = map__new2(start, md->dso);
1151 if (map == NULL) 1144 if (map == NULL)
1152 return -ENOMEM; 1145 return -ENOMEM;
1153 1146
@@ -1163,13 +1156,13 @@ static int dso__load_kcore(struct dso *dso, struct map *map,
1163 const char *kallsyms_filename) 1156 const char *kallsyms_filename)
1164{ 1157{
1165 struct map_groups *kmaps = map__kmaps(map); 1158 struct map_groups *kmaps = map__kmaps(map);
1166 struct machine *machine;
1167 struct kcore_mapfn_data md; 1159 struct kcore_mapfn_data md;
1168 struct map *old_map, *new_map, *replacement_map = NULL; 1160 struct map *old_map, *new_map, *replacement_map = NULL;
1161 struct machine *machine;
1169 bool is_64_bit; 1162 bool is_64_bit;
1170 int err, fd; 1163 int err, fd;
1171 char kcore_filename[PATH_MAX]; 1164 char kcore_filename[PATH_MAX];
1172 struct symbol *sym; 1165 u64 stext;
1173 1166
1174 if (!kmaps) 1167 if (!kmaps)
1175 return -EINVAL; 1168 return -EINVAL;
@@ -1177,7 +1170,7 @@ static int dso__load_kcore(struct dso *dso, struct map *map,
1177 machine = kmaps->machine; 1170 machine = kmaps->machine;
1178 1171
1179 /* This function requires that the map is the kernel map */ 1172 /* This function requires that the map is the kernel map */
1180 if (map != machine->vmlinux_maps[map->type]) 1173 if (!__map__is_kernel(map))
1181 return -EINVAL; 1174 return -EINVAL;
1182 1175
1183 if (!filename_from_kallsyms_filename(kcore_filename, "kcore", 1176 if (!filename_from_kallsyms_filename(kcore_filename, "kcore",
@@ -1189,7 +1182,6 @@ static int dso__load_kcore(struct dso *dso, struct map *map,
1189 return -EINVAL; 1182 return -EINVAL;
1190 1183
1191 md.dso = dso; 1184 md.dso = dso;
1192 md.type = map->type;
1193 INIT_LIST_HEAD(&md.maps); 1185 INIT_LIST_HEAD(&md.maps);
1194 1186
1195 fd = open(kcore_filename, O_RDONLY); 1187 fd = open(kcore_filename, O_RDONLY);
@@ -1200,7 +1192,7 @@ static int dso__load_kcore(struct dso *dso, struct map *map,
1200 } 1192 }
1201 1193
1202 /* Read new maps into temporary lists */ 1194 /* Read new maps into temporary lists */
1203 err = file__read_maps(fd, md.type == MAP__FUNCTION, kcore_mapfn, &md, 1195 err = file__read_maps(fd, map->prot & PROT_EXEC, kcore_mapfn, &md,
1204 &is_64_bit); 1196 &is_64_bit);
1205 if (err) 1197 if (err)
1206 goto out_err; 1198 goto out_err;
@@ -1212,7 +1204,7 @@ static int dso__load_kcore(struct dso *dso, struct map *map,
1212 } 1204 }
1213 1205
1214 /* Remove old maps */ 1206 /* Remove old maps */
1215 old_map = map_groups__first(kmaps, map->type); 1207 old_map = map_groups__first(kmaps);
1216 while (old_map) { 1208 while (old_map) {
1217 struct map *next = map_groups__next(old_map); 1209 struct map *next = map_groups__next(old_map);
1218 1210
@@ -1220,14 +1212,15 @@ static int dso__load_kcore(struct dso *dso, struct map *map,
1220 map_groups__remove(kmaps, old_map); 1212 map_groups__remove(kmaps, old_map);
1221 old_map = next; 1213 old_map = next;
1222 } 1214 }
1215 machine->trampolines_mapped = false;
1223 1216
1224 /* Find the kernel map using the first symbol */ 1217 /* Find the kernel map using the '_stext' symbol */
1225 sym = dso__first_symbol(dso, map->type); 1218 if (!kallsyms__get_function_start(kallsyms_filename, "_stext", &stext)) {
1226 list_for_each_entry(new_map, &md.maps, node) { 1219 list_for_each_entry(new_map, &md.maps, node) {
1227 if (sym && sym->start >= new_map->start && 1220 if (stext >= new_map->start && stext < new_map->end) {
1228 sym->start < new_map->end) { 1221 replacement_map = new_map;
1229 replacement_map = new_map; 1222 break;
1230 break; 1223 }
1231 } 1224 }
1232 } 1225 }
1233 1226
@@ -1256,6 +1249,19 @@ static int dso__load_kcore(struct dso *dso, struct map *map,
1256 map__put(new_map); 1249 map__put(new_map);
1257 } 1250 }
1258 1251
1252 if (machine__is(machine, "x86_64")) {
1253 u64 addr;
1254
1255 /*
1256 * If one of the corresponding symbols is there, assume the
1257 * entry trampoline maps are too.
1258 */
1259 if (!kallsyms__get_function_start(kallsyms_filename,
1260 ENTRY_TRAMPOLINE_NAME,
1261 &addr))
1262 machine->trampolines_mapped = true;
1263 }
1264
1259 /* 1265 /*
1260 * Set the data type and long name so that kcore can be read via 1266 * Set the data type and long name so that kcore can be read via
1261 * dso__data_read_addr(). 1267 * dso__data_read_addr().
@@ -1268,7 +1274,7 @@ static int dso__load_kcore(struct dso *dso, struct map *map,
1268 1274
1269 close(fd); 1275 close(fd);
1270 1276
1271 if (map->type == MAP__FUNCTION) 1277 if (map->prot & PROT_EXEC)
1272 pr_debug("Using %s for kernel object code\n", kcore_filename); 1278 pr_debug("Using %s for kernel object code\n", kcore_filename);
1273 else 1279 else
1274 pr_debug("Using %s for kernel data\n", kcore_filename); 1280 pr_debug("Using %s for kernel data\n", kcore_filename);
@@ -1289,14 +1295,10 @@ out_err:
1289 * If the kernel is relocated at boot time, kallsyms won't match. Compute the 1295 * If the kernel is relocated at boot time, kallsyms won't match. Compute the
1290 * delta based on the relocation reference symbol. 1296 * delta based on the relocation reference symbol.
1291 */ 1297 */
1292static int kallsyms__delta(struct map *map, const char *filename, u64 *delta) 1298static int kallsyms__delta(struct kmap *kmap, const char *filename, u64 *delta)
1293{ 1299{
1294 struct kmap *kmap = map__kmap(map);
1295 u64 addr; 1300 u64 addr;
1296 1301
1297 if (!kmap)
1298 return -1;
1299
1300 if (!kmap->ref_reloc_sym || !kmap->ref_reloc_sym->name) 1302 if (!kmap->ref_reloc_sym || !kmap->ref_reloc_sym->name)
1301 return 0; 1303 return 0;
1302 1304
@@ -1310,19 +1312,23 @@ static int kallsyms__delta(struct map *map, const char *filename, u64 *delta)
1310int __dso__load_kallsyms(struct dso *dso, const char *filename, 1312int __dso__load_kallsyms(struct dso *dso, const char *filename,
1311 struct map *map, bool no_kcore) 1313 struct map *map, bool no_kcore)
1312{ 1314{
1315 struct kmap *kmap = map__kmap(map);
1313 u64 delta = 0; 1316 u64 delta = 0;
1314 1317
1315 if (symbol__restricted_filename(filename, "/proc/kallsyms")) 1318 if (symbol__restricted_filename(filename, "/proc/kallsyms"))
1316 return -1; 1319 return -1;
1317 1320
1318 if (dso__load_all_kallsyms(dso, filename, map) < 0) 1321 if (!kmap || !kmap->kmaps)
1319 return -1; 1322 return -1;
1320 1323
1321 if (kallsyms__delta(map, filename, &delta)) 1324 if (dso__load_all_kallsyms(dso, filename) < 0)
1322 return -1; 1325 return -1;
1323 1326
1324 symbols__fixup_end(&dso->symbols[map->type]); 1327 if (kallsyms__delta(kmap, filename, &delta))
1325 symbols__fixup_duplicate(&dso->symbols[map->type]); 1328 return -1;
1329
1330 symbols__fixup_end(&dso->symbols);
1331 symbols__fixup_duplicate(&dso->symbols);
1326 1332
1327 if (dso->kernel == DSO_TYPE_GUEST_KERNEL) 1333 if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
1328 dso->symtab_type = DSO_BINARY_TYPE__GUEST_KALLSYMS; 1334 dso->symtab_type = DSO_BINARY_TYPE__GUEST_KALLSYMS;
@@ -1330,9 +1336,9 @@ int __dso__load_kallsyms(struct dso *dso, const char *filename,
1330 dso->symtab_type = DSO_BINARY_TYPE__KALLSYMS; 1336 dso->symtab_type = DSO_BINARY_TYPE__KALLSYMS;
1331 1337
1332 if (!no_kcore && !dso__load_kcore(dso, map, filename)) 1338 if (!no_kcore && !dso__load_kcore(dso, map, filename))
1333 return dso__split_kallsyms_for_kcore(dso, map); 1339 return map_groups__split_kallsyms_for_kcore(kmap->kmaps, dso);
1334 else 1340 else
1335 return dso__split_kallsyms(dso, map, delta); 1341 return map_groups__split_kallsyms(kmap->kmaps, dso, delta, map);
1336} 1342}
1337 1343
1338int dso__load_kallsyms(struct dso *dso, const char *filename, 1344int dso__load_kallsyms(struct dso *dso, const char *filename,
@@ -1341,8 +1347,7 @@ int dso__load_kallsyms(struct dso *dso, const char *filename,
1341 return __dso__load_kallsyms(dso, filename, map, false); 1347 return __dso__load_kallsyms(dso, filename, map, false);
1342} 1348}
1343 1349
1344static int dso__load_perf_map(const char *map_path, struct dso *dso, 1350static int dso__load_perf_map(const char *map_path, struct dso *dso)
1345 struct map *map)
1346{ 1351{
1347 char *line = NULL; 1352 char *line = NULL;
1348 size_t n; 1353 size_t n;
@@ -1379,12 +1384,12 @@ static int dso__load_perf_map(const char *map_path, struct dso *dso,
1379 if (len + 2 >= line_len) 1384 if (len + 2 >= line_len)
1380 continue; 1385 continue;
1381 1386
1382 sym = symbol__new(start, size, STB_GLOBAL, line + len); 1387 sym = symbol__new(start, size, STB_GLOBAL, STT_FUNC, line + len);
1383 1388
1384 if (sym == NULL) 1389 if (sym == NULL)
1385 goto out_delete_line; 1390 goto out_delete_line;
1386 1391
1387 symbols__insert(&dso->symbols[map->type], sym); 1392 symbols__insert(&dso->symbols, sym);
1388 nr_syms++; 1393 nr_syms++;
1389 } 1394 }
1390 1395
@@ -1509,25 +1514,27 @@ int dso__load(struct dso *dso, struct map *map)
1509 pthread_mutex_lock(&dso->lock); 1514 pthread_mutex_lock(&dso->lock);
1510 1515
1511 /* check again under the dso->lock */ 1516 /* check again under the dso->lock */
1512 if (dso__loaded(dso, map->type)) { 1517 if (dso__loaded(dso)) {
1513 ret = 1; 1518 ret = 1;
1514 goto out; 1519 goto out;
1515 } 1520 }
1516 1521
1522 if (map->groups && map->groups->machine)
1523 machine = map->groups->machine;
1524 else
1525 machine = NULL;
1526
1517 if (dso->kernel) { 1527 if (dso->kernel) {
1518 if (dso->kernel == DSO_TYPE_KERNEL) 1528 if (dso->kernel == DSO_TYPE_KERNEL)
1519 ret = dso__load_kernel_sym(dso, map); 1529 ret = dso__load_kernel_sym(dso, map);
1520 else if (dso->kernel == DSO_TYPE_GUEST_KERNEL) 1530 else if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
1521 ret = dso__load_guest_kernel_sym(dso, map); 1531 ret = dso__load_guest_kernel_sym(dso, map);
1522 1532
1533 if (machine__is(machine, "x86_64"))
1534 machine__map_x86_64_entry_trampolines(machine, dso);
1523 goto out; 1535 goto out;
1524 } 1536 }
1525 1537
1526 if (map->groups && map->groups->machine)
1527 machine = map->groups->machine;
1528 else
1529 machine = NULL;
1530
1531 dso->adjust_symbols = 0; 1538 dso->adjust_symbols = 0;
1532 1539
1533 if (perfmap) { 1540 if (perfmap) {
@@ -1542,7 +1549,7 @@ int dso__load(struct dso *dso, struct map *map)
1542 goto out; 1549 goto out;
1543 } 1550 }
1544 1551
1545 ret = dso__load_perf_map(map_path, dso, map); 1552 ret = dso__load_perf_map(map_path, dso);
1546 dso->symtab_type = ret > 0 ? DSO_BINARY_TYPE__JAVA_JIT : 1553 dso->symtab_type = ret > 0 ? DSO_BINARY_TYPE__JAVA_JIT :
1547 DSO_BINARY_TYPE__NOT_FOUND; 1554 DSO_BINARY_TYPE__NOT_FOUND;
1548 goto out; 1555 goto out;
@@ -1651,7 +1658,7 @@ int dso__load(struct dso *dso, struct map *map)
1651 if (ret > 0) { 1658 if (ret > 0) {
1652 int nr_plt; 1659 int nr_plt;
1653 1660
1654 nr_plt = dso__synthesize_plt_symbols(dso, runtime_ss, map); 1661 nr_plt = dso__synthesize_plt_symbols(dso, runtime_ss);
1655 if (nr_plt > 0) 1662 if (nr_plt > 0)
1656 ret += nr_plt; 1663 ret += nr_plt;
1657 } 1664 }
@@ -1663,17 +1670,16 @@ out_free:
1663 if (ret < 0 && strstr(dso->name, " (deleted)") != NULL) 1670 if (ret < 0 && strstr(dso->name, " (deleted)") != NULL)
1664 ret = 0; 1671 ret = 0;
1665out: 1672out:
1666 dso__set_loaded(dso, map->type); 1673 dso__set_loaded(dso);
1667 pthread_mutex_unlock(&dso->lock); 1674 pthread_mutex_unlock(&dso->lock);
1668 nsinfo__mountns_exit(&nsc); 1675 nsinfo__mountns_exit(&nsc);
1669 1676
1670 return ret; 1677 return ret;
1671} 1678}
1672 1679
1673struct map *map_groups__find_by_name(struct map_groups *mg, 1680struct map *map_groups__find_by_name(struct map_groups *mg, const char *name)
1674 enum map_type type, const char *name)
1675{ 1681{
1676 struct maps *maps = &mg->maps[type]; 1682 struct maps *maps = &mg->maps;
1677 struct map *map; 1683 struct map *map;
1678 1684
1679 down_read(&maps->lock); 1685 down_read(&maps->lock);
@@ -1720,7 +1726,7 @@ int dso__load_vmlinux(struct dso *dso, struct map *map,
1720 else 1726 else
1721 dso->binary_type = DSO_BINARY_TYPE__VMLINUX; 1727 dso->binary_type = DSO_BINARY_TYPE__VMLINUX;
1722 dso__set_long_name(dso, vmlinux, vmlinux_allocated); 1728 dso__set_long_name(dso, vmlinux, vmlinux_allocated);
1723 dso__set_loaded(dso, map->type); 1729 dso__set_loaded(dso);
1724 pr_debug("Using %s for symbols\n", symfs_vmlinux); 1730 pr_debug("Using %s for symbols\n", symfs_vmlinux);
1725 } 1731 }
1726 1732
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 70c16741f50a..1a16438eb3ce 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -57,7 +57,8 @@ struct symbol {
57 u64 start; 57 u64 start;
58 u64 end; 58 u64 end;
59 u16 namelen; 59 u16 namelen;
60 u8 binding; 60 u8 type:4;
61 u8 binding:4;
61 u8 idle:1; 62 u8 idle:1;
62 u8 ignore:1; 63 u8 ignore:1;
63 u8 inlined:1; 64 u8 inlined:1;
@@ -259,17 +260,16 @@ int __dso__load_kallsyms(struct dso *dso, const char *filename, struct map *map,
259 bool no_kcore); 260 bool no_kcore);
260int dso__load_kallsyms(struct dso *dso, const char *filename, struct map *map); 261int dso__load_kallsyms(struct dso *dso, const char *filename, struct map *map);
261 262
262void dso__insert_symbol(struct dso *dso, enum map_type type, 263void dso__insert_symbol(struct dso *dso,
263 struct symbol *sym); 264 struct symbol *sym);
264 265
265struct symbol *dso__find_symbol(struct dso *dso, enum map_type type, 266struct symbol *dso__find_symbol(struct dso *dso, u64 addr);
266 u64 addr); 267struct symbol *dso__find_symbol_by_name(struct dso *dso, const char *name);
267struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, 268
268 const char *name);
269struct symbol *symbol__next_by_name(struct symbol *sym); 269struct symbol *symbol__next_by_name(struct symbol *sym);
270 270
271struct symbol *dso__first_symbol(struct dso *dso, enum map_type type); 271struct symbol *dso__first_symbol(struct dso *dso);
272struct symbol *dso__last_symbol(struct dso *dso, enum map_type type); 272struct symbol *dso__last_symbol(struct dso *dso);
273struct symbol *dso__next_symbol(struct symbol *sym); 273struct symbol *dso__next_symbol(struct symbol *sym);
274 274
275enum dso_type dso__type_fd(int fd); 275enum dso_type dso__type_fd(int fd);
@@ -288,7 +288,7 @@ void symbol__exit(void);
288void symbol__elf_init(void); 288void symbol__elf_init(void);
289int symbol__annotation_init(void); 289int symbol__annotation_init(void);
290 290
291struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name); 291struct symbol *symbol__new(u64 start, u64 len, u8 binding, u8 type, const char *name);
292size_t __symbol__fprintf_symname_offs(const struct symbol *sym, 292size_t __symbol__fprintf_symname_offs(const struct symbol *sym,
293 const struct addr_location *al, 293 const struct addr_location *al,
294 bool unknown_as_addr, 294 bool unknown_as_addr,
@@ -300,7 +300,6 @@ size_t __symbol__fprintf_symname(const struct symbol *sym,
300 bool unknown_as_addr, FILE *fp); 300 bool unknown_as_addr, FILE *fp);
301size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp); 301size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp);
302size_t symbol__fprintf(struct symbol *sym, FILE *fp); 302size_t symbol__fprintf(struct symbol *sym, FILE *fp);
303bool symbol_type__is_a(char symbol_type, enum map_type map_type);
304bool symbol__restricted_filename(const char *filename, 303bool symbol__restricted_filename(const char *filename,
305 const char *restricted_filename); 304 const char *restricted_filename);
306int symbol__config_symfs(const struct option *opt __maybe_unused, 305int symbol__config_symfs(const struct option *opt __maybe_unused,
@@ -308,8 +307,7 @@ int symbol__config_symfs(const struct option *opt __maybe_unused,
308 307
309int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss, 308int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss,
310 struct symsrc *runtime_ss, int kmodule); 309 struct symsrc *runtime_ss, int kmodule);
311int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, 310int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss);
312 struct map *map);
313 311
314char *dso__demangle_sym(struct dso *dso, int kmodule, const char *elf_name); 312char *dso__demangle_sym(struct dso *dso, int kmodule, const char *elf_name);
315 313
@@ -317,7 +315,7 @@ void __symbols__insert(struct rb_root *symbols, struct symbol *sym, bool kernel)
317void symbols__insert(struct rb_root *symbols, struct symbol *sym); 315void symbols__insert(struct rb_root *symbols, struct symbol *sym);
318void symbols__fixup_duplicate(struct rb_root *symbols); 316void symbols__fixup_duplicate(struct rb_root *symbols);
319void symbols__fixup_end(struct rb_root *symbols); 317void symbols__fixup_end(struct rb_root *symbols);
320void __map_groups__fixup_end(struct map_groups *mg, enum map_type type); 318void map_groups__fixup_end(struct map_groups *mg);
321 319
322typedef int (*mapfn_t)(u64 start, u64 len, u64 pgoff, void *data); 320typedef int (*mapfn_t)(u64 start, u64 len, u64 pgoff, void *data);
323int file__read_maps(int fd, bool exe, mapfn_t mapfn, void *data, 321int file__read_maps(int fd, bool exe, mapfn_t mapfn, void *data,
diff --git a/tools/perf/util/symbol_fprintf.c b/tools/perf/util/symbol_fprintf.c
index 6dd2cb88ccbe..ed0205cc7942 100644
--- a/tools/perf/util/symbol_fprintf.c
+++ b/tools/perf/util/symbol_fprintf.c
@@ -58,13 +58,13 @@ size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp)
58} 58}
59 59
60size_t dso__fprintf_symbols_by_name(struct dso *dso, 60size_t dso__fprintf_symbols_by_name(struct dso *dso,
61 enum map_type type, FILE *fp) 61 FILE *fp)
62{ 62{
63 size_t ret = 0; 63 size_t ret = 0;
64 struct rb_node *nd; 64 struct rb_node *nd;
65 struct symbol_name_rb_node *pos; 65 struct symbol_name_rb_node *pos;
66 66
67 for (nd = rb_first(&dso->symbol_names[type]); nd; nd = rb_next(nd)) { 67 for (nd = rb_first(&dso->symbol_names); nd; nd = rb_next(nd)) {
68 pos = rb_entry(nd, struct symbol_name_rb_node, rb_node); 68 pos = rb_entry(nd, struct symbol_name_rb_node, rb_node);
69 fprintf(fp, "%s\n", pos->sym.name); 69 fprintf(fp, "%s\n", pos->sym.name);
70 } 70 }
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 68b65b10579b..2048d393ece6 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -302,23 +302,20 @@ int thread__insert_map(struct thread *thread, struct map *map)
302static int __thread__prepare_access(struct thread *thread) 302static int __thread__prepare_access(struct thread *thread)
303{ 303{
304 bool initialized = false; 304 bool initialized = false;
305 int i, err = 0; 305 int err = 0;
306 306 struct maps *maps = &thread->mg->maps;
307 for (i = 0; i < MAP__NR_TYPES; ++i) { 307 struct map *map;
308 struct maps *maps = &thread->mg->maps[i];
309 struct map *map;
310 308
311 down_read(&maps->lock); 309 down_read(&maps->lock);
312 310
313 for (map = maps__first(maps); map; map = map__next(map)) { 311 for (map = maps__first(maps); map; map = map__next(map)) {
314 err = unwind__prepare_access(thread, map, &initialized); 312 err = unwind__prepare_access(thread, map, &initialized);
315 if (err || initialized) 313 if (err || initialized)
316 break; 314 break;
317 }
318
319 up_read(&maps->lock);
320 } 315 }
321 316
317 up_read(&maps->lock);
318
322 return err; 319 return err;
323} 320}
324 321
@@ -335,8 +332,6 @@ static int thread__prepare_access(struct thread *thread)
335static int thread__clone_map_groups(struct thread *thread, 332static int thread__clone_map_groups(struct thread *thread,
336 struct thread *parent) 333 struct thread *parent)
337{ 334{
338 int i;
339
340 /* This is new thread, we share map groups for process. */ 335 /* This is new thread, we share map groups for process. */
341 if (thread->pid_ == parent->pid_) 336 if (thread->pid_ == parent->pid_)
342 return thread__prepare_access(thread); 337 return thread__prepare_access(thread);
@@ -348,9 +343,8 @@ static int thread__clone_map_groups(struct thread *thread,
348 } 343 }
349 344
350 /* But this one is new process, copy maps. */ 345 /* But this one is new process, copy maps. */
351 for (i = 0; i < MAP__NR_TYPES; ++i) 346 if (map_groups__clone(thread, parent->mg) < 0)
352 if (map_groups__clone(thread, parent->mg, i) < 0) 347 return -ENOMEM;
353 return -ENOMEM;
354 348
355 return 0; 349 return 0;
356} 350}
@@ -371,8 +365,7 @@ int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp)
371 return thread__clone_map_groups(thread, parent); 365 return thread__clone_map_groups(thread, parent);
372} 366}
373 367
374void thread__find_cpumode_addr_location(struct thread *thread, 368void thread__find_cpumode_addr_location(struct thread *thread, u64 addr,
375 enum map_type type, u64 addr,
376 struct addr_location *al) 369 struct addr_location *al)
377{ 370{
378 size_t i; 371 size_t i;
@@ -384,7 +377,7 @@ void thread__find_cpumode_addr_location(struct thread *thread,
384 }; 377 };
385 378
386 for (i = 0; i < ARRAY_SIZE(cpumodes); i++) { 379 for (i = 0; i < ARRAY_SIZE(cpumodes); i++) {
387 thread__find_addr_location(thread, cpumodes[i], type, addr, al); 380 thread__find_symbol(thread, cpumodes[i], addr, al);
388 if (al->map) 381 if (al->map)
389 break; 382 break;
390 } 383 }
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 14d44c3235b8..07606aa6998d 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -92,16 +92,13 @@ size_t thread__fprintf(struct thread *thread, FILE *fp);
92 92
93struct thread *thread__main_thread(struct machine *machine, struct thread *thread); 93struct thread *thread__main_thread(struct machine *machine, struct thread *thread);
94 94
95void thread__find_addr_map(struct thread *thread, 95struct map *thread__find_map(struct thread *thread, u8 cpumode, u64 addr,
96 u8 cpumode, enum map_type type, u64 addr, 96 struct addr_location *al);
97 struct addr_location *al);
98 97
99void thread__find_addr_location(struct thread *thread, 98struct symbol *thread__find_symbol(struct thread *thread, u8 cpumode,
100 u8 cpumode, enum map_type type, u64 addr, 99 u64 addr, struct addr_location *al);
101 struct addr_location *al);
102 100
103void thread__find_cpumode_addr_location(struct thread *thread, 101void thread__find_cpumode_addr_location(struct thread *thread, u64 addr,
104 enum map_type type, u64 addr,
105 struct addr_location *al); 102 struct addr_location *al);
106 103
107static inline void *thread__priv(struct thread *thread) 104static inline void *thread__priv(struct thread *thread)
diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c
index d7f2113462fb..c85d0d1a65ed 100644
--- a/tools/perf/util/trace-event-info.c
+++ b/tools/perf/util/trace-event-info.c
@@ -103,11 +103,10 @@ out:
103 103
104static int record_header_files(void) 104static int record_header_files(void)
105{ 105{
106 char *path; 106 char *path = get_events_file("header_page");
107 struct stat st; 107 struct stat st;
108 int err = -EIO; 108 int err = -EIO;
109 109
110 path = get_tracing_file("events/header_page");
111 if (!path) { 110 if (!path) {
112 pr_debug("can't get tracing/events/header_page"); 111 pr_debug("can't get tracing/events/header_page");
113 return -ENOMEM; 112 return -ENOMEM;
@@ -128,9 +127,9 @@ static int record_header_files(void)
128 goto out; 127 goto out;
129 } 128 }
130 129
131 put_tracing_file(path); 130 put_events_file(path);
132 131
133 path = get_tracing_file("events/header_event"); 132 path = get_events_file("header_event");
134 if (!path) { 133 if (!path) {
135 pr_debug("can't get tracing/events/header_event"); 134 pr_debug("can't get tracing/events/header_event");
136 err = -ENOMEM; 135 err = -ENOMEM;
@@ -154,7 +153,7 @@ static int record_header_files(void)
154 153
155 err = 0; 154 err = 0;
156out: 155out:
157 put_tracing_file(path); 156 put_events_file(path);
158 return err; 157 return err;
159} 158}
160 159
@@ -243,7 +242,7 @@ static int record_ftrace_files(struct tracepoint_path *tps)
243 char *path; 242 char *path;
244 int ret; 243 int ret;
245 244
246 path = get_tracing_file("events/ftrace"); 245 path = get_events_file("ftrace");
247 if (!path) { 246 if (!path) {
248 pr_debug("can't get tracing/events/ftrace"); 247 pr_debug("can't get tracing/events/ftrace");
249 return -ENOMEM; 248 return -ENOMEM;
diff --git a/tools/perf/util/trace-event.c b/tools/perf/util/trace-event.c
index 16a776371d03..1aa368603268 100644
--- a/tools/perf/util/trace-event.c
+++ b/tools/perf/util/trace-event.c
@@ -75,6 +75,7 @@ void trace_event__cleanup(struct trace_event *t)
75static struct event_format* 75static struct event_format*
76tp_format(const char *sys, const char *name) 76tp_format(const char *sys, const char *name)
77{ 77{
78 char *tp_dir = get_events_file(sys);
78 struct pevent *pevent = tevent.pevent; 79 struct pevent *pevent = tevent.pevent;
79 struct event_format *event = NULL; 80 struct event_format *event = NULL;
80 char path[PATH_MAX]; 81 char path[PATH_MAX];
@@ -82,8 +83,11 @@ tp_format(const char *sys, const char *name)
82 char *data; 83 char *data;
83 int err; 84 int err;
84 85
85 scnprintf(path, PATH_MAX, "%s/%s/%s/format", 86 if (!tp_dir)
86 tracing_events_path, sys, name); 87 return ERR_PTR(-errno);
88
89 scnprintf(path, PATH_MAX, "%s/%s/format", tp_dir, name);
90 put_events_file(tp_dir);
87 91
88 err = filename__read_str(path, &data, &size); 92 err = filename__read_str(path, &data, &size);
89 if (err) 93 if (err)
diff --git a/tools/perf/util/unwind-libdw.c b/tools/perf/util/unwind-libdw.c
index 7bdd239c795c..538db4e5d1e6 100644
--- a/tools/perf/util/unwind-libdw.c
+++ b/tools/perf/util/unwind-libdw.c
@@ -28,10 +28,11 @@ static int __report_module(struct addr_location *al, u64 ip,
28{ 28{
29 Dwfl_Module *mod; 29 Dwfl_Module *mod;
30 struct dso *dso = NULL; 30 struct dso *dso = NULL;
31 31 /*
32 thread__find_addr_location(ui->thread, 32 * Some callers will use al->sym, so we can't just use the
33 PERF_RECORD_MISC_USER, 33 * cheaper thread__find_map() here.
34 MAP__FUNCTION, ip, al); 34 */
35 thread__find_symbol(ui->thread, PERF_RECORD_MISC_USER, ip, al);
35 36
36 if (al->map) 37 if (al->map)
37 dso = al->map->dso; 38 dso = al->map->dso;
@@ -103,19 +104,7 @@ static int access_dso_mem(struct unwind_info *ui, Dwarf_Addr addr,
103 struct addr_location al; 104 struct addr_location al;
104 ssize_t size; 105 ssize_t size;
105 106
106 thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER, 107 if (!thread__find_map(ui->thread, PERF_RECORD_MISC_USER, addr, &al)) {
107 MAP__FUNCTION, addr, &al);
108 if (!al.map) {
109 /*
110 * We've seen cases (softice) where DWARF unwinder went
111 * through non executable mmaps, which we need to lookup
112 * in MAP__VARIABLE tree.
113 */
114 thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER,
115 MAP__VARIABLE, addr, &al);
116 }
117
118 if (!al.map) {
119 pr_debug("unwind: no map for %lx\n", (unsigned long)addr); 108 pr_debug("unwind: no map for %lx\n", (unsigned long)addr);
120 return -1; 109 return -1;
121 } 110 }
diff --git a/tools/perf/util/unwind-libunwind-local.c b/tools/perf/util/unwind-libunwind-local.c
index af873044d33a..6a11bc7e6b27 100644
--- a/tools/perf/util/unwind-libunwind-local.c
+++ b/tools/perf/util/unwind-libunwind-local.c
@@ -366,19 +366,7 @@ static int read_unwind_spec_debug_frame(struct dso *dso,
366static struct map *find_map(unw_word_t ip, struct unwind_info *ui) 366static struct map *find_map(unw_word_t ip, struct unwind_info *ui)
367{ 367{
368 struct addr_location al; 368 struct addr_location al;
369 369 return thread__find_map(ui->thread, PERF_RECORD_MISC_USER, ip, &al);
370 thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER,
371 MAP__FUNCTION, ip, &al);
372 if (!al.map) {
373 /*
374 * We've seen cases (softice) where DWARF unwinder went
375 * through non executable mmaps, which we need to lookup
376 * in MAP__VARIABLE tree.
377 */
378 thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER,
379 MAP__VARIABLE, ip, &al);
380 }
381 return al.map;
382} 370}
383 371
384static int 372static int
@@ -586,12 +574,9 @@ static int entry(u64 ip, struct thread *thread,
586 struct unwind_entry e; 574 struct unwind_entry e;
587 struct addr_location al; 575 struct addr_location al;
588 576
589 thread__find_addr_location(thread, PERF_RECORD_MISC_USER, 577 e.sym = thread__find_symbol(thread, PERF_RECORD_MISC_USER, ip, &al);
590 MAP__FUNCTION, ip, &al);
591
592 e.ip = al.addr; 578 e.ip = al.addr;
593 e.map = al.map; 579 e.map = al.map;
594 e.sym = al.sym;
595 580
596 pr_debug("unwind: %s:ip = 0x%" PRIx64 " (0x%" PRIx64 ")\n", 581 pr_debug("unwind: %s:ip = 0x%" PRIx64 " (0x%" PRIx64 ")\n",
597 al.sym ? al.sym->name : "''", 582 al.sym ? al.sym->name : "''",
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 1019bbc5dbd8..eac5b858a371 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -38,11 +38,43 @@ void perf_set_multithreaded(void)
38} 38}
39 39
40unsigned int page_size; 40unsigned int page_size;
41int cacheline_size; 41
42#ifdef _SC_LEVEL1_DCACHE_LINESIZE
43#define cache_line_size(cacheline_sizep) *cacheline_sizep = sysconf(_SC_LEVEL1_DCACHE_LINESIZE)
44#else
45static void cache_line_size(int *cacheline_sizep)
46{
47 if (sysfs__read_int("devices/system/cpu/cpu0/cache/index0/coherency_line_size", cacheline_sizep))
48 pr_debug("cannot determine cache line size");
49}
50#endif
51
52int cacheline_size(void)
53{
54 static int size;
55
56 if (!size)
57 cache_line_size(&size);
58
59 return size;
60}
42 61
43int sysctl_perf_event_max_stack = PERF_MAX_STACK_DEPTH; 62int sysctl_perf_event_max_stack = PERF_MAX_STACK_DEPTH;
44int sysctl_perf_event_max_contexts_per_stack = PERF_MAX_CONTEXTS_PER_STACK; 63int sysctl_perf_event_max_contexts_per_stack = PERF_MAX_CONTEXTS_PER_STACK;
45 64
65int sysctl__max_stack(void)
66{
67 int value;
68
69 if (sysctl__read_int("kernel/perf_event_max_stack", &value) == 0)
70 sysctl_perf_event_max_stack = value;
71
72 if (sysctl__read_int("kernel/perf_event_max_contexts_per_stack", &value) == 0)
73 sysctl_perf_event_max_contexts_per_stack = value;
74
75 return sysctl_perf_event_max_stack;
76}
77
46bool test_attr__enabled; 78bool test_attr__enabled;
47 79
48bool perf_host = true; 80bool perf_host = true;
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index c9626c206208..dc58254a2b69 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -43,7 +43,9 @@ size_t hex_width(u64 v);
43int hex2u64(const char *ptr, u64 *val); 43int hex2u64(const char *ptr, u64 *val);
44 44
45extern unsigned int page_size; 45extern unsigned int page_size;
46extern int cacheline_size; 46int __pure cacheline_size(void);
47
48int sysctl__max_stack(void);
47 49
48int fetch_kernel_version(unsigned int *puint, 50int fetch_kernel_version(unsigned int *puint,
49 char *str, size_t str_sz); 51 char *str, size_t str_sz);
diff --git a/tools/perf/util/vdso.c b/tools/perf/util/vdso.c
index 0acb1ec0e2f0..741af209b19d 100644
--- a/tools/perf/util/vdso.c
+++ b/tools/perf/util/vdso.c
@@ -139,12 +139,10 @@ static enum dso_type machine__thread_dso_type(struct machine *machine,
139 struct thread *thread) 139 struct thread *thread)
140{ 140{
141 enum dso_type dso_type = DSO__TYPE_UNKNOWN; 141 enum dso_type dso_type = DSO__TYPE_UNKNOWN;
142 struct map *map; 142 struct map *map = map_groups__first(thread->mg);
143 struct dso *dso;
144 143
145 map = map_groups__first(thread->mg, MAP__FUNCTION);
146 for (; map ; map = map_groups__next(map)) { 144 for (; map ; map = map_groups__next(map)) {
147 dso = map->dso; 145 struct dso *dso = map->dso;
148 if (!dso || dso->long_name[0] != '/') 146 if (!dso || dso->long_name[0] != '/')
149 continue; 147 continue;
150 dso_type = dso__type(dso, machine); 148 dso_type = dso__type(dso, machine);