diff options
author | Peter Zijlstra <a.p.zijlstra@chello.nl> | 2009-05-26 09:30:22 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-05-26 10:18:43 -0400 |
commit | f17e04afaff84b5cfd317da29ac4d764908ff833 (patch) | |
tree | e8c469b6687458887614de4caee7586a8c7365ee | |
parent | db20c0031288ff524d82b1f240f35f85d4a052eb (diff) |
perf report: Fix ELF symbol parsing
[ Impact: fix DSO symbol output in perf report ]
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: John Kacur <jkacur@redhat.com>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r-- | Documentation/perf_counter/Makefile | 2 | ||||
-rw-r--r-- | Documentation/perf_counter/builtin-report.c | 72 |
2 files changed, 22 insertions, 52 deletions
diff --git a/Documentation/perf_counter/Makefile b/Documentation/perf_counter/Makefile index 412dea15d0b7..10c13a6f2bc9 100644 --- a/Documentation/perf_counter/Makefile +++ b/Documentation/perf_counter/Makefile | |||
@@ -159,7 +159,7 @@ uname_V := $(shell sh -c 'uname -v 2>/dev/null || echo not') | |||
159 | 159 | ||
160 | # CFLAGS and LDFLAGS are for the users to override from the command line. | 160 | # CFLAGS and LDFLAGS are for the users to override from the command line. |
161 | 161 | ||
162 | CFLAGS = -g -O2 -Wall | 162 | CFLAGS = -ggdb3 -Wall |
163 | LDFLAGS = -lpthread -lrt -lelf | 163 | LDFLAGS = -lpthread -lrt -lelf |
164 | ALL_CFLAGS = $(CFLAGS) | 164 | ALL_CFLAGS = $(CFLAGS) |
165 | ALL_LDFLAGS = $(LDFLAGS) | 165 | ALL_LDFLAGS = $(LDFLAGS) |
diff --git a/Documentation/perf_counter/builtin-report.c b/Documentation/perf_counter/builtin-report.c index 9e59d6071ef3..697f960495fc 100644 --- a/Documentation/perf_counter/builtin-report.c +++ b/Documentation/perf_counter/builtin-report.c | |||
@@ -55,34 +55,6 @@ typedef union event_union { | |||
55 | struct comm_event comm; | 55 | struct comm_event comm; |
56 | } event_t; | 56 | } event_t; |
57 | 57 | ||
58 | struct section { | ||
59 | struct list_head node; | ||
60 | uint64_t start; | ||
61 | uint64_t end; | ||
62 | uint64_t offset; | ||
63 | char name[0]; | ||
64 | }; | ||
65 | |||
66 | struct section *section__new(uint64_t start, uint64_t size, | ||
67 | uint64_t offset, char *name) | ||
68 | { | ||
69 | struct section *self = malloc(sizeof(*self) + strlen(name) + 1); | ||
70 | |||
71 | if (self != NULL) { | ||
72 | self->start = start; | ||
73 | self->end = start + size; | ||
74 | self->offset = offset; | ||
75 | strcpy(self->name, name); | ||
76 | } | ||
77 | |||
78 | return self; | ||
79 | } | ||
80 | |||
81 | static void section__delete(struct section *self) | ||
82 | { | ||
83 | free(self); | ||
84 | } | ||
85 | |||
86 | struct symbol { | 58 | struct symbol { |
87 | struct rb_node rb_node; | 59 | struct rb_node rb_node; |
88 | uint64_t start; | 60 | uint64_t start; |
@@ -116,7 +88,6 @@ static size_t symbol__fprintf(struct symbol *self, FILE *fp) | |||
116 | 88 | ||
117 | struct dso { | 89 | struct dso { |
118 | struct list_head node; | 90 | struct list_head node; |
119 | struct list_head sections; | ||
120 | struct rb_root syms; | 91 | struct rb_root syms; |
121 | char name[0]; | 92 | char name[0]; |
122 | }; | 93 | }; |
@@ -127,21 +98,12 @@ static struct dso *dso__new(const char *name) | |||
127 | 98 | ||
128 | if (self != NULL) { | 99 | if (self != NULL) { |
129 | strcpy(self->name, name); | 100 | strcpy(self->name, name); |
130 | INIT_LIST_HEAD(&self->sections); | ||
131 | self->syms = RB_ROOT; | 101 | self->syms = RB_ROOT; |
132 | } | 102 | } |
133 | 103 | ||
134 | return self; | 104 | return self; |
135 | } | 105 | } |
136 | 106 | ||
137 | static void dso__delete_sections(struct dso *self) | ||
138 | { | ||
139 | struct section *pos, *n; | ||
140 | |||
141 | list_for_each_entry_safe(pos, n, &self->sections, node) | ||
142 | section__delete(pos); | ||
143 | } | ||
144 | |||
145 | static void dso__delete_symbols(struct dso *self) | 107 | static void dso__delete_symbols(struct dso *self) |
146 | { | 108 | { |
147 | struct symbol *pos; | 109 | struct symbol *pos; |
@@ -156,7 +118,6 @@ static void dso__delete_symbols(struct dso *self) | |||
156 | 118 | ||
157 | static void dso__delete(struct dso *self) | 119 | static void dso__delete(struct dso *self) |
158 | { | 120 | { |
159 | dso__delete_sections(self); | ||
160 | dso__delete_symbols(self); | 121 | dso__delete_symbols(self); |
161 | free(self); | 122 | free(self); |
162 | } | 123 | } |
@@ -282,9 +243,6 @@ static int dso__load(struct dso *self) | |||
282 | if (sec == NULL) | 243 | if (sec == NULL) |
283 | goto out_elf_end; | 244 | goto out_elf_end; |
284 | 245 | ||
285 | if (gelf_getshdr(sec, &shdr) == NULL) | ||
286 | goto out_elf_end; | ||
287 | |||
288 | Elf_Data *syms = elf_getdata(sec, NULL); | 246 | Elf_Data *syms = elf_getdata(sec, NULL); |
289 | if (syms == NULL) | 247 | if (syms == NULL) |
290 | goto out_elf_end; | 248 | goto out_elf_end; |
@@ -302,11 +260,21 @@ static int dso__load(struct dso *self) | |||
302 | GElf_Sym sym; | 260 | GElf_Sym sym; |
303 | uint32_t index; | 261 | uint32_t index; |
304 | elf_symtab__for_each_symbol(syms, nr_syms, index, sym) { | 262 | elf_symtab__for_each_symbol(syms, nr_syms, index, sym) { |
263 | struct symbol *f; | ||
264 | |||
305 | if (!elf_sym__is_function(&sym)) | 265 | if (!elf_sym__is_function(&sym)) |
306 | continue; | 266 | continue; |
307 | struct symbol *f = symbol__new(sym.st_value, sym.st_size, | 267 | |
308 | elf_sym__name(&sym, symstrs)); | 268 | sec = elf_getscn(elf, sym.st_shndx); |
309 | if (f == NULL) | 269 | if (!sec) |
270 | goto out_elf_end; | ||
271 | |||
272 | gelf_getshdr(sec, &shdr); | ||
273 | sym.st_value -= shdr.sh_addr - shdr.sh_offset; | ||
274 | |||
275 | f = symbol__new(sym.st_value, sym.st_size, | ||
276 | elf_sym__name(&sym, symstrs)); | ||
277 | if (!f) | ||
310 | goto out_elf_end; | 278 | goto out_elf_end; |
311 | 279 | ||
312 | dso__insert_symbol(self, f); | 280 | dso__insert_symbol(self, f); |
@@ -498,7 +466,7 @@ static size_t symhist__fprintf(struct symhist *self, FILE *fp) | |||
498 | ret += fprintf(fp, "%s", self->sym ? self->sym->name: "<unknown>"); | 466 | ret += fprintf(fp, "%s", self->sym ? self->sym->name: "<unknown>"); |
499 | else | 467 | else |
500 | ret += fprintf(fp, "%s: %s", | 468 | ret += fprintf(fp, "%s: %s", |
501 | self->dso ? self->dso->name : "<unknown", | 469 | self->dso ? self->dso->name : "<unknown>", |
502 | self->sym ? self->sym->name : "<unknown>"); | 470 | self->sym ? self->sym->name : "<unknown>"); |
503 | return ret + fprintf(fp, ": %u\n", self->count); | 471 | return ret + fprintf(fp, ": %u\n", self->count); |
504 | } | 472 | } |
@@ -714,6 +682,7 @@ more: | |||
714 | int show = 0; | 682 | int show = 0; |
715 | struct dso *dso = NULL; | 683 | struct dso *dso = NULL; |
716 | struct thread *thread = threads__findnew(event->ip.pid); | 684 | struct thread *thread = threads__findnew(event->ip.pid); |
685 | uint64_t ip = event->ip.ip; | ||
717 | 686 | ||
718 | if (thread == NULL) { | 687 | if (thread == NULL) { |
719 | fprintf(stderr, "problem processing %d event, bailing out\n", | 688 | fprintf(stderr, "problem processing %d event, bailing out\n", |
@@ -728,19 +697,20 @@ more: | |||
728 | } else if (event->header.misc & PERF_EVENT_MISC_USER) { | 697 | } else if (event->header.misc & PERF_EVENT_MISC_USER) { |
729 | show = SHOW_USER; | 698 | show = SHOW_USER; |
730 | level = '.'; | 699 | level = '.'; |
731 | struct map *map = thread__find_map(thread, event->ip.ip); | 700 | struct map *map = thread__find_map(thread, ip); |
732 | if (map != NULL) | 701 | if (map != NULL) { |
733 | dso = map->dso; | 702 | dso = map->dso; |
703 | ip -= map->start + map->pgoff; | ||
704 | } | ||
734 | } else { | 705 | } else { |
735 | show = SHOW_HV; | 706 | show = SHOW_HV; |
736 | level = 'H'; | 707 | level = 'H'; |
737 | } | 708 | } |
738 | 709 | ||
739 | if (show & show_mask) { | 710 | if (show & show_mask) { |
740 | struct symbol *sym = dso__find_symbol(dso, event->ip.ip); | 711 | struct symbol *sym = dso__find_symbol(dso, ip); |
741 | 712 | ||
742 | if (thread__symbol_incnew(thread, sym, event->ip.ip, | 713 | if (thread__symbol_incnew(thread, sym, ip, dso, level)) { |
743 | dso, level)) { | ||
744 | fprintf(stderr, "problem incrementing symbol count, bailing out\n"); | 714 | fprintf(stderr, "problem incrementing symbol count, bailing out\n"); |
745 | goto done; | 715 | goto done; |
746 | } | 716 | } |