diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2009-08-06 13:43:17 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-08-09 06:54:36 -0400 |
commit | 94cb9e385d5b4d55a5ae389baa10ad2835ea39bb (patch) | |
tree | b089b9d5a20e9f35ced28880f6a98c511c89040e /tools | |
parent | 8f18aec535b5ca513dd13b531730177d35175ffa (diff) |
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: Arnaldo Carvalho de Melo <acme@redhat.com>
Acked-by: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/builtin-report.c | 3 | ||||
-rw-r--r-- | tools/perf/util/symbol.c | 57 | ||||
-rw-r--r-- | tools/perf/util/symbol.h | 2 |
3 files changed, 50 insertions, 12 deletions
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 84205462e07b..a5e2f8df411c 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
@@ -700,7 +700,8 @@ sort__sym_print(FILE *fp, struct hist_entry *self, unsigned int width __used) | |||
700 | size_t ret = 0; | 700 | size_t ret = 0; |
701 | 701 | ||
702 | if (verbose) | 702 | if (verbose) |
703 | ret += repsep_fprintf(fp, "%#018llx ", (u64)self->ip); | 703 | ret += repsep_fprintf(fp, "%#018llx %c ", (u64)self->ip, |
704 | dso__symtab_origin(self->dso)); | ||
704 | 705 | ||
705 | ret += repsep_fprintf(fp, "[%c] ", self->level); | 706 | ret += repsep_fprintf(fp, "[%c] ", self->level); |
706 | if (self->sym) { | 707 | if (self->sym) { |
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 16ddca202948..f1dcede14307 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -24,6 +24,16 @@ const char *sym_hist_filter; | |||
24 | #define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */ | 24 | #define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */ |
25 | #endif | 25 | #endif |
26 | 26 | ||
27 | enum dso_origin { | ||
28 | DSO__ORIG_KERNEL = 0, | ||
29 | DSO__ORIG_JAVA_JIT, | ||
30 | DSO__ORIG_FEDORA, | ||
31 | DSO__ORIG_UBUNTU, | ||
32 | DSO__ORIG_BUILDID, | ||
33 | DSO__ORIG_DSO, | ||
34 | DSO__ORIG_NOT_FOUND, | ||
35 | }; | ||
36 | |||
27 | static struct symbol *symbol__new(u64 start, u64 len, | 37 | static struct symbol *symbol__new(u64 start, u64 len, |
28 | const char *name, unsigned int priv_size, | 38 | const char *name, unsigned int priv_size, |
29 | u64 obj_start, int verbose) | 39 | u64 obj_start, int verbose) |
@@ -81,6 +91,7 @@ struct dso *dso__new(const char *name, unsigned int sym_priv_size) | |||
81 | self->sym_priv_size = sym_priv_size; | 91 | self->sym_priv_size = sym_priv_size; |
82 | self->find_symbol = dso__find_symbol; | 92 | self->find_symbol = dso__find_symbol; |
83 | self->slen_calculated = 0; | 93 | self->slen_calculated = 0; |
94 | self->origin = DSO__ORIG_NOT_FOUND; | ||
84 | } | 95 | } |
85 | 96 | ||
86 | return self; | 97 | return self; |
@@ -710,7 +721,7 @@ static char *dso__read_build_id(struct dso *self, int verbose) | |||
710 | ++raw; | 721 | ++raw; |
711 | bid += 2; | 722 | bid += 2; |
712 | } | 723 | } |
713 | if (verbose) | 724 | if (verbose >= 2) |
714 | printf("%s(%s): %s\n", __func__, self->name, build_id); | 725 | printf("%s(%s): %s\n", __func__, self->name, build_id); |
715 | out_elf_end: | 726 | out_elf_end: |
716 | elf_end(elf); | 727 | elf_end(elf); |
@@ -720,11 +731,26 @@ out: | |||
720 | return build_id; | 731 | return build_id; |
721 | } | 732 | } |
722 | 733 | ||
734 | char dso__symtab_origin(const struct dso *self) | ||
735 | { | ||
736 | static const char origin[] = { | ||
737 | [DSO__ORIG_KERNEL] = 'k', | ||
738 | [DSO__ORIG_JAVA_JIT] = 'j', | ||
739 | [DSO__ORIG_FEDORA] = 'f', | ||
740 | [DSO__ORIG_UBUNTU] = 'u', | ||
741 | [DSO__ORIG_BUILDID] = 'b', | ||
742 | [DSO__ORIG_DSO] = 'd', | ||
743 | }; | ||
744 | |||
745 | if (self == NULL || self->origin == DSO__ORIG_NOT_FOUND) | ||
746 | return '!'; | ||
747 | return origin[self->origin]; | ||
748 | } | ||
749 | |||
723 | int dso__load(struct dso *self, symbol_filter_t filter, int verbose) | 750 | int dso__load(struct dso *self, symbol_filter_t filter, int verbose) |
724 | { | 751 | { |
725 | int size = PATH_MAX; | 752 | int size = PATH_MAX; |
726 | char *name = malloc(size), *build_id = NULL; | 753 | char *name = malloc(size), *build_id = NULL; |
727 | int variant = 0; | ||
728 | int ret = -1; | 754 | int ret = -1; |
729 | int fd; | 755 | int fd; |
730 | 756 | ||
@@ -733,19 +759,26 @@ int dso__load(struct dso *self, symbol_filter_t filter, int verbose) | |||
733 | 759 | ||
734 | self->adjust_symbols = 0; | 760 | self->adjust_symbols = 0; |
735 | 761 | ||
736 | if (strncmp(self->name, "/tmp/perf-", 10) == 0) | 762 | if (strncmp(self->name, "/tmp/perf-", 10) == 0) { |
737 | return dso__load_perf_map(self, filter, verbose); | 763 | ret = dso__load_perf_map(self, filter, verbose); |
764 | self->origin = ret > 0 ? DSO__ORIG_JAVA_JIT : | ||
765 | DSO__ORIG_NOT_FOUND; | ||
766 | return ret; | ||
767 | } | ||
768 | |||
769 | self->origin = DSO__ORIG_FEDORA - 1; | ||
738 | 770 | ||
739 | more: | 771 | more: |
740 | do { | 772 | do { |
741 | switch (variant) { | 773 | self->origin++; |
742 | case 0: /* Fedora */ | 774 | switch (self->origin) { |
775 | case DSO__ORIG_FEDORA: | ||
743 | snprintf(name, size, "/usr/lib/debug%s.debug", self->name); | 776 | snprintf(name, size, "/usr/lib/debug%s.debug", self->name); |
744 | break; | 777 | break; |
745 | case 1: /* Ubuntu */ | 778 | case DSO__ORIG_UBUNTU: |
746 | snprintf(name, size, "/usr/lib/debug%s", self->name); | 779 | snprintf(name, size, "/usr/lib/debug%s", self->name); |
747 | break; | 780 | break; |
748 | case 2: | 781 | case DSO__ORIG_BUILDID: |
749 | build_id = dso__read_build_id(self, verbose); | 782 | build_id = dso__read_build_id(self, verbose); |
750 | if (build_id != NULL) { | 783 | if (build_id != NULL) { |
751 | snprintf(name, size, | 784 | snprintf(name, size, |
@@ -754,16 +787,15 @@ more: | |||
754 | free(build_id); | 787 | free(build_id); |
755 | break; | 788 | break; |
756 | } | 789 | } |
757 | variant++; | 790 | self->origin++; |
758 | /* Fall thru */ | 791 | /* Fall thru */ |
759 | case 3: /* Sane people */ | 792 | case DSO__ORIG_DSO: |
760 | snprintf(name, size, "%s", self->name); | 793 | snprintf(name, size, "%s", self->name); |
761 | break; | 794 | break; |
762 | 795 | ||
763 | default: | 796 | default: |
764 | goto out; | 797 | goto out; |
765 | } | 798 | } |
766 | variant++; | ||
767 | 799 | ||
768 | fd = open(name, O_RDONLY); | 800 | fd = open(name, O_RDONLY); |
769 | } while (fd < 0); | 801 | } while (fd < 0); |
@@ -899,6 +931,9 @@ int dso__load_kernel(struct dso *self, const char *vmlinux, | |||
899 | if (err <= 0) | 931 | if (err <= 0) |
900 | err = dso__load_kallsyms(self, filter, verbose); | 932 | err = dso__load_kallsyms(self, filter, verbose); |
901 | 933 | ||
934 | if (err > 0) | ||
935 | self->origin = DSO__ORIG_KERNEL; | ||
936 | |||
902 | return err; | 937 | return err; |
903 | } | 938 | } |
904 | 939 | ||
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 2f92b21c712d..1e003ec2f4b1 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h | |||
@@ -26,6 +26,7 @@ struct dso { | |||
26 | unsigned int sym_priv_size; | 26 | unsigned int sym_priv_size; |
27 | unsigned char adjust_symbols; | 27 | unsigned char adjust_symbols; |
28 | unsigned char slen_calculated; | 28 | unsigned char slen_calculated; |
29 | unsigned char origin; | ||
29 | char name[0]; | 30 | char name[0]; |
30 | }; | 31 | }; |
31 | 32 | ||
@@ -49,6 +50,7 @@ int dso__load_modules(struct dso *self, symbol_filter_t filter, int verbose); | |||
49 | int dso__load(struct dso *self, symbol_filter_t filter, int verbose); | 50 | int dso__load(struct dso *self, symbol_filter_t filter, int verbose); |
50 | 51 | ||
51 | size_t dso__fprintf(struct dso *self, FILE *fp); | 52 | size_t dso__fprintf(struct dso *self, FILE *fp); |
53 | char dso__symtab_origin(const struct dso *self); | ||
52 | 54 | ||
53 | void symbol__init(void); | 55 | void symbol__init(void); |
54 | #endif /* _PERF_SYMBOL_ */ | 56 | #endif /* _PERF_SYMBOL_ */ |