aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/perf/builtin-annotate.c2
-rw-r--r--tools/perf/builtin-report.c2
-rw-r--r--tools/perf/builtin-top.c2
-rw-r--r--tools/perf/util/symbol.c159
-rw-r--r--tools/perf/util/symbol.h5
5 files changed, 156 insertions, 14 deletions
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 3becc8a35bee..88205686eb6e 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -171,7 +171,7 @@ static int load_kernel(void)
171 if (!kernel_dso) 171 if (!kernel_dso)
172 return -1; 172 return -1;
173 173
174 err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose); 174 err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose, 0);
175 if (err <= 0) { 175 if (err <= 0) {
176 dso__delete(kernel_dso); 176 dso__delete(kernel_dso);
177 kernel_dso = NULL; 177 kernel_dso = NULL;
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 58d1612894ff..38d136fedfb9 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -188,7 +188,7 @@ static int load_kernel(void)
188 if (!kernel_dso) 188 if (!kernel_dso)
189 return -1; 189 return -1;
190 190
191 err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose); 191 err = dso__load_kernel(kernel_dso, vmlinux, NULL, verbose, 0);
192 if (err <= 0) { 192 if (err <= 0) {
193 dso__delete(kernel_dso); 193 dso__delete(kernel_dso);
194 kernel_dso = NULL; 194 kernel_dso = NULL;
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 97fde1d84365..9bb25fc3d4ce 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -364,7 +364,7 @@ static int parse_symbols(void)
364 if (kernel_dso == NULL) 364 if (kernel_dso == NULL)
365 return -1; 365 return -1;
366 366
367 if (dso__load_kernel(kernel_dso, NULL, symbol_filter, 1) <= 0) 367 if (dso__load_kernel(kernel_dso, NULL, symbol_filter, 1, 0) <= 0)
368 goto out_delete_dso; 368 goto out_delete_dso;
369 369
370 node = rb_first(&kernel_dso->syms); 370 node = rb_first(&kernel_dso->syms);
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index c077b6a14690..98a13114de70 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)
@@ -310,6 +314,26 @@ static inline int elf_sym__is_function(const GElf_Sym *sym)
310 sym->st_size != 0; 314 sym->st_size != 0;
311} 315}
312 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
313static inline const char *elf_sym__name(const GElf_Sym *sym, 337static inline const char *elf_sym__name(const GElf_Sym *sym,
314 const Elf_Data *symstrs) 338 const Elf_Data *symstrs)
315{ 339{
@@ -451,9 +475,9 @@ static int dso__synthesize_plt_symbols(struct dso *self, Elf *elf,
451} 475}
452 476
453static 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,
454 symbol_filter_t filter, int verbose) 478 symbol_filter_t filter, int verbose, struct module *mod)
455{ 479{
456 Elf_Data *symstrs; 480 Elf_Data *symstrs, *secstrs;
457 uint32_t nr_syms; 481 uint32_t nr_syms;
458 int err = -1; 482 int err = -1;
459 uint32_t index; 483 uint32_t index;
@@ -461,7 +485,7 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
461 GElf_Shdr shdr; 485 GElf_Shdr shdr;
462 Elf_Data *syms; 486 Elf_Data *syms;
463 GElf_Sym sym; 487 GElf_Sym sym;
464 Elf_Scn *sec, *sec_dynsym; 488 Elf_Scn *sec, *sec_dynsym, *sec_strndx;
465 Elf *elf; 489 Elf *elf;
466 size_t dynsym_idx; 490 size_t dynsym_idx;
467 int nr = 0; 491 int nr = 0;
@@ -520,6 +544,14 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
520 if (symstrs == NULL) 544 if (symstrs == NULL)
521 goto out_elf_end; 545 goto out_elf_end;
522 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
523 nr_syms = shdr.sh_size / shdr.sh_entsize; 555 nr_syms = shdr.sh_size / shdr.sh_entsize;
524 556
525 memset(&sym, 0, sizeof(sym)); 557 memset(&sym, 0, sizeof(sym));
@@ -529,8 +561,11 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
529 elf_symtab__for_each_symbol(syms, nr_syms, index, sym) { 561 elf_symtab__for_each_symbol(syms, nr_syms, index, sym) {
530 struct symbol *f; 562 struct symbol *f;
531 u64 obj_start; 563 u64 obj_start;
564 struct section *section = NULL;
565 int is_label = elf_sym__is_label(&sym);
566 const char *section_name;
532 567
533 if (!elf_sym__is_function(&sym)) 568 if (!is_label && !elf_sym__is_function(&sym))
534 continue; 569 continue;
535 570
536 sec = elf_getscn(elf, sym.st_shndx); 571 sec = elf_getscn(elf, sym.st_shndx);
@@ -538,6 +573,11 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
538 goto out_elf_end; 573 goto out_elf_end;
539 574
540 gelf_getshdr(sec, &shdr); 575 gelf_getshdr(sec, &shdr);
576
577 if (is_label && !elf_sec__is_text(&shdr, secstrs))
578 continue;
579
580 section_name = elf_sec__name(&shdr, secstrs);
541 obj_start = sym.st_value; 581 obj_start = sym.st_value;
542 582
543 if (self->prelinked) { 583 if (self->prelinked) {
@@ -548,6 +588,17 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
548 sym.st_value -= shdr.sh_addr - shdr.sh_offset; 588 sym.st_value -= shdr.sh_addr - shdr.sh_offset;
549 } 589 }
550 590
591 if (mod) {
592 section = mod->sections->find_section(mod->sections, section_name);
593 if (section)
594 sym.st_value += section->vma;
595 else {
596 fprintf(stderr, "dso__load_sym() module %s lookup of %s failed\n",
597 mod->name, section_name);
598 goto out_elf_end;
599 }
600 }
601
551 f = symbol__new(sym.st_value, sym.st_size, 602 f = symbol__new(sym.st_value, sym.st_size,
552 elf_sym__name(&sym, symstrs), 603 elf_sym__name(&sym, symstrs),
553 self->sym_priv_size, obj_start, verbose); 604 self->sym_priv_size, obj_start, verbose);
@@ -557,6 +608,7 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
557 if (filter && filter(self, f)) 608 if (filter && filter(self, f))
558 symbol__delete(f, self->sym_priv_size); 609 symbol__delete(f, self->sym_priv_size);
559 else { 610 else {
611 f->module = mod;
560 dso__insert_symbol(self, f); 612 dso__insert_symbol(self, f);
561 nr++; 613 nr++;
562 } 614 }
@@ -606,7 +658,7 @@ more:
606 fd = open(name, O_RDONLY); 658 fd = open(name, O_RDONLY);
607 } while (fd < 0); 659 } while (fd < 0);
608 660
609 ret = dso__load_sym(self, fd, name, filter, verbose); 661 ret = dso__load_sym(self, fd, name, filter, verbose, NULL);
610 close(fd); 662 close(fd);
611 663
612 /* 664 /*
@@ -620,6 +672,86 @@ out:
620 return ret; 672 return ret;
621} 673}
622 674
675static int dso__load_module(struct dso *self, struct mod_dso *mods, const char *name,
676 symbol_filter_t filter, int verbose)
677{
678 struct module *mod = mod_dso__find_module(mods, name);
679 int err = 0, fd;
680
681 if (mod == NULL || !mod->active)
682 return err;
683
684 fd = open(mod->path, O_RDONLY);
685
686 if (fd < 0)
687 return err;
688
689 err = dso__load_sym(self, fd, name, filter, verbose, mod);
690 close(fd);
691
692 return err;
693}
694
695int dso__load_modules(struct dso *self, symbol_filter_t filter, int verbose)
696{
697 struct mod_dso *mods = mod_dso__new_dso("modules");
698 struct module *pos;
699 struct rb_node *next;
700 int err;
701
702 err = mod_dso__load_modules(mods);
703
704 if (err <= 0)
705 return err;
706
707 /*
708 * Iterate over modules, and load active symbols.
709 */
710 next = rb_first(&mods->mods);
711 while (next) {
712 pos = rb_entry(next, struct module, rb_node);
713 err = dso__load_module(self, mods, pos->name, filter, verbose);
714
715 if (err < 0)
716 break;
717
718 next = rb_next(&pos->rb_node);
719 }
720
721 if (err < 0) {
722 mod_dso__delete_modules(mods);
723 mod_dso__delete_self(mods);
724 }
725
726 return err;
727}
728
729static inline void dso__fill_symbol_holes(struct dso *self)
730{
731 struct symbol *prev = NULL;
732 struct rb_node *nd;
733
734 for (nd = rb_last(&self->syms); nd; nd = rb_prev(nd)) {
735 struct symbol *pos = rb_entry(nd, struct symbol, rb_node);
736
737 if (prev) {
738 u64 hole = 0;
739 int alias = pos->start == prev->start;
740
741 if (!alias)
742 hole = prev->start - pos->end - 1;
743
744 if (hole || alias) {
745 if (alias)
746 pos->end = prev->end;
747 else if (hole)
748 pos->end = prev->start - 1;
749 }
750 }
751 prev = pos;
752 }
753}
754
623static int dso__load_vmlinux(struct dso *self, const char *vmlinux, 755static int dso__load_vmlinux(struct dso *self, const char *vmlinux,
624 symbol_filter_t filter, int verbose) 756 symbol_filter_t filter, int verbose)
625{ 757{
@@ -628,19 +760,26 @@ static int dso__load_vmlinux(struct dso *self, const char *vmlinux,
628 if (fd < 0) 760 if (fd < 0)
629 return -1; 761 return -1;
630 762
631 err = dso__load_sym(self, fd, vmlinux, filter, verbose); 763 err = dso__load_sym(self, fd, vmlinux, filter, verbose, NULL);
764
765 if (err > 0)
766 dso__fill_symbol_holes(self);
767
632 close(fd); 768 close(fd);
633 769
634 return err; 770 return err;
635} 771}
636 772
637int dso__load_kernel(struct dso *self, const char *vmlinux, 773int dso__load_kernel(struct dso *self, const char *vmlinux,
638 symbol_filter_t filter, int verbose) 774 symbol_filter_t filter, int verbose, int modules)
639{ 775{
640 int err = -1; 776 int err = -1;
641 777
642 if (vmlinux) 778 if (vmlinux) {
643 err = dso__load_vmlinux(self, vmlinux, filter, verbose); 779 err = dso__load_vmlinux(self, vmlinux, filter, verbose);
780 if (err > 0 && modules)
781 err = dso__load_modules(self, filter, verbose);
782 }
644 783
645 if (err <= 0) 784 if (err <= 0)
646 err = dso__load_kallsyms(self, filter, verbose); 785 err = dso__load_kallsyms(self, filter, verbose);
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 65a8449b91f5..4e141a30911e 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -5,6 +5,7 @@
5#include "types.h" 5#include "types.h"
6#include <linux/list.h> 6#include <linux/list.h>
7#include <linux/rbtree.h> 7#include <linux/rbtree.h>
8#include "module.h"
8 9
9struct symbol { 10struct symbol {
10 struct rb_node rb_node; 11 struct rb_node rb_node;
@@ -13,6 +14,7 @@ struct symbol {
13 u64 obj_start; 14 u64 obj_start;
14 u64 hist_sum; 15 u64 hist_sum;
15 u64 *hist; 16 u64 *hist;
17 struct module *module;
16 void *priv; 18 void *priv;
17 char name[0]; 19 char name[0];
18}; 20};
@@ -41,7 +43,8 @@ static inline void *dso__sym_priv(struct dso *self, struct symbol *sym)
41struct symbol *dso__find_symbol(struct dso *self, u64 ip); 43struct symbol *dso__find_symbol(struct dso *self, u64 ip);
42 44
43int dso__load_kernel(struct dso *self, const char *vmlinux, 45int dso__load_kernel(struct dso *self, const char *vmlinux,
44 symbol_filter_t filter, int verbose); 46 symbol_filter_t filter, int verbose, int modules);
47int dso__load_modules(struct dso *self, symbol_filter_t filter, int verbose);
45int dso__load(struct dso *self, symbol_filter_t filter, int verbose); 48int dso__load(struct dso *self, symbol_filter_t filter, int verbose);
46 49
47size_t dso__fprintf(struct dso *self, FILE *fp); 50size_t dso__fprintf(struct dso *self, FILE *fp);