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.c447
1 files changed, 301 insertions, 146 deletions
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 559fb06210f5..e88296899470 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -2,12 +2,14 @@
2#include "../perf.h" 2#include "../perf.h"
3#include "string.h" 3#include "string.h"
4#include "symbol.h" 4#include "symbol.h"
5#include "thread.h"
5 6
6#include "debug.h" 7#include "debug.h"
7 8
8#include <libelf.h> 9#include <libelf.h>
9#include <gelf.h> 10#include <gelf.h>
10#include <elf.h> 11#include <elf.h>
12#include <sys/utsname.h>
11 13
12const char *sym_hist_filter; 14const char *sym_hist_filter;
13 15
@@ -18,12 +20,15 @@ enum dso_origin {
18 DSO__ORIG_UBUNTU, 20 DSO__ORIG_UBUNTU,
19 DSO__ORIG_BUILDID, 21 DSO__ORIG_BUILDID,
20 DSO__ORIG_DSO, 22 DSO__ORIG_DSO,
23 DSO__ORIG_KMODULE,
21 DSO__ORIG_NOT_FOUND, 24 DSO__ORIG_NOT_FOUND,
22}; 25};
23 26
24static struct symbol *symbol__new(u64 start, u64 len, 27static void dsos__add(struct dso *dso);
25 const char *name, unsigned int priv_size, 28static struct dso *dsos__find(const char *name);
26 u64 obj_start, int v) 29
30static struct symbol *symbol__new(u64 start, u64 len, const char *name,
31 unsigned int priv_size, int v)
27{ 32{
28 size_t namelen = strlen(name) + 1; 33 size_t namelen = strlen(name) + 1;
29 struct symbol *self = calloc(1, priv_size + sizeof(*self) + namelen); 34 struct symbol *self = calloc(1, priv_size + sizeof(*self) + namelen);
@@ -32,10 +37,9 @@ static struct symbol *symbol__new(u64 start, u64 len,
32 return NULL; 37 return NULL;
33 38
34 if (v >= 2) 39 if (v >= 2)
35 printf("new symbol: %016Lx [%08lx]: %s, hist: %p, obj_start: %p\n", 40 printf("new symbol: %016Lx [%08lx]: %s, hist: %p\n",
36 (u64)start, (unsigned long)len, name, self->hist, (void *)(unsigned long)obj_start); 41 start, (unsigned long)len, name, self->hist);
37 42
38 self->obj_start= obj_start;
39 self->hist = NULL; 43 self->hist = NULL;
40 self->hist_sum = 0; 44 self->hist_sum = 0;
41 45
@@ -60,12 +64,8 @@ static void symbol__delete(struct symbol *self, unsigned int priv_size)
60 64
61static size_t symbol__fprintf(struct symbol *self, FILE *fp) 65static size_t symbol__fprintf(struct symbol *self, FILE *fp)
62{ 66{
63 if (!self->module) 67 return fprintf(fp, " %llx-%llx %s\n",
64 return fprintf(fp, " %llx-%llx %s\n",
65 self->start, self->end, self->name); 68 self->start, self->end, self->name);
66 else
67 return fprintf(fp, " %llx-%llx %s \t[%s]\n",
68 self->start, self->end, self->name, self->module->name);
69} 69}
70 70
71struct dso *dso__new(const char *name, unsigned int sym_priv_size) 71struct dso *dso__new(const char *name, unsigned int sym_priv_size)
@@ -74,6 +74,8 @@ struct dso *dso__new(const char *name, unsigned int sym_priv_size)
74 74
75 if (self != NULL) { 75 if (self != NULL) {
76 strcpy(self->name, name); 76 strcpy(self->name, name);
77 self->long_name = self->name;
78 self->short_name = self->name;
77 self->syms = RB_ROOT; 79 self->syms = RB_ROOT;
78 self->sym_priv_size = sym_priv_size; 80 self->sym_priv_size = sym_priv_size;
79 self->find_symbol = dso__find_symbol; 81 self->find_symbol = dso__find_symbol;
@@ -100,6 +102,8 @@ static void dso__delete_symbols(struct dso *self)
100void dso__delete(struct dso *self) 102void dso__delete(struct dso *self)
101{ 103{
102 dso__delete_symbols(self); 104 dso__delete_symbols(self);
105 if (self->long_name != self->name)
106 free(self->long_name);
103 free(self); 107 free(self);
104} 108}
105 109
@@ -147,7 +151,7 @@ struct symbol *dso__find_symbol(struct dso *self, u64 ip)
147 151
148size_t dso__fprintf(struct dso *self, FILE *fp) 152size_t dso__fprintf(struct dso *self, FILE *fp)
149{ 153{
150 size_t ret = fprintf(fp, "dso: %s\n", self->name); 154 size_t ret = fprintf(fp, "dso: %s\n", self->long_name);
151 155
152 struct rb_node *nd; 156 struct rb_node *nd;
153 for (nd = rb_first(&self->syms); nd; nd = rb_next(nd)) { 157 for (nd = rb_first(&self->syms); nd; nd = rb_next(nd)) {
@@ -158,7 +162,8 @@ size_t dso__fprintf(struct dso *self, FILE *fp)
158 return ret; 162 return ret;
159} 163}
160 164
161static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int v) 165static int dso__load_kallsyms(struct dso *self, struct map *map,
166 symbol_filter_t filter, int v)
162{ 167{
163 struct rb_node *nd, *prevnd; 168 struct rb_node *nd, *prevnd;
164 char *line = NULL; 169 char *line = NULL;
@@ -200,12 +205,12 @@ static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int v)
200 * Well fix up the end later, when we have all sorted. 205 * Well fix up the end later, when we have all sorted.
201 */ 206 */
202 sym = symbol__new(start, 0xdead, line + len + 2, 207 sym = symbol__new(start, 0xdead, line + len + 2,
203 self->sym_priv_size, 0, v); 208 self->sym_priv_size, v);
204 209
205 if (sym == NULL) 210 if (sym == NULL)
206 goto out_delete_line; 211 goto out_delete_line;
207 212
208 if (filter && filter(self, sym)) 213 if (filter && filter(map, sym))
209 symbol__delete(sym, self->sym_priv_size); 214 symbol__delete(sym, self->sym_priv_size);
210 else { 215 else {
211 dso__insert_symbol(self, sym); 216 dso__insert_symbol(self, sym);
@@ -241,14 +246,15 @@ out_failure:
241 return -1; 246 return -1;
242} 247}
243 248
244static int dso__load_perf_map(struct dso *self, symbol_filter_t filter, int v) 249static int dso__load_perf_map(struct dso *self, struct map *map,
250 symbol_filter_t filter, int v)
245{ 251{
246 char *line = NULL; 252 char *line = NULL;
247 size_t n; 253 size_t n;
248 FILE *file; 254 FILE *file;
249 int nr_syms = 0; 255 int nr_syms = 0;
250 256
251 file = fopen(self->name, "r"); 257 file = fopen(self->long_name, "r");
252 if (file == NULL) 258 if (file == NULL)
253 goto out_failure; 259 goto out_failure;
254 260
@@ -279,12 +285,12 @@ static int dso__load_perf_map(struct dso *self, symbol_filter_t filter, int v)
279 continue; 285 continue;
280 286
281 sym = symbol__new(start, size, line + len, 287 sym = symbol__new(start, size, line + len,
282 self->sym_priv_size, start, v); 288 self->sym_priv_size, v);
283 289
284 if (sym == NULL) 290 if (sym == NULL)
285 goto out_delete_line; 291 goto out_delete_line;
286 292
287 if (filter && filter(self, sym)) 293 if (filter && filter(map, sym))
288 symbol__delete(sym, self->sym_priv_size); 294 symbol__delete(sym, self->sym_priv_size);
289 else { 295 else {
290 dso__insert_symbol(self, sym); 296 dso__insert_symbol(self, sym);
@@ -410,7 +416,7 @@ static int dso__synthesize_plt_symbols(struct dso *self, int v)
410 Elf *elf; 416 Elf *elf;
411 int nr = 0, symidx, fd, err = 0; 417 int nr = 0, symidx, fd, err = 0;
412 418
413 fd = open(self->name, O_RDONLY); 419 fd = open(self->long_name, O_RDONLY);
414 if (fd < 0) 420 if (fd < 0)
415 goto out; 421 goto out;
416 422
@@ -478,7 +484,7 @@ static int dso__synthesize_plt_symbols(struct dso *self, int v)
478 "%s@plt", elf_sym__name(&sym, symstrs)); 484 "%s@plt", elf_sym__name(&sym, symstrs));
479 485
480 f = symbol__new(plt_offset, shdr_plt.sh_entsize, 486 f = symbol__new(plt_offset, shdr_plt.sh_entsize,
481 sympltname, self->sym_priv_size, 0, v); 487 sympltname, self->sym_priv_size, v);
482 if (!f) 488 if (!f)
483 goto out_elf_end; 489 goto out_elf_end;
484 490
@@ -496,7 +502,7 @@ static int dso__synthesize_plt_symbols(struct dso *self, int v)
496 "%s@plt", elf_sym__name(&sym, symstrs)); 502 "%s@plt", elf_sym__name(&sym, symstrs));
497 503
498 f = symbol__new(plt_offset, shdr_plt.sh_entsize, 504 f = symbol__new(plt_offset, shdr_plt.sh_entsize,
499 sympltname, self->sym_priv_size, 0, v); 505 sympltname, self->sym_priv_size, v);
500 if (!f) 506 if (!f)
501 goto out_elf_end; 507 goto out_elf_end;
502 508
@@ -515,12 +521,13 @@ out_close:
515 return nr; 521 return nr;
516out: 522out:
517 fprintf(stderr, "%s: problems reading %s PLT info.\n", 523 fprintf(stderr, "%s: problems reading %s PLT info.\n",
518 __func__, self->name); 524 __func__, self->long_name);
519 return 0; 525 return 0;
520} 526}
521 527
522static int dso__load_sym(struct dso *self, int fd, const char *name, 528static int dso__load_sym(struct dso *self, struct map *map, const char *name,
523 symbol_filter_t filter, int v, struct module *mod) 529 int fd, symbol_filter_t filter, int kernel,
530 int kmodule, int v)
524{ 531{
525 Elf_Data *symstrs, *secstrs; 532 Elf_Data *symstrs, *secstrs;
526 uint32_t nr_syms; 533 uint32_t nr_syms;
@@ -532,7 +539,7 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
532 GElf_Sym sym; 539 GElf_Sym sym;
533 Elf_Scn *sec, *sec_strndx; 540 Elf_Scn *sec, *sec_strndx;
534 Elf *elf; 541 Elf *elf;
535 int nr = 0, kernel = !strcmp("[kernel]", self->name); 542 int nr = 0;
536 543
537 elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); 544 elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
538 if (elf == NULL) { 545 if (elf == NULL) {
@@ -589,8 +596,6 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
589 struct symbol *f; 596 struct symbol *f;
590 const char *elf_name; 597 const char *elf_name;
591 char *demangled; 598 char *demangled;
592 u64 obj_start;
593 struct section *section = NULL;
594 int is_label = elf_sym__is_label(&sym); 599 int is_label = elf_sym__is_label(&sym);
595 const char *section_name; 600 const char *section_name;
596 601
@@ -607,7 +612,6 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
607 continue; 612 continue;
608 613
609 section_name = elf_sec__name(&shdr, secstrs); 614 section_name = elf_sec__name(&shdr, secstrs);
610 obj_start = sym.st_value;
611 615
612 if (self->adjust_symbols) { 616 if (self->adjust_symbols) {
613 if (v >= 2) 617 if (v >= 2)
@@ -615,18 +619,8 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
615 (u64)sym.st_value, (u64)shdr.sh_addr, (u64)shdr.sh_offset); 619 (u64)sym.st_value, (u64)shdr.sh_addr, (u64)shdr.sh_offset);
616 620
617 sym.st_value -= shdr.sh_addr - shdr.sh_offset; 621 sym.st_value -= shdr.sh_addr - shdr.sh_offset;
618 } 622 } else if (kmodule)
619 623 sym.st_value += shdr.sh_offset;
620 if (mod) {
621 section = mod->sections->find_section(mod->sections, section_name);
622 if (section)
623 sym.st_value += section->vma;
624 else {
625 fprintf(stderr, "dso__load_sym() module %s lookup of %s failed\n",
626 mod->name, section_name);
627 goto out_elf_end;
628 }
629 }
630 /* 624 /*
631 * We need to figure out if the object was created from C++ sources 625 * We need to figure out if the object was created from C++ sources
632 * DWARF DW_compile_unit has this, but we don't always have access 626 * DWARF DW_compile_unit has this, but we don't always have access
@@ -638,15 +632,14 @@ static int dso__load_sym(struct dso *self, int fd, const char *name,
638 elf_name = demangled; 632 elf_name = demangled;
639 633
640 f = symbol__new(sym.st_value, sym.st_size, elf_name, 634 f = symbol__new(sym.st_value, sym.st_size, elf_name,
641 self->sym_priv_size, obj_start, v); 635 self->sym_priv_size, v);
642 free(demangled); 636 free(demangled);
643 if (!f) 637 if (!f)
644 goto out_elf_end; 638 goto out_elf_end;
645 639
646 if (filter && filter(self, f)) 640 if (filter && filter(map, f))
647 symbol__delete(f, self->sym_priv_size); 641 symbol__delete(f, self->sym_priv_size);
648 else { 642 else {
649 f->module = mod;
650 dso__insert_symbol(self, f); 643 dso__insert_symbol(self, f);
651 nr++; 644 nr++;
652 } 645 }
@@ -671,7 +664,7 @@ static char *dso__read_build_id(struct dso *self, int v)
671 char *build_id = NULL, *bid; 664 char *build_id = NULL, *bid;
672 unsigned char *raw; 665 unsigned char *raw;
673 Elf *elf; 666 Elf *elf;
674 int fd = open(self->name, O_RDONLY); 667 int fd = open(self->long_name, O_RDONLY);
675 668
676 if (fd < 0) 669 if (fd < 0)
677 goto out; 670 goto out;
@@ -680,7 +673,7 @@ static char *dso__read_build_id(struct dso *self, int v)
680 if (elf == NULL) { 673 if (elf == NULL) {
681 if (v) 674 if (v)
682 fprintf(stderr, "%s: cannot read %s ELF file.\n", 675 fprintf(stderr, "%s: cannot read %s ELF file.\n",
683 __func__, self->name); 676 __func__, self->long_name);
684 goto out_close; 677 goto out_close;
685 } 678 }
686 679
@@ -709,7 +702,7 @@ static char *dso__read_build_id(struct dso *self, int v)
709 bid += 2; 702 bid += 2;
710 } 703 }
711 if (v >= 2) 704 if (v >= 2)
712 printf("%s(%s): %s\n", __func__, self->name, build_id); 705 printf("%s(%s): %s\n", __func__, self->long_name, build_id);
713out_elf_end: 706out_elf_end:
714 elf_end(elf); 707 elf_end(elf);
715out_close: 708out_close:
@@ -727,6 +720,7 @@ char dso__symtab_origin(const struct dso *self)
727 [DSO__ORIG_UBUNTU] = 'u', 720 [DSO__ORIG_UBUNTU] = 'u',
728 [DSO__ORIG_BUILDID] = 'b', 721 [DSO__ORIG_BUILDID] = 'b',
729 [DSO__ORIG_DSO] = 'd', 722 [DSO__ORIG_DSO] = 'd',
723 [DSO__ORIG_KMODULE] = 'K',
730 }; 724 };
731 725
732 if (self == NULL || self->origin == DSO__ORIG_NOT_FOUND) 726 if (self == NULL || self->origin == DSO__ORIG_NOT_FOUND)
@@ -734,7 +728,7 @@ char dso__symtab_origin(const struct dso *self)
734 return origin[self->origin]; 728 return origin[self->origin];
735} 729}
736 730
737int dso__load(struct dso *self, symbol_filter_t filter, int v) 731int dso__load(struct dso *self, struct map *map, symbol_filter_t filter, int v)
738{ 732{
739 int size = PATH_MAX; 733 int size = PATH_MAX;
740 char *name = malloc(size), *build_id = NULL; 734 char *name = malloc(size), *build_id = NULL;
@@ -747,7 +741,7 @@ int dso__load(struct dso *self, symbol_filter_t filter, int v)
747 self->adjust_symbols = 0; 741 self->adjust_symbols = 0;
748 742
749 if (strncmp(self->name, "/tmp/perf-", 10) == 0) { 743 if (strncmp(self->name, "/tmp/perf-", 10) == 0) {
750 ret = dso__load_perf_map(self, filter, v); 744 ret = dso__load_perf_map(self, map, filter, v);
751 self->origin = ret > 0 ? DSO__ORIG_JAVA_JIT : 745 self->origin = ret > 0 ? DSO__ORIG_JAVA_JIT :
752 DSO__ORIG_NOT_FOUND; 746 DSO__ORIG_NOT_FOUND;
753 return ret; 747 return ret;
@@ -760,10 +754,12 @@ more:
760 self->origin++; 754 self->origin++;
761 switch (self->origin) { 755 switch (self->origin) {
762 case DSO__ORIG_FEDORA: 756 case DSO__ORIG_FEDORA:
763 snprintf(name, size, "/usr/lib/debug%s.debug", self->name); 757 snprintf(name, size, "/usr/lib/debug%s.debug",
758 self->long_name);
764 break; 759 break;
765 case DSO__ORIG_UBUNTU: 760 case DSO__ORIG_UBUNTU:
766 snprintf(name, size, "/usr/lib/debug%s", self->name); 761 snprintf(name, size, "/usr/lib/debug%s",
762 self->long_name);
767 break; 763 break;
768 case DSO__ORIG_BUILDID: 764 case DSO__ORIG_BUILDID:
769 build_id = dso__read_build_id(self, v); 765 build_id = dso__read_build_id(self, v);
@@ -777,7 +773,7 @@ more:
777 self->origin++; 773 self->origin++;
778 /* Fall thru */ 774 /* Fall thru */
779 case DSO__ORIG_DSO: 775 case DSO__ORIG_DSO:
780 snprintf(name, size, "%s", self->name); 776 snprintf(name, size, "%s", self->long_name);
781 break; 777 break;
782 778
783 default: 779 default:
@@ -787,7 +783,7 @@ more:
787 fd = open(name, O_RDONLY); 783 fd = open(name, O_RDONLY);
788 } while (fd < 0); 784 } while (fd < 0);
789 785
790 ret = dso__load_sym(self, fd, name, filter, v, NULL); 786 ret = dso__load_sym(self, map, name, fd, filter, 0, 0, v);
791 close(fd); 787 close(fd);
792 788
793 /* 789 /*
@@ -808,89 +804,247 @@ out:
808 return ret; 804 return ret;
809} 805}
810 806
811static int dso__load_module(struct dso *self, struct mod_dso *mods, const char *name, 807static struct rb_root kernel_maps;
812 symbol_filter_t filter, int v) 808struct map *kernel_map;
809
810static void kernel_maps__insert(struct map *map)
813{ 811{
814 struct module *mod = mod_dso__find_module(mods, name); 812 maps__insert(&kernel_maps, map);
815 int err = 0, fd; 813}
816 814
817 if (mod == NULL || !mod->active) 815struct symbol *kernel_maps__find_symbol(u64 ip, struct map **mapp)
818 return err; 816{
817 /*
818 * We can't have kernel_map in kernel_maps because it spans an address
819 * space that includes the modules. The right way to fix this is to
820 * create several maps, so that we don't have overlapping ranges with
821 * modules. For now lets look first on the kernel dso.
822 */
823 struct map *map = maps__find(&kernel_maps, ip);
824 struct symbol *sym;
825
826 if (map) {
827 ip = map->map_ip(map, ip);
828 sym = map->dso->find_symbol(map->dso, ip);
829 } else {
830 map = kernel_map;
831 sym = map->dso->find_symbol(map->dso, ip);
832 }
819 833
820 fd = open(mod->path, O_RDONLY); 834 if (mapp)
835 *mapp = map;
821 836
822 if (fd < 0) 837 return sym;
838}
839
840struct map *kernel_maps__find_by_dso_name(const char *name)
841{
842 struct rb_node *nd;
843
844 for (nd = rb_first(&kernel_maps); nd; nd = rb_next(nd)) {
845 struct map *map = rb_entry(nd, struct map, rb_node);
846
847 if (map->dso && strcmp(map->dso->name, name) == 0)
848 return map;
849 }
850
851 return NULL;
852}
853
854static int dso__load_module_sym(struct dso *self, struct map *map,
855 symbol_filter_t filter, int v)
856{
857 int err = 0, fd = open(self->long_name, O_RDONLY);
858
859 if (fd < 0) {
860 if (v)
861 fprintf(stderr, "%s: cannot open %s\n",
862 __func__, self->long_name);
823 return err; 863 return err;
864 }
824 865
825 err = dso__load_sym(self, fd, name, filter, v, mod); 866 err = dso__load_sym(self, map, self->long_name, fd, filter, 0, 1, v);
826 close(fd); 867 close(fd);
827 868
828 return err; 869 return err;
829} 870}
830 871
831int dso__load_modules(struct dso *self, symbol_filter_t filter, int v) 872static int dsos__load_modules_sym_dir(char *dirname,
873 symbol_filter_t filter, int v)
832{ 874{
833 struct mod_dso *mods = mod_dso__new_dso("modules"); 875 struct dirent *dent;
834 struct module *pos; 876 int nr_symbols = 0, err;
835 struct rb_node *next; 877 DIR *dir = opendir(dirname);
836 int err, count = 0;
837 878
838 err = mod_dso__load_modules(mods); 879 if (!dir) {
880 if (v)
881 fprintf(stderr, "%s: cannot open %s dir\n", __func__,
882 dirname);
883 return -1;
884 }
839 885
840 if (err <= 0) 886 while ((dent = readdir(dir)) != NULL) {
841 return err; 887 char path[PATH_MAX];
888
889 if (dent->d_type == DT_DIR) {
890 if (!strcmp(dent->d_name, ".") ||
891 !strcmp(dent->d_name, ".."))
892 continue;
893
894 snprintf(path, sizeof(path), "%s/%s",
895 dirname, dent->d_name);
896 err = dsos__load_modules_sym_dir(path, filter, v);
897 if (err < 0)
898 goto failure;
899 } else {
900 char *dot = strrchr(dent->d_name, '.'),
901 dso_name[PATH_MAX];
902 struct map *map;
903 struct rb_node *last;
904
905 if (dot == NULL || strcmp(dot, ".ko"))
906 continue;
907 snprintf(dso_name, sizeof(dso_name), "[%.*s]",
908 (int)(dot - dent->d_name), dent->d_name);
909
910 map = kernel_maps__find_by_dso_name(dso_name);
911 if (map == NULL)
912 continue;
913
914 snprintf(path, sizeof(path), "%s/%s",
915 dirname, dent->d_name);
916
917 map->dso->long_name = strdup(path);
918 if (map->dso->long_name == NULL)
919 goto failure;
920
921 err = dso__load_module_sym(map->dso, map, filter, v);
922 if (err < 0)
923 goto failure;
924 last = rb_last(&map->dso->syms);
925 if (last) {
926 struct symbol *sym;
927 sym = rb_entry(last, struct symbol, rb_node);
928 map->end = map->start + sym->end;
929 }
930 }
931 nr_symbols += err;
932 }
842 933
843 /* 934 return nr_symbols;
844 * Iterate over modules, and load active symbols. 935failure:
845 */ 936 closedir(dir);
846 next = rb_first(&mods->mods); 937 return -1;
847 while (next) { 938}
848 pos = rb_entry(next, struct module, rb_node);
849 err = dso__load_module(self, mods, pos->name, filter, v);
850 939
851 if (err < 0) 940static int dsos__load_modules_sym(symbol_filter_t filter, int v)
852 break; 941{
942 struct utsname uts;
943 char modules_path[PATH_MAX];
853 944
854 next = rb_next(&pos->rb_node); 945 if (uname(&uts) < 0)
855 count += err; 946 return -1;
856 }
857 947
858 if (err < 0) { 948 snprintf(modules_path, sizeof(modules_path), "/lib/modules/%s/kernel",
859 mod_dso__delete_modules(mods); 949 uts.release);
860 mod_dso__delete_self(mods);
861 return err;
862 }
863 950
864 return count; 951 return dsos__load_modules_sym_dir(modules_path, filter, v);
865} 952}
866 953
867static inline void dso__fill_symbol_holes(struct dso *self) 954/*
955 * Constructor variant for modules (where we know from /proc/modules where
956 * they are loaded) and for vmlinux, where only after we load all the
957 * symbols we'll know where it starts and ends.
958 */
959static struct map *map__new2(u64 start, struct dso *dso)
868{ 960{
869 struct symbol *prev = NULL; 961 struct map *self = malloc(sizeof(*self));
870 struct rb_node *nd;
871 962
872 for (nd = rb_last(&self->syms); nd; nd = rb_prev(nd)) { 963 if (self != NULL) {
873 struct symbol *pos = rb_entry(nd, struct symbol, rb_node); 964 self->start = start;
965 /*
966 * Will be filled after we load all the symbols
967 */
968 self->end = 0;
969
970 self->pgoff = 0;
971 self->dso = dso;
972 self->map_ip = map__map_ip;
973 RB_CLEAR_NODE(&self->rb_node);
974 }
975 return self;
976}
977
978int dsos__load_modules(unsigned int sym_priv_size,
979 symbol_filter_t filter, int v)
980{
981 char *line = NULL;
982 size_t n;
983 FILE *file = fopen("/proc/modules", "r");
984 struct map *map;
874 985
875 if (prev) { 986 if (file == NULL)
876 u64 hole = 0; 987 return -1;
877 int alias = pos->start == prev->start;
878 988
879 if (!alias) 989 while (!feof(file)) {
880 hole = prev->start - pos->end - 1; 990 char name[PATH_MAX];
991 u64 start;
992 struct dso *dso;
993 char *sep;
994 int line_len;
881 995
882 if (hole || alias) { 996 line_len = getline(&line, &n, file);
883 if (alias) 997 if (line_len < 0)
884 pos->end = prev->end; 998 break;
885 else if (hole) 999
886 pos->end = prev->start - 1; 1000 if (!line)
887 } 1001 goto out_failure;
1002
1003 line[--line_len] = '\0'; /* \n */
1004
1005 sep = strrchr(line, 'x');
1006 if (sep == NULL)
1007 continue;
1008
1009 hex2u64(sep + 1, &start);
1010
1011 sep = strchr(line, ' ');
1012 if (sep == NULL)
1013 continue;
1014
1015 *sep = '\0';
1016
1017 snprintf(name, sizeof(name), "[%s]", line);
1018 dso = dso__new(name, sym_priv_size);
1019
1020 if (dso == NULL)
1021 goto out_delete_line;
1022
1023 map = map__new2(start, dso);
1024 if (map == NULL) {
1025 dso__delete(dso);
1026 goto out_delete_line;
888 } 1027 }
889 prev = pos; 1028
1029 dso->origin = DSO__ORIG_KMODULE;
1030 kernel_maps__insert(map);
1031 dsos__add(dso);
890 } 1032 }
1033
1034 free(line);
1035 fclose(file);
1036
1037 v = 1;
1038 return dsos__load_modules_sym(filter, v);
1039
1040out_delete_line:
1041 free(line);
1042out_failure:
1043 return -1;
891} 1044}
892 1045
893static int dso__load_vmlinux(struct dso *self, const char *vmlinux, 1046static int dso__load_vmlinux(struct dso *self, struct map *map,
1047 const char *vmlinux,
894 symbol_filter_t filter, int v) 1048 symbol_filter_t filter, int v)
895{ 1049{
896 int err, fd = open(vmlinux, O_RDONLY); 1050 int err, fd = open(vmlinux, O_RDONLY);
@@ -898,28 +1052,36 @@ static int dso__load_vmlinux(struct dso *self, const char *vmlinux,
898 if (fd < 0) 1052 if (fd < 0)
899 return -1; 1053 return -1;
900 1054
901 err = dso__load_sym(self, fd, vmlinux, filter, v, NULL); 1055 err = dso__load_sym(self, map, self->long_name, fd, filter, 1, 0, v);
902
903 if (err > 0)
904 dso__fill_symbol_holes(self);
905 1056
906 close(fd); 1057 close(fd);
907 1058
908 return err; 1059 return err;
909} 1060}
910 1061
911int dso__load_kernel(struct dso *self, const char *vmlinux, 1062int dsos__load_kernel(const char *vmlinux, unsigned int sym_priv_size,
912 symbol_filter_t filter, int v, int use_modules) 1063 symbol_filter_t filter, int v, int use_modules)
913{ 1064{
914 int err = -1; 1065 int err = -1;
1066 struct dso *dso = dso__new(vmlinux, sym_priv_size);
1067
1068 if (dso == NULL)
1069 return -1;
1070
1071 dso->short_name = "[kernel]";
1072 kernel_map = map__new2(0, dso);
1073 if (kernel_map == NULL)
1074 goto out_delete_dso;
1075
1076 kernel_map->map_ip = vdso__map_ip;
915 1077
916 if (vmlinux) { 1078 if (vmlinux) {
917 err = dso__load_vmlinux(self, vmlinux, filter, v); 1079 err = dso__load_vmlinux(dso, kernel_map, vmlinux, filter, v);
918 if (err > 0 && use_modules) { 1080 if (err > 0 && use_modules) {
919 int syms = dso__load_modules(self, filter, v); 1081 int syms = dsos__load_modules(sym_priv_size, filter, v);
920 1082
921 if (syms < 0) { 1083 if (syms < 0) {
922 fprintf(stderr, "dso__load_modules failed!\n"); 1084 fprintf(stderr, "dsos__load_modules failed!\n");
923 return syms; 1085 return syms;
924 } 1086 }
925 err += syms; 1087 err += syms;
@@ -927,18 +1089,34 @@ int dso__load_kernel(struct dso *self, const char *vmlinux,
927 } 1089 }
928 1090
929 if (err <= 0) 1091 if (err <= 0)
930 err = dso__load_kallsyms(self, filter, v); 1092 err = dso__load_kallsyms(dso, kernel_map, filter, v);
1093
1094 if (err > 0) {
1095 struct rb_node *node = rb_first(&dso->syms);
1096 struct symbol *sym = rb_entry(node, struct symbol, rb_node);
931 1097
932 if (err > 0) 1098 kernel_map->start = sym->start;
933 self->origin = DSO__ORIG_KERNEL; 1099 node = rb_last(&dso->syms);
1100 sym = rb_entry(node, struct symbol, rb_node);
1101 kernel_map->end = sym->end;
1102
1103 dso->origin = DSO__ORIG_KERNEL;
1104 /*
1105 * XXX See kernel_maps__find_symbol comment
1106 * kernel_maps__insert(kernel_map)
1107 */
1108 dsos__add(dso);
1109 }
934 1110
935 return err; 1111 return err;
1112
1113out_delete_dso:
1114 dso__delete(dso);
1115 return -1;
936} 1116}
937 1117
938LIST_HEAD(dsos); 1118LIST_HEAD(dsos);
939struct dso *kernel_dso;
940struct dso *vdso; 1119struct dso *vdso;
941struct dso *hypervisor_dso;
942 1120
943const char *vmlinux_name = "vmlinux"; 1121const char *vmlinux_name = "vmlinux";
944int modules; 1122int modules;
@@ -970,7 +1148,7 @@ struct dso *dsos__findnew(const char *name)
970 if (!dso) 1148 if (!dso)
971 goto out_delete_dso; 1149 goto out_delete_dso;
972 1150
973 nr = dso__load(dso, NULL, verbose); 1151 nr = dso__load(dso, NULL, NULL, verbose);
974 if (nr < 0) { 1152 if (nr < 0) {
975 eprintf("Failed to open: %s\n", name); 1153 eprintf("Failed to open: %s\n", name);
976 goto out_delete_dso; 1154 goto out_delete_dso;
@@ -995,43 +1173,20 @@ void dsos__fprintf(FILE *fp)
995 dso__fprintf(pos, fp); 1173 dso__fprintf(pos, fp);
996} 1174}
997 1175
998static struct symbol *vdso__find_symbol(struct dso *dso, u64 ip)
999{
1000 return dso__find_symbol(dso, ip);
1001}
1002
1003int load_kernel(void) 1176int load_kernel(void)
1004{ 1177{
1005 int err; 1178 if (dsos__load_kernel(vmlinux_name, 0, NULL, verbose, modules) <= 0)
1006
1007 kernel_dso = dso__new("[kernel]", 0);
1008 if (!kernel_dso)
1009 return -1; 1179 return -1;
1010 1180
1011 err = dso__load_kernel(kernel_dso, vmlinux_name, NULL, verbose, modules);
1012 if (err <= 0) {
1013 dso__delete(kernel_dso);
1014 kernel_dso = NULL;
1015 } else
1016 dsos__add(kernel_dso);
1017
1018 vdso = dso__new("[vdso]", 0); 1181 vdso = dso__new("[vdso]", 0);
1019 if (!vdso) 1182 if (!vdso)
1020 return -1; 1183 return -1;
1021 1184
1022 vdso->find_symbol = vdso__find_symbol;
1023
1024 dsos__add(vdso); 1185 dsos__add(vdso);
1025 1186
1026 hypervisor_dso = dso__new("[hypervisor]", 0); 1187 return 0;
1027 if (!hypervisor_dso)
1028 return -1;
1029 dsos__add(hypervisor_dso);
1030
1031 return err;
1032} 1188}
1033 1189
1034
1035void symbol__init(void) 1190void symbol__init(void)
1036{ 1191{
1037 elf_version(EV_CURRENT); 1192 elf_version(EV_CURRENT);