Commit f5812a7a authored by Arnaldo Carvalho de Melo's avatar Arnaldo Carvalho de Melo Committed by Ingo Molnar

perf_counter tools: Adjust only prelinked symbol's addresses

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: default avatarArnaldo 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: default avatarIngo Molnar <mingo@elte.hu>
parent 57e7986e
...@@ -520,7 +520,9 @@ static int dso__load_sym(struct dso *self, int fd, const char *name, ...@@ -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; nr_syms = shdr.sh_size / shdr.sh_entsize;
memset(&sym, 0, sizeof(sym)); 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) { elf_symtab__for_each_symbol(syms, nr_syms, index, sym) {
struct symbol *f; struct symbol *f;
u64 obj_start; u64 obj_start;
...@@ -535,11 +537,13 @@ static int dso__load_sym(struct dso *self, int fd, const char *name, ...@@ -535,11 +537,13 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
gelf_getshdr(sec, &shdr); gelf_getshdr(sec, &shdr);
obj_start = sym.st_value; obj_start = sym.st_value;
if (verbose >= 2) if (self->prelinked) {
printf("adjusting symbol: st_value: %Lx sh_addr: %Lx sh_offset: %Lx\n", if (verbose >= 2)
(u64)sym.st_value, (u64)shdr.sh_addr, (u64)shdr.sh_offset); 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, f = symbol__new(sym.st_value, sym.st_size,
elf_sym__name(&sym, symstrs), elf_sym__name(&sym, symstrs),
...@@ -573,6 +577,8 @@ int dso__load(struct dso *self, symbol_filter_t filter, int verbose) ...@@ -573,6 +577,8 @@ int dso__load(struct dso *self, symbol_filter_t filter, int verbose)
if (!name) if (!name)
return -1; return -1;
self->prelinked = 0;
if (strncmp(self->name, "/tmp/perf-", 10) == 0) if (strncmp(self->name, "/tmp/perf-", 10) == 0)
return dso__load_perf_map(self, filter, verbose); return dso__load_perf_map(self, filter, verbose);
......
...@@ -20,8 +20,9 @@ struct symbol { ...@@ -20,8 +20,9 @@ struct symbol {
struct dso { struct dso {
struct list_head node; struct list_head node;
struct rb_root syms; struct rb_root syms;
unsigned int sym_priv_size;
struct symbol *(*find_symbol)(struct dso *, u64 ip); struct symbol *(*find_symbol)(struct dso *, u64 ip);
unsigned int sym_priv_size;
unsigned char prelinked;
char name[0]; char name[0];
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment