diff options
-rw-r--r-- | arch/x86/kernel/cpu/perf_event.c | 10 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/perf_event_intel.c | 1 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/perf_event_intel_uncore.c | 10 | ||||
-rw-r--r-- | include/uapi/linux/perf_event.h | 15 | ||||
-rw-r--r-- | kernel/events/core.c | 21 | ||||
-rw-r--r-- | tools/lib/lk/debugfs.c | 1 | ||||
-rw-r--r-- | tools/perf/arch/x86/util/tsc.c | 6 | ||||
-rw-r--r-- | tools/perf/builtin-inject.c | 2 | ||||
-rw-r--r-- | tools/perf/builtin-report.c | 5 | ||||
-rw-r--r-- | tools/perf/builtin-script.c | 2 | ||||
-rw-r--r-- | tools/perf/builtin-trace.c | 17 | ||||
-rw-r--r-- | tools/perf/config/Makefile | 3 | ||||
-rw-r--r-- | tools/perf/config/feature-tests.mak | 10 | ||||
-rw-r--r-- | tools/perf/util/annotate.c | 2 | ||||
-rw-r--r-- | tools/perf/util/dwarf-aux.c | 19 | ||||
-rw-r--r-- | tools/perf/util/dwarf-aux.h | 3 | ||||
-rw-r--r-- | tools/perf/util/header.c | 41 | ||||
-rw-r--r-- | tools/perf/util/hist.c | 2 | ||||
-rw-r--r-- | tools/perf/util/probe-finder.c | 12 | ||||
-rw-r--r-- | tools/perf/util/session.c | 9 | ||||
-rw-r--r-- | tools/perf/util/session.h | 4 | ||||
-rw-r--r-- | tools/perf/util/symbol-elf.c | 16 | ||||
-rw-r--r-- | tools/perf/util/trace-event-parse.c | 2 |
23 files changed, 164 insertions, 49 deletions
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 8355c84b9729..a9c606bb4945 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c | |||
@@ -1883,9 +1883,9 @@ static struct pmu pmu = { | |||
1883 | 1883 | ||
1884 | void arch_perf_update_userpage(struct perf_event_mmap_page *userpg, u64 now) | 1884 | void arch_perf_update_userpage(struct perf_event_mmap_page *userpg, u64 now) |
1885 | { | 1885 | { |
1886 | userpg->cap_usr_time = 0; | 1886 | userpg->cap_user_time = 0; |
1887 | userpg->cap_usr_time_zero = 0; | 1887 | userpg->cap_user_time_zero = 0; |
1888 | userpg->cap_usr_rdpmc = x86_pmu.attr_rdpmc; | 1888 | userpg->cap_user_rdpmc = x86_pmu.attr_rdpmc; |
1889 | userpg->pmc_width = x86_pmu.cntval_bits; | 1889 | userpg->pmc_width = x86_pmu.cntval_bits; |
1890 | 1890 | ||
1891 | if (!boot_cpu_has(X86_FEATURE_CONSTANT_TSC)) | 1891 | if (!boot_cpu_has(X86_FEATURE_CONSTANT_TSC)) |
@@ -1894,13 +1894,13 @@ void arch_perf_update_userpage(struct perf_event_mmap_page *userpg, u64 now) | |||
1894 | if (!boot_cpu_has(X86_FEATURE_NONSTOP_TSC)) | 1894 | if (!boot_cpu_has(X86_FEATURE_NONSTOP_TSC)) |
1895 | return; | 1895 | return; |
1896 | 1896 | ||
1897 | userpg->cap_usr_time = 1; | 1897 | userpg->cap_user_time = 1; |
1898 | userpg->time_mult = this_cpu_read(cyc2ns); | 1898 | userpg->time_mult = this_cpu_read(cyc2ns); |
1899 | userpg->time_shift = CYC2NS_SCALE_FACTOR; | 1899 | userpg->time_shift = CYC2NS_SCALE_FACTOR; |
1900 | userpg->time_offset = this_cpu_read(cyc2ns_offset) - now; | 1900 | userpg->time_offset = this_cpu_read(cyc2ns_offset) - now; |
1901 | 1901 | ||
1902 | if (sched_clock_stable && !check_tsc_disabled()) { | 1902 | if (sched_clock_stable && !check_tsc_disabled()) { |
1903 | userpg->cap_usr_time_zero = 1; | 1903 | userpg->cap_user_time_zero = 1; |
1904 | userpg->time_zero = this_cpu_read(cyc2ns_offset); | 1904 | userpg->time_zero = this_cpu_read(cyc2ns_offset); |
1905 | } | 1905 | } |
1906 | } | 1906 | } |
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index 9db76c31b3c3..f31a1655d1ff 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c | |||
@@ -2325,6 +2325,7 @@ __init int intel_pmu_init(void) | |||
2325 | break; | 2325 | break; |
2326 | 2326 | ||
2327 | case 55: /* Atom 22nm "Silvermont" */ | 2327 | case 55: /* Atom 22nm "Silvermont" */ |
2328 | case 77: /* Avoton "Silvermont" */ | ||
2328 | memcpy(hw_cache_event_ids, slm_hw_cache_event_ids, | 2329 | memcpy(hw_cache_event_ids, slm_hw_cache_event_ids, |
2329 | sizeof(hw_cache_event_ids)); | 2330 | sizeof(hw_cache_event_ids)); |
2330 | memcpy(hw_cache_extra_regs, slm_hw_cache_extra_regs, | 2331 | memcpy(hw_cache_extra_regs, slm_hw_cache_extra_regs, |
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c index 8ed44589b0e4..4118f9f68315 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c | |||
@@ -2706,14 +2706,14 @@ static void uncore_pmu_init_hrtimer(struct intel_uncore_box *box) | |||
2706 | box->hrtimer.function = uncore_pmu_hrtimer; | 2706 | box->hrtimer.function = uncore_pmu_hrtimer; |
2707 | } | 2707 | } |
2708 | 2708 | ||
2709 | struct intel_uncore_box *uncore_alloc_box(struct intel_uncore_type *type, int cpu) | 2709 | static struct intel_uncore_box *uncore_alloc_box(struct intel_uncore_type *type, int node) |
2710 | { | 2710 | { |
2711 | struct intel_uncore_box *box; | 2711 | struct intel_uncore_box *box; |
2712 | int i, size; | 2712 | int i, size; |
2713 | 2713 | ||
2714 | size = sizeof(*box) + type->num_shared_regs * sizeof(struct intel_uncore_extra_reg); | 2714 | size = sizeof(*box) + type->num_shared_regs * sizeof(struct intel_uncore_extra_reg); |
2715 | 2715 | ||
2716 | box = kzalloc_node(size, GFP_KERNEL, cpu_to_node(cpu)); | 2716 | box = kzalloc_node(size, GFP_KERNEL, node); |
2717 | if (!box) | 2717 | if (!box) |
2718 | return NULL; | 2718 | return NULL; |
2719 | 2719 | ||
@@ -3031,7 +3031,7 @@ static int uncore_validate_group(struct intel_uncore_pmu *pmu, | |||
3031 | struct intel_uncore_box *fake_box; | 3031 | struct intel_uncore_box *fake_box; |
3032 | int ret = -EINVAL, n; | 3032 | int ret = -EINVAL, n; |
3033 | 3033 | ||
3034 | fake_box = uncore_alloc_box(pmu->type, smp_processor_id()); | 3034 | fake_box = uncore_alloc_box(pmu->type, NUMA_NO_NODE); |
3035 | if (!fake_box) | 3035 | if (!fake_box) |
3036 | return -ENOMEM; | 3036 | return -ENOMEM; |
3037 | 3037 | ||
@@ -3294,7 +3294,7 @@ static int uncore_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id | |||
3294 | } | 3294 | } |
3295 | 3295 | ||
3296 | type = pci_uncores[UNCORE_PCI_DEV_TYPE(id->driver_data)]; | 3296 | type = pci_uncores[UNCORE_PCI_DEV_TYPE(id->driver_data)]; |
3297 | box = uncore_alloc_box(type, 0); | 3297 | box = uncore_alloc_box(type, NUMA_NO_NODE); |
3298 | if (!box) | 3298 | if (!box) |
3299 | return -ENOMEM; | 3299 | return -ENOMEM; |
3300 | 3300 | ||
@@ -3499,7 +3499,7 @@ static int uncore_cpu_prepare(int cpu, int phys_id) | |||
3499 | if (pmu->func_id < 0) | 3499 | if (pmu->func_id < 0) |
3500 | pmu->func_id = j; | 3500 | pmu->func_id = j; |
3501 | 3501 | ||
3502 | box = uncore_alloc_box(type, cpu); | 3502 | box = uncore_alloc_box(type, cpu_to_node(cpu)); |
3503 | if (!box) | 3503 | if (!box) |
3504 | return -ENOMEM; | 3504 | return -ENOMEM; |
3505 | 3505 | ||
diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h index 40a1fb807396..009a655a5d35 100644 --- a/include/uapi/linux/perf_event.h +++ b/include/uapi/linux/perf_event.h | |||
@@ -380,10 +380,13 @@ struct perf_event_mmap_page { | |||
380 | union { | 380 | union { |
381 | __u64 capabilities; | 381 | __u64 capabilities; |
382 | struct { | 382 | struct { |
383 | __u64 cap_usr_time : 1, | 383 | __u64 cap_bit0 : 1, /* Always 0, deprecated, see commit 860f085b74e9 */ |
384 | cap_usr_rdpmc : 1, | 384 | cap_bit0_is_deprecated : 1, /* Always 1, signals that bit 0 is zero */ |
385 | cap_usr_time_zero : 1, | 385 | |
386 | cap_____res : 61; | 386 | cap_user_rdpmc : 1, /* The RDPMC instruction can be used to read counts */ |
387 | cap_user_time : 1, /* The time_* fields are used */ | ||
388 | cap_user_time_zero : 1, /* The time_zero field is used */ | ||
389 | cap_____res : 59; | ||
387 | }; | 390 | }; |
388 | }; | 391 | }; |
389 | 392 | ||
@@ -442,12 +445,13 @@ struct perf_event_mmap_page { | |||
442 | * ((rem * time_mult) >> time_shift); | 445 | * ((rem * time_mult) >> time_shift); |
443 | */ | 446 | */ |
444 | __u64 time_zero; | 447 | __u64 time_zero; |
448 | __u32 size; /* Header size up to __reserved[] fields. */ | ||
445 | 449 | ||
446 | /* | 450 | /* |
447 | * Hole for extension of the self monitor capabilities | 451 | * Hole for extension of the self monitor capabilities |
448 | */ | 452 | */ |
449 | 453 | ||
450 | __u64 __reserved[119]; /* align to 1k */ | 454 | __u8 __reserved[118*8+4]; /* align to 1k. */ |
451 | 455 | ||
452 | /* | 456 | /* |
453 | * Control data for the mmap() data buffer. | 457 | * Control data for the mmap() data buffer. |
@@ -528,6 +532,7 @@ enum perf_event_type { | |||
528 | * u64 len; | 532 | * u64 len; |
529 | * u64 pgoff; | 533 | * u64 pgoff; |
530 | * char filename[]; | 534 | * char filename[]; |
535 | * struct sample_id sample_id; | ||
531 | * }; | 536 | * }; |
532 | */ | 537 | */ |
533 | PERF_RECORD_MMAP = 1, | 538 | PERF_RECORD_MMAP = 1, |
diff --git a/kernel/events/core.c b/kernel/events/core.c index dd236b66ca3a..cb4238e85b38 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c | |||
@@ -3660,6 +3660,26 @@ static void calc_timer_values(struct perf_event *event, | |||
3660 | *running = ctx_time - event->tstamp_running; | 3660 | *running = ctx_time - event->tstamp_running; |
3661 | } | 3661 | } |
3662 | 3662 | ||
3663 | static void perf_event_init_userpage(struct perf_event *event) | ||
3664 | { | ||
3665 | struct perf_event_mmap_page *userpg; | ||
3666 | struct ring_buffer *rb; | ||
3667 | |||
3668 | rcu_read_lock(); | ||
3669 | rb = rcu_dereference(event->rb); | ||
3670 | if (!rb) | ||
3671 | goto unlock; | ||
3672 | |||
3673 | userpg = rb->user_page; | ||
3674 | |||
3675 | /* Allow new userspace to detect that bit 0 is deprecated */ | ||
3676 | userpg->cap_bit0_is_deprecated = 1; | ||
3677 | userpg->size = offsetof(struct perf_event_mmap_page, __reserved); | ||
3678 | |||
3679 | unlock: | ||
3680 | rcu_read_unlock(); | ||
3681 | } | ||
3682 | |||
3663 | void __weak arch_perf_update_userpage(struct perf_event_mmap_page *userpg, u64 now) | 3683 | void __weak arch_perf_update_userpage(struct perf_event_mmap_page *userpg, u64 now) |
3664 | { | 3684 | { |
3665 | } | 3685 | } |
@@ -4044,6 +4064,7 @@ again: | |||
4044 | ring_buffer_attach(event, rb); | 4064 | ring_buffer_attach(event, rb); |
4045 | rcu_assign_pointer(event->rb, rb); | 4065 | rcu_assign_pointer(event->rb, rb); |
4046 | 4066 | ||
4067 | perf_event_init_userpage(event); | ||
4047 | perf_event_update_userpage(event); | 4068 | perf_event_update_userpage(event); |
4048 | 4069 | ||
4049 | unlock: | 4070 | unlock: |
diff --git a/tools/lib/lk/debugfs.c b/tools/lib/lk/debugfs.c index 099e7cd022e4..7c4347962353 100644 --- a/tools/lib/lk/debugfs.c +++ b/tools/lib/lk/debugfs.c | |||
@@ -5,7 +5,6 @@ | |||
5 | #include <stdbool.h> | 5 | #include <stdbool.h> |
6 | #include <sys/vfs.h> | 6 | #include <sys/vfs.h> |
7 | #include <sys/mount.h> | 7 | #include <sys/mount.h> |
8 | #include <linux/magic.h> | ||
9 | #include <linux/kernel.h> | 8 | #include <linux/kernel.h> |
10 | 9 | ||
11 | #include "debugfs.h" | 10 | #include "debugfs.h" |
diff --git a/tools/perf/arch/x86/util/tsc.c b/tools/perf/arch/x86/util/tsc.c index 9570c2b0f83c..b2519e49424f 100644 --- a/tools/perf/arch/x86/util/tsc.c +++ b/tools/perf/arch/x86/util/tsc.c | |||
@@ -32,7 +32,7 @@ u64 tsc_to_perf_time(u64 cyc, struct perf_tsc_conversion *tc) | |||
32 | int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc, | 32 | int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc, |
33 | struct perf_tsc_conversion *tc) | 33 | struct perf_tsc_conversion *tc) |
34 | { | 34 | { |
35 | bool cap_usr_time_zero; | 35 | bool cap_user_time_zero; |
36 | u32 seq; | 36 | u32 seq; |
37 | int i = 0; | 37 | int i = 0; |
38 | 38 | ||
@@ -42,7 +42,7 @@ int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc, | |||
42 | tc->time_mult = pc->time_mult; | 42 | tc->time_mult = pc->time_mult; |
43 | tc->time_shift = pc->time_shift; | 43 | tc->time_shift = pc->time_shift; |
44 | tc->time_zero = pc->time_zero; | 44 | tc->time_zero = pc->time_zero; |
45 | cap_usr_time_zero = pc->cap_usr_time_zero; | 45 | cap_user_time_zero = pc->cap_user_time_zero; |
46 | rmb(); | 46 | rmb(); |
47 | if (pc->lock == seq && !(seq & 1)) | 47 | if (pc->lock == seq && !(seq & 1)) |
48 | break; | 48 | break; |
@@ -52,7 +52,7 @@ int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc, | |||
52 | } | 52 | } |
53 | } | 53 | } |
54 | 54 | ||
55 | if (!cap_usr_time_zero) | 55 | if (!cap_user_time_zero) |
56 | return -EOPNOTSUPP; | 56 | return -EOPNOTSUPP; |
57 | 57 | ||
58 | return 0; | 58 | return 0; |
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index 423875c999b2..afe377b2884f 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c | |||
@@ -321,8 +321,6 @@ found: | |||
321 | return perf_event__repipe(tool, event_sw, &sample_sw, machine); | 321 | return perf_event__repipe(tool, event_sw, &sample_sw, machine); |
322 | } | 322 | } |
323 | 323 | ||
324 | extern volatile int session_done; | ||
325 | |||
326 | static void sig_handler(int sig __maybe_unused) | 324 | static void sig_handler(int sig __maybe_unused) |
327 | { | 325 | { |
328 | session_done = 1; | 326 | session_done = 1; |
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 8e50d8d77419..72eae7498c09 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
@@ -401,8 +401,6 @@ static int perf_report__setup_sample_type(struct perf_report *rep) | |||
401 | return 0; | 401 | return 0; |
402 | } | 402 | } |
403 | 403 | ||
404 | extern volatile int session_done; | ||
405 | |||
406 | static void sig_handler(int sig __maybe_unused) | 404 | static void sig_handler(int sig __maybe_unused) |
407 | { | 405 | { |
408 | session_done = 1; | 406 | session_done = 1; |
@@ -568,6 +566,9 @@ static int __cmd_report(struct perf_report *rep) | |||
568 | } | 566 | } |
569 | } | 567 | } |
570 | 568 | ||
569 | if (session_done()) | ||
570 | return 0; | ||
571 | |||
571 | if (nr_samples == 0) { | 572 | if (nr_samples == 0) { |
572 | ui__error("The %s file has no samples!\n", session->filename); | 573 | ui__error("The %s file has no samples!\n", session->filename); |
573 | return 0; | 574 | return 0; |
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 7f31a3ded1b6..9c333ff3dfeb 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c | |||
@@ -553,8 +553,6 @@ static struct perf_tool perf_script = { | |||
553 | .ordering_requires_timestamps = true, | 553 | .ordering_requires_timestamps = true, |
554 | }; | 554 | }; |
555 | 555 | ||
556 | extern volatile int session_done; | ||
557 | |||
558 | static void sig_handler(int sig __maybe_unused) | 556 | static void sig_handler(int sig __maybe_unused) |
559 | { | 557 | { |
560 | session_done = 1; | 558 | session_done = 1; |
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index f5aa6375e3e9..fd4853404727 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c | |||
@@ -16,6 +16,23 @@ | |||
16 | #include <sys/mman.h> | 16 | #include <sys/mman.h> |
17 | #include <linux/futex.h> | 17 | #include <linux/futex.h> |
18 | 18 | ||
19 | /* For older distros: */ | ||
20 | #ifndef MAP_STACK | ||
21 | # define MAP_STACK 0x20000 | ||
22 | #endif | ||
23 | |||
24 | #ifndef MADV_HWPOISON | ||
25 | # define MADV_HWPOISON 100 | ||
26 | #endif | ||
27 | |||
28 | #ifndef MADV_MERGEABLE | ||
29 | # define MADV_MERGEABLE 12 | ||
30 | #endif | ||
31 | |||
32 | #ifndef MADV_UNMERGEABLE | ||
33 | # define MADV_UNMERGEABLE 13 | ||
34 | #endif | ||
35 | |||
19 | static size_t syscall_arg__scnprintf_hex(char *bf, size_t size, | 36 | static size_t syscall_arg__scnprintf_hex(char *bf, size_t size, |
20 | unsigned long arg, | 37 | unsigned long arg, |
21 | u8 arg_idx __maybe_unused, | 38 | u8 arg_idx __maybe_unused, |
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile index 214e17e97e5c..346ee929d250 100644 --- a/tools/perf/config/Makefile +++ b/tools/perf/config/Makefile | |||
@@ -180,6 +180,9 @@ FLAGS_LIBELF=$(CFLAGS) $(LDFLAGS) $(EXTLIBS) | |||
180 | ifeq ($(call try-cc,$(SOURCE_ELF_MMAP),$(FLAGS_LIBELF),-DLIBELF_MMAP),y) | 180 | ifeq ($(call try-cc,$(SOURCE_ELF_MMAP),$(FLAGS_LIBELF),-DLIBELF_MMAP),y) |
181 | CFLAGS += -DLIBELF_MMAP | 181 | CFLAGS += -DLIBELF_MMAP |
182 | endif | 182 | endif |
183 | ifeq ($(call try-cc,$(SOURCE_ELF_GETPHDRNUM),$(FLAGS_LIBELF),-DHAVE_ELF_GETPHDRNUM),y) | ||
184 | CFLAGS += -DHAVE_ELF_GETPHDRNUM | ||
185 | endif | ||
183 | 186 | ||
184 | # include ARCH specific config | 187 | # include ARCH specific config |
185 | -include $(src-perf)/arch/$(ARCH)/Makefile | 188 | -include $(src-perf)/arch/$(ARCH)/Makefile |
diff --git a/tools/perf/config/feature-tests.mak b/tools/perf/config/feature-tests.mak index 708fb8e9822a..d5a8dd44945f 100644 --- a/tools/perf/config/feature-tests.mak +++ b/tools/perf/config/feature-tests.mak | |||
@@ -61,6 +61,15 @@ int main(void) | |||
61 | } | 61 | } |
62 | endef | 62 | endef |
63 | 63 | ||
64 | define SOURCE_ELF_GETPHDRNUM | ||
65 | #include <libelf.h> | ||
66 | int main(void) | ||
67 | { | ||
68 | size_t dst; | ||
69 | return elf_getphdrnum(0, &dst); | ||
70 | } | ||
71 | endef | ||
72 | |||
64 | ifndef NO_SLANG | 73 | ifndef NO_SLANG |
65 | define SOURCE_SLANG | 74 | define SOURCE_SLANG |
66 | #include <slang.h> | 75 | #include <slang.h> |
@@ -210,6 +219,7 @@ define SOURCE_LIBAUDIT | |||
210 | 219 | ||
211 | int main(void) | 220 | int main(void) |
212 | { | 221 | { |
222 | printf(\"error message: %s\n\", audit_errno_to_name(0)); | ||
213 | return audit_open(); | 223 | return audit_open(); |
214 | } | 224 | } |
215 | endef | 225 | endef |
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index bfc5a27597d6..7eae5488ecea 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c | |||
@@ -809,7 +809,7 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, | |||
809 | end = map__rip_2objdump(map, sym->end); | 809 | end = map__rip_2objdump(map, sym->end); |
810 | 810 | ||
811 | offset = line_ip - start; | 811 | offset = line_ip - start; |
812 | if (offset < 0 || (u64)line_ip > end) | 812 | if ((u64)line_ip < start || (u64)line_ip > end) |
813 | offset = -1; | 813 | offset = -1; |
814 | else | 814 | else |
815 | parsed_line = tmp2 + 1; | 815 | parsed_line = tmp2 + 1; |
diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c index 3e5f5430a28a..e23bde19d590 100644 --- a/tools/perf/util/dwarf-aux.c +++ b/tools/perf/util/dwarf-aux.c | |||
@@ -263,6 +263,21 @@ bool die_is_signed_type(Dwarf_Die *tp_die) | |||
263 | } | 263 | } |
264 | 264 | ||
265 | /** | 265 | /** |
266 | * die_is_func_def - Ensure that this DIE is a subprogram and definition | ||
267 | * @dw_die: a DIE | ||
268 | * | ||
269 | * Ensure that this DIE is a subprogram and NOT a declaration. This | ||
270 | * returns true if @dw_die is a function definition. | ||
271 | **/ | ||
272 | bool die_is_func_def(Dwarf_Die *dw_die) | ||
273 | { | ||
274 | Dwarf_Attribute attr; | ||
275 | |||
276 | return (dwarf_tag(dw_die) == DW_TAG_subprogram && | ||
277 | dwarf_attr(dw_die, DW_AT_declaration, &attr) == NULL); | ||
278 | } | ||
279 | |||
280 | /** | ||
266 | * die_get_data_member_location - Get the data-member offset | 281 | * die_get_data_member_location - Get the data-member offset |
267 | * @mb_die: a DIE of a member of a data structure | 282 | * @mb_die: a DIE of a member of a data structure |
268 | * @offs: The offset of the member in the data structure | 283 | * @offs: The offset of the member in the data structure |
@@ -392,6 +407,10 @@ static int __die_search_func_cb(Dwarf_Die *fn_die, void *data) | |||
392 | { | 407 | { |
393 | struct __addr_die_search_param *ad = data; | 408 | struct __addr_die_search_param *ad = data; |
394 | 409 | ||
410 | /* | ||
411 | * Since a declaration entry doesn't has given pc, this always returns | ||
412 | * function definition entry. | ||
413 | */ | ||
395 | if (dwarf_tag(fn_die) == DW_TAG_subprogram && | 414 | if (dwarf_tag(fn_die) == DW_TAG_subprogram && |
396 | dwarf_haspc(fn_die, ad->addr)) { | 415 | dwarf_haspc(fn_die, ad->addr)) { |
397 | memcpy(ad->die_mem, fn_die, sizeof(Dwarf_Die)); | 416 | memcpy(ad->die_mem, fn_die, sizeof(Dwarf_Die)); |
diff --git a/tools/perf/util/dwarf-aux.h b/tools/perf/util/dwarf-aux.h index 6ce1717784b7..8658d41697d2 100644 --- a/tools/perf/util/dwarf-aux.h +++ b/tools/perf/util/dwarf-aux.h | |||
@@ -38,6 +38,9 @@ extern int cu_find_lineinfo(Dwarf_Die *cudie, unsigned long addr, | |||
38 | extern int cu_walk_functions_at(Dwarf_Die *cu_die, Dwarf_Addr addr, | 38 | extern int cu_walk_functions_at(Dwarf_Die *cu_die, Dwarf_Addr addr, |
39 | int (*callback)(Dwarf_Die *, void *), void *data); | 39 | int (*callback)(Dwarf_Die *, void *), void *data); |
40 | 40 | ||
41 | /* Ensure that this DIE is a subprogram and definition (not declaration) */ | ||
42 | extern bool die_is_func_def(Dwarf_Die *dw_die); | ||
43 | |||
41 | /* Compare diename and tname */ | 44 | /* Compare diename and tname */ |
42 | extern bool die_compare_name(Dwarf_Die *dw_die, const char *tname); | 45 | extern bool die_compare_name(Dwarf_Die *dw_die, const char *tname); |
43 | 46 | ||
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 26441d0e571b..ce69901176d8 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
@@ -199,9 +199,11 @@ static int write_buildid(char *name, size_t name_len, u8 *build_id, | |||
199 | return write_padded(fd, name, name_len + 1, len); | 199 | return write_padded(fd, name, name_len + 1, len); |
200 | } | 200 | } |
201 | 201 | ||
202 | static int __dsos__write_buildid_table(struct list_head *head, pid_t pid, | 202 | static int __dsos__write_buildid_table(struct list_head *head, |
203 | u16 misc, int fd) | 203 | struct machine *machine, |
204 | pid_t pid, u16 misc, int fd) | ||
204 | { | 205 | { |
206 | char nm[PATH_MAX]; | ||
205 | struct dso *pos; | 207 | struct dso *pos; |
206 | 208 | ||
207 | dsos__for_each_with_build_id(pos, head) { | 209 | dsos__for_each_with_build_id(pos, head) { |
@@ -215,6 +217,10 @@ static int __dsos__write_buildid_table(struct list_head *head, pid_t pid, | |||
215 | if (is_vdso_map(pos->short_name)) { | 217 | if (is_vdso_map(pos->short_name)) { |
216 | name = (char *) VDSO__MAP_NAME; | 218 | name = (char *) VDSO__MAP_NAME; |
217 | name_len = sizeof(VDSO__MAP_NAME) + 1; | 219 | name_len = sizeof(VDSO__MAP_NAME) + 1; |
220 | } else if (dso__is_kcore(pos)) { | ||
221 | machine__mmap_name(machine, nm, sizeof(nm)); | ||
222 | name = nm; | ||
223 | name_len = strlen(nm) + 1; | ||
218 | } else { | 224 | } else { |
219 | name = pos->long_name; | 225 | name = pos->long_name; |
220 | name_len = pos->long_name_len + 1; | 226 | name_len = pos->long_name_len + 1; |
@@ -240,10 +246,10 @@ static int machine__write_buildid_table(struct machine *machine, int fd) | |||
240 | umisc = PERF_RECORD_MISC_GUEST_USER; | 246 | umisc = PERF_RECORD_MISC_GUEST_USER; |
241 | } | 247 | } |
242 | 248 | ||
243 | err = __dsos__write_buildid_table(&machine->kernel_dsos, machine->pid, | 249 | err = __dsos__write_buildid_table(&machine->kernel_dsos, machine, |
244 | kmisc, fd); | 250 | machine->pid, kmisc, fd); |
245 | if (err == 0) | 251 | if (err == 0) |
246 | err = __dsos__write_buildid_table(&machine->user_dsos, | 252 | err = __dsos__write_buildid_table(&machine->user_dsos, machine, |
247 | machine->pid, umisc, fd); | 253 | machine->pid, umisc, fd); |
248 | return err; | 254 | return err; |
249 | } | 255 | } |
@@ -375,23 +381,31 @@ out_free: | |||
375 | return err; | 381 | return err; |
376 | } | 382 | } |
377 | 383 | ||
378 | static int dso__cache_build_id(struct dso *dso, const char *debugdir) | 384 | static int dso__cache_build_id(struct dso *dso, struct machine *machine, |
385 | const char *debugdir) | ||
379 | { | 386 | { |
380 | bool is_kallsyms = dso->kernel && dso->long_name[0] != '/'; | 387 | bool is_kallsyms = dso->kernel && dso->long_name[0] != '/'; |
381 | bool is_vdso = is_vdso_map(dso->short_name); | 388 | bool is_vdso = is_vdso_map(dso->short_name); |
389 | char *name = dso->long_name; | ||
390 | char nm[PATH_MAX]; | ||
382 | 391 | ||
383 | return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id), | 392 | if (dso__is_kcore(dso)) { |
384 | dso->long_name, debugdir, | 393 | is_kallsyms = true; |
385 | is_kallsyms, is_vdso); | 394 | machine__mmap_name(machine, nm, sizeof(nm)); |
395 | name = nm; | ||
396 | } | ||
397 | return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id), name, | ||
398 | debugdir, is_kallsyms, is_vdso); | ||
386 | } | 399 | } |
387 | 400 | ||
388 | static int __dsos__cache_build_ids(struct list_head *head, const char *debugdir) | 401 | static int __dsos__cache_build_ids(struct list_head *head, |
402 | struct machine *machine, const char *debugdir) | ||
389 | { | 403 | { |
390 | struct dso *pos; | 404 | struct dso *pos; |
391 | int err = 0; | 405 | int err = 0; |
392 | 406 | ||
393 | dsos__for_each_with_build_id(pos, head) | 407 | dsos__for_each_with_build_id(pos, head) |
394 | if (dso__cache_build_id(pos, debugdir)) | 408 | if (dso__cache_build_id(pos, machine, debugdir)) |
395 | err = -1; | 409 | err = -1; |
396 | 410 | ||
397 | return err; | 411 | return err; |
@@ -399,8 +413,9 @@ static int __dsos__cache_build_ids(struct list_head *head, const char *debugdir) | |||
399 | 413 | ||
400 | static int machine__cache_build_ids(struct machine *machine, const char *debugdir) | 414 | static int machine__cache_build_ids(struct machine *machine, const char *debugdir) |
401 | { | 415 | { |
402 | int ret = __dsos__cache_build_ids(&machine->kernel_dsos, debugdir); | 416 | int ret = __dsos__cache_build_ids(&machine->kernel_dsos, machine, |
403 | ret |= __dsos__cache_build_ids(&machine->user_dsos, debugdir); | 417 | debugdir); |
418 | ret |= __dsos__cache_build_ids(&machine->user_dsos, machine, debugdir); | ||
404 | return ret; | 419 | return ret; |
405 | } | 420 | } |
406 | 421 | ||
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 46a0d35a05e1..9ff6cf3e9a99 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c | |||
@@ -611,6 +611,8 @@ void hists__collapse_resort(struct hists *hists) | |||
611 | next = rb_first(root); | 611 | next = rb_first(root); |
612 | 612 | ||
613 | while (next) { | 613 | while (next) { |
614 | if (session_done()) | ||
615 | break; | ||
614 | n = rb_entry(next, struct hist_entry, rb_node_in); | 616 | n = rb_entry(next, struct hist_entry, rb_node_in); |
615 | next = rb_next(&n->rb_node_in); | 617 | next = rb_next(&n->rb_node_in); |
616 | 618 | ||
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index be0329394d56..20c7299a9d4e 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c | |||
@@ -734,7 +734,7 @@ static int call_probe_finder(Dwarf_Die *sc_die, struct probe_finder *pf) | |||
734 | } | 734 | } |
735 | 735 | ||
736 | /* If not a real subprogram, find a real one */ | 736 | /* If not a real subprogram, find a real one */ |
737 | if (dwarf_tag(sc_die) != DW_TAG_subprogram) { | 737 | if (!die_is_func_def(sc_die)) { |
738 | if (!die_find_realfunc(&pf->cu_die, pf->addr, &pf->sp_die)) { | 738 | if (!die_find_realfunc(&pf->cu_die, pf->addr, &pf->sp_die)) { |
739 | pr_warning("Failed to find probe point in any " | 739 | pr_warning("Failed to find probe point in any " |
740 | "functions.\n"); | 740 | "functions.\n"); |
@@ -980,12 +980,10 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data) | |||
980 | struct dwarf_callback_param *param = data; | 980 | struct dwarf_callback_param *param = data; |
981 | struct probe_finder *pf = param->data; | 981 | struct probe_finder *pf = param->data; |
982 | struct perf_probe_point *pp = &pf->pev->point; | 982 | struct perf_probe_point *pp = &pf->pev->point; |
983 | Dwarf_Attribute attr; | ||
984 | 983 | ||
985 | /* Check tag and diename */ | 984 | /* Check tag and diename */ |
986 | if (dwarf_tag(sp_die) != DW_TAG_subprogram || | 985 | if (!die_is_func_def(sp_die) || |
987 | !die_compare_name(sp_die, pp->function) || | 986 | !die_compare_name(sp_die, pp->function)) |
988 | dwarf_attr(sp_die, DW_AT_declaration, &attr)) | ||
989 | return DWARF_CB_OK; | 987 | return DWARF_CB_OK; |
990 | 988 | ||
991 | /* Check declared file */ | 989 | /* Check declared file */ |
@@ -1474,7 +1472,7 @@ static int line_range_inline_cb(Dwarf_Die *in_die, void *data) | |||
1474 | return 0; | 1472 | return 0; |
1475 | } | 1473 | } |
1476 | 1474 | ||
1477 | /* Search function from function name */ | 1475 | /* Search function definition from function name */ |
1478 | static int line_range_search_cb(Dwarf_Die *sp_die, void *data) | 1476 | static int line_range_search_cb(Dwarf_Die *sp_die, void *data) |
1479 | { | 1477 | { |
1480 | struct dwarf_callback_param *param = data; | 1478 | struct dwarf_callback_param *param = data; |
@@ -1485,7 +1483,7 @@ static int line_range_search_cb(Dwarf_Die *sp_die, void *data) | |||
1485 | if (lr->file && strtailcmp(lr->file, dwarf_decl_file(sp_die))) | 1483 | if (lr->file && strtailcmp(lr->file, dwarf_decl_file(sp_die))) |
1486 | return DWARF_CB_OK; | 1484 | return DWARF_CB_OK; |
1487 | 1485 | ||
1488 | if (dwarf_tag(sp_die) == DW_TAG_subprogram && | 1486 | if (die_is_func_def(sp_die) && |
1489 | die_compare_name(sp_die, lr->function)) { | 1487 | die_compare_name(sp_die, lr->function)) { |
1490 | lf->fname = dwarf_decl_file(sp_die); | 1488 | lf->fname = dwarf_decl_file(sp_die); |
1491 | dwarf_decl_line(sp_die, &lr->offset); | 1489 | dwarf_decl_line(sp_die, &lr->offset); |
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 51f5edf2a6d0..70ffa41518f3 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
@@ -531,6 +531,9 @@ static int flush_sample_queue(struct perf_session *s, | |||
531 | return 0; | 531 | return 0; |
532 | 532 | ||
533 | list_for_each_entry_safe(iter, tmp, head, list) { | 533 | list_for_each_entry_safe(iter, tmp, head, list) { |
534 | if (session_done()) | ||
535 | return 0; | ||
536 | |||
534 | if (iter->timestamp > limit) | 537 | if (iter->timestamp > limit) |
535 | break; | 538 | break; |
536 | 539 | ||
@@ -1160,7 +1163,6 @@ static void perf_session__warn_about_errors(const struct perf_session *session, | |||
1160 | } | 1163 | } |
1161 | } | 1164 | } |
1162 | 1165 | ||
1163 | #define session_done() (*(volatile int *)(&session_done)) | ||
1164 | volatile int session_done; | 1166 | volatile int session_done; |
1165 | 1167 | ||
1166 | static int __perf_session__process_pipe_events(struct perf_session *self, | 1168 | static int __perf_session__process_pipe_events(struct perf_session *self, |
@@ -1372,10 +1374,13 @@ more: | |||
1372 | "Processing events..."); | 1374 | "Processing events..."); |
1373 | } | 1375 | } |
1374 | 1376 | ||
1377 | err = 0; | ||
1378 | if (session_done()) | ||
1379 | goto out_err; | ||
1380 | |||
1375 | if (file_pos < file_size) | 1381 | if (file_pos < file_size) |
1376 | goto more; | 1382 | goto more; |
1377 | 1383 | ||
1378 | err = 0; | ||
1379 | /* do the final flush for ordered samples */ | 1384 | /* do the final flush for ordered samples */ |
1380 | session->ordered_samples.next_flush = ULLONG_MAX; | 1385 | session->ordered_samples.next_flush = ULLONG_MAX; |
1381 | err = flush_sample_queue(session, tool); | 1386 | err = flush_sample_queue(session, tool); |
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 3aa75fb2225f..04bf7373a7e5 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h | |||
@@ -124,4 +124,8 @@ int __perf_session__set_tracepoints_handlers(struct perf_session *session, | |||
124 | 124 | ||
125 | #define perf_session__set_tracepoints_handlers(session, array) \ | 125 | #define perf_session__set_tracepoints_handlers(session, array) \ |
126 | __perf_session__set_tracepoints_handlers(session, array, ARRAY_SIZE(array)) | 126 | __perf_session__set_tracepoints_handlers(session, array, ARRAY_SIZE(array)) |
127 | |||
128 | extern volatile int session_done; | ||
129 | |||
130 | #define session_done() (*(volatile int *)(&session_done)) | ||
127 | #endif /* __PERF_SESSION_H */ | 131 | #endif /* __PERF_SESSION_H */ |
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index a7b9ab557380..a9c829be5216 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c | |||
@@ -8,6 +8,22 @@ | |||
8 | #include "symbol.h" | 8 | #include "symbol.h" |
9 | #include "debug.h" | 9 | #include "debug.h" |
10 | 10 | ||
11 | #ifndef HAVE_ELF_GETPHDRNUM | ||
12 | static int elf_getphdrnum(Elf *elf, size_t *dst) | ||
13 | { | ||
14 | GElf_Ehdr gehdr; | ||
15 | GElf_Ehdr *ehdr; | ||
16 | |||
17 | ehdr = gelf_getehdr(elf, &gehdr); | ||
18 | if (!ehdr) | ||
19 | return -1; | ||
20 | |||
21 | *dst = ehdr->e_phnum; | ||
22 | |||
23 | return 0; | ||
24 | } | ||
25 | #endif | ||
26 | |||
11 | #ifndef NT_GNU_BUILD_ID | 27 | #ifndef NT_GNU_BUILD_ID |
12 | #define NT_GNU_BUILD_ID 3 | 28 | #define NT_GNU_BUILD_ID 3 |
13 | #endif | 29 | #endif |
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c index fe7a27d67d2b..e9e1c03f927d 100644 --- a/tools/perf/util/trace-event-parse.c +++ b/tools/perf/util/trace-event-parse.c | |||
@@ -186,7 +186,7 @@ void parse_proc_kallsyms(struct pevent *pevent, | |||
186 | char *next = NULL; | 186 | char *next = NULL; |
187 | char *addr_str; | 187 | char *addr_str; |
188 | char *mod; | 188 | char *mod; |
189 | char *fmt; | 189 | char *fmt = NULL; |
190 | 190 | ||
191 | line = strtok_r(file, "\n", &next); | 191 | line = strtok_r(file, "\n", &next); |
192 | while (line) { | 192 | while (line) { |