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); |
