Browse Source

perf symbols: Fix symbol annotation for relocated kernel

Kernel maps map memory addresses to file offsets.

For symbol annotation, objdump needs the object VMA addresses.  For an
unrelocated kernel, that is the same as the memory address.

The addresses passed to objdump for symbol annotation did not take into
account kernel relocation.

This patch fixes that.

Reported-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Tested-by: Jiri Olsa <jolsa@redhat.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Namhyung Kim <namhyung@gmail.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1391004884-10334-2-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Adrian Hunter 11 years ago
parent
commit
9176753d1e
3 changed files with 6 additions and 2 deletions
  1. 3 2
      tools/perf/util/map.c
  2. 1 0
      tools/perf/util/map.h
  3. 2 0
      tools/perf/util/symbol-elf.c

+ 3 - 2
tools/perf/util/map.c

@@ -39,6 +39,7 @@ void map__init(struct map *map, enum map_type type,
 	map->start    = start;
 	map->start    = start;
 	map->end      = end;
 	map->end      = end;
 	map->pgoff    = pgoff;
 	map->pgoff    = pgoff;
+	map->reloc    = 0;
 	map->dso      = dso;
 	map->dso      = dso;
 	map->map_ip   = map__map_ip;
 	map->map_ip   = map__map_ip;
 	map->unmap_ip = map__unmap_ip;
 	map->unmap_ip = map__unmap_ip;
@@ -288,7 +289,7 @@ u64 map__rip_2objdump(struct map *map, u64 rip)
 	if (map->dso->rel)
 	if (map->dso->rel)
 		return rip - map->pgoff;
 		return rip - map->pgoff;
 
 
-	return map->unmap_ip(map, rip);
+	return map->unmap_ip(map, rip) - map->reloc;
 }
 }
 
 
 /**
 /**
@@ -311,7 +312,7 @@ u64 map__objdump_2mem(struct map *map, u64 ip)
 	if (map->dso->rel)
 	if (map->dso->rel)
 		return map->unmap_ip(map, ip + map->pgoff);
 		return map->unmap_ip(map, ip + map->pgoff);
 
 
-	return ip;
+	return ip + map->reloc;
 }
 }
 
 
 void map_groups__init(struct map_groups *mg)
 void map_groups__init(struct map_groups *mg)

+ 1 - 0
tools/perf/util/map.h

@@ -36,6 +36,7 @@ struct map {
 	bool			erange_warned;
 	bool			erange_warned;
 	u32			priv;
 	u32			priv;
 	u64			pgoff;
 	u64			pgoff;
+	u64			reloc;
 	u32			maj, min; /* only valid for MMAP2 record */
 	u32			maj, min; /* only valid for MMAP2 record */
 	u64			ino;      /* only valid for MMAP2 record */
 	u64			ino;      /* only valid for MMAP2 record */
 	u64			ino_generation;/* only valid for MMAP2 record */
 	u64			ino_generation;/* only valid for MMAP2 record */

+ 2 - 0
tools/perf/util/symbol-elf.c

@@ -751,6 +751,8 @@ int dso__load_sym(struct dso *dso, struct map *map,
 			if (strcmp(elf_name, kmap->ref_reloc_sym->name))
 			if (strcmp(elf_name, kmap->ref_reloc_sym->name))
 				continue;
 				continue;
 			kmap->ref_reloc_sym->unrelocated_addr = sym.st_value;
 			kmap->ref_reloc_sym->unrelocated_addr = sym.st_value;
+			map->reloc = kmap->ref_reloc_sym->addr -
+				     kmap->ref_reloc_sym->unrelocated_addr;
 			break;
 			break;
 		}
 		}
 	}
 	}