Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull perf fixes from Ingo Molnar:
"An Intel PMU driver hotplug fix and three 'perf probe' tooling fixes"

* 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
perf/x86/intel: Handle exclusive threadid correctly on CPU hotplug
perf probe: Fix to probe on gcc generated functions in modules
perf probe: Add error checks to offline probe post-processing
perf probe: Fix to show correct locations for events on modules

+77 -43
+5 -2
arch/x86/events/intel/core.c
··· 3176 3176 3177 3177 if (x86_pmu.flags & PMU_FL_EXCL_CNTRS) { 3178 3178 for_each_cpu(i, topology_sibling_cpumask(cpu)) { 3179 + struct cpu_hw_events *sibling; 3179 3180 struct intel_excl_cntrs *c; 3180 3181 3181 - c = per_cpu(cpu_hw_events, i).excl_cntrs; 3182 + sibling = &per_cpu(cpu_hw_events, i); 3183 + c = sibling->excl_cntrs; 3182 3184 if (c && c->core_id == core_id) { 3183 3185 cpuc->kfree_on_online[1] = cpuc->excl_cntrs; 3184 3186 cpuc->excl_cntrs = c; 3185 - cpuc->excl_thread_id = 1; 3187 + if (!sibling->excl_thread_id) 3188 + cpuc->excl_thread_id = 1; 3186 3189 break; 3187 3190 } 3188 3191 }
+62 -33
tools/perf/util/probe-event.c
··· 610 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 641 * Rename DWARF symbols to ELF symbols -- gcc sometimes optimizes functions 615 642 * and generate new symbols with suffixes such as .constprop.N or .isra.N ··· 649 622 post_process_offline_probe_trace_events(struct probe_trace_event *tevs, 650 623 int ntevs, const char *pathname) 651 624 { 652 - struct symbol *sym; 653 625 struct map *map; 654 626 unsigned long stext = 0; 655 - u64 addr; 656 - int i; 627 + int i, ret = 0; 657 628 658 629 /* Prepare a map for offline binary */ 659 630 map = dso__new_map(pathname); ··· 661 636 } 662 637 663 638 for (i = 0; i < ntevs; i++) { 664 - addr = tevs[i].point.address + tevs[i].point.offset - stext; 665 - sym = map__find_symbol(map, addr); 666 - if (!sym) 667 - continue; 668 - if (!strcmp(sym->name, tevs[i].point.symbol)) 669 - continue; 670 - /* If we have no realname, use symbol for it */ 671 - if (!tevs[i].point.realname) 672 - tevs[i].point.realname = tevs[i].point.symbol; 673 - else 674 - free(tevs[i].point.symbol); 675 - tevs[i].point.symbol = strdup(sym->name); 676 - tevs[i].point.offset = addr - sym->start; 639 + ret = post_process_probe_trace_point(&tevs[i].point, 640 + map, stext); 641 + if (ret < 0) 642 + break; 677 643 } 678 644 map__put(map); 679 645 680 - return 0; 646 + return ret; 681 647 } 682 648 683 649 static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs, ··· 698 682 return ret; 699 683 } 700 684 701 - static int add_module_to_probe_trace_events(struct probe_trace_event *tevs, 702 - int ntevs, const char *module) 685 + static int 686 + post_process_module_probe_trace_events(struct probe_trace_event *tevs, 687 + int ntevs, const char *module, 688 + struct debuginfo *dinfo) 703 689 { 690 + Dwarf_Addr text_offs = 0; 704 691 int i, ret = 0; 705 692 char *mod_name = NULL; 693 + struct map *map; 706 694 707 695 if (!module) 708 696 return 0; 709 697 710 - mod_name = find_module_name(module); 698 + map = get_target_map(module, false); 699 + if (!map || debuginfo__get_text_offset(dinfo, &text_offs, true) < 0) { 700 + pr_warning("Failed to get ELF symbols for %s\n", module); 701 + return -EINVAL; 702 + } 711 703 704 + mod_name = find_module_name(module); 712 705 for (i = 0; i < ntevs; i++) { 706 + ret = post_process_probe_trace_point(&tevs[i].point, 707 + map, (unsigned long)text_offs); 708 + if (ret < 0) 709 + break; 713 710 tevs[i].point.module = 714 711 strdup(mod_name ? mod_name : module); 715 712 if (!tevs[i].point.module) { ··· 732 703 } 733 704 734 705 free(mod_name); 706 + map__put(map); 707 + 735 708 return ret; 736 709 } 737 710 ··· 791 760 static int post_process_probe_trace_events(struct perf_probe_event *pev, 792 761 struct probe_trace_event *tevs, 793 762 int ntevs, const char *module, 794 - bool uprobe) 763 + bool uprobe, struct debuginfo *dinfo) 795 764 { 796 765 int ret; 797 766 ··· 799 768 ret = add_exec_to_probe_trace_events(tevs, ntevs, module); 800 769 else if (module) 801 770 /* Currently ref_reloc_sym based probe is not for drivers */ 802 - ret = add_module_to_probe_trace_events(tevs, ntevs, module); 771 + ret = post_process_module_probe_trace_events(tevs, ntevs, 772 + module, dinfo); 803 773 else 804 774 ret = post_process_kernel_probe_trace_events(tevs, ntevs); 805 775 ··· 844 812 } 845 813 } 846 814 847 - debuginfo__delete(dinfo); 848 - 849 815 if (ntevs > 0) { /* Succeeded to find trace events */ 850 816 pr_debug("Found %d probe_trace_events.\n", ntevs); 851 817 ret = post_process_probe_trace_events(pev, *tevs, ntevs, 852 - pev->target, pev->uprobes); 818 + pev->target, pev->uprobes, dinfo); 853 819 if (ret < 0 || ret == ntevs) { 820 + pr_debug("Post processing failed or all events are skipped. (%d)\n", ret); 854 821 clear_probe_trace_events(*tevs, ntevs); 855 822 zfree(tevs); 823 + ntevs = 0; 856 824 } 857 - if (ret != ntevs) 858 - return ret < 0 ? ret : ntevs; 859 - ntevs = 0; 860 - /* Fall through */ 861 825 } 826 + 827 + debuginfo__delete(dinfo); 862 828 863 829 if (ntevs == 0) { /* No error but failed to find probe point. */ 864 830 pr_warning("Probe point '%s' not found.\n", 865 831 synthesize_perf_probe_point(&pev->point)); 866 832 return -ENOENT; 867 - } 868 - /* Error path : ntevs < 0 */ 869 - pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs); 870 - if (ntevs < 0) { 833 + } else if (ntevs < 0) { 834 + /* Error path : ntevs < 0 */ 835 + pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs); 871 836 if (ntevs == -EBADF) 872 837 pr_warning("Warning: No dwarf info found in the vmlinux - " 873 838 "please rebuild kernel with CONFIG_DEBUG_INFO=y.\n");
+7 -8
tools/perf/util/probe-finder.c
··· 1501 1501 } 1502 1502 1503 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 1507 int n, i; 1507 1508 Elf32_Word shndx; ··· 1531 1530 if (!shdr) 1532 1531 return -ENOENT; 1533 1532 *offs = shdr->sh_addr; 1533 + if (adjust_offset) 1534 + *offs -= shdr->sh_offset; 1534 1535 } 1535 1536 } 1536 1537 return 0; ··· 1546 1543 Dwarf_Addr _addr = 0, baseaddr = 0; 1547 1544 const char *fname = NULL, *func = NULL, *basefunc = NULL, *tmp; 1548 1545 int baseline = 0, lineno = 0, ret = 0; 1549 - bool reloc = false; 1550 1546 1551 - retry: 1547 + /* We always need to relocate the address for aranges */ 1548 + if (debuginfo__get_text_offset(dbg, &baseaddr, false) == 0) 1549 + addr += baseaddr; 1552 1550 /* Find cu die */ 1553 1551 if (!dwarf_addrdie(dbg->dbg, (Dwarf_Addr)addr, &cudie)) { 1554 - if (!reloc && debuginfo__get_text_offset(dbg, &baseaddr) == 0) { 1555 - addr += baseaddr; 1556 - reloc = true; 1557 - goto retry; 1558 - } 1559 1552 pr_warning("Failed to find debug information for address %lx\n", 1560 1553 addr); 1561 1554 ret = -EINVAL;
+3
tools/perf/util/probe-finder.h
··· 46 46 int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr, 47 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 52 /* Find a line range */ 50 53 int debuginfo__find_line_range(struct debuginfo *dbg, struct line_range *lr); 51 54