diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2018-04-27 21:15:24 +0300 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2018-04-27 21:15:24 +0300 |
commit | 4e0d1e8bcb96821ea16c8c025f36a112804e829f (patch) | |
tree | 9738b4b1316af59bb29e42b51abb4752b30fce1b | |
parent | 857140e81690748ce9a0a7ae7ed91cddb254f51a (diff) | |
download | linux-4e0d1e8bcb96821ea16c8c025f36a112804e829f.tar.xz |
perf symbols: Split kernel symbol processing from dso__load_sym()
More should be done to split this function, removing stuff map
relocation steps from the actual symbol table loading.
Arch specific stuff also should go elsewhere, to tools/arch/ and
we should have it keyed by data from the perf_env either in the
perf.data header or from the running environment.
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Wang Nan <wangnan0@huawei.com>
Link: https://lkml.kernel.org/n/tip-236gyo6cx6iet90u3uc01cws@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r-- | tools/perf/util/symbol-elf.c | 205 |
1 files changed, 108 insertions, 97 deletions
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index 0b230f1a31c4..48943b834f11 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c @@ -797,6 +797,110 @@ static u64 ref_reloc(struct kmap *kmap) void __weak arch__sym_update(struct symbol *s __maybe_unused, GElf_Sym *sym __maybe_unused) { } +static int dso__process_kernel_symbol(struct dso *dso, struct map *map, + GElf_Sym *sym, GElf_Shdr *shdr, + struct map_groups *kmaps, struct kmap *kmap, + struct dso **curr_dsop, struct map **curr_mapp, + const char *section_name, + bool adjust_kernel_syms, bool kmodule, bool *remap_kernel) +{ + struct dso *curr_dso = *curr_dsop; + struct map *curr_map; + char dso_name[PATH_MAX]; + + /* Adjust symbol to map to file offset */ + if (adjust_kernel_syms) + sym->st_value -= shdr->sh_addr - shdr->sh_offset; + + if (strcmp(section_name, (curr_dso->short_name + dso->short_name_len)) == 0) + return 0; + + if (strcmp(section_name, ".text") == 0) { + /* + * The initial kernel mapping is based on + * kallsyms and identity maps. Overwrite it to + * map to the kernel dso. + */ + if (*remap_kernel && dso->kernel) { + *remap_kernel = false; + map->start = shdr->sh_addr + ref_reloc(kmap); + map->end = map->start + shdr->sh_size; + map->pgoff = shdr->sh_offset; + map->map_ip = map__map_ip; + map->unmap_ip = map__unmap_ip; + /* Ensure maps are correctly ordered */ + if (kmaps) { + map__get(map); + map_groups__remove(kmaps, map); + map_groups__insert(kmaps, map); + map__put(map); + } + } + + /* + * The initial module mapping is based on + * /proc/modules mapped to offset zero. + * Overwrite it to map to the module dso. + */ + if (*remap_kernel && kmodule) { + *remap_kernel = false; + map->pgoff = shdr->sh_offset; + } + + *curr_mapp = map; + *curr_dsop = dso; + return 0; + } + + if (!kmap) + return 0; + + snprintf(dso_name, sizeof(dso_name), "%s%s", dso->short_name, section_name); + + curr_map = map_groups__find_by_name(kmaps, dso_name); + if (curr_map == NULL) { + u64 start = sym->st_value; + + if (kmodule) + start += map->start + shdr->sh_offset; + + curr_dso = dso__new(dso_name); + if (curr_dso == NULL) + return -1; + curr_dso->kernel = dso->kernel; + curr_dso->long_name = dso->long_name; + curr_dso->long_name_len = dso->long_name_len; + curr_map = map__new2(start, curr_dso); + dso__put(curr_dso); + if (curr_map == NULL) + return -1; + + if (adjust_kernel_syms) { + curr_map->start = shdr->sh_addr + ref_reloc(kmap); + curr_map->end = curr_map->start + shdr->sh_size; + curr_map->pgoff = shdr->sh_offset; + } else { + curr_map->map_ip = curr_map->unmap_ip = identity__map_ip; + } + curr_dso->symtab_type = dso->symtab_type; + map_groups__insert(kmaps, curr_map); + /* + * Add it before we drop the referece to curr_map, i.e. while + * we still are sure to have a reference to this DSO via + * *curr_map->dso. + */ + dsos__add(&map->groups->machine->dsos, curr_dso); + /* kmaps already got it */ + map__put(curr_map); + dso__set_loaded(curr_dso); + *curr_mapp = curr_map; + *curr_dsop = curr_dso; + } else + *curr_dsop = curr_map->dso; + + return 0; +} + int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss, struct symsrc *runtime_ss, int kmodule) { @@ -973,102 +1077,9 @@ int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss, --sym.st_value; if (dso->kernel || kmodule) { - char dso_name[PATH_MAX]; - - /* Adjust symbol to map to file offset */ - if (adjust_kernel_syms) - sym.st_value -= shdr.sh_addr - shdr.sh_offset; - - if (strcmp(section_name, - (curr_dso->short_name + - dso->short_name_len)) == 0) - goto new_symbol; - - if (strcmp(section_name, ".text") == 0) { - /* - * The initial kernel mapping is based on - * kallsyms and identity maps. Overwrite it to - * map to the kernel dso. - */ - if (remap_kernel && dso->kernel) { - remap_kernel = false; - map->start = shdr.sh_addr + - ref_reloc(kmap); - map->end = map->start + shdr.sh_size; - map->pgoff = shdr.sh_offset; - map->map_ip = map__map_ip; - map->unmap_ip = map__unmap_ip; - /* Ensure maps are correctly ordered */ - if (kmaps) { - map__get(map); - map_groups__remove(kmaps, map); - map_groups__insert(kmaps, map); - map__put(map); - } - } - - /* - * The initial module mapping is based on - * /proc/modules mapped to offset zero. - * Overwrite it to map to the module dso. - */ - if (remap_kernel && kmodule) { - remap_kernel = false; - map->pgoff = shdr.sh_offset; - } - - curr_map = map; - curr_dso = dso; - goto new_symbol; - } - - if (!kmap) - goto new_symbol; - - snprintf(dso_name, sizeof(dso_name), - "%s%s", dso->short_name, section_name); - - curr_map = map_groups__find_by_name(kmaps, dso_name); - if (curr_map == NULL) { - u64 start = sym.st_value; - - if (kmodule) - start += map->start + shdr.sh_offset; - - curr_dso = dso__new(dso_name); - if (curr_dso == NULL) - goto out_elf_end; - curr_dso->kernel = dso->kernel; - curr_dso->long_name = dso->long_name; - curr_dso->long_name_len = dso->long_name_len; - curr_map = map__new2(start, curr_dso); - dso__put(curr_dso); - if (curr_map == NULL) { - goto out_elf_end; - } - if (adjust_kernel_syms) { - curr_map->start = shdr.sh_addr + - ref_reloc(kmap); - curr_map->end = curr_map->start + - shdr.sh_size; - curr_map->pgoff = shdr.sh_offset; - } else { - curr_map->map_ip = identity__map_ip; - curr_map->unmap_ip = identity__map_ip; - } - curr_dso->symtab_type = dso->symtab_type; - map_groups__insert(kmaps, curr_map); - /* - * Add it before we drop the referece to curr_map, - * i.e. while we still are sure to have a reference - * to this DSO via curr_map->dso. - */ - dsos__add(&map->groups->machine->dsos, curr_dso); - /* kmaps already got it */ - map__put(curr_map); - dso__set_loaded(curr_dso); - } else - curr_dso = curr_map->dso; + if (dso__process_kernel_symbol(dso, map, &sym, &shdr, kmaps, kmap, &curr_dso, &curr_map, + section_name, adjust_kernel_syms, kmodule, &remap_kernel)) + goto out_elf_end; } else if ((used_opd && runtime_ss->adjust_symbols) || (!used_opd && syms_ss->adjust_symbols)) { pr_debug4("%s: adjusting symbol: st_value: %#" PRIx64 " " @@ -1077,7 +1088,7 @@ int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss, (u64)shdr.sh_offset); sym.st_value -= shdr.sh_addr - shdr.sh_offset; } -new_symbol: + demangled = demangle_sym(dso, kmodule, elf_name); if (demangled != NULL) elf_name = demangled; |