diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-08-11 08:19:09 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-08-11 08:19:09 -0400 |
commit | 89034bc2c7b839702c00a704e79d112737f98be0 (patch) | |
tree | e65b1f3d4c751baa840efc81bc4734f089379eb3 /tools/perf/util/symbol.c | |
parent | fb82ad719831db58e9baa4c67015aae3fe27e7e3 (diff) | |
parent | 85dfd81dc57e8183a277ddd7a56aa65c96f3f487 (diff) |
Merge branch 'linus' into tracing/core
Conflicts:
kernel/trace/trace_events_filter.c
We use the tracing/core version.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf/util/symbol.c')
-rw-r--r-- | tools/perf/util/symbol.c | 281 |
1 files changed, 215 insertions, 66 deletions
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 4683b67b5ee4..f1dcede14307 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -7,8 +7,33 @@ | |||
7 | #include <gelf.h> | 7 | #include <gelf.h> |
8 | #include <elf.h> | 8 | #include <elf.h> |
9 | 9 | ||
10 | #ifndef NO_DEMANGLE | ||
11 | #include <bfd.h> | ||
12 | #else | ||
13 | static inline | ||
14 | char *bfd_demangle(void __used *v, const char __used *c, int __used i) | ||
15 | { | ||
16 | return NULL; | ||
17 | } | ||
18 | #endif | ||
19 | |||
10 | const char *sym_hist_filter; | 20 | const char *sym_hist_filter; |
11 | 21 | ||
22 | #ifndef DMGL_PARAMS | ||
23 | #define DMGL_PARAMS (1 << 0) /* Include function args */ | ||
24 | #define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */ | ||
25 | #endif | ||
26 | |||
27 | enum dso_origin { | ||
28 | DSO__ORIG_KERNEL = 0, | ||
29 | DSO__ORIG_JAVA_JIT, | ||
30 | DSO__ORIG_FEDORA, | ||
31 | DSO__ORIG_UBUNTU, | ||
32 | DSO__ORIG_BUILDID, | ||
33 | DSO__ORIG_DSO, | ||
34 | DSO__ORIG_NOT_FOUND, | ||
35 | }; | ||
36 | |||
12 | static struct symbol *symbol__new(u64 start, u64 len, | 37 | static struct symbol *symbol__new(u64 start, u64 len, |
13 | const char *name, unsigned int priv_size, | 38 | const char *name, unsigned int priv_size, |
14 | u64 obj_start, int verbose) | 39 | u64 obj_start, int verbose) |
@@ -65,6 +90,8 @@ struct dso *dso__new(const char *name, unsigned int sym_priv_size) | |||
65 | self->syms = RB_ROOT; | 90 | self->syms = RB_ROOT; |
66 | self->sym_priv_size = sym_priv_size; | 91 | self->sym_priv_size = sym_priv_size; |
67 | self->find_symbol = dso__find_symbol; | 92 | self->find_symbol = dso__find_symbol; |
93 | self->slen_calculated = 0; | ||
94 | self->origin = DSO__ORIG_NOT_FOUND; | ||
68 | } | 95 | } |
69 | 96 | ||
70 | return self; | 97 | return self; |
@@ -373,36 +400,61 @@ static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep, | |||
373 | idx < nr_entries; \ | 400 | idx < nr_entries; \ |
374 | ++idx, pos = gelf_getrela(reldata, idx, &pos_mem)) | 401 | ++idx, pos = gelf_getrela(reldata, idx, &pos_mem)) |
375 | 402 | ||
376 | static int dso__synthesize_plt_symbols(struct dso *self, Elf *elf, | 403 | /* |
377 | GElf_Ehdr *ehdr, Elf_Scn *scn_dynsym, | 404 | * We need to check if we have a .dynsym, so that we can handle the |
378 | GElf_Shdr *shdr_dynsym, | 405 | * .plt, synthesizing its symbols, that aren't on the symtabs (be it |
379 | size_t dynsym_idx, int verbose) | 406 | * .dynsym or .symtab). |
407 | * And always look at the original dso, not at debuginfo packages, that | ||
408 | * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS). | ||
409 | */ | ||
410 | static int dso__synthesize_plt_symbols(struct dso *self, int verbose) | ||
380 | { | 411 | { |
381 | uint32_t nr_rel_entries, idx; | 412 | uint32_t nr_rel_entries, idx; |
382 | GElf_Sym sym; | 413 | GElf_Sym sym; |
383 | u64 plt_offset; | 414 | u64 plt_offset; |
384 | GElf_Shdr shdr_plt; | 415 | GElf_Shdr shdr_plt; |
385 | struct symbol *f; | 416 | struct symbol *f; |
386 | GElf_Shdr shdr_rel_plt; | 417 | GElf_Shdr shdr_rel_plt, shdr_dynsym; |
387 | Elf_Data *reldata, *syms, *symstrs; | 418 | Elf_Data *reldata, *syms, *symstrs; |
388 | Elf_Scn *scn_plt_rel, *scn_symstrs; | 419 | Elf_Scn *scn_plt_rel, *scn_symstrs, *scn_dynsym; |
420 | size_t dynsym_idx; | ||
421 | GElf_Ehdr ehdr; | ||
389 | char sympltname[1024]; | 422 | char sympltname[1024]; |
390 | int nr = 0, symidx; | 423 | Elf *elf; |
424 | int nr = 0, symidx, fd, err = 0; | ||
425 | |||
426 | fd = open(self->name, O_RDONLY); | ||
427 | if (fd < 0) | ||
428 | goto out; | ||
429 | |||
430 | elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); | ||
431 | if (elf == NULL) | ||
432 | goto out_close; | ||
433 | |||
434 | if (gelf_getehdr(elf, &ehdr) == NULL) | ||
435 | goto out_elf_end; | ||
391 | 436 | ||
392 | scn_plt_rel = elf_section_by_name(elf, ehdr, &shdr_rel_plt, | 437 | scn_dynsym = elf_section_by_name(elf, &ehdr, &shdr_dynsym, |
438 | ".dynsym", &dynsym_idx); | ||
439 | if (scn_dynsym == NULL) | ||
440 | goto out_elf_end; | ||
441 | |||
442 | scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt, | ||
393 | ".rela.plt", NULL); | 443 | ".rela.plt", NULL); |
394 | if (scn_plt_rel == NULL) { | 444 | if (scn_plt_rel == NULL) { |
395 | scn_plt_rel = elf_section_by_name(elf, ehdr, &shdr_rel_plt, | 445 | scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt, |
396 | ".rel.plt", NULL); | 446 | ".rel.plt", NULL); |
397 | if (scn_plt_rel == NULL) | 447 | if (scn_plt_rel == NULL) |
398 | return 0; | 448 | goto out_elf_end; |
399 | } | 449 | } |
400 | 450 | ||
451 | err = -1; | ||
452 | |||
401 | if (shdr_rel_plt.sh_link != dynsym_idx) | 453 | if (shdr_rel_plt.sh_link != dynsym_idx) |
402 | return 0; | 454 | goto out_elf_end; |
403 | 455 | ||
404 | if (elf_section_by_name(elf, ehdr, &shdr_plt, ".plt", NULL) == NULL) | 456 | if (elf_section_by_name(elf, &ehdr, &shdr_plt, ".plt", NULL) == NULL) |
405 | return 0; | 457 | goto out_elf_end; |
406 | 458 | ||
407 | /* | 459 | /* |
408 | * Fetch the relocation section to find the indexes to the GOT | 460 | * Fetch the relocation section to find the indexes to the GOT |
@@ -410,19 +462,19 @@ static int dso__synthesize_plt_symbols(struct dso *self, Elf *elf, | |||
410 | */ | 462 | */ |
411 | reldata = elf_getdata(scn_plt_rel, NULL); | 463 | reldata = elf_getdata(scn_plt_rel, NULL); |
412 | if (reldata == NULL) | 464 | if (reldata == NULL) |
413 | return -1; | 465 | goto out_elf_end; |
414 | 466 | ||
415 | syms = elf_getdata(scn_dynsym, NULL); | 467 | syms = elf_getdata(scn_dynsym, NULL); |
416 | if (syms == NULL) | 468 | if (syms == NULL) |
417 | return -1; | 469 | goto out_elf_end; |
418 | 470 | ||
419 | scn_symstrs = elf_getscn(elf, shdr_dynsym->sh_link); | 471 | scn_symstrs = elf_getscn(elf, shdr_dynsym.sh_link); |
420 | if (scn_symstrs == NULL) | 472 | if (scn_symstrs == NULL) |
421 | return -1; | 473 | goto out_elf_end; |
422 | 474 | ||
423 | symstrs = elf_getdata(scn_symstrs, NULL); | 475 | symstrs = elf_getdata(scn_symstrs, NULL); |
424 | if (symstrs == NULL) | 476 | if (symstrs == NULL) |
425 | return -1; | 477 | goto out_elf_end; |
426 | 478 | ||
427 | nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize; | 479 | nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize; |
428 | plt_offset = shdr_plt.sh_offset; | 480 | plt_offset = shdr_plt.sh_offset; |
@@ -441,7 +493,7 @@ static int dso__synthesize_plt_symbols(struct dso *self, Elf *elf, | |||
441 | f = symbol__new(plt_offset, shdr_plt.sh_entsize, | 493 | f = symbol__new(plt_offset, shdr_plt.sh_entsize, |
442 | sympltname, self->sym_priv_size, 0, verbose); | 494 | sympltname, self->sym_priv_size, 0, verbose); |
443 | if (!f) | 495 | if (!f) |
444 | return -1; | 496 | goto out_elf_end; |
445 | 497 | ||
446 | dso__insert_symbol(self, f); | 498 | dso__insert_symbol(self, f); |
447 | ++nr; | 499 | ++nr; |
@@ -459,19 +511,25 @@ static int dso__synthesize_plt_symbols(struct dso *self, Elf *elf, | |||
459 | f = symbol__new(plt_offset, shdr_plt.sh_entsize, | 511 | f = symbol__new(plt_offset, shdr_plt.sh_entsize, |
460 | sympltname, self->sym_priv_size, 0, verbose); | 512 | sympltname, self->sym_priv_size, 0, verbose); |
461 | if (!f) | 513 | if (!f) |
462 | return -1; | 514 | goto out_elf_end; |
463 | 515 | ||
464 | dso__insert_symbol(self, f); | 516 | dso__insert_symbol(self, f); |
465 | ++nr; | 517 | ++nr; |
466 | } | 518 | } |
467 | } else { | ||
468 | /* | ||
469 | * TODO: There are still one more shdr_rel_plt.sh_type | ||
470 | * I have to investigate, but probably should be ignored. | ||
471 | */ | ||
472 | } | 519 | } |
473 | 520 | ||
474 | return nr; | 521 | err = 0; |
522 | out_elf_end: | ||
523 | elf_end(elf); | ||
524 | out_close: | ||
525 | close(fd); | ||
526 | |||
527 | if (err == 0) | ||
528 | return nr; | ||
529 | out: | ||
530 | fprintf(stderr, "%s: problems reading %s PLT info.\n", | ||
531 | __func__, self->name); | ||
532 | return 0; | ||
475 | } | 533 | } |
476 | 534 | ||
477 | static int dso__load_sym(struct dso *self, int fd, const char *name, | 535 | static int dso__load_sym(struct dso *self, int fd, const char *name, |
@@ -485,10 +543,9 @@ static int dso__load_sym(struct dso *self, int fd, const char *name, | |||
485 | GElf_Shdr shdr; | 543 | GElf_Shdr shdr; |
486 | Elf_Data *syms; | 544 | Elf_Data *syms; |
487 | GElf_Sym sym; | 545 | GElf_Sym sym; |
488 | Elf_Scn *sec, *sec_dynsym, *sec_strndx; | 546 | Elf_Scn *sec, *sec_strndx; |
489 | Elf *elf; | 547 | Elf *elf; |
490 | size_t dynsym_idx; | 548 | int nr = 0, kernel = !strcmp("[kernel]", self->name); |
491 | int nr = 0; | ||
492 | 549 | ||
493 | elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); | 550 | elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); |
494 | if (elf == NULL) { | 551 | if (elf == NULL) { |
@@ -504,32 +561,11 @@ static int dso__load_sym(struct dso *self, int fd, const char *name, | |||
504 | goto out_elf_end; | 561 | goto out_elf_end; |
505 | } | 562 | } |
506 | 563 | ||
507 | /* | ||
508 | * We need to check if we have a .dynsym, so that we can handle the | ||
509 | * .plt, synthesizing its symbols, that aren't on the symtabs (be it | ||
510 | * .dynsym or .symtab) | ||
511 | */ | ||
512 | sec_dynsym = elf_section_by_name(elf, &ehdr, &shdr, | ||
513 | ".dynsym", &dynsym_idx); | ||
514 | if (sec_dynsym != NULL) { | ||
515 | nr = dso__synthesize_plt_symbols(self, elf, &ehdr, | ||
516 | sec_dynsym, &shdr, | ||
517 | dynsym_idx, verbose); | ||
518 | if (nr < 0) | ||
519 | goto out_elf_end; | ||
520 | } | ||
521 | |||
522 | /* | ||
523 | * But if we have a full .symtab (that is a superset of .dynsym) we | ||
524 | * should add the symbols not in the .dynsyn | ||
525 | */ | ||
526 | sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL); | 564 | sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL); |
527 | if (sec == NULL) { | 565 | if (sec == NULL) { |
528 | if (sec_dynsym == NULL) | 566 | sec = elf_section_by_name(elf, &ehdr, &shdr, ".dynsym", NULL); |
567 | if (sec == NULL) | ||
529 | goto out_elf_end; | 568 | goto out_elf_end; |
530 | |||
531 | sec = sec_dynsym; | ||
532 | gelf_getshdr(sec, &shdr); | ||
533 | } | 569 | } |
534 | 570 | ||
535 | syms = elf_getdata(sec, NULL); | 571 | syms = elf_getdata(sec, NULL); |
@@ -549,18 +585,23 @@ static int dso__load_sym(struct dso *self, int fd, const char *name, | |||
549 | goto out_elf_end; | 585 | goto out_elf_end; |
550 | 586 | ||
551 | secstrs = elf_getdata(sec_strndx, NULL); | 587 | secstrs = elf_getdata(sec_strndx, NULL); |
552 | if (symstrs == NULL) | 588 | if (secstrs == NULL) |
553 | goto out_elf_end; | 589 | goto out_elf_end; |
554 | 590 | ||
555 | nr_syms = shdr.sh_size / shdr.sh_entsize; | 591 | nr_syms = shdr.sh_size / shdr.sh_entsize; |
556 | 592 | ||
557 | memset(&sym, 0, sizeof(sym)); | 593 | memset(&sym, 0, sizeof(sym)); |
558 | self->adjust_symbols = (ehdr.e_type == ET_EXEC || | 594 | if (!kernel) { |
595 | self->adjust_symbols = (ehdr.e_type == ET_EXEC || | ||
559 | elf_section_by_name(elf, &ehdr, &shdr, | 596 | elf_section_by_name(elf, &ehdr, &shdr, |
560 | ".gnu.prelink_undo", | 597 | ".gnu.prelink_undo", |
561 | NULL) != NULL); | 598 | NULL) != NULL); |
599 | } else self->adjust_symbols = 0; | ||
600 | |||
562 | elf_symtab__for_each_symbol(syms, nr_syms, index, sym) { | 601 | elf_symtab__for_each_symbol(syms, nr_syms, index, sym) { |
563 | struct symbol *f; | 602 | struct symbol *f; |
603 | const char *name; | ||
604 | char *demangled; | ||
564 | u64 obj_start; | 605 | u64 obj_start; |
565 | struct section *section = NULL; | 606 | struct section *section = NULL; |
566 | int is_label = elf_sym__is_label(&sym); | 607 | int is_label = elf_sym__is_label(&sym); |
@@ -599,10 +640,19 @@ static int dso__load_sym(struct dso *self, int fd, const char *name, | |||
599 | goto out_elf_end; | 640 | goto out_elf_end; |
600 | } | 641 | } |
601 | } | 642 | } |
643 | /* | ||
644 | * We need to figure out if the object was created from C++ sources | ||
645 | * DWARF DW_compile_unit has this, but we don't always have access | ||
646 | * to it... | ||
647 | */ | ||
648 | name = elf_sym__name(&sym, symstrs); | ||
649 | demangled = bfd_demangle(NULL, name, DMGL_PARAMS | DMGL_ANSI); | ||
650 | if (demangled != NULL) | ||
651 | name = demangled; | ||
602 | 652 | ||
603 | f = symbol__new(sym.st_value, sym.st_size, | 653 | f = symbol__new(sym.st_value, sym.st_size, name, |
604 | elf_sym__name(&sym, symstrs), | ||
605 | self->sym_priv_size, obj_start, verbose); | 654 | self->sym_priv_size, obj_start, verbose); |
655 | free(demangled); | ||
606 | if (!f) | 656 | if (!f) |
607 | goto out_elf_end; | 657 | goto out_elf_end; |
608 | 658 | ||
@@ -622,11 +672,85 @@ out_close: | |||
622 | return err; | 672 | return err; |
623 | } | 673 | } |
624 | 674 | ||
675 | #define BUILD_ID_SIZE 128 | ||
676 | |||
677 | static char *dso__read_build_id(struct dso *self, int verbose) | ||
678 | { | ||
679 | int i; | ||
680 | GElf_Ehdr ehdr; | ||
681 | GElf_Shdr shdr; | ||
682 | Elf_Data *build_id_data; | ||
683 | Elf_Scn *sec; | ||
684 | char *build_id = NULL, *bid; | ||
685 | unsigned char *raw; | ||
686 | Elf *elf; | ||
687 | int fd = open(self->name, O_RDONLY); | ||
688 | |||
689 | if (fd < 0) | ||
690 | goto out; | ||
691 | |||
692 | elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); | ||
693 | if (elf == NULL) { | ||
694 | if (verbose) | ||
695 | fprintf(stderr, "%s: cannot read %s ELF file.\n", | ||
696 | __func__, self->name); | ||
697 | goto out_close; | ||
698 | } | ||
699 | |||
700 | if (gelf_getehdr(elf, &ehdr) == NULL) { | ||
701 | if (verbose) | ||
702 | fprintf(stderr, "%s: cannot get elf header.\n", __func__); | ||
703 | goto out_elf_end; | ||
704 | } | ||
705 | |||
706 | sec = elf_section_by_name(elf, &ehdr, &shdr, ".note.gnu.build-id", NULL); | ||
707 | if (sec == NULL) | ||
708 | goto out_elf_end; | ||
709 | |||
710 | build_id_data = elf_getdata(sec, NULL); | ||
711 | if (build_id_data == NULL) | ||
712 | goto out_elf_end; | ||
713 | build_id = malloc(BUILD_ID_SIZE); | ||
714 | if (build_id == NULL) | ||
715 | goto out_elf_end; | ||
716 | raw = build_id_data->d_buf + 16; | ||
717 | bid = build_id; | ||
718 | |||
719 | for (i = 0; i < 20; ++i) { | ||
720 | sprintf(bid, "%02x", *raw); | ||
721 | ++raw; | ||
722 | bid += 2; | ||
723 | } | ||
724 | if (verbose >= 2) | ||
725 | printf("%s(%s): %s\n", __func__, self->name, build_id); | ||
726 | out_elf_end: | ||
727 | elf_end(elf); | ||
728 | out_close: | ||
729 | close(fd); | ||
730 | out: | ||
731 | return build_id; | ||
732 | } | ||
733 | |||
734 | char dso__symtab_origin(const struct dso *self) | ||
735 | { | ||
736 | static const char origin[] = { | ||
737 | [DSO__ORIG_KERNEL] = 'k', | ||
738 | [DSO__ORIG_JAVA_JIT] = 'j', | ||
739 | [DSO__ORIG_FEDORA] = 'f', | ||
740 | [DSO__ORIG_UBUNTU] = 'u', | ||
741 | [DSO__ORIG_BUILDID] = 'b', | ||
742 | [DSO__ORIG_DSO] = 'd', | ||
743 | }; | ||
744 | |||
745 | if (self == NULL || self->origin == DSO__ORIG_NOT_FOUND) | ||
746 | return '!'; | ||
747 | return origin[self->origin]; | ||
748 | } | ||
749 | |||
625 | int dso__load(struct dso *self, symbol_filter_t filter, int verbose) | 750 | int dso__load(struct dso *self, symbol_filter_t filter, int verbose) |
626 | { | 751 | { |
627 | int size = strlen(self->name) + sizeof("/usr/lib/debug%s.debug"); | 752 | int size = PATH_MAX; |
628 | char *name = malloc(size); | 753 | char *name = malloc(size), *build_id = NULL; |
629 | int variant = 0; | ||
630 | int ret = -1; | 754 | int ret = -1; |
631 | int fd; | 755 | int fd; |
632 | 756 | ||
@@ -635,26 +759,43 @@ int dso__load(struct dso *self, symbol_filter_t filter, int verbose) | |||
635 | 759 | ||
636 | self->adjust_symbols = 0; | 760 | self->adjust_symbols = 0; |
637 | 761 | ||
638 | if (strncmp(self->name, "/tmp/perf-", 10) == 0) | 762 | if (strncmp(self->name, "/tmp/perf-", 10) == 0) { |
639 | return dso__load_perf_map(self, filter, verbose); | 763 | ret = dso__load_perf_map(self, filter, verbose); |
764 | self->origin = ret > 0 ? DSO__ORIG_JAVA_JIT : | ||
765 | DSO__ORIG_NOT_FOUND; | ||
766 | return ret; | ||
767 | } | ||
768 | |||
769 | self->origin = DSO__ORIG_FEDORA - 1; | ||
640 | 770 | ||
641 | more: | 771 | more: |
642 | do { | 772 | do { |
643 | switch (variant) { | 773 | self->origin++; |
644 | case 0: /* Fedora */ | 774 | switch (self->origin) { |
775 | case DSO__ORIG_FEDORA: | ||
645 | snprintf(name, size, "/usr/lib/debug%s.debug", self->name); | 776 | snprintf(name, size, "/usr/lib/debug%s.debug", self->name); |
646 | break; | 777 | break; |
647 | case 1: /* Ubuntu */ | 778 | case DSO__ORIG_UBUNTU: |
648 | snprintf(name, size, "/usr/lib/debug%s", self->name); | 779 | snprintf(name, size, "/usr/lib/debug%s", self->name); |
649 | break; | 780 | break; |
650 | case 2: /* Sane people */ | 781 | case DSO__ORIG_BUILDID: |
782 | build_id = dso__read_build_id(self, verbose); | ||
783 | if (build_id != NULL) { | ||
784 | snprintf(name, size, | ||
785 | "/usr/lib/debug/.build-id/%.2s/%s.debug", | ||
786 | build_id, build_id + 2); | ||
787 | free(build_id); | ||
788 | break; | ||
789 | } | ||
790 | self->origin++; | ||
791 | /* Fall thru */ | ||
792 | case DSO__ORIG_DSO: | ||
651 | snprintf(name, size, "%s", self->name); | 793 | snprintf(name, size, "%s", self->name); |
652 | break; | 794 | break; |
653 | 795 | ||
654 | default: | 796 | default: |
655 | goto out; | 797 | goto out; |
656 | } | 798 | } |
657 | variant++; | ||
658 | 799 | ||
659 | fd = open(name, O_RDONLY); | 800 | fd = open(name, O_RDONLY); |
660 | } while (fd < 0); | 801 | } while (fd < 0); |
@@ -668,6 +809,11 @@ more: | |||
668 | if (!ret) | 809 | if (!ret) |
669 | goto more; | 810 | goto more; |
670 | 811 | ||
812 | if (ret > 0) { | ||
813 | int nr_plt = dso__synthesize_plt_symbols(self, verbose); | ||
814 | if (nr_plt > 0) | ||
815 | ret += nr_plt; | ||
816 | } | ||
671 | out: | 817 | out: |
672 | free(name); | 818 | free(name); |
673 | return ret; | 819 | return ret; |
@@ -785,6 +931,9 @@ int dso__load_kernel(struct dso *self, const char *vmlinux, | |||
785 | if (err <= 0) | 931 | if (err <= 0) |
786 | err = dso__load_kallsyms(self, filter, verbose); | 932 | err = dso__load_kallsyms(self, filter, verbose); |
787 | 933 | ||
934 | if (err > 0) | ||
935 | self->origin = DSO__ORIG_KERNEL; | ||
936 | |||
788 | return err; | 937 | return err; |
789 | } | 938 | } |
790 | 939 | ||