diff options
Diffstat (limited to 'tools/perf/util/symbol.c')
-rw-r--r-- | tools/perf/util/symbol.c | 199 |
1 files changed, 149 insertions, 50 deletions
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 5c0f42e6b33b..fd3d9c8e90fc 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -3,6 +3,8 @@ | |||
3 | #include "string.h" | 3 | #include "string.h" |
4 | #include "symbol.h" | 4 | #include "symbol.h" |
5 | 5 | ||
6 | #include "debug.h" | ||
7 | |||
6 | #include <libelf.h> | 8 | #include <libelf.h> |
7 | #include <gelf.h> | 9 | #include <gelf.h> |
8 | #include <elf.h> | 10 | #include <elf.h> |
@@ -21,7 +23,7 @@ enum dso_origin { | |||
21 | 23 | ||
22 | static struct symbol *symbol__new(u64 start, u64 len, | 24 | static struct symbol *symbol__new(u64 start, u64 len, |
23 | const char *name, unsigned int priv_size, | 25 | const char *name, unsigned int priv_size, |
24 | u64 obj_start, int verbose) | 26 | u64 obj_start, int v) |
25 | { | 27 | { |
26 | size_t namelen = strlen(name) + 1; | 28 | size_t namelen = strlen(name) + 1; |
27 | struct symbol *self = calloc(1, priv_size + sizeof(*self) + namelen); | 29 | struct symbol *self = calloc(1, priv_size + sizeof(*self) + namelen); |
@@ -29,7 +31,7 @@ static struct symbol *symbol__new(u64 start, u64 len, | |||
29 | if (!self) | 31 | if (!self) |
30 | return NULL; | 32 | return NULL; |
31 | 33 | ||
32 | if (verbose >= 2) | 34 | if (v >= 2) |
33 | printf("new symbol: %016Lx [%08lx]: %s, hist: %p, obj_start: %p\n", | 35 | printf("new symbol: %016Lx [%08lx]: %s, hist: %p, obj_start: %p\n", |
34 | (u64)start, (unsigned long)len, name, self->hist, (void *)(unsigned long)obj_start); | 36 | (u64)start, (unsigned long)len, name, self->hist, (void *)(unsigned long)obj_start); |
35 | 37 | ||
@@ -156,7 +158,7 @@ size_t dso__fprintf(struct dso *self, FILE *fp) | |||
156 | return ret; | 158 | return ret; |
157 | } | 159 | } |
158 | 160 | ||
159 | static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int verbose) | 161 | static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int v) |
160 | { | 162 | { |
161 | struct rb_node *nd, *prevnd; | 163 | struct rb_node *nd, *prevnd; |
162 | char *line = NULL; | 164 | char *line = NULL; |
@@ -198,7 +200,7 @@ static int dso__load_kallsyms(struct dso *self, symbol_filter_t filter, int verb | |||
198 | * Well fix up the end later, when we have all sorted. | 200 | * Well fix up the end later, when we have all sorted. |
199 | */ | 201 | */ |
200 | sym = symbol__new(start, 0xdead, line + len + 2, | 202 | sym = symbol__new(start, 0xdead, line + len + 2, |
201 | self->sym_priv_size, 0, verbose); | 203 | self->sym_priv_size, 0, v); |
202 | 204 | ||
203 | if (sym == NULL) | 205 | if (sym == NULL) |
204 | goto out_delete_line; | 206 | goto out_delete_line; |
@@ -239,7 +241,7 @@ out_failure: | |||
239 | return -1; | 241 | return -1; |
240 | } | 242 | } |
241 | 243 | ||
242 | static int dso__load_perf_map(struct dso *self, symbol_filter_t filter, int verbose) | 244 | static int dso__load_perf_map(struct dso *self, symbol_filter_t filter, int v) |
243 | { | 245 | { |
244 | char *line = NULL; | 246 | char *line = NULL; |
245 | size_t n; | 247 | size_t n; |
@@ -277,7 +279,7 @@ static int dso__load_perf_map(struct dso *self, symbol_filter_t filter, int verb | |||
277 | continue; | 279 | continue; |
278 | 280 | ||
279 | sym = symbol__new(start, size, line + len, | 281 | sym = symbol__new(start, size, line + len, |
280 | self->sym_priv_size, start, verbose); | 282 | self->sym_priv_size, start, v); |
281 | 283 | ||
282 | if (sym == NULL) | 284 | if (sym == NULL) |
283 | goto out_delete_line; | 285 | goto out_delete_line; |
@@ -305,13 +307,13 @@ out_failure: | |||
305 | * elf_symtab__for_each_symbol - iterate thru all the symbols | 307 | * elf_symtab__for_each_symbol - iterate thru all the symbols |
306 | * | 308 | * |
307 | * @self: struct elf_symtab instance to iterate | 309 | * @self: struct elf_symtab instance to iterate |
308 | * @index: uint32_t index | 310 | * @idx: uint32_t idx |
309 | * @sym: GElf_Sym iterator | 311 | * @sym: GElf_Sym iterator |
310 | */ | 312 | */ |
311 | #define elf_symtab__for_each_symbol(syms, nr_syms, index, sym) \ | 313 | #define elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) \ |
312 | for (index = 0, gelf_getsym(syms, index, &sym);\ | 314 | for (idx = 0, gelf_getsym(syms, idx, &sym);\ |
313 | index < nr_syms; \ | 315 | idx < nr_syms; \ |
314 | index++, gelf_getsym(syms, index, &sym)) | 316 | idx++, gelf_getsym(syms, idx, &sym)) |
315 | 317 | ||
316 | static inline uint8_t elf_sym__type(const GElf_Sym *sym) | 318 | static inline uint8_t elf_sym__type(const GElf_Sym *sym) |
317 | { | 319 | { |
@@ -354,7 +356,7 @@ static inline const char *elf_sym__name(const GElf_Sym *sym, | |||
354 | 356 | ||
355 | static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep, | 357 | static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep, |
356 | GElf_Shdr *shp, const char *name, | 358 | GElf_Shdr *shp, const char *name, |
357 | size_t *index) | 359 | size_t *idx) |
358 | { | 360 | { |
359 | Elf_Scn *sec = NULL; | 361 | Elf_Scn *sec = NULL; |
360 | size_t cnt = 1; | 362 | size_t cnt = 1; |
@@ -365,8 +367,8 @@ static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep, | |||
365 | gelf_getshdr(sec, shp); | 367 | gelf_getshdr(sec, shp); |
366 | str = elf_strptr(elf, ep->e_shstrndx, shp->sh_name); | 368 | str = elf_strptr(elf, ep->e_shstrndx, shp->sh_name); |
367 | if (!strcmp(name, str)) { | 369 | if (!strcmp(name, str)) { |
368 | if (index) | 370 | if (idx) |
369 | *index = cnt; | 371 | *idx = cnt; |
370 | break; | 372 | break; |
371 | } | 373 | } |
372 | ++cnt; | 374 | ++cnt; |
@@ -392,7 +394,7 @@ static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep, | |||
392 | * And always look at the original dso, not at debuginfo packages, that | 394 | * And always look at the original dso, not at debuginfo packages, that |
393 | * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS). | 395 | * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS). |
394 | */ | 396 | */ |
395 | static int dso__synthesize_plt_symbols(struct dso *self, int verbose) | 397 | static int dso__synthesize_plt_symbols(struct dso *self, int v) |
396 | { | 398 | { |
397 | uint32_t nr_rel_entries, idx; | 399 | uint32_t nr_rel_entries, idx; |
398 | GElf_Sym sym; | 400 | GElf_Sym sym; |
@@ -442,7 +444,7 @@ static int dso__synthesize_plt_symbols(struct dso *self, int verbose) | |||
442 | goto out_elf_end; | 444 | goto out_elf_end; |
443 | 445 | ||
444 | /* | 446 | /* |
445 | * Fetch the relocation section to find the indexes to the GOT | 447 | * Fetch the relocation section to find the idxes to the GOT |
446 | * and the symbols in the .dynsym they refer to. | 448 | * and the symbols in the .dynsym they refer to. |
447 | */ | 449 | */ |
448 | reldata = elf_getdata(scn_plt_rel, NULL); | 450 | reldata = elf_getdata(scn_plt_rel, NULL); |
@@ -476,7 +478,7 @@ static int dso__synthesize_plt_symbols(struct dso *self, int verbose) | |||
476 | "%s@plt", elf_sym__name(&sym, symstrs)); | 478 | "%s@plt", elf_sym__name(&sym, symstrs)); |
477 | 479 | ||
478 | f = symbol__new(plt_offset, shdr_plt.sh_entsize, | 480 | f = symbol__new(plt_offset, shdr_plt.sh_entsize, |
479 | sympltname, self->sym_priv_size, 0, verbose); | 481 | sympltname, self->sym_priv_size, 0, v); |
480 | if (!f) | 482 | if (!f) |
481 | goto out_elf_end; | 483 | goto out_elf_end; |
482 | 484 | ||
@@ -494,7 +496,7 @@ static int dso__synthesize_plt_symbols(struct dso *self, int verbose) | |||
494 | "%s@plt", elf_sym__name(&sym, symstrs)); | 496 | "%s@plt", elf_sym__name(&sym, symstrs)); |
495 | 497 | ||
496 | f = symbol__new(plt_offset, shdr_plt.sh_entsize, | 498 | f = symbol__new(plt_offset, shdr_plt.sh_entsize, |
497 | sympltname, self->sym_priv_size, 0, verbose); | 499 | sympltname, self->sym_priv_size, 0, v); |
498 | if (!f) | 500 | if (!f) |
499 | goto out_elf_end; | 501 | goto out_elf_end; |
500 | 502 | ||
@@ -518,12 +520,12 @@ out: | |||
518 | } | 520 | } |
519 | 521 | ||
520 | static int dso__load_sym(struct dso *self, int fd, const char *name, | 522 | static int dso__load_sym(struct dso *self, int fd, const char *name, |
521 | symbol_filter_t filter, int verbose, struct module *mod) | 523 | symbol_filter_t filter, int v, struct module *mod) |
522 | { | 524 | { |
523 | Elf_Data *symstrs, *secstrs; | 525 | Elf_Data *symstrs, *secstrs; |
524 | uint32_t nr_syms; | 526 | uint32_t nr_syms; |
525 | int err = -1; | 527 | int err = -1; |
526 | uint32_t index; | 528 | uint32_t idx; |
527 | GElf_Ehdr ehdr; | 529 | GElf_Ehdr ehdr; |
528 | GElf_Shdr shdr; | 530 | GElf_Shdr shdr; |
529 | Elf_Data *syms; | 531 | Elf_Data *syms; |
@@ -534,14 +536,14 @@ static int dso__load_sym(struct dso *self, int fd, const char *name, | |||
534 | 536 | ||
535 | elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); | 537 | elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); |
536 | if (elf == NULL) { | 538 | if (elf == NULL) { |
537 | if (verbose) | 539 | if (v) |
538 | fprintf(stderr, "%s: cannot read %s ELF file.\n", | 540 | fprintf(stderr, "%s: cannot read %s ELF file.\n", |
539 | __func__, name); | 541 | __func__, name); |
540 | goto out_close; | 542 | goto out_close; |
541 | } | 543 | } |
542 | 544 | ||
543 | if (gelf_getehdr(elf, &ehdr) == NULL) { | 545 | if (gelf_getehdr(elf, &ehdr) == NULL) { |
544 | if (verbose) | 546 | if (v) |
545 | fprintf(stderr, "%s: cannot get elf header.\n", __func__); | 547 | fprintf(stderr, "%s: cannot get elf header.\n", __func__); |
546 | goto out_elf_end; | 548 | goto out_elf_end; |
547 | } | 549 | } |
@@ -583,9 +585,9 @@ static int dso__load_sym(struct dso *self, int fd, const char *name, | |||
583 | NULL) != NULL); | 585 | NULL) != NULL); |
584 | } else self->adjust_symbols = 0; | 586 | } else self->adjust_symbols = 0; |
585 | 587 | ||
586 | elf_symtab__for_each_symbol(syms, nr_syms, index, sym) { | 588 | elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) { |
587 | struct symbol *f; | 589 | struct symbol *f; |
588 | const char *name; | 590 | const char *elf_name; |
589 | char *demangled; | 591 | char *demangled; |
590 | u64 obj_start; | 592 | u64 obj_start; |
591 | struct section *section = NULL; | 593 | struct section *section = NULL; |
@@ -608,7 +610,7 @@ static int dso__load_sym(struct dso *self, int fd, const char *name, | |||
608 | obj_start = sym.st_value; | 610 | obj_start = sym.st_value; |
609 | 611 | ||
610 | if (self->adjust_symbols) { | 612 | if (self->adjust_symbols) { |
611 | if (verbose >= 2) | 613 | if (v >= 2) |
612 | printf("adjusting symbol: st_value: %Lx sh_addr: %Lx sh_offset: %Lx\n", | 614 | printf("adjusting symbol: st_value: %Lx sh_addr: %Lx sh_offset: %Lx\n", |
613 | (u64)sym.st_value, (u64)shdr.sh_addr, (u64)shdr.sh_offset); | 615 | (u64)sym.st_value, (u64)shdr.sh_addr, (u64)shdr.sh_offset); |
614 | 616 | ||
@@ -630,13 +632,13 @@ static int dso__load_sym(struct dso *self, int fd, const char *name, | |||
630 | * DWARF DW_compile_unit has this, but we don't always have access | 632 | * DWARF DW_compile_unit has this, but we don't always have access |
631 | * to it... | 633 | * to it... |
632 | */ | 634 | */ |
633 | name = elf_sym__name(&sym, symstrs); | 635 | elf_name = elf_sym__name(&sym, symstrs); |
634 | demangled = bfd_demangle(NULL, name, DMGL_PARAMS | DMGL_ANSI); | 636 | demangled = bfd_demangle(NULL, elf_name, DMGL_PARAMS | DMGL_ANSI); |
635 | if (demangled != NULL) | 637 | if (demangled != NULL) |
636 | name = demangled; | 638 | elf_name = demangled; |
637 | 639 | ||
638 | f = symbol__new(sym.st_value, sym.st_size, name, | 640 | f = symbol__new(sym.st_value, sym.st_size, elf_name, |
639 | self->sym_priv_size, obj_start, verbose); | 641 | self->sym_priv_size, obj_start, v); |
640 | free(demangled); | 642 | free(demangled); |
641 | if (!f) | 643 | if (!f) |
642 | goto out_elf_end; | 644 | goto out_elf_end; |
@@ -659,7 +661,7 @@ out_close: | |||
659 | 661 | ||
660 | #define BUILD_ID_SIZE 128 | 662 | #define BUILD_ID_SIZE 128 |
661 | 663 | ||
662 | static char *dso__read_build_id(struct dso *self, int verbose) | 664 | static char *dso__read_build_id(struct dso *self, int v) |
663 | { | 665 | { |
664 | int i; | 666 | int i; |
665 | GElf_Ehdr ehdr; | 667 | GElf_Ehdr ehdr; |
@@ -676,14 +678,14 @@ static char *dso__read_build_id(struct dso *self, int verbose) | |||
676 | 678 | ||
677 | elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); | 679 | elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); |
678 | if (elf == NULL) { | 680 | if (elf == NULL) { |
679 | if (verbose) | 681 | if (v) |
680 | fprintf(stderr, "%s: cannot read %s ELF file.\n", | 682 | fprintf(stderr, "%s: cannot read %s ELF file.\n", |
681 | __func__, self->name); | 683 | __func__, self->name); |
682 | goto out_close; | 684 | goto out_close; |
683 | } | 685 | } |
684 | 686 | ||
685 | if (gelf_getehdr(elf, &ehdr) == NULL) { | 687 | if (gelf_getehdr(elf, &ehdr) == NULL) { |
686 | if (verbose) | 688 | if (v) |
687 | fprintf(stderr, "%s: cannot get elf header.\n", __func__); | 689 | fprintf(stderr, "%s: cannot get elf header.\n", __func__); |
688 | goto out_elf_end; | 690 | goto out_elf_end; |
689 | } | 691 | } |
@@ -706,7 +708,7 @@ static char *dso__read_build_id(struct dso *self, int verbose) | |||
706 | ++raw; | 708 | ++raw; |
707 | bid += 2; | 709 | bid += 2; |
708 | } | 710 | } |
709 | if (verbose >= 2) | 711 | if (v >= 2) |
710 | printf("%s(%s): %s\n", __func__, self->name, build_id); | 712 | printf("%s(%s): %s\n", __func__, self->name, build_id); |
711 | out_elf_end: | 713 | out_elf_end: |
712 | elf_end(elf); | 714 | elf_end(elf); |
@@ -732,7 +734,7 @@ char dso__symtab_origin(const struct dso *self) | |||
732 | return origin[self->origin]; | 734 | return origin[self->origin]; |
733 | } | 735 | } |
734 | 736 | ||
735 | int dso__load(struct dso *self, symbol_filter_t filter, int verbose) | 737 | int dso__load(struct dso *self, symbol_filter_t filter, int v) |
736 | { | 738 | { |
737 | int size = PATH_MAX; | 739 | int size = PATH_MAX; |
738 | char *name = malloc(size), *build_id = NULL; | 740 | char *name = malloc(size), *build_id = NULL; |
@@ -745,7 +747,7 @@ int dso__load(struct dso *self, symbol_filter_t filter, int verbose) | |||
745 | self->adjust_symbols = 0; | 747 | self->adjust_symbols = 0; |
746 | 748 | ||
747 | if (strncmp(self->name, "/tmp/perf-", 10) == 0) { | 749 | if (strncmp(self->name, "/tmp/perf-", 10) == 0) { |
748 | ret = dso__load_perf_map(self, filter, verbose); | 750 | ret = dso__load_perf_map(self, filter, v); |
749 | self->origin = ret > 0 ? DSO__ORIG_JAVA_JIT : | 751 | self->origin = ret > 0 ? DSO__ORIG_JAVA_JIT : |
750 | DSO__ORIG_NOT_FOUND; | 752 | DSO__ORIG_NOT_FOUND; |
751 | return ret; | 753 | return ret; |
@@ -764,7 +766,7 @@ more: | |||
764 | snprintf(name, size, "/usr/lib/debug%s", self->name); | 766 | snprintf(name, size, "/usr/lib/debug%s", self->name); |
765 | break; | 767 | break; |
766 | case DSO__ORIG_BUILDID: | 768 | case DSO__ORIG_BUILDID: |
767 | build_id = dso__read_build_id(self, verbose); | 769 | build_id = dso__read_build_id(self, v); |
768 | if (build_id != NULL) { | 770 | if (build_id != NULL) { |
769 | snprintf(name, size, | 771 | snprintf(name, size, |
770 | "/usr/lib/debug/.build-id/%.2s/%s.debug", | 772 | "/usr/lib/debug/.build-id/%.2s/%s.debug", |
@@ -785,7 +787,7 @@ more: | |||
785 | fd = open(name, O_RDONLY); | 787 | fd = open(name, O_RDONLY); |
786 | } while (fd < 0); | 788 | } while (fd < 0); |
787 | 789 | ||
788 | ret = dso__load_sym(self, fd, name, filter, verbose, NULL); | 790 | ret = dso__load_sym(self, fd, name, filter, v, NULL); |
789 | close(fd); | 791 | close(fd); |
790 | 792 | ||
791 | /* | 793 | /* |
@@ -795,7 +797,7 @@ more: | |||
795 | goto more; | 797 | goto more; |
796 | 798 | ||
797 | if (ret > 0) { | 799 | if (ret > 0) { |
798 | int nr_plt = dso__synthesize_plt_symbols(self, verbose); | 800 | int nr_plt = dso__synthesize_plt_symbols(self, v); |
799 | if (nr_plt > 0) | 801 | if (nr_plt > 0) |
800 | ret += nr_plt; | 802 | ret += nr_plt; |
801 | } | 803 | } |
@@ -807,7 +809,7 @@ out: | |||
807 | } | 809 | } |
808 | 810 | ||
809 | static int dso__load_module(struct dso *self, struct mod_dso *mods, const char *name, | 811 | static int dso__load_module(struct dso *self, struct mod_dso *mods, const char *name, |
810 | symbol_filter_t filter, int verbose) | 812 | symbol_filter_t filter, int v) |
811 | { | 813 | { |
812 | struct module *mod = mod_dso__find_module(mods, name); | 814 | struct module *mod = mod_dso__find_module(mods, name); |
813 | int err = 0, fd; | 815 | int err = 0, fd; |
@@ -820,13 +822,13 @@ static int dso__load_module(struct dso *self, struct mod_dso *mods, const char * | |||
820 | if (fd < 0) | 822 | if (fd < 0) |
821 | return err; | 823 | return err; |
822 | 824 | ||
823 | err = dso__load_sym(self, fd, name, filter, verbose, mod); | 825 | err = dso__load_sym(self, fd, name, filter, v, mod); |
824 | close(fd); | 826 | close(fd); |
825 | 827 | ||
826 | return err; | 828 | return err; |
827 | } | 829 | } |
828 | 830 | ||
829 | int dso__load_modules(struct dso *self, symbol_filter_t filter, int verbose) | 831 | int dso__load_modules(struct dso *self, symbol_filter_t filter, int v) |
830 | { | 832 | { |
831 | struct mod_dso *mods = mod_dso__new_dso("modules"); | 833 | struct mod_dso *mods = mod_dso__new_dso("modules"); |
832 | struct module *pos; | 834 | struct module *pos; |
@@ -844,7 +846,7 @@ int dso__load_modules(struct dso *self, symbol_filter_t filter, int verbose) | |||
844 | next = rb_first(&mods->mods); | 846 | next = rb_first(&mods->mods); |
845 | while (next) { | 847 | while (next) { |
846 | pos = rb_entry(next, struct module, rb_node); | 848 | pos = rb_entry(next, struct module, rb_node); |
847 | err = dso__load_module(self, mods, pos->name, filter, verbose); | 849 | err = dso__load_module(self, mods, pos->name, filter, v); |
848 | 850 | ||
849 | if (err < 0) | 851 | if (err < 0) |
850 | break; | 852 | break; |
@@ -887,14 +889,14 @@ static inline void dso__fill_symbol_holes(struct dso *self) | |||
887 | } | 889 | } |
888 | 890 | ||
889 | static int dso__load_vmlinux(struct dso *self, const char *vmlinux, | 891 | static int dso__load_vmlinux(struct dso *self, const char *vmlinux, |
890 | symbol_filter_t filter, int verbose) | 892 | symbol_filter_t filter, int v) |
891 | { | 893 | { |
892 | int err, fd = open(vmlinux, O_RDONLY); | 894 | int err, fd = open(vmlinux, O_RDONLY); |
893 | 895 | ||
894 | if (fd < 0) | 896 | if (fd < 0) |
895 | return -1; | 897 | return -1; |
896 | 898 | ||
897 | err = dso__load_sym(self, fd, vmlinux, filter, verbose, NULL); | 899 | err = dso__load_sym(self, fd, vmlinux, filter, v, NULL); |
898 | 900 | ||
899 | if (err > 0) | 901 | if (err > 0) |
900 | dso__fill_symbol_holes(self); | 902 | dso__fill_symbol_holes(self); |
@@ -905,18 +907,18 @@ static int dso__load_vmlinux(struct dso *self, const char *vmlinux, | |||
905 | } | 907 | } |
906 | 908 | ||
907 | int dso__load_kernel(struct dso *self, const char *vmlinux, | 909 | int dso__load_kernel(struct dso *self, const char *vmlinux, |
908 | symbol_filter_t filter, int verbose, int modules) | 910 | symbol_filter_t filter, int v, int use_modules) |
909 | { | 911 | { |
910 | int err = -1; | 912 | int err = -1; |
911 | 913 | ||
912 | if (vmlinux) { | 914 | if (vmlinux) { |
913 | err = dso__load_vmlinux(self, vmlinux, filter, verbose); | 915 | err = dso__load_vmlinux(self, vmlinux, filter, v); |
914 | if (err > 0 && modules) | 916 | if (err > 0 && use_modules) |
915 | err = dso__load_modules(self, filter, verbose); | 917 | err = dso__load_modules(self, filter, v); |
916 | } | 918 | } |
917 | 919 | ||
918 | if (err <= 0) | 920 | if (err <= 0) |
919 | err = dso__load_kallsyms(self, filter, verbose); | 921 | err = dso__load_kallsyms(self, filter, v); |
920 | 922 | ||
921 | if (err > 0) | 923 | if (err > 0) |
922 | self->origin = DSO__ORIG_KERNEL; | 924 | self->origin = DSO__ORIG_KERNEL; |
@@ -924,6 +926,103 @@ int dso__load_kernel(struct dso *self, const char *vmlinux, | |||
924 | return err; | 926 | return err; |
925 | } | 927 | } |
926 | 928 | ||
929 | LIST_HEAD(dsos); | ||
930 | struct dso *kernel_dso; | ||
931 | struct dso *vdso; | ||
932 | struct dso *hypervisor_dso; | ||
933 | |||
934 | const char *vmlinux_name = "vmlinux"; | ||
935 | int modules; | ||
936 | |||
937 | static void dsos__add(struct dso *dso) | ||
938 | { | ||
939 | list_add_tail(&dso->node, &dsos); | ||
940 | } | ||
941 | |||
942 | static struct dso *dsos__find(const char *name) | ||
943 | { | ||
944 | struct dso *pos; | ||
945 | |||
946 | list_for_each_entry(pos, &dsos, node) | ||
947 | if (strcmp(pos->name, name) == 0) | ||
948 | return pos; | ||
949 | return NULL; | ||
950 | } | ||
951 | |||
952 | struct dso *dsos__findnew(const char *name) | ||
953 | { | ||
954 | struct dso *dso = dsos__find(name); | ||
955 | int nr; | ||
956 | |||
957 | if (dso) | ||
958 | return dso; | ||
959 | |||
960 | dso = dso__new(name, 0); | ||
961 | if (!dso) | ||
962 | goto out_delete_dso; | ||
963 | |||
964 | nr = dso__load(dso, NULL, verbose); | ||
965 | if (nr < 0) { | ||
966 | eprintf("Failed to open: %s\n", name); | ||
967 | goto out_delete_dso; | ||
968 | } | ||
969 | if (!nr) | ||
970 | eprintf("No symbols found in: %s, maybe install a debug package?\n", name); | ||
971 | |||
972 | dsos__add(dso); | ||
973 | |||
974 | return dso; | ||
975 | |||
976 | out_delete_dso: | ||
977 | dso__delete(dso); | ||
978 | return NULL; | ||
979 | } | ||
980 | |||
981 | void dsos__fprintf(FILE *fp) | ||
982 | { | ||
983 | struct dso *pos; | ||
984 | |||
985 | list_for_each_entry(pos, &dsos, node) | ||
986 | dso__fprintf(pos, fp); | ||
987 | } | ||
988 | |||
989 | static struct symbol *vdso__find_symbol(struct dso *dso, u64 ip) | ||
990 | { | ||
991 | return dso__find_symbol(dso, ip); | ||
992 | } | ||
993 | |||
994 | int load_kernel(void) | ||
995 | { | ||
996 | int err; | ||
997 | |||
998 | kernel_dso = dso__new("[kernel]", 0); | ||
999 | if (!kernel_dso) | ||
1000 | return -1; | ||
1001 | |||
1002 | err = dso__load_kernel(kernel_dso, vmlinux_name, NULL, verbose, modules); | ||
1003 | if (err <= 0) { | ||
1004 | dso__delete(kernel_dso); | ||
1005 | kernel_dso = NULL; | ||
1006 | } else | ||
1007 | dsos__add(kernel_dso); | ||
1008 | |||
1009 | vdso = dso__new("[vdso]", 0); | ||
1010 | if (!vdso) | ||
1011 | return -1; | ||
1012 | |||
1013 | vdso->find_symbol = vdso__find_symbol; | ||
1014 | |||
1015 | dsos__add(vdso); | ||
1016 | |||
1017 | hypervisor_dso = dso__new("[hypervisor]", 0); | ||
1018 | if (!hypervisor_dso) | ||
1019 | return -1; | ||
1020 | dsos__add(hypervisor_dso); | ||
1021 | |||
1022 | return err; | ||
1023 | } | ||
1024 | |||
1025 | |||
927 | void symbol__init(void) | 1026 | void symbol__init(void) |
928 | { | 1027 | { |
929 | elf_version(EV_CURRENT); | 1028 | elf_version(EV_CURRENT); |