aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/symbol.c
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2009-10-02 02:29:58 -0400
committerIngo Molnar <mingo@elte.hu>2009-10-02 04:48:42 -0400
commit439d473b4777de510e1322168ac6f2f377ecd5bc (patch)
treef33622a0b98c2b0ce16637322d48542eb93e2fa3 /tools/perf/util/symbol.c
parent2ccdc450e658053681202d42ac64b3638f22dc1a (diff)
perf tools: Rewrite and improve support for kernel modules
Representing modules as struct map entries, backed by a DSO, etc, using /proc/modules to find where the module is loaded. DSOs now can have a short and long name, so that in verbose mode we can show exactly which .ko or vmlinux image was used. As kernel modules now are a DSO separate from the kernel, we can ask for just the hits for a particular set of kernel modules, just like we can do with shared libraries: [root@doppio linux-2.6-tip]# perf report -n --vmlinux /home/acme/git/build/tip-recvmmsg/vmlinux --modules --dsos \[drm\] | head -15 84.58% 13266 Xorg [k] drm_clflush_pages 4.02% 630 Xorg [k] trace_kmalloc.clone.0 3.95% 619 Xorg [k] drm_ioctl 2.07% 324 Xorg [k] drm_addbufs 1.68% 263 Xorg [k] drm_gem_close_ioctl 0.77% 120 Xorg [k] drm_setmaster_ioctl 0.70% 110 Xorg [k] drm_lastclose 0.68% 106 Xorg [k] drm_open 0.54% 85 Xorg [k] drm_mm_search_free [root@doppio linux-2.6-tip]# Specifying --dsos /lib/modules/2.6.31-tip/kernel/drivers/gpu/drm/drm.ko would have the same effect. Allowing specifying just 'drm.ko' is left for another patch. Processing kallsyms so that per kernel module struct map are instantiated was also left for another patch. That will allow removing the module name from each of its symbols. struct symbol was reduced by removing the ->module backpointer and moving it (well now the map) to struct symbol_entry in perf top, that is its only user right now. The total linecount went down by ~500 lines. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Frédéric Weisbecker <fweisbec@gmail.com> Cc: "H. Peter Anvin" <hpa@zytor.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Mike Galbraith <efault@gmx.de> Cc: Avi Kivity <avi@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.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);