diff options
author | Ingo Molnar <mingo@kernel.org> | 2014-09-19 01:13:36 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2014-09-19 01:13:36 -0400 |
commit | 4f7cf3a992cc0c15c97d2e34ea08a1cb7faace39 (patch) | |
tree | f65a2e146bbb838b882128e17d06a1b34e8fe63c | |
parent | c88f2096136416b261bd3647cc260935f6e95805 (diff) | |
parent | e5685730e2c620f97bc12380e9370e857e5bd7a7 (diff) |
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:
User visible changes:
o Add +field argument support for --sort option (Jiri Olsa)
o Do not access kallsyms when analyzing user binaries with 'probe' (Masami Hiramatsu)
o Ignore stripped vmlinux and fallback to kallsyms (Anton Blanchard)
o Add path to Ubuntu kernel debuginfo file (Anton Blanchard)
o Disable kernel symbol demangling by default (Avi Kivity)
Infrastructure changes:
o More intel PT prep work, from Adrian Hunter, including:
- Let a user specify a PMU event without any config terms
- Add perf-with-kcore script
- Let default config be defined for a PMU
- Add perf_pmu__scan_file()
o "perf kvm stat report" improvements by Alexander Yarygin:
o Save pid string in opts.target.pid
o Enable the target.system_wide flag
o Unify the title bar output
o Fix build issue on powerpc when DWARF support is disabled (Anton Blanchard)
o Allow to specify lib compile variable for spec usage (Jiri Olsa)
o Fix build on ARM (Stephane Eranian)
o Fix build on powerpc when DWARF support is disabled (Anton Blanchard)
o Don't include sys/poll.h directly (Arnaldo Carvalho de Melo)
o Use ring buffer consume method to look like other tools (Arnaldo Carvalho de Melo)
o Allow to specify lib compile variable for spec usage (Jiri Olsa)
o Fix GNU-only grep usage in Makefile (John Spencer)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
31 files changed, 487 insertions, 60 deletions
diff --git a/tools/perf/.gitignore b/tools/perf/.gitignore index 782d86e961b9..717221e98450 100644 --- a/tools/perf/.gitignore +++ b/tools/perf/.gitignore | |||
@@ -15,6 +15,7 @@ perf.data | |||
15 | perf.data.old | 15 | perf.data.old |
16 | output.svg | 16 | output.svg |
17 | perf-archive | 17 | perf-archive |
18 | perf-with-kcore | ||
18 | tags | 19 | tags |
19 | TAGS | 20 | TAGS |
20 | cscope* | 21 | cscope* |
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt index 1513935c399b..aaa869be3dc1 100644 --- a/tools/perf/Documentation/perf-probe.txt +++ b/tools/perf/Documentation/perf-probe.txt | |||
@@ -104,6 +104,9 @@ OPTIONS | |||
104 | Specify path to the executable or shared library file for user | 104 | Specify path to the executable or shared library file for user |
105 | space tracing. Can also be used with --funcs option. | 105 | space tracing. Can also be used with --funcs option. |
106 | 106 | ||
107 | --demangle-kernel:: | ||
108 | Demangle kernel symbols. | ||
109 | |||
107 | In absence of -m/-x options, perf probe checks if the first argument after | 110 | In absence of -m/-x options, perf probe checks if the first argument after |
108 | the options is an absolute path name. If its an absolute path, perf probe | 111 | the options is an absolute path name. If its an absolute path, perf probe |
109 | uses it as a target module/target user space binary to probe. | 112 | uses it as a target module/target user space binary to probe. |
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt index d561e0214f52..0927bf4e6c2a 100644 --- a/tools/perf/Documentation/perf-report.txt +++ b/tools/perf/Documentation/perf-report.txt | |||
@@ -276,6 +276,9 @@ OPTIONS | |||
276 | Demangle symbol names to human readable form. It's enabled by default, | 276 | Demangle symbol names to human readable form. It's enabled by default, |
277 | disable with --no-demangle. | 277 | disable with --no-demangle. |
278 | 278 | ||
279 | --demangle-kernel:: | ||
280 | Demangle kernel symbol names to human readable form (for C++ kernels). | ||
281 | |||
279 | --mem-mode:: | 282 | --mem-mode:: |
280 | Use the data addresses of samples in addition to instruction addresses | 283 | Use the data addresses of samples in addition to instruction addresses |
281 | to build the histograms. To generate meaningful output, the perf.data | 284 | to build the histograms. To generate meaningful output, the perf.data |
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt index 28fdee394880..3265b1070518 100644 --- a/tools/perf/Documentation/perf-top.txt +++ b/tools/perf/Documentation/perf-top.txt | |||
@@ -98,6 +98,9 @@ Default is to monitor all CPUS. | |||
98 | --hide_user_symbols:: | 98 | --hide_user_symbols:: |
99 | Hide user symbols. | 99 | Hide user symbols. |
100 | 100 | ||
101 | --demangle-kernel:: | ||
102 | Demangle kernel symbols. | ||
103 | |||
101 | -D:: | 104 | -D:: |
102 | --dump-symtab:: | 105 | --dump-symtab:: |
103 | Dump the symbol table used for profiling. | 106 | Dump the symbol table used for profiling. |
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index 95e832b1bc3c..171f4e65601b 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf | |||
@@ -126,6 +126,7 @@ PYRF_OBJS = | |||
126 | SCRIPT_SH = | 126 | SCRIPT_SH = |
127 | 127 | ||
128 | SCRIPT_SH += perf-archive.sh | 128 | SCRIPT_SH += perf-archive.sh |
129 | SCRIPT_SH += perf-with-kcore.sh | ||
129 | 130 | ||
130 | grep-libs = $(filter -l%,$(1)) | 131 | grep-libs = $(filter -l%,$(1)) |
131 | strip-libs = $(filter-out -l%,$(1)) | 132 | strip-libs = $(filter-out -l%,$(1)) |
@@ -878,6 +879,8 @@ install-bin: all install-gtk | |||
878 | $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)' | 879 | $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)' |
879 | $(call QUIET_INSTALL, perf-archive) \ | 880 | $(call QUIET_INSTALL, perf-archive) \ |
880 | $(INSTALL) $(OUTPUT)perf-archive -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)' | 881 | $(INSTALL) $(OUTPUT)perf-archive -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)' |
882 | $(call QUIET_INSTALL, perf-with-kcore) \ | ||
883 | $(INSTALL) $(OUTPUT)perf-with-kcore -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)' | ||
881 | ifndef NO_LIBPERL | 884 | ifndef NO_LIBPERL |
882 | $(call QUIET_INSTALL, perl-scripts) \ | 885 | $(call QUIET_INSTALL, perl-scripts) \ |
883 | $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'; \ | 886 | $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'; \ |
@@ -923,7 +926,7 @@ config-clean: | |||
923 | @$(MAKE) -C config/feature-checks clean >/dev/null | 926 | @$(MAKE) -C config/feature-checks clean >/dev/null |
924 | 927 | ||
925 | clean: $(LIBTRACEEVENT)-clean $(LIBAPIKFS)-clean config-clean | 928 | clean: $(LIBTRACEEVENT)-clean $(LIBAPIKFS)-clean config-clean |
926 | $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf.o $(LANG_BINDINGS) $(GTK_OBJS) | 929 | $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(OUTPUT)perf.o $(LANG_BINDINGS) $(GTK_OBJS) |
927 | $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf | 930 | $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf |
928 | $(call QUIET_CLEAN, core-gen) $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS $(OUTPUT)PERF-FEATURES $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex* | 931 | $(call QUIET_CLEAN, core-gen) $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS $(OUTPUT)PERF-FEATURES $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex* |
929 | $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean | 932 | $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean |
diff --git a/tools/perf/arch/arm/tests/dwarf-unwind.c b/tools/perf/arch/arm/tests/dwarf-unwind.c index 9f870d27cb39..62eff847f91c 100644 --- a/tools/perf/arch/arm/tests/dwarf-unwind.c +++ b/tools/perf/arch/arm/tests/dwarf-unwind.c | |||
@@ -3,6 +3,7 @@ | |||
3 | #include "thread.h" | 3 | #include "thread.h" |
4 | #include "map.h" | 4 | #include "map.h" |
5 | #include "event.h" | 5 | #include "event.h" |
6 | #include "debug.h" | ||
6 | #include "tests/tests.h" | 7 | #include "tests/tests.h" |
7 | 8 | ||
8 | #define STACK_SIZE 8192 | 9 | #define STACK_SIZE 8192 |
diff --git a/tools/perf/arch/arm/util/unwind-libunwind.c b/tools/perf/arch/arm/util/unwind-libunwind.c index 729ed69a6664..62c397ed3d97 100644 --- a/tools/perf/arch/arm/util/unwind-libunwind.c +++ b/tools/perf/arch/arm/util/unwind-libunwind.c | |||
@@ -3,6 +3,7 @@ | |||
3 | #include <libunwind.h> | 3 | #include <libunwind.h> |
4 | #include "perf_regs.h" | 4 | #include "perf_regs.h" |
5 | #include "../../util/unwind.h" | 5 | #include "../../util/unwind.h" |
6 | #include "../../util/debug.h" | ||
6 | 7 | ||
7 | int libunwind__arch_reg_id(int regnum) | 8 | int libunwind__arch_reg_id(int regnum) |
8 | { | 9 | { |
diff --git a/tools/perf/arch/powerpc/Makefile b/tools/perf/arch/powerpc/Makefile index b92219b1900d..6f7782bea5dd 100644 --- a/tools/perf/arch/powerpc/Makefile +++ b/tools/perf/arch/powerpc/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | ifndef NO_DWARF | 1 | ifndef NO_DWARF |
2 | PERF_HAVE_DWARF_REGS := 1 | 2 | PERF_HAVE_DWARF_REGS := 1 |
3 | LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o | 3 | LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o |
4 | LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/skip-callchain-idx.o | ||
4 | endif | 5 | endif |
5 | LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o | 6 | LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o |
6 | LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/skip-callchain-idx.o | ||
diff --git a/tools/perf/bench/sched-messaging.c b/tools/perf/bench/sched-messaging.c index 52a56599a543..d7f281c2828d 100644 --- a/tools/perf/bench/sched-messaging.c +++ b/tools/perf/bench/sched-messaging.c | |||
@@ -26,7 +26,7 @@ | |||
26 | #include <sys/socket.h> | 26 | #include <sys/socket.h> |
27 | #include <sys/wait.h> | 27 | #include <sys/wait.h> |
28 | #include <sys/time.h> | 28 | #include <sys/time.h> |
29 | #include <sys/poll.h> | 29 | #include <poll.h> |
30 | #include <limits.h> | 30 | #include <limits.h> |
31 | #include <err.h> | 31 | #include <err.h> |
32 | 32 | ||
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index 1a4ef9cd9d5f..f5d3ae483110 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c | |||
@@ -543,14 +543,12 @@ static void print_vcpu_info(struct perf_kvm_stat *kvm) | |||
543 | 543 | ||
544 | pr_info("Analyze events for "); | 544 | pr_info("Analyze events for "); |
545 | 545 | ||
546 | if (kvm->live) { | 546 | if (kvm->opts.target.system_wide) |
547 | if (kvm->opts.target.system_wide) | 547 | pr_info("all VMs, "); |
548 | pr_info("all VMs, "); | 548 | else if (kvm->opts.target.pid) |
549 | else if (kvm->opts.target.pid) | 549 | pr_info("pid(s) %s, ", kvm->opts.target.pid); |
550 | pr_info("pid(s) %s, ", kvm->opts.target.pid); | 550 | else |
551 | else | 551 | pr_info("dazed and confused on what is monitored, "); |
552 | pr_info("dazed and confused on what is monitored, "); | ||
553 | } | ||
554 | 552 | ||
555 | if (vcpu == -1) | 553 | if (vcpu == -1) |
556 | pr_info("all VCPUs:\n\n"); | 554 | pr_info("all VCPUs:\n\n"); |
@@ -1085,8 +1083,8 @@ static int read_events(struct perf_kvm_stat *kvm) | |||
1085 | 1083 | ||
1086 | static int parse_target_str(struct perf_kvm_stat *kvm) | 1084 | static int parse_target_str(struct perf_kvm_stat *kvm) |
1087 | { | 1085 | { |
1088 | if (kvm->pid_str) { | 1086 | if (kvm->opts.target.pid) { |
1089 | kvm->pid_list = intlist__new(kvm->pid_str); | 1087 | kvm->pid_list = intlist__new(kvm->opts.target.pid); |
1090 | if (kvm->pid_list == NULL) { | 1088 | if (kvm->pid_list == NULL) { |
1091 | pr_err("Error parsing process id string\n"); | 1089 | pr_err("Error parsing process id string\n"); |
1092 | return -EINVAL; | 1090 | return -EINVAL; |
@@ -1188,7 +1186,7 @@ kvm_events_report(struct perf_kvm_stat *kvm, int argc, const char **argv) | |||
1188 | OPT_STRING('k', "key", &kvm->sort_key, "sort-key", | 1186 | OPT_STRING('k', "key", &kvm->sort_key, "sort-key", |
1189 | "key for sorting: sample(sort by samples number)" | 1187 | "key for sorting: sample(sort by samples number)" |
1190 | " time (sort by avg time)"), | 1188 | " time (sort by avg time)"), |
1191 | OPT_STRING('p', "pid", &kvm->pid_str, "pid", | 1189 | OPT_STRING('p', "pid", &kvm->opts.target.pid, "pid", |
1192 | "analyze events only for given process id(s)"), | 1190 | "analyze events only for given process id(s)"), |
1193 | OPT_END() | 1191 | OPT_END() |
1194 | }; | 1192 | }; |
@@ -1207,6 +1205,9 @@ kvm_events_report(struct perf_kvm_stat *kvm, int argc, const char **argv) | |||
1207 | kvm_events_report_options); | 1205 | kvm_events_report_options); |
1208 | } | 1206 | } |
1209 | 1207 | ||
1208 | if (!kvm->opts.target.pid) | ||
1209 | kvm->opts.target.system_wide = true; | ||
1210 | |||
1210 | return kvm_events_report_vcpu(kvm); | 1211 | return kvm_events_report_vcpu(kvm); |
1211 | } | 1212 | } |
1212 | 1213 | ||
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c index 347729e29a92..04412b4770a2 100644 --- a/tools/perf/builtin-probe.c +++ b/tools/perf/builtin-probe.c | |||
@@ -376,6 +376,8 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) | |||
376 | "target executable name or path", opt_set_target), | 376 | "target executable name or path", opt_set_target), |
377 | OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle, | 377 | OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle, |
378 | "Disable symbol demangling"), | 378 | "Disable symbol demangling"), |
379 | OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel, | ||
380 | "Enable kernel symbol demangling"), | ||
379 | OPT_END() | 381 | OPT_END() |
380 | }; | 382 | }; |
381 | int ret; | 383 | int ret; |
@@ -470,7 +472,8 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) | |||
470 | usage_with_options(probe_usage, options); | 472 | usage_with_options(probe_usage, options); |
471 | } | 473 | } |
472 | 474 | ||
473 | ret = show_line_range(¶ms.line_range, params.target); | 475 | ret = show_line_range(¶ms.line_range, params.target, |
476 | params.uprobes); | ||
474 | if (ret < 0) | 477 | if (ret < 0) |
475 | pr_err_with_code(" Error: Failed to show lines.", ret); | 478 | pr_err_with_code(" Error: Failed to show lines.", ret); |
476 | return ret; | 479 | return ret; |
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 87e28a4e33ba..a1b040394170 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
@@ -65,8 +65,9 @@ static int process_synthesized_event(struct perf_tool *tool, | |||
65 | return record__write(rec, event, event->header.size); | 65 | return record__write(rec, event, event->header.size); |
66 | } | 66 | } |
67 | 67 | ||
68 | static int record__mmap_read(struct record *rec, struct perf_mmap *md) | 68 | static int record__mmap_read(struct record *rec, int idx) |
69 | { | 69 | { |
70 | struct perf_mmap *md = &rec->evlist->mmap[idx]; | ||
70 | unsigned int head = perf_mmap__read_head(md); | 71 | unsigned int head = perf_mmap__read_head(md); |
71 | unsigned int old = md->prev; | 72 | unsigned int old = md->prev; |
72 | unsigned char *data = md->base + page_size; | 73 | unsigned char *data = md->base + page_size; |
@@ -102,8 +103,7 @@ static int record__mmap_read(struct record *rec, struct perf_mmap *md) | |||
102 | } | 103 | } |
103 | 104 | ||
104 | md->prev = old; | 105 | md->prev = old; |
105 | perf_mmap__write_tail(md, old); | 106 | perf_evlist__mmap_consume(rec->evlist, idx); |
106 | |||
107 | out: | 107 | out: |
108 | return rc; | 108 | return rc; |
109 | } | 109 | } |
@@ -245,7 +245,7 @@ static int record__mmap_read_all(struct record *rec) | |||
245 | 245 | ||
246 | for (i = 0; i < rec->evlist->nr_mmaps; i++) { | 246 | for (i = 0; i < rec->evlist->nr_mmaps; i++) { |
247 | if (rec->evlist->mmap[i].base) { | 247 | if (rec->evlist->mmap[i].base) { |
248 | if (record__mmap_read(rec, &rec->evlist->mmap[i]) != 0) { | 248 | if (record__mmap_read(rec, i) != 0) { |
249 | rc = -1; | 249 | rc = -1; |
250 | goto out; | 250 | goto out; |
251 | } | 251 | } |
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 3da59a87ec7c..8c0b3f22412a 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
@@ -680,6 +680,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) | |||
680 | "objdump binary to use for disassembly and annotations"), | 680 | "objdump binary to use for disassembly and annotations"), |
681 | OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle, | 681 | OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle, |
682 | "Disable symbol demangling"), | 682 | "Disable symbol demangling"), |
683 | OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel, | ||
684 | "Enable kernel symbol demangling"), | ||
683 | OPT_BOOLEAN(0, "mem-mode", &report.mem_mode, "mem access profile"), | 685 | OPT_BOOLEAN(0, "mem-mode", &report.mem_mode, "mem access profile"), |
684 | OPT_CALLBACK(0, "percent-limit", &report, "percent", | 686 | OPT_CALLBACK(0, "percent-limit", &report, "percent", |
685 | "Don't show entries under that percent", parse_percent_limit), | 687 | "Don't show entries under that percent", parse_percent_limit), |
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 9848e270b92c..e13864be2acb 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c | |||
@@ -59,7 +59,7 @@ | |||
59 | 59 | ||
60 | #include <sys/syscall.h> | 60 | #include <sys/syscall.h> |
61 | #include <sys/ioctl.h> | 61 | #include <sys/ioctl.h> |
62 | #include <sys/poll.h> | 62 | #include <poll.h> |
63 | #include <sys/prctl.h> | 63 | #include <sys/prctl.h> |
64 | #include <sys/wait.h> | 64 | #include <sys/wait.h> |
65 | #include <sys/uio.h> | 65 | #include <sys/uio.h> |
@@ -1142,6 +1142,8 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1142 | "Interleave source code with assembly code (default)"), | 1142 | "Interleave source code with assembly code (default)"), |
1143 | OPT_BOOLEAN(0, "asm-raw", &symbol_conf.annotate_asm_raw, | 1143 | OPT_BOOLEAN(0, "asm-raw", &symbol_conf.annotate_asm_raw, |
1144 | "Display raw encoding of assembly instructions (default)"), | 1144 | "Display raw encoding of assembly instructions (default)"), |
1145 | OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel, | ||
1146 | "Enable kernel symbol demangling"), | ||
1145 | OPT_STRING(0, "objdump", &objdump_path, "path", | 1147 | OPT_STRING(0, "objdump", &objdump_path, "path", |
1146 | "objdump binary to use for disassembly and annotations"), | 1148 | "objdump binary to use for disassembly and annotations"), |
1147 | OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style", | 1149 | OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style", |
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile index 75d4c237b03d..58f609198c6d 100644 --- a/tools/perf/config/Makefile +++ b/tools/perf/config/Makefile | |||
@@ -48,10 +48,6 @@ ifneq ($(ARCH),$(filter $(ARCH),x86 arm)) | |||
48 | NO_LIBDW_DWARF_UNWIND := 1 | 48 | NO_LIBDW_DWARF_UNWIND := 1 |
49 | endif | 49 | endif |
50 | 50 | ||
51 | ifeq ($(ARCH),powerpc) | ||
52 | CFLAGS += -DHAVE_SKIP_CALLCHAIN_IDX | ||
53 | endif | ||
54 | |||
55 | ifeq ($(LIBUNWIND_LIBS),) | 51 | ifeq ($(LIBUNWIND_LIBS),) |
56 | NO_LIBUNWIND := 1 | 52 | NO_LIBUNWIND := 1 |
57 | else | 53 | else |
@@ -378,6 +374,12 @@ ifndef NO_LIBELF | |||
378 | endif # NO_DWARF | 374 | endif # NO_DWARF |
379 | endif # NO_LIBELF | 375 | endif # NO_LIBELF |
380 | 376 | ||
377 | ifeq ($(ARCH),powerpc) | ||
378 | ifndef NO_DWARF | ||
379 | CFLAGS += -DHAVE_SKIP_CALLCHAIN_IDX | ||
380 | endif | ||
381 | endif | ||
382 | |||
381 | ifndef NO_LIBUNWIND | 383 | ifndef NO_LIBUNWIND |
382 | ifneq ($(feature-libunwind), 1) | 384 | ifneq ($(feature-libunwind), 1) |
383 | msg := $(warning No libunwind found. Please install libunwind-dev[el] >= 1.1 and/or set LIBUNWIND_DIR); | 385 | msg := $(warning No libunwind found. Please install libunwind-dev[el] >= 1.1 and/or set LIBUNWIND_DIR); |
@@ -651,11 +653,13 @@ else | |||
651 | sysconfdir = $(prefix)/etc | 653 | sysconfdir = $(prefix)/etc |
652 | ETC_PERFCONFIG = etc/perfconfig | 654 | ETC_PERFCONFIG = etc/perfconfig |
653 | endif | 655 | endif |
656 | ifndef lib | ||
654 | ifeq ($(IS_X86_64),1) | 657 | ifeq ($(IS_X86_64),1) |
655 | lib = lib64 | 658 | lib = lib64 |
656 | else | 659 | else |
657 | lib = lib | 660 | lib = lib |
658 | endif | 661 | endif |
662 | endif # lib | ||
659 | libdir = $(prefix)/$(lib) | 663 | libdir = $(prefix)/$(lib) |
660 | 664 | ||
661 | # Shell quote (do not use $(call) to accommodate ancient setups); | 665 | # Shell quote (do not use $(call) to accommodate ancient setups); |
diff --git a/tools/perf/config/utilities.mak b/tools/perf/config/utilities.mak index 4d985e0f03f5..7076a62d0ff7 100644 --- a/tools/perf/config/utilities.mak +++ b/tools/perf/config/utilities.mak | |||
@@ -132,7 +132,7 @@ endef | |||
132 | # | 132 | # |
133 | # Usage: bool-value = $(call is-absolute,path) | 133 | # Usage: bool-value = $(call is-absolute,path) |
134 | # | 134 | # |
135 | is-absolute = $(shell echo $(shell-sq) | grep ^/ -q && echo y) | 135 | is-absolute = $(shell echo $(shell-sq) | grep -q ^/ && echo y) |
136 | 136 | ||
137 | # lookup | 137 | # lookup |
138 | # | 138 | # |
diff --git a/tools/perf/perf-with-kcore.sh b/tools/perf/perf-with-kcore.sh new file mode 100644 index 000000000000..c7ff90a90e4e --- /dev/null +++ b/tools/perf/perf-with-kcore.sh | |||
@@ -0,0 +1,259 @@ | |||
1 | #!/bin/bash | ||
2 | # perf-with-kcore: use perf with a copy of kcore | ||
3 | # Copyright (c) 2014, Intel Corporation. | ||
4 | # | ||
5 | # This program is free software; you can redistribute it and/or modify it | ||
6 | # under the terms and conditions of the GNU General Public License, | ||
7 | # version 2, as published by the Free Software Foundation. | ||
8 | # | ||
9 | # This program is distributed in the hope it will be useful, but WITHOUT | ||
10 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | # more details. | ||
13 | |||
14 | set -e | ||
15 | |||
16 | usage() | ||
17 | { | ||
18 | echo "Usage: perf-with-kcore <perf sub-command> <perf.data directory> [<sub-command options> [ -- <workload>]]" >&2 | ||
19 | echo " <perf sub-command> can be record, script, report or inject" >&2 | ||
20 | echo " or: perf-with-kcore fix_buildid_cache_permissions" >&2 | ||
21 | exit 1 | ||
22 | } | ||
23 | |||
24 | find_perf() | ||
25 | { | ||
26 | if [ -n "$PERF" ] ; then | ||
27 | return | ||
28 | fi | ||
29 | PERF=`which perf || true` | ||
30 | if [ -z "$PERF" ] ; then | ||
31 | echo "Failed to find perf" >&2 | ||
32 | exit 1 | ||
33 | fi | ||
34 | if [ ! -x "$PERF" ] ; then | ||
35 | echo "Failed to find perf" >&2 | ||
36 | exit 1 | ||
37 | fi | ||
38 | echo "Using $PERF" | ||
39 | "$PERF" version | ||
40 | } | ||
41 | |||
42 | copy_kcore() | ||
43 | { | ||
44 | echo "Copying kcore" | ||
45 | |||
46 | if [ $EUID -eq 0 ] ; then | ||
47 | SUDO="" | ||
48 | else | ||
49 | SUDO="sudo" | ||
50 | fi | ||
51 | |||
52 | rm -f perf.data.junk | ||
53 | ("$PERF" record -o perf.data.junk $PERF_OPTIONS -- sleep 60) >/dev/null 2>/dev/null & | ||
54 | PERF_PID=$! | ||
55 | |||
56 | # Need to make sure that perf has started | ||
57 | sleep 1 | ||
58 | |||
59 | KCORE=$(($SUDO "$PERF" buildid-cache -v -f -k /proc/kcore >/dev/null) 2>&1) | ||
60 | case "$KCORE" in | ||
61 | "kcore added to build-id cache directory "*) | ||
62 | KCORE_DIR=${KCORE#"kcore added to build-id cache directory "} | ||
63 | ;; | ||
64 | *) | ||
65 | kill $PERF_PID | ||
66 | wait >/dev/null 2>/dev/null || true | ||
67 | rm perf.data.junk | ||
68 | echo "$KCORE" | ||
69 | echo "Failed to find kcore" >&2 | ||
70 | exit 1 | ||
71 | ;; | ||
72 | esac | ||
73 | |||
74 | kill $PERF_PID | ||
75 | wait >/dev/null 2>/dev/null || true | ||
76 | rm perf.data.junk | ||
77 | |||
78 | $SUDO cp -a "$KCORE_DIR" "$(pwd)/$PERF_DATA_DIR" | ||
79 | $SUDO rm -f "$KCORE_DIR/kcore" | ||
80 | $SUDO rm -f "$KCORE_DIR/kallsyms" | ||
81 | $SUDO rm -f "$KCORE_DIR/modules" | ||
82 | $SUDO rmdir "$KCORE_DIR" | ||
83 | |||
84 | KCORE_DIR_BASENAME=$(basename "$KCORE_DIR") | ||
85 | KCORE_DIR="$(pwd)/$PERF_DATA_DIR/$KCORE_DIR_BASENAME" | ||
86 | |||
87 | $SUDO chown $UID "$KCORE_DIR" | ||
88 | $SUDO chown $UID "$KCORE_DIR/kcore" | ||
89 | $SUDO chown $UID "$KCORE_DIR/kallsyms" | ||
90 | $SUDO chown $UID "$KCORE_DIR/modules" | ||
91 | |||
92 | $SUDO chgrp $GROUPS "$KCORE_DIR" | ||
93 | $SUDO chgrp $GROUPS "$KCORE_DIR/kcore" | ||
94 | $SUDO chgrp $GROUPS "$KCORE_DIR/kallsyms" | ||
95 | $SUDO chgrp $GROUPS "$KCORE_DIR/modules" | ||
96 | |||
97 | ln -s "$KCORE_DIR_BASENAME" "$PERF_DATA_DIR/kcore_dir" | ||
98 | } | ||
99 | |||
100 | fix_buildid_cache_permissions() | ||
101 | { | ||
102 | if [ $EUID -ne 0 ] ; then | ||
103 | echo "This script must be run as root via sudo " >&2 | ||
104 | exit 1 | ||
105 | fi | ||
106 | |||
107 | if [ -z "$SUDO_USER" ] ; then | ||
108 | echo "This script must be run via sudo" >&2 | ||
109 | exit 1 | ||
110 | fi | ||
111 | |||
112 | USER_HOME=$(bash <<< "echo ~$SUDO_USER") | ||
113 | |||
114 | if [ "$HOME" != "$USER_HOME" ] ; then | ||
115 | echo "Fix unnecessary because root has a home: $HOME" >&2 | ||
116 | exit 1 | ||
117 | fi | ||
118 | |||
119 | echo "Fixing buildid cache permissions" | ||
120 | |||
121 | find "$USER_HOME/.debug" -xdev -type d ! -user "$SUDO_USER" -ls -exec chown "$SUDO_USER" \{\} \; | ||
122 | find "$USER_HOME/.debug" -xdev -type f -links 1 ! -user "$SUDO_USER" -ls -exec chown "$SUDO_USER" \{\} \; | ||
123 | find "$USER_HOME/.debug" -xdev -type l ! -user "$SUDO_USER" -ls -exec chown -h "$SUDO_USER" \{\} \; | ||
124 | |||
125 | if [ -n "$SUDO_GID" ] ; then | ||
126 | find "$USER_HOME/.debug" -xdev -type d ! -group "$SUDO_GID" -ls -exec chgrp "$SUDO_GID" \{\} \; | ||
127 | find "$USER_HOME/.debug" -xdev -type f -links 1 ! -group "$SUDO_GID" -ls -exec chgrp "$SUDO_GID" \{\} \; | ||
128 | find "$USER_HOME/.debug" -xdev -type l ! -group "$SUDO_GID" -ls -exec chgrp -h "$SUDO_GID" \{\} \; | ||
129 | fi | ||
130 | |||
131 | echo "Done" | ||
132 | } | ||
133 | |||
134 | check_buildid_cache_permissions() | ||
135 | { | ||
136 | if [ $EUID -eq 0 ] ; then | ||
137 | return | ||
138 | fi | ||
139 | |||
140 | PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type d ! -user "$USER" -print -quit) | ||
141 | PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type f -links 1 ! -user "$USER" -print -quit) | ||
142 | PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type l ! -user "$USER" -print -quit) | ||
143 | |||
144 | PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type d ! -group "$GROUPS" -print -quit) | ||
145 | PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type f -links 1 ! -group "$GROUPS" -print -quit) | ||
146 | PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type l ! -group "$GROUPS" -print -quit) | ||
147 | |||
148 | if [ -n "$PERMISSIONS_OK" ] ; then | ||
149 | echo "*** WARNING *** buildid cache permissions may need fixing" >&2 | ||
150 | fi | ||
151 | } | ||
152 | |||
153 | record() | ||
154 | { | ||
155 | echo "Recording" | ||
156 | |||
157 | if [ $EUID -ne 0 ] ; then | ||
158 | |||
159 | if [ "$(cat /proc/sys/kernel/kptr_restrict)" -ne 0 ] ; then | ||
160 | echo "*** WARNING *** /proc/sys/kernel/kptr_restrict prevents access to kernel addresses" >&2 | ||
161 | fi | ||
162 | |||
163 | if echo "$PERF_OPTIONS" | grep -q ' -a \|^-a \| -a$\|^-a$\| --all-cpus \|^--all-cpus \| --all-cpus$\|^--all-cpus$' ; then | ||
164 | echo "*** WARNING *** system-wide tracing without root access will not be able to read all necessary information from /proc" >&2 | ||
165 | fi | ||
166 | |||
167 | if echo "$PERF_OPTIONS" | grep -q 'intel_pt\|intel_bts\| -I\|^-I' ; then | ||
168 | if [ "$(cat /proc/sys/kernel/perf_event_paranoid)" -gt -1 ] ; then | ||
169 | echo "*** WARNING *** /proc/sys/kernel/perf_event_paranoid restricts buffer size and tracepoint (sched_switch) use" >&2 | ||
170 | fi | ||
171 | |||
172 | if echo "$PERF_OPTIONS" | grep -q ' --per-thread \|^--per-thread \| --per-thread$\|^--per-thread$' ; then | ||
173 | true | ||
174 | elif echo "$PERF_OPTIONS" | grep -q ' -t \|^-t \| -t$\|^-t$' ; then | ||
175 | true | ||
176 | elif [ ! -r /sys/kernel/debug -o ! -x /sys/kernel/debug ] ; then | ||
177 | echo "*** WARNING *** /sys/kernel/debug permissions prevent tracepoint (sched_switch) use" >&2 | ||
178 | fi | ||
179 | fi | ||
180 | fi | ||
181 | |||
182 | if [ -z "$1" ] ; then | ||
183 | echo "Workload is required for recording" >&2 | ||
184 | usage | ||
185 | fi | ||
186 | |||
187 | if [ -e "$PERF_DATA_DIR" ] ; then | ||
188 | echo "'$PERF_DATA_DIR' exists" >&2 | ||
189 | exit 1 | ||
190 | fi | ||
191 | |||
192 | find_perf | ||
193 | |||
194 | mkdir "$PERF_DATA_DIR" | ||
195 | |||
196 | echo "$PERF record -o $PERF_DATA_DIR/perf.data $PERF_OPTIONS -- $*" | ||
197 | "$PERF" record -o "$PERF_DATA_DIR/perf.data" $PERF_OPTIONS -- $* || true | ||
198 | |||
199 | if rmdir "$PERF_DATA_DIR" > /dev/null 2>/dev/null ; then | ||
200 | exit 1 | ||
201 | fi | ||
202 | |||
203 | copy_kcore | ||
204 | |||
205 | echo "Done" | ||
206 | } | ||
207 | |||
208 | subcommand() | ||
209 | { | ||
210 | find_perf | ||
211 | check_buildid_cache_permissions | ||
212 | echo "$PERF $PERF_SUB_COMMAND -i $PERF_DATA_DIR/perf.data --kallsyms=$PERF_DATA_DIR/kcore_dir/kallsyms $*" | ||
213 | "$PERF" $PERF_SUB_COMMAND -i "$PERF_DATA_DIR/perf.data" "--kallsyms=$PERF_DATA_DIR/kcore_dir/kallsyms" $* | ||
214 | } | ||
215 | |||
216 | if [ "$1" = "fix_buildid_cache_permissions" ] ; then | ||
217 | fix_buildid_cache_permissions | ||
218 | exit 0 | ||
219 | fi | ||
220 | |||
221 | PERF_SUB_COMMAND=$1 | ||
222 | PERF_DATA_DIR=$2 | ||
223 | shift || true | ||
224 | shift || true | ||
225 | |||
226 | if [ -z "$PERF_SUB_COMMAND" ] ; then | ||
227 | usage | ||
228 | fi | ||
229 | |||
230 | if [ -z "$PERF_DATA_DIR" ] ; then | ||
231 | usage | ||
232 | fi | ||
233 | |||
234 | case "$PERF_SUB_COMMAND" in | ||
235 | "record") | ||
236 | while [ "$1" != "--" ] ; do | ||
237 | PERF_OPTIONS+="$1 " | ||
238 | shift || break | ||
239 | done | ||
240 | if [ "$1" != "--" ] ; then | ||
241 | echo "Options and workload are required for recording" >&2 | ||
242 | usage | ||
243 | fi | ||
244 | shift | ||
245 | record $* | ||
246 | ;; | ||
247 | "script") | ||
248 | subcommand $* | ||
249 | ;; | ||
250 | "report") | ||
251 | subcommand $* | ||
252 | ;; | ||
253 | "inject") | ||
254 | subcommand $* | ||
255 | ;; | ||
256 | *) | ||
257 | usage | ||
258 | ;; | ||
259 | esac | ||
diff --git a/tools/perf/tests/pmu.c b/tools/perf/tests/pmu.c index 12b322fa3475..eeb68bb1972d 100644 --- a/tools/perf/tests/pmu.c +++ b/tools/perf/tests/pmu.c | |||
@@ -152,7 +152,7 @@ int test__pmu(void) | |||
152 | if (ret) | 152 | if (ret) |
153 | break; | 153 | break; |
154 | 154 | ||
155 | ret = perf_pmu__config_terms(&formats, &attr, terms); | 155 | ret = perf_pmu__config_terms(&formats, &attr, terms, false); |
156 | if (ret) | 156 | if (ret) |
157 | break; | 157 | break; |
158 | 158 | ||
diff --git a/tools/perf/util/kvm-stat.h b/tools/perf/util/kvm-stat.h index 0b5a8cd2ee79..cf1d7913783b 100644 --- a/tools/perf/util/kvm-stat.h +++ b/tools/perf/util/kvm-stat.h | |||
@@ -92,7 +92,6 @@ struct perf_kvm_stat { | |||
92 | u64 lost_events; | 92 | u64 lost_events; |
93 | u64 duration; | 93 | u64 duration; |
94 | 94 | ||
95 | const char *pid_str; | ||
96 | struct intlist *pid_list; | 95 | struct intlist *pid_list; |
97 | 96 | ||
98 | struct rb_root result; | 97 | struct rb_root result; |
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index e34c81a0bcf3..61be3e695ec2 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c | |||
@@ -643,7 +643,18 @@ int parse_events_add_pmu(struct list_head *list, int *idx, | |||
643 | if (!pmu) | 643 | if (!pmu) |
644 | return -EINVAL; | 644 | return -EINVAL; |
645 | 645 | ||
646 | memset(&attr, 0, sizeof(attr)); | 646 | if (pmu->default_config) { |
647 | memcpy(&attr, pmu->default_config, | ||
648 | sizeof(struct perf_event_attr)); | ||
649 | } else { | ||
650 | memset(&attr, 0, sizeof(attr)); | ||
651 | } | ||
652 | |||
653 | if (!head_config) { | ||
654 | attr.type = pmu->type; | ||
655 | evsel = __add_event(list, idx, &attr, NULL, pmu->cpus); | ||
656 | return evsel ? 0 : -ENOMEM; | ||
657 | } | ||
647 | 658 | ||
648 | if (perf_pmu__check_alias(pmu, head_config, &unit, &scale)) | 659 | if (perf_pmu__check_alias(pmu, head_config, &unit, &scale)) |
649 | return -EINVAL; | 660 | return -EINVAL; |
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y index 0bc87ba46bf3..55fab6ad609a 100644 --- a/tools/perf/util/parse-events.y +++ b/tools/perf/util/parse-events.y | |||
@@ -210,6 +210,16 @@ PE_NAME '/' event_config '/' | |||
210 | parse_events__free_terms($3); | 210 | parse_events__free_terms($3); |
211 | $$ = list; | 211 | $$ = list; |
212 | } | 212 | } |
213 | | | ||
214 | PE_NAME '/' '/' | ||
215 | { | ||
216 | struct parse_events_evlist *data = _data; | ||
217 | struct list_head *list; | ||
218 | |||
219 | ALLOC_LIST(list); | ||
220 | ABORT_ON(parse_events_add_pmu(list, &data->idx, $1, NULL)); | ||
221 | $$ = list; | ||
222 | } | ||
213 | 223 | ||
214 | value_sym: | 224 | value_sym: |
215 | PE_VALUE_SYM_HW | 225 | PE_VALUE_SYM_HW |
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 9bf582750561..22a4ad5a927a 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c | |||
@@ -2,6 +2,8 @@ | |||
2 | #include <sys/types.h> | 2 | #include <sys/types.h> |
3 | #include <unistd.h> | 3 | #include <unistd.h> |
4 | #include <stdio.h> | 4 | #include <stdio.h> |
5 | #include <stdbool.h> | ||
6 | #include <stdarg.h> | ||
5 | #include <dirent.h> | 7 | #include <dirent.h> |
6 | #include <api/fs/fs.h> | 8 | #include <api/fs/fs.h> |
7 | #include <locale.h> | 9 | #include <locale.h> |
@@ -387,6 +389,12 @@ static struct cpu_map *pmu_cpumask(const char *name) | |||
387 | return cpus; | 389 | return cpus; |
388 | } | 390 | } |
389 | 391 | ||
392 | struct perf_event_attr *__attribute__((weak)) | ||
393 | perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused) | ||
394 | { | ||
395 | return NULL; | ||
396 | } | ||
397 | |||
390 | static struct perf_pmu *pmu_lookup(const char *name) | 398 | static struct perf_pmu *pmu_lookup(const char *name) |
391 | { | 399 | { |
392 | struct perf_pmu *pmu; | 400 | struct perf_pmu *pmu; |
@@ -421,6 +429,9 @@ static struct perf_pmu *pmu_lookup(const char *name) | |||
421 | pmu->name = strdup(name); | 429 | pmu->name = strdup(name); |
422 | pmu->type = type; | 430 | pmu->type = type; |
423 | list_add_tail(&pmu->list, &pmus); | 431 | list_add_tail(&pmu->list, &pmus); |
432 | |||
433 | pmu->default_config = perf_pmu__get_default_config(pmu); | ||
434 | |||
424 | return pmu; | 435 | return pmu; |
425 | } | 436 | } |
426 | 437 | ||
@@ -479,28 +490,24 @@ pmu_find_format(struct list_head *formats, char *name) | |||
479 | } | 490 | } |
480 | 491 | ||
481 | /* | 492 | /* |
482 | * Returns value based on the format definition (format parameter) | 493 | * Sets value based on the format definition (format parameter) |
483 | * and unformated value (value parameter). | 494 | * and unformated value (value parameter). |
484 | * | ||
485 | * TODO maybe optimize a little ;) | ||
486 | */ | 495 | */ |
487 | static __u64 pmu_format_value(unsigned long *format, __u64 value) | 496 | static void pmu_format_value(unsigned long *format, __u64 value, __u64 *v, |
497 | bool zero) | ||
488 | { | 498 | { |
489 | unsigned long fbit, vbit; | 499 | unsigned long fbit, vbit; |
490 | __u64 v = 0; | ||
491 | 500 | ||
492 | for (fbit = 0, vbit = 0; fbit < PERF_PMU_FORMAT_BITS; fbit++) { | 501 | for (fbit = 0, vbit = 0; fbit < PERF_PMU_FORMAT_BITS; fbit++) { |
493 | 502 | ||
494 | if (!test_bit(fbit, format)) | 503 | if (!test_bit(fbit, format)) |
495 | continue; | 504 | continue; |
496 | 505 | ||
497 | if (!(value & (1llu << vbit++))) | 506 | if (value & (1llu << vbit++)) |
498 | continue; | 507 | *v |= (1llu << fbit); |
499 | 508 | else if (zero) | |
500 | v |= (1llu << fbit); | 509 | *v &= ~(1llu << fbit); |
501 | } | 510 | } |
502 | |||
503 | return v; | ||
504 | } | 511 | } |
505 | 512 | ||
506 | /* | 513 | /* |
@@ -509,7 +516,8 @@ static __u64 pmu_format_value(unsigned long *format, __u64 value) | |||
509 | */ | 516 | */ |
510 | static int pmu_config_term(struct list_head *formats, | 517 | static int pmu_config_term(struct list_head *formats, |
511 | struct perf_event_attr *attr, | 518 | struct perf_event_attr *attr, |
512 | struct parse_events_term *term) | 519 | struct parse_events_term *term, |
520 | bool zero) | ||
513 | { | 521 | { |
514 | struct perf_pmu_format *format; | 522 | struct perf_pmu_format *format; |
515 | __u64 *vp; | 523 | __u64 *vp; |
@@ -548,18 +556,19 @@ static int pmu_config_term(struct list_head *formats, | |||
548 | * non-hardcoded terms, here's the place to translate | 556 | * non-hardcoded terms, here's the place to translate |
549 | * them into value. | 557 | * them into value. |
550 | */ | 558 | */ |
551 | *vp |= pmu_format_value(format->bits, term->val.num); | 559 | pmu_format_value(format->bits, term->val.num, vp, zero); |
552 | return 0; | 560 | return 0; |
553 | } | 561 | } |
554 | 562 | ||
555 | int perf_pmu__config_terms(struct list_head *formats, | 563 | int perf_pmu__config_terms(struct list_head *formats, |
556 | struct perf_event_attr *attr, | 564 | struct perf_event_attr *attr, |
557 | struct list_head *head_terms) | 565 | struct list_head *head_terms, |
566 | bool zero) | ||
558 | { | 567 | { |
559 | struct parse_events_term *term; | 568 | struct parse_events_term *term; |
560 | 569 | ||
561 | list_for_each_entry(term, head_terms, list) | 570 | list_for_each_entry(term, head_terms, list) |
562 | if (pmu_config_term(formats, attr, term)) | 571 | if (pmu_config_term(formats, attr, term, zero)) |
563 | return -EINVAL; | 572 | return -EINVAL; |
564 | 573 | ||
565 | return 0; | 574 | return 0; |
@@ -573,8 +582,10 @@ int perf_pmu__config_terms(struct list_head *formats, | |||
573 | int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr, | 582 | int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr, |
574 | struct list_head *head_terms) | 583 | struct list_head *head_terms) |
575 | { | 584 | { |
585 | bool zero = !!pmu->default_config; | ||
586 | |||
576 | attr->type = pmu->type; | 587 | attr->type = pmu->type; |
577 | return perf_pmu__config_terms(&pmu->format, attr, head_terms); | 588 | return perf_pmu__config_terms(&pmu->format, attr, head_terms, zero); |
578 | } | 589 | } |
579 | 590 | ||
580 | static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu, | 591 | static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu, |
@@ -794,3 +805,39 @@ bool pmu_have_event(const char *pname, const char *name) | |||
794 | } | 805 | } |
795 | return false; | 806 | return false; |
796 | } | 807 | } |
808 | |||
809 | static FILE *perf_pmu__open_file(struct perf_pmu *pmu, const char *name) | ||
810 | { | ||
811 | struct stat st; | ||
812 | char path[PATH_MAX]; | ||
813 | const char *sysfs; | ||
814 | |||
815 | sysfs = sysfs__mountpoint(); | ||
816 | if (!sysfs) | ||
817 | return NULL; | ||
818 | |||
819 | snprintf(path, PATH_MAX, | ||
820 | "%s" EVENT_SOURCE_DEVICE_PATH "%s/%s", sysfs, pmu->name, name); | ||
821 | |||
822 | if (stat(path, &st) < 0) | ||
823 | return NULL; | ||
824 | |||
825 | return fopen(path, "r"); | ||
826 | } | ||
827 | |||
828 | int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt, | ||
829 | ...) | ||
830 | { | ||
831 | va_list args; | ||
832 | FILE *file; | ||
833 | int ret = EOF; | ||
834 | |||
835 | va_start(args, fmt); | ||
836 | file = perf_pmu__open_file(pmu, name); | ||
837 | if (file) { | ||
838 | ret = vfscanf(file, fmt, args); | ||
839 | fclose(file); | ||
840 | } | ||
841 | va_end(args); | ||
842 | return ret; | ||
843 | } | ||
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h index 1c1e2eecbe1f..0f5c0a88fdc8 100644 --- a/tools/perf/util/pmu.h +++ b/tools/perf/util/pmu.h | |||
@@ -13,9 +13,12 @@ enum { | |||
13 | 13 | ||
14 | #define PERF_PMU_FORMAT_BITS 64 | 14 | #define PERF_PMU_FORMAT_BITS 64 |
15 | 15 | ||
16 | struct perf_event_attr; | ||
17 | |||
16 | struct perf_pmu { | 18 | struct perf_pmu { |
17 | char *name; | 19 | char *name; |
18 | __u32 type; | 20 | __u32 type; |
21 | struct perf_event_attr *default_config; | ||
19 | struct cpu_map *cpus; | 22 | struct cpu_map *cpus; |
20 | struct list_head format; /* HEAD struct perf_pmu_format -> list */ | 23 | struct list_head format; /* HEAD struct perf_pmu_format -> list */ |
21 | struct list_head aliases; /* HEAD struct perf_pmu_alias -> list */ | 24 | struct list_head aliases; /* HEAD struct perf_pmu_alias -> list */ |
@@ -27,7 +30,8 @@ int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr, | |||
27 | struct list_head *head_terms); | 30 | struct list_head *head_terms); |
28 | int perf_pmu__config_terms(struct list_head *formats, | 31 | int perf_pmu__config_terms(struct list_head *formats, |
29 | struct perf_event_attr *attr, | 32 | struct perf_event_attr *attr, |
30 | struct list_head *head_terms); | 33 | struct list_head *head_terms, |
34 | bool zero); | ||
31 | int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms, | 35 | int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms, |
32 | const char **unit, double *scale); | 36 | const char **unit, double *scale); |
33 | struct list_head *perf_pmu__alias(struct perf_pmu *pmu, | 37 | struct list_head *perf_pmu__alias(struct perf_pmu *pmu, |
@@ -45,5 +49,11 @@ struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu); | |||
45 | void print_pmu_events(const char *event_glob, bool name_only); | 49 | void print_pmu_events(const char *event_glob, bool name_only); |
46 | bool pmu_have_event(const char *pname, const char *name); | 50 | bool pmu_have_event(const char *pname, const char *name); |
47 | 51 | ||
52 | int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt, | ||
53 | ...) __attribute__((format(scanf, 3, 4))); | ||
54 | |||
48 | int perf_pmu__test(void); | 55 | int perf_pmu__test(void); |
56 | |||
57 | struct perf_event_attr *perf_pmu__get_default_config(struct perf_pmu *pmu); | ||
58 | |||
49 | #endif /* __PMU_H */ | 59 | #endif /* __PMU_H */ |
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index f73595fc0627..be37b5aca335 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c | |||
@@ -697,11 +697,11 @@ end: | |||
697 | return ret; | 697 | return ret; |
698 | } | 698 | } |
699 | 699 | ||
700 | int show_line_range(struct line_range *lr, const char *module) | 700 | int show_line_range(struct line_range *lr, const char *module, bool user) |
701 | { | 701 | { |
702 | int ret; | 702 | int ret; |
703 | 703 | ||
704 | ret = init_symbol_maps(false); | 704 | ret = init_symbol_maps(user); |
705 | if (ret < 0) | 705 | if (ret < 0) |
706 | return ret; | 706 | return ret; |
707 | ret = __show_line_range(lr, module); | 707 | ret = __show_line_range(lr, module); |
@@ -776,7 +776,7 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs, | |||
776 | int i, ret = 0; | 776 | int i, ret = 0; |
777 | struct debuginfo *dinfo; | 777 | struct debuginfo *dinfo; |
778 | 778 | ||
779 | ret = init_symbol_maps(false); | 779 | ret = init_symbol_maps(pevs->uprobes); |
780 | if (ret < 0) | 780 | if (ret < 0) |
781 | return ret; | 781 | return ret; |
782 | 782 | ||
@@ -822,7 +822,8 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev, | |||
822 | } | 822 | } |
823 | 823 | ||
824 | int show_line_range(struct line_range *lr __maybe_unused, | 824 | int show_line_range(struct line_range *lr __maybe_unused, |
825 | const char *module __maybe_unused) | 825 | const char *module __maybe_unused, |
826 | bool user __maybe_unused) | ||
826 | { | 827 | { |
827 | pr_warning("Debuginfo-analysis is not supported.\n"); | 828 | pr_warning("Debuginfo-analysis is not supported.\n"); |
828 | return -ENOSYS; | 829 | return -ENOSYS; |
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h index 776c9347a3b6..e01e9943139f 100644 --- a/tools/perf/util/probe-event.h +++ b/tools/perf/util/probe-event.h | |||
@@ -128,7 +128,8 @@ extern int add_perf_probe_events(struct perf_probe_event *pevs, int npevs, | |||
128 | bool force_add); | 128 | bool force_add); |
129 | extern int del_perf_probe_events(struct strlist *dellist); | 129 | extern int del_perf_probe_events(struct strlist *dellist); |
130 | extern int show_perf_probe_events(void); | 130 | extern int show_perf_probe_events(void); |
131 | extern int show_line_range(struct line_range *lr, const char *module); | 131 | extern int show_line_range(struct line_range *lr, const char *module, |
132 | bool user); | ||
132 | extern int show_available_vars(struct perf_probe_event *pevs, int npevs, | 133 | extern int show_available_vars(struct perf_probe_event *pevs, int npevs, |
133 | int max_probe_points, const char *module, | 134 | int max_probe_points, const char *module, |
134 | struct strfilter *filter, bool externs); | 135 | struct strfilter *filter, bool externs); |
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 9c593561aa71..c7918f83b300 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c | |||
@@ -609,14 +609,18 @@ static int convert_to_trace_point(Dwarf_Die *sp_die, Dwfl_Module *mod, | |||
609 | return -EINVAL; | 609 | return -EINVAL; |
610 | } | 610 | } |
611 | 611 | ||
612 | /* Get an appropriate symbol from symtab */ | 612 | symbol = dwarf_diename(sp_die); |
613 | symbol = dwfl_module_addrsym(mod, paddr, &sym, NULL); | ||
614 | if (!symbol) { | 613 | if (!symbol) { |
615 | pr_warning("Failed to find symbol at 0x%lx\n", | 614 | /* Try to get the symbol name from symtab */ |
616 | (unsigned long)paddr); | 615 | symbol = dwfl_module_addrsym(mod, paddr, &sym, NULL); |
617 | return -ENOENT; | 616 | if (!symbol) { |
617 | pr_warning("Failed to find symbol at 0x%lx\n", | ||
618 | (unsigned long)paddr); | ||
619 | return -ENOENT; | ||
620 | } | ||
621 | eaddr = sym.st_value; | ||
618 | } | 622 | } |
619 | tp->offset = (unsigned long)(paddr - sym.st_value); | 623 | tp->offset = (unsigned long)(paddr - eaddr); |
620 | tp->address = (unsigned long)paddr; | 624 | tp->address = (unsigned long)paddr; |
621 | tp->symbol = strdup(symbol); | 625 | tp->symbol = strdup(symbol); |
622 | if (!tp->symbol) | 626 | if (!tp->symbol) |
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 1958637cf136..289df9d1e65a 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c | |||
@@ -1446,12 +1446,47 @@ static const char *get_default_sort_order(void) | |||
1446 | return default_sort_orders[sort__mode]; | 1446 | return default_sort_orders[sort__mode]; |
1447 | } | 1447 | } |
1448 | 1448 | ||
1449 | static int setup_sort_order(void) | ||
1450 | { | ||
1451 | char *new_sort_order; | ||
1452 | |||
1453 | /* | ||
1454 | * Append '+'-prefixed sort order to the default sort | ||
1455 | * order string. | ||
1456 | */ | ||
1457 | if (!sort_order || is_strict_order(sort_order)) | ||
1458 | return 0; | ||
1459 | |||
1460 | if (sort_order[1] == '\0') { | ||
1461 | error("Invalid --sort key: `+'"); | ||
1462 | return -EINVAL; | ||
1463 | } | ||
1464 | |||
1465 | /* | ||
1466 | * We allocate new sort_order string, but we never free it, | ||
1467 | * because it's checked over the rest of the code. | ||
1468 | */ | ||
1469 | if (asprintf(&new_sort_order, "%s,%s", | ||
1470 | get_default_sort_order(), sort_order + 1) < 0) { | ||
1471 | error("Not enough memory to set up --sort"); | ||
1472 | return -ENOMEM; | ||
1473 | } | ||
1474 | |||
1475 | sort_order = new_sort_order; | ||
1476 | return 0; | ||
1477 | } | ||
1478 | |||
1449 | static int __setup_sorting(void) | 1479 | static int __setup_sorting(void) |
1450 | { | 1480 | { |
1451 | char *tmp, *tok, *str; | 1481 | char *tmp, *tok, *str; |
1452 | const char *sort_keys = sort_order; | 1482 | const char *sort_keys; |
1453 | int ret = 0; | 1483 | int ret = 0; |
1454 | 1484 | ||
1485 | ret = setup_sort_order(); | ||
1486 | if (ret) | ||
1487 | return ret; | ||
1488 | |||
1489 | sort_keys = sort_order; | ||
1455 | if (sort_keys == NULL) { | 1490 | if (sort_keys == NULL) { |
1456 | if (is_strict_order(field_order)) { | 1491 | if (is_strict_order(field_order)) { |
1457 | /* | 1492 | /* |
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index 9fb5e9e9f161..2a92e10317c5 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c | |||
@@ -680,6 +680,11 @@ static u64 ref_reloc(struct kmap *kmap) | |||
680 | return 0; | 680 | return 0; |
681 | } | 681 | } |
682 | 682 | ||
683 | static bool want_demangle(bool is_kernel_sym) | ||
684 | { | ||
685 | return is_kernel_sym ? symbol_conf.demangle_kernel : symbol_conf.demangle; | ||
686 | } | ||
687 | |||
683 | int dso__load_sym(struct dso *dso, struct map *map, | 688 | int dso__load_sym(struct dso *dso, struct map *map, |
684 | struct symsrc *syms_ss, struct symsrc *runtime_ss, | 689 | struct symsrc *syms_ss, struct symsrc *runtime_ss, |
685 | symbol_filter_t filter, int kmodule) | 690 | symbol_filter_t filter, int kmodule) |
@@ -712,6 +717,14 @@ int dso__load_sym(struct dso *dso, struct map *map, | |||
712 | symbols__delete(&dso->symbols[map->type]); | 717 | symbols__delete(&dso->symbols[map->type]); |
713 | 718 | ||
714 | if (!syms_ss->symtab) { | 719 | if (!syms_ss->symtab) { |
720 | /* | ||
721 | * If the vmlinux is stripped, fail so we will fall back | ||
722 | * to using kallsyms. The vmlinux runtime symbols aren't | ||
723 | * of much use. | ||
724 | */ | ||
725 | if (dso->kernel) | ||
726 | goto out_elf_end; | ||
727 | |||
715 | syms_ss->symtab = syms_ss->dynsym; | 728 | syms_ss->symtab = syms_ss->dynsym; |
716 | syms_ss->symshdr = syms_ss->dynshdr; | 729 | syms_ss->symshdr = syms_ss->dynshdr; |
717 | } | 730 | } |
@@ -938,7 +951,7 @@ new_symbol: | |||
938 | * DWARF DW_compile_unit has this, but we don't always have access | 951 | * DWARF DW_compile_unit has this, but we don't always have access |
939 | * to it... | 952 | * to it... |
940 | */ | 953 | */ |
941 | if (symbol_conf.demangle) { | 954 | if (want_demangle(dso->kernel || kmodule)) { |
942 | int demangle_flags = DMGL_NO_OPTS; | 955 | int demangle_flags = DMGL_NO_OPTS; |
943 | if (verbose) | 956 | if (verbose) |
944 | demangle_flags = DMGL_PARAMS | DMGL_ANSI; | 957 | demangle_flags = DMGL_PARAMS | DMGL_ANSI; |
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index ac098a3c2a31..be84f7a9838b 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -34,6 +34,7 @@ struct symbol_conf symbol_conf = { | |||
34 | .try_vmlinux_path = true, | 34 | .try_vmlinux_path = true, |
35 | .annotate_src = true, | 35 | .annotate_src = true, |
36 | .demangle = true, | 36 | .demangle = true, |
37 | .demangle_kernel = false, | ||
37 | .cumulate_callchain = true, | 38 | .cumulate_callchain = true, |
38 | .show_hist_headers = true, | 39 | .show_hist_headers = true, |
39 | .symfs = "", | 40 | .symfs = "", |
@@ -1756,7 +1757,7 @@ static int vmlinux_path__init(struct perf_session_env *env) | |||
1756 | char bf[PATH_MAX]; | 1757 | char bf[PATH_MAX]; |
1757 | char *kernel_version; | 1758 | char *kernel_version; |
1758 | 1759 | ||
1759 | vmlinux_path = malloc(sizeof(char *) * 5); | 1760 | vmlinux_path = malloc(sizeof(char *) * 6); |
1760 | if (vmlinux_path == NULL) | 1761 | if (vmlinux_path == NULL) |
1761 | return -1; | 1762 | return -1; |
1762 | 1763 | ||
@@ -1787,6 +1788,12 @@ static int vmlinux_path__init(struct perf_session_env *env) | |||
1787 | if (vmlinux_path[vmlinux_path__nr_entries] == NULL) | 1788 | if (vmlinux_path[vmlinux_path__nr_entries] == NULL) |
1788 | goto out_fail; | 1789 | goto out_fail; |
1789 | ++vmlinux_path__nr_entries; | 1790 | ++vmlinux_path__nr_entries; |
1791 | snprintf(bf, sizeof(bf), "/usr/lib/debug/boot/vmlinux-%s", | ||
1792 | kernel_version); | ||
1793 | vmlinux_path[vmlinux_path__nr_entries] = strdup(bf); | ||
1794 | if (vmlinux_path[vmlinux_path__nr_entries] == NULL) | ||
1795 | goto out_fail; | ||
1796 | ++vmlinux_path__nr_entries; | ||
1790 | snprintf(bf, sizeof(bf), "/lib/modules/%s/build/vmlinux", kernel_version); | 1797 | snprintf(bf, sizeof(bf), "/lib/modules/%s/build/vmlinux", kernel_version); |
1791 | vmlinux_path[vmlinux_path__nr_entries] = strdup(bf); | 1798 | vmlinux_path[vmlinux_path__nr_entries] = strdup(bf); |
1792 | if (vmlinux_path[vmlinux_path__nr_entries] == NULL) | 1799 | if (vmlinux_path[vmlinux_path__nr_entries] == NULL) |
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 3f95ea0357e3..bec4b7bd09de 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h | |||
@@ -120,6 +120,7 @@ struct symbol_conf { | |||
120 | annotate_src, | 120 | annotate_src, |
121 | event_group, | 121 | event_group, |
122 | demangle, | 122 | demangle, |
123 | demangle_kernel, | ||
123 | filter_relative, | 124 | filter_relative, |
124 | show_hist_headers; | 125 | show_hist_headers; |
125 | const char *vmlinux_name, | 126 | const char *vmlinux_name, |
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index d6a79b1fb28c..80bfdaa0e2a4 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h | |||
@@ -39,6 +39,8 @@ | |||
39 | 39 | ||
40 | #define _ALL_SOURCE 1 | 40 | #define _ALL_SOURCE 1 |
41 | #define _BSD_SOURCE 1 | 41 | #define _BSD_SOURCE 1 |
42 | /* glibc 2.20 deprecates _BSD_SOURCE in favour of _DEFAULT_SOURCE */ | ||
43 | #define _DEFAULT_SOURCE 1 | ||
42 | #define HAS_BOOL | 44 | #define HAS_BOOL |
43 | 45 | ||
44 | #include <unistd.h> | 46 | #include <unistd.h> |
@@ -64,7 +66,7 @@ | |||
64 | #include <regex.h> | 66 | #include <regex.h> |
65 | #include <utime.h> | 67 | #include <utime.h> |
66 | #include <sys/wait.h> | 68 | #include <sys/wait.h> |
67 | #include <sys/poll.h> | 69 | #include <poll.h> |
68 | #include <sys/socket.h> | 70 | #include <sys/socket.h> |
69 | #include <sys/ioctl.h> | 71 | #include <sys/ioctl.h> |
70 | #include <inttypes.h> | 72 | #include <inttypes.h> |