aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/symbol.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/symbol.c')
-rw-r--r--tools/perf/util/symbol.c179
1 files changed, 161 insertions, 18 deletions
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 78c2efde01b7..4683b67b5ee4 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -35,7 +35,7 @@ static struct symbol *symbol__new(u64 start, u64 len,
35 self = ((void *)self) + priv_size; 35 self = ((void *)self) + priv_size;
36 } 36 }
37 self->start = start; 37 self->start = start;
38 self->end = start + len - 1; 38 self->end = len ? start + len - 1 : start;
39 memcpy(self->name, name, namelen); 39 memcpy(self->name, name, namelen);
40 40
41 return self; 41 return self;
@@ -48,8 +48,12 @@ static void symbol__delete(struct symbol *self, unsigned int priv_size)
48 48
49static size_t symbol__fprintf(struct symbol *self, FILE *fp) 49static size_t symbol__fprintf(struct symbol *self, FILE *fp)
50{ 50{
51 return fprintf(fp, " %llx-%llx %s\n", 51 if (!self->module)
52 return fprintf(fp, " %llx-%llx %s\n",
52 self->start, self->end, self->name); 53 self->start, self->end, self->name);
54 else
55 return fprintf(fp, " %llx-%llx %s \t[%s]\n",
56 self->start, self->end, self->name, self->module->name);
53} 57}
54 58
55struct dso *dso__new(const char *name, unsigned int sym_priv_size) 59struct dso *dso__new(const char *name, unsigned int sym_priv_size)
@@ -146,6 +150,7 @@ static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int verb
146 char *line = NULL; 150 char *line = NULL;
147 size_t n; 151 size_t n;
148 FILE *file = fopen("/proc/kallsyms", "r"); 152 FILE *file = fopen("/proc/kallsyms", "r");
153 int count = 0;
149 154
150 if (file == NULL) 155 if (file == NULL)
151 goto out_failure; 156 goto out_failure;
@@ -188,8 +193,10 @@ static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int verb
188 193
189 if (filter && filter(self, sym)) 194 if (filter && filter(self, sym))
190 symbol__delete(sym, self->sym_priv_size); 195 symbol__delete(sym, self->sym_priv_size);
191 else 196 else {
192 dso__insert_symbol(self, sym); 197 dso__insert_symbol(self, sym);
198 count++;
199 }
193 } 200 }
194 201
195 /* 202 /*
@@ -212,7 +219,7 @@ static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int verb
212 free(line); 219 free(line);
213 fclose(file); 220 fclose(file);
214 221
215 return 0; 222 return count;
216 223
217out_delete_line: 224out_delete_line:
218 free(line); 225 free(line);
@@ -307,6 +314,26 @@ static inline int elf_sym__is_function(const GElf_Sym *sym)
307 sym->st_size != 0; 314 sym->st_size != 0;
308} 315}
309 316
317static inline int elf_sym__is_label(const GElf_Sym *sym)
318{
319 return elf_sym__type(sym) == STT_NOTYPE &&
320 sym->st_name != 0 &&
321 sym->st_shndx != SHN_UNDEF &&
322 sym->st_shndx != SHN_ABS;
323}
324
325static inline const char *elf_sec__name(const GElf_Shdr *shdr,
326 const Elf_Data *secstrs)
327{
328 return secstrs->d_buf + shdr->sh_name;
329}
330
331static inline int elf_sec__is_text(const GElf_Shdr *shdr,
332 const Elf_Data *secstrs)
333{
334 return strstr(elf_sec__name(shdr, secstrs), "text") != NULL;
335}
336
310static inline const char *elf_sym__name(const GElf_Sym *sym, 337static inline const char *elf_sym__name(const GElf_Sym *sym,
311 const Elf_Data *symstrs) 338 const Elf_Data *symstrs)
312{ 339{
@@ -448,9 +475,9 @@ static int dso__synthesize_plt_symbols(struct dso *self, Elf *elf,
448} 475}
449 476
450static int dso__load_sym(struct dso *self, int fd, const char *name, 477static int dso__load_sym(struct dso *self, int fd, const char *name,
451 symbol_filter_t filter, int verbose) 478 symbol_filter_t filter, int verbose, struct module *mod)
452{ 479{
453 Elf_Data *symstrs; 480 Elf_Data *symstrs, *secstrs;
454 uint32_t nr_syms; 481 uint32_t nr_syms;
455 int err = -1; 482 int err = -1;
456 uint32_t index; 483 uint32_t index;
@@ -458,7 +485,7 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
458 GElf_Shdr shdr; 485 GElf_Shdr shdr;
459 Elf_Data *syms; 486 Elf_Data *syms;
460 GElf_Sym sym; 487 GElf_Sym sym;
461 Elf_Scn *sec, *sec_dynsym; 488 Elf_Scn *sec, *sec_dynsym, *sec_strndx;
462 Elf *elf; 489 Elf *elf;
463 size_t dynsym_idx; 490 size_t dynsym_idx;
464 int nr = 0; 491 int nr = 0;
@@ -517,17 +544,29 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
517 if (symstrs == NULL) 544 if (symstrs == NULL)
518 goto out_elf_end; 545 goto out_elf_end;
519 546
547 sec_strndx = elf_getscn(elf, ehdr.e_shstrndx);
548 if (sec_strndx == NULL)
549 goto out_elf_end;
550
551 secstrs = elf_getdata(sec_strndx, NULL);
552 if (symstrs == NULL)
553 goto out_elf_end;
554
520 nr_syms = shdr.sh_size / shdr.sh_entsize; 555 nr_syms = shdr.sh_size / shdr.sh_entsize;
521 556
522 memset(&sym, 0, sizeof(sym)); 557 memset(&sym, 0, sizeof(sym));
523 self->prelinked = elf_section_by_name(elf, &ehdr, &shdr, 558 self->adjust_symbols = (ehdr.e_type == ET_EXEC ||
524 ".gnu.prelink_undo", 559 elf_section_by_name(elf, &ehdr, &shdr,
525 NULL) != NULL; 560 ".gnu.prelink_undo",
561 NULL) != NULL);
526 elf_symtab__for_each_symbol(syms, nr_syms, index, sym) { 562 elf_symtab__for_each_symbol(syms, nr_syms, index, sym) {
527 struct symbol *f; 563 struct symbol *f;
528 u64 obj_start; 564 u64 obj_start;
565 struct section *section = NULL;
566 int is_label = elf_sym__is_label(&sym);
567 const char *section_name;
529 568
530 if (!elf_sym__is_function(&sym)) 569 if (!is_label && !elf_sym__is_function(&sym))
531 continue; 570 continue;
532 571
533 sec = elf_getscn(elf, sym.st_shndx); 572 sec = elf_getscn(elf, sym.st_shndx);
@@ -535,9 +574,14 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
535 goto out_elf_end; 574 goto out_elf_end;
536 575
537 gelf_getshdr(sec, &shdr); 576 gelf_getshdr(sec, &shdr);
577
578 if (is_label && !elf_sec__is_text(&shdr, secstrs))
579 continue;
580
581 section_name = elf_sec__name(&shdr, secstrs);
538 obj_start = sym.st_value; 582 obj_start = sym.st_value;
539 583
540 if (self->prelinked) { 584 if (self->adjust_symbols) {
541 if (verbose >= 2) 585 if (verbose >= 2)
542 printf("adjusting symbol: st_value: %Lx sh_addr: %Lx sh_offset: %Lx\n", 586 printf("adjusting symbol: st_value: %Lx sh_addr: %Lx sh_offset: %Lx\n",
543 (u64)sym.st_value, (u64)shdr.sh_addr, (u64)shdr.sh_offset); 587 (u64)sym.st_value, (u64)shdr.sh_addr, (u64)shdr.sh_offset);
@@ -545,6 +589,17 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
545 sym.st_value -= shdr.sh_addr - shdr.sh_offset; 589 sym.st_value -= shdr.sh_addr - shdr.sh_offset;
546 } 590 }
547 591
592 if (mod) {
593 section = mod->sections->find_section(mod->sections, section_name);
594 if (section)
595 sym.st_value += section->vma;
596 else {
597 fprintf(stderr, "dso__load_sym() module %s lookup of %s failed\n",
598 mod->name, section_name);
599 goto out_elf_end;
600 }
601 }
602
548 f = symbol__new(sym.st_value, sym.st_size, 603 f = symbol__new(sym.st_value, sym.st_size,
549 elf_sym__name(&sym, symstrs), 604 elf_sym__name(&sym, symstrs),
550 self->sym_priv_size, obj_start, verbose); 605 self->sym_priv_size, obj_start, verbose);
@@ -554,6 +609,7 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
554 if (filter && filter(self, f)) 609 if (filter && filter(self, f))
555 symbol__delete(f, self->sym_priv_size); 610 symbol__delete(f, self->sym_priv_size);
556 else { 611 else {
612 f->module = mod;
557 dso__insert_symbol(self, f); 613 dso__insert_symbol(self, f);
558 nr++; 614 nr++;
559 } 615 }
@@ -577,7 +633,7 @@ int dso__load(struct dso *self, symbol_filter_t filter, int verbose)
577 if (!name) 633 if (!name)
578 return -1; 634 return -1;
579 635
580 self->prelinked = 0; 636 self->adjust_symbols = 0;
581 637
582 if (strncmp(self->name, "/tmp/perf-", 10) == 0) 638 if (strncmp(self->name, "/tmp/perf-", 10) == 0)
583 return dso__load_perf_map(self, filter, verbose); 639 return dso__load_perf_map(self, filter, verbose);
@@ -603,7 +659,7 @@ more:
603 fd = open(name, O_RDONLY); 659 fd = open(name, O_RDONLY);
604 } while (fd < 0); 660 } while (fd < 0);
605 661
606 ret = dso__load_sym(self, fd, name, filter, verbose); 662 ret = dso__load_sym(self, fd, name, filter, verbose, NULL);
607 close(fd); 663 close(fd);
608 664
609 /* 665 /*
@@ -617,6 +673,86 @@ out:
617 return ret; 673 return ret;
618} 674}
619 675
676static int dso__load_module(struct dso *self, struct mod_dso *mods, const char *name,
677 symbol_filter_t filter, int verbose)
678{
679 struct module *mod = mod_dso__find_module(mods, name);
680 int err = 0, fd;
681
682 if (mod == NULL || !mod->active)
683 return err;
684
685 fd = open(mod->path, O_RDONLY);
686
687 if (fd < 0)
688 return err;
689
690 err = dso__load_sym(self, fd, name, filter, verbose, mod);
691 close(fd);
692
693 return err;
694}
695
696int dso__load_modules(struct dso *self, symbol_filter_t filter, int verbose)
697{
698 struct mod_dso *mods = mod_dso__new_dso("modules");
699 struct module *pos;
700 struct rb_node *next;
701 int err;
702
703 err = mod_dso__load_modules(mods);
704
705 if (err <= 0)
706 return err;
707
708 /*
709 * Iterate over modules, and load active symbols.
710 */
711 next = rb_first(&mods->mods);
712 while (next) {
713 pos = rb_entry(next, struct module, rb_node);
714 err = dso__load_module(self, mods, pos->name, filter, verbose);
715
716 if (err < 0)
717 break;
718
719 next = rb_next(&pos->rb_node);
720 }
721
722 if (err < 0) {
723 mod_dso__delete_modules(mods);
724 mod_dso__delete_self(mods);
725 }
726
727 return err;
728}
729
730static inline void dso__fill_symbol_holes(struct dso *self)
731{
732 struct symbol *prev = NULL;
733 struct rb_node *nd;
734
735 for (nd = rb_last(&self->syms); nd; nd = rb_prev(nd)) {
736 struct symbol *pos = rb_entry(nd, struct symbol, rb_node);
737
738 if (prev) {
739 u64 hole = 0;
740 int alias = pos->start == prev->start;
741
742 if (!alias)
743 hole = prev->start - pos->end - 1;
744
745 if (hole || alias) {
746 if (alias)
747 pos->end = prev->end;
748 else if (hole)
749 pos->end = prev->start - 1;
750 }
751 }
752 prev = pos;
753 }
754}
755
620static int dso__load_vmlinux(struct dso *self, const char *vmlinux, 756static int dso__load_vmlinux(struct dso *self, const char *vmlinux,
621 symbol_filter_t filter, int verbose) 757 symbol_filter_t filter, int verbose)
622{ 758{
@@ -625,21 +761,28 @@ static int dso__load_vmlinux(struct dso *self, const char *vmlinux,
625 if (fd < 0) 761 if (fd < 0)
626 return -1; 762 return -1;
627 763
628 err = dso__load_sym(self, fd, vmlinux, filter, verbose); 764 err = dso__load_sym(self, fd, vmlinux, filter, verbose, NULL);
765
766 if (err > 0)
767 dso__fill_symbol_holes(self);
768
629 close(fd); 769 close(fd);
630 770
631 return err; 771 return err;
632} 772}
633 773
634int dso__load_kernel(struct dso *self, const char *vmlinux, 774int dso__load_kernel(struct dso *self, const char *vmlinux,
635 symbol_filter_t filter, int verbose) 775 symbol_filter_t filter, int verbose, int modules)
636{ 776{
637 int err = -1; 777 int err = -1;
638 778
639 if (vmlinux) 779 if (vmlinux) {
640 err = dso__load_vmlinux(self, vmlinux, filter, verbose); 780 err = dso__load_vmlinux(self, vmlinux, filter, verbose);
781 if (err > 0 && modules)
782 err = dso__load_modules(self, filter, verbose);
783 }
641 784
642 if (err < 0) 785 if (err <= 0)
643 err = dso__load_kallsyms(self, filter, verbose); 786 err = dso__load_kallsyms(self, filter, verbose);
644 787
645 return err; 788 return err;