diff options
author | Ingo Molnar <mingo@kernel.org> | 2017-01-25 09:52:46 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2017-01-25 09:52:46 -0500 |
commit | 47cd95a6326888a46e7ce8389cd394a3e1c647e7 (patch) | |
tree | dfbb526bcca1a4f627294f19983e1f0b43af9204 /tools/perf | |
parent | 9f6f941e25bad8fcffc24d10762962d62edba767 (diff) | |
parent | 883af14e67e8b8702b5560aa64c888c0cd0bd66c (diff) |
Merge branch 'linus' into perf/core, to pick up fixes
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools/perf')
-rw-r--r-- | tools/perf/builtin-kmem.c | 1 | ||||
-rw-r--r-- | tools/perf/util/probe-event.c | 95 | ||||
-rw-r--r-- | tools/perf/util/probe-finder.c | 15 | ||||
-rw-r--r-- | tools/perf/util/probe-finder.h | 3 |
4 files changed, 72 insertions, 42 deletions
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index 35a02f8e5a4a..915869e00d86 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c | |||
@@ -655,7 +655,6 @@ static const struct { | |||
655 | { "__GFP_RECLAIM", "R" }, | 655 | { "__GFP_RECLAIM", "R" }, |
656 | { "__GFP_DIRECT_RECLAIM", "DR" }, | 656 | { "__GFP_DIRECT_RECLAIM", "DR" }, |
657 | { "__GFP_KSWAPD_RECLAIM", "KR" }, | 657 | { "__GFP_KSWAPD_RECLAIM", "KR" }, |
658 | { "__GFP_OTHER_NODE", "ON" }, | ||
659 | }; | 658 | }; |
660 | 659 | ||
661 | static size_t max_gfp_len; | 660 | static size_t max_gfp_len; |
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 4a57c8a60bd9..6a6f44dd594b 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c | |||
@@ -610,6 +610,33 @@ error: | |||
610 | return ret ? : -ENOENT; | 610 | return ret ? : -ENOENT; |
611 | } | 611 | } |
612 | 612 | ||
613 | /* Adjust symbol name and address */ | ||
614 | static int post_process_probe_trace_point(struct probe_trace_point *tp, | ||
615 | struct map *map, unsigned long offs) | ||
616 | { | ||
617 | struct symbol *sym; | ||
618 | u64 addr = tp->address + tp->offset - offs; | ||
619 | |||
620 | sym = map__find_symbol(map, addr); | ||
621 | if (!sym) | ||
622 | return -ENOENT; | ||
623 | |||
624 | if (strcmp(sym->name, tp->symbol)) { | ||
625 | /* If we have no realname, use symbol for it */ | ||
626 | if (!tp->realname) | ||
627 | tp->realname = tp->symbol; | ||
628 | else | ||
629 | free(tp->symbol); | ||
630 | tp->symbol = strdup(sym->name); | ||
631 | if (!tp->symbol) | ||
632 | return -ENOMEM; | ||
633 | } | ||
634 | tp->offset = addr - sym->start; | ||
635 | tp->address -= offs; | ||
636 | |||
637 | return 0; | ||
638 | } | ||
639 | |||
613 | /* | 640 | /* |
614 | * Rename DWARF symbols to ELF symbols -- gcc sometimes optimizes functions | 641 | * Rename DWARF symbols to ELF symbols -- gcc sometimes optimizes functions |
615 | * and generate new symbols with suffixes such as .constprop.N or .isra.N | 642 | * and generate new symbols with suffixes such as .constprop.N or .isra.N |
@@ -622,11 +649,9 @@ static int | |||
622 | post_process_offline_probe_trace_events(struct probe_trace_event *tevs, | 649 | post_process_offline_probe_trace_events(struct probe_trace_event *tevs, |
623 | int ntevs, const char *pathname) | 650 | int ntevs, const char *pathname) |
624 | { | 651 | { |
625 | struct symbol *sym; | ||
626 | struct map *map; | 652 | struct map *map; |
627 | unsigned long stext = 0; | 653 | unsigned long stext = 0; |
628 | u64 addr; | 654 | int i, ret = 0; |
629 | int i; | ||
630 | 655 | ||
631 | /* Prepare a map for offline binary */ | 656 | /* Prepare a map for offline binary */ |
632 | map = dso__new_map(pathname); | 657 | map = dso__new_map(pathname); |
@@ -636,23 +661,14 @@ post_process_offline_probe_trace_events(struct probe_trace_event *tevs, | |||
636 | } | 661 | } |
637 | 662 | ||
638 | for (i = 0; i < ntevs; i++) { | 663 | for (i = 0; i < ntevs; i++) { |
639 | addr = tevs[i].point.address + tevs[i].point.offset - stext; | 664 | ret = post_process_probe_trace_point(&tevs[i].point, |
640 | sym = map__find_symbol(map, addr); | 665 | map, stext); |
641 | if (!sym) | 666 | if (ret < 0) |
642 | continue; | 667 | break; |
643 | if (!strcmp(sym->name, tevs[i].point.symbol)) | ||
644 | continue; | ||
645 | /* If we have no realname, use symbol for it */ | ||
646 | if (!tevs[i].point.realname) | ||
647 | tevs[i].point.realname = tevs[i].point.symbol; | ||
648 | else | ||
649 | free(tevs[i].point.symbol); | ||
650 | tevs[i].point.symbol = strdup(sym->name); | ||
651 | tevs[i].point.offset = addr - sym->start; | ||
652 | } | 668 | } |
653 | map__put(map); | 669 | map__put(map); |
654 | 670 | ||
655 | return 0; | 671 | return ret; |
656 | } | 672 | } |
657 | 673 | ||
658 | static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs, | 674 | static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs, |
@@ -682,18 +698,31 @@ static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs, | |||
682 | return ret; | 698 | return ret; |
683 | } | 699 | } |
684 | 700 | ||
685 | static int add_module_to_probe_trace_events(struct probe_trace_event *tevs, | 701 | static int |
686 | int ntevs, const char *module) | 702 | post_process_module_probe_trace_events(struct probe_trace_event *tevs, |
703 | int ntevs, const char *module, | ||
704 | struct debuginfo *dinfo) | ||
687 | { | 705 | { |
706 | Dwarf_Addr text_offs = 0; | ||
688 | int i, ret = 0; | 707 | int i, ret = 0; |
689 | char *mod_name = NULL; | 708 | char *mod_name = NULL; |
709 | struct map *map; | ||
690 | 710 | ||
691 | if (!module) | 711 | if (!module) |
692 | return 0; | 712 | return 0; |
693 | 713 | ||
694 | mod_name = find_module_name(module); | 714 | map = get_target_map(module, false); |
715 | if (!map || debuginfo__get_text_offset(dinfo, &text_offs, true) < 0) { | ||
716 | pr_warning("Failed to get ELF symbols for %s\n", module); | ||
717 | return -EINVAL; | ||
718 | } | ||
695 | 719 | ||
720 | mod_name = find_module_name(module); | ||
696 | for (i = 0; i < ntevs; i++) { | 721 | for (i = 0; i < ntevs; i++) { |
722 | ret = post_process_probe_trace_point(&tevs[i].point, | ||
723 | map, (unsigned long)text_offs); | ||
724 | if (ret < 0) | ||
725 | break; | ||
697 | tevs[i].point.module = | 726 | tevs[i].point.module = |
698 | strdup(mod_name ? mod_name : module); | 727 | strdup(mod_name ? mod_name : module); |
699 | if (!tevs[i].point.module) { | 728 | if (!tevs[i].point.module) { |
@@ -703,6 +732,8 @@ static int add_module_to_probe_trace_events(struct probe_trace_event *tevs, | |||
703 | } | 732 | } |
704 | 733 | ||
705 | free(mod_name); | 734 | free(mod_name); |
735 | map__put(map); | ||
736 | |||
706 | return ret; | 737 | return ret; |
707 | } | 738 | } |
708 | 739 | ||
@@ -760,7 +791,7 @@ arch__post_process_probe_trace_events(struct perf_probe_event *pev __maybe_unuse | |||
760 | static int post_process_probe_trace_events(struct perf_probe_event *pev, | 791 | static int post_process_probe_trace_events(struct perf_probe_event *pev, |
761 | struct probe_trace_event *tevs, | 792 | struct probe_trace_event *tevs, |
762 | int ntevs, const char *module, | 793 | int ntevs, const char *module, |
763 | bool uprobe) | 794 | bool uprobe, struct debuginfo *dinfo) |
764 | { | 795 | { |
765 | int ret; | 796 | int ret; |
766 | 797 | ||
@@ -768,7 +799,8 @@ static int post_process_probe_trace_events(struct perf_probe_event *pev, | |||
768 | ret = add_exec_to_probe_trace_events(tevs, ntevs, module); | 799 | ret = add_exec_to_probe_trace_events(tevs, ntevs, module); |
769 | else if (module) | 800 | else if (module) |
770 | /* Currently ref_reloc_sym based probe is not for drivers */ | 801 | /* Currently ref_reloc_sym based probe is not for drivers */ |
771 | ret = add_module_to_probe_trace_events(tevs, ntevs, module); | 802 | ret = post_process_module_probe_trace_events(tevs, ntevs, |
803 | module, dinfo); | ||
772 | else | 804 | else |
773 | ret = post_process_kernel_probe_trace_events(tevs, ntevs); | 805 | ret = post_process_kernel_probe_trace_events(tevs, ntevs); |
774 | 806 | ||
@@ -812,30 +844,27 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev, | |||
812 | } | 844 | } |
813 | } | 845 | } |
814 | 846 | ||
815 | debuginfo__delete(dinfo); | ||
816 | |||
817 | if (ntevs > 0) { /* Succeeded to find trace events */ | 847 | if (ntevs > 0) { /* Succeeded to find trace events */ |
818 | pr_debug("Found %d probe_trace_events.\n", ntevs); | 848 | pr_debug("Found %d probe_trace_events.\n", ntevs); |
819 | ret = post_process_probe_trace_events(pev, *tevs, ntevs, | 849 | ret = post_process_probe_trace_events(pev, *tevs, ntevs, |
820 | pev->target, pev->uprobes); | 850 | pev->target, pev->uprobes, dinfo); |
821 | if (ret < 0 || ret == ntevs) { | 851 | if (ret < 0 || ret == ntevs) { |
852 | pr_debug("Post processing failed or all events are skipped. (%d)\n", ret); | ||
822 | clear_probe_trace_events(*tevs, ntevs); | 853 | clear_probe_trace_events(*tevs, ntevs); |
823 | zfree(tevs); | 854 | zfree(tevs); |
855 | ntevs = 0; | ||
824 | } | 856 | } |
825 | if (ret != ntevs) | ||
826 | return ret < 0 ? ret : ntevs; | ||
827 | ntevs = 0; | ||
828 | /* Fall through */ | ||
829 | } | 857 | } |
830 | 858 | ||
859 | debuginfo__delete(dinfo); | ||
860 | |||
831 | if (ntevs == 0) { /* No error but failed to find probe point. */ | 861 | if (ntevs == 0) { /* No error but failed to find probe point. */ |
832 | pr_warning("Probe point '%s' not found.\n", | 862 | pr_warning("Probe point '%s' not found.\n", |
833 | synthesize_perf_probe_point(&pev->point)); | 863 | synthesize_perf_probe_point(&pev->point)); |
834 | return -ENOENT; | 864 | return -ENOENT; |
835 | } | 865 | } else if (ntevs < 0) { |
836 | /* Error path : ntevs < 0 */ | 866 | /* Error path : ntevs < 0 */ |
837 | pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs); | 867 | pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs); |
838 | if (ntevs < 0) { | ||
839 | if (ntevs == -EBADF) | 868 | if (ntevs == -EBADF) |
840 | pr_warning("Warning: No dwarf info found in the vmlinux - " | 869 | pr_warning("Warning: No dwarf info found in the vmlinux - " |
841 | "please rebuild kernel with CONFIG_DEBUG_INFO=y.\n"); | 870 | "please rebuild kernel with CONFIG_DEBUG_INFO=y.\n"); |
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index df4debe564da..0d9d6e0803b8 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c | |||
@@ -1501,7 +1501,8 @@ int debuginfo__find_available_vars_at(struct debuginfo *dbg, | |||
1501 | } | 1501 | } |
1502 | 1502 | ||
1503 | /* For the kernel module, we need a special code to get a DIE */ | 1503 | /* For the kernel module, we need a special code to get a DIE */ |
1504 | static int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs) | 1504 | int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs, |
1505 | bool adjust_offset) | ||
1505 | { | 1506 | { |
1506 | int n, i; | 1507 | int n, i; |
1507 | Elf32_Word shndx; | 1508 | Elf32_Word shndx; |
@@ -1530,6 +1531,8 @@ static int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs) | |||
1530 | if (!shdr) | 1531 | if (!shdr) |
1531 | return -ENOENT; | 1532 | return -ENOENT; |
1532 | *offs = shdr->sh_addr; | 1533 | *offs = shdr->sh_addr; |
1534 | if (adjust_offset) | ||
1535 | *offs -= shdr->sh_offset; | ||
1533 | } | 1536 | } |
1534 | } | 1537 | } |
1535 | return 0; | 1538 | return 0; |
@@ -1543,16 +1546,12 @@ int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr, | |||
1543 | Dwarf_Addr _addr = 0, baseaddr = 0; | 1546 | Dwarf_Addr _addr = 0, baseaddr = 0; |
1544 | const char *fname = NULL, *func = NULL, *basefunc = NULL, *tmp; | 1547 | const char *fname = NULL, *func = NULL, *basefunc = NULL, *tmp; |
1545 | int baseline = 0, lineno = 0, ret = 0; | 1548 | int baseline = 0, lineno = 0, ret = 0; |
1546 | bool reloc = false; | ||
1547 | 1549 | ||
1548 | retry: | 1550 | /* We always need to relocate the address for aranges */ |
1551 | if (debuginfo__get_text_offset(dbg, &baseaddr, false) == 0) | ||
1552 | addr += baseaddr; | ||
1549 | /* Find cu die */ | 1553 | /* Find cu die */ |
1550 | if (!dwarf_addrdie(dbg->dbg, (Dwarf_Addr)addr, &cudie)) { | 1554 | if (!dwarf_addrdie(dbg->dbg, (Dwarf_Addr)addr, &cudie)) { |
1551 | if (!reloc && debuginfo__get_text_offset(dbg, &baseaddr) == 0) { | ||
1552 | addr += baseaddr; | ||
1553 | reloc = true; | ||
1554 | goto retry; | ||
1555 | } | ||
1556 | pr_warning("Failed to find debug information for address %lx\n", | 1555 | pr_warning("Failed to find debug information for address %lx\n", |
1557 | addr); | 1556 | addr); |
1558 | ret = -EINVAL; | 1557 | ret = -EINVAL; |
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h index f1d8558f498e..2956c5198652 100644 --- a/tools/perf/util/probe-finder.h +++ b/tools/perf/util/probe-finder.h | |||
@@ -46,6 +46,9 @@ int debuginfo__find_trace_events(struct debuginfo *dbg, | |||
46 | int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr, | 46 | int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr, |
47 | struct perf_probe_point *ppt); | 47 | struct perf_probe_point *ppt); |
48 | 48 | ||
49 | int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs, | ||
50 | bool adjust_offset); | ||
51 | |||
49 | /* Find a line range */ | 52 | /* Find a line range */ |
50 | int debuginfo__find_line_range(struct debuginfo *dbg, struct line_range *lr); | 53 | int debuginfo__find_line_range(struct debuginfo *dbg, struct line_range *lr); |
51 | 54 | ||