diff options
author | Peter Zijlstra <a.p.zijlstra@chello.nl> | 2009-05-27 07:35:35 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-05-27 08:54:29 -0400 |
commit | b7a16eac5e679fb5f531b9eeff7db7952303e77d (patch) | |
tree | 657ba175c6f28a01bd91bf2c34931e469149fde8 /Documentation/perf_counter/builtin-report.c | |
parent | d716fba49c7445ec87c3f045c59624fac03ee3f2 (diff) |
perf_counter: tools: /usr/lib/debug%s.debug support
Some distros seem to store debuginfo in weird places.
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>
Diffstat (limited to 'Documentation/perf_counter/builtin-report.c')
-rw-r--r-- | Documentation/perf_counter/builtin-report.c | 94 |
1 files changed, 76 insertions, 18 deletions
diff --git a/Documentation/perf_counter/builtin-report.c b/Documentation/perf_counter/builtin-report.c index 6265bedcd937..a9ff49a4edea 100644 --- a/Documentation/perf_counter/builtin-report.c +++ b/Documentation/perf_counter/builtin-report.c | |||
@@ -190,7 +190,8 @@ static inline int elf_sym__is_function(const GElf_Sym *sym) | |||
190 | { | 190 | { |
191 | return elf_sym__type(sym) == STT_FUNC && | 191 | return elf_sym__type(sym) == STT_FUNC && |
192 | sym->st_name != 0 && | 192 | sym->st_name != 0 && |
193 | sym->st_shndx != SHN_UNDEF; | 193 | sym->st_shndx != SHN_UNDEF && |
194 | sym->st_size != 0; | ||
194 | } | 195 | } |
195 | 196 | ||
196 | static inline const char *elf_sym__name(const GElf_Sym *sym, | 197 | static inline const char *elf_sym__name(const GElf_Sym *sym, |
@@ -222,11 +223,11 @@ static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep, | |||
222 | return sec; | 223 | return sec; |
223 | } | 224 | } |
224 | 225 | ||
225 | static int dso__load(struct dso *self) | 226 | static int dso__load_sym(struct dso *self, int fd, char *name) |
226 | { | 227 | { |
227 | Elf_Data *symstrs; | 228 | Elf_Data *symstrs; |
228 | uint32_t nr_syms; | 229 | uint32_t nr_syms; |
229 | int fd, err = -1; | 230 | int err = -1; |
230 | uint32_t index; | 231 | uint32_t index; |
231 | GElf_Ehdr ehdr; | 232 | GElf_Ehdr ehdr; |
232 | GElf_Shdr shdr; | 233 | GElf_Shdr shdr; |
@@ -234,16 +235,12 @@ static int dso__load(struct dso *self) | |||
234 | GElf_Sym sym; | 235 | GElf_Sym sym; |
235 | Elf_Scn *sec; | 236 | Elf_Scn *sec; |
236 | Elf *elf; | 237 | Elf *elf; |
237 | 238 | int nr = 0; | |
238 | |||
239 | fd = open(self->name, O_RDONLY); | ||
240 | if (fd == -1) | ||
241 | return -1; | ||
242 | 239 | ||
243 | elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); | 240 | elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); |
244 | if (elf == NULL) { | 241 | if (elf == NULL) { |
245 | fprintf(stderr, "%s: cannot read %s ELF file.\n", | 242 | fprintf(stderr, "%s: cannot read %s ELF file.\n", |
246 | __func__, self->name); | 243 | __func__, name); |
247 | goto out_close; | 244 | goto out_close; |
248 | } | 245 | } |
249 | 246 | ||
@@ -292,16 +289,63 @@ static int dso__load(struct dso *self) | |||
292 | goto out_elf_end; | 289 | goto out_elf_end; |
293 | 290 | ||
294 | dso__insert_symbol(self, f); | 291 | dso__insert_symbol(self, f); |
292 | |||
293 | nr++; | ||
295 | } | 294 | } |
296 | 295 | ||
297 | err = 0; | 296 | err = nr; |
298 | out_elf_end: | 297 | out_elf_end: |
299 | elf_end(elf); | 298 | elf_end(elf); |
300 | out_close: | 299 | out_close: |
301 | close(fd); | ||
302 | return err; | 300 | return err; |
303 | } | 301 | } |
304 | 302 | ||
303 | static int dso__load(struct dso *self) | ||
304 | { | ||
305 | int size = strlen(self->name) + sizeof("/usr/lib/debug%s.debug"); | ||
306 | char *name = malloc(size); | ||
307 | int variant = 0; | ||
308 | int ret = -1; | ||
309 | int fd; | ||
310 | |||
311 | if (!name) | ||
312 | return -1; | ||
313 | |||
314 | more: | ||
315 | do { | ||
316 | switch (variant) { | ||
317 | case 0: /* Fedora */ | ||
318 | snprintf(name, size, "/usr/lib/debug%s.debug", self->name); | ||
319 | break; | ||
320 | case 1: /* Ubuntu */ | ||
321 | snprintf(name, size, "/usr/lib/debug%s", self->name); | ||
322 | break; | ||
323 | case 2: /* Sane people */ | ||
324 | snprintf(name, size, "%s", self->name); | ||
325 | break; | ||
326 | |||
327 | default: | ||
328 | goto out; | ||
329 | } | ||
330 | variant++; | ||
331 | |||
332 | fd = open(name, O_RDONLY); | ||
333 | } while (fd < 0); | ||
334 | |||
335 | ret = dso__load_sym(self, fd, name); | ||
336 | close(fd); | ||
337 | |||
338 | /* | ||
339 | * Some people seem to have debuginfo files _WITHOUT_ debug info!?!? | ||
340 | */ | ||
341 | if (!ret) | ||
342 | goto more; | ||
343 | |||
344 | out: | ||
345 | free(name); | ||
346 | return ret; | ||
347 | } | ||
348 | |||
305 | static size_t dso__fprintf(struct dso *self, FILE *fp) | 349 | static size_t dso__fprintf(struct dso *self, FILE *fp) |
306 | { | 350 | { |
307 | size_t ret = fprintf(fp, "dso: %s\n", self->name); | 351 | size_t ret = fprintf(fp, "dso: %s\n", self->name); |
@@ -336,11 +380,23 @@ static struct dso *dsos__find(const char *name) | |||
336 | static struct dso *dsos__findnew(const char *name) | 380 | static struct dso *dsos__findnew(const char *name) |
337 | { | 381 | { |
338 | struct dso *dso = dsos__find(name); | 382 | struct dso *dso = dsos__find(name); |
383 | int nr; | ||
339 | 384 | ||
340 | if (dso == NULL) { | 385 | if (dso == NULL) { |
341 | dso = dso__new(name); | 386 | dso = dso__new(name); |
342 | if (dso != NULL && dso__load(dso) < 0) | 387 | if (!dso) |
388 | goto out_delete_dso; | ||
389 | |||
390 | nr = dso__load(dso); | ||
391 | if (nr < 0) { | ||
392 | fprintf(stderr, "Failed to open: %s\n", name); | ||
343 | goto out_delete_dso; | 393 | goto out_delete_dso; |
394 | } | ||
395 | if (!nr) { | ||
396 | fprintf(stderr, | ||
397 | "Failed to find debug symbols for: %s, maybe install a debug package?\n", | ||
398 | name); | ||
399 | } | ||
344 | 400 | ||
345 | dsos__add(dso); | 401 | dsos__add(dso); |
346 | } | 402 | } |
@@ -547,9 +603,9 @@ symhist__fprintf(struct symhist *self, uint64_t total_samples, FILE *fp) | |||
547 | size_t ret; | 603 | size_t ret; |
548 | 604 | ||
549 | if (total_samples) | 605 | if (total_samples) |
550 | ret = fprintf(fp, "%5.2f", (self->count * 100.0) / total_samples); | 606 | ret = fprintf(fp, "%5.2f%% ", (self->count * 100.0) / total_samples); |
551 | else | 607 | else |
552 | ret = fprintf(fp, "%12d", self->count); | 608 | ret = fprintf(fp, "%12d ", self->count); |
553 | 609 | ||
554 | ret += fprintf(fp, "%14s [%c] ", | 610 | ret += fprintf(fp, "%14s [%c] ", |
555 | thread__name(self->thread, bf, sizeof(bf)), | 611 | thread__name(self->thread, bf, sizeof(bf)), |
@@ -922,10 +978,12 @@ more: | |||
922 | } | 978 | } |
923 | default: { | 979 | default: { |
924 | broken_event: | 980 | broken_event: |
925 | fprintf(stderr, "%p [%p]: skipping unknown header type: %d\n", | 981 | if (dump_trace) |
926 | (void *)(offset + head), | 982 | fprintf(stderr, "%p [%p]: skipping unknown header type: %d\n", |
927 | (void *)(long)(event->header.size), | 983 | (void *)(offset + head), |
928 | event->header.type); | 984 | (void *)(long)(event->header.size), |
985 | event->header.type); | ||
986 | |||
929 | total_unknown++; | 987 | total_unknown++; |
930 | 988 | ||
931 | /* | 989 | /* |