aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Zijlstra <a.p.zijlstra@chello.nl>2009-05-26 09:30:22 -0400
committerIngo Molnar <mingo@elte.hu>2009-05-26 10:18:43 -0400
commitf17e04afaff84b5cfd317da29ac4d764908ff833 (patch)
treee8c469b6687458887614de4caee7586a8c7365ee
parentdb20c0031288ff524d82b1f240f35f85d4a052eb (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/Makefile2
-rw-r--r--Documentation/perf_counter/builtin-report.c72
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
162CFLAGS = -g -O2 -Wall 162CFLAGS = -ggdb3 -Wall
163LDFLAGS = -lpthread -lrt -lelf 163LDFLAGS = -lpthread -lrt -lelf
164ALL_CFLAGS = $(CFLAGS) 164ALL_CFLAGS = $(CFLAGS)
165ALL_LDFLAGS = $(LDFLAGS) 165ALL_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
58struct section {
59 struct list_head node;
60 uint64_t start;
61 uint64_t end;
62 uint64_t offset;
63 char name[0];
64};
65
66struct 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
81static void section__delete(struct section *self)
82{
83 free(self);
84}
85
86struct symbol { 58struct 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
117struct dso { 89struct 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
137static 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
145static void dso__delete_symbols(struct dso *self) 107static 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
157static void dso__delete(struct dso *self) 119static 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 }