diff options
| author | Ingo Molnar <mingo@kernel.org> | 2018-05-02 13:36:19 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@kernel.org> | 2018-05-02 13:36:19 -0400 |
| commit | eaeb1f4d892936133c5f8d3aafb36b7f384fe59c (patch) | |
| tree | 6829eabc8ba773559d8a8b018c779664c978e58e | |
| parent | 2d618bdf71635463a4aa4ad0fe46ec852292bc0c (diff) | |
| parent | 107cad95ffd81afad295ed5c29d006e525f1f80f (diff) | |
Merge tag 'perf-core-for-mingo-4.18-20180502' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:
perf stat: (Jiri Olsa)
- Display time in precision based on std deviation
- Add --table option to display time of each run
- Display length strings of each run for --table option
perf buildid-cache: (Ravi Bangoria)
- Add --list and --purge-all options
perf test: (Hendrik Brueckner)
- Let 'perf test list' display subtests
Core libraries:
- Remove the splitting of maps into MAP__FUNCTION and MAP__VARIABLE.
It isn't needed, adds complexity, so remove this split in a very granular
fashion using better ways of detecting if a map is executable, using map->prot,
etc. More is needed to further untangle map aspects from DSO ones and
also to have arch specific stuff better isolated. (Arnaldo Carvalho de Melo)
- Fix spelling mistake: "builid" -> "buildid" in a jitdump error
message (Colin Ian King)
Build system: (Jiri Olsa)
- Add support to check 2 independent files in check-headers.sh
Documentation: (Takashi Iwai)
- Support for asciidoctor, since 'asciidoc' wasn't so far ported to
python3 and distros are ditching python2
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
59 files changed, 794 insertions, 813 deletions
diff --git a/tools/lib/symbol/kallsyms.c b/tools/lib/symbol/kallsyms.c index 689b6a130dd7..96d830545bbb 100644 --- a/tools/lib/symbol/kallsyms.c +++ b/tools/lib/symbol/kallsyms.c | |||
| @@ -10,6 +10,12 @@ u8 kallsyms2elf_type(char type) | |||
| 10 | return (type == 't' || type == 'w') ? STT_FUNC : STT_OBJECT; | 10 | return (type == 't' || type == 'w') ? STT_FUNC : STT_OBJECT; |
| 11 | } | 11 | } |
| 12 | 12 | ||
| 13 | bool kallsyms__is_function(char symbol_type) | ||
| 14 | { | ||
| 15 | symbol_type = toupper(symbol_type); | ||
| 16 | return symbol_type == 'T' || symbol_type == 'W'; | ||
| 17 | } | ||
| 18 | |||
| 13 | int kallsyms__parse(const char *filename, void *arg, | 19 | int kallsyms__parse(const char *filename, void *arg, |
| 14 | int (*process_symbol)(void *arg, const char *name, | 20 | int (*process_symbol)(void *arg, const char *name, |
| 15 | char type, u64 start)) | 21 | char type, u64 start)) |
diff --git a/tools/lib/symbol/kallsyms.h b/tools/lib/symbol/kallsyms.h index bc40101d72c1..72ab9870454b 100644 --- a/tools/lib/symbol/kallsyms.h +++ b/tools/lib/symbol/kallsyms.h | |||
| @@ -20,6 +20,8 @@ static inline u8 kallsyms2elf_binding(char type) | |||
| 20 | 20 | ||
| 21 | u8 kallsyms2elf_type(char type); | 21 | u8 kallsyms2elf_type(char type); |
| 22 | 22 | ||
| 23 | bool kallsyms__is_function(char symbol_type); | ||
| 24 | |||
| 23 | int kallsyms__parse(const char *filename, void *arg, | 25 | int kallsyms__parse(const char *filename, void *arg, |
| 24 | int (*process_symbol)(void *arg, const char *name, | 26 | int (*process_symbol)(void *arg, const char *name, |
| 25 | char type, u64 start)); | 27 | char type, u64 start)); |
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 | |||
| 47 | man7dir=$(mandir)/man7 | 47 | man7dir=$(mandir)/man7 |
| 48 | 48 | ||
| 49 | ASCIIDOC=asciidoc | 49 | ASCIIDOC=asciidoc |
| 50 | ASCIIDOC_EXTRA = --unsafe | 50 | ASCIIDOC_EXTRA = --unsafe -f asciidoc.conf |
| 51 | ASCIIDOC_HTML = xhtml11 | ||
| 51 | MANPAGE_XSL = manpage-normal.xsl | 52 | MANPAGE_XSL = manpage-normal.xsl |
| 52 | XMLTO_EXTRA = | 53 | XMLTO_EXTRA = |
| 53 | INSTALL?=install | 54 | INSTALL?=install |
| @@ -55,6 +56,14 @@ RM ?= rm -f | |||
| 55 | DOC_REF = origin/man | 56 | DOC_REF = origin/man |
| 56 | HTML_REF = origin/html | 57 | HTML_REF = origin/html |
| 57 | 58 | ||
| 59 | ifdef USE_ASCIIDOCTOR | ||
| 60 | ASCIIDOC = asciidoctor | ||
| 61 | ASCIIDOC_EXTRA = -a compat-mode | ||
| 62 | ASCIIDOC_EXTRA += -I. -rasciidoctor-extensions | ||
| 63 | ASCIIDOC_EXTRA += -a mansource="perf" -a manmanual="perf Manual" | ||
| 64 | ASCIIDOC_HTML = xhtml5 | ||
| 65 | endif | ||
| 66 | |||
| 58 | infodir?=$(prefix)/share/info | 67 | infodir?=$(prefix)/share/info |
| 59 | MAKEINFO=makeinfo | 68 | MAKEINFO=makeinfo |
| 60 | INSTALL_INFO=install-info | 69 | INSTALL_INFO=install-info |
| @@ -73,10 +82,12 @@ ifeq ($(_tmp_tool_path),) | |||
| 73 | missing_tools = $(ASCIIDOC) | 82 | missing_tools = $(ASCIIDOC) |
| 74 | endif | 83 | endif |
| 75 | 84 | ||
| 85 | ifndef USE_ASCIIDOCTOR | ||
| 76 | _tmp_tool_path := $(call get-executable,$(XMLTO)) | 86 | _tmp_tool_path := $(call get-executable,$(XMLTO)) |
| 77 | ifeq ($(_tmp_tool_path),) | 87 | ifeq ($(_tmp_tool_path),) |
| 78 | missing_tools += $(XMLTO) | 88 | missing_tools += $(XMLTO) |
| 79 | endif | 89 | endif |
| 90 | endif | ||
| 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 | |||
| 282 | ifdef 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 $@+ $@ |
| 288 | endif | ||
| 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 | ||
| 326 | WEBDOC_DEST = /pub/software/tools/perf/docs | 345 | WEBDOC_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 @@ | |||
| 1 | require 'asciidoctor' | ||
| 2 | require 'asciidoctor/extensions' | ||
| 3 | |||
| 4 | module 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 | ||
| 25 | end | ||
| 26 | |||
| 27 | Asciidoctor::Extensions.register do | ||
| 28 | inline_macro Perf::Documentation::LinkPerfProcessor, :linkperf | ||
| 29 | end | ||
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-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. | |||
| 116 | print counts using a CSV-style output to make it easy to import directly into | 116 | print counts using a CSV-style output to make it easy to import directly into |
| 117 | spreadsheets. Columns are separated by the string specified in SEP. | 117 | spreadsheets. 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:: |
| 121 | monitor only in the container (cgroup) called "name". This option is available only | 137 | monitor only in the container (cgroup) called "name". This option is available only |
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/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/builtin-annotate.c b/tools/perf/builtin-annotate.c index 51709a961496..6e5d9f718154 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c | |||
| @@ -228,7 +228,7 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel, | |||
| 228 | */ | 228 | */ |
| 229 | if (al->sym != NULL) { | 229 | if (al->sym != NULL) { |
| 230 | rb_erase(&al->sym->rb_node, | 230 | rb_erase(&al->sym->rb_node, |
| 231 | &al->map->dso->symbols[al->map->type]); | 231 | &al->map->dso->symbols); |
| 232 | symbol__delete(al->sym); | 232 | symbol__delete(al->sym); |
| 233 | dso__reset_find_symbol_cache(al->map->dso); | 233 | dso__reset_find_symbol_cache(al->map->dso); |
| 234 | } | 234 | } |
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c index 41db2cba77eb..7a7403913b57 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 | ||
| 29 | static int build_id_cache__kcore_buildid(const char *proc_dir, char *sbuildid) | 30 | static 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 | ||
| 243 | static 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 | |||
| 242 | static bool dso__missing_buildid_cache(struct dso *dso, int parm __maybe_unused) | 271 | static 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 | ||
| 329 | static 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 | |||
| 300 | int cmd_buildid_cache(int argc, const char **argv) | 349 | int 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,9 @@ int cmd_buildid_cache(int argc, const char **argv) | |||
| 420 | } | 488 | } |
| 421 | } | 489 | } |
| 422 | 490 | ||
| 491 | if (purge_all) | ||
| 492 | ret = build_id_cache__purge_all(); | ||
| 493 | |||
| 423 | if (missing_filename) | 494 | if (missing_filename) |
| 424 | ret = build_id_cache__fprintf_missing(session, stdout); | 495 | ret = build_id_cache__fprintf_missing(session, stdout); |
| 425 | 496 | ||
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..4c931afb2e80 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
| @@ -523,12 +523,9 @@ static void report__warn_kptr_restrict(const struct report *rep) | |||
| 523 | "As no suitable kallsyms nor vmlinux was found, kernel samples\n" | 523 | "As no suitable kallsyms nor vmlinux was found, kernel samples\n" |
| 524 | "can't be resolved."; | 524 | "can't be resolved."; |
| 525 | 525 | ||
| 526 | if (kernel_map) { | 526 | if (kernel_map && map__has_symbols(kernel_map)) { |
| 527 | const struct dso *kdso = kernel_map->dso; | 527 | desc = "If some relocation was applied (e.g. " |
| 528 | if (!RB_EMPTY_ROOT(&kdso->symbols[MAP__FUNCTION])) { | 528 | "kexec) symbols may be misresolved."; |
| 529 | desc = "If some relocation was applied (e.g. " | ||
| 530 | "kexec) symbols may be misresolved."; | ||
| 531 | } | ||
| 532 | } | 529 | } |
| 533 | 530 | ||
| 534 | ui__warning( | 531 | ui__warning( |
| @@ -718,10 +715,7 @@ static size_t maps__fprintf_task(struct maps *maps, int indent, FILE *fp) | |||
| 718 | 715 | ||
| 719 | static int map_groups__fprintf_task(struct map_groups *mg, int indent, FILE *fp) | 716 | static int map_groups__fprintf_task(struct map_groups *mg, int indent, FILE *fp) |
| 720 | { | 717 | { |
| 721 | int printed = 0, i; | 718 | 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 | } | 719 | } |
| 726 | 720 | ||
| 727 | static void task__print_level(struct task *task, FILE *fp, int level) | 721 | static 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..fa2c7a288750 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c | |||
| @@ -717,8 +717,8 @@ static int perf_sample__fprintf_brstack(struct perf_sample *sample, | |||
| 717 | if (PRINT_FIELD(DSO)) { | 717 | if (PRINT_FIELD(DSO)) { |
| 718 | memset(&alf, 0, sizeof(alf)); | 718 | memset(&alf, 0, sizeof(alf)); |
| 719 | memset(&alt, 0, sizeof(alt)); | 719 | memset(&alt, 0, sizeof(alt)); |
| 720 | thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, from, &alf); | 720 | thread__find_map(thread, sample->cpumode, from, &alf); |
| 721 | thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, to, &alt); | 721 | thread__find_map(thread, sample->cpumode, to, &alt); |
| 722 | } | 722 | } |
| 723 | 723 | ||
| 724 | printed += fprintf(fp, " 0x%"PRIx64, from); | 724 | printed += fprintf(fp, " 0x%"PRIx64, from); |
| @@ -764,13 +764,8 @@ static int perf_sample__fprintf_brstacksym(struct perf_sample *sample, | |||
| 764 | from = br->entries[i].from; | 764 | from = br->entries[i].from; |
| 765 | to = br->entries[i].to; | 765 | to = br->entries[i].to; |
| 766 | 766 | ||
| 767 | thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, from, &alf); | 767 | thread__find_symbol(thread, sample->cpumode, from, &alf); |
| 768 | if (alf.map) | 768 | 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 | 769 | ||
| 775 | printed += symbol__fprintf_symname_offs(alf.sym, &alf, fp); | 770 | printed += symbol__fprintf_symname_offs(alf.sym, &alf, fp); |
| 776 | if (PRINT_FIELD(DSO)) { | 771 | if (PRINT_FIELD(DSO)) { |
| @@ -814,12 +809,12 @@ static int perf_sample__fprintf_brstackoff(struct perf_sample *sample, | |||
| 814 | from = br->entries[i].from; | 809 | from = br->entries[i].from; |
| 815 | to = br->entries[i].to; | 810 | to = br->entries[i].to; |
| 816 | 811 | ||
| 817 | thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, from, &alf); | 812 | if (thread__find_map(thread, sample->cpumode, from, &alf) && |
| 818 | if (alf.map && !alf.map->dso->adjust_symbols) | 813 | !alf.map->dso->adjust_symbols) |
| 819 | from = map__map_ip(alf.map, from); | 814 | from = map__map_ip(alf.map, from); |
| 820 | 815 | ||
| 821 | thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, to, &alt); | 816 | if (thread__find_map(thread, sample->cpumode, to, &alt) && |
| 822 | if (alt.map && !alt.map->dso->adjust_symbols) | 817 | !alt.map->dso->adjust_symbols) |
| 823 | to = map__map_ip(alt.map, to); | 818 | to = map__map_ip(alt.map, to); |
| 824 | 819 | ||
| 825 | printed += fprintf(fp, " 0x%"PRIx64, from); | 820 | printed += fprintf(fp, " 0x%"PRIx64, from); |
| @@ -882,8 +877,7 @@ static int grab_bb(u8 *buffer, u64 start, u64 end, | |||
| 882 | return 0; | 877 | return 0; |
| 883 | } | 878 | } |
| 884 | 879 | ||
| 885 | thread__find_addr_map(thread, *cpumode, MAP__FUNCTION, start, &al); | 880 | 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); | 881 | pr_debug("\tcannot resolve %" PRIx64 "-%" PRIx64 "\n", start, end); |
| 888 | return 0; | 882 | return 0; |
| 889 | } | 883 | } |
| @@ -933,10 +927,8 @@ static int ip__fprintf_sym(uint64_t addr, struct thread *thread, | |||
| 933 | 927 | ||
| 934 | memset(&al, 0, sizeof(al)); | 928 | memset(&al, 0, sizeof(al)); |
| 935 | 929 | ||
| 936 | thread__find_addr_map(thread, cpumode, MAP__FUNCTION, addr, &al); | 930 | thread__find_map(thread, cpumode, addr, &al); |
| 937 | if (!al.map) | 931 | |
| 938 | thread__find_addr_map(thread, cpumode, MAP__VARIABLE, | ||
| 939 | addr, &al); | ||
| 940 | if ((*lastsym) && al.addr >= (*lastsym)->start && al.addr < (*lastsym)->end) | 932 | if ((*lastsym) && al.addr >= (*lastsym)->start && al.addr < (*lastsym)->end) |
| 941 | return 0; | 933 | return 0; |
| 942 | 934 | ||
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index f17dc601b0f3..a4f662a462c6 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c | |||
| @@ -164,6 +164,7 @@ static bool forever = false; | |||
| 164 | static bool metric_only = false; | 164 | static bool metric_only = false; |
| 165 | static bool force_metric_only = false; | 165 | static bool force_metric_only = false; |
| 166 | static bool no_merge = false; | 166 | static bool no_merge = false; |
| 167 | static bool walltime_run_table = false; | ||
| 167 | static struct timespec ref_time; | 168 | static struct timespec ref_time; |
| 168 | static struct cpu_map *aggr_map; | 169 | static struct cpu_map *aggr_map; |
| 169 | static aggr_get_id_t aggr_get_id; | 170 | static aggr_get_id_t aggr_get_id; |
| @@ -173,6 +174,7 @@ static const char *output_name; | |||
| 173 | static int output_fd; | 174 | static int output_fd; |
| 174 | static int print_free_counters_hint; | 175 | static int print_free_counters_hint; |
| 175 | static int print_mixed_hw_group_error; | 176 | static int print_mixed_hw_group_error; |
| 177 | static u64 *walltime_run; | ||
| 176 | 178 | ||
| 177 | struct perf_stat { | 179 | struct perf_stat { |
| 178 | bool record; | 180 | bool record; |
| @@ -569,7 +571,7 @@ static struct perf_evsel *perf_evsel__reset_weak_group(struct perf_evsel *evsel) | |||
| 569 | return leader; | 571 | return leader; |
| 570 | } | 572 | } |
| 571 | 573 | ||
| 572 | static int __run_perf_stat(int argc, const char **argv) | 574 | static int __run_perf_stat(int argc, const char **argv, int run_idx) |
| 573 | { | 575 | { |
| 574 | int interval = stat_config.interval; | 576 | int interval = stat_config.interval; |
| 575 | int times = stat_config.times; | 577 | int times = stat_config.times; |
| @@ -752,6 +754,9 @@ try_again: | |||
| 752 | 754 | ||
| 753 | t1 = rdclock(); | 755 | t1 = rdclock(); |
| 754 | 756 | ||
| 757 | if (walltime_run_table) | ||
| 758 | walltime_run[run_idx] = t1 - t0; | ||
| 759 | |||
| 755 | update_stats(&walltime_nsecs_stats, t1 - t0); | 760 | update_stats(&walltime_nsecs_stats, t1 - t0); |
| 756 | 761 | ||
| 757 | /* | 762 | /* |
| @@ -766,7 +771,7 @@ try_again: | |||
| 766 | return WEXITSTATUS(status); | 771 | return WEXITSTATUS(status); |
| 767 | } | 772 | } |
| 768 | 773 | ||
| 769 | static int run_perf_stat(int argc, const char **argv) | 774 | static int run_perf_stat(int argc, const char **argv, int run_idx) |
| 770 | { | 775 | { |
| 771 | int ret; | 776 | int ret; |
| 772 | 777 | ||
| @@ -779,7 +784,7 @@ static int run_perf_stat(int argc, const char **argv) | |||
| 779 | if (sync_run) | 784 | if (sync_run) |
| 780 | sync(); | 785 | sync(); |
| 781 | 786 | ||
| 782 | ret = __run_perf_stat(argc, argv); | 787 | ret = __run_perf_stat(argc, argv, run_idx); |
| 783 | if (ret) | 788 | if (ret) |
| 784 | return ret; | 789 | return ret; |
| 785 | 790 | ||
| @@ -1764,19 +1769,67 @@ static void print_header(int argc, const char **argv) | |||
| 1764 | } | 1769 | } |
| 1765 | } | 1770 | } |
| 1766 | 1771 | ||
| 1772 | static int get_precision(double num) | ||
| 1773 | { | ||
| 1774 | if (num > 1) | ||
| 1775 | return 0; | ||
| 1776 | |||
| 1777 | return lround(ceil(-log10(num))); | ||
| 1778 | } | ||
| 1779 | |||
| 1780 | static 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 | |||
| 1767 | static void print_footer(void) | 1807 | static void print_footer(void) |
| 1768 | { | 1808 | { |
| 1809 | double avg = avg_stats(&walltime_nsecs_stats) / NSEC_PER_SEC; | ||
| 1769 | FILE *output = stat_config.output; | 1810 | FILE *output = stat_config.output; |
| 1770 | int n; | 1811 | int n; |
| 1771 | 1812 | ||
| 1772 | if (!null_run) | 1813 | if (!null_run) |
| 1773 | fprintf(output, "\n"); | 1814 | fprintf(output, "\n"); |
| 1774 | fprintf(output, " %17.9f seconds time elapsed", | 1815 | |
| 1775 | avg_stats(&walltime_nsecs_stats) / NSEC_PER_SEC); | 1816 | if (run_count == 1) { |
| 1776 | if (run_count > 1) { | 1817 | fprintf(output, " %17.9f seconds time elapsed", avg); |
| 1777 | fprintf(output, " "); | 1818 | } else { |
| 1778 | print_noise_pct(stddev_stats(&walltime_nsecs_stats), | 1819 | double sd = stddev_stats(&walltime_nsecs_stats) / NSEC_PER_SEC; |
| 1779 | 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); | ||
| 1780 | } | 1833 | } |
| 1781 | fprintf(output, "\n\n"); | 1834 | fprintf(output, "\n\n"); |
| 1782 | 1835 | ||
| @@ -1952,6 +2005,8 @@ static const struct option stat_options[] = { | |||
| 1952 | "be more verbose (show counter open errors, etc)"), | 2005 | "be more verbose (show counter open errors, etc)"), |
| 1953 | OPT_INTEGER('r', "repeat", &run_count, | 2006 | OPT_INTEGER('r', "repeat", &run_count, |
| 1954 | "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)"), | ||
| 1955 | OPT_BOOLEAN('n', "null", &null_run, | 2010 | OPT_BOOLEAN('n', "null", &null_run, |
| 1956 | "null run - dont start any counters"), | 2011 | "null run - dont start any counters"), |
| 1957 | OPT_INCR('d', "detailed", &detailed_run, | 2012 | OPT_INCR('d', "detailed", &detailed_run, |
| @@ -2843,6 +2898,13 @@ int cmd_stat(int argc, const char **argv) | |||
| 2843 | goto out; | 2898 | goto out; |
| 2844 | } | 2899 | } |
| 2845 | 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 | |||
| 2846 | if (output_fd < 0) { | 2908 | if (output_fd < 0) { |
| 2847 | fprintf(stderr, "argument to --log-fd must be a > 0\n"); | 2909 | fprintf(stderr, "argument to --log-fd must be a > 0\n"); |
| 2848 | parse_options_usage(stat_usage, stat_options, "log-fd", 0); | 2910 | parse_options_usage(stat_usage, stat_options, "log-fd", 0); |
| @@ -2897,6 +2959,14 @@ int cmd_stat(int argc, const char **argv) | |||
| 2897 | run_count = 1; | 2959 | run_count = 1; |
| 2898 | } | 2960 | } |
| 2899 | 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 | |||
| 2900 | if ((stat_config.aggr_mode == AGGR_THREAD) && | 2970 | if ((stat_config.aggr_mode == AGGR_THREAD) && |
| 2901 | !target__has_task(&target)) { | 2971 | !target__has_task(&target)) { |
| 2902 | if (!target.system_wide || target.cpu_list) { | 2972 | if (!target.system_wide || target.cpu_list) { |
| @@ -3012,7 +3082,7 @@ int cmd_stat(int argc, const char **argv) | |||
| 3012 | fprintf(output, "[ perf stat: executing run #%d ... ]\n", | 3082 | fprintf(output, "[ perf stat: executing run #%d ... ]\n", |
| 3013 | run_idx + 1); | 3083 | run_idx + 1); |
| 3014 | 3084 | ||
| 3015 | status = run_perf_stat(argc, argv); | 3085 | status = run_perf_stat(argc, argv, run_idx); |
| 3016 | if (forever && status != -1) { | 3086 | if (forever && status != -1) { |
| 3017 | print_counters(NULL, argc, argv); | 3087 | print_counters(NULL, argc, argv); |
| 3018 | perf_stat__reset_stats(); | 3088 | perf_stat__reset_stats(); |
| @@ -3060,6 +3130,8 @@ int cmd_stat(int argc, const char **argv) | |||
| 3060 | perf_stat__exit_aggr_mode(); | 3130 | perf_stat__exit_aggr_mode(); |
| 3061 | perf_evlist__free_stats(evsel_list); | 3131 | perf_evlist__free_stats(evsel_list); |
| 3062 | out: | 3132 | out: |
| 3133 | free(walltime_run); | ||
| 3134 | |||
| 3063 | if (smi_cost && smi_reset) | 3135 | if (smi_cost && smi_reset) |
| 3064 | sysfs__write_int(FREEZE_ON_SMI_PATH, 0); | 3136 | sysfs__write_int(FREEZE_ON_SMI_PATH, 0); |
| 3065 | 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..3c061c57afb6 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)); |
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 3ad17ee89403..c7effcfc40ed 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'; |
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 | |||
| 55 | include/uapi/asm-generic/mman-common.h | 55 | include/uapi/asm-generic/mman-common.h |
| 56 | ' | 56 | ' |
| 57 | 57 | ||
| 58 | check () { | 58 | check_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 | ||
| 71 | check () { | ||
| 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 | |||
| 83 | done | 87 | done |
| 84 | 88 | ||
| 85 | # diff with extra ignore lines | 89 | # diff with extra ignore lines |
| 86 | check arch/x86/lib/memcpy_64.S -I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>" | 90 | check arch/x86/lib/memcpy_64.S '-I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>"' |
| 87 | check arch/x86/lib/memset_64.S -I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>" | 91 | check arch/x86/lib/memset_64.S '-I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>"' |
| 88 | check include/uapi/asm-generic/mman.h -I "^#include <\(uapi/\)*asm-generic/mman-common.h>" | 92 | check include/uapi/asm-generic/mman.h '-I "^#include <\(uapi/\)*asm-generic/mman-common.h>"' |
| 89 | check include/uapi/linux/mman.h -I "^#include <\(uapi/\)*asm/mman.h>" | 93 | check include/uapi/linux/mman.h '-I "^#include <\(uapi/\)*asm/mman.h>"' |
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/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/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/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 { | |||
| 1679 | static bool kern_sym_match(struct sym_args *args, const char *name, char type) | 1679 | static 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 | ||
| 1973 | static int addr_filter__entire_dso(struct addr_filter *filt, struct dso *dso) | 1973 | static 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/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/cs-etm.c b/tools/perf/util/cs-etm.c index 40020b1ca54f..6533b1adb50b 100644 --- a/tools/perf/util/cs-etm.c +++ b/tools/perf/util/cs-etm.c | |||
| @@ -269,9 +269,7 @@ static u32 cs_etm__mem_access(struct cs_etm_queue *etmq, u64 address, | |||
| 269 | thread = etmq->etm->unknown_thread; | 269 | thread = etmq->etm->unknown_thread; |
| 270 | } | 270 | } |
| 271 | 271 | ||
| 272 | thread__find_addr_map(thread, cpumode, MAP__FUNCTION, address, &al); | 272 | if (!thread__find_map(thread, cpumode, address, &al) || !al.map->dso) |
| 273 | |||
| 274 | if (!al.map || !al.map->dso) | ||
| 275 | return 0; | 273 | return 0; |
| 276 | 274 | ||
| 277 | if (al.map->dso->data.status == DSO_DATA_STATUS_ERROR && | 275 | if (al.map->dso->data.status == DSO_DATA_STATUS_ERROR && |
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 | ||
| 1179 | bool dso__loaded(const struct dso *dso, enum map_type type) | 1179 | bool dso__loaded(const struct dso *dso) |
| 1180 | { | 1180 | { |
| 1181 | return dso->loaded & (1 << type); | 1181 | return dso->loaded; |
| 1182 | } | 1182 | } |
| 1183 | 1183 | ||
| 1184 | bool dso__sorted_by_name(const struct dso *dso, enum map_type type) | 1184 | bool 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 | ||
| 1189 | void dso__set_sorted_by_name(struct dso *dso, enum map_type type) | 1189 | void 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 | ||
| 1194 | struct dso *dso__new(const char *name) | 1194 | struct 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 | ||
| 1232 | void dso__delete(struct dso *dso) | 1230 | void 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 | ||
| 1470 | size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp) | 1463 | size_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 | ||
| 210 | static inline void dso__set_loaded(struct dso *dso, enum map_type type) | 209 | static inline void dso__set_loaded(struct dso *dso) |
| 211 | { | 210 | { |
| 212 | dso->loaded |= (1 << type); | 211 | dso->loaded = true; |
| 213 | } | 212 | } |
| 214 | 213 | ||
| 215 | struct dso *dso__new(const char *name); | 214 | struct 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 | ||
| 234 | bool dso__loaded(const struct dso *dso, enum map_type type); | 233 | bool dso__loaded(const struct dso *dso); |
| 235 | 234 | ||
| 236 | bool dso__sorted_by_name(const struct dso *dso, enum map_type type); | 235 | static inline bool dso__has_symbols(const struct dso *dso) |
| 237 | void dso__set_sorted_by_name(struct dso *dso, enum map_type type); | 236 | { |
| 238 | void dso__sort_by_name(struct dso *dso, enum map_type type); | 237 | return !RB_EMPTY_ROOT(&dso->symbols); |
| 238 | } | ||
| 239 | |||
| 240 | bool dso__sorted_by_name(const struct dso *dso); | ||
| 241 | void dso__set_sorted_by_name(struct dso *dso); | ||
| 242 | void dso__sort_by_name(struct dso *dso); | ||
| 239 | 243 | ||
| 240 | void dso__set_build_id(struct dso *dso, void *build_id); | 244 | void dso__set_build_id(struct dso *dso, void *build_id); |
| 241 | bool dso__build_id_equal(const struct dso *dso, u8 *build_id); | 245 | bool 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, | |||
| 349 | size_t __dsos__fprintf(struct list_head *head, FILE *fp); | 353 | size_t __dsos__fprintf(struct list_head *head, FILE *fp); |
| 350 | 354 | ||
| 351 | size_t dso__fprintf_buildid(struct dso *dso, FILE *fp); | 355 | size_t dso__fprintf_buildid(struct dso *dso, FILE *fp); |
| 352 | size_t dso__fprintf_symbols_by_name(struct dso *dso, | 356 | size_t dso__fprintf_symbols_by_name(struct dso *dso, FILE *fp); |
| 353 | enum map_type type, FILE *fp); | 357 | size_t dso__fprintf(struct dso *dso, FILE *fp); |
| 354 | size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp); | ||
| 355 | 358 | ||
| 356 | static inline bool dso__is_vmlinux(struct dso *dso) | 359 | static inline bool dso__is_vmlinux(struct dso *dso) |
| 357 | { | 360 | { |
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 98ff3a6a3d50..244135b5ea43 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c | |||
| @@ -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) { |
| @@ -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 | ||
| @@ -1489,9 +1488,8 @@ int perf_event__process(struct perf_tool *tool __maybe_unused, | |||
| 1489 | return machine__process_event(machine, event, sample); | 1488 | return machine__process_event(machine, event, sample); |
| 1490 | } | 1489 | } |
| 1491 | 1490 | ||
| 1492 | void thread__find_addr_map(struct thread *thread, u8 cpumode, | 1491 | struct map *thread__find_map(struct thread *thread, u8 cpumode, u64 addr, |
| 1493 | enum map_type type, u64 addr, | 1492 | struct addr_location *al) |
| 1494 | struct addr_location *al) | ||
| 1495 | { | 1493 | { |
| 1496 | struct map_groups *mg = thread->mg; | 1494 | struct map_groups *mg = thread->mg; |
| 1497 | struct machine *machine = mg->machine; | 1495 | struct machine *machine = mg->machine; |
| @@ -1505,7 +1503,7 @@ void thread__find_addr_map(struct thread *thread, u8 cpumode, | |||
| 1505 | 1503 | ||
| 1506 | if (machine == NULL) { | 1504 | if (machine == NULL) { |
| 1507 | al->map = NULL; | 1505 | al->map = NULL; |
| 1508 | return; | 1506 | return NULL; |
| 1509 | } | 1507 | } |
| 1510 | 1508 | ||
| 1511 | if (cpumode == PERF_RECORD_MISC_KERNEL && perf_host) { | 1509 | if (cpumode == PERF_RECORD_MISC_KERNEL && perf_host) { |
| @@ -1533,10 +1531,10 @@ void thread__find_addr_map(struct thread *thread, u8 cpumode, | |||
| 1533 | !perf_host) | 1531 | !perf_host) |
| 1534 | al->filtered |= (1 << HIST_FILTER__HOST); | 1532 | al->filtered |= (1 << HIST_FILTER__HOST); |
| 1535 | 1533 | ||
| 1536 | return; | 1534 | return NULL; |
| 1537 | } | 1535 | } |
| 1538 | try_again: | 1536 | try_again: |
| 1539 | al->map = map_groups__find(mg, type, al->addr); | 1537 | al->map = map_groups__find(mg, al->addr); |
| 1540 | if (al->map == NULL) { | 1538 | if (al->map == NULL) { |
| 1541 | /* | 1539 | /* |
| 1542 | * If this is outside of all known maps, and is a negative | 1540 | * If this is outside of all known maps, and is a negative |
| @@ -1563,17 +1561,17 @@ try_again: | |||
| 1563 | map__load(al->map); | 1561 | map__load(al->map); |
| 1564 | al->addr = al->map->map_ip(al->map, al->addr); | 1562 | al->addr = al->map->map_ip(al->map, al->addr); |
| 1565 | } | 1563 | } |
| 1564 | |||
| 1565 | return al->map; | ||
| 1566 | } | 1566 | } |
| 1567 | 1567 | ||
| 1568 | void thread__find_addr_location(struct thread *thread, | 1568 | struct symbol *thread__find_symbol(struct thread *thread, u8 cpumode, |
| 1569 | u8 cpumode, enum map_type type, u64 addr, | 1569 | u64 addr, struct addr_location *al) |
| 1570 | struct addr_location *al) | ||
| 1571 | { | 1570 | { |
| 1572 | thread__find_addr_map(thread, cpumode, type, addr, al); | 1571 | al->sym = NULL; |
| 1573 | if (al->map != NULL) | 1572 | if (thread__find_map(thread, cpumode, addr, al)) |
| 1574 | al->sym = map__find_symbol(al->map, al->addr); | 1573 | al->sym = map__find_symbol(al->map, al->addr); |
| 1575 | else | 1574 | return al->sym; |
| 1576 | al->sym = NULL; | ||
| 1577 | } | 1575 | } |
| 1578 | 1576 | ||
| 1579 | /* | 1577 | /* |
| @@ -1590,7 +1588,7 @@ int machine__resolve(struct machine *machine, struct addr_location *al, | |||
| 1590 | return -1; | 1588 | return -1; |
| 1591 | 1589 | ||
| 1592 | dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread), thread->tid); | 1590 | 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); | 1591 | thread__find_map(thread, sample->cpumode, sample->ip, al); |
| 1594 | dump_printf(" ...... dso: %s\n", | 1592 | dump_printf(" ...... dso: %s\n", |
| 1595 | al->map ? al->map->dso->long_name : | 1593 | al->map ? al->map->dso->long_name : |
| 1596 | al->level == 'H' ? "[hypervisor]" : "<not found>"); | 1594 | al->level == 'H' ? "[hypervisor]" : "<not found>"); |
| @@ -1669,10 +1667,7 @@ bool sample_addr_correlates_sym(struct perf_event_attr *attr) | |||
| 1669 | void thread__resolve(struct thread *thread, struct addr_location *al, | 1667 | void thread__resolve(struct thread *thread, struct addr_location *al, |
| 1670 | struct perf_sample *sample) | 1668 | struct perf_sample *sample) |
| 1671 | { | 1669 | { |
| 1672 | thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, sample->addr, al); | 1670 | 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 | 1671 | ||
| 1677 | al->cpu = sample->cpu; | 1672 | al->cpu = sample->cpu; |
| 1678 | al->sym = NULL; | 1673 | al->sym = NULL; |
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.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/machine.c b/tools/perf/util/machine.c index 32d50492505d..72a351613d85 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 | ||
| 28 | static void __machine__remove_thread(struct machine *machine, struct thread *th, bool lock); | 29 | static 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 | ||
| @@ -857,62 +854,44 @@ static int machine__get_running_kernel_start(struct machine *machine, | |||
| 857 | static int | 854 | static int |
| 858 | __machine__create_kernel_maps(struct machine *machine, struct dso *kernel) | 855 | __machine__create_kernel_maps(struct machine *machine, struct dso *kernel) |
| 859 | { | 856 | { |
| 860 | int type; | 857 | struct kmap *kmap; |
| 858 | struct map *map; | ||
| 861 | 859 | ||
| 862 | /* In case of renewal the kernel map, destroy previous one */ | 860 | /* In case of renewal the kernel map, destroy previous one */ |
| 863 | machine__destroy_kernel_maps(machine); | 861 | machine__destroy_kernel_maps(machine); |
| 864 | 862 | ||
| 865 | for (type = 0; type < MAP__NR_TYPES; ++type) { | 863 | machine->vmlinux_map = map__new2(0, kernel); |
| 866 | struct kmap *kmap; | 864 | if (machine->vmlinux_map == NULL) |
| 867 | struct map *map; | 865 | return -1; |
| 868 | |||
| 869 | machine->vmlinux_maps[type] = map__new2(0, kernel, type); | ||
| 870 | if (machine->vmlinux_maps[type] == NULL) | ||
| 871 | return -1; | ||
| 872 | 866 | ||
| 873 | machine->vmlinux_maps[type]->map_ip = | 867 | machine->vmlinux_map->map_ip = machine->vmlinux_map->unmap_ip = identity__map_ip; |
| 874 | machine->vmlinux_maps[type]->unmap_ip = | 868 | map = machine__kernel_map(machine); |
| 875 | identity__map_ip; | 869 | kmap = map__kmap(map); |
| 876 | map = __machine__kernel_map(machine, type); | 870 | if (!kmap) |
| 877 | kmap = map__kmap(map); | 871 | return -1; |
| 878 | if (!kmap) | ||
| 879 | return -1; | ||
| 880 | 872 | ||
| 881 | kmap->kmaps = &machine->kmaps; | 873 | kmap->kmaps = &machine->kmaps; |
| 882 | map_groups__insert(&machine->kmaps, map); | 874 | map_groups__insert(&machine->kmaps, map); |
| 883 | } | ||
| 884 | 875 | ||
| 885 | return 0; | 876 | return 0; |
| 886 | } | 877 | } |
| 887 | 878 | ||
| 888 | void machine__destroy_kernel_maps(struct machine *machine) | 879 | void machine__destroy_kernel_maps(struct machine *machine) |
| 889 | { | 880 | { |
| 890 | int type; | 881 | struct kmap *kmap; |
| 891 | 882 | 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 | 883 | ||
| 899 | kmap = map__kmap(map); | 884 | if (map == NULL) |
| 900 | map_groups__remove(&machine->kmaps, map); | 885 | 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 | 886 | ||
| 913 | map__put(machine->vmlinux_maps[type]); | 887 | kmap = map__kmap(map); |
| 914 | machine->vmlinux_maps[type] = NULL; | 888 | map_groups__remove(&machine->kmaps, map); |
| 889 | if (kmap && kmap->ref_reloc_sym) { | ||
| 890 | zfree((char **)&kmap->ref_reloc_sym->name); | ||
| 891 | zfree(&kmap->ref_reloc_sym); | ||
| 915 | } | 892 | } |
| 893 | |||
| 894 | map__zput(machine->vmlinux_map); | ||
| 916 | } | 895 | } |
| 917 | 896 | ||
| 918 | int machines__create_guest_kernel_maps(struct machines *machines) | 897 | int machines__create_guest_kernel_maps(struct machines *machines) |
| @@ -989,32 +968,31 @@ int machines__create_kernel_maps(struct machines *machines, pid_t pid) | |||
| 989 | return machine__create_kernel_maps(machine); | 968 | return machine__create_kernel_maps(machine); |
| 990 | } | 969 | } |
| 991 | 970 | ||
| 992 | int machine__load_kallsyms(struct machine *machine, const char *filename, | 971 | int machine__load_kallsyms(struct machine *machine, const char *filename) |
| 993 | enum map_type type) | ||
| 994 | { | 972 | { |
| 995 | struct map *map = machine__kernel_map(machine); | 973 | struct map *map = machine__kernel_map(machine); |
| 996 | int ret = __dso__load_kallsyms(map->dso, filename, map, true); | 974 | int ret = __dso__load_kallsyms(map->dso, filename, map, true); |
| 997 | 975 | ||
| 998 | if (ret > 0) { | 976 | if (ret > 0) { |
| 999 | dso__set_loaded(map->dso, type); | 977 | dso__set_loaded(map->dso); |
| 1000 | /* | 978 | /* |
| 1001 | * Since /proc/kallsyms will have multiple sessions for the | 979 | * Since /proc/kallsyms will have multiple sessions for the |
| 1002 | * kernel, with modules between them, fixup the end of all | 980 | * kernel, with modules between them, fixup the end of all |
| 1003 | * sections. | 981 | * sections. |
| 1004 | */ | 982 | */ |
| 1005 | __map_groups__fixup_end(&machine->kmaps, type); | 983 | map_groups__fixup_end(&machine->kmaps); |
| 1006 | } | 984 | } |
| 1007 | 985 | ||
| 1008 | return ret; | 986 | return ret; |
| 1009 | } | 987 | } |
| 1010 | 988 | ||
| 1011 | int machine__load_vmlinux_path(struct machine *machine, enum map_type type) | 989 | int machine__load_vmlinux_path(struct machine *machine) |
| 1012 | { | 990 | { |
| 1013 | struct map *map = machine__kernel_map(machine); | 991 | struct map *map = machine__kernel_map(machine); |
| 1014 | int ret = dso__load_vmlinux_path(map->dso, map); | 992 | int ret = dso__load_vmlinux_path(map->dso, map); |
| 1015 | 993 | ||
| 1016 | if (ret > 0) | 994 | if (ret > 0) |
| 1017 | dso__set_loaded(map->dso, type); | 995 | dso__set_loaded(map->dso); |
| 1018 | 996 | ||
| 1019 | return ret; | 997 | return ret; |
| 1020 | } | 998 | } |
| @@ -1055,10 +1033,9 @@ static bool is_kmod_dso(struct dso *dso) | |||
| 1055 | static int map_groups__set_module_path(struct map_groups *mg, const char *path, | 1033 | static int map_groups__set_module_path(struct map_groups *mg, const char *path, |
| 1056 | struct kmod_path *m) | 1034 | struct kmod_path *m) |
| 1057 | { | 1035 | { |
| 1058 | struct map *map; | ||
| 1059 | char *long_name; | 1036 | char *long_name; |
| 1037 | struct map *map = map_groups__find_by_name(mg, m->name); | ||
| 1060 | 1038 | ||
| 1061 | map = map_groups__find_by_name(mg, MAP__FUNCTION, m->name); | ||
| 1062 | if (map == NULL) | 1039 | if (map == NULL) |
| 1063 | return 0; | 1040 | return 0; |
| 1064 | 1041 | ||
| @@ -1207,19 +1184,14 @@ static int machine__create_modules(struct machine *machine) | |||
| 1207 | static void machine__set_kernel_mmap(struct machine *machine, | 1184 | static void machine__set_kernel_mmap(struct machine *machine, |
| 1208 | u64 start, u64 end) | 1185 | u64 start, u64 end) |
| 1209 | { | 1186 | { |
| 1210 | int i; | 1187 | machine->vmlinux_map->start = start; |
| 1211 | 1188 | machine->vmlinux_map->end = end; | |
| 1212 | for (i = 0; i < MAP__NR_TYPES; i++) { | 1189 | /* |
| 1213 | machine->vmlinux_maps[i]->start = start; | 1190 | * Be a bit paranoid here, some perf.data file came with |
| 1214 | machine->vmlinux_maps[i]->end = end; | 1191 | * a zero sized synthesized MMAP event for the kernel. |
| 1215 | 1192 | */ | |
| 1216 | /* | 1193 | if (start == 0 && end == 0) |
| 1217 | * Be a bit paranoid here, some perf.data file came with | 1194 | machine->vmlinux_map->end = ~0ULL; |
| 1218 | * a zero sized synthesized MMAP event for the kernel. | ||
| 1219 | */ | ||
| 1220 | if (start == 0 && end == 0) | ||
| 1221 | machine->vmlinux_maps[i]->end = ~0ULL; | ||
| 1222 | } | ||
| 1223 | } | 1195 | } |
| 1224 | 1196 | ||
| 1225 | int machine__create_kernel_maps(struct machine *machine) | 1197 | int machine__create_kernel_maps(struct machine *machine) |
| @@ -1249,7 +1221,7 @@ int machine__create_kernel_maps(struct machine *machine) | |||
| 1249 | 1221 | ||
| 1250 | if (!machine__get_running_kernel_start(machine, &name, &addr)) { | 1222 | if (!machine__get_running_kernel_start(machine, &name, &addr)) { |
| 1251 | if (name && | 1223 | if (name && |
| 1252 | maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, name, addr)) { | 1224 | map__set_kallsyms_ref_reloc_sym(machine->vmlinux_map, name, addr)) { |
| 1253 | machine__destroy_kernel_maps(machine); | 1225 | machine__destroy_kernel_maps(machine); |
| 1254 | return -1; | 1226 | return -1; |
| 1255 | } | 1227 | } |
| @@ -1379,9 +1351,9 @@ static int machine__process_kernel_mmap_event(struct machine *machine, | |||
| 1379 | * time /proc/sys/kernel/kptr_restrict was non zero. | 1351 | * time /proc/sys/kernel/kptr_restrict was non zero. |
| 1380 | */ | 1352 | */ |
| 1381 | if (event->mmap.pgoff != 0) { | 1353 | if (event->mmap.pgoff != 0) { |
| 1382 | maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, | 1354 | map__set_kallsyms_ref_reloc_sym(machine->vmlinux_map, |
| 1383 | symbol_name, | 1355 | symbol_name, |
| 1384 | event->mmap.pgoff); | 1356 | event->mmap.pgoff); |
| 1385 | } | 1357 | } |
| 1386 | 1358 | ||
| 1387 | if (machine__is_default_guest(machine)) { | 1359 | if (machine__is_default_guest(machine)) { |
| @@ -1402,7 +1374,6 @@ int machine__process_mmap2_event(struct machine *machine, | |||
| 1402 | { | 1374 | { |
| 1403 | struct thread *thread; | 1375 | struct thread *thread; |
| 1404 | struct map *map; | 1376 | struct map *map; |
| 1405 | enum map_type type; | ||
| 1406 | int ret = 0; | 1377 | int ret = 0; |
| 1407 | 1378 | ||
| 1408 | if (dump_trace) | 1379 | if (dump_trace) |
| @@ -1421,11 +1392,6 @@ int machine__process_mmap2_event(struct machine *machine, | |||
| 1421 | if (thread == NULL) | 1392 | if (thread == NULL) |
| 1422 | goto out_problem; | 1393 | goto out_problem; |
| 1423 | 1394 | ||
| 1424 | if (event->header.misc & PERF_RECORD_MISC_MMAP_DATA) | ||
| 1425 | type = MAP__VARIABLE; | ||
| 1426 | else | ||
| 1427 | type = MAP__FUNCTION; | ||
| 1428 | |||
| 1429 | map = map__new(machine, event->mmap2.start, | 1395 | map = map__new(machine, event->mmap2.start, |
| 1430 | event->mmap2.len, event->mmap2.pgoff, | 1396 | event->mmap2.len, event->mmap2.pgoff, |
| 1431 | event->mmap2.maj, | 1397 | event->mmap2.maj, |
| @@ -1433,7 +1399,7 @@ int machine__process_mmap2_event(struct machine *machine, | |||
| 1433 | event->mmap2.ino_generation, | 1399 | event->mmap2.ino_generation, |
| 1434 | event->mmap2.prot, | 1400 | event->mmap2.prot, |
| 1435 | event->mmap2.flags, | 1401 | event->mmap2.flags, |
| 1436 | event->mmap2.filename, type, thread); | 1402 | event->mmap2.filename, thread); |
| 1437 | 1403 | ||
| 1438 | if (map == NULL) | 1404 | if (map == NULL) |
| 1439 | goto out_problem_map; | 1405 | goto out_problem_map; |
| @@ -1460,7 +1426,7 @@ int machine__process_mmap_event(struct machine *machine, union perf_event *event | |||
| 1460 | { | 1426 | { |
| 1461 | struct thread *thread; | 1427 | struct thread *thread; |
| 1462 | struct map *map; | 1428 | struct map *map; |
| 1463 | enum map_type type; | 1429 | u32 prot = 0; |
| 1464 | int ret = 0; | 1430 | int ret = 0; |
| 1465 | 1431 | ||
| 1466 | if (dump_trace) | 1432 | if (dump_trace) |
| @@ -1479,16 +1445,14 @@ int machine__process_mmap_event(struct machine *machine, union perf_event *event | |||
| 1479 | if (thread == NULL) | 1445 | if (thread == NULL) |
| 1480 | goto out_problem; | 1446 | goto out_problem; |
| 1481 | 1447 | ||
| 1482 | if (event->header.misc & PERF_RECORD_MISC_MMAP_DATA) | 1448 | if (!(event->header.misc & PERF_RECORD_MISC_MMAP_DATA)) |
| 1483 | type = MAP__VARIABLE; | 1449 | prot = PROT_EXEC; |
| 1484 | else | ||
| 1485 | type = MAP__FUNCTION; | ||
| 1486 | 1450 | ||
| 1487 | map = map__new(machine, event->mmap.start, | 1451 | map = map__new(machine, event->mmap.start, |
| 1488 | event->mmap.len, event->mmap.pgoff, | 1452 | event->mmap.len, event->mmap.pgoff, |
| 1489 | 0, 0, 0, 0, 0, 0, | 1453 | 0, 0, 0, 0, prot, 0, |
| 1490 | event->mmap.filename, | 1454 | event->mmap.filename, |
| 1491 | type, thread); | 1455 | thread); |
| 1492 | 1456 | ||
| 1493 | if (map == NULL) | 1457 | if (map == NULL) |
| 1494 | goto out_problem_map; | 1458 | goto out_problem_map; |
| @@ -1664,7 +1628,7 @@ static void ip__resolve_ams(struct thread *thread, | |||
| 1664 | * Thus, we have to try consecutively until we find a match | 1628 | * Thus, we have to try consecutively until we find a match |
| 1665 | * or else, the symbol is unknown | 1629 | * or else, the symbol is unknown |
| 1666 | */ | 1630 | */ |
| 1667 | thread__find_cpumode_addr_location(thread, MAP__FUNCTION, ip, &al); | 1631 | thread__find_cpumode_addr_location(thread, ip, &al); |
| 1668 | 1632 | ||
| 1669 | ams->addr = ip; | 1633 | ams->addr = ip; |
| 1670 | ams->al_addr = al.addr; | 1634 | ams->al_addr = al.addr; |
| @@ -1681,15 +1645,7 @@ static void ip__resolve_data(struct thread *thread, | |||
| 1681 | 1645 | ||
| 1682 | memset(&al, 0, sizeof(al)); | 1646 | memset(&al, 0, sizeof(al)); |
| 1683 | 1647 | ||
| 1684 | thread__find_addr_location(thread, m, MAP__VARIABLE, addr, &al); | 1648 | thread__find_symbol(thread, m, addr, &al); |
| 1685 | if (al.map == NULL) { | ||
| 1686 | /* | ||
| 1687 | * some shared data regions have execute bit set which puts | ||
| 1688 | * their mapping in the MAP__FUNCTION type array. | ||
| 1689 | * Check there as a fallback option before dropping the sample. | ||
| 1690 | */ | ||
| 1691 | thread__find_addr_location(thread, m, MAP__FUNCTION, addr, &al); | ||
| 1692 | } | ||
| 1693 | 1649 | ||
| 1694 | ams->addr = addr; | 1650 | ams->addr = addr; |
| 1695 | ams->al_addr = al.addr; | 1651 | ams->al_addr = al.addr; |
| @@ -1758,8 +1714,7 @@ static int add_callchain_ip(struct thread *thread, | |||
| 1758 | al.filtered = 0; | 1714 | al.filtered = 0; |
| 1759 | al.sym = NULL; | 1715 | al.sym = NULL; |
| 1760 | if (!cpumode) { | 1716 | if (!cpumode) { |
| 1761 | thread__find_cpumode_addr_location(thread, MAP__FUNCTION, | 1717 | thread__find_cpumode_addr_location(thread, ip, &al); |
| 1762 | ip, &al); | ||
| 1763 | } else { | 1718 | } else { |
| 1764 | if (ip >= PERF_CONTEXT_MAX) { | 1719 | if (ip >= PERF_CONTEXT_MAX) { |
| 1765 | switch (ip) { | 1720 | switch (ip) { |
| @@ -1784,8 +1739,7 @@ static int add_callchain_ip(struct thread *thread, | |||
| 1784 | } | 1739 | } |
| 1785 | return 0; | 1740 | return 0; |
| 1786 | } | 1741 | } |
| 1787 | thread__find_addr_location(thread, *cpumode, MAP__FUNCTION, | 1742 | thread__find_symbol(thread, *cpumode, ip, &al); |
| 1788 | ip, &al); | ||
| 1789 | } | 1743 | } |
| 1790 | 1744 | ||
| 1791 | if (al.sym != NULL) { | 1745 | if (al.sym != NULL) { |
| @@ -2373,7 +2327,7 @@ char *machine__resolve_kernel_addr(void *vmachine, unsigned long long *addrp, ch | |||
| 2373 | { | 2327 | { |
| 2374 | struct machine *machine = vmachine; | 2328 | struct machine *machine = vmachine; |
| 2375 | struct map *map; | 2329 | struct map *map; |
| 2376 | struct symbol *sym = map_groups__find_symbol(&machine->kmaps, MAP__FUNCTION, *addrp, &map); | 2330 | struct symbol *sym = machine__find_kernel_symbol(machine, *addrp, &map); |
| 2377 | 2331 | ||
| 2378 | if (sym == NULL) | 2332 | if (sym == NULL) |
| 2379 | return NULL; | 2333 | return NULL; |
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h index 66cc200ef86f..388fb4741c54 100644 --- a/tools/perf/util/machine.h +++ b/tools/perf/util/machine.h | |||
| @@ -49,7 +49,7 @@ 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 */ |
| @@ -64,16 +64,22 @@ static inline struct threads *machine__threads(struct machine *machine, pid_t ti | |||
| 64 | return &machine->threads[(unsigned int)tid % THREADS__TABLE_SIZE]; | 64 | return &machine->threads[(unsigned int)tid % THREADS__TABLE_SIZE]; |
| 65 | } | 65 | } |
| 66 | 66 | ||
| 67 | /* | ||
| 68 | * The main kernel (vmlinux) map | ||
| 69 | */ | ||
| 67 | static inline | 70 | static inline |
| 68 | struct map *__machine__kernel_map(struct machine *machine, enum map_type type) | 71 | struct map *machine__kernel_map(struct machine *machine) |
| 69 | { | 72 | { |
| 70 | return machine->vmlinux_maps[type]; | 73 | return machine->vmlinux_map; |
| 71 | } | 74 | } |
| 72 | 75 | ||
| 76 | /* | ||
| 77 | * kernel (the one returned by machine__kernel_map()) plus kernel modules maps | ||
| 78 | */ | ||
| 73 | static inline | 79 | static inline |
| 74 | struct map *machine__kernel_map(struct machine *machine) | 80 | struct maps *machine__kernel_maps(struct machine *machine) |
| 75 | { | 81 | { |
| 76 | return __machine__kernel_map(machine, MAP__FUNCTION); | 82 | return &machine->kmaps.maps; |
| 77 | } | 83 | } |
| 78 | 84 | ||
| 79 | int machine__get_kernel_start(struct machine *machine); | 85 | int machine__get_kernel_start(struct machine *machine); |
| @@ -190,44 +196,27 @@ struct dso *machine__findnew_dso(struct machine *machine, const char *filename); | |||
| 190 | size_t machine__fprintf(struct machine *machine, FILE *fp); | 196 | size_t machine__fprintf(struct machine *machine, FILE *fp); |
| 191 | 197 | ||
| 192 | static inline | 198 | static inline |
| 193 | struct symbol *machine__find_kernel_symbol(struct machine *machine, | 199 | struct symbol *machine__find_kernel_symbol(struct machine *machine, u64 addr, |
| 194 | enum map_type type, u64 addr, | ||
| 195 | struct map **mapp) | 200 | struct map **mapp) |
| 196 | { | 201 | { |
| 197 | return map_groups__find_symbol(&machine->kmaps, type, addr, mapp); | 202 | return map_groups__find_symbol(&machine->kmaps, addr, mapp); |
| 198 | } | 203 | } |
| 199 | 204 | ||
| 200 | static inline | 205 | static inline |
| 201 | struct symbol *machine__find_kernel_symbol_by_name(struct machine *machine, | 206 | struct symbol *machine__find_kernel_symbol_by_name(struct machine *machine, |
| 202 | enum map_type type, const char *name, | 207 | const char *name, |
| 203 | struct map **mapp) | 208 | struct map **mapp) |
| 204 | { | 209 | { |
| 205 | return map_groups__find_symbol_by_name(&machine->kmaps, type, name, mapp); | 210 | return map_groups__find_symbol_by_name(&machine->kmaps, name, mapp); |
| 206 | } | ||
| 207 | |||
| 208 | static inline | ||
| 209 | struct 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 | |||
| 216 | static inline | ||
| 217 | struct 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 | } | 211 | } |
| 223 | 212 | ||
| 224 | struct map *machine__findnew_module_map(struct machine *machine, u64 start, | 213 | struct map *machine__findnew_module_map(struct machine *machine, u64 start, |
| 225 | const char *filename); | 214 | const char *filename); |
| 226 | int arch__fix_module_text_start(u64 *start, const char *name); | 215 | int arch__fix_module_text_start(u64 *start, const char *name); |
| 227 | 216 | ||
| 228 | int machine__load_kallsyms(struct machine *machine, const char *filename, | 217 | int machine__load_kallsyms(struct machine *machine, const char *filename); |
| 229 | enum map_type type); | 218 | |
| 230 | int machine__load_vmlinux_path(struct machine *machine, enum map_type type); | 219 | int machine__load_vmlinux_path(struct machine *machine); |
| 231 | 220 | ||
| 232 | size_t machine__fprintf_dsos_buildid(struct machine *machine, FILE *fp, | 221 | size_t machine__fprintf_dsos_buildid(struct machine *machine, FILE *fp, |
| 233 | bool (skip)(struct dso *dso, int parm), int parm); | 222 | bool (skip)(struct dso *dso, int parm), int parm); |
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index 8fe57031e1a8..c8fe836e4c3c 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c | |||
| @@ -22,11 +22,6 @@ | |||
| 22 | 22 | ||
| 23 | static void __maps__insert(struct maps *maps, struct map *map); | 23 | static void __maps__insert(struct maps *maps, struct map *map); |
| 24 | 24 | ||
| 25 | const char *map_type__name[MAP__NR_TYPES] = { | ||
| 26 | [MAP__FUNCTION] = "Functions", | ||
| 27 | [MAP__VARIABLE] = "Variables", | ||
| 28 | }; | ||
| 29 | |||
| 30 | static inline int is_anon_memory(const char *filename, u32 flags) | 25 | static 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 | ||
| 132 | void map__init(struct map *map, enum map_type type, | 127 | void 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, | |||
| 149 | struct map *map__new(struct machine *machine, u64 start, u64 len, | 142 | struct 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 | */ |
| 234 | struct map *map__new2(u64 start, struct dso *dso, enum map_type type) | 227 | struct 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,12 @@ struct map *map__new2(u64 start, struct dso *dso, enum map_type type) | |||
| 256 | */ | 249 | */ |
| 257 | bool __map__is_kernel(const struct map *map) | 250 | bool __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 | |||
| 255 | bool map__has_symbols(const struct map *map) | ||
| 256 | { | ||
| 257 | return dso__has_symbols(map->dso); | ||
| 260 | } | 258 | } |
| 261 | 259 | ||
| 262 | static void map__exit(struct map *map) | 260 | static void map__exit(struct map *map) |
| @@ -279,7 +277,7 @@ void map__put(struct map *map) | |||
| 279 | 277 | ||
| 280 | void map__fixup_start(struct map *map) | 278 | void map__fixup_start(struct map *map) |
| 281 | { | 279 | { |
| 282 | struct rb_root *symbols = &map->dso->symbols[map->type]; | 280 | struct rb_root *symbols = &map->dso->symbols; |
| 283 | struct rb_node *nd = rb_first(symbols); | 281 | struct rb_node *nd = rb_first(symbols); |
| 284 | if (nd != NULL) { | 282 | if (nd != NULL) { |
| 285 | struct symbol *sym = rb_entry(nd, struct symbol, rb_node); | 283 | struct symbol *sym = rb_entry(nd, struct symbol, rb_node); |
| @@ -289,7 +287,7 @@ void map__fixup_start(struct map *map) | |||
| 289 | 287 | ||
| 290 | void map__fixup_end(struct map *map) | 288 | void map__fixup_end(struct map *map) |
| 291 | { | 289 | { |
| 292 | struct rb_root *symbols = &map->dso->symbols[map->type]; | 290 | struct rb_root *symbols = &map->dso->symbols; |
| 293 | struct rb_node *nd = rb_last(symbols); | 291 | struct rb_node *nd = rb_last(symbols); |
| 294 | if (nd != NULL) { | 292 | if (nd != NULL) { |
| 295 | struct symbol *sym = rb_entry(nd, struct symbol, rb_node); | 293 | struct symbol *sym = rb_entry(nd, struct symbol, rb_node); |
| @@ -304,7 +302,7 @@ int map__load(struct map *map) | |||
| 304 | const char *name = map->dso->long_name; | 302 | const char *name = map->dso->long_name; |
| 305 | int nr; | 303 | int nr; |
| 306 | 304 | ||
| 307 | if (dso__loaded(map->dso, map->type)) | 305 | if (dso__loaded(map->dso)) |
| 308 | return 0; | 306 | return 0; |
| 309 | 307 | ||
| 310 | nr = dso__load(map->dso, map); | 308 | nr = dso__load(map->dso, map); |
| @@ -348,7 +346,7 @@ struct symbol *map__find_symbol(struct map *map, u64 addr) | |||
| 348 | if (map__load(map) < 0) | 346 | if (map__load(map) < 0) |
| 349 | return NULL; | 347 | return NULL; |
| 350 | 348 | ||
| 351 | return dso__find_symbol(map->dso, map->type, addr); | 349 | return dso__find_symbol(map->dso, addr); |
| 352 | } | 350 | } |
| 353 | 351 | ||
| 354 | struct symbol *map__find_symbol_by_name(struct map *map, const char *name) | 352 | struct symbol *map__find_symbol_by_name(struct map *map, const char *name) |
| @@ -356,10 +354,10 @@ struct symbol *map__find_symbol_by_name(struct map *map, const char *name) | |||
| 356 | if (map__load(map) < 0) | 354 | if (map__load(map) < 0) |
| 357 | return NULL; | 355 | return NULL; |
| 358 | 356 | ||
| 359 | if (!dso__sorted_by_name(map->dso, map->type)) | 357 | if (!dso__sorted_by_name(map->dso)) |
| 360 | dso__sort_by_name(map->dso, map->type); | 358 | dso__sort_by_name(map->dso); |
| 361 | 359 | ||
| 362 | return dso__find_symbol_by_name(map->dso, map->type, name); | 360 | return dso__find_symbol_by_name(map->dso, name); |
| 363 | } | 361 | } |
| 364 | 362 | ||
| 365 | struct map *map__clone(struct map *from) | 363 | struct map *map__clone(struct map *from) |
| @@ -494,10 +492,7 @@ static void maps__init(struct maps *maps) | |||
| 494 | 492 | ||
| 495 | void map_groups__init(struct map_groups *mg, struct machine *machine) | 493 | void map_groups__init(struct map_groups *mg, struct machine *machine) |
| 496 | { | 494 | { |
| 497 | int i; | 495 | maps__init(&mg->maps); |
| 498 | for (i = 0; i < MAP__NR_TYPES; ++i) { | ||
| 499 | maps__init(&mg->maps[i]); | ||
| 500 | } | ||
| 501 | mg->machine = machine; | 496 | mg->machine = machine; |
| 502 | refcount_set(&mg->refcnt, 1); | 497 | refcount_set(&mg->refcnt, 1); |
| 503 | } | 498 | } |
| @@ -525,22 +520,12 @@ static void maps__exit(struct maps *maps) | |||
| 525 | 520 | ||
| 526 | void map_groups__exit(struct map_groups *mg) | 521 | void map_groups__exit(struct map_groups *mg) |
| 527 | { | 522 | { |
| 528 | int i; | 523 | maps__exit(&mg->maps); |
| 529 | |||
| 530 | for (i = 0; i < MAP__NR_TYPES; ++i) | ||
| 531 | maps__exit(&mg->maps[i]); | ||
| 532 | } | 524 | } |
| 533 | 525 | ||
| 534 | bool map_groups__empty(struct map_groups *mg) | 526 | bool map_groups__empty(struct map_groups *mg) |
| 535 | { | 527 | { |
| 536 | int i; | 528 | 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 | } | 529 | } |
| 545 | 530 | ||
| 546 | struct map_groups *map_groups__new(struct machine *machine) | 531 | struct map_groups *map_groups__new(struct machine *machine) |
| @@ -566,10 +551,9 @@ void map_groups__put(struct map_groups *mg) | |||
| 566 | } | 551 | } |
| 567 | 552 | ||
| 568 | struct symbol *map_groups__find_symbol(struct map_groups *mg, | 553 | struct symbol *map_groups__find_symbol(struct map_groups *mg, |
| 569 | enum map_type type, u64 addr, | 554 | u64 addr, struct map **mapp) |
| 570 | struct map **mapp) | ||
| 571 | { | 555 | { |
| 572 | struct map *map = map_groups__find(mg, type, addr); | 556 | struct map *map = map_groups__find(mg, addr); |
| 573 | 557 | ||
| 574 | /* Ensure map is loaded before using map->map_ip */ | 558 | /* Ensure map is loaded before using map->map_ip */ |
| 575 | if (map != NULL && map__load(map) >= 0) { | 559 | if (map != NULL && map__load(map) >= 0) { |
| @@ -608,13 +592,10 @@ out: | |||
| 608 | } | 592 | } |
| 609 | 593 | ||
| 610 | struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg, | 594 | struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg, |
| 611 | enum map_type type, | ||
| 612 | const char *name, | 595 | const char *name, |
| 613 | struct map **mapp) | 596 | struct map **mapp) |
| 614 | { | 597 | { |
| 615 | struct symbol *sym = maps__find_symbol_by_name(&mg->maps[type], name, mapp); | 598 | return maps__find_symbol_by_name(&mg->maps, name, mapp); |
| 616 | |||
| 617 | return sym; | ||
| 618 | } | 599 | } |
| 619 | 600 | ||
| 620 | int map_groups__find_ams(struct addr_map_symbol *ams) | 601 | int map_groups__find_ams(struct addr_map_symbol *ams) |
| @@ -622,8 +603,7 @@ int map_groups__find_ams(struct addr_map_symbol *ams) | |||
| 622 | if (ams->addr < ams->map->start || ams->addr >= ams->map->end) { | 603 | if (ams->addr < ams->map->start || ams->addr >= ams->map->end) { |
| 623 | if (ams->map->groups == NULL) | 604 | if (ams->map->groups == NULL) |
| 624 | return -1; | 605 | return -1; |
| 625 | ams->map = map_groups__find(ams->map->groups, ams->map->type, | 606 | ams->map = map_groups__find(ams->map->groups, ams->addr); |
| 626 | ams->addr); | ||
| 627 | if (ams->map == NULL) | 607 | if (ams->map == NULL) |
| 628 | return -1; | 608 | return -1; |
| 629 | } | 609 | } |
| @@ -646,7 +626,7 @@ static size_t maps__fprintf(struct maps *maps, FILE *fp) | |||
| 646 | printed += fprintf(fp, "Map:"); | 626 | printed += fprintf(fp, "Map:"); |
| 647 | printed += map__fprintf(pos, fp); | 627 | printed += map__fprintf(pos, fp); |
| 648 | if (verbose > 2) { | 628 | if (verbose > 2) { |
| 649 | printed += dso__fprintf(pos->dso, pos->type, fp); | 629 | printed += dso__fprintf(pos->dso, fp); |
| 650 | printed += fprintf(fp, "--\n"); | 630 | printed += fprintf(fp, "--\n"); |
| 651 | } | 631 | } |
| 652 | } | 632 | } |
| @@ -656,24 +636,14 @@ static size_t maps__fprintf(struct maps *maps, FILE *fp) | |||
| 656 | return printed; | 636 | return printed; |
| 657 | } | 637 | } |
| 658 | 638 | ||
| 659 | size_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 | |||
| 666 | size_t map_groups__fprintf(struct map_groups *mg, FILE *fp) | 639 | size_t map_groups__fprintf(struct map_groups *mg, FILE *fp) |
| 667 | { | 640 | { |
| 668 | size_t printed = 0, i; | 641 | 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 | } | 642 | } |
| 673 | 643 | ||
| 674 | static void __map_groups__insert(struct map_groups *mg, struct map *map) | 644 | static void __map_groups__insert(struct map_groups *mg, struct map *map) |
| 675 | { | 645 | { |
| 676 | __maps__insert(&mg->maps[map->type], map); | 646 | __maps__insert(&mg->maps, map); |
| 677 | map->groups = mg; | 647 | map->groups = mg; |
| 678 | } | 648 | } |
| 679 | 649 | ||
| @@ -758,19 +728,18 @@ out: | |||
| 758 | int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map, | 728 | int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map, |
| 759 | FILE *fp) | 729 | FILE *fp) |
| 760 | { | 730 | { |
| 761 | return maps__fixup_overlappings(&mg->maps[map->type], map, fp); | 731 | return maps__fixup_overlappings(&mg->maps, map, fp); |
| 762 | } | 732 | } |
| 763 | 733 | ||
| 764 | /* | 734 | /* |
| 765 | * XXX This should not really _copy_ te maps, but refcount them. | 735 | * XXX This should not really _copy_ te maps, but refcount them. |
| 766 | */ | 736 | */ |
| 767 | int map_groups__clone(struct thread *thread, | 737 | int map_groups__clone(struct thread *thread, struct map_groups *parent) |
| 768 | struct map_groups *parent, enum map_type type) | ||
| 769 | { | 738 | { |
| 770 | struct map_groups *mg = thread->mg; | 739 | struct map_groups *mg = thread->mg; |
| 771 | int err = -ENOMEM; | 740 | int err = -ENOMEM; |
| 772 | struct map *map; | 741 | struct map *map; |
| 773 | struct maps *maps = &parent->maps[type]; | 742 | struct maps *maps = &parent->maps; |
| 774 | 743 | ||
| 775 | down_read(&maps->lock); | 744 | down_read(&maps->lock); |
| 776 | 745 | ||
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h index 0e9bbe01b0ab..f1afe1ab6ff7 100644 --- a/tools/perf/util/map.h +++ b/tools/perf/util/map.h | |||
| @@ -12,15 +12,6 @@ | |||
| 12 | #include <linux/types.h> | 12 | #include <linux/types.h> |
| 13 | #include "rwsem.h" | 13 | #include "rwsem.h" |
| 14 | 14 | ||
| 15 | enum map_type { | ||
| 16 | MAP__FUNCTION = 0, | ||
| 17 | MAP__VARIABLE, | ||
| 18 | }; | ||
| 19 | |||
| 20 | #define MAP__NR_TYPES (MAP__VARIABLE + 1) | ||
| 21 | |||
| 22 | extern const char *map_type__name[MAP__NR_TYPES]; | ||
| 23 | |||
| 24 | struct dso; | 15 | struct dso; |
| 25 | struct ip_callchain; | 16 | struct ip_callchain; |
| 26 | struct ref_reloc_sym; | 17 | struct ref_reloc_sym; |
| @@ -35,7 +26,6 @@ struct map { | |||
| 35 | }; | 26 | }; |
| 36 | u64 start; | 27 | u64 start; |
| 37 | u64 end; | 28 | u64 end; |
| 38 | u8 /* enum map_type */ type; | ||
| 39 | bool erange_warned; | 29 | bool erange_warned; |
| 40 | u32 priv; | 30 | u32 priv; |
| 41 | u32 prot; | 31 | u32 prot; |
| @@ -67,7 +57,7 @@ struct maps { | |||
| 67 | }; | 57 | }; |
| 68 | 58 | ||
| 69 | struct map_groups { | 59 | struct map_groups { |
| 70 | struct maps maps[MAP__NR_TYPES]; | 60 | struct maps maps; |
| 71 | struct machine *machine; | 61 | struct machine *machine; |
| 72 | refcount_t refcnt; | 62 | refcount_t refcnt; |
| 73 | }; | 63 | }; |
| @@ -125,7 +115,7 @@ struct thread; | |||
| 125 | * Note: caller must ensure map->dso is not NULL (map is loaded). | 115 | * Note: caller must ensure map->dso is not NULL (map is loaded). |
| 126 | */ | 116 | */ |
| 127 | #define map__for_each_symbol(map, pos, n) \ | 117 | #define map__for_each_symbol(map, pos, n) \ |
| 128 | dso__for_each_symbol(map->dso, pos, n, map->type) | 118 | dso__for_each_symbol(map->dso, pos, n) |
| 129 | 119 | ||
| 130 | /* map__for_each_symbol_with_name - iterate over the symbols in the given map | 120 | /* map__for_each_symbol_with_name - iterate over the symbols in the given map |
| 131 | * that have the given name | 121 | * that have the given name |
| @@ -144,13 +134,13 @@ struct thread; | |||
| 144 | #define map__for_each_symbol_by_name(map, sym_name, pos) \ | 134 | #define map__for_each_symbol_by_name(map, sym_name, pos) \ |
| 145 | __map__for_each_symbol_by_name(map, sym_name, (pos)) | 135 | __map__for_each_symbol_by_name(map, sym_name, (pos)) |
| 146 | 136 | ||
| 147 | void map__init(struct map *map, enum map_type type, | 137 | void map__init(struct map *map, |
| 148 | u64 start, u64 end, u64 pgoff, struct dso *dso); | 138 | u64 start, u64 end, u64 pgoff, struct dso *dso); |
| 149 | struct map *map__new(struct machine *machine, u64 start, u64 len, | 139 | struct map *map__new(struct machine *machine, u64 start, u64 len, |
| 150 | u64 pgoff, u32 d_maj, u32 d_min, u64 ino, | 140 | u64 pgoff, u32 d_maj, u32 d_min, u64 ino, |
| 151 | u64 ino_gen, u32 prot, u32 flags, | 141 | u64 ino_gen, u32 prot, u32 flags, |
| 152 | char *filename, enum map_type type, struct thread *thread); | 142 | char *filename, struct thread *thread); |
| 153 | struct map *map__new2(u64 start, struct dso *dso, enum map_type type); | 143 | struct map *map__new2(u64 start, struct dso *dso); |
| 154 | void map__delete(struct map *map); | 144 | void map__delete(struct map *map); |
| 155 | struct map *map__clone(struct map *map); | 145 | struct map *map__clone(struct map *map); |
| 156 | 146 | ||
| @@ -185,8 +175,6 @@ void map__fixup_end(struct map *map); | |||
| 185 | 175 | ||
| 186 | void map__reloc_vmlinux(struct map *map); | 176 | void map__reloc_vmlinux(struct map *map); |
| 187 | 177 | ||
| 188 | size_t __map_groups__fprintf_maps(struct map_groups *mg, enum map_type type, | ||
| 189 | FILE *fp); | ||
| 190 | void maps__insert(struct maps *maps, struct map *map); | 178 | void maps__insert(struct maps *maps, struct map *map); |
| 191 | void maps__remove(struct maps *maps, struct map *map); | 179 | void maps__remove(struct maps *maps, struct map *map); |
| 192 | struct map *maps__find(struct maps *maps, u64 addr); | 180 | struct map *maps__find(struct maps *maps, u64 addr); |
| @@ -197,34 +185,29 @@ struct symbol *maps__find_symbol_by_name(struct maps *maps, const char *name, | |||
| 197 | void map_groups__init(struct map_groups *mg, struct machine *machine); | 185 | void map_groups__init(struct map_groups *mg, struct machine *machine); |
| 198 | void map_groups__exit(struct map_groups *mg); | 186 | void map_groups__exit(struct map_groups *mg); |
| 199 | int map_groups__clone(struct thread *thread, | 187 | int map_groups__clone(struct thread *thread, |
| 200 | struct map_groups *parent, enum map_type type); | 188 | struct map_groups *parent); |
| 201 | size_t map_groups__fprintf(struct map_groups *mg, FILE *fp); | 189 | size_t map_groups__fprintf(struct map_groups *mg, FILE *fp); |
| 202 | 190 | ||
| 203 | int maps__set_kallsyms_ref_reloc_sym(struct map **maps, const char *symbol_name, | 191 | int map__set_kallsyms_ref_reloc_sym(struct map *map, const char *symbol_name, |
| 204 | u64 addr); | 192 | u64 addr); |
| 205 | 193 | ||
| 206 | static inline void map_groups__insert(struct map_groups *mg, struct map *map) | 194 | static inline void map_groups__insert(struct map_groups *mg, struct map *map) |
| 207 | { | 195 | { |
| 208 | maps__insert(&mg->maps[map->type], map); | 196 | maps__insert(&mg->maps, map); |
| 209 | map->groups = mg; | 197 | map->groups = mg; |
| 210 | } | 198 | } |
| 211 | 199 | ||
| 212 | static inline void map_groups__remove(struct map_groups *mg, struct map *map) | 200 | static inline void map_groups__remove(struct map_groups *mg, struct map *map) |
| 213 | { | 201 | { |
| 214 | maps__remove(&mg->maps[map->type], map); | 202 | maps__remove(&mg->maps, map); |
| 215 | } | 203 | } |
| 216 | 204 | ||
| 217 | static inline struct map *map_groups__find(struct map_groups *mg, | 205 | static inline struct map *map_groups__find(struct map_groups *mg, u64 addr) |
| 218 | enum map_type type, u64 addr) | ||
| 219 | { | 206 | { |
| 220 | return maps__find(&mg->maps[type], addr); | 207 | return maps__find(&mg->maps, addr); |
| 221 | } | 208 | } |
| 222 | 209 | ||
| 223 | static inline struct map *map_groups__first(struct map_groups *mg, | 210 | struct map *map_groups__first(struct map_groups *mg); |
| 224 | enum map_type type) | ||
| 225 | { | ||
| 226 | return maps__first(&mg->maps[type]); | ||
| 227 | } | ||
| 228 | 211 | ||
| 229 | static inline struct map *map_groups__next(struct map *map) | 212 | static inline struct map *map_groups__next(struct map *map) |
| 230 | { | 213 | { |
| @@ -232,11 +215,9 @@ static inline struct map *map_groups__next(struct map *map) | |||
| 232 | } | 215 | } |
| 233 | 216 | ||
| 234 | struct symbol *map_groups__find_symbol(struct map_groups *mg, | 217 | struct symbol *map_groups__find_symbol(struct map_groups *mg, |
| 235 | enum map_type type, u64 addr, | 218 | u64 addr, struct map **mapp); |
| 236 | struct map **mapp); | ||
| 237 | 219 | ||
| 238 | struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg, | 220 | struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg, |
| 239 | enum map_type type, | ||
| 240 | const char *name, | 221 | const char *name, |
| 241 | struct map **mapp); | 222 | struct map **mapp); |
| 242 | 223 | ||
| @@ -244,18 +225,10 @@ struct addr_map_symbol; | |||
| 244 | 225 | ||
| 245 | int map_groups__find_ams(struct addr_map_symbol *ams); | 226 | int map_groups__find_ams(struct addr_map_symbol *ams); |
| 246 | 227 | ||
| 247 | static inline | ||
| 248 | struct 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 | |||
| 254 | int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map, | 228 | int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map, |
| 255 | FILE *fp); | 229 | FILE *fp); |
| 256 | 230 | ||
| 257 | struct map *map_groups__find_by_name(struct map_groups *mg, | 231 | struct map *map_groups__find_by_name(struct map_groups *mg, const char *name); |
| 258 | enum map_type type, const char *name); | ||
| 259 | 232 | ||
| 260 | bool __map__is_kernel(const struct map *map); | 233 | bool __map__is_kernel(const struct map *map); |
| 261 | 234 | ||
| @@ -264,4 +237,6 @@ static inline bool __map__is_kmodule(const struct map *map) | |||
| 264 | return !__map__is_kernel(map); | 237 | return !__map__is_kernel(map); |
| 265 | } | 238 | } |
| 266 | 239 | ||
| 240 | bool map__has_symbols(const struct map *map); | ||
| 241 | |||
| 267 | #endif /* __PERF_MAP_H */ | 242 | #endif /* __PERF_MAP_H */ |
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 | ||
| 114 | static 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 | |||
| 120 | static struct symbol *__find_kernel_function(u64 addr, struct map **mapp) | ||
| 121 | { | ||
| 122 | return machine__find_kernel_function(host_machine, addr, mapp); | ||
| 123 | } | ||
| 124 | |||
| 125 | static struct ref_reloc_sym *kernel_get_ref_reloc_sym(void) | 114 | static 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 | ||
| 162 | static struct map *kernel_get_module_map(const char *module) | 151 | static 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 | |||
| 3520 | end: | 3507 | end: |
| 3521 | map__put(map); | 3508 | map__put(map); |
| 3522 | exit_probe_symbol_maps(); | 3509 | exit_probe_symbol_maps(); |
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 | ||
| 1976 | int maps__set_kallsyms_ref_reloc_sym(struct map **maps, | 1976 | int 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..e65903a695a6 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)) |
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 | ||
| 10 | struct stats | 10 | struct 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..48943b834f11 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 | ||
| 117 | static bool elf_sym__is_a(GElf_Sym *sym, enum map_type type) | 117 | static 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 | ||
| 129 | static inline const char *elf_sym__name(const GElf_Sym *sym, | 122 | static 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 | ||
| 153 | static bool elf_sec__is_a(GElf_Shdr *shdr, Elf_Data *secstrs, | 146 | static 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 | ||
| 166 | static size_t elf_addr_to_index(Elf *elf, GElf_Addr addr) | 152 | static 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 | */ |
| 259 | int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, struct map *map) | 245 | int 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) | |||
| 811 | void __weak arch__sym_update(struct symbol *s __maybe_unused, | 797 | void __weak arch__sym_update(struct symbol *s __maybe_unused, |
| 812 | GElf_Sym *sym __maybe_unused) { } | 798 | GElf_Sym *sym __maybe_unused) { } |
| 813 | 799 | ||
| 800 | static 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 | |||
| 814 | int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss, | 904 | int 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 | } |
| 1099 | new_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; |
| @@ -1413,7 +1406,7 @@ static int kcore_copy__process_kallsyms(void *arg, const char *name, char type, | |||
| 1413 | { | 1406 | { |
| 1414 | struct kcore_copy_info *kci = arg; | 1407 | struct kcore_copy_info *kci = arg; |
| 1415 | 1408 | ||
| 1416 | if (!symbol_type__is_a(type, MAP__FUNCTION)) | 1409 | if (!kallsyms__is_function(type)) |
| 1417 | return 0; | 1410 | return 0; |
| 1418 | 1411 | ||
| 1419 | if (strchr(name, '[')) { | 1412 | if (strchr(name, '[')) { |
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 | ||
| 290 | int dso__synthesize_plt_symbols(struct dso *dso __maybe_unused, | 290 | int 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..f48dc157c2bd 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 | ||
| 73 | bool symbol_type__is_a(char symbol_type, enum map_type map_type) | 74 | static 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 | ||
| 87 | static int prefix_underscores_count(const char *str) | 80 | static 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 | ||
| 231 | void __map_groups__fixup_end(struct map_groups *mg, enum map_type type) | 224 | void 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 | ||
| 259 | struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name) | 252 | struct 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 | ||
| 485 | void dso__reset_find_symbol_cache(struct dso *dso) | 479 | void 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 | ||
| 495 | void dso__insert_symbol(struct dso *dso, enum map_type type, struct symbol *sym) | 485 | void 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 | ||
| 507 | struct symbol *dso__find_symbol(struct dso *dso, | 497 | struct 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 | ||
| 518 | struct symbol *dso__first_symbol(struct dso *dso, enum map_type type) | 507 | struct 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 | ||
| 523 | struct symbol *dso__last_symbol(struct dso *dso, enum map_type type) | 512 | struct 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 | ||
| 528 | struct symbol *dso__next_symbol(struct symbol *sym) | 517 | struct 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 | */ |
| 544 | struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, | 533 | struct 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 | ||
| 555 | void dso__sort_by_name(struct dso *dso, enum map_type type) | 543 | void 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 | ||
| 562 | int modules__parse(const char *filename, void *arg, | 549 | int modules__parse(const char *filename, void *arg, |
| @@ -621,11 +608,6 @@ out: | |||
| 621 | return err; | 608 | return err; |
| 622 | } | 609 | } |
| 623 | 610 | ||
| 624 | struct 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 | */ |
| 692 | static int dso__load_all_kallsyms(struct dso *dso, const char *filename, | 674 | static 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 | ||
| 699 | static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map) | 679 | static 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,14 +727,14 @@ 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 | */ |
| 751 | static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta) | 730 | static 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; |
| 761 | 740 | ||
| @@ -778,7 +757,7 @@ static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta) | |||
| 778 | *module++ = '\0'; | 757 | *module++ = '\0'; |
| 779 | 758 | ||
| 780 | if (strcmp(curr_map->dso->short_name, module)) { | 759 | if (strcmp(curr_map->dso->short_name, module)) { |
| 781 | if (curr_map != map && | 760 | if (curr_map != initial_map && |
| 782 | dso->kernel == DSO_TYPE_GUEST_KERNEL && | 761 | dso->kernel == DSO_TYPE_GUEST_KERNEL && |
| 783 | machine__is_default_guest(machine)) { | 762 | machine__is_default_guest(machine)) { |
| 784 | /* | 763 | /* |
| @@ -788,18 +767,16 @@ static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta) | |||
| 788 | * symbols are in its kmap. Mark it as | 767 | * symbols are in its kmap. Mark it as |
| 789 | * loaded. | 768 | * loaded. |
| 790 | */ | 769 | */ |
| 791 | dso__set_loaded(curr_map->dso, | 770 | dso__set_loaded(curr_map->dso); |
| 792 | curr_map->type); | ||
| 793 | } | 771 | } |
| 794 | 772 | ||
| 795 | curr_map = map_groups__find_by_name(kmaps, | 773 | curr_map = map_groups__find_by_name(kmaps, module); |
| 796 | map->type, module); | ||
| 797 | if (curr_map == NULL) { | 774 | if (curr_map == NULL) { |
| 798 | pr_debug("%s/proc/{kallsyms,modules} " | 775 | pr_debug("%s/proc/{kallsyms,modules} " |
| 799 | "inconsistency while looking " | 776 | "inconsistency while looking " |
| 800 | "for \"%s\" module!\n", | 777 | "for \"%s\" module!\n", |
| 801 | machine->root_dir, module); | 778 | machine->root_dir, module); |
| 802 | curr_map = map; | 779 | curr_map = initial_map; |
| 803 | goto discard_symbol; | 780 | goto discard_symbol; |
| 804 | } | 781 | } |
| 805 | 782 | ||
| @@ -809,11 +786,11 @@ static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta) | |||
| 809 | } | 786 | } |
| 810 | /* | 787 | /* |
| 811 | * So that we look just like we get from .ko files, | 788 | * So that we look just like we get from .ko files, |
| 812 | * i.e. not prelinked, relative to map->start. | 789 | * i.e. not prelinked, relative to initial_map->start. |
| 813 | */ | 790 | */ |
| 814 | pos->start = curr_map->map_ip(curr_map, pos->start); | 791 | pos->start = curr_map->map_ip(curr_map, pos->start); |
| 815 | pos->end = curr_map->map_ip(curr_map, pos->end); | 792 | pos->end = curr_map->map_ip(curr_map, pos->end); |
| 816 | } else if (curr_map != map) { | 793 | } else if (curr_map != initial_map) { |
| 817 | char dso_name[PATH_MAX]; | 794 | char dso_name[PATH_MAX]; |
| 818 | struct dso *ndso; | 795 | struct dso *ndso; |
| 819 | 796 | ||
| @@ -824,7 +801,7 @@ static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta) | |||
| 824 | } | 801 | } |
| 825 | 802 | ||
| 826 | if (count == 0) { | 803 | if (count == 0) { |
| 827 | curr_map = map; | 804 | curr_map = initial_map; |
| 828 | goto add_symbol; | 805 | goto add_symbol; |
| 829 | } | 806 | } |
| 830 | 807 | ||
| @@ -843,7 +820,7 @@ static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta) | |||
| 843 | 820 | ||
| 844 | ndso->kernel = dso->kernel; | 821 | ndso->kernel = dso->kernel; |
| 845 | 822 | ||
| 846 | curr_map = map__new2(pos->start, ndso, map->type); | 823 | curr_map = map__new2(pos->start, ndso); |
| 847 | if (curr_map == NULL) { | 824 | if (curr_map == NULL) { |
| 848 | dso__put(ndso); | 825 | dso__put(ndso); |
| 849 | return -1; | 826 | return -1; |
| @@ -858,9 +835,9 @@ static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta) | |||
| 858 | pos->end -= delta; | 835 | pos->end -= delta; |
| 859 | } | 836 | } |
| 860 | add_symbol: | 837 | add_symbol: |
| 861 | if (curr_map != map) { | 838 | if (curr_map != initial_map) { |
| 862 | rb_erase(&pos->rb_node, root); | 839 | rb_erase(&pos->rb_node, root); |
| 863 | symbols__insert(&curr_map->dso->symbols[curr_map->type], pos); | 840 | symbols__insert(&curr_map->dso->symbols, pos); |
| 864 | ++moved; | 841 | ++moved; |
| 865 | } else | 842 | } else |
| 866 | ++count; | 843 | ++count; |
| @@ -871,10 +848,10 @@ discard_symbol: | |||
| 871 | symbol__delete(pos); | 848 | symbol__delete(pos); |
| 872 | } | 849 | } |
| 873 | 850 | ||
| 874 | if (curr_map != map && | 851 | if (curr_map != initial_map && |
| 875 | dso->kernel == DSO_TYPE_GUEST_KERNEL && | 852 | dso->kernel == DSO_TYPE_GUEST_KERNEL && |
| 876 | machine__is_default_guest(kmaps->machine)) { | 853 | machine__is_default_guest(kmaps->machine)) { |
| 877 | dso__set_loaded(curr_map->dso, curr_map->type); | 854 | dso__set_loaded(curr_map->dso); |
| 878 | } | 855 | } |
| 879 | 856 | ||
| 880 | return count + moved; | 857 | return count + moved; |
| @@ -1035,6 +1012,11 @@ out_delete_from: | |||
| 1035 | return ret; | 1012 | return ret; |
| 1036 | } | 1013 | } |
| 1037 | 1014 | ||
| 1015 | struct map *map_groups__first(struct map_groups *mg) | ||
| 1016 | { | ||
| 1017 | return maps__first(&mg->maps); | ||
| 1018 | } | ||
| 1019 | |||
| 1038 | static int do_validate_kcore_modules(const char *filename, struct map *map, | 1020 | static int do_validate_kcore_modules(const char *filename, struct map *map, |
| 1039 | struct map_groups *kmaps) | 1021 | struct map_groups *kmaps) |
| 1040 | { | 1022 | { |
| @@ -1046,7 +1028,7 @@ static int do_validate_kcore_modules(const char *filename, struct map *map, | |||
| 1046 | if (err) | 1028 | if (err) |
| 1047 | return err; | 1029 | return err; |
| 1048 | 1030 | ||
| 1049 | old_map = map_groups__first(kmaps, map->type); | 1031 | old_map = map_groups__first(kmaps); |
| 1050 | while (old_map) { | 1032 | while (old_map) { |
| 1051 | struct map *next = map_groups__next(old_map); | 1033 | struct map *next = map_groups__next(old_map); |
| 1052 | struct module_info *mi; | 1034 | struct module_info *mi; |
| @@ -1138,7 +1120,6 @@ static int validate_kcore_addresses(const char *kallsyms_filename, | |||
| 1138 | 1120 | ||
| 1139 | struct kcore_mapfn_data { | 1121 | struct kcore_mapfn_data { |
| 1140 | struct dso *dso; | 1122 | struct dso *dso; |
| 1141 | enum map_type type; | ||
| 1142 | struct list_head maps; | 1123 | struct list_head maps; |
| 1143 | }; | 1124 | }; |
| 1144 | 1125 | ||
| @@ -1147,7 +1128,7 @@ static int kcore_mapfn(u64 start, u64 len, u64 pgoff, void *data) | |||
| 1147 | struct kcore_mapfn_data *md = data; | 1128 | struct kcore_mapfn_data *md = data; |
| 1148 | struct map *map; | 1129 | struct map *map; |
| 1149 | 1130 | ||
| 1150 | map = map__new2(start, md->dso, md->type); | 1131 | map = map__new2(start, md->dso); |
| 1151 | if (map == NULL) | 1132 | if (map == NULL) |
| 1152 | return -ENOMEM; | 1133 | return -ENOMEM; |
| 1153 | 1134 | ||
| @@ -1163,7 +1144,6 @@ static int dso__load_kcore(struct dso *dso, struct map *map, | |||
| 1163 | const char *kallsyms_filename) | 1144 | const char *kallsyms_filename) |
| 1164 | { | 1145 | { |
| 1165 | struct map_groups *kmaps = map__kmaps(map); | 1146 | struct map_groups *kmaps = map__kmaps(map); |
| 1166 | struct machine *machine; | ||
| 1167 | struct kcore_mapfn_data md; | 1147 | struct kcore_mapfn_data md; |
| 1168 | struct map *old_map, *new_map, *replacement_map = NULL; | 1148 | struct map *old_map, *new_map, *replacement_map = NULL; |
| 1169 | bool is_64_bit; | 1149 | bool is_64_bit; |
| @@ -1174,10 +1154,8 @@ static int dso__load_kcore(struct dso *dso, struct map *map, | |||
| 1174 | if (!kmaps) | 1154 | if (!kmaps) |
| 1175 | return -EINVAL; | 1155 | return -EINVAL; |
| 1176 | 1156 | ||
| 1177 | machine = kmaps->machine; | ||
| 1178 | |||
| 1179 | /* This function requires that the map is the kernel map */ | 1157 | /* This function requires that the map is the kernel map */ |
| 1180 | if (map != machine->vmlinux_maps[map->type]) | 1158 | if (!__map__is_kernel(map)) |
| 1181 | return -EINVAL; | 1159 | return -EINVAL; |
| 1182 | 1160 | ||
| 1183 | if (!filename_from_kallsyms_filename(kcore_filename, "kcore", | 1161 | if (!filename_from_kallsyms_filename(kcore_filename, "kcore", |
| @@ -1189,7 +1167,6 @@ static int dso__load_kcore(struct dso *dso, struct map *map, | |||
| 1189 | return -EINVAL; | 1167 | return -EINVAL; |
| 1190 | 1168 | ||
| 1191 | md.dso = dso; | 1169 | md.dso = dso; |
| 1192 | md.type = map->type; | ||
| 1193 | INIT_LIST_HEAD(&md.maps); | 1170 | INIT_LIST_HEAD(&md.maps); |
| 1194 | 1171 | ||
| 1195 | fd = open(kcore_filename, O_RDONLY); | 1172 | fd = open(kcore_filename, O_RDONLY); |
| @@ -1200,7 +1177,7 @@ static int dso__load_kcore(struct dso *dso, struct map *map, | |||
| 1200 | } | 1177 | } |
| 1201 | 1178 | ||
| 1202 | /* Read new maps into temporary lists */ | 1179 | /* Read new maps into temporary lists */ |
| 1203 | err = file__read_maps(fd, md.type == MAP__FUNCTION, kcore_mapfn, &md, | 1180 | err = file__read_maps(fd, map->prot & PROT_EXEC, kcore_mapfn, &md, |
| 1204 | &is_64_bit); | 1181 | &is_64_bit); |
| 1205 | if (err) | 1182 | if (err) |
| 1206 | goto out_err; | 1183 | goto out_err; |
| @@ -1212,7 +1189,7 @@ static int dso__load_kcore(struct dso *dso, struct map *map, | |||
| 1212 | } | 1189 | } |
| 1213 | 1190 | ||
| 1214 | /* Remove old maps */ | 1191 | /* Remove old maps */ |
| 1215 | old_map = map_groups__first(kmaps, map->type); | 1192 | old_map = map_groups__first(kmaps); |
| 1216 | while (old_map) { | 1193 | while (old_map) { |
| 1217 | struct map *next = map_groups__next(old_map); | 1194 | struct map *next = map_groups__next(old_map); |
| 1218 | 1195 | ||
| @@ -1222,7 +1199,7 @@ static int dso__load_kcore(struct dso *dso, struct map *map, | |||
| 1222 | } | 1199 | } |
| 1223 | 1200 | ||
| 1224 | /* Find the kernel map using the first symbol */ | 1201 | /* Find the kernel map using the first symbol */ |
| 1225 | sym = dso__first_symbol(dso, map->type); | 1202 | sym = dso__first_symbol(dso); |
| 1226 | list_for_each_entry(new_map, &md.maps, node) { | 1203 | list_for_each_entry(new_map, &md.maps, node) { |
| 1227 | if (sym && sym->start >= new_map->start && | 1204 | if (sym && sym->start >= new_map->start && |
| 1228 | sym->start < new_map->end) { | 1205 | sym->start < new_map->end) { |
| @@ -1268,7 +1245,7 @@ static int dso__load_kcore(struct dso *dso, struct map *map, | |||
| 1268 | 1245 | ||
| 1269 | close(fd); | 1246 | close(fd); |
| 1270 | 1247 | ||
| 1271 | if (map->type == MAP__FUNCTION) | 1248 | if (map->prot & PROT_EXEC) |
| 1272 | pr_debug("Using %s for kernel object code\n", kcore_filename); | 1249 | pr_debug("Using %s for kernel object code\n", kcore_filename); |
| 1273 | else | 1250 | else |
| 1274 | pr_debug("Using %s for kernel data\n", kcore_filename); | 1251 | pr_debug("Using %s for kernel data\n", kcore_filename); |
| @@ -1289,14 +1266,10 @@ out_err: | |||
| 1289 | * If the kernel is relocated at boot time, kallsyms won't match. Compute the | 1266 | * If the kernel is relocated at boot time, kallsyms won't match. Compute the |
| 1290 | * delta based on the relocation reference symbol. | 1267 | * delta based on the relocation reference symbol. |
| 1291 | */ | 1268 | */ |
| 1292 | static int kallsyms__delta(struct map *map, const char *filename, u64 *delta) | 1269 | static int kallsyms__delta(struct kmap *kmap, const char *filename, u64 *delta) |
| 1293 | { | 1270 | { |
| 1294 | struct kmap *kmap = map__kmap(map); | ||
| 1295 | u64 addr; | 1271 | u64 addr; |
| 1296 | 1272 | ||
| 1297 | if (!kmap) | ||
| 1298 | return -1; | ||
| 1299 | |||
| 1300 | if (!kmap->ref_reloc_sym || !kmap->ref_reloc_sym->name) | 1273 | if (!kmap->ref_reloc_sym || !kmap->ref_reloc_sym->name) |
| 1301 | return 0; | 1274 | return 0; |
| 1302 | 1275 | ||
| @@ -1310,19 +1283,23 @@ static int kallsyms__delta(struct map *map, const char *filename, u64 *delta) | |||
| 1310 | int __dso__load_kallsyms(struct dso *dso, const char *filename, | 1283 | int __dso__load_kallsyms(struct dso *dso, const char *filename, |
| 1311 | struct map *map, bool no_kcore) | 1284 | struct map *map, bool no_kcore) |
| 1312 | { | 1285 | { |
| 1286 | struct kmap *kmap = map__kmap(map); | ||
| 1313 | u64 delta = 0; | 1287 | u64 delta = 0; |
| 1314 | 1288 | ||
| 1315 | if (symbol__restricted_filename(filename, "/proc/kallsyms")) | 1289 | if (symbol__restricted_filename(filename, "/proc/kallsyms")) |
| 1316 | return -1; | 1290 | return -1; |
| 1317 | 1291 | ||
| 1318 | if (dso__load_all_kallsyms(dso, filename, map) < 0) | 1292 | if (!kmap || !kmap->kmaps) |
| 1293 | return -1; | ||
| 1294 | |||
| 1295 | if (dso__load_all_kallsyms(dso, filename) < 0) | ||
| 1319 | return -1; | 1296 | return -1; |
| 1320 | 1297 | ||
| 1321 | if (kallsyms__delta(map, filename, &delta)) | 1298 | if (kallsyms__delta(kmap, filename, &delta)) |
| 1322 | return -1; | 1299 | return -1; |
| 1323 | 1300 | ||
| 1324 | symbols__fixup_end(&dso->symbols[map->type]); | 1301 | symbols__fixup_end(&dso->symbols); |
| 1325 | symbols__fixup_duplicate(&dso->symbols[map->type]); | 1302 | symbols__fixup_duplicate(&dso->symbols); |
| 1326 | 1303 | ||
| 1327 | if (dso->kernel == DSO_TYPE_GUEST_KERNEL) | 1304 | if (dso->kernel == DSO_TYPE_GUEST_KERNEL) |
| 1328 | dso->symtab_type = DSO_BINARY_TYPE__GUEST_KALLSYMS; | 1305 | dso->symtab_type = DSO_BINARY_TYPE__GUEST_KALLSYMS; |
| @@ -1330,9 +1307,9 @@ int __dso__load_kallsyms(struct dso *dso, const char *filename, | |||
| 1330 | dso->symtab_type = DSO_BINARY_TYPE__KALLSYMS; | 1307 | dso->symtab_type = DSO_BINARY_TYPE__KALLSYMS; |
| 1331 | 1308 | ||
| 1332 | if (!no_kcore && !dso__load_kcore(dso, map, filename)) | 1309 | if (!no_kcore && !dso__load_kcore(dso, map, filename)) |
| 1333 | return dso__split_kallsyms_for_kcore(dso, map); | 1310 | return map_groups__split_kallsyms_for_kcore(kmap->kmaps, dso); |
| 1334 | else | 1311 | else |
| 1335 | return dso__split_kallsyms(dso, map, delta); | 1312 | return map_groups__split_kallsyms(kmap->kmaps, dso, delta, map); |
| 1336 | } | 1313 | } |
| 1337 | 1314 | ||
| 1338 | int dso__load_kallsyms(struct dso *dso, const char *filename, | 1315 | int dso__load_kallsyms(struct dso *dso, const char *filename, |
| @@ -1341,8 +1318,7 @@ int dso__load_kallsyms(struct dso *dso, const char *filename, | |||
| 1341 | return __dso__load_kallsyms(dso, filename, map, false); | 1318 | return __dso__load_kallsyms(dso, filename, map, false); |
| 1342 | } | 1319 | } |
| 1343 | 1320 | ||
| 1344 | static int dso__load_perf_map(const char *map_path, struct dso *dso, | 1321 | static int dso__load_perf_map(const char *map_path, struct dso *dso) |
| 1345 | struct map *map) | ||
| 1346 | { | 1322 | { |
| 1347 | char *line = NULL; | 1323 | char *line = NULL; |
| 1348 | size_t n; | 1324 | size_t n; |
| @@ -1379,12 +1355,12 @@ static int dso__load_perf_map(const char *map_path, struct dso *dso, | |||
| 1379 | if (len + 2 >= line_len) | 1355 | if (len + 2 >= line_len) |
| 1380 | continue; | 1356 | continue; |
| 1381 | 1357 | ||
| 1382 | sym = symbol__new(start, size, STB_GLOBAL, line + len); | 1358 | sym = symbol__new(start, size, STB_GLOBAL, STT_FUNC, line + len); |
| 1383 | 1359 | ||
| 1384 | if (sym == NULL) | 1360 | if (sym == NULL) |
| 1385 | goto out_delete_line; | 1361 | goto out_delete_line; |
| 1386 | 1362 | ||
| 1387 | symbols__insert(&dso->symbols[map->type], sym); | 1363 | symbols__insert(&dso->symbols, sym); |
| 1388 | nr_syms++; | 1364 | nr_syms++; |
| 1389 | } | 1365 | } |
| 1390 | 1366 | ||
| @@ -1509,7 +1485,7 @@ int dso__load(struct dso *dso, struct map *map) | |||
| 1509 | pthread_mutex_lock(&dso->lock); | 1485 | pthread_mutex_lock(&dso->lock); |
| 1510 | 1486 | ||
| 1511 | /* check again under the dso->lock */ | 1487 | /* check again under the dso->lock */ |
| 1512 | if (dso__loaded(dso, map->type)) { | 1488 | if (dso__loaded(dso)) { |
| 1513 | ret = 1; | 1489 | ret = 1; |
| 1514 | goto out; | 1490 | goto out; |
| 1515 | } | 1491 | } |
| @@ -1542,7 +1518,7 @@ int dso__load(struct dso *dso, struct map *map) | |||
| 1542 | goto out; | 1518 | goto out; |
| 1543 | } | 1519 | } |
| 1544 | 1520 | ||
| 1545 | ret = dso__load_perf_map(map_path, dso, map); | 1521 | ret = dso__load_perf_map(map_path, dso); |
| 1546 | dso->symtab_type = ret > 0 ? DSO_BINARY_TYPE__JAVA_JIT : | 1522 | dso->symtab_type = ret > 0 ? DSO_BINARY_TYPE__JAVA_JIT : |
| 1547 | DSO_BINARY_TYPE__NOT_FOUND; | 1523 | DSO_BINARY_TYPE__NOT_FOUND; |
| 1548 | goto out; | 1524 | goto out; |
| @@ -1651,7 +1627,7 @@ int dso__load(struct dso *dso, struct map *map) | |||
| 1651 | if (ret > 0) { | 1627 | if (ret > 0) { |
| 1652 | int nr_plt; | 1628 | int nr_plt; |
| 1653 | 1629 | ||
| 1654 | nr_plt = dso__synthesize_plt_symbols(dso, runtime_ss, map); | 1630 | nr_plt = dso__synthesize_plt_symbols(dso, runtime_ss); |
| 1655 | if (nr_plt > 0) | 1631 | if (nr_plt > 0) |
| 1656 | ret += nr_plt; | 1632 | ret += nr_plt; |
| 1657 | } | 1633 | } |
| @@ -1663,17 +1639,16 @@ out_free: | |||
| 1663 | if (ret < 0 && strstr(dso->name, " (deleted)") != NULL) | 1639 | if (ret < 0 && strstr(dso->name, " (deleted)") != NULL) |
| 1664 | ret = 0; | 1640 | ret = 0; |
| 1665 | out: | 1641 | out: |
| 1666 | dso__set_loaded(dso, map->type); | 1642 | dso__set_loaded(dso); |
| 1667 | pthread_mutex_unlock(&dso->lock); | 1643 | pthread_mutex_unlock(&dso->lock); |
| 1668 | nsinfo__mountns_exit(&nsc); | 1644 | nsinfo__mountns_exit(&nsc); |
| 1669 | 1645 | ||
| 1670 | return ret; | 1646 | return ret; |
| 1671 | } | 1647 | } |
| 1672 | 1648 | ||
| 1673 | struct map *map_groups__find_by_name(struct map_groups *mg, | 1649 | struct map *map_groups__find_by_name(struct map_groups *mg, const char *name) |
| 1674 | enum map_type type, const char *name) | ||
| 1675 | { | 1650 | { |
| 1676 | struct maps *maps = &mg->maps[type]; | 1651 | struct maps *maps = &mg->maps; |
| 1677 | struct map *map; | 1652 | struct map *map; |
| 1678 | 1653 | ||
| 1679 | down_read(&maps->lock); | 1654 | down_read(&maps->lock); |
| @@ -1720,7 +1695,7 @@ int dso__load_vmlinux(struct dso *dso, struct map *map, | |||
| 1720 | else | 1695 | else |
| 1721 | dso->binary_type = DSO_BINARY_TYPE__VMLINUX; | 1696 | dso->binary_type = DSO_BINARY_TYPE__VMLINUX; |
| 1722 | dso__set_long_name(dso, vmlinux, vmlinux_allocated); | 1697 | dso__set_long_name(dso, vmlinux, vmlinux_allocated); |
| 1723 | dso__set_loaded(dso, map->type); | 1698 | dso__set_loaded(dso); |
| 1724 | pr_debug("Using %s for symbols\n", symfs_vmlinux); | 1699 | pr_debug("Using %s for symbols\n", symfs_vmlinux); |
| 1725 | } | 1700 | } |
| 1726 | 1701 | ||
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); |
| 260 | int dso__load_kallsyms(struct dso *dso, const char *filename, struct map *map); | 261 | int dso__load_kallsyms(struct dso *dso, const char *filename, struct map *map); |
| 261 | 262 | ||
| 262 | void dso__insert_symbol(struct dso *dso, enum map_type type, | 263 | void dso__insert_symbol(struct dso *dso, |
| 263 | struct symbol *sym); | 264 | struct symbol *sym); |
| 264 | 265 | ||
| 265 | struct symbol *dso__find_symbol(struct dso *dso, enum map_type type, | 266 | struct symbol *dso__find_symbol(struct dso *dso, u64 addr); |
| 266 | u64 addr); | 267 | struct symbol *dso__find_symbol_by_name(struct dso *dso, const char *name); |
| 267 | struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, | 268 | |
| 268 | const char *name); | ||
| 269 | struct symbol *symbol__next_by_name(struct symbol *sym); | 269 | struct symbol *symbol__next_by_name(struct symbol *sym); |
| 270 | 270 | ||
| 271 | struct symbol *dso__first_symbol(struct dso *dso, enum map_type type); | 271 | struct symbol *dso__first_symbol(struct dso *dso); |
| 272 | struct symbol *dso__last_symbol(struct dso *dso, enum map_type type); | 272 | struct symbol *dso__last_symbol(struct dso *dso); |
| 273 | struct symbol *dso__next_symbol(struct symbol *sym); | 273 | struct symbol *dso__next_symbol(struct symbol *sym); |
| 274 | 274 | ||
| 275 | enum dso_type dso__type_fd(int fd); | 275 | enum dso_type dso__type_fd(int fd); |
| @@ -288,7 +288,7 @@ void symbol__exit(void); | |||
| 288 | void symbol__elf_init(void); | 288 | void symbol__elf_init(void); |
| 289 | int symbol__annotation_init(void); | 289 | int symbol__annotation_init(void); |
| 290 | 290 | ||
| 291 | struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name); | 291 | struct symbol *symbol__new(u64 start, u64 len, u8 binding, u8 type, const char *name); |
| 292 | size_t __symbol__fprintf_symname_offs(const struct symbol *sym, | 292 | size_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); |
| 301 | size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp); | 301 | size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp); |
| 302 | size_t symbol__fprintf(struct symbol *sym, FILE *fp); | 302 | size_t symbol__fprintf(struct symbol *sym, FILE *fp); |
| 303 | bool symbol_type__is_a(char symbol_type, enum map_type map_type); | ||
| 304 | bool symbol__restricted_filename(const char *filename, | 303 | bool symbol__restricted_filename(const char *filename, |
| 305 | const char *restricted_filename); | 304 | const char *restricted_filename); |
| 306 | int symbol__config_symfs(const struct option *opt __maybe_unused, | 305 | int 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 | ||
| 309 | int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss, | 308 | int 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); |
| 311 | int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, | 310 | int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss); |
| 312 | struct map *map); | ||
| 313 | 311 | ||
| 314 | char *dso__demangle_sym(struct dso *dso, int kmodule, const char *elf_name); | 312 | char *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) | |||
| 317 | void symbols__insert(struct rb_root *symbols, struct symbol *sym); | 315 | void symbols__insert(struct rb_root *symbols, struct symbol *sym); |
| 318 | void symbols__fixup_duplicate(struct rb_root *symbols); | 316 | void symbols__fixup_duplicate(struct rb_root *symbols); |
| 319 | void symbols__fixup_end(struct rb_root *symbols); | 317 | void symbols__fixup_end(struct rb_root *symbols); |
| 320 | void __map_groups__fixup_end(struct map_groups *mg, enum map_type type); | 318 | void map_groups__fixup_end(struct map_groups *mg); |
| 321 | 319 | ||
| 322 | typedef int (*mapfn_t)(u64 start, u64 len, u64 pgoff, void *data); | 320 | typedef int (*mapfn_t)(u64 start, u64 len, u64 pgoff, void *data); |
| 323 | int file__read_maps(int fd, bool exe, mapfn_t mapfn, void *data, | 321 | int 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 | ||
| 60 | size_t dso__fprintf_symbols_by_name(struct dso *dso, | 60 | size_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) | |||
| 302 | static int __thread__prepare_access(struct thread *thread) | 302 | static 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) | |||
| 335 | static int thread__clone_map_groups(struct thread *thread, | 332 | static 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 | ||
| 374 | void thread__find_cpumode_addr_location(struct thread *thread, | 368 | void 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 | ||
| 93 | struct thread *thread__main_thread(struct machine *machine, struct thread *thread); | 93 | struct thread *thread__main_thread(struct machine *machine, struct thread *thread); |
| 94 | 94 | ||
| 95 | void thread__find_addr_map(struct thread *thread, | 95 | struct 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 | ||
| 99 | void thread__find_addr_location(struct thread *thread, | 98 | struct 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 | ||
| 103 | void thread__find_cpumode_addr_location(struct thread *thread, | 101 | void 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 | ||
| 107 | static inline void *thread__priv(struct thread *thread) | 104 | static inline void *thread__priv(struct thread *thread) |
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, | |||
| 366 | static struct map *find_map(unw_word_t ip, struct unwind_info *ui) | 366 | static 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 | ||
| 384 | static int | 372 | static 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/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); |
