aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/symbol.c
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2009-07-11 11:18:36 -0400
committerIngo Molnar <mingo@elte.hu>2009-07-11 13:20:26 -0400
commita25e46c46311316cd1b3f27f8bb036df1693c032 (patch)
tree271937d116b3bd343f91948440321fa80e7702ab /tools/perf/util/symbol.c
parent021191b35cdfb1b5ee6e78ed5ae010114a40902c (diff)
perf_counter tools: PLT info is stripped in -debuginfo packages
So we need to get the richer .symtab from the debuginfo packages but the PLT info from the original DSO where we have just the leaner .dynsym symtab. Example: | [acme@doppio pahole]$ perf report --sort comm,dso,symbol > before | [acme@doppio pahole]$ perf report --sort comm,dso,symbol > after | [acme@doppio pahole]$ diff -U1 before after | --- before 2009-07-11 11:04:22.688595741 -0300 | +++ after 2009-07-11 11:04:33.380595676 -0300 | @@ -80,3 +80,2 @@ | 0.07% pahole ./build/pahole [.] pahole_stealer | - 0.06% pahole /usr/lib64/libdw-0.141.so [.] 0x00000000007140 | 0.06% pahole /usr/lib64/libdw-0.141.so [.] __libdw_getabbrev | @@ -91,2 +90,3 @@ | 0.06% pahole [kernel] [k] free_hot_cold_page | + 0.06% pahole /usr/lib64/libdw-0.141.so [.] tfind@plt | 0.05% pahole ./build/libdwarves.so.1.0.0 [.] ftype__add_parameter | @@ -242,2 +242,3 @@ | 0.01% pahole [kernel] [k] account_group_user_time | + 0.01% pahole /usr/lib64/libdw-0.141.so [.] strlen@plt | 0.01% pahole ./build/pahole [.] strcmp@plt | [acme@doppio pahole]$ Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> LKML-Reference: <1247325517-12272-4-git-send-email-acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf/util/symbol.c')
-rw-r--r--tools/perf/util/symbol.c116
1 files changed, 65 insertions, 51 deletions
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 8efe7e41109a..f40266b4845d 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -374,36 +374,61 @@ static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
374 idx < nr_entries; \ 374 idx < nr_entries; \
375 ++idx, pos = gelf_getrela(reldata, idx, &pos_mem)) 375 ++idx, pos = gelf_getrela(reldata, idx, &pos_mem))
376 376
377static int dso__synthesize_plt_symbols(struct dso *self, Elf *elf, 377/*
378 GElf_Ehdr *ehdr, Elf_Scn *scn_dynsym, 378 * We need to check if we have a .dynsym, so that we can handle the
379 GElf_Shdr *shdr_dynsym, 379 * .plt, synthesizing its symbols, that aren't on the symtabs (be it
380 size_t dynsym_idx, int verbose) 380 * .dynsym or .symtab).
381 * And always look at the original dso, not at debuginfo packages, that
382 * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS).
383 */
384static int dso__synthesize_plt_symbols(struct dso *self, int verbose)
381{ 385{
382 uint32_t nr_rel_entries, idx; 386 uint32_t nr_rel_entries, idx;
383 GElf_Sym sym; 387 GElf_Sym sym;
384 u64 plt_offset; 388 u64 plt_offset;
385 GElf_Shdr shdr_plt; 389 GElf_Shdr shdr_plt;
386 struct symbol *f; 390 struct symbol *f;
387 GElf_Shdr shdr_rel_plt; 391 GElf_Shdr shdr_rel_plt, shdr_dynsym;
388 Elf_Data *reldata, *syms, *symstrs; 392 Elf_Data *reldata, *syms, *symstrs;
389 Elf_Scn *scn_plt_rel, *scn_symstrs; 393 Elf_Scn *scn_plt_rel, *scn_symstrs, *scn_dynsym;
394 size_t dynsym_idx;
395 GElf_Ehdr ehdr;
390 char sympltname[1024]; 396 char sympltname[1024];
391 int nr = 0, symidx; 397 Elf *elf;
398 int nr = 0, symidx, fd, err = 0;
399
400 fd = open(self->name, O_RDONLY);
401 if (fd < 0)
402 goto out;
403
404 elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
405 if (elf == NULL)
406 goto out_close;
407
408 if (gelf_getehdr(elf, &ehdr) == NULL)
409 goto out_elf_end;
410
411 scn_dynsym = elf_section_by_name(elf, &ehdr, &shdr_dynsym,
412 ".dynsym", &dynsym_idx);
413 if (scn_dynsym == NULL)
414 goto out_elf_end;
392 415
393 scn_plt_rel = elf_section_by_name(elf, ehdr, &shdr_rel_plt, 416 scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt,
394 ".rela.plt", NULL); 417 ".rela.plt", NULL);
395 if (scn_plt_rel == NULL) { 418 if (scn_plt_rel == NULL) {
396 scn_plt_rel = elf_section_by_name(elf, ehdr, &shdr_rel_plt, 419 scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt,
397 ".rel.plt", NULL); 420 ".rel.plt", NULL);
398 if (scn_plt_rel == NULL) 421 if (scn_plt_rel == NULL)
399 return 0; 422 goto out_elf_end;
400 } 423 }
401 424
425 err = -1;
426
402 if (shdr_rel_plt.sh_link != dynsym_idx) 427 if (shdr_rel_plt.sh_link != dynsym_idx)
403 return 0; 428 goto out_elf_end;
404 429
405 if (elf_section_by_name(elf, ehdr, &shdr_plt, ".plt", NULL) == NULL) 430 if (elf_section_by_name(elf, &ehdr, &shdr_plt, ".plt", NULL) == NULL)
406 return 0; 431 goto out_elf_end;
407 432
408 /* 433 /*
409 * Fetch the relocation section to find the indexes to the GOT 434 * Fetch the relocation section to find the indexes to the GOT
@@ -411,19 +436,19 @@ static int dso__synthesize_plt_symbols(struct dso *self, Elf *elf,
411 */ 436 */
412 reldata = elf_getdata(scn_plt_rel, NULL); 437 reldata = elf_getdata(scn_plt_rel, NULL);
413 if (reldata == NULL) 438 if (reldata == NULL)
414 return -1; 439 goto out_elf_end;
415 440
416 syms = elf_getdata(scn_dynsym, NULL); 441 syms = elf_getdata(scn_dynsym, NULL);
417 if (syms == NULL) 442 if (syms == NULL)
418 return -1; 443 goto out_elf_end;
419 444
420 scn_symstrs = elf_getscn(elf, shdr_dynsym->sh_link); 445 scn_symstrs = elf_getscn(elf, shdr_dynsym.sh_link);
421 if (scn_symstrs == NULL) 446 if (scn_symstrs == NULL)
422 return -1; 447 goto out_elf_end;
423 448
424 symstrs = elf_getdata(scn_symstrs, NULL); 449 symstrs = elf_getdata(scn_symstrs, NULL);
425 if (symstrs == NULL) 450 if (symstrs == NULL)
426 return -1; 451 goto out_elf_end;
427 452
428 nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize; 453 nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize;
429 plt_offset = shdr_plt.sh_offset; 454 plt_offset = shdr_plt.sh_offset;
@@ -442,7 +467,7 @@ static int dso__synthesize_plt_symbols(struct dso *self, Elf *elf,
442 f = symbol__new(plt_offset, shdr_plt.sh_entsize, 467 f = symbol__new(plt_offset, shdr_plt.sh_entsize,
443 sympltname, self->sym_priv_size, 0, verbose); 468 sympltname, self->sym_priv_size, 0, verbose);
444 if (!f) 469 if (!f)
445 return -1; 470 goto out_elf_end;
446 471
447 dso__insert_symbol(self, f); 472 dso__insert_symbol(self, f);
448 ++nr; 473 ++nr;
@@ -460,19 +485,25 @@ static int dso__synthesize_plt_symbols(struct dso *self, Elf *elf,
460 f = symbol__new(plt_offset, shdr_plt.sh_entsize, 485 f = symbol__new(plt_offset, shdr_plt.sh_entsize,
461 sympltname, self->sym_priv_size, 0, verbose); 486 sympltname, self->sym_priv_size, 0, verbose);
462 if (!f) 487 if (!f)
463 return -1; 488 goto out_elf_end;
464 489
465 dso__insert_symbol(self, f); 490 dso__insert_symbol(self, f);
466 ++nr; 491 ++nr;
467 } 492 }
468 } else {
469 /*
470 * TODO: There are still one more shdr_rel_plt.sh_type
471 * I have to investigate, but probably should be ignored.
472 */
473 } 493 }
474 494
475 return nr; 495 err = 0;
496out_elf_end:
497 elf_end(elf);
498out_close:
499 close(fd);
500
501 if (err == 0)
502 return nr;
503out:
504 fprintf(stderr, "%s: problems reading %s PLT info.\n",
505 __func__, self->name);
506 return 0;
476} 507}
477 508
478static int dso__load_sym(struct dso *self, int fd, const char *name, 509static int dso__load_sym(struct dso *self, int fd, const char *name,
@@ -486,9 +517,8 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
486 GElf_Shdr shdr; 517 GElf_Shdr shdr;
487 Elf_Data *syms; 518 Elf_Data *syms;
488 GElf_Sym sym; 519 GElf_Sym sym;
489 Elf_Scn *sec, *sec_dynsym, *sec_strndx; 520 Elf_Scn *sec, *sec_strndx;
490 Elf *elf; 521 Elf *elf;
491 size_t dynsym_idx;
492 int nr = 0; 522 int nr = 0;
493 523
494 elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); 524 elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
@@ -505,32 +535,11 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
505 goto out_elf_end; 535 goto out_elf_end;
506 } 536 }
507 537
508 /*
509 * We need to check if we have a .dynsym, so that we can handle the
510 * .plt, synthesizing its symbols, that aren't on the symtabs (be it
511 * .dynsym or .symtab)
512 */
513 sec_dynsym = elf_section_by_name(elf, &ehdr, &shdr,
514 ".dynsym", &dynsym_idx);
515 if (sec_dynsym != NULL) {
516 nr = dso__synthesize_plt_symbols(self, elf, &ehdr,
517 sec_dynsym, &shdr,
518 dynsym_idx, verbose);
519 if (nr < 0)
520 goto out_elf_end;
521 }
522
523 /*
524 * But if we have a full .symtab (that is a superset of .dynsym) we
525 * should add the symbols not in the .dynsyn
526 */
527 sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL); 538 sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL);
528 if (sec == NULL) { 539 if (sec == NULL) {
529 if (sec_dynsym == NULL) 540 sec = elf_section_by_name(elf, &ehdr, &shdr, ".dynsym", NULL);
541 if (sec == NULL)
530 goto out_elf_end; 542 goto out_elf_end;
531
532 sec = sec_dynsym;
533 gelf_getshdr(sec, &shdr);
534 } 543 }
535 544
536 syms = elf_getdata(sec, NULL); 545 syms = elf_getdata(sec, NULL);
@@ -669,6 +678,11 @@ more:
669 if (!ret) 678 if (!ret)
670 goto more; 679 goto more;
671 680
681 if (ret > 0) {
682 int nr_plt = dso__synthesize_plt_symbols(self, verbose);
683 if (nr_plt > 0)
684 ret += nr_plt;
685 }
672out: 686out:
673 free(name); 687 free(name);
674 return ret; 688 return ret;