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

perf report: Add debug help for the finding of symbol bugs - show the symtab...

perf report: Add debug help for the finding of symbol bugs - show the symtab origin (DSO, build-id, kernel, etc)

Used with perf report --verbose:

[acme@doppio linux-2.6-tip]$ perf report -v | head -16
     5.17%  firefox  /usr/lib64/xulrunner-1.9.1/libxul.so   0x00000000005d8eee f [.] imgContainer::DrawFrameTo(gfxIImageFrame*, gfxIImageFrame*, nsRect&)
     2.56%  firefox  /lib64/libpthread-2.10.1.so            0x0000000000008e02 d [.] __pthread_mutex_lock_internal
     1.94%  firefox  /usr/lib64/xulrunner-1.9.1/libxul.so   0x0000000000d0af8f f [.] SearchTable
     1.75%  firefox  [kernel]                               0xffffffffff60013b k [.] vread_hpet
     1.63%  firefox  /lib64/libpthread-2.10.1.so            0x000000000000a404 d [.] __pthread_mutex_unlock
     1.47%  firefox  /usr/lib64/xulrunner-1.9.1/libmozjs.so 0x00000000000482ea f [.] js_Interpret
     1.42%  firefox  /usr/lib64/xulrunner-1.9.1/libmozjs.so 0x000000000003eda3 f [.] JS_CallTracer
     1.24%  firefox  [kernel]                               0xffffffff8102ca4a k [k] read_hpet
     1.16%  firefox  [kernel]                               0xffffffff810f3dd4 k [k] fget_light
     1.11%  firefox  /usr/lib64/xulrunner-1.9.1/libmozjs.so 0x00000000000567ff f [.] js_TraceObject
     0.98%  firefox  /usr/lib64/firefox-3.5.2/firefox       0x000000000000dd23 b [.] arena_ralloc
[acme@doppio linux-2.6-tip]$

