perf_counter tools: Adjust only prelinked symbol's addresses
authorArnaldo Carvalho de Melo <acme@redhat.com>
Tue, 30 Jun 2009 14:43:17 +0000 (11:43 -0300)
committerIngo Molnar <mingo@elte.hu>
Tue, 30 Jun 2009 15:09:30 +0000 (17:09 +0200)
I.e. we can't handle these two kinds of files in the same way:

1) prelinked system library:

[acme@doppio pahole]$ readelf -s /usr/lib64/libdw-0.141.so | egrep 'FUNC.+GLOBAL.+dwfl_report_elf'
   278: 00000030450105a0   261 FUNC    GLOBAL DEFAULT   12 dwfl_report_elf@@ELFUTILS_0.122

2) not prelinked library with debug information from a -debuginfo package:

[acme@doppio pahole]$ readelf -s /usr/lib/debug/usr/lib64/libdw-0.141.so.debug | egrep 'FUNC.+GLOBAL.+dwfl_report_elf'
   629: 00000000000105a0   261 FUNC    GLOBAL DEFAULT   12 dwfl_report_elf
[acme@doppio pahole]$

Now the numbers I got for a pahole perf run are in line with
the numbers I get from oprofile.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
LKML-Reference: <20090630144317.GB12663@ghostprotocols.net>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
tools/perf/util/symbol.c
tools/perf/util/symbol.h

index 9c659ef6aec2d64d8532943888ba3bcad8d883d4..78c2efde01b7bee7a52665969cf0fcb87917b481 100644 (file)
@@ -520,7 +520,9 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
        nr_syms = shdr.sh_size / shdr.sh_entsize;
 
        memset(&sym, 0, sizeof(sym));
-
+       self->prelinked = elf_section_by_name(elf, &ehdr, &shdr,
+                                             ".gnu.prelink_undo",
+                                             NULL) != NULL;
        elf_symtab__for_each_symbol(syms, nr_syms, index, sym) {
                struct symbol *f;
                u64 obj_start;
@@ -535,11 +537,13 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
                gelf_getshdr(sec, &shdr);
                obj_start = sym.st_value;
 
-               if (verbose >= 2)
-                       printf("adjusting symbol: st_value: %Lx sh_addr: %Lx sh_offset: %Lx\n",
-                               (u64)sym.st_value, (u64)shdr.sh_addr, (u64)shdr.sh_offset);
+               if (self->prelinked) {
+                       if (verbose >= 2)
+                               printf("adjusting symbol: st_value: %Lx sh_addr: %Lx sh_offset: %Lx\n",
+                                       (u64)sym.st_value, (u64)shdr.sh_addr, (u64)shdr.sh_offset);
 
-               sym.st_value -= shdr.sh_addr - shdr.sh_offset;
+                       sym.st_value -= shdr.sh_addr - shdr.sh_offset;
+               }
 
                f = symbol__new(sym.st_value, sym.st_size,
                                elf_sym__name(&sym, symstrs),
@@ -573,6 +577,8 @@ int dso__load(struct dso *self, symbol_filter_t filter, int verbose)
        if (!name)
                return -1;
 
+       self->prelinked = 0;
+
        if (strncmp(self->name, "/tmp/perf-", 10) == 0)
                return dso__load_perf_map(self, filter, verbose);
 
index 940b432db16ed0034b86f7d2659294c7b173d900..2c48ace8203bc8d1ae0b355a74b2a34577f5a1a8 100644 (file)
@@ -20,8 +20,9 @@ struct symbol {
 struct dso {
        struct list_head node;
        struct rb_root   syms;
-       unsigned int     sym_priv_size;
        struct symbol    *(*find_symbol)(struct dso *, u64 ip);
+       unsigned int     sym_priv_size;
+       unsigned char    prelinked;
        char             name[0];
 };