perf symbols: Split kernel symbol processing from dso__load_sym()
authorArnaldo Carvalho de Melo <acme@redhat.com>
Fri, 27 Apr 2018 18:15:24 +0000 (15:15 -0300)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Fri, 27 Apr 2018 18:15:24 +0000 (15:15 -0300)
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>
tools/perf/util/symbol-elf.c

index 0b230f1a31c4c1b29c6a56e00f347e2037ce00de..48943b834f11c946b6f803d7ce90ed01dbb8f4f3 100644 (file)
@@ -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;