The new field is just after the symbol address. To help in
figuring out symbol resolution bugs.
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Acked-by: default avatarPeter Zijlstra <peterz@infradead.org>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent 8f18aec5
...@@ -700,7 +700,8 @@ sort__sym_print(FILE *fp, struct hist_entry *self, unsigned int width __used) ...@@ -700,7 +700,8 @@ sort__sym_print(FILE *fp, struct hist_entry *self, unsigned int width __used)
size_t ret = 0; size_t ret = 0;
if (verbose) if (verbose)
ret += repsep_fprintf(fp, "%#018llx ", (u64)self->ip); ret += repsep_fprintf(fp, "%#018llx %c ", (u64)self->ip,
dso__symtab_origin(self->dso));
ret += repsep_fprintf(fp, "[%c] ", self->level); ret += repsep_fprintf(fp, "[%c] ", self->level);
if (self->sym) { if (self->sym) {
......
...@@ -24,6 +24,16 @@ const char *sym_hist_filter; ...@@ -24,6 +24,16 @@ const char *sym_hist_filter;
#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */ #define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */
#endif #endif
enum dso_origin {
DSO__ORIG_KERNEL = 0,
DSO__ORIG_JAVA_JIT,
DSO__ORIG_FEDORA,
DSO__ORIG_UBUNTU,
DSO__ORIG_BUILDID,
DSO__ORIG_DSO,
DSO__ORIG_NOT_FOUND,
};
static struct symbol *symbol__new(u64 start, u64 len, static struct symbol *symbol__new(u64 start, u64 len,
const char *name, unsigned int priv_size, const char *name, unsigned int priv_size,
u64 obj_start, int verbose) u64 obj_start, int verbose)
...@@ -81,6 +91,7 @@ struct dso *dso__new(const char *name, unsigned int sym_priv_size) ...@@ -81,6 +91,7 @@ struct dso *dso__new(const char *name, unsigned int sym_priv_size)
self->sym_priv_size = sym_priv_size; self->sym_priv_size = sym_priv_size;
self->find_symbol = dso__find_symbol; self->find_symbol = dso__find_symbol;
self->slen_calculated = 0; self->slen_calculated = 0;
self->origin = DSO__ORIG_NOT_FOUND;
} }
return self; return self;
...@@ -710,7 +721,7 @@ static char *dso__read_build_id(struct dso *self, int verbose) ...@@ -710,7 +721,7 @@ static char *dso__read_build_id(struct dso *self, int verbose)
++raw; ++raw;
bid += 2; bid += 2;
} }
if (verbose) if (verbose >= 2)
printf("%s(%s): %s\n", __func__, self->name, build_id); printf("%s(%s): %s\n", __func__, self->name, build_id);
out_elf_end: out_elf_end:
elf_end(elf); elf_end(elf);
...@@ -720,11 +731,26 @@ out: ...@@ -720,11 +731,26 @@ out:
return build_id; return build_id;
} }
char dso__symtab_origin(const struct dso *self)
{
static const char origin[] = {
[DSO__ORIG_KERNEL] = 'k',
[DSO__ORIG_JAVA_JIT] = 'j',
[DSO__ORIG_FEDORA] = 'f',
[DSO__ORIG_UBUNTU] = 'u',
[DSO__ORIG_BUILDID] = 'b',
[DSO__ORIG_DSO] = 'd',
};
if (self == NULL || self->origin == DSO__ORIG_NOT_FOUND)
return '!';
return origin[self->origin];
}
int dso__load(struct dso *self, symbol_filter_t filter, int verbose) int dso__load(struct dso *self, symbol_filter_t filter, int verbose)
{ {
int size = PATH_MAX; int size = PATH_MAX;
char *name = malloc(size), *build_id = NULL; char *name = malloc(size), *build_id = NULL;
int variant = 0;
int ret = -1; int ret = -1;
int fd; int fd;
...@@ -733,19 +759,26 @@ int dso__load(struct dso *self, symbol_filter_t filter, int verbose) ...@@ -733,19 +759,26 @@ int dso__load(struct dso *self, symbol_filter_t filter, int verbose)
self->adjust_symbols = 0; self->adjust_symbols = 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); ret = dso__load_perf_map(self, filter, verbose);
self->origin = ret > 0 ? DSO__ORIG_JAVA_JIT :
DSO__ORIG_NOT_FOUND;
return ret;
}
self->origin = DSO__ORIG_FEDORA - 1;
more: more:
do { do {
switch (variant) { self->origin++;
case 0: /* Fedora */ switch (self->origin) {
case DSO__ORIG_FEDORA:
snprintf(name, size, "/usr/lib/debug%s.debug", self->name); snprintf(name, size, "/usr/lib/debug%s.debug", self->name);
break; break;
case 1: /* Ubuntu */ case DSO__ORIG_UBUNTU:
snprintf(name, size, "/usr/lib/debug%s", self->name); snprintf(name, size, "/usr/lib/debug%s", self->name);
break; break;
case 2: case DSO__ORIG_BUILDID:
build_id = dso__read_build_id(self, verbose); build_id = dso__read_build_id(self, verbose);
if (build_id != NULL) { if (build_id != NULL) {
snprintf(name, size, snprintf(name, size,
...@@ -754,16 +787,15 @@ more: ...@@ -754,16 +787,15 @@ more:
free(build_id); free(build_id);
break; break;
} }
variant++; self->origin++;
/* Fall thru */ /* Fall thru */
case 3: /* Sane people */ case DSO__ORIG_DSO:
snprintf(name, size, "%s", self->name); snprintf(name, size, "%s", self->name);
break; break;
default: default:
goto out; goto out;
} }
variant++;
fd = open(name, O_RDONLY); fd = open(name, O_RDONLY);
} while (fd < 0); } while (fd < 0);
...@@ -899,6 +931,9 @@ int dso__load_kernel(struct dso *self, const char *vmlinux, ...@@ -899,6 +931,9 @@ int dso__load_kernel(struct dso *self, const char *vmlinux,
if (err <= 0) if (err <= 0)
err = dso__load_kallsyms(self, filter, verbose); err = dso__load_kallsyms(self, filter, verbose);
if (err > 0)
self->origin = DSO__ORIG_KERNEL;
return err; return err;
} }
......
...@@ -26,6 +26,7 @@ struct dso { ...@@ -26,6 +26,7 @@ struct dso {
unsigned int sym_priv_size; unsigned int sym_priv_size;
unsigned char adjust_symbols; unsigned char adjust_symbols;
unsigned char slen_calculated; unsigned char slen_calculated;
unsigned char origin;
char name[0]; char name[0];
}; };
...@@ -49,6 +50,7 @@ int dso__load_modules(struct dso *self, symbol_filter_t filter, int verbose); ...@@ -49,6 +50,7 @@ int dso__load_modules(struct dso *self, symbol_filter_t filter, int verbose);
int dso__load(struct dso *self, symbol_filter_t filter, int verbose); int dso__load(struct dso *self, symbol_filter_t filter, int verbose);
size_t dso__fprintf(struct dso *self, FILE *fp); size_t dso__fprintf(struct dso *self, FILE *fp);
char dso__symtab_origin(const struct dso *self);
void symbol__init(void); void symbol__init(void);
#endif /* _PERF_SYMBOL_ */ #endif /* _PERF_SYMBOL_ */
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