diff options
Diffstat (limited to 'tools/perf')
| -rw-r--r-- | tools/perf/Makefile | 4 | ||||
| -rw-r--r-- | tools/perf/builtin-annotate.c | 2 | ||||
| -rw-r--r-- | tools/perf/builtin-record.c | 10 | ||||
| -rw-r--r-- | tools/perf/builtin-report.c | 23 | ||||
| -rw-r--r-- | tools/perf/builtin-script.c | 1 | ||||
| -rw-r--r-- | tools/perf/builtin-test.c | 2 | ||||
| -rw-r--r-- | tools/perf/builtin-top.c | 37 | ||||
| -rwxr-xr-x | tools/perf/util/PERF-VERSION-GEN | 7 | ||||
| -rw-r--r-- | tools/perf/util/event.c | 31 | ||||
| -rw-r--r-- | tools/perf/util/event.h | 2 | ||||
| -rw-r--r-- | tools/perf/util/evlist.c | 68 | ||||
| -rw-r--r-- | tools/perf/util/evlist.h | 6 | ||||
| -rw-r--r-- | tools/perf/util/evsel.c | 26 | ||||
| -rw-r--r-- | tools/perf/util/evsel.h | 7 | ||||
| -rw-r--r-- | tools/perf/util/header.c | 8 | ||||
| -rw-r--r-- | tools/perf/util/include/linux/const.h | 1 | ||||
| -rw-r--r-- | tools/perf/util/python.c | 14 | ||||
| -rw-r--r-- | tools/perf/util/session.c | 12 | ||||
| -rw-r--r-- | tools/perf/util/symbol.c | 48 | ||||
| -rw-r--r-- | tools/perf/util/symbol.h | 3 | ||||
| -rw-r--r-- | tools/perf/util/trace-event-parse.c | 1 |
21 files changed, 230 insertions, 83 deletions
diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 1455413ec7a7..940257b5774e 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile | |||
| @@ -215,11 +215,13 @@ LIB_FILE=$(OUTPUT)libperf.a | |||
| 215 | LIB_H += ../../include/linux/perf_event.h | 215 | LIB_H += ../../include/linux/perf_event.h |
| 216 | LIB_H += ../../include/linux/rbtree.h | 216 | LIB_H += ../../include/linux/rbtree.h |
| 217 | LIB_H += ../../include/linux/list.h | 217 | LIB_H += ../../include/linux/list.h |
| 218 | LIB_H += ../../include/linux/const.h | ||
| 218 | LIB_H += ../../include/linux/hash.h | 219 | LIB_H += ../../include/linux/hash.h |
| 219 | LIB_H += ../../include/linux/stringify.h | 220 | LIB_H += ../../include/linux/stringify.h |
| 220 | LIB_H += util/include/linux/bitmap.h | 221 | LIB_H += util/include/linux/bitmap.h |
| 221 | LIB_H += util/include/linux/bitops.h | 222 | LIB_H += util/include/linux/bitops.h |
| 222 | LIB_H += util/include/linux/compiler.h | 223 | LIB_H += util/include/linux/compiler.h |
| 224 | LIB_H += util/include/linux/const.h | ||
| 223 | LIB_H += util/include/linux/ctype.h | 225 | LIB_H += util/include/linux/ctype.h |
| 224 | LIB_H += util/include/linux/kernel.h | 226 | LIB_H += util/include/linux/kernel.h |
| 225 | LIB_H += util/include/linux/list.h | 227 | LIB_H += util/include/linux/list.h |
| @@ -631,7 +633,7 @@ prefix_SQ = $(subst ','\'',$(prefix)) | |||
| 631 | 633 | ||
| 632 | SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH)) | 634 | SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH)) |
| 633 | 635 | ||
| 634 | LIBS = -Wl,--whole-archive $(PERFLIBS) -Wl,--no-whole-archive $(EXTLIBS) | 636 | LIBS = -Wl,--whole-archive $(PERFLIBS) -Wl,--no-whole-archive -Wl,--start-group $(EXTLIBS) -Wl,--end-group |
| 635 | 637 | ||
| 636 | ALL_CFLAGS += $(BASIC_CFLAGS) | 638 | ALL_CFLAGS += $(BASIC_CFLAGS) |
| 637 | ALL_CFLAGS += $(ARCH_CFLAGS) | 639 | ALL_CFLAGS += $(ARCH_CFLAGS) |
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index e18eb7ed30ae..7b139e1e7e86 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c | |||
| @@ -8,8 +8,6 @@ | |||
| 8 | #include "builtin.h" | 8 | #include "builtin.h" |
| 9 | 9 | ||
| 10 | #include "util/util.h" | 10 | #include "util/util.h" |
| 11 | |||
| 12 | #include "util/util.h" | ||
| 13 | #include "util/color.h" | 11 | #include "util/color.h" |
| 14 | #include <linux/list.h> | 12 | #include <linux/list.h> |
| 15 | #include "util/cache.h" | 13 | #include "util/cache.h" |
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 0974f957b8fa..8e2c85798185 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
| @@ -823,6 +823,16 @@ int cmd_record(int argc, const char **argv, const char *prefix __used) | |||
| 823 | 823 | ||
| 824 | symbol__init(); | 824 | symbol__init(); |
| 825 | 825 | ||
| 826 | if (symbol_conf.kptr_restrict) | ||
| 827 | pr_warning( | ||
| 828 | "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" | ||
| 829 | "check /proc/sys/kernel/kptr_restrict.\n\n" | ||
| 830 | "Samples in kernel functions may not be resolved if a suitable vmlinux\n" | ||
| 831 | "file is not found in the buildid cache or in the vmlinux path.\n\n" | ||
| 832 | "Samples in kernel modules won't be resolved at all.\n\n" | ||
| 833 | "If some relocation was applied (e.g. kexec) symbols may be misresolved\n" | ||
| 834 | "even with a suitable vmlinux or kallsyms file.\n\n"); | ||
| 835 | |||
| 826 | if (no_buildid_cache || no_buildid) | 836 | if (no_buildid_cache || no_buildid) |
| 827 | disable_buildid_cache(); | 837 | disable_buildid_cache(); |
| 828 | 838 | ||
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 498c6f70a747..287a173523a7 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
| @@ -116,6 +116,9 @@ static int process_sample_event(union perf_event *event, | |||
| 116 | if (al.filtered || (hide_unresolved && al.sym == NULL)) | 116 | if (al.filtered || (hide_unresolved && al.sym == NULL)) |
| 117 | return 0; | 117 | return 0; |
| 118 | 118 | ||
| 119 | if (al.map != NULL) | ||
| 120 | al.map->dso->hit = 1; | ||
| 121 | |||
| 119 | if (perf_session__add_hist_entry(session, &al, sample, evsel)) { | 122 | if (perf_session__add_hist_entry(session, &al, sample, evsel)) { |
| 120 | pr_debug("problem incrementing symbol period, skipping event\n"); | 123 | pr_debug("problem incrementing symbol period, skipping event\n"); |
| 121 | return -1; | 124 | return -1; |
| @@ -249,6 +252,8 @@ static int __cmd_report(void) | |||
| 249 | u64 nr_samples; | 252 | u64 nr_samples; |
| 250 | struct perf_session *session; | 253 | struct perf_session *session; |
| 251 | struct perf_evsel *pos; | 254 | struct perf_evsel *pos; |
| 255 | struct map *kernel_map; | ||
| 256 | struct kmap *kernel_kmap; | ||
| 252 | const char *help = "For a higher level overview, try: perf report --sort comm,dso"; | 257 | const char *help = "For a higher level overview, try: perf report --sort comm,dso"; |
| 253 | 258 | ||
| 254 | signal(SIGINT, sig_handler); | 259 | signal(SIGINT, sig_handler); |
| @@ -268,6 +273,24 @@ static int __cmd_report(void) | |||
| 268 | if (ret) | 273 | if (ret) |
| 269 | goto out_delete; | 274 | goto out_delete; |
| 270 | 275 | ||
| 276 | kernel_map = session->host_machine.vmlinux_maps[MAP__FUNCTION]; | ||
| 277 | kernel_kmap = map__kmap(kernel_map); | ||
| 278 | if (kernel_map == NULL || | ||
| 279 | (kernel_map->dso->hit && | ||
| 280 | (kernel_kmap->ref_reloc_sym == NULL || | ||
| 281 | kernel_kmap->ref_reloc_sym->addr == 0))) { | ||
| 282 | const struct dso *kdso = kernel_map->dso; | ||
| 283 | |||
| 284 | ui__warning( | ||
| 285 | "Kernel address maps (/proc/{kallsyms,modules}) were restricted.\n\n" | ||
| 286 | "Check /proc/sys/kernel/kptr_restrict before running 'perf record'.\n\n%s\n\n" | ||
| 287 | "Samples in kernel modules can't be resolved as well.\n\n", | ||
| 288 | RB_EMPTY_ROOT(&kdso->symbols[MAP__FUNCTION]) ? | ||
| 289 | "As no suitable kallsyms nor vmlinux was found, kernel samples\n" | ||
| 290 | "can't be resolved." : | ||
| 291 | "If some relocation was applied (e.g. kexec) symbols may be misresolved."); | ||
| 292 | } | ||
| 293 | |||
| 271 | if (dump_trace) { | 294 | if (dump_trace) { |
| 272 | perf_session__fprintf_nr_events(session, stdout); | 295 | perf_session__fprintf_nr_events(session, stdout); |
| 273 | goto out_delete; | 296 | goto out_delete; |
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 974f6d3f4e53..22747de7234b 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c | |||
| @@ -10,7 +10,6 @@ | |||
| 10 | #include "util/symbol.h" | 10 | #include "util/symbol.h" |
| 11 | #include "util/thread.h" | 11 | #include "util/thread.h" |
| 12 | #include "util/trace-event.h" | 12 | #include "util/trace-event.h" |
| 13 | #include "util/parse-options.h" | ||
| 14 | #include "util/util.h" | 13 | #include "util/util.h" |
| 15 | #include "util/evlist.h" | 14 | #include "util/evlist.h" |
| 16 | #include "util/evsel.h" | 15 | #include "util/evsel.h" |
diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c index b67186228c89..2da9162262b0 100644 --- a/tools/perf/builtin-test.c +++ b/tools/perf/builtin-test.c | |||
| @@ -474,7 +474,7 @@ static int test__basic_mmap(void) | |||
| 474 | unsigned int nr_events[nsyscalls], | 474 | unsigned int nr_events[nsyscalls], |
| 475 | expected_nr_events[nsyscalls], i, j; | 475 | expected_nr_events[nsyscalls], i, j; |
| 476 | struct perf_evsel *evsels[nsyscalls], *evsel; | 476 | struct perf_evsel *evsels[nsyscalls], *evsel; |
| 477 | int sample_size = perf_sample_size(attr.sample_type); | 477 | int sample_size = __perf_evsel__sample_size(attr.sample_type); |
| 478 | 478 | ||
| 479 | for (i = 0; i < nsyscalls; ++i) { | 479 | for (i = 0; i < nsyscalls; ++i) { |
| 480 | char name[64]; | 480 | char name[64]; |
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 2d7934e9de38..f2f3f4937aa2 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c | |||
| @@ -62,8 +62,6 @@ | |||
| 62 | #include <linux/unistd.h> | 62 | #include <linux/unistd.h> |
| 63 | #include <linux/types.h> | 63 | #include <linux/types.h> |
| 64 | 64 | ||
| 65 | #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) | ||
| 66 | |||
| 67 | static struct perf_top top = { | 65 | static struct perf_top top = { |
| 68 | .count_filter = 5, | 66 | .count_filter = 5, |
| 69 | .delay_secs = 2, | 67 | .delay_secs = 2, |
| @@ -82,6 +80,8 @@ static bool use_tui, use_stdio; | |||
| 82 | 80 | ||
| 83 | static int default_interval = 0; | 81 | static int default_interval = 0; |
| 84 | 82 | ||
| 83 | static bool kptr_restrict_warned; | ||
| 84 | static bool vmlinux_warned; | ||
| 85 | static bool inherit = false; | 85 | static bool inherit = false; |
| 86 | static int realtime_prio = 0; | 86 | static int realtime_prio = 0; |
| 87 | static bool group = false; | 87 | static bool group = false; |
| @@ -740,7 +740,22 @@ static void perf_event__process_sample(const union perf_event *event, | |||
| 740 | al.filtered) | 740 | al.filtered) |
| 741 | return; | 741 | return; |
| 742 | 742 | ||
| 743 | if (!kptr_restrict_warned && | ||
| 744 | symbol_conf.kptr_restrict && | ||
| 745 | al.cpumode == PERF_RECORD_MISC_KERNEL) { | ||
| 746 | ui__warning( | ||
| 747 | "Kernel address maps (/proc/{kallsyms,modules}) are restricted.\n\n" | ||
| 748 | "Check /proc/sys/kernel/kptr_restrict.\n\n" | ||
| 749 | "Kernel%s samples will not be resolved.\n", | ||
| 750 | !RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION]) ? | ||
| 751 | " modules" : ""); | ||
| 752 | if (use_browser <= 0) | ||
| 753 | sleep(5); | ||
| 754 | kptr_restrict_warned = true; | ||
| 755 | } | ||
| 756 | |||
| 743 | if (al.sym == NULL) { | 757 | if (al.sym == NULL) { |
| 758 | const char *msg = "Kernel samples will not be resolved.\n"; | ||
| 744 | /* | 759 | /* |
| 745 | * As we do lazy loading of symtabs we only will know if the | 760 | * As we do lazy loading of symtabs we only will know if the |
| 746 | * specified vmlinux file is invalid when we actually have a | 761 | * specified vmlinux file is invalid when we actually have a |
| @@ -752,12 +767,20 @@ static void perf_event__process_sample(const union perf_event *event, | |||
| 752 | * --hide-kernel-symbols, even if the user specifies an | 767 | * --hide-kernel-symbols, even if the user specifies an |
| 753 | * invalid --vmlinux ;-) | 768 | * invalid --vmlinux ;-) |
| 754 | */ | 769 | */ |
| 755 | if (al.map == machine->vmlinux_maps[MAP__FUNCTION] && | 770 | if (!kptr_restrict_warned && !vmlinux_warned && |
| 771 | al.map == machine->vmlinux_maps[MAP__FUNCTION] && | ||
| 756 | RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION])) { | 772 | RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION])) { |
| 757 | ui__warning("The %s file can't be used\n", | 773 | if (symbol_conf.vmlinux_name) { |
| 758 | symbol_conf.vmlinux_name); | 774 | ui__warning("The %s file can't be used.\n%s", |
| 759 | exit_browser(0); | 775 | symbol_conf.vmlinux_name, msg); |
| 760 | exit(1); | 776 | } else { |
| 777 | ui__warning("A vmlinux file was not found.\n%s", | ||
| 778 | msg); | ||
| 779 | } | ||
| 780 | |||
| 781 | if (use_browser <= 0) | ||
| 782 | sleep(5); | ||
| 783 | vmlinux_warned = true; | ||
| 761 | } | 784 | } |
| 762 | 785 | ||
| 763 | return; | 786 | return; |
diff --git a/tools/perf/util/PERF-VERSION-GEN b/tools/perf/util/PERF-VERSION-GEN index 26d4d3fd6deb..ad73300f7bac 100755 --- a/tools/perf/util/PERF-VERSION-GEN +++ b/tools/perf/util/PERF-VERSION-GEN | |||
| @@ -23,12 +23,7 @@ if test -d ../../.git -o -f ../../.git && | |||
| 23 | then | 23 | then |
| 24 | VN=$(echo "$VN" | sed -e 's/-/./g'); | 24 | VN=$(echo "$VN" | sed -e 's/-/./g'); |
| 25 | else | 25 | else |
| 26 | eval $(grep '^VERSION[[:space:]]*=' ../../Makefile|tr -d ' ') | 26 | VN=$(MAKEFLAGS= make -sC ../.. kernelversion) |
| 27 | eval $(grep '^PATCHLEVEL[[:space:]]*=' ../../Makefile|tr -d ' ') | ||
| 28 | eval $(grep '^SUBLEVEL[[:space:]]*=' ../../Makefile|tr -d ' ') | ||
| 29 | eval $(grep '^EXTRAVERSION[[:space:]]*=' ../../Makefile|tr -d ' ') | ||
| 30 | |||
| 31 | VN="${VERSION}.${PATCHLEVEL}.${SUBLEVEL}${EXTRAVERSION}" | ||
| 32 | fi | 27 | fi |
| 33 | 28 | ||
| 34 | VN=$(expr "$VN" : v*'\(.*\)') | 29 | VN=$(expr "$VN" : v*'\(.*\)') |
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 6635fcd11ca5..3c1b8a632101 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c | |||
| @@ -35,22 +35,6 @@ const char *perf_event__name(unsigned int id) | |||
| 35 | return perf_event__names[id]; | 35 | return perf_event__names[id]; |
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | int perf_sample_size(u64 sample_type) | ||
| 39 | { | ||
| 40 | u64 mask = sample_type & PERF_SAMPLE_MASK; | ||
| 41 | int size = 0; | ||
| 42 | int i; | ||
| 43 | |||
| 44 | for (i = 0; i < 64; i++) { | ||
| 45 | if (mask & (1ULL << i)) | ||
| 46 | size++; | ||
| 47 | } | ||
| 48 | |||
| 49 | size *= sizeof(u64); | ||
| 50 | |||
| 51 | return size; | ||
| 52 | } | ||
| 53 | |||
| 54 | static struct perf_sample synth_sample = { | 38 | static struct perf_sample synth_sample = { |
| 55 | .pid = -1, | 39 | .pid = -1, |
| 56 | .tid = -1, | 40 | .tid = -1, |
| @@ -553,9 +537,18 @@ static int perf_event__process_kernel_mmap(union perf_event *event, | |||
| 553 | goto out_problem; | 537 | goto out_problem; |
| 554 | 538 | ||
| 555 | perf_event__set_kernel_mmap_len(event, machine->vmlinux_maps); | 539 | perf_event__set_kernel_mmap_len(event, machine->vmlinux_maps); |
| 556 | perf_session__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, | 540 | |
| 557 | symbol_name, | 541 | /* |
| 558 | event->mmap.pgoff); | 542 | * Avoid using a zero address (kptr_restrict) for the ref reloc |
| 543 | * symbol. Effectively having zero here means that at record | ||
| 544 | * time /proc/sys/kernel/kptr_restrict was non zero. | ||
| 545 | */ | ||
| 546 | if (event->mmap.pgoff != 0) { | ||
| 547 | perf_session__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, | ||
| 548 | symbol_name, | ||
| 549 | event->mmap.pgoff); | ||
| 550 | } | ||
| 551 | |||
| 559 | if (machine__is_default_guest(machine)) { | 552 | if (machine__is_default_guest(machine)) { |
| 560 | /* | 553 | /* |
| 561 | * preload dso of guest kernel and modules | 554 | * preload dso of guest kernel and modules |
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index c08332871408..1d7f66488a88 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h | |||
| @@ -82,8 +82,6 @@ struct perf_sample { | |||
| 82 | struct ip_callchain *callchain; | 82 | struct ip_callchain *callchain; |
| 83 | }; | 83 | }; |
| 84 | 84 | ||
| 85 | int perf_sample_size(u64 sample_type); | ||
| 86 | |||
| 87 | #define BUILD_ID_SIZE 20 | 85 | #define BUILD_ID_SIZE 20 |
| 88 | 86 | ||
| 89 | struct build_id_event { | 87 | struct build_id_event { |
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 50aa34879c33..b021ea9265c3 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c | |||
| @@ -12,7 +12,6 @@ | |||
| 12 | #include "evlist.h" | 12 | #include "evlist.h" |
| 13 | #include "evsel.h" | 13 | #include "evsel.h" |
| 14 | #include "util.h" | 14 | #include "util.h" |
| 15 | #include "debug.h" | ||
| 16 | 15 | ||
| 17 | #include <sys/mman.h> | 16 | #include <sys/mman.h> |
| 18 | 17 | ||
| @@ -257,19 +256,15 @@ int perf_evlist__alloc_mmap(struct perf_evlist *evlist) | |||
| 257 | return evlist->mmap != NULL ? 0 : -ENOMEM; | 256 | return evlist->mmap != NULL ? 0 : -ENOMEM; |
| 258 | } | 257 | } |
| 259 | 258 | ||
| 260 | static int __perf_evlist__mmap(struct perf_evlist *evlist, struct perf_evsel *evsel, | 259 | static int __perf_evlist__mmap(struct perf_evlist *evlist, |
| 261 | int idx, int prot, int mask, int fd) | 260 | int idx, int prot, int mask, int fd) |
| 262 | { | 261 | { |
| 263 | evlist->mmap[idx].prev = 0; | 262 | evlist->mmap[idx].prev = 0; |
| 264 | evlist->mmap[idx].mask = mask; | 263 | evlist->mmap[idx].mask = mask; |
| 265 | evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, prot, | 264 | evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, prot, |
| 266 | MAP_SHARED, fd, 0); | 265 | MAP_SHARED, fd, 0); |
| 267 | if (evlist->mmap[idx].base == MAP_FAILED) { | 266 | if (evlist->mmap[idx].base == MAP_FAILED) |
| 268 | if (evlist->cpus->map[idx] == -1 && evsel->attr.inherit) | ||
| 269 | ui__warning("Inherit is not allowed on per-task " | ||
| 270 | "events using mmap.\n"); | ||
| 271 | return -1; | 267 | return -1; |
| 272 | } | ||
| 273 | 268 | ||
| 274 | perf_evlist__add_pollfd(evlist, fd); | 269 | perf_evlist__add_pollfd(evlist, fd); |
| 275 | return 0; | 270 | return 0; |
| @@ -289,7 +284,7 @@ static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, int prot, int m | |||
| 289 | 284 | ||
| 290 | if (output == -1) { | 285 | if (output == -1) { |
| 291 | output = fd; | 286 | output = fd; |
| 292 | if (__perf_evlist__mmap(evlist, evsel, cpu, | 287 | if (__perf_evlist__mmap(evlist, cpu, |
| 293 | prot, mask, output) < 0) | 288 | prot, mask, output) < 0) |
| 294 | goto out_unmap; | 289 | goto out_unmap; |
| 295 | } else { | 290 | } else { |
| @@ -329,7 +324,7 @@ static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, int prot, in | |||
| 329 | 324 | ||
| 330 | if (output == -1) { | 325 | if (output == -1) { |
| 331 | output = fd; | 326 | output = fd; |
| 332 | if (__perf_evlist__mmap(evlist, evsel, thread, | 327 | if (__perf_evlist__mmap(evlist, thread, |
| 333 | prot, mask, output) < 0) | 328 | prot, mask, output) < 0) |
| 334 | goto out_unmap; | 329 | goto out_unmap; |
| 335 | } else { | 330 | } else { |
| @@ -460,33 +455,46 @@ int perf_evlist__set_filters(struct perf_evlist *evlist) | |||
| 460 | return 0; | 455 | return 0; |
| 461 | } | 456 | } |
| 462 | 457 | ||
| 463 | u64 perf_evlist__sample_type(struct perf_evlist *evlist) | 458 | bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist) |
| 464 | { | 459 | { |
| 465 | struct perf_evsel *pos; | 460 | struct perf_evsel *pos, *first; |
| 466 | u64 type = 0; | 461 | |
| 467 | 462 | pos = first = list_entry(evlist->entries.next, struct perf_evsel, node); | |
| 468 | list_for_each_entry(pos, &evlist->entries, node) { | 463 | |
| 469 | if (!type) | 464 | list_for_each_entry_continue(pos, &evlist->entries, node) { |
| 470 | type = pos->attr.sample_type; | 465 | if (first->attr.sample_type != pos->attr.sample_type) |
| 471 | else if (type != pos->attr.sample_type) | 466 | return false; |
| 472 | die("non matching sample_type"); | ||
| 473 | } | 467 | } |
| 474 | 468 | ||
| 475 | return type; | 469 | return true; |
| 476 | } | 470 | } |
| 477 | 471 | ||
| 478 | bool perf_evlist__sample_id_all(const struct perf_evlist *evlist) | 472 | u64 perf_evlist__sample_type(const struct perf_evlist *evlist) |
| 473 | { | ||
| 474 | struct perf_evsel *first; | ||
| 475 | |||
| 476 | first = list_entry(evlist->entries.next, struct perf_evsel, node); | ||
| 477 | return first->attr.sample_type; | ||
| 478 | } | ||
| 479 | |||
| 480 | bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist) | ||
| 479 | { | 481 | { |
| 480 | bool value = false, first = true; | 482 | struct perf_evsel *pos, *first; |
| 481 | struct perf_evsel *pos; | 483 | |
| 482 | 484 | pos = first = list_entry(evlist->entries.next, struct perf_evsel, node); | |
| 483 | list_for_each_entry(pos, &evlist->entries, node) { | 485 | |
| 484 | if (first) { | 486 | list_for_each_entry_continue(pos, &evlist->entries, node) { |
| 485 | value = pos->attr.sample_id_all; | 487 | if (first->attr.sample_id_all != pos->attr.sample_id_all) |
| 486 | first = false; | 488 | return false; |
| 487 | } else if (value != pos->attr.sample_id_all) | ||
| 488 | die("non matching sample_id_all"); | ||
| 489 | } | 489 | } |
| 490 | 490 | ||
| 491 | return value; | 491 | return true; |
| 492 | } | ||
| 493 | |||
| 494 | bool perf_evlist__sample_id_all(const struct perf_evlist *evlist) | ||
| 495 | { | ||
| 496 | struct perf_evsel *first; | ||
| 497 | |||
| 498 | first = list_entry(evlist->entries.next, struct perf_evsel, node); | ||
| 499 | return first->attr.sample_id_all; | ||
| 492 | } | 500 | } |
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 0a1ef1f051f0..b2b862374f37 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h | |||
| @@ -66,7 +66,9 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, pid_t target_pid, | |||
| 66 | void perf_evlist__delete_maps(struct perf_evlist *evlist); | 66 | void perf_evlist__delete_maps(struct perf_evlist *evlist); |
| 67 | int perf_evlist__set_filters(struct perf_evlist *evlist); | 67 | int perf_evlist__set_filters(struct perf_evlist *evlist); |
| 68 | 68 | ||
| 69 | u64 perf_evlist__sample_type(struct perf_evlist *evlist); | 69 | u64 perf_evlist__sample_type(const struct perf_evlist *evlist); |
| 70 | bool perf_evlist__sample_id_all(const struct perf_evlist *evlist); | 70 | bool perf_evlist__sample_id_all(const const struct perf_evlist *evlist); |
| 71 | 71 | ||
| 72 | bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist); | ||
| 73 | bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist); | ||
| 72 | #endif /* __PERF_EVLIST_H */ | 74 | #endif /* __PERF_EVLIST_H */ |
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index ee0fe0dffa71..0239eb87b232 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c | |||
| @@ -15,6 +15,22 @@ | |||
| 15 | 15 | ||
| 16 | #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) | 16 | #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) |
| 17 | 17 | ||
| 18 | int __perf_evsel__sample_size(u64 sample_type) | ||
| 19 | { | ||
| 20 | u64 mask = sample_type & PERF_SAMPLE_MASK; | ||
| 21 | int size = 0; | ||
| 22 | int i; | ||
| 23 | |||
| 24 | for (i = 0; i < 64; i++) { | ||
| 25 | if (mask & (1ULL << i)) | ||
| 26 | size++; | ||
| 27 | } | ||
| 28 | |||
| 29 | size *= sizeof(u64); | ||
| 30 | |||
| 31 | return size; | ||
| 32 | } | ||
| 33 | |||
| 18 | void perf_evsel__init(struct perf_evsel *evsel, | 34 | void perf_evsel__init(struct perf_evsel *evsel, |
| 19 | struct perf_event_attr *attr, int idx) | 35 | struct perf_event_attr *attr, int idx) |
| 20 | { | 36 | { |
| @@ -35,7 +51,17 @@ struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx) | |||
| 35 | 51 | ||
| 36 | int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) | 52 | int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) |
| 37 | { | 53 | { |
| 54 | int cpu, thread; | ||
| 38 | evsel->fd = xyarray__new(ncpus, nthreads, sizeof(int)); | 55 | evsel->fd = xyarray__new(ncpus, nthreads, sizeof(int)); |
| 56 | |||
| 57 | if (evsel->fd) { | ||
| 58 | for (cpu = 0; cpu < ncpus; cpu++) { | ||
| 59 | for (thread = 0; thread < nthreads; thread++) { | ||
| 60 | FD(evsel, cpu, thread) = -1; | ||
| 61 | } | ||
| 62 | } | ||
| 63 | } | ||
| 64 | |||
| 39 | return evsel->fd != NULL ? 0 : -ENOMEM; | 65 | return evsel->fd != NULL ? 0 : -ENOMEM; |
| 40 | } | 66 | } |
| 41 | 67 | ||
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index f79bb2c09a6c..7e9366e4490b 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h | |||
| @@ -149,4 +149,11 @@ static inline int perf_evsel__read_scaled(struct perf_evsel *evsel, | |||
| 149 | return __perf_evsel__read(evsel, ncpus, nthreads, true); | 149 | return __perf_evsel__read(evsel, ncpus, nthreads, true); |
| 150 | } | 150 | } |
| 151 | 151 | ||
| 152 | int __perf_evsel__sample_size(u64 sample_type); | ||
| 153 | |||
| 154 | static inline int perf_evsel__sample_size(struct perf_evsel *evsel) | ||
| 155 | { | ||
| 156 | return __perf_evsel__sample_size(evsel->attr.sample_type); | ||
| 157 | } | ||
| 158 | |||
| 152 | #endif /* __PERF_EVSEL_H */ | 159 | #endif /* __PERF_EVSEL_H */ |
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 0717bebc7649..afb0849fe530 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
| @@ -193,9 +193,13 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, | |||
| 193 | *linkname = malloc(size), *targetname; | 193 | *linkname = malloc(size), *targetname; |
| 194 | int len, err = -1; | 194 | int len, err = -1; |
| 195 | 195 | ||
| 196 | if (is_kallsyms) | 196 | if (is_kallsyms) { |
| 197 | if (symbol_conf.kptr_restrict) { | ||
| 198 | pr_debug("Not caching a kptr_restrict'ed /proc/kallsyms\n"); | ||
| 199 | return 0; | ||
| 200 | } | ||
| 197 | realname = (char *)name; | 201 | realname = (char *)name; |
| 198 | else | 202 | } else |
| 199 | realname = realpath(name, NULL); | 203 | realname = realpath(name, NULL); |
| 200 | 204 | ||
| 201 | if (realname == NULL || filename == NULL || linkname == NULL) | 205 | if (realname == NULL || filename == NULL || linkname == NULL) |
diff --git a/tools/perf/util/include/linux/const.h b/tools/perf/util/include/linux/const.h new file mode 100644 index 000000000000..1b476c9ae649 --- /dev/null +++ b/tools/perf/util/include/linux/const.h | |||
| @@ -0,0 +1 @@ | |||
| #include "../../../../include/linux/const.h" | |||
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index 69436b3200a4..a9ac0504aabd 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c | |||
| @@ -674,7 +674,7 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist, | |||
| 674 | struct perf_evlist *evlist = &pevlist->evlist; | 674 | struct perf_evlist *evlist = &pevlist->evlist; |
| 675 | union perf_event *event; | 675 | union perf_event *event; |
| 676 | int sample_id_all = 1, cpu; | 676 | int sample_id_all = 1, cpu; |
| 677 | static char *kwlist[] = {"sample_id_all", NULL, NULL}; | 677 | static char *kwlist[] = {"cpu", "sample_id_all", NULL, NULL}; |
| 678 | int err; | 678 | int err; |
| 679 | 679 | ||
| 680 | if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|i", kwlist, | 680 | if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|i", kwlist, |
| @@ -692,16 +692,14 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist, | |||
| 692 | 692 | ||
| 693 | first = list_entry(evlist->entries.next, struct perf_evsel, node); | 693 | first = list_entry(evlist->entries.next, struct perf_evsel, node); |
| 694 | err = perf_event__parse_sample(event, first->attr.sample_type, | 694 | err = perf_event__parse_sample(event, first->attr.sample_type, |
| 695 | perf_sample_size(first->attr.sample_type), | 695 | perf_evsel__sample_size(first), |
| 696 | sample_id_all, &pevent->sample); | 696 | sample_id_all, &pevent->sample); |
| 697 | if (err) { | 697 | if (err) |
| 698 | pr_err("Can't parse sample, err = %d\n", err); | 698 | return PyErr_Format(PyExc_OSError, |
| 699 | goto end; | 699 | "perf: can't parse sample, err=%d", err); |
| 700 | } | ||
| 701 | |||
| 702 | return pyevent; | 700 | return pyevent; |
| 703 | } | 701 | } |
| 704 | end: | 702 | |
| 705 | Py_INCREF(Py_None); | 703 | Py_INCREF(Py_None); |
| 706 | return Py_None; | 704 | return Py_None; |
| 707 | } | 705 | } |
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 64500fc78799..f5a8fbdd3f76 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
| @@ -58,6 +58,16 @@ static int perf_session__open(struct perf_session *self, bool force) | |||
| 58 | goto out_close; | 58 | goto out_close; |
| 59 | } | 59 | } |
| 60 | 60 | ||
| 61 | if (!perf_evlist__valid_sample_type(self->evlist)) { | ||
| 62 | pr_err("non matching sample_type"); | ||
| 63 | goto out_close; | ||
| 64 | } | ||
| 65 | |||
| 66 | if (!perf_evlist__valid_sample_id_all(self->evlist)) { | ||
| 67 | pr_err("non matching sample_id_all"); | ||
| 68 | goto out_close; | ||
| 69 | } | ||
| 70 | |||
| 61 | self->size = input_stat.st_size; | 71 | self->size = input_stat.st_size; |
| 62 | return 0; | 72 | return 0; |
| 63 | 73 | ||
| @@ -97,7 +107,7 @@ out: | |||
| 97 | void perf_session__update_sample_type(struct perf_session *self) | 107 | void perf_session__update_sample_type(struct perf_session *self) |
| 98 | { | 108 | { |
| 99 | self->sample_type = perf_evlist__sample_type(self->evlist); | 109 | self->sample_type = perf_evlist__sample_type(self->evlist); |
| 100 | self->sample_size = perf_sample_size(self->sample_type); | 110 | self->sample_size = __perf_evsel__sample_size(self->sample_type); |
| 101 | self->sample_id_all = perf_evlist__sample_id_all(self->evlist); | 111 | self->sample_id_all = perf_evlist__sample_id_all(self->evlist); |
| 102 | perf_session__id_header_size(self); | 112 | perf_session__id_header_size(self); |
| 103 | } | 113 | } |
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 516876dfbe52..eec196329fd9 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
| @@ -676,9 +676,30 @@ discard_symbol: rb_erase(&pos->rb_node, root); | |||
| 676 | return count + moved; | 676 | return count + moved; |
| 677 | } | 677 | } |
| 678 | 678 | ||
| 679 | static bool symbol__restricted_filename(const char *filename, | ||
| 680 | const char *restricted_filename) | ||
| 681 | { | ||
| 682 | bool restricted = false; | ||
| 683 | |||
| 684 | if (symbol_conf.kptr_restrict) { | ||
| 685 | char *r = realpath(filename, NULL); | ||
| 686 | |||
| 687 | if (r != NULL) { | ||
| 688 | restricted = strcmp(r, restricted_filename) == 0; | ||
| 689 | free(r); | ||
| 690 | return restricted; | ||
| 691 | } | ||
| 692 | } | ||
| 693 | |||
| 694 | return restricted; | ||
| 695 | } | ||
| 696 | |||
| 679 | int dso__load_kallsyms(struct dso *dso, const char *filename, | 697 | int dso__load_kallsyms(struct dso *dso, const char *filename, |
| 680 | struct map *map, symbol_filter_t filter) | 698 | struct map *map, symbol_filter_t filter) |
| 681 | { | 699 | { |
| 700 | if (symbol__restricted_filename(filename, "/proc/kallsyms")) | ||
| 701 | return -1; | ||
| 702 | |||
| 682 | if (dso__load_all_kallsyms(dso, filename, map) < 0) | 703 | if (dso__load_all_kallsyms(dso, filename, map) < 0) |
| 683 | return -1; | 704 | return -1; |
| 684 | 705 | ||
| @@ -1790,6 +1811,9 @@ static int machine__create_modules(struct machine *machine) | |||
| 1790 | modules = path; | 1811 | modules = path; |
| 1791 | } | 1812 | } |
| 1792 | 1813 | ||
| 1814 | if (symbol__restricted_filename(path, "/proc/modules")) | ||
| 1815 | return -1; | ||
| 1816 | |||
| 1793 | file = fopen(modules, "r"); | 1817 | file = fopen(modules, "r"); |
| 1794 | if (file == NULL) | 1818 | if (file == NULL) |
| 1795 | return -1; | 1819 | return -1; |
| @@ -2239,6 +2263,9 @@ static u64 machine__get_kernel_start_addr(struct machine *machine) | |||
| 2239 | } | 2263 | } |
| 2240 | } | 2264 | } |
| 2241 | 2265 | ||
| 2266 | if (symbol__restricted_filename(filename, "/proc/kallsyms")) | ||
| 2267 | return 0; | ||
| 2268 | |||
| 2242 | if (kallsyms__parse(filename, &args, symbol__in_kernel) <= 0) | 2269 | if (kallsyms__parse(filename, &args, symbol__in_kernel) <= 0) |
| 2243 | return 0; | 2270 | return 0; |
| 2244 | 2271 | ||
| @@ -2410,6 +2437,25 @@ static int setup_list(struct strlist **list, const char *list_str, | |||
| 2410 | return 0; | 2437 | return 0; |
| 2411 | } | 2438 | } |
| 2412 | 2439 | ||
| 2440 | static bool symbol__read_kptr_restrict(void) | ||
| 2441 | { | ||
| 2442 | bool value = false; | ||
| 2443 | |||
| 2444 | if (geteuid() != 0) { | ||
| 2445 | FILE *fp = fopen("/proc/sys/kernel/kptr_restrict", "r"); | ||
| 2446 | if (fp != NULL) { | ||
| 2447 | char line[8]; | ||
| 2448 | |||
| 2449 | if (fgets(line, sizeof(line), fp) != NULL) | ||
| 2450 | value = atoi(line) != 0; | ||
| 2451 | |||
| 2452 | fclose(fp); | ||
| 2453 | } | ||
| 2454 | } | ||
| 2455 | |||
| 2456 | return value; | ||
| 2457 | } | ||
| 2458 | |||
| 2413 | int symbol__init(void) | 2459 | int symbol__init(void) |
| 2414 | { | 2460 | { |
| 2415 | const char *symfs; | 2461 | const char *symfs; |
| @@ -2456,6 +2502,8 @@ int symbol__init(void) | |||
| 2456 | if (symfs != symbol_conf.symfs) | 2502 | if (symfs != symbol_conf.symfs) |
| 2457 | free((void *)symfs); | 2503 | free((void *)symfs); |
| 2458 | 2504 | ||
| 2505 | symbol_conf.kptr_restrict = symbol__read_kptr_restrict(); | ||
| 2506 | |||
| 2459 | symbol_conf.initialized = true; | 2507 | symbol_conf.initialized = true; |
| 2460 | return 0; | 2508 | return 0; |
| 2461 | 2509 | ||
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 242de0101a86..325ee36a9d29 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h | |||
| @@ -75,7 +75,8 @@ struct symbol_conf { | |||
| 75 | use_callchain, | 75 | use_callchain, |
| 76 | exclude_other, | 76 | exclude_other, |
| 77 | show_cpu_utilization, | 77 | show_cpu_utilization, |
| 78 | initialized; | 78 | initialized, |
| 79 | kptr_restrict; | ||
| 79 | const char *vmlinux_name, | 80 | const char *vmlinux_name, |
| 80 | *kallsyms_name, | 81 | *kallsyms_name, |
| 81 | *source_prefix, | 82 | *source_prefix, |
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c index 1e88485c16a0..0a7ed5b5e281 100644 --- a/tools/perf/util/trace-event-parse.c +++ b/tools/perf/util/trace-event-parse.c | |||
| @@ -2187,6 +2187,7 @@ static const struct flag flags[] = { | |||
| 2187 | { "TASKLET_SOFTIRQ", 6 }, | 2187 | { "TASKLET_SOFTIRQ", 6 }, |
| 2188 | { "SCHED_SOFTIRQ", 7 }, | 2188 | { "SCHED_SOFTIRQ", 7 }, |
| 2189 | { "HRTIMER_SOFTIRQ", 8 }, | 2189 | { "HRTIMER_SOFTIRQ", 8 }, |
| 2190 | { "RCU_SOFTIRQ", 9 }, | ||
| 2190 | 2191 | ||
| 2191 | { "HRTIMER_NORESTART", 0 }, | 2192 | { "HRTIMER_NORESTART", 0 }, |
| 2192 | { "HRTIMER_RESTART", 1 }, | 2193 | { "HRTIMER_RESTART", 1 }, |
