map__rip_2objdump() and map__objdump_2mem() should be update since
map->dso->adjust_symbols becomes true for normal shared objects.
In this patch, the offset of '.text' section is stored into dso
and used here to re-calculate address to objdump.

In most of the cases, executable code is in '.text' section, so the
adjustment made to a symbol in dso__load_sym (using
sym.st_value -= shdr.sh_addr - shdr.sh_offset) should equal to
'sym.st_value -= dso->text_offset'. Therefore, adding text_offset back
get objdump address from symbol address (rip). However, it is not true
for kernel and kernel module since there could be multiple executable
sections with different offset. Exclude kernel for this reason.

Signed-off-by: Wang Nan <[email protected]>
Cc: Arnaldo Carvalho de Melo <[email protected]>
Cc: He Kuang <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Masami Hiramatsu <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Li Zefan <[email protected]>
Cc: [email protected]
---
 tools/perf/util/dso.h        |  1 +
 tools/perf/util/map.c        |  6 ++++++
 tools/perf/util/symbol-elf.c | 12 ++++++------
 3 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index 45ec4d0..ef3dbc9 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -162,6 +162,7 @@ struct dso {
        u8               loaded;
        u8               rel;
        u8               build_id[BUILD_ID_SIZE];
+       u64              text_offset;
        const char       *short_name;
        const char       *long_name;
        u16              long_name_len;
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 171b6d1..eedf93d 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -431,6 +431,9 @@ u64 map__rip_2objdump(struct map *map, u64 rip)
        if (map->dso->rel)
                return rip - map->pgoff;
 
+       if (map->dso->kernel == DSO_TYPE_USER)
+               return rip + map->dso->text_offset;
+
        return map->unmap_ip(map, rip) - map->reloc;
 }
 
@@ -454,6 +457,9 @@ u64 map__objdump_2mem(struct map *map, u64 ip)
        if (map->dso->rel)
                return map->unmap_ip(map, ip + map->pgoff);
 
+       if (map->dso->kernel == DSO_TYPE_USER)
+               return map->unmap_ip(map, ip - map->dso->text_offset);
+
        return ip + map->reloc;
 }
 
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index d37e206..d4e59dd 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -793,6 +793,7 @@ int dso__load_sym(struct dso *dso, struct map *map,
        uint32_t idx;
        GElf_Ehdr ehdr;
        GElf_Shdr shdr;
+       GElf_Shdr tshdr;
        Elf_Data *syms, *opddata = NULL;
        GElf_Sym sym;
        Elf_Scn *sec, *sec_strndx;
@@ -832,6 +833,9 @@ int dso__load_sym(struct dso *dso, struct map *map,
        sec = syms_ss->symtab;
        shdr = syms_ss->symshdr;
 
+       if (elf_section_by_name(elf, &ehdr, &tshdr, ".text", NULL))
+               dso->text_offset = tshdr.sh_addr - tshdr.sh_offset;
+
        if (runtime_ss->opdsec)
                opddata = elf_rawdata(runtime_ss->opdsec, NULL);
 
@@ -880,12 +884,8 @@ int dso__load_sym(struct dso *dso, struct map *map,
         * Handle any relocation of vdso necessary because older kernels
         * attempted to prelink vdso to its virtual address.
         */
-       if (dso__is_vdso(dso)) {
-               GElf_Shdr tshdr;
-
-               if (elf_section_by_name(elf, &ehdr, &tshdr, ".text", NULL))
-                       map->reloc = map->start - tshdr.sh_addr + 
tshdr.sh_offset;
-       }
+       if (dso__is_vdso(dso))
+               map->reloc = map->start - dso->text_offset;
 
        dso->adjust_symbols = runtime_ss->adjust_symbols || ref_reloc(kmap);
        /*
-- 
1.8.3.4

Reply via email to