aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-11-11 20:06:34 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-11-11 20:06:34 -0500
commitad5d69899e52792671c1aa6c7360464c7edfe09c (patch)
tree21833c1fdab4b3cf791d4fdc86dd578e4a620514
parentef1417a5a6a400dbc1a2f44da716ab146a29ddc4 (diff)
parentcaea6cf52139116e43e615d87fcbf9823e197fdf (diff)
Merge branch 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf updates from Ingo Molnar: "As a first remark I'd like to note that the way to build perf tooling has been simplified and sped up, in the future it should be enough for you to build perf via: cd tools/perf/ make install (ie without the -j option.) The build system will figure out the number of CPUs and will do a parallel build+install. The various build system inefficiencies and breakages Linus reported against the v3.12 pull request should now be resolved - please (re-)report any remaining annoyances or bugs. Main changes on the perf kernel side: * Performance optimizations: . perf ring-buffer code optimizations, by Peter Zijlstra . perf ring-buffer code optimizations, by Oleg Nesterov . x86 NMI call-stack processing optimizations, by Peter Zijlstra . perf context-switch optimizations, by Peter Zijlstra . perf sampling speedups, by Peter Zijlstra . x86 Intel PEBS processing speedups, by Peter Zijlstra * Enhanced hardware support: . for Intel Ivy Bridge-EP uncore PMUs, by Zheng Yan . for Haswell transactions, by Andi Kleen, Peter Zijlstra * Core perf events code enhancements and fixes by Oleg Nesterov: . for uprobes, if fork() is called with pending ret-probes . for uprobes platform support code * New ABI details by Andi Kleen: . Report x86 Haswell TSX transaction abort cost as weight Main changes on the perf tooling side (some of these tooling changes utilize the above kernel side changes): * 'perf report/top' enhancements: . Convert callchain children list to rbtree, greatly reducing the time taken for callchain processing, from Namhyung Kim. . Add new COMM infrastructure, further improving histogram processing, from Frédéric Weisbecker, one fix from Namhyung Kim. . Add /proc/kcore based live-annotation improvements, including build-id cache support, multi map 'call' instruction navigation fixes, kcore address validation, objdump workarounds. From Adrian Hunter. . Show progress on histogram collapsing, that can take a long time, from Namhyung Kim. . Add --max-stack option to limit callchain stack scan in 'top' and 'report', improving callchain processing when reducing the stack depth is an option, from Waiman Long. . Add new option --ignore-vmlinux for perf top, from Willy Tarreau. * 'perf trace' enhancements: . 'perf trace' now can can use a 'perf probe' dynamic tracepoints to hook into the userspace -> kernel pathname copy so that it can map fds to pathnames without reading /proc/pid/fd/ symlinks. From Arnaldo Carvalho de Melo. . Show VFS path associated with fd in live sessions, using a 'vfs_getname' 'perf probe' created dynamic tracepoint or by looking at /proc/pid/fd, from Arnaldo Carvalho de Melo. . Add 'trace' beautifiers for lots of syscall arguments, from Arnaldo Carvalho de Melo. . Implement more compact 'trace' output by suppressing zeroed args, from Arnaldo Carvalho de Melo. . Show thread COMM by default in 'trace', from Arnaldo Carvalho de Melo. . Add option to show full timestamp in 'trace', from David Ahern. . Add 'record' command in 'trace', to record raw_syscalls:*, from David Ahern. . Add summary option to dump syscall statistics in 'trace', from David Ahern. . Improve error messages in 'trace', providing hints about system configuration steps needed for using it, from Ramkumar Ramachandra. . 'perf trace' now emits hints as to why tracing is not possible, helping the user to setup the system to allow tracing in the desired permission granularity, telling if the problem is due to debugfs not being mounted or with not enough permission for !root, /proc/sys/kernel/perf_event_paranoit value, etc. From Arnaldo Carvalho de Melo. * 'perf record' enhancements: . Check maximum frequency rate for record/top, emitting better error messages, from Jiri Olsa. . 'perf record' code cleanups, from David Ahern. . Improve write_output error message in 'perf record', from Adrian Hunter. . Allow specifying B/K/M/G unit to the --mmap-pages arguments, from Jiri Olsa. . Fix command line callchain attribute tests to handle the new -g/--call-chain semantics, from Arnaldo Carvalho de Melo. * 'perf kvm' enhancements: . Disable live kvm command if timerfd is not supported, from David Ahern. . Fix detection of non-core features, from David Ahern. * 'perf list' enhancements: . Add usage to 'perf list', from David Ahern. . Show error in 'perf list' if tracepoints not available, from Pekka Enberg. * 'perf probe' enhancements: . Support "$vars" meta argument syntax for local variables, allowing asking for all possible variables at a given probe point to be collected when it hits, from Masami Hiramatsu. * 'perf sched' enhancements: . Address the root cause of that 'perf sched' stack initialization build slowdown, by programmatically setting a big array after moving the global variable back to the stack. Fix from Adrian Hunter. * 'perf script' enhancements: . Set up output options for in-stream attributes, from Adrian Hunter. . Print addr by default for BTS in 'perf script', from Adrian Juntmer * 'perf stat' enhancements: . Improved messages when doing profiling in all or a subset of CPUs using a workload as the session delimitator, as in: 'perf stat --cpu 0,2 sleep 10s' from Arnaldo Carvalho de Melo. . Add units to nanosec-based counters in 'perf stat', from David Ahern. . Remove bogus info when using 'perf stat' -e cycles/instructions, from Ramkumar Ramachandra. * 'perf lock' enhancements: . 'perf lock' fixes and cleanups, from Davidlohr Bueso. * 'perf test' enhancements: . Fixup PERF_SAMPLE_TRANSACTION handling in sample synthesizing and 'perf test', from Adrian Hunter. . Clarify the "sample parsing" test entry, from Arnaldo Carvalho de Melo. . Consider PERF_SAMPLE_TRANSACTION in the "sample parsing" test, from Arnaldo Carvalho de Melo. . Memory leak fixes in 'perf test', from Felipe Pena. * 'perf bench' enhancements: . Change the procps visible command-name of invididual benchmark tests plus cleanups, from Ingo Molnar. * Generic perf tooling infrastructure/plumbing changes: . Separating data file properties from session, code reorganization from Jiri Olsa. . Fix version when building out of tree, as when using one of these: $ make help | grep perf perf-tar-src-pkg - Build perf-3.12.0.tar source tarball perf-targz-src-pkg - Build perf-3.12.0.tar.gz source tarball perf-tarbz2-src-pkg - Build perf-3.12.0.tar.bz2 source tarball perf-tarxz-src-pkg - Build perf-3.12.0.tar.xz source tarball $ from David Ahern. . Enhance option parse error message, showing just the help lines of the options affected, from Namhyung Kim. . libtraceevent updates from upstream trace-cmd repo, from Steven Rostedt. . Always use perf_evsel__set_sample_bit to set sample_type, from Adrian Hunter. . Memory and mmap leak fixes from Chenggang Qin. . Assorted build fixes for from David Ahern and Jiri Olsa. . Speed up and prettify the build system, from Ingo Molnar. . Implement addr2line directly using libbfd, from Roberto Vitillo. . Separate the GTK support in a separate libperf-gtk.so DSO, that is only loaded when --gtk is specified, from Namhyung Kim. . perf bash completion fixes and improvements from Ramkumar Ramachandra. . Support for Openembedded/Yocto -dbg packages, from Ricardo Ribalda Delgado. And lots and lots of other fixes and code reorganizations that did not make it into the list, see the shortlog, diffstat and the Git log for details!" * 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (300 commits) uprobes: Fix the memory out of bound overwrite in copy_insn() uprobes: Fix the wrong usage of current->utask in uprobe_copy_process() perf tools: Remove unneeded include perf record: Remove post_processing_offset variable perf record: Remove advance_output function perf record: Refactor feature handling into a separate function perf trace: Don't relookup fields by name in each sample perf tools: Fix version when building out of tree perf evsel: Ditch evsel->handler.data field uprobes: Export write_opcode() as uprobe_write_opcode() uprobes: Introduce arch_uprobe->ixol uprobes: Kill module_init() and module_exit() uprobes: Move function declarations out of arch perf/x86/intel: Add Ivy Bridge-EP uncore IRP box support perf/x86/intel/uncore: Add filter support for IvyBridge-EP QPI boxes perf: Factor out strncpy() in perf_event_mmap_event() tools/perf: Add required memory barriers perf: Fix arch_perf_out_copy_user default perf: Update a stale comment perf: Optimize perf_output_begin() -- address calculation ...
-rw-r--r--arch/powerpc/include/asm/uprobes.h8
-rw-r--r--arch/x86/include/asm/uprobes.h12
-rw-r--r--arch/x86/kernel/cpu/perf_event.c4
-rw-r--r--arch/x86/kernel/cpu/perf_event.h6
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel.c78
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_ds.c203
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_lbr.c31
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_uncore.c134
-rw-r--r--arch/x86/lib/usercopy.c43
-rw-r--r--arch/x86/mm/fault.c41
-rw-r--r--arch/x86/oprofile/backtrace.c4
-rw-r--r--include/linux/perf_event.h5
-rw-r--r--include/linux/uprobes.h15
-rw-r--r--include/uapi/linux/perf_event.h25
-rw-r--r--kernel/events/core.c156
-rw-r--r--kernel/events/internal.h35
-rw-r--r--kernel/events/ring_buffer.c101
-rw-r--r--kernel/events/uprobes.c223
-rw-r--r--kernel/fork.c2
-rw-r--r--kernel/sysctl.c1
-rw-r--r--scripts/package/Makefile4
-rw-r--r--tools/lib/traceevent/Makefile18
-rw-r--r--tools/lib/traceevent/event-parse.c165
-rw-r--r--tools/lib/traceevent/event-parse.h14
-rw-r--r--tools/perf/.gitignore1
-rw-r--r--tools/perf/Documentation/Makefile79
-rw-r--r--tools/perf/Documentation/perf-buildid-cache.txt13
-rw-r--r--tools/perf/Documentation/perf-kvm.txt4
-rw-r--r--tools/perf/Documentation/perf-lock.txt2
-rw-r--r--tools/perf/Documentation/perf-record.txt11
-rw-r--r--tools/perf/Documentation/perf-report.txt16
-rw-r--r--tools/perf/Documentation/perf-stat.txt5
-rw-r--r--tools/perf/Documentation/perf-timechart.txt15
-rw-r--r--tools/perf/Documentation/perf-top.txt15
-rw-r--r--tools/perf/Documentation/perf-trace.txt31
-rw-r--r--tools/perf/Makefile848
-rw-r--r--tools/perf/Makefile.perf892
-rw-r--r--tools/perf/arch/x86/include/perf_regs.h6
-rw-r--r--tools/perf/arch/x86/util/unwind.c4
-rw-r--r--tools/perf/bash_completion106
-rw-r--r--tools/perf/bench/mem-memcpy-arch.h2
-rw-r--r--tools/perf/bench/mem-memcpy.c2
-rw-r--r--tools/perf/bench/mem-memset-arch.h2
-rw-r--r--tools/perf/bench/mem-memset.c2
-rw-r--r--tools/perf/bench/numa.c38
-rw-r--r--tools/perf/bench/sched-pipe.c115
-rw-r--r--tools/perf/builtin-annotate.c45
-rw-r--r--tools/perf/builtin-bench.c245
-rw-r--r--tools/perf/builtin-buildid-cache.c156
-rw-r--r--tools/perf/builtin-buildid-list.c11
-rw-r--r--tools/perf/builtin-diff.c31
-rw-r--r--tools/perf/builtin-evlist.c7
-rw-r--r--tools/perf/builtin-inject.c46
-rw-r--r--tools/perf/builtin-kmem.c13
-rw-r--r--tools/perf/builtin-kvm.c30
-rw-r--r--tools/perf/builtin-list.c84
-rw-r--r--tools/perf/builtin-lock.c137
-rw-r--r--tools/perf/builtin-mem.c9
-rw-r--r--tools/perf/builtin-probe.c14
-rw-r--r--tools/perf/builtin-record.c168
-rw-r--r--tools/perf/builtin-report.c124
-rw-r--r--tools/perf/builtin-sched.c70
-rw-r--r--tools/perf/builtin-script.c127
-rw-r--r--tools/perf/builtin-stat.c211
-rw-r--r--tools/perf/builtin-timechart.c14
-rw-r--r--tools/perf/builtin-top.c61
-rw-r--r--tools/perf/builtin-trace.c1403
-rw-r--r--tools/perf/config/Makefile371
-rw-r--r--tools/perf/config/feature-checks/Makefile148
-rw-r--r--tools/perf/config/feature-checks/test-all.c111
-rw-r--r--tools/perf/config/feature-checks/test-backtrace.c13
-rw-r--r--tools/perf/config/feature-checks/test-bionic.c6
-rw-r--r--tools/perf/config/feature-checks/test-cplus-demangle.c14
-rw-r--r--tools/perf/config/feature-checks/test-dwarf.c10
-rw-r--r--tools/perf/config/feature-checks/test-fortify-source.c6
-rw-r--r--tools/perf/config/feature-checks/test-glibc.c8
-rw-r--r--tools/perf/config/feature-checks/test-gtk2-infobar.c11
-rw-r--r--tools/perf/config/feature-checks/test-gtk2.c10
-rw-r--r--tools/perf/config/feature-checks/test-hello.c6
-rw-r--r--tools/perf/config/feature-checks/test-libaudit.c10
-rw-r--r--tools/perf/config/feature-checks/test-libbfd.c15
-rw-r--r--tools/perf/config/feature-checks/test-libelf-getphdrnum.c8
-rw-r--r--tools/perf/config/feature-checks/test-libelf-mmap.c8
-rw-r--r--tools/perf/config/feature-checks/test-libelf.c8
-rw-r--r--tools/perf/config/feature-checks/test-libnuma.c9
-rw-r--r--tools/perf/config/feature-checks/test-libperl.c9
-rw-r--r--tools/perf/config/feature-checks/test-libpython-version.c10
-rw-r--r--tools/perf/config/feature-checks/test-libpython.c8
-rw-r--r--tools/perf/config/feature-checks/test-libslang.c6
-rw-r--r--tools/perf/config/feature-checks/test-libunwind.c27
-rw-r--r--tools/perf/config/feature-checks/test-on-exit.c16
-rw-r--r--tools/perf/config/feature-checks/test-stackprotector-all.c6
-rw-r--r--tools/perf/config/feature-checks/test-stackprotector.c6
-rw-r--r--tools/perf/config/feature-checks/test-timerfd.c18
-rw-r--r--tools/perf/config/feature-checks/test-volatile-register-var.c6
-rw-r--r--tools/perf/config/feature-tests.mak246
-rw-r--r--tools/perf/config/utilities.mak17
-rw-r--r--tools/perf/perf.c14
-rw-r--r--tools/perf/perf.h65
-rw-r--r--tools/perf/scripts/python/Perf-Trace-Util/Context.c6
-rw-r--r--tools/perf/tests/attr/README6
-rw-r--r--tools/perf/tests/attr/test-record-graph-default2
-rw-r--r--tools/perf/tests/attr/test-record-graph-dwarf2
-rw-r--r--tools/perf/tests/attr/test-record-graph-fp2
-rw-r--r--tools/perf/tests/code-reading.c2
-rw-r--r--tools/perf/tests/dso-data.c1
-rw-r--r--tools/perf/tests/hists_link.c14
-rw-r--r--tools/perf/tests/parse-events.c6
-rw-r--r--tools/perf/tests/perf-record.c12
-rw-r--r--tools/perf/tests/rdpmc.c2
-rw-r--r--tools/perf/tests/sample-parsing.c11
-rw-r--r--tools/perf/tests/task-exit.c14
-rw-r--r--tools/perf/ui/browser.h32
-rw-r--r--tools/perf/ui/browsers/annotate.c24
-rw-r--r--tools/perf/ui/browsers/hists.c12
-rw-r--r--tools/perf/ui/browsers/map.c40
-rw-r--r--tools/perf/ui/browsers/map.h2
-rw-r--r--tools/perf/ui/browsers/scripts.c8
-rw-r--r--tools/perf/ui/gtk/annotate.c13
-rw-r--r--tools/perf/ui/gtk/browser.c2
-rw-r--r--tools/perf/ui/gtk/gtk.h22
-rw-r--r--tools/perf/ui/gtk/progress.c20
-rw-r--r--tools/perf/ui/gtk/setup.c2
-rw-r--r--tools/perf/ui/gtk/util.c4
-rw-r--r--tools/perf/ui/hist.c2
-rw-r--r--tools/perf/ui/progress.c32
-rw-r--r--tools/perf/ui/progress.h19
-rw-r--r--tools/perf/ui/setup.c61
-rw-r--r--tools/perf/ui/stdio/hist.c14
-rw-r--r--tools/perf/ui/tui/progress.c15
-rw-r--r--tools/perf/ui/tui/setup.c3
-rw-r--r--tools/perf/ui/tui/tui.h6
-rw-r--r--tools/perf/ui/ui.h14
-rwxr-xr-xtools/perf/util/PERF-VERSION-GEN5
-rw-r--r--tools/perf/util/annotate.c76
-rw-r--r--tools/perf/util/annotate.h26
-rw-r--r--tools/perf/util/build-id.c6
-rw-r--r--tools/perf/util/build-id.h3
-rw-r--r--tools/perf/util/cache.h3
-rw-r--r--tools/perf/util/callchain.c147
-rw-r--r--tools/perf/util/callchain.h11
-rw-r--r--tools/perf/util/color.c11
-rw-r--r--tools/perf/util/color.h2
-rw-r--r--tools/perf/util/comm.c121
-rw-r--r--tools/perf/util/comm.h21
-rw-r--r--tools/perf/util/cpumap.c6
-rw-r--r--tools/perf/util/data.c120
-rw-r--r--tools/perf/util/data.h48
-rw-r--r--tools/perf/util/dso.c50
-rw-r--r--tools/perf/util/dso.h3
-rw-r--r--tools/perf/util/event.c38
-rw-r--r--tools/perf/util/event.h14
-rw-r--r--tools/perf/util/evlist.c249
-rw-r--r--tools/perf/util/evlist.h19
-rw-r--r--tools/perf/util/evsel.c29
-rw-r--r--tools/perf/util/evsel.h11
-rw-r--r--tools/perf/util/fs.c119
-rw-r--r--tools/perf/util/fs.h7
-rwxr-xr-xtools/perf/util/generate-cmdlist.sh4
-rw-r--r--tools/perf/util/header.c22
-rw-r--r--tools/perf/util/hist.c95
-rw-r--r--tools/perf/util/hist.h75
-rw-r--r--tools/perf/util/include/dwarf-regs.h2
-rw-r--r--tools/perf/util/include/linux/compiler.h19
-rw-r--r--tools/perf/util/include/linux/magic.h4
-rw-r--r--tools/perf/util/intlist.c23
-rw-r--r--tools/perf/util/intlist.h2
-rw-r--r--tools/perf/util/machine.c166
-rw-r--r--tools/perf/util/machine.h29
-rw-r--r--tools/perf/util/map.c50
-rw-r--r--tools/perf/util/map.h7
-rw-r--r--tools/perf/util/parse-events.c4
-rw-r--r--tools/perf/util/parse-events.l63
-rw-r--r--tools/perf/util/parse-options.c218
-rw-r--r--tools/perf/util/parse-options.h4
-rw-r--r--tools/perf/util/path.c10
-rw-r--r--tools/perf/util/perf_regs.h4
-rw-r--r--tools/perf/util/pmu.c33
-rw-r--r--tools/perf/util/pmu.h1
-rw-r--r--tools/perf/util/probe-event.c5
-rw-r--r--tools/perf/util/probe-finder.c248
-rw-r--r--tools/perf/util/probe-finder.h15
-rw-r--r--tools/perf/util/pstack.h10
-rw-r--r--tools/perf/util/python-ext-sources2
-rw-r--r--tools/perf/util/python.c8
-rw-r--r--tools/perf/util/rblist.c27
-rw-r--r--tools/perf/util/rblist.h1
-rw-r--r--tools/perf/util/record.c71
-rw-r--r--tools/perf/util/scripting-engines/trace-event-perl.c2
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c4
-rw-r--r--tools/perf/util/session.c278
-rw-r--r--tools/perf/util/session.h38
-rw-r--r--tools/perf/util/sort.c318
-rw-r--r--tools/perf/util/sort.h8
-rw-r--r--tools/perf/util/srcline.c265
-rw-r--r--tools/perf/util/strfilter.c72
-rw-r--r--tools/perf/util/strfilter.h12
-rw-r--r--tools/perf/util/symbol-elf.c607
-rw-r--r--tools/perf/util/symbol-minimal.c15
-rw-r--r--tools/perf/util/symbol.c449
-rw-r--r--tools/perf/util/symbol.h29
-rw-r--r--tools/perf/util/sysfs.c60
-rw-r--r--tools/perf/util/sysfs.h6
-rw-r--r--tools/perf/util/thread.c137
-rw-r--r--tools/perf/util/thread.h20
-rw-r--r--tools/perf/util/top.h1
-rw-r--r--tools/perf/util/trace-event-parse.c36
-rw-r--r--tools/perf/util/trace-event.h9
-rw-r--r--tools/perf/util/unwind.h4
-rw-r--r--tools/perf/util/util.c66
-rw-r--r--tools/perf/util/util.h26
-rw-r--r--tools/scripts/Makefile.include23
212 files changed, 9109 insertions, 3939 deletions
diff --git a/arch/powerpc/include/asm/uprobes.h b/arch/powerpc/include/asm/uprobes.h
index 23016020915e..75c6ecdb8f37 100644
--- a/arch/powerpc/include/asm/uprobes.h
+++ b/arch/powerpc/include/asm/uprobes.h
@@ -37,6 +37,7 @@ typedef ppc_opcode_t uprobe_opcode_t;
37struct arch_uprobe { 37struct arch_uprobe {
38 union { 38 union {
39 u8 insn[MAX_UINSN_BYTES]; 39 u8 insn[MAX_UINSN_BYTES];
40 u8 ixol[MAX_UINSN_BYTES];
40 u32 ainsn; 41 u32 ainsn;
41 }; 42 };
42}; 43};
@@ -45,11 +46,4 @@ struct arch_uprobe_task {
45 unsigned long saved_trap_nr; 46 unsigned long saved_trap_nr;
46}; 47};
47 48
48extern int arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long addr);
49extern int arch_uprobe_pre_xol(struct arch_uprobe *aup, struct pt_regs *regs);
50extern int arch_uprobe_post_xol(struct arch_uprobe *aup, struct pt_regs *regs);
51extern bool arch_uprobe_xol_was_trapped(struct task_struct *tsk);
52extern int arch_uprobe_exception_notify(struct notifier_block *self, unsigned long val, void *data);
53extern void arch_uprobe_abort_xol(struct arch_uprobe *aup, struct pt_regs *regs);
54extern unsigned long arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr, struct pt_regs *regs);
55#endif /* _ASM_UPROBES_H */ 49#endif /* _ASM_UPROBES_H */
diff --git a/arch/x86/include/asm/uprobes.h b/arch/x86/include/asm/uprobes.h
index 6e5197910fd8..3087ea9c5f2e 100644
--- a/arch/x86/include/asm/uprobes.h
+++ b/arch/x86/include/asm/uprobes.h
@@ -35,7 +35,10 @@ typedef u8 uprobe_opcode_t;
35 35
36struct arch_uprobe { 36struct arch_uprobe {
37 u16 fixups; 37 u16 fixups;
38 u8 insn[MAX_UINSN_BYTES]; 38 union {
39 u8 insn[MAX_UINSN_BYTES];
40 u8 ixol[MAX_UINSN_BYTES];
41 };
39#ifdef CONFIG_X86_64 42#ifdef CONFIG_X86_64
40 unsigned long rip_rela_target_address; 43 unsigned long rip_rela_target_address;
41#endif 44#endif
@@ -49,11 +52,4 @@ struct arch_uprobe_task {
49 unsigned int saved_tf; 52 unsigned int saved_tf;
50}; 53};
51 54
52extern int arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long addr);
53extern int arch_uprobe_pre_xol(struct arch_uprobe *aup, struct pt_regs *regs);
54extern int arch_uprobe_post_xol(struct arch_uprobe *aup, struct pt_regs *regs);
55extern bool arch_uprobe_xol_was_trapped(struct task_struct *tsk);
56extern int arch_uprobe_exception_notify(struct notifier_block *self, unsigned long val, void *data);
57extern void arch_uprobe_abort_xol(struct arch_uprobe *aup, struct pt_regs *regs);
58extern unsigned long arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr, struct pt_regs *regs);
59#endif /* _ASM_UPROBES_H */ 55#endif /* _ASM_UPROBES_H */
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index 8a87a3224121..8e132931614d 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -1989,7 +1989,7 @@ perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry *entry)
1989 frame.return_address = 0; 1989 frame.return_address = 0;
1990 1990
1991 bytes = copy_from_user_nmi(&frame, fp, sizeof(frame)); 1991 bytes = copy_from_user_nmi(&frame, fp, sizeof(frame));
1992 if (bytes != sizeof(frame)) 1992 if (bytes != 0)
1993 break; 1993 break;
1994 1994
1995 if (!valid_user_frame(fp, sizeof(frame))) 1995 if (!valid_user_frame(fp, sizeof(frame)))
@@ -2041,7 +2041,7 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
2041 frame.return_address = 0; 2041 frame.return_address = 0;
2042 2042
2043 bytes = copy_from_user_nmi(&frame, fp, sizeof(frame)); 2043 bytes = copy_from_user_nmi(&frame, fp, sizeof(frame));
2044 if (bytes != sizeof(frame)) 2044 if (bytes != 0)
2045 break; 2045 break;
2046 2046
2047 if (!valid_user_frame(fp, sizeof(frame))) 2047 if (!valid_user_frame(fp, sizeof(frame)))
diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h
index cc16faae0538..fd00bb29425d 100644
--- a/arch/x86/kernel/cpu/perf_event.h
+++ b/arch/x86/kernel/cpu/perf_event.h
@@ -164,6 +164,11 @@ struct cpu_hw_events {
164 struct perf_guest_switch_msr guest_switch_msrs[X86_PMC_IDX_MAX]; 164 struct perf_guest_switch_msr guest_switch_msrs[X86_PMC_IDX_MAX];
165 165
166 /* 166 /*
167 * Intel checkpoint mask
168 */
169 u64 intel_cp_status;
170
171 /*
167 * manage shared (per-core, per-cpu) registers 172 * manage shared (per-core, per-cpu) registers
168 * used on Intel NHM/WSM/SNB 173 * used on Intel NHM/WSM/SNB
169 */ 174 */
@@ -440,6 +445,7 @@ struct x86_pmu {
440 int lbr_nr; /* hardware stack size */ 445 int lbr_nr; /* hardware stack size */
441 u64 lbr_sel_mask; /* LBR_SELECT valid bits */ 446 u64 lbr_sel_mask; /* LBR_SELECT valid bits */
442 const int *lbr_sel_map; /* lbr_select mappings */ 447 const int *lbr_sel_map; /* lbr_select mappings */
448 bool lbr_double_abort; /* duplicated lbr aborts */
443 449
444 /* 450 /*
445 * Extra registers for events 451 * Extra registers for events
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c
index f31a1655d1ff..0fa4f242f050 100644
--- a/arch/x86/kernel/cpu/perf_event_intel.c
+++ b/arch/x86/kernel/cpu/perf_event_intel.c
@@ -190,9 +190,9 @@ static struct extra_reg intel_snbep_extra_regs[] __read_mostly = {
190 EVENT_EXTRA_END 190 EVENT_EXTRA_END
191}; 191};
192 192
193EVENT_ATTR_STR(mem-loads, mem_ld_nhm, "event=0x0b,umask=0x10,ldlat=3"); 193EVENT_ATTR_STR(mem-loads, mem_ld_nhm, "event=0x0b,umask=0x10,ldlat=3");
194EVENT_ATTR_STR(mem-loads, mem_ld_snb, "event=0xcd,umask=0x1,ldlat=3"); 194EVENT_ATTR_STR(mem-loads, mem_ld_snb, "event=0xcd,umask=0x1,ldlat=3");
195EVENT_ATTR_STR(mem-stores, mem_st_snb, "event=0xcd,umask=0x2"); 195EVENT_ATTR_STR(mem-stores, mem_st_snb, "event=0xcd,umask=0x2");
196 196
197struct attribute *nhm_events_attrs[] = { 197struct attribute *nhm_events_attrs[] = {
198 EVENT_PTR(mem_ld_nhm), 198 EVENT_PTR(mem_ld_nhm),
@@ -1184,6 +1184,11 @@ static void intel_pmu_disable_fixed(struct hw_perf_event *hwc)
1184 wrmsrl(hwc->config_base, ctrl_val); 1184 wrmsrl(hwc->config_base, ctrl_val);
1185} 1185}
1186 1186
1187static inline bool event_is_checkpointed(struct perf_event *event)
1188{
1189 return (event->hw.config & HSW_IN_TX_CHECKPOINTED) != 0;
1190}
1191
1187static void intel_pmu_disable_event(struct perf_event *event) 1192static void intel_pmu_disable_event(struct perf_event *event)
1188{ 1193{
1189 struct hw_perf_event *hwc = &event->hw; 1194 struct hw_perf_event *hwc = &event->hw;
@@ -1197,6 +1202,7 @@ static void intel_pmu_disable_event(struct perf_event *event)
1197 1202
1198 cpuc->intel_ctrl_guest_mask &= ~(1ull << hwc->idx); 1203 cpuc->intel_ctrl_guest_mask &= ~(1ull << hwc->idx);
1199 cpuc->intel_ctrl_host_mask &= ~(1ull << hwc->idx); 1204 cpuc->intel_ctrl_host_mask &= ~(1ull << hwc->idx);
1205 cpuc->intel_cp_status &= ~(1ull << hwc->idx);
1200 1206
1201 /* 1207 /*
1202 * must disable before any actual event 1208 * must disable before any actual event
@@ -1271,6 +1277,9 @@ static void intel_pmu_enable_event(struct perf_event *event)
1271 if (event->attr.exclude_guest) 1277 if (event->attr.exclude_guest)
1272 cpuc->intel_ctrl_host_mask |= (1ull << hwc->idx); 1278 cpuc->intel_ctrl_host_mask |= (1ull << hwc->idx);
1273 1279
1280 if (unlikely(event_is_checkpointed(event)))
1281 cpuc->intel_cp_status |= (1ull << hwc->idx);
1282
1274 if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) { 1283 if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) {
1275 intel_pmu_enable_fixed(hwc); 1284 intel_pmu_enable_fixed(hwc);
1276 return; 1285 return;
@@ -1289,6 +1298,17 @@ static void intel_pmu_enable_event(struct perf_event *event)
1289int intel_pmu_save_and_restart(struct perf_event *event) 1298int intel_pmu_save_and_restart(struct perf_event *event)
1290{ 1299{
1291 x86_perf_event_update(event); 1300 x86_perf_event_update(event);
1301 /*
1302 * For a checkpointed counter always reset back to 0. This
1303 * avoids a situation where the counter overflows, aborts the
1304 * transaction and is then set back to shortly before the
1305 * overflow, and overflows and aborts again.
1306 */
1307 if (unlikely(event_is_checkpointed(event))) {
1308 /* No race with NMIs because the counter should not be armed */
1309 wrmsrl(event->hw.event_base, 0);
1310 local64_set(&event->hw.prev_count, 0);
1311 }
1292 return x86_perf_event_set_period(event); 1312 return x86_perf_event_set_period(event);
1293} 1313}
1294 1314
@@ -1372,6 +1392,13 @@ again:
1372 x86_pmu.drain_pebs(regs); 1392 x86_pmu.drain_pebs(regs);
1373 } 1393 }
1374 1394
1395 /*
1396 * Checkpointed counters can lead to 'spurious' PMIs because the
1397 * rollback caused by the PMI will have cleared the overflow status
1398 * bit. Therefore always force probe these counters.
1399 */
1400 status |= cpuc->intel_cp_status;
1401
1375 for_each_set_bit(bit, (unsigned long *)&status, X86_PMC_IDX_MAX) { 1402 for_each_set_bit(bit, (unsigned long *)&status, X86_PMC_IDX_MAX) {
1376 struct perf_event *event = cpuc->events[bit]; 1403 struct perf_event *event = cpuc->events[bit];
1377 1404
@@ -1837,6 +1864,20 @@ static int hsw_hw_config(struct perf_event *event)
1837 event->attr.precise_ip > 0)) 1864 event->attr.precise_ip > 0))
1838 return -EOPNOTSUPP; 1865 return -EOPNOTSUPP;
1839 1866
1867 if (event_is_checkpointed(event)) {
1868 /*
1869 * Sampling of checkpointed events can cause situations where
1870 * the CPU constantly aborts because of a overflow, which is
1871 * then checkpointed back and ignored. Forbid checkpointing
1872 * for sampling.
1873 *
1874 * But still allow a long sampling period, so that perf stat
1875 * from KVM works.
1876 */
1877 if (event->attr.sample_period > 0 &&
1878 event->attr.sample_period < 0x7fffffff)
1879 return -EOPNOTSUPP;
1880 }
1840 return 0; 1881 return 0;
1841} 1882}
1842 1883
@@ -2182,10 +2223,36 @@ static __init void intel_nehalem_quirk(void)
2182 } 2223 }
2183} 2224}
2184 2225
2185EVENT_ATTR_STR(mem-loads, mem_ld_hsw, "event=0xcd,umask=0x1,ldlat=3"); 2226EVENT_ATTR_STR(mem-loads, mem_ld_hsw, "event=0xcd,umask=0x1,ldlat=3");
2186EVENT_ATTR_STR(mem-stores, mem_st_hsw, "event=0xd0,umask=0x82") 2227EVENT_ATTR_STR(mem-stores, mem_st_hsw, "event=0xd0,umask=0x82")
2228
2229/* Haswell special events */
2230EVENT_ATTR_STR(tx-start, tx_start, "event=0xc9,umask=0x1");
2231EVENT_ATTR_STR(tx-commit, tx_commit, "event=0xc9,umask=0x2");
2232EVENT_ATTR_STR(tx-abort, tx_abort, "event=0xc9,umask=0x4");
2233EVENT_ATTR_STR(tx-capacity, tx_capacity, "event=0x54,umask=0x2");
2234EVENT_ATTR_STR(tx-conflict, tx_conflict, "event=0x54,umask=0x1");
2235EVENT_ATTR_STR(el-start, el_start, "event=0xc8,umask=0x1");
2236EVENT_ATTR_STR(el-commit, el_commit, "event=0xc8,umask=0x2");
2237EVENT_ATTR_STR(el-abort, el_abort, "event=0xc8,umask=0x4");
2238EVENT_ATTR_STR(el-capacity, el_capacity, "event=0x54,umask=0x2");
2239EVENT_ATTR_STR(el-conflict, el_conflict, "event=0x54,umask=0x1");
2240EVENT_ATTR_STR(cycles-t, cycles_t, "event=0x3c,in_tx=1");
2241EVENT_ATTR_STR(cycles-ct, cycles_ct, "event=0x3c,in_tx=1,in_tx_cp=1");
2187 2242
2188static struct attribute *hsw_events_attrs[] = { 2243static struct attribute *hsw_events_attrs[] = {
2244 EVENT_PTR(tx_start),
2245 EVENT_PTR(tx_commit),
2246 EVENT_PTR(tx_abort),
2247 EVENT_PTR(tx_capacity),
2248 EVENT_PTR(tx_conflict),
2249 EVENT_PTR(el_start),
2250 EVENT_PTR(el_commit),
2251 EVENT_PTR(el_abort),
2252 EVENT_PTR(el_capacity),
2253 EVENT_PTR(el_conflict),
2254 EVENT_PTR(cycles_t),
2255 EVENT_PTR(cycles_ct),
2189 EVENT_PTR(mem_ld_hsw), 2256 EVENT_PTR(mem_ld_hsw),
2190 EVENT_PTR(mem_st_hsw), 2257 EVENT_PTR(mem_st_hsw),
2191 NULL 2258 NULL
@@ -2452,6 +2519,7 @@ __init int intel_pmu_init(void)
2452 x86_pmu.hw_config = hsw_hw_config; 2519 x86_pmu.hw_config = hsw_hw_config;
2453 x86_pmu.get_event_constraints = hsw_get_event_constraints; 2520 x86_pmu.get_event_constraints = hsw_get_event_constraints;
2454 x86_pmu.cpu_events = hsw_events_attrs; 2521 x86_pmu.cpu_events = hsw_events_attrs;
2522 x86_pmu.lbr_double_abort = true;
2455 pr_cont("Haswell events, "); 2523 pr_cont("Haswell events, ");
2456 break; 2524 break;
2457 2525
diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c
index ab3ba1c1b7dd..ae96cfa5eddd 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_ds.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c
@@ -12,6 +12,7 @@
12 12
13#define BTS_BUFFER_SIZE (PAGE_SIZE << 4) 13#define BTS_BUFFER_SIZE (PAGE_SIZE << 4)
14#define PEBS_BUFFER_SIZE PAGE_SIZE 14#define PEBS_BUFFER_SIZE PAGE_SIZE
15#define PEBS_FIXUP_SIZE PAGE_SIZE
15 16
16/* 17/*
17 * pebs_record_32 for p4 and core not supported 18 * pebs_record_32 for p4 and core not supported
@@ -182,18 +183,32 @@ struct pebs_record_nhm {
182 * Same as pebs_record_nhm, with two additional fields. 183 * Same as pebs_record_nhm, with two additional fields.
183 */ 184 */
184struct pebs_record_hsw { 185struct pebs_record_hsw {
185 struct pebs_record_nhm nhm; 186 u64 flags, ip;
186 /* 187 u64 ax, bx, cx, dx;
187 * Real IP of the event. In the Intel documentation this 188 u64 si, di, bp, sp;
188 * is called eventingrip. 189 u64 r8, r9, r10, r11;
189 */ 190 u64 r12, r13, r14, r15;
190 u64 real_ip; 191 u64 status, dla, dse, lat;
191 /* 192 u64 real_ip, tsx_tuning;
192 * TSX tuning information field: abort cycles and abort flags. 193};
193 */ 194
194 u64 tsx_tuning; 195union hsw_tsx_tuning {
196 struct {
197 u32 cycles_last_block : 32,
198 hle_abort : 1,
199 rtm_abort : 1,
200 instruction_abort : 1,
201 non_instruction_abort : 1,
202 retry : 1,
203 data_conflict : 1,
204 capacity_writes : 1,
205 capacity_reads : 1;
206 };
207 u64 value;
195}; 208};
196 209
210#define PEBS_HSW_TSX_FLAGS 0xff00000000ULL
211
197void init_debug_store_on_cpu(int cpu) 212void init_debug_store_on_cpu(int cpu)
198{ 213{
199 struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds; 214 struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds;
@@ -214,12 +229,14 @@ void fini_debug_store_on_cpu(int cpu)
214 wrmsr_on_cpu(cpu, MSR_IA32_DS_AREA, 0, 0); 229 wrmsr_on_cpu(cpu, MSR_IA32_DS_AREA, 0, 0);
215} 230}
216 231
232static DEFINE_PER_CPU(void *, insn_buffer);
233
217static int alloc_pebs_buffer(int cpu) 234static int alloc_pebs_buffer(int cpu)
218{ 235{
219 struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds; 236 struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds;
220 int node = cpu_to_node(cpu); 237 int node = cpu_to_node(cpu);
221 int max, thresh = 1; /* always use a single PEBS record */ 238 int max, thresh = 1; /* always use a single PEBS record */
222 void *buffer; 239 void *buffer, *ibuffer;
223 240
224 if (!x86_pmu.pebs) 241 if (!x86_pmu.pebs)
225 return 0; 242 return 0;
@@ -228,6 +245,19 @@ static int alloc_pebs_buffer(int cpu)
228 if (unlikely(!buffer)) 245 if (unlikely(!buffer))
229 return -ENOMEM; 246 return -ENOMEM;
230 247
248 /*
249 * HSW+ already provides us the eventing ip; no need to allocate this
250 * buffer then.
251 */
252 if (x86_pmu.intel_cap.pebs_format < 2) {
253 ibuffer = kzalloc_node(PEBS_FIXUP_SIZE, GFP_KERNEL, node);
254 if (!ibuffer) {
255 kfree(buffer);
256 return -ENOMEM;
257 }
258 per_cpu(insn_buffer, cpu) = ibuffer;
259 }
260
231 max = PEBS_BUFFER_SIZE / x86_pmu.pebs_record_size; 261 max = PEBS_BUFFER_SIZE / x86_pmu.pebs_record_size;
232 262
233 ds->pebs_buffer_base = (u64)(unsigned long)buffer; 263 ds->pebs_buffer_base = (u64)(unsigned long)buffer;
@@ -248,6 +278,9 @@ static void release_pebs_buffer(int cpu)
248 if (!ds || !x86_pmu.pebs) 278 if (!ds || !x86_pmu.pebs)
249 return; 279 return;
250 280
281 kfree(per_cpu(insn_buffer, cpu));
282 per_cpu(insn_buffer, cpu) = NULL;
283
251 kfree((void *)(unsigned long)ds->pebs_buffer_base); 284 kfree((void *)(unsigned long)ds->pebs_buffer_base);
252 ds->pebs_buffer_base = 0; 285 ds->pebs_buffer_base = 0;
253} 286}
@@ -715,6 +748,7 @@ static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs)
715 unsigned long old_to, to = cpuc->lbr_entries[0].to; 748 unsigned long old_to, to = cpuc->lbr_entries[0].to;
716 unsigned long ip = regs->ip; 749 unsigned long ip = regs->ip;
717 int is_64bit = 0; 750 int is_64bit = 0;
751 void *kaddr;
718 752
719 /* 753 /*
720 * We don't need to fixup if the PEBS assist is fault like 754 * We don't need to fixup if the PEBS assist is fault like
@@ -738,7 +772,7 @@ static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs)
738 * unsigned math, either ip is before the start (impossible) or 772 * unsigned math, either ip is before the start (impossible) or
739 * the basic block is larger than 1 page (sanity) 773 * the basic block is larger than 1 page (sanity)
740 */ 774 */
741 if ((ip - to) > PAGE_SIZE) 775 if ((ip - to) > PEBS_FIXUP_SIZE)
742 return 0; 776 return 0;
743 777
744 /* 778 /*
@@ -749,29 +783,33 @@ static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs)
749 return 1; 783 return 1;
750 } 784 }
751 785
786 if (!kernel_ip(ip)) {
787 int size, bytes;
788 u8 *buf = this_cpu_read(insn_buffer);
789
790 size = ip - to; /* Must fit our buffer, see above */
791 bytes = copy_from_user_nmi(buf, (void __user *)to, size);
792 if (bytes != 0)
793 return 0;
794
795 kaddr = buf;
796 } else {
797 kaddr = (void *)to;
798 }
799
752 do { 800 do {
753 struct insn insn; 801 struct insn insn;
754 u8 buf[MAX_INSN_SIZE];
755 void *kaddr;
756 802
757 old_to = to; 803 old_to = to;
758 if (!kernel_ip(ip)) {
759 int bytes, size = MAX_INSN_SIZE;
760
761 bytes = copy_from_user_nmi(buf, (void __user *)to, size);
762 if (bytes != size)
763 return 0;
764
765 kaddr = buf;
766 } else
767 kaddr = (void *)to;
768 804
769#ifdef CONFIG_X86_64 805#ifdef CONFIG_X86_64
770 is_64bit = kernel_ip(to) || !test_thread_flag(TIF_IA32); 806 is_64bit = kernel_ip(to) || !test_thread_flag(TIF_IA32);
771#endif 807#endif
772 insn_init(&insn, kaddr, is_64bit); 808 insn_init(&insn, kaddr, is_64bit);
773 insn_get_length(&insn); 809 insn_get_length(&insn);
810
774 to += insn.length; 811 to += insn.length;
812 kaddr += insn.length;
775 } while (to < ip); 813 } while (to < ip);
776 814
777 if (to == ip) { 815 if (to == ip) {
@@ -786,16 +824,34 @@ static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs)
786 return 0; 824 return 0;
787} 825}
788 826
827static inline u64 intel_hsw_weight(struct pebs_record_hsw *pebs)
828{
829 if (pebs->tsx_tuning) {
830 union hsw_tsx_tuning tsx = { .value = pebs->tsx_tuning };
831 return tsx.cycles_last_block;
832 }
833 return 0;
834}
835
836static inline u64 intel_hsw_transaction(struct pebs_record_hsw *pebs)
837{
838 u64 txn = (pebs->tsx_tuning & PEBS_HSW_TSX_FLAGS) >> 32;
839
840 /* For RTM XABORTs also log the abort code from AX */
841 if ((txn & PERF_TXN_TRANSACTION) && (pebs->ax & 1))
842 txn |= ((pebs->ax >> 24) & 0xff) << PERF_TXN_ABORT_SHIFT;
843 return txn;
844}
845
789static void __intel_pmu_pebs_event(struct perf_event *event, 846static void __intel_pmu_pebs_event(struct perf_event *event,
790 struct pt_regs *iregs, void *__pebs) 847 struct pt_regs *iregs, void *__pebs)
791{ 848{
792 /* 849 /*
793 * We cast to pebs_record_nhm to get the load latency data 850 * We cast to the biggest pebs_record but are careful not to
794 * if extra_reg MSR_PEBS_LD_LAT_THRESHOLD used 851 * unconditionally access the 'extra' entries.
795 */ 852 */
796 struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); 853 struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
797 struct pebs_record_nhm *pebs = __pebs; 854 struct pebs_record_hsw *pebs = __pebs;
798 struct pebs_record_hsw *pebs_hsw = __pebs;
799 struct perf_sample_data data; 855 struct perf_sample_data data;
800 struct pt_regs regs; 856 struct pt_regs regs;
801 u64 sample_type; 857 u64 sample_type;
@@ -854,7 +910,7 @@ static void __intel_pmu_pebs_event(struct perf_event *event,
854 regs.sp = pebs->sp; 910 regs.sp = pebs->sp;
855 911
856 if (event->attr.precise_ip > 1 && x86_pmu.intel_cap.pebs_format >= 2) { 912 if (event->attr.precise_ip > 1 && x86_pmu.intel_cap.pebs_format >= 2) {
857 regs.ip = pebs_hsw->real_ip; 913 regs.ip = pebs->real_ip;
858 regs.flags |= PERF_EFLAGS_EXACT; 914 regs.flags |= PERF_EFLAGS_EXACT;
859 } else if (event->attr.precise_ip > 1 && intel_pmu_pebs_fixup_ip(&regs)) 915 } else if (event->attr.precise_ip > 1 && intel_pmu_pebs_fixup_ip(&regs))
860 regs.flags |= PERF_EFLAGS_EXACT; 916 regs.flags |= PERF_EFLAGS_EXACT;
@@ -862,9 +918,18 @@ static void __intel_pmu_pebs_event(struct perf_event *event,
862 regs.flags &= ~PERF_EFLAGS_EXACT; 918 regs.flags &= ~PERF_EFLAGS_EXACT;
863 919
864 if ((event->attr.sample_type & PERF_SAMPLE_ADDR) && 920 if ((event->attr.sample_type & PERF_SAMPLE_ADDR) &&
865 x86_pmu.intel_cap.pebs_format >= 1) 921 x86_pmu.intel_cap.pebs_format >= 1)
866 data.addr = pebs->dla; 922 data.addr = pebs->dla;
867 923
924 if (x86_pmu.intel_cap.pebs_format >= 2) {
925 /* Only set the TSX weight when no memory weight. */
926 if ((event->attr.sample_type & PERF_SAMPLE_WEIGHT) && !fll)
927 data.weight = intel_hsw_weight(pebs);
928
929 if (event->attr.sample_type & PERF_SAMPLE_TRANSACTION)
930 data.txn = intel_hsw_transaction(pebs);
931 }
932
868 if (has_branch_stack(event)) 933 if (has_branch_stack(event))
869 data.br_stack = &cpuc->lbr_stack; 934 data.br_stack = &cpuc->lbr_stack;
870 935
@@ -913,17 +978,34 @@ static void intel_pmu_drain_pebs_core(struct pt_regs *iregs)
913 __intel_pmu_pebs_event(event, iregs, at); 978 __intel_pmu_pebs_event(event, iregs, at);
914} 979}
915 980
916static void __intel_pmu_drain_pebs_nhm(struct pt_regs *iregs, void *at, 981static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs)
917 void *top)
918{ 982{
919 struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); 983 struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
920 struct debug_store *ds = cpuc->ds; 984 struct debug_store *ds = cpuc->ds;
921 struct perf_event *event = NULL; 985 struct perf_event *event = NULL;
986 void *at, *top;
922 u64 status = 0; 987 u64 status = 0;
923 int bit; 988 int bit;
924 989
990 if (!x86_pmu.pebs_active)
991 return;
992
993 at = (struct pebs_record_nhm *)(unsigned long)ds->pebs_buffer_base;
994 top = (struct pebs_record_nhm *)(unsigned long)ds->pebs_index;
995
925 ds->pebs_index = ds->pebs_buffer_base; 996 ds->pebs_index = ds->pebs_buffer_base;
926 997
998 if (unlikely(at > top))
999 return;
1000
1001 /*
1002 * Should not happen, we program the threshold at 1 and do not
1003 * set a reset value.
1004 */
1005 WARN_ONCE(top - at > x86_pmu.max_pebs_events * x86_pmu.pebs_record_size,
1006 "Unexpected number of pebs records %ld\n",
1007 (long)(top - at) / x86_pmu.pebs_record_size);
1008
927 for (; at < top; at += x86_pmu.pebs_record_size) { 1009 for (; at < top; at += x86_pmu.pebs_record_size) {
928 struct pebs_record_nhm *p = at; 1010 struct pebs_record_nhm *p = at;
929 1011
@@ -951,61 +1033,6 @@ static void __intel_pmu_drain_pebs_nhm(struct pt_regs *iregs, void *at,
951 } 1033 }
952} 1034}
953 1035
954static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs)
955{
956 struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
957 struct debug_store *ds = cpuc->ds;
958 struct pebs_record_nhm *at, *top;
959 int n;
960
961 if (!x86_pmu.pebs_active)
962 return;
963
964 at = (struct pebs_record_nhm *)(unsigned long)ds->pebs_buffer_base;
965 top = (struct pebs_record_nhm *)(unsigned long)ds->pebs_index;
966
967 ds->pebs_index = ds->pebs_buffer_base;
968
969 n = top - at;
970 if (n <= 0)
971 return;
972
973 /*
974 * Should not happen, we program the threshold at 1 and do not
975 * set a reset value.
976 */
977 WARN_ONCE(n > x86_pmu.max_pebs_events,
978 "Unexpected number of pebs records %d\n", n);
979
980 return __intel_pmu_drain_pebs_nhm(iregs, at, top);
981}
982
983static void intel_pmu_drain_pebs_hsw(struct pt_regs *iregs)
984{
985 struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
986 struct debug_store *ds = cpuc->ds;
987 struct pebs_record_hsw *at, *top;
988 int n;
989
990 if (!x86_pmu.pebs_active)
991 return;
992
993 at = (struct pebs_record_hsw *)(unsigned long)ds->pebs_buffer_base;
994 top = (struct pebs_record_hsw *)(unsigned long)ds->pebs_index;
995
996 n = top - at;
997 if (n <= 0)
998 return;
999 /*
1000 * Should not happen, we program the threshold at 1 and do not
1001 * set a reset value.
1002 */
1003 WARN_ONCE(n > x86_pmu.max_pebs_events,
1004 "Unexpected number of pebs records %d\n", n);
1005
1006 return __intel_pmu_drain_pebs_nhm(iregs, at, top);
1007}
1008
1009/* 1036/*
1010 * BTS, PEBS probe and setup 1037 * BTS, PEBS probe and setup
1011 */ 1038 */
@@ -1040,7 +1067,7 @@ void intel_ds_init(void)
1040 case 2: 1067 case 2:
1041 pr_cont("PEBS fmt2%c, ", pebs_type); 1068 pr_cont("PEBS fmt2%c, ", pebs_type);
1042 x86_pmu.pebs_record_size = sizeof(struct pebs_record_hsw); 1069 x86_pmu.pebs_record_size = sizeof(struct pebs_record_hsw);
1043 x86_pmu.drain_pebs = intel_pmu_drain_pebs_hsw; 1070 x86_pmu.drain_pebs = intel_pmu_drain_pebs_nhm;
1044 break; 1071 break;
1045 1072
1046 default: 1073 default:
diff --git a/arch/x86/kernel/cpu/perf_event_intel_lbr.c b/arch/x86/kernel/cpu/perf_event_intel_lbr.c
index d5be06a5005e..d82d155aca8c 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_lbr.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_lbr.c
@@ -284,6 +284,7 @@ static void intel_pmu_lbr_read_64(struct cpu_hw_events *cpuc)
284 int lbr_format = x86_pmu.intel_cap.lbr_format; 284 int lbr_format = x86_pmu.intel_cap.lbr_format;
285 u64 tos = intel_pmu_lbr_tos(); 285 u64 tos = intel_pmu_lbr_tos();
286 int i; 286 int i;
287 int out = 0;
287 288
288 for (i = 0; i < x86_pmu.lbr_nr; i++) { 289 for (i = 0; i < x86_pmu.lbr_nr; i++) {
289 unsigned long lbr_idx = (tos - i) & mask; 290 unsigned long lbr_idx = (tos - i) & mask;
@@ -306,15 +307,27 @@ static void intel_pmu_lbr_read_64(struct cpu_hw_events *cpuc)
306 } 307 }
307 from = (u64)((((s64)from) << skip) >> skip); 308 from = (u64)((((s64)from) << skip) >> skip);
308 309
309 cpuc->lbr_entries[i].from = from; 310 /*
310 cpuc->lbr_entries[i].to = to; 311 * Some CPUs report duplicated abort records,
311 cpuc->lbr_entries[i].mispred = mis; 312 * with the second entry not having an abort bit set.
312 cpuc->lbr_entries[i].predicted = pred; 313 * Skip them here. This loop runs backwards,
313 cpuc->lbr_entries[i].in_tx = in_tx; 314 * so we need to undo the previous record.
314 cpuc->lbr_entries[i].abort = abort; 315 * If the abort just happened outside the window
315 cpuc->lbr_entries[i].reserved = 0; 316 * the extra entry cannot be removed.
317 */
318 if (abort && x86_pmu.lbr_double_abort && out > 0)
319 out--;
320
321 cpuc->lbr_entries[out].from = from;
322 cpuc->lbr_entries[out].to = to;
323 cpuc->lbr_entries[out].mispred = mis;
324 cpuc->lbr_entries[out].predicted = pred;
325 cpuc->lbr_entries[out].in_tx = in_tx;
326 cpuc->lbr_entries[out].abort = abort;
327 cpuc->lbr_entries[out].reserved = 0;
328 out++;
316 } 329 }
317 cpuc->lbr_stack.nr = i; 330 cpuc->lbr_stack.nr = out;
318} 331}
319 332
320void intel_pmu_lbr_read(void) 333void intel_pmu_lbr_read(void)
@@ -478,7 +491,7 @@ static int branch_type(unsigned long from, unsigned long to, int abort)
478 491
479 /* may fail if text not present */ 492 /* may fail if text not present */
480 bytes = copy_from_user_nmi(buf, (void __user *)from, size); 493 bytes = copy_from_user_nmi(buf, (void __user *)from, size);
481 if (bytes != size) 494 if (bytes != 0)
482 return X86_BR_NONE; 495 return X86_BR_NONE;
483 496
484 addr = buf; 497 addr = buf;
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c
index 4118f9f68315..29c248799ced 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c
@@ -997,6 +997,20 @@ static int snbep_pci2phy_map_init(int devid)
997 } 997 }
998 } 998 }
999 999
1000 if (!err) {
1001 /*
1002 * For PCI bus with no UBOX device, find the next bus
1003 * that has UBOX device and use its mapping.
1004 */
1005 i = -1;
1006 for (bus = 255; bus >= 0; bus--) {
1007 if (pcibus_to_physid[bus] >= 0)
1008 i = pcibus_to_physid[bus];
1009 else
1010 pcibus_to_physid[bus] = i;
1011 }
1012 }
1013
1000 if (ubox_dev) 1014 if (ubox_dev)
1001 pci_dev_put(ubox_dev); 1015 pci_dev_put(ubox_dev);
1002 1016
@@ -1099,6 +1113,24 @@ static struct attribute *ivt_uncore_qpi_formats_attr[] = {
1099 &format_attr_umask.attr, 1113 &format_attr_umask.attr,
1100 &format_attr_edge.attr, 1114 &format_attr_edge.attr,
1101 &format_attr_thresh8.attr, 1115 &format_attr_thresh8.attr,
1116 &format_attr_match_rds.attr,
1117 &format_attr_match_rnid30.attr,
1118 &format_attr_match_rnid4.attr,
1119 &format_attr_match_dnid.attr,
1120 &format_attr_match_mc.attr,
1121 &format_attr_match_opc.attr,
1122 &format_attr_match_vnw.attr,
1123 &format_attr_match0.attr,
1124 &format_attr_match1.attr,
1125 &format_attr_mask_rds.attr,
1126 &format_attr_mask_rnid30.attr,
1127 &format_attr_mask_rnid4.attr,
1128 &format_attr_mask_dnid.attr,
1129 &format_attr_mask_mc.attr,
1130 &format_attr_mask_opc.attr,
1131 &format_attr_mask_vnw.attr,
1132 &format_attr_mask0.attr,
1133 &format_attr_mask1.attr,
1102 NULL, 1134 NULL,
1103}; 1135};
1104 1136
@@ -1312,17 +1344,83 @@ static struct intel_uncore_type ivt_uncore_imc = {
1312 IVT_UNCORE_PCI_COMMON_INIT(), 1344 IVT_UNCORE_PCI_COMMON_INIT(),
1313}; 1345};
1314 1346
1347/* registers in IRP boxes are not properly aligned */
1348static unsigned ivt_uncore_irp_ctls[] = {0xd8, 0xdc, 0xe0, 0xe4};
1349static unsigned ivt_uncore_irp_ctrs[] = {0xa0, 0xb0, 0xb8, 0xc0};
1350
1351static void ivt_uncore_irp_enable_event(struct intel_uncore_box *box, struct perf_event *event)
1352{
1353 struct pci_dev *pdev = box->pci_dev;
1354 struct hw_perf_event *hwc = &event->hw;
1355
1356 pci_write_config_dword(pdev, ivt_uncore_irp_ctls[hwc->idx],
1357 hwc->config | SNBEP_PMON_CTL_EN);
1358}
1359
1360static void ivt_uncore_irp_disable_event(struct intel_uncore_box *box, struct perf_event *event)
1361{
1362 struct pci_dev *pdev = box->pci_dev;
1363 struct hw_perf_event *hwc = &event->hw;
1364
1365 pci_write_config_dword(pdev, ivt_uncore_irp_ctls[hwc->idx], hwc->config);
1366}
1367
1368static u64 ivt_uncore_irp_read_counter(struct intel_uncore_box *box, struct perf_event *event)
1369{
1370 struct pci_dev *pdev = box->pci_dev;
1371 struct hw_perf_event *hwc = &event->hw;
1372 u64 count = 0;
1373
1374 pci_read_config_dword(pdev, ivt_uncore_irp_ctrs[hwc->idx], (u32 *)&count);
1375 pci_read_config_dword(pdev, ivt_uncore_irp_ctrs[hwc->idx] + 4, (u32 *)&count + 1);
1376
1377 return count;
1378}
1379
1380static struct intel_uncore_ops ivt_uncore_irp_ops = {
1381 .init_box = ivt_uncore_pci_init_box,
1382 .disable_box = snbep_uncore_pci_disable_box,
1383 .enable_box = snbep_uncore_pci_enable_box,
1384 .disable_event = ivt_uncore_irp_disable_event,
1385 .enable_event = ivt_uncore_irp_enable_event,
1386 .read_counter = ivt_uncore_irp_read_counter,
1387};
1388
1389static struct intel_uncore_type ivt_uncore_irp = {
1390 .name = "irp",
1391 .num_counters = 4,
1392 .num_boxes = 1,
1393 .perf_ctr_bits = 48,
1394 .event_mask = IVT_PMON_RAW_EVENT_MASK,
1395 .box_ctl = SNBEP_PCI_PMON_BOX_CTL,
1396 .ops = &ivt_uncore_irp_ops,
1397 .format_group = &ivt_uncore_format_group,
1398};
1399
1400static struct intel_uncore_ops ivt_uncore_qpi_ops = {
1401 .init_box = ivt_uncore_pci_init_box,
1402 .disable_box = snbep_uncore_pci_disable_box,
1403 .enable_box = snbep_uncore_pci_enable_box,
1404 .disable_event = snbep_uncore_pci_disable_event,
1405 .enable_event = snbep_qpi_enable_event,
1406 .read_counter = snbep_uncore_pci_read_counter,
1407 .hw_config = snbep_qpi_hw_config,
1408 .get_constraint = uncore_get_constraint,
1409 .put_constraint = uncore_put_constraint,
1410};
1411
1315static struct intel_uncore_type ivt_uncore_qpi = { 1412static struct intel_uncore_type ivt_uncore_qpi = {
1316 .name = "qpi", 1413 .name = "qpi",
1317 .num_counters = 4, 1414 .num_counters = 4,
1318 .num_boxes = 3, 1415 .num_boxes = 3,
1319 .perf_ctr_bits = 48, 1416 .perf_ctr_bits = 48,
1320 .perf_ctr = SNBEP_PCI_PMON_CTR0, 1417 .perf_ctr = SNBEP_PCI_PMON_CTR0,
1321 .event_ctl = SNBEP_PCI_PMON_CTL0, 1418 .event_ctl = SNBEP_PCI_PMON_CTL0,
1322 .event_mask = IVT_QPI_PCI_PMON_RAW_EVENT_MASK, 1419 .event_mask = IVT_QPI_PCI_PMON_RAW_EVENT_MASK,
1323 .box_ctl = SNBEP_PCI_PMON_BOX_CTL, 1420 .box_ctl = SNBEP_PCI_PMON_BOX_CTL,
1324 .ops = &ivt_uncore_pci_ops, 1421 .num_shared_regs = 1,
1325 .format_group = &ivt_uncore_qpi_format_group, 1422 .ops = &ivt_uncore_qpi_ops,
1423 .format_group = &ivt_uncore_qpi_format_group,
1326}; 1424};
1327 1425
1328static struct intel_uncore_type ivt_uncore_r2pcie = { 1426static struct intel_uncore_type ivt_uncore_r2pcie = {
@@ -1346,6 +1444,7 @@ static struct intel_uncore_type ivt_uncore_r3qpi = {
1346enum { 1444enum {
1347 IVT_PCI_UNCORE_HA, 1445 IVT_PCI_UNCORE_HA,
1348 IVT_PCI_UNCORE_IMC, 1446 IVT_PCI_UNCORE_IMC,
1447 IVT_PCI_UNCORE_IRP,
1349 IVT_PCI_UNCORE_QPI, 1448 IVT_PCI_UNCORE_QPI,
1350 IVT_PCI_UNCORE_R2PCIE, 1449 IVT_PCI_UNCORE_R2PCIE,
1351 IVT_PCI_UNCORE_R3QPI, 1450 IVT_PCI_UNCORE_R3QPI,
@@ -1354,6 +1453,7 @@ enum {
1354static struct intel_uncore_type *ivt_pci_uncores[] = { 1453static struct intel_uncore_type *ivt_pci_uncores[] = {
1355 [IVT_PCI_UNCORE_HA] = &ivt_uncore_ha, 1454 [IVT_PCI_UNCORE_HA] = &ivt_uncore_ha,
1356 [IVT_PCI_UNCORE_IMC] = &ivt_uncore_imc, 1455 [IVT_PCI_UNCORE_IMC] = &ivt_uncore_imc,
1456 [IVT_PCI_UNCORE_IRP] = &ivt_uncore_irp,
1357 [IVT_PCI_UNCORE_QPI] = &ivt_uncore_qpi, 1457 [IVT_PCI_UNCORE_QPI] = &ivt_uncore_qpi,
1358 [IVT_PCI_UNCORE_R2PCIE] = &ivt_uncore_r2pcie, 1458 [IVT_PCI_UNCORE_R2PCIE] = &ivt_uncore_r2pcie,
1359 [IVT_PCI_UNCORE_R3QPI] = &ivt_uncore_r3qpi, 1459 [IVT_PCI_UNCORE_R3QPI] = &ivt_uncore_r3qpi,
@@ -1401,6 +1501,10 @@ static DEFINE_PCI_DEVICE_TABLE(ivt_uncore_pci_ids) = {
1401 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xef1), 1501 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xef1),
1402 .driver_data = UNCORE_PCI_DEV_DATA(IVT_PCI_UNCORE_IMC, 7), 1502 .driver_data = UNCORE_PCI_DEV_DATA(IVT_PCI_UNCORE_IMC, 7),
1403 }, 1503 },
1504 { /* IRP */
1505 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe39),
1506 .driver_data = UNCORE_PCI_DEV_DATA(IVT_PCI_UNCORE_IRP, 0),
1507 },
1404 { /* QPI0 Port 0 */ 1508 { /* QPI0 Port 0 */
1405 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe32), 1509 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe32),
1406 .driver_data = UNCORE_PCI_DEV_DATA(IVT_PCI_UNCORE_QPI, 0), 1510 .driver_data = UNCORE_PCI_DEV_DATA(IVT_PCI_UNCORE_QPI, 0),
@@ -1429,6 +1533,16 @@ static DEFINE_PCI_DEVICE_TABLE(ivt_uncore_pci_ids) = {
1429 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe3e), 1533 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe3e),
1430 .driver_data = UNCORE_PCI_DEV_DATA(IVT_PCI_UNCORE_R3QPI, 2), 1534 .driver_data = UNCORE_PCI_DEV_DATA(IVT_PCI_UNCORE_R3QPI, 2),
1431 }, 1535 },
1536 { /* QPI Port 0 filter */
1537 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe86),
1538 .driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV,
1539 SNBEP_PCI_QPI_PORT0_FILTER),
1540 },
1541 { /* QPI Port 0 filter */
1542 PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe96),
1543 .driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV,
1544 SNBEP_PCI_QPI_PORT1_FILTER),
1545 },
1432 { /* end: all zeroes */ } 1546 { /* end: all zeroes */ }
1433}; 1547};
1434 1548
diff --git a/arch/x86/lib/usercopy.c b/arch/x86/lib/usercopy.c
index 4f74d94c8d97..ddf9ecb53cc3 100644
--- a/arch/x86/lib/usercopy.c
+++ b/arch/x86/lib/usercopy.c
@@ -11,39 +11,26 @@
11#include <linux/sched.h> 11#include <linux/sched.h>
12 12
13/* 13/*
14 * best effort, GUP based copy_from_user() that is NMI-safe 14 * We rely on the nested NMI work to allow atomic faults from the NMI path; the
15 * nested NMI paths are careful to preserve CR2.
15 */ 16 */
16unsigned long 17unsigned long
17copy_from_user_nmi(void *to, const void __user *from, unsigned long n) 18copy_from_user_nmi(void *to, const void __user *from, unsigned long n)
18{ 19{
19 unsigned long offset, addr = (unsigned long)from; 20 unsigned long ret;
20 unsigned long size, len = 0;
21 struct page *page;
22 void *map;
23 int ret;
24 21
25 if (__range_not_ok(from, n, TASK_SIZE)) 22 if (__range_not_ok(from, n, TASK_SIZE))
26 return len; 23 return 0;
27 24
28 do { 25 /*
29 ret = __get_user_pages_fast(addr, 1, 0, &page); 26 * Even though this function is typically called from NMI/IRQ context
30 if (!ret) 27 * disable pagefaults so that its behaviour is consistent even when
31 break; 28 * called form other contexts.
32 29 */
33 offset = addr & (PAGE_SIZE - 1); 30 pagefault_disable();
34 size = min(PAGE_SIZE - offset, n - len); 31 ret = __copy_from_user_inatomic(to, from, n);
35 32 pagefault_enable();
36 map = kmap_atomic(page); 33
37 memcpy(to, map+offset, size); 34 return ret;
38 kunmap_atomic(map);
39 put_page(page);
40
41 len += size;
42 to += size;
43 addr += size;
44
45 } while (len < n);
46
47 return len;
48} 35}
49EXPORT_SYMBOL_GPL(copy_from_user_nmi); 36EXPORT_SYMBOL_GPL(copy_from_user_nmi);
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index 3aaeffcfd67a..7a517bb41060 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -51,7 +51,7 @@ kmmio_fault(struct pt_regs *regs, unsigned long addr)
51 return 0; 51 return 0;
52} 52}
53 53
54static inline int __kprobes notify_page_fault(struct pt_regs *regs) 54static inline int __kprobes kprobes_fault(struct pt_regs *regs)
55{ 55{
56 int ret = 0; 56 int ret = 0;
57 57
@@ -1048,7 +1048,7 @@ __do_page_fault(struct pt_regs *regs, unsigned long error_code)
1048 return; 1048 return;
1049 1049
1050 /* kprobes don't want to hook the spurious faults: */ 1050 /* kprobes don't want to hook the spurious faults: */
1051 if (notify_page_fault(regs)) 1051 if (kprobes_fault(regs))
1052 return; 1052 return;
1053 /* 1053 /*
1054 * Don't take the mm semaphore here. If we fixup a prefetch 1054 * Don't take the mm semaphore here. If we fixup a prefetch
@@ -1060,23 +1060,8 @@ __do_page_fault(struct pt_regs *regs, unsigned long error_code)
1060 } 1060 }
1061 1061
1062 /* kprobes don't want to hook the spurious faults: */ 1062 /* kprobes don't want to hook the spurious faults: */
1063 if (unlikely(notify_page_fault(regs))) 1063 if (unlikely(kprobes_fault(regs)))
1064 return; 1064 return;
1065 /*
1066 * It's safe to allow irq's after cr2 has been saved and the
1067 * vmalloc fault has been handled.
1068 *
1069 * User-mode registers count as a user access even for any
1070 * potential system fault or CPU buglet:
1071 */
1072 if (user_mode_vm(regs)) {
1073 local_irq_enable();
1074 error_code |= PF_USER;
1075 flags |= FAULT_FLAG_USER;
1076 } else {
1077 if (regs->flags & X86_EFLAGS_IF)
1078 local_irq_enable();
1079 }
1080 1065
1081 if (unlikely(error_code & PF_RSVD)) 1066 if (unlikely(error_code & PF_RSVD))
1082 pgtable_bad(regs, error_code, address); 1067 pgtable_bad(regs, error_code, address);
@@ -1088,8 +1073,6 @@ __do_page_fault(struct pt_regs *regs, unsigned long error_code)
1088 } 1073 }
1089 } 1074 }
1090 1075
1091 perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
1092
1093 /* 1076 /*
1094 * If we're in an interrupt, have no user context or are running 1077 * If we're in an interrupt, have no user context or are running
1095 * in an atomic region then we must not take the fault: 1078 * in an atomic region then we must not take the fault:
@@ -1099,6 +1082,24 @@ __do_page_fault(struct pt_regs *regs, unsigned long error_code)
1099 return; 1082 return;
1100 } 1083 }
1101 1084
1085 /*
1086 * It's safe to allow irq's after cr2 has been saved and the
1087 * vmalloc fault has been handled.
1088 *
1089 * User-mode registers count as a user access even for any
1090 * potential system fault or CPU buglet:
1091 */
1092 if (user_mode_vm(regs)) {
1093 local_irq_enable();
1094 error_code |= PF_USER;
1095 flags |= FAULT_FLAG_USER;
1096 } else {
1097 if (regs->flags & X86_EFLAGS_IF)
1098 local_irq_enable();
1099 }
1100
1101 perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
1102
1102 if (error_code & PF_WRITE) 1103 if (error_code & PF_WRITE)
1103 flags |= FAULT_FLAG_WRITE; 1104 flags |= FAULT_FLAG_WRITE;
1104 1105
diff --git a/arch/x86/oprofile/backtrace.c b/arch/x86/oprofile/backtrace.c
index d6aa6e8315d1..5d04be5efb64 100644
--- a/arch/x86/oprofile/backtrace.c
+++ b/arch/x86/oprofile/backtrace.c
@@ -47,7 +47,7 @@ dump_user_backtrace_32(struct stack_frame_ia32 *head)
47 unsigned long bytes; 47 unsigned long bytes;
48 48
49 bytes = copy_from_user_nmi(bufhead, head, sizeof(bufhead)); 49 bytes = copy_from_user_nmi(bufhead, head, sizeof(bufhead));
50 if (bytes != sizeof(bufhead)) 50 if (bytes != 0)
51 return NULL; 51 return NULL;
52 52
53 fp = (struct stack_frame_ia32 *) compat_ptr(bufhead[0].next_frame); 53 fp = (struct stack_frame_ia32 *) compat_ptr(bufhead[0].next_frame);
@@ -93,7 +93,7 @@ static struct stack_frame *dump_user_backtrace(struct stack_frame *head)
93 unsigned long bytes; 93 unsigned long bytes;
94 94
95 bytes = copy_from_user_nmi(bufhead, head, sizeof(bufhead)); 95 bytes = copy_from_user_nmi(bufhead, head, sizeof(bufhead));
96 if (bytes != sizeof(bufhead)) 96 if (bytes != 0)
97 return NULL; 97 return NULL;
98 98
99 oprofile_add_trace(bufhead[0].return_address); 99 oprofile_add_trace(bufhead[0].return_address);
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index c8ba627c1d60..2e069d1288df 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -584,6 +584,10 @@ struct perf_sample_data {
584 struct perf_regs_user regs_user; 584 struct perf_regs_user regs_user;
585 u64 stack_user_size; 585 u64 stack_user_size;
586 u64 weight; 586 u64 weight;
587 /*
588 * Transaction flags for abort events:
589 */
590 u64 txn;
587}; 591};
588 592
589static inline void perf_sample_data_init(struct perf_sample_data *data, 593static inline void perf_sample_data_init(struct perf_sample_data *data,
@@ -599,6 +603,7 @@ static inline void perf_sample_data_init(struct perf_sample_data *data,
599 data->stack_user_size = 0; 603 data->stack_user_size = 0;
600 data->weight = 0; 604 data->weight = 0;
601 data->data_src.val = 0; 605 data->data_src.val = 0;
606 data->txn = 0;
602} 607}
603 608
604extern void perf_output_sample(struct perf_output_handle *handle, 609extern void perf_output_sample(struct perf_output_handle *handle,
diff --git a/include/linux/uprobes.h b/include/linux/uprobes.h
index 06f28beed7c2..319eae70fe84 100644
--- a/include/linux/uprobes.h
+++ b/include/linux/uprobes.h
@@ -30,6 +30,7 @@
30struct vm_area_struct; 30struct vm_area_struct;
31struct mm_struct; 31struct mm_struct;
32struct inode; 32struct inode;
33struct notifier_block;
33 34
34#ifdef CONFIG_ARCH_SUPPORTS_UPROBES 35#ifdef CONFIG_ARCH_SUPPORTS_UPROBES
35# include <asm/uprobes.h> 36# include <asm/uprobes.h>
@@ -108,6 +109,7 @@ extern int __weak set_swbp(struct arch_uprobe *aup, struct mm_struct *mm, unsign
108extern int __weak set_orig_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr); 109extern int __weak set_orig_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr);
109extern bool __weak is_swbp_insn(uprobe_opcode_t *insn); 110extern bool __weak is_swbp_insn(uprobe_opcode_t *insn);
110extern bool __weak is_trap_insn(uprobe_opcode_t *insn); 111extern bool __weak is_trap_insn(uprobe_opcode_t *insn);
112extern int uprobe_write_opcode(struct mm_struct *mm, unsigned long vaddr, uprobe_opcode_t);
111extern int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *uc); 113extern int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *uc);
112extern int uprobe_apply(struct inode *inode, loff_t offset, struct uprobe_consumer *uc, bool); 114extern int uprobe_apply(struct inode *inode, loff_t offset, struct uprobe_consumer *uc, bool);
113extern void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consumer *uc); 115extern void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consumer *uc);
@@ -117,14 +119,21 @@ extern void uprobe_start_dup_mmap(void);
117extern void uprobe_end_dup_mmap(void); 119extern void uprobe_end_dup_mmap(void);
118extern void uprobe_dup_mmap(struct mm_struct *oldmm, struct mm_struct *newmm); 120extern void uprobe_dup_mmap(struct mm_struct *oldmm, struct mm_struct *newmm);
119extern void uprobe_free_utask(struct task_struct *t); 121extern void uprobe_free_utask(struct task_struct *t);
120extern void uprobe_copy_process(struct task_struct *t); 122extern void uprobe_copy_process(struct task_struct *t, unsigned long flags);
121extern unsigned long __weak uprobe_get_swbp_addr(struct pt_regs *regs); 123extern unsigned long __weak uprobe_get_swbp_addr(struct pt_regs *regs);
122extern int uprobe_post_sstep_notifier(struct pt_regs *regs); 124extern int uprobe_post_sstep_notifier(struct pt_regs *regs);
123extern int uprobe_pre_sstep_notifier(struct pt_regs *regs); 125extern int uprobe_pre_sstep_notifier(struct pt_regs *regs);
124extern void uprobe_notify_resume(struct pt_regs *regs); 126extern void uprobe_notify_resume(struct pt_regs *regs);
125extern bool uprobe_deny_signal(void); 127extern bool uprobe_deny_signal(void);
126extern bool __weak arch_uprobe_skip_sstep(struct arch_uprobe *aup, struct pt_regs *regs); 128extern bool arch_uprobe_skip_sstep(struct arch_uprobe *aup, struct pt_regs *regs);
127extern void uprobe_clear_state(struct mm_struct *mm); 129extern void uprobe_clear_state(struct mm_struct *mm);
130extern int arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long addr);
131extern int arch_uprobe_pre_xol(struct arch_uprobe *aup, struct pt_regs *regs);
132extern int arch_uprobe_post_xol(struct arch_uprobe *aup, struct pt_regs *regs);
133extern bool arch_uprobe_xol_was_trapped(struct task_struct *tsk);
134extern int arch_uprobe_exception_notify(struct notifier_block *self, unsigned long val, void *data);
135extern void arch_uprobe_abort_xol(struct arch_uprobe *aup, struct pt_regs *regs);
136extern unsigned long arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr, struct pt_regs *regs);
128#else /* !CONFIG_UPROBES */ 137#else /* !CONFIG_UPROBES */
129struct uprobes_state { 138struct uprobes_state {
130}; 139};
@@ -174,7 +183,7 @@ static inline unsigned long uprobe_get_swbp_addr(struct pt_regs *regs)
174static inline void uprobe_free_utask(struct task_struct *t) 183static inline void uprobe_free_utask(struct task_struct *t)
175{ 184{
176} 185}
177static inline void uprobe_copy_process(struct task_struct *t) 186static inline void uprobe_copy_process(struct task_struct *t, unsigned long flags)
178{ 187{
179} 188}
180static inline void uprobe_clear_state(struct mm_struct *mm) 189static inline void uprobe_clear_state(struct mm_struct *mm)
diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
index 2fc1602e23bb..e1802d6153ae 100644
--- a/include/uapi/linux/perf_event.h
+++ b/include/uapi/linux/perf_event.h
@@ -136,8 +136,9 @@ enum perf_event_sample_format {
136 PERF_SAMPLE_WEIGHT = 1U << 14, 136 PERF_SAMPLE_WEIGHT = 1U << 14,
137 PERF_SAMPLE_DATA_SRC = 1U << 15, 137 PERF_SAMPLE_DATA_SRC = 1U << 15,
138 PERF_SAMPLE_IDENTIFIER = 1U << 16, 138 PERF_SAMPLE_IDENTIFIER = 1U << 16,
139 PERF_SAMPLE_TRANSACTION = 1U << 17,
139 140
140 PERF_SAMPLE_MAX = 1U << 17, /* non-ABI */ 141 PERF_SAMPLE_MAX = 1U << 18, /* non-ABI */
141}; 142};
142 143
143/* 144/*
@@ -181,6 +182,28 @@ enum perf_sample_regs_abi {
181}; 182};
182 183
183/* 184/*
185 * Values for the memory transaction event qualifier, mostly for
186 * abort events. Multiple bits can be set.
187 */
188enum {
189 PERF_TXN_ELISION = (1 << 0), /* From elision */
190 PERF_TXN_TRANSACTION = (1 << 1), /* From transaction */
191 PERF_TXN_SYNC = (1 << 2), /* Instruction is related */
192 PERF_TXN_ASYNC = (1 << 3), /* Instruction not related */
193 PERF_TXN_RETRY = (1 << 4), /* Retry possible */
194 PERF_TXN_CONFLICT = (1 << 5), /* Conflict abort */
195 PERF_TXN_CAPACITY_WRITE = (1 << 6), /* Capacity write abort */
196 PERF_TXN_CAPACITY_READ = (1 << 7), /* Capacity read abort */
197
198 PERF_TXN_MAX = (1 << 8), /* non-ABI */
199
200 /* bits 32..63 are reserved for the abort code */
201
202 PERF_TXN_ABORT_MASK = (0xffffffffULL << 32),
203 PERF_TXN_ABORT_SHIFT = 32,
204};
205
206/*
184 * The format of the data returned by read() on a perf event fd, 207 * The format of the data returned by read() on a perf event fd,
185 * as specified by attr.read_format: 208 * as specified by attr.read_format:
186 * 209 *
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 663f43a20f73..8c875ef6e120 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -175,8 +175,8 @@ int sysctl_perf_event_sample_rate __read_mostly = DEFAULT_MAX_SAMPLE_RATE;
175static int max_samples_per_tick __read_mostly = DIV_ROUND_UP(DEFAULT_MAX_SAMPLE_RATE, HZ); 175static int max_samples_per_tick __read_mostly = DIV_ROUND_UP(DEFAULT_MAX_SAMPLE_RATE, HZ);
176static int perf_sample_period_ns __read_mostly = DEFAULT_SAMPLE_PERIOD_NS; 176static int perf_sample_period_ns __read_mostly = DEFAULT_SAMPLE_PERIOD_NS;
177 177
178static atomic_t perf_sample_allowed_ns __read_mostly = 178static int perf_sample_allowed_ns __read_mostly =
179 ATOMIC_INIT( DEFAULT_SAMPLE_PERIOD_NS * DEFAULT_CPU_TIME_MAX_PERCENT / 100); 179 DEFAULT_SAMPLE_PERIOD_NS * DEFAULT_CPU_TIME_MAX_PERCENT / 100;
180 180
181void update_perf_cpu_limits(void) 181void update_perf_cpu_limits(void)
182{ 182{
@@ -184,7 +184,7 @@ void update_perf_cpu_limits(void)
184 184
185 tmp *= sysctl_perf_cpu_time_max_percent; 185 tmp *= sysctl_perf_cpu_time_max_percent;
186 do_div(tmp, 100); 186 do_div(tmp, 100);
187 atomic_set(&perf_sample_allowed_ns, tmp); 187 ACCESS_ONCE(perf_sample_allowed_ns) = tmp;
188} 188}
189 189
190static int perf_rotate_context(struct perf_cpu_context *cpuctx); 190static int perf_rotate_context(struct perf_cpu_context *cpuctx);
@@ -193,7 +193,7 @@ int perf_proc_update_handler(struct ctl_table *table, int write,
193 void __user *buffer, size_t *lenp, 193 void __user *buffer, size_t *lenp,
194 loff_t *ppos) 194 loff_t *ppos)
195{ 195{
196 int ret = proc_dointvec(table, write, buffer, lenp, ppos); 196 int ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
197 197
198 if (ret || !write) 198 if (ret || !write)
199 return ret; 199 return ret;
@@ -228,14 +228,15 @@ int perf_cpu_time_max_percent_handler(struct ctl_table *table, int write,
228 * we detect that events are taking too long. 228 * we detect that events are taking too long.
229 */ 229 */
230#define NR_ACCUMULATED_SAMPLES 128 230#define NR_ACCUMULATED_SAMPLES 128
231DEFINE_PER_CPU(u64, running_sample_length); 231static DEFINE_PER_CPU(u64, running_sample_length);
232 232
233void perf_sample_event_took(u64 sample_len_ns) 233void perf_sample_event_took(u64 sample_len_ns)
234{ 234{
235 u64 avg_local_sample_len; 235 u64 avg_local_sample_len;
236 u64 local_samples_len; 236 u64 local_samples_len;
237 u64 allowed_ns = ACCESS_ONCE(perf_sample_allowed_ns);
237 238
238 if (atomic_read(&perf_sample_allowed_ns) == 0) 239 if (allowed_ns == 0)
239 return; 240 return;
240 241
241 /* decay the counter by 1 average sample */ 242 /* decay the counter by 1 average sample */
@@ -251,7 +252,7 @@ void perf_sample_event_took(u64 sample_len_ns)
251 */ 252 */
252 avg_local_sample_len = local_samples_len/NR_ACCUMULATED_SAMPLES; 253 avg_local_sample_len = local_samples_len/NR_ACCUMULATED_SAMPLES;
253 254
254 if (avg_local_sample_len <= atomic_read(&perf_sample_allowed_ns)) 255 if (avg_local_sample_len <= allowed_ns)
255 return; 256 return;
256 257
257 if (max_samples_per_tick <= 1) 258 if (max_samples_per_tick <= 1)
@@ -262,10 +263,9 @@ void perf_sample_event_took(u64 sample_len_ns)
262 perf_sample_period_ns = NSEC_PER_SEC / sysctl_perf_event_sample_rate; 263 perf_sample_period_ns = NSEC_PER_SEC / sysctl_perf_event_sample_rate;
263 264
264 printk_ratelimited(KERN_WARNING 265 printk_ratelimited(KERN_WARNING
265 "perf samples too long (%lld > %d), lowering " 266 "perf samples too long (%lld > %lld), lowering "
266 "kernel.perf_event_max_sample_rate to %d\n", 267 "kernel.perf_event_max_sample_rate to %d\n",
267 avg_local_sample_len, 268 avg_local_sample_len, allowed_ns,
268 atomic_read(&perf_sample_allowed_ns),
269 sysctl_perf_event_sample_rate); 269 sysctl_perf_event_sample_rate);
270 270
271 update_perf_cpu_limits(); 271 update_perf_cpu_limits();
@@ -899,6 +899,7 @@ static void unclone_ctx(struct perf_event_context *ctx)
899 put_ctx(ctx->parent_ctx); 899 put_ctx(ctx->parent_ctx);
900 ctx->parent_ctx = NULL; 900 ctx->parent_ctx = NULL;
901 } 901 }
902 ctx->generation++;
902} 903}
903 904
904static u32 perf_event_pid(struct perf_event *event, struct task_struct *p) 905static u32 perf_event_pid(struct perf_event *event, struct task_struct *p)
@@ -1136,6 +1137,8 @@ list_add_event(struct perf_event *event, struct perf_event_context *ctx)
1136 ctx->nr_events++; 1137 ctx->nr_events++;
1137 if (event->attr.inherit_stat) 1138 if (event->attr.inherit_stat)
1138 ctx->nr_stat++; 1139 ctx->nr_stat++;
1140
1141 ctx->generation++;
1139} 1142}
1140 1143
1141/* 1144/*
@@ -1201,6 +1204,9 @@ static void perf_event__header_size(struct perf_event *event)
1201 if (sample_type & PERF_SAMPLE_DATA_SRC) 1204 if (sample_type & PERF_SAMPLE_DATA_SRC)
1202 size += sizeof(data->data_src.val); 1205 size += sizeof(data->data_src.val);
1203 1206
1207 if (sample_type & PERF_SAMPLE_TRANSACTION)
1208 size += sizeof(data->txn);
1209
1204 event->header_size = size; 1210 event->header_size = size;
1205} 1211}
1206 1212
@@ -1310,6 +1316,8 @@ list_del_event(struct perf_event *event, struct perf_event_context *ctx)
1310 */ 1316 */
1311 if (event->state > PERF_EVENT_STATE_OFF) 1317 if (event->state > PERF_EVENT_STATE_OFF)
1312 event->state = PERF_EVENT_STATE_OFF; 1318 event->state = PERF_EVENT_STATE_OFF;
1319
1320 ctx->generation++;
1313} 1321}
1314 1322
1315static void perf_group_detach(struct perf_event *event) 1323static void perf_group_detach(struct perf_event *event)
@@ -2146,22 +2154,38 @@ static void ctx_sched_out(struct perf_event_context *ctx,
2146} 2154}
2147 2155
2148/* 2156/*
2149 * Test whether two contexts are equivalent, i.e. whether they 2157 * Test whether two contexts are equivalent, i.e. whether they have both been
2150 * have both been cloned from the same version of the same context 2158 * cloned from the same version of the same context.
2151 * and they both have the same number of enabled events. 2159 *
2152 * If the number of enabled events is the same, then the set 2160 * Equivalence is measured using a generation number in the context that is
2153 * of enabled events should be the same, because these are both 2161 * incremented on each modification to it; see unclone_ctx(), list_add_event()
2154 * inherited contexts, therefore we can't access individual events 2162 * and list_del_event().
2155 * in them directly with an fd; we can only enable/disable all
2156 * events via prctl, or enable/disable all events in a family
2157 * via ioctl, which will have the same effect on both contexts.
2158 */ 2163 */
2159static int context_equiv(struct perf_event_context *ctx1, 2164static int context_equiv(struct perf_event_context *ctx1,
2160 struct perf_event_context *ctx2) 2165 struct perf_event_context *ctx2)
2161{ 2166{
2162 return ctx1->parent_ctx && ctx1->parent_ctx == ctx2->parent_ctx 2167 /* Pinning disables the swap optimization */
2163 && ctx1->parent_gen == ctx2->parent_gen 2168 if (ctx1->pin_count || ctx2->pin_count)
2164 && !ctx1->pin_count && !ctx2->pin_count; 2169 return 0;
2170
2171 /* If ctx1 is the parent of ctx2 */
2172 if (ctx1 == ctx2->parent_ctx && ctx1->generation == ctx2->parent_gen)
2173 return 1;
2174
2175 /* If ctx2 is the parent of ctx1 */
2176 if (ctx1->parent_ctx == ctx2 && ctx1->parent_gen == ctx2->generation)
2177 return 1;
2178
2179 /*
2180 * If ctx1 and ctx2 have the same parent; we flatten the parent
2181 * hierarchy, see perf_event_init_context().
2182 */
2183 if (ctx1->parent_ctx && ctx1->parent_ctx == ctx2->parent_ctx &&
2184 ctx1->parent_gen == ctx2->parent_gen)
2185 return 1;
2186
2187 /* Unmatched */
2188 return 0;
2165} 2189}
2166 2190
2167static void __perf_event_sync_stat(struct perf_event *event, 2191static void __perf_event_sync_stat(struct perf_event *event,
@@ -2244,7 +2268,7 @@ static void perf_event_context_sched_out(struct task_struct *task, int ctxn,
2244{ 2268{
2245 struct perf_event_context *ctx = task->perf_event_ctxp[ctxn]; 2269 struct perf_event_context *ctx = task->perf_event_ctxp[ctxn];
2246 struct perf_event_context *next_ctx; 2270 struct perf_event_context *next_ctx;
2247 struct perf_event_context *parent; 2271 struct perf_event_context *parent, *next_parent;
2248 struct perf_cpu_context *cpuctx; 2272 struct perf_cpu_context *cpuctx;
2249 int do_switch = 1; 2273 int do_switch = 1;
2250 2274
@@ -2256,10 +2280,18 @@ static void perf_event_context_sched_out(struct task_struct *task, int ctxn,
2256 return; 2280 return;
2257 2281
2258 rcu_read_lock(); 2282 rcu_read_lock();
2259 parent = rcu_dereference(ctx->parent_ctx);
2260 next_ctx = next->perf_event_ctxp[ctxn]; 2283 next_ctx = next->perf_event_ctxp[ctxn];
2261 if (parent && next_ctx && 2284 if (!next_ctx)
2262 rcu_dereference(next_ctx->parent_ctx) == parent) { 2285 goto unlock;
2286
2287 parent = rcu_dereference(ctx->parent_ctx);
2288 next_parent = rcu_dereference(next_ctx->parent_ctx);
2289
2290 /* If neither context have a parent context; they cannot be clones. */
2291 if (!parent && !next_parent)
2292 goto unlock;
2293
2294 if (next_parent == ctx || next_ctx == parent || next_parent == parent) {
2263 /* 2295 /*
2264 * Looks like the two contexts are clones, so we might be 2296 * Looks like the two contexts are clones, so we might be
2265 * able to optimize the context switch. We lock both 2297 * able to optimize the context switch. We lock both
@@ -2287,6 +2319,7 @@ static void perf_event_context_sched_out(struct task_struct *task, int ctxn,
2287 raw_spin_unlock(&next_ctx->lock); 2319 raw_spin_unlock(&next_ctx->lock);
2288 raw_spin_unlock(&ctx->lock); 2320 raw_spin_unlock(&ctx->lock);
2289 } 2321 }
2322unlock:
2290 rcu_read_unlock(); 2323 rcu_read_unlock();
2291 2324
2292 if (do_switch) { 2325 if (do_switch) {
@@ -4572,6 +4605,9 @@ void perf_output_sample(struct perf_output_handle *handle,
4572 if (sample_type & PERF_SAMPLE_DATA_SRC) 4605 if (sample_type & PERF_SAMPLE_DATA_SRC)
4573 perf_output_put(handle, data->data_src.val); 4606 perf_output_put(handle, data->data_src.val);
4574 4607
4608 if (sample_type & PERF_SAMPLE_TRANSACTION)
4609 perf_output_put(handle, data->txn);
4610
4575 if (!event->attr.watermark) { 4611 if (!event->attr.watermark) {
4576 int wakeup_events = event->attr.wakeup_events; 4612 int wakeup_events = event->attr.wakeup_events;
4577 4613
@@ -5100,27 +5136,26 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event)
5100 unsigned int size; 5136 unsigned int size;
5101 char tmp[16]; 5137 char tmp[16];
5102 char *buf = NULL; 5138 char *buf = NULL;
5103 const char *name; 5139 char *name;
5104
5105 memset(tmp, 0, sizeof(tmp));
5106 5140
5107 if (file) { 5141 if (file) {
5108 struct inode *inode; 5142 struct inode *inode;
5109 dev_t dev; 5143 dev_t dev;
5144
5145 buf = kmalloc(PATH_MAX, GFP_KERNEL);
5146 if (!buf) {
5147 name = "//enomem";
5148 goto cpy_name;
5149 }
5110 /* 5150 /*
5111 * d_path works from the end of the rb backwards, so we 5151 * d_path() works from the end of the rb backwards, so we
5112 * need to add enough zero bytes after the string to handle 5152 * need to add enough zero bytes after the string to handle
5113 * the 64bit alignment we do later. 5153 * the 64bit alignment we do later.
5114 */ 5154 */
5115 buf = kzalloc(PATH_MAX + sizeof(u64), GFP_KERNEL); 5155 name = d_path(&file->f_path, buf, PATH_MAX - sizeof(u64));
5116 if (!buf) {
5117 name = strncpy(tmp, "//enomem", sizeof(tmp));
5118 goto got_name;
5119 }
5120 name = d_path(&file->f_path, buf, PATH_MAX);
5121 if (IS_ERR(name)) { 5156 if (IS_ERR(name)) {
5122 name = strncpy(tmp, "//toolong", sizeof(tmp)); 5157 name = "//toolong";
5123 goto got_name; 5158 goto cpy_name;
5124 } 5159 }
5125 inode = file_inode(vma->vm_file); 5160 inode = file_inode(vma->vm_file);
5126 dev = inode->i_sb->s_dev; 5161 dev = inode->i_sb->s_dev;
@@ -5128,34 +5163,39 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event)
5128 gen = inode->i_generation; 5163 gen = inode->i_generation;
5129 maj = MAJOR(dev); 5164 maj = MAJOR(dev);
5130 min = MINOR(dev); 5165 min = MINOR(dev);
5131 5166 goto got_name;
5132 } else { 5167 } else {
5133 if (arch_vma_name(mmap_event->vma)) { 5168 name = (char *)arch_vma_name(vma);
5134 name = strncpy(tmp, arch_vma_name(mmap_event->vma), 5169 if (name)
5135 sizeof(tmp) - 1); 5170 goto cpy_name;
5136 tmp[sizeof(tmp) - 1] = '\0';
5137 goto got_name;
5138 }
5139 5171
5140 if (!vma->vm_mm) { 5172 if (vma->vm_start <= vma->vm_mm->start_brk &&
5141 name = strncpy(tmp, "[vdso]", sizeof(tmp));
5142 goto got_name;
5143 } else if (vma->vm_start <= vma->vm_mm->start_brk &&
5144 vma->vm_end >= vma->vm_mm->brk) { 5173 vma->vm_end >= vma->vm_mm->brk) {
5145 name = strncpy(tmp, "[heap]", sizeof(tmp)); 5174 name = "[heap]";
5146 goto got_name; 5175 goto cpy_name;
5147 } else if (vma->vm_start <= vma->vm_mm->start_stack && 5176 }
5177 if (vma->vm_start <= vma->vm_mm->start_stack &&
5148 vma->vm_end >= vma->vm_mm->start_stack) { 5178 vma->vm_end >= vma->vm_mm->start_stack) {
5149 name = strncpy(tmp, "[stack]", sizeof(tmp)); 5179 name = "[stack]";
5150 goto got_name; 5180 goto cpy_name;
5151 } 5181 }
5152 5182
5153 name = strncpy(tmp, "//anon", sizeof(tmp)); 5183 name = "//anon";
5154 goto got_name; 5184 goto cpy_name;
5155 } 5185 }
5156 5186
5187cpy_name:
5188 strlcpy(tmp, name, sizeof(tmp));
5189 name = tmp;
5157got_name: 5190got_name:
5158 size = ALIGN(strlen(name)+1, sizeof(u64)); 5191 /*
5192 * Since our buffer works in 8 byte units we need to align our string
5193 * size to a multiple of 8. However, we must guarantee the tail end is
5194 * zero'd out to avoid leaking random bits to userspace.
5195 */
5196 size = strlen(name)+1;
5197 while (!IS_ALIGNED(size, sizeof(u64)))
5198 name[size++] = '\0';
5159 5199
5160 mmap_event->file_name = name; 5200 mmap_event->file_name = name;
5161 mmap_event->file_size = size; 5201 mmap_event->file_size = size;
@@ -7129,7 +7169,6 @@ SYSCALL_DEFINE5(perf_event_open,
7129 } 7169 }
7130 7170
7131 perf_install_in_context(ctx, event, event->cpu); 7171 perf_install_in_context(ctx, event, event->cpu);
7132 ++ctx->generation;
7133 perf_unpin_context(ctx); 7172 perf_unpin_context(ctx);
7134 mutex_unlock(&ctx->mutex); 7173 mutex_unlock(&ctx->mutex);
7135 7174
@@ -7212,7 +7251,6 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu,
7212 WARN_ON_ONCE(ctx->parent_ctx); 7251 WARN_ON_ONCE(ctx->parent_ctx);
7213 mutex_lock(&ctx->mutex); 7252 mutex_lock(&ctx->mutex);
7214 perf_install_in_context(ctx, event, cpu); 7253 perf_install_in_context(ctx, event, cpu);
7215 ++ctx->generation;
7216 perf_unpin_context(ctx); 7254 perf_unpin_context(ctx);
7217 mutex_unlock(&ctx->mutex); 7255 mutex_unlock(&ctx->mutex);
7218 7256
diff --git a/kernel/events/internal.h b/kernel/events/internal.h
index ca6599723be5..569b218782ad 100644
--- a/kernel/events/internal.h
+++ b/kernel/events/internal.h
@@ -82,16 +82,16 @@ static inline unsigned long perf_data_size(struct ring_buffer *rb)
82} 82}
83 83
84#define DEFINE_OUTPUT_COPY(func_name, memcpy_func) \ 84#define DEFINE_OUTPUT_COPY(func_name, memcpy_func) \
85static inline unsigned int \ 85static inline unsigned long \
86func_name(struct perf_output_handle *handle, \ 86func_name(struct perf_output_handle *handle, \
87 const void *buf, unsigned int len) \ 87 const void *buf, unsigned long len) \
88{ \ 88{ \
89 unsigned long size, written; \ 89 unsigned long size, written; \
90 \ 90 \
91 do { \ 91 do { \
92 size = min_t(unsigned long, handle->size, len); \ 92 size = min(handle->size, len); \
93 \
94 written = memcpy_func(handle->addr, buf, size); \ 93 written = memcpy_func(handle->addr, buf, size); \
94 written = size - written; \
95 \ 95 \
96 len -= written; \ 96 len -= written; \
97 handle->addr += written; \ 97 handle->addr += written; \
@@ -110,20 +110,37 @@ func_name(struct perf_output_handle *handle, \
110 return len; \ 110 return len; \
111} 111}
112 112
113static inline int memcpy_common(void *dst, const void *src, size_t n) 113static inline unsigned long
114memcpy_common(void *dst, const void *src, unsigned long n)
114{ 115{
115 memcpy(dst, src, n); 116 memcpy(dst, src, n);
116 return n; 117 return 0;
117} 118}
118 119
119DEFINE_OUTPUT_COPY(__output_copy, memcpy_common) 120DEFINE_OUTPUT_COPY(__output_copy, memcpy_common)
120 121
121#define MEMCPY_SKIP(dst, src, n) (n) 122static inline unsigned long
123memcpy_skip(void *dst, const void *src, unsigned long n)
124{
125 return 0;
126}
122 127
123DEFINE_OUTPUT_COPY(__output_skip, MEMCPY_SKIP) 128DEFINE_OUTPUT_COPY(__output_skip, memcpy_skip)
124 129
125#ifndef arch_perf_out_copy_user 130#ifndef arch_perf_out_copy_user
126#define arch_perf_out_copy_user __copy_from_user_inatomic 131#define arch_perf_out_copy_user arch_perf_out_copy_user
132
133static inline unsigned long
134arch_perf_out_copy_user(void *dst, const void *src, unsigned long n)
135{
136 unsigned long ret;
137
138 pagefault_disable();
139 ret = __copy_from_user_inatomic(dst, src, n);
140 pagefault_enable();
141
142 return ret;
143}
127#endif 144#endif
128 145
129DEFINE_OUTPUT_COPY(__output_copy_user, arch_perf_out_copy_user) 146DEFINE_OUTPUT_COPY(__output_copy_user, arch_perf_out_copy_user)
diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c
index 9c2ddfbf4525..e8b168af135b 100644
--- a/kernel/events/ring_buffer.c
+++ b/kernel/events/ring_buffer.c
@@ -12,40 +12,10 @@
12#include <linux/perf_event.h> 12#include <linux/perf_event.h>
13#include <linux/vmalloc.h> 13#include <linux/vmalloc.h>
14#include <linux/slab.h> 14#include <linux/slab.h>
15#include <linux/circ_buf.h>
15 16
16#include "internal.h" 17#include "internal.h"
17 18
18static bool perf_output_space(struct ring_buffer *rb, unsigned long tail,
19 unsigned long offset, unsigned long head)
20{
21 unsigned long sz = perf_data_size(rb);
22 unsigned long mask = sz - 1;
23
24 /*
25 * check if user-writable
26 * overwrite : over-write its own tail
27 * !overwrite: buffer possibly drops events.
28 */
29 if (rb->overwrite)
30 return true;
31
32 /*
33 * verify that payload is not bigger than buffer
34 * otherwise masking logic may fail to detect
35 * the "not enough space" condition
36 */
37 if ((head - offset) > sz)
38 return false;
39
40 offset = (offset - tail) & mask;
41 head = (head - tail) & mask;
42
43 if ((int)(head - offset) < 0)
44 return false;
45
46 return true;
47}
48
49static void perf_output_wakeup(struct perf_output_handle *handle) 19static void perf_output_wakeup(struct perf_output_handle *handle)
50{ 20{
51 atomic_set(&handle->rb->poll, POLL_IN); 21 atomic_set(&handle->rb->poll, POLL_IN);
@@ -115,8 +85,8 @@ again:
115 rb->user_page->data_head = head; 85 rb->user_page->data_head = head;
116 86
117 /* 87 /*
118 * Now check if we missed an update, rely on the (compiler) 88 * Now check if we missed an update -- rely on previous implied
119 * barrier in atomic_dec_and_test() to re-read rb->head. 89 * compiler barriers to force a re-read.
120 */ 90 */
121 if (unlikely(head != local_read(&rb->head))) { 91 if (unlikely(head != local_read(&rb->head))) {
122 local_inc(&rb->nest); 92 local_inc(&rb->nest);
@@ -135,8 +105,7 @@ int perf_output_begin(struct perf_output_handle *handle,
135{ 105{
136 struct ring_buffer *rb; 106 struct ring_buffer *rb;
137 unsigned long tail, offset, head; 107 unsigned long tail, offset, head;
138 int have_lost; 108 int have_lost, page_shift;
139 struct perf_sample_data sample_data;
140 struct { 109 struct {
141 struct perf_event_header header; 110 struct perf_event_header header;
142 u64 id; 111 u64 id;
@@ -151,57 +120,63 @@ int perf_output_begin(struct perf_output_handle *handle,
151 event = event->parent; 120 event = event->parent;
152 121
153 rb = rcu_dereference(event->rb); 122 rb = rcu_dereference(event->rb);
154 if (!rb) 123 if (unlikely(!rb))
155 goto out; 124 goto out;
156 125
157 handle->rb = rb; 126 if (unlikely(!rb->nr_pages))
158 handle->event = event;
159
160 if (!rb->nr_pages)
161 goto out; 127 goto out;
162 128
129 handle->rb = rb;
130 handle->event = event;
131
163 have_lost = local_read(&rb->lost); 132 have_lost = local_read(&rb->lost);
164 if (have_lost) { 133 if (unlikely(have_lost)) {
165 lost_event.header.size = sizeof(lost_event); 134 size += sizeof(lost_event);
166 perf_event_header__init_id(&lost_event.header, &sample_data, 135 if (event->attr.sample_id_all)
167 event); 136 size += event->id_header_size;
168 size += lost_event.header.size;
169 } 137 }
170 138
171 perf_output_get_handle(handle); 139 perf_output_get_handle(handle);
172 140
173 do { 141 do {
174 /*
175 * Userspace could choose to issue a mb() before updating the
176 * tail pointer. So that all reads will be completed before the
177 * write is issued.
178 *
179 * See perf_output_put_handle().
180 */
181 tail = ACCESS_ONCE(rb->user_page->data_tail); 142 tail = ACCESS_ONCE(rb->user_page->data_tail);
182 smp_mb();
183 offset = head = local_read(&rb->head); 143 offset = head = local_read(&rb->head);
184 head += size; 144 if (!rb->overwrite &&
185 if (unlikely(!perf_output_space(rb, tail, offset, head))) 145 unlikely(CIRC_SPACE(head, tail, perf_data_size(rb)) < size))
186 goto fail; 146 goto fail;
147 head += size;
187 } while (local_cmpxchg(&rb->head, offset, head) != offset); 148 } while (local_cmpxchg(&rb->head, offset, head) != offset);
188 149
189 if (head - local_read(&rb->wakeup) > rb->watermark) 150 /*
151 * Separate the userpage->tail read from the data stores below.
152 * Matches the MB userspace SHOULD issue after reading the data
153 * and before storing the new tail position.
154 *
155 * See perf_output_put_handle().
156 */
157 smp_mb();
158
159 if (unlikely(head - local_read(&rb->wakeup) > rb->watermark))
190 local_add(rb->watermark, &rb->wakeup); 160 local_add(rb->watermark, &rb->wakeup);
191 161
192 handle->page = offset >> (PAGE_SHIFT + page_order(rb)); 162 page_shift = PAGE_SHIFT + page_order(rb);
193 handle->page &= rb->nr_pages - 1;
194 handle->size = offset & ((PAGE_SIZE << page_order(rb)) - 1);
195 handle->addr = rb->data_pages[handle->page];
196 handle->addr += handle->size;
197 handle->size = (PAGE_SIZE << page_order(rb)) - handle->size;
198 163
199 if (have_lost) { 164 handle->page = (offset >> page_shift) & (rb->nr_pages - 1);
165 offset &= (1UL << page_shift) - 1;
166 handle->addr = rb->data_pages[handle->page] + offset;
167 handle->size = (1UL << page_shift) - offset;
168
169 if (unlikely(have_lost)) {
170 struct perf_sample_data sample_data;
171
172 lost_event.header.size = sizeof(lost_event);
200 lost_event.header.type = PERF_RECORD_LOST; 173 lost_event.header.type = PERF_RECORD_LOST;
201 lost_event.header.misc = 0; 174 lost_event.header.misc = 0;
202 lost_event.id = event->id; 175 lost_event.id = event->id;
203 lost_event.lost = local_xchg(&rb->lost, 0); 176 lost_event.lost = local_xchg(&rb->lost, 0);
204 177
178 perf_event_header__init_id(&lost_event.header,
179 &sample_data, event);
205 perf_output_put(handle, lost_event); 180 perf_output_put(handle, lost_event);
206 perf_event__output_id_sample(event, handle, &sample_data); 181 perf_event__output_id_sample(event, handle, &sample_data);
207 } 182 }
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index ad8e1bdca70e..24b7d6ca871b 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -35,6 +35,7 @@
35#include <linux/kdebug.h> /* notifier mechanism */ 35#include <linux/kdebug.h> /* notifier mechanism */
36#include "../../mm/internal.h" /* munlock_vma_page */ 36#include "../../mm/internal.h" /* munlock_vma_page */
37#include <linux/percpu-rwsem.h> 37#include <linux/percpu-rwsem.h>
38#include <linux/task_work.h>
38 39
39#include <linux/uprobes.h> 40#include <linux/uprobes.h>
40 41
@@ -244,12 +245,12 @@ static int verify_opcode(struct page *page, unsigned long vaddr, uprobe_opcode_t
244 * the architecture. If an arch has variable length instruction and the 245 * the architecture. If an arch has variable length instruction and the
245 * breakpoint instruction is not of the smallest length instruction 246 * breakpoint instruction is not of the smallest length instruction
246 * supported by that architecture then we need to modify is_trap_at_addr and 247 * supported by that architecture then we need to modify is_trap_at_addr and
247 * write_opcode accordingly. This would never be a problem for archs that 248 * uprobe_write_opcode accordingly. This would never be a problem for archs
248 * have fixed length instructions. 249 * that have fixed length instructions.
249 */ 250 */
250 251
251/* 252/*
252 * write_opcode - write the opcode at a given virtual address. 253 * uprobe_write_opcode - write the opcode at a given virtual address.
253 * @mm: the probed process address space. 254 * @mm: the probed process address space.
254 * @vaddr: the virtual address to store the opcode. 255 * @vaddr: the virtual address to store the opcode.
255 * @opcode: opcode to be written at @vaddr. 256 * @opcode: opcode to be written at @vaddr.
@@ -260,7 +261,7 @@ static int verify_opcode(struct page *page, unsigned long vaddr, uprobe_opcode_t
260 * For mm @mm, write the opcode at @vaddr. 261 * For mm @mm, write the opcode at @vaddr.
261 * Return 0 (success) or a negative errno. 262 * Return 0 (success) or a negative errno.
262 */ 263 */
263static int write_opcode(struct mm_struct *mm, unsigned long vaddr, 264int uprobe_write_opcode(struct mm_struct *mm, unsigned long vaddr,
264 uprobe_opcode_t opcode) 265 uprobe_opcode_t opcode)
265{ 266{
266 struct page *old_page, *new_page; 267 struct page *old_page, *new_page;
@@ -314,7 +315,7 @@ put_old:
314 */ 315 */
315int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr) 316int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr)
316{ 317{
317 return write_opcode(mm, vaddr, UPROBE_SWBP_INSN); 318 return uprobe_write_opcode(mm, vaddr, UPROBE_SWBP_INSN);
318} 319}
319 320
320/** 321/**
@@ -329,7 +330,7 @@ int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned
329int __weak 330int __weak
330set_orig_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr) 331set_orig_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr)
331{ 332{
332 return write_opcode(mm, vaddr, *(uprobe_opcode_t *)auprobe->insn); 333 return uprobe_write_opcode(mm, vaddr, *(uprobe_opcode_t *)auprobe->insn);
333} 334}
334 335
335static int match_uprobe(struct uprobe *l, struct uprobe *r) 336static int match_uprobe(struct uprobe *l, struct uprobe *r)
@@ -503,9 +504,8 @@ static bool consumer_del(struct uprobe *uprobe, struct uprobe_consumer *uc)
503 return ret; 504 return ret;
504} 505}
505 506
506static int 507static int __copy_insn(struct address_space *mapping, struct file *filp,
507__copy_insn(struct address_space *mapping, struct file *filp, char *insn, 508 void *insn, int nbytes, loff_t offset)
508 unsigned long nbytes, loff_t offset)
509{ 509{
510 struct page *page; 510 struct page *page;
511 511
@@ -527,28 +527,28 @@ __copy_insn(struct address_space *mapping, struct file *filp, char *insn,
527 527
528static int copy_insn(struct uprobe *uprobe, struct file *filp) 528static int copy_insn(struct uprobe *uprobe, struct file *filp)
529{ 529{
530 struct address_space *mapping; 530 struct address_space *mapping = uprobe->inode->i_mapping;
531 unsigned long nbytes; 531 loff_t offs = uprobe->offset;
532 int bytes; 532 void *insn = uprobe->arch.insn;
533 533 int size = MAX_UINSN_BYTES;
534 nbytes = PAGE_SIZE - (uprobe->offset & ~PAGE_MASK); 534 int len, err = -EIO;
535 mapping = uprobe->inode->i_mapping;
536 535
537 /* Instruction at end of binary; copy only available bytes */ 536 /* Copy only available bytes, -EIO if nothing was read */
538 if (uprobe->offset + MAX_UINSN_BYTES > uprobe->inode->i_size) 537 do {
539 bytes = uprobe->inode->i_size - uprobe->offset; 538 if (offs >= i_size_read(uprobe->inode))
540 else 539 break;
541 bytes = MAX_UINSN_BYTES;
542 540
543 /* Instruction at the page-boundary; copy bytes in second page */ 541 len = min_t(int, size, PAGE_SIZE - (offs & ~PAGE_MASK));
544 if (nbytes < bytes) { 542 err = __copy_insn(mapping, filp, insn, len, offs);
545 int err = __copy_insn(mapping, filp, uprobe->arch.insn + nbytes,
546 bytes - nbytes, uprobe->offset + nbytes);
547 if (err) 543 if (err)
548 return err; 544 break;
549 bytes = nbytes; 545
550 } 546 insn += len;
551 return __copy_insn(mapping, filp, uprobe->arch.insn, bytes, uprobe->offset); 547 offs += len;
548 size -= len;
549 } while (size);
550
551 return err;
552} 552}
553 553
554static int prepare_uprobe(struct uprobe *uprobe, struct file *file, 554static int prepare_uprobe(struct uprobe *uprobe, struct file *file,
@@ -576,7 +576,7 @@ static int prepare_uprobe(struct uprobe *uprobe, struct file *file,
576 if (ret) 576 if (ret)
577 goto out; 577 goto out;
578 578
579 /* write_opcode() assumes we don't cross page boundary */ 579 /* uprobe_write_opcode() assumes we don't cross page boundary */
580 BUG_ON((uprobe->offset & ~PAGE_MASK) + 580 BUG_ON((uprobe->offset & ~PAGE_MASK) +
581 UPROBE_SWBP_INSN_SIZE > PAGE_SIZE); 581 UPROBE_SWBP_INSN_SIZE > PAGE_SIZE);
582 582
@@ -1096,21 +1096,22 @@ void uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned lon
1096} 1096}
1097 1097
1098/* Slot allocation for XOL */ 1098/* Slot allocation for XOL */
1099static int xol_add_vma(struct xol_area *area) 1099static int xol_add_vma(struct mm_struct *mm, struct xol_area *area)
1100{ 1100{
1101 struct mm_struct *mm = current->mm;
1102 int ret = -EALREADY; 1101 int ret = -EALREADY;
1103 1102
1104 down_write(&mm->mmap_sem); 1103 down_write(&mm->mmap_sem);
1105 if (mm->uprobes_state.xol_area) 1104 if (mm->uprobes_state.xol_area)
1106 goto fail; 1105 goto fail;
1107 1106
1108 ret = -ENOMEM; 1107 if (!area->vaddr) {
1109 /* Try to map as high as possible, this is only a hint. */ 1108 /* Try to map as high as possible, this is only a hint. */
1110 area->vaddr = get_unmapped_area(NULL, TASK_SIZE - PAGE_SIZE, PAGE_SIZE, 0, 0); 1109 area->vaddr = get_unmapped_area(NULL, TASK_SIZE - PAGE_SIZE,
1111 if (area->vaddr & ~PAGE_MASK) { 1110 PAGE_SIZE, 0, 0);
1112 ret = area->vaddr; 1111 if (area->vaddr & ~PAGE_MASK) {
1113 goto fail; 1112 ret = area->vaddr;
1113 goto fail;
1114 }
1114 } 1115 }
1115 1116
1116 ret = install_special_mapping(mm, area->vaddr, PAGE_SIZE, 1117 ret = install_special_mapping(mm, area->vaddr, PAGE_SIZE,
@@ -1120,30 +1121,19 @@ static int xol_add_vma(struct xol_area *area)
1120 1121
1121 smp_wmb(); /* pairs with get_xol_area() */ 1122 smp_wmb(); /* pairs with get_xol_area() */
1122 mm->uprobes_state.xol_area = area; 1123 mm->uprobes_state.xol_area = area;
1123 ret = 0;
1124 fail: 1124 fail:
1125 up_write(&mm->mmap_sem); 1125 up_write(&mm->mmap_sem);
1126 1126
1127 return ret; 1127 return ret;
1128} 1128}
1129 1129
1130/* 1130static struct xol_area *__create_xol_area(unsigned long vaddr)
1131 * get_xol_area - Allocate process's xol_area if necessary.
1132 * This area will be used for storing instructions for execution out of line.
1133 *
1134 * Returns the allocated area or NULL.
1135 */
1136static struct xol_area *get_xol_area(void)
1137{ 1131{
1138 struct mm_struct *mm = current->mm; 1132 struct mm_struct *mm = current->mm;
1139 struct xol_area *area;
1140 uprobe_opcode_t insn = UPROBE_SWBP_INSN; 1133 uprobe_opcode_t insn = UPROBE_SWBP_INSN;
1134 struct xol_area *area;
1141 1135
1142 area = mm->uprobes_state.xol_area; 1136 area = kmalloc(sizeof(*area), GFP_KERNEL);
1143 if (area)
1144 goto ret;
1145
1146 area = kzalloc(sizeof(*area), GFP_KERNEL);
1147 if (unlikely(!area)) 1137 if (unlikely(!area))
1148 goto out; 1138 goto out;
1149 1139
@@ -1155,13 +1145,14 @@ static struct xol_area *get_xol_area(void)
1155 if (!area->page) 1145 if (!area->page)
1156 goto free_bitmap; 1146 goto free_bitmap;
1157 1147
1158 /* allocate first slot of task's xol_area for the return probes */ 1148 area->vaddr = vaddr;
1149 init_waitqueue_head(&area->wq);
1150 /* Reserve the 1st slot for get_trampoline_vaddr() */
1159 set_bit(0, area->bitmap); 1151 set_bit(0, area->bitmap);
1160 copy_to_page(area->page, 0, &insn, UPROBE_SWBP_INSN_SIZE);
1161 atomic_set(&area->slot_count, 1); 1152 atomic_set(&area->slot_count, 1);
1162 init_waitqueue_head(&area->wq); 1153 copy_to_page(area->page, 0, &insn, UPROBE_SWBP_INSN_SIZE);
1163 1154
1164 if (!xol_add_vma(area)) 1155 if (!xol_add_vma(mm, area))
1165 return area; 1156 return area;
1166 1157
1167 __free_page(area->page); 1158 __free_page(area->page);
@@ -1170,9 +1161,25 @@ static struct xol_area *get_xol_area(void)
1170 free_area: 1161 free_area:
1171 kfree(area); 1162 kfree(area);
1172 out: 1163 out:
1164 return NULL;
1165}
1166
1167/*
1168 * get_xol_area - Allocate process's xol_area if necessary.
1169 * This area will be used for storing instructions for execution out of line.
1170 *
1171 * Returns the allocated area or NULL.
1172 */
1173static struct xol_area *get_xol_area(void)
1174{
1175 struct mm_struct *mm = current->mm;
1176 struct xol_area *area;
1177
1178 if (!mm->uprobes_state.xol_area)
1179 __create_xol_area(0);
1180
1173 area = mm->uprobes_state.xol_area; 1181 area = mm->uprobes_state.xol_area;
1174 ret: 1182 smp_read_barrier_depends(); /* pairs with wmb in xol_add_vma() */
1175 smp_read_barrier_depends(); /* pairs with wmb in xol_add_vma() */
1176 return area; 1183 return area;
1177} 1184}
1178 1185
@@ -1256,7 +1263,8 @@ static unsigned long xol_get_insn_slot(struct uprobe *uprobe)
1256 return 0; 1263 return 0;
1257 1264
1258 /* Initialize the slot */ 1265 /* Initialize the slot */
1259 copy_to_page(area->page, xol_vaddr, uprobe->arch.insn, MAX_UINSN_BYTES); 1266 copy_to_page(area->page, xol_vaddr,
1267 uprobe->arch.ixol, sizeof(uprobe->arch.ixol));
1260 /* 1268 /*
1261 * We probably need flush_icache_user_range() but it needs vma. 1269 * We probably need flush_icache_user_range() but it needs vma.
1262 * This should work on supported architectures too. 1270 * This should work on supported architectures too.
@@ -1345,14 +1353,6 @@ void uprobe_free_utask(struct task_struct *t)
1345} 1353}
1346 1354
1347/* 1355/*
1348 * Called in context of a new clone/fork from copy_process.
1349 */
1350void uprobe_copy_process(struct task_struct *t)
1351{
1352 t->utask = NULL;
1353}
1354
1355/*
1356 * Allocate a uprobe_task object for the task if if necessary. 1356 * Allocate a uprobe_task object for the task if if necessary.
1357 * Called when the thread hits a breakpoint. 1357 * Called when the thread hits a breakpoint.
1358 * 1358 *
@@ -1367,6 +1367,90 @@ static struct uprobe_task *get_utask(void)
1367 return current->utask; 1367 return current->utask;
1368} 1368}
1369 1369
1370static int dup_utask(struct task_struct *t, struct uprobe_task *o_utask)
1371{
1372 struct uprobe_task *n_utask;
1373 struct return_instance **p, *o, *n;
1374
1375 n_utask = kzalloc(sizeof(struct uprobe_task), GFP_KERNEL);
1376 if (!n_utask)
1377 return -ENOMEM;
1378 t->utask = n_utask;
1379
1380 p = &n_utask->return_instances;
1381 for (o = o_utask->return_instances; o; o = o->next) {
1382 n = kmalloc(sizeof(struct return_instance), GFP_KERNEL);
1383 if (!n)
1384 return -ENOMEM;
1385
1386 *n = *o;
1387 atomic_inc(&n->uprobe->ref);
1388 n->next = NULL;
1389
1390 *p = n;
1391 p = &n->next;
1392 n_utask->depth++;
1393 }
1394
1395 return 0;
1396}
1397
1398static void uprobe_warn(struct task_struct *t, const char *msg)
1399{
1400 pr_warn("uprobe: %s:%d failed to %s\n",
1401 current->comm, current->pid, msg);
1402}
1403
1404static void dup_xol_work(struct callback_head *work)
1405{
1406 kfree(work);
1407
1408 if (current->flags & PF_EXITING)
1409 return;
1410
1411 if (!__create_xol_area(current->utask->vaddr))
1412 uprobe_warn(current, "dup xol area");
1413}
1414
1415/*
1416 * Called in context of a new clone/fork from copy_process.
1417 */
1418void uprobe_copy_process(struct task_struct *t, unsigned long flags)
1419{
1420 struct uprobe_task *utask = current->utask;
1421 struct mm_struct *mm = current->mm;
1422 struct callback_head *work;
1423 struct xol_area *area;
1424
1425 t->utask = NULL;
1426
1427 if (!utask || !utask->return_instances)
1428 return;
1429
1430 if (mm == t->mm && !(flags & CLONE_VFORK))
1431 return;
1432
1433 if (dup_utask(t, utask))
1434 return uprobe_warn(t, "dup ret instances");
1435
1436 /* The task can fork() after dup_xol_work() fails */
1437 area = mm->uprobes_state.xol_area;
1438 if (!area)
1439 return uprobe_warn(t, "dup xol area");
1440
1441 if (mm == t->mm)
1442 return;
1443
1444 /* TODO: move it into the union in uprobe_task */
1445 work = kmalloc(sizeof(*work), GFP_KERNEL);
1446 if (!work)
1447 return uprobe_warn(t, "dup xol area");
1448
1449 t->utask->vaddr = area->vaddr;
1450 init_task_work(work, dup_xol_work);
1451 task_work_add(t, work, true);
1452}
1453
1370/* 1454/*
1371 * Current area->vaddr notion assume the trampoline address is always 1455 * Current area->vaddr notion assume the trampoline address is always
1372 * equal area->vaddr. 1456 * equal area->vaddr.
@@ -1857,9 +1941,4 @@ static int __init init_uprobes(void)
1857 1941
1858 return register_die_notifier(&uprobe_exception_nb); 1942 return register_die_notifier(&uprobe_exception_nb);
1859} 1943}
1860module_init(init_uprobes); 1944__initcall(init_uprobes);
1861
1862static void __exit exit_uprobes(void)
1863{
1864}
1865module_exit(exit_uprobes);
diff --git a/kernel/fork.c b/kernel/fork.c
index 086fe73ad6bd..8531609b6a82 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1373,7 +1373,6 @@ static struct task_struct *copy_process(unsigned long clone_flags,
1373 INIT_LIST_HEAD(&p->pi_state_list); 1373 INIT_LIST_HEAD(&p->pi_state_list);
1374 p->pi_state_cache = NULL; 1374 p->pi_state_cache = NULL;
1375#endif 1375#endif
1376 uprobe_copy_process(p);
1377 /* 1376 /*
1378 * sigaltstack should be cleared when sharing the same VM 1377 * sigaltstack should be cleared when sharing the same VM
1379 */ 1378 */
@@ -1490,6 +1489,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
1490 perf_event_fork(p); 1489 perf_event_fork(p);
1491 1490
1492 trace_task_newtask(p, clone_flags); 1491 trace_task_newtask(p, clone_flags);
1492 uprobe_copy_process(p, clone_flags);
1493 1493
1494 return p; 1494 return p;
1495 1495
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 8b80f1bae21a..5fee859888a4 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -1049,6 +1049,7 @@ static struct ctl_table kern_table[] = {
1049 .maxlen = sizeof(sysctl_perf_event_sample_rate), 1049 .maxlen = sizeof(sysctl_perf_event_sample_rate),
1050 .mode = 0644, 1050 .mode = 0644,
1051 .proc_handler = perf_proc_update_handler, 1051 .proc_handler = perf_proc_update_handler,
1052 .extra1 = &one,
1052 }, 1053 },
1053 { 1054 {
1054 .procname = "perf_cpu_time_max_percent", 1055 .procname = "perf_cpu_time_max_percent",
diff --git a/scripts/package/Makefile b/scripts/package/Makefile
index a4f31c900fa6..c5d473393816 100644
--- a/scripts/package/Makefile
+++ b/scripts/package/Makefile
@@ -115,7 +115,9 @@ git --git-dir=$(srctree)/.git archive --prefix=$(perf-tar)/ \
115 -o $(perf-tar).tar; \ 115 -o $(perf-tar).tar; \
116mkdir -p $(perf-tar); \ 116mkdir -p $(perf-tar); \
117git --git-dir=$(srctree)/.git rev-parse HEAD > $(perf-tar)/HEAD; \ 117git --git-dir=$(srctree)/.git rev-parse HEAD > $(perf-tar)/HEAD; \
118tar rf $(perf-tar).tar $(perf-tar)/HEAD; \ 118(cd $(srctree)/tools/perf; \
119util/PERF-VERSION-GEN ../../$(perf-tar)/ 2>/dev/null); \
120tar rf $(perf-tar).tar $(perf-tar)/HEAD $(perf-tar)/PERF-VERSION-FILE; \
119rm -r $(perf-tar); \ 121rm -r $(perf-tar); \
120$(if $(findstring tar-src,$@),, \ 122$(if $(findstring tar-src,$@),, \
121$(if $(findstring bz2,$@),bzip2, \ 123$(if $(findstring bz2,$@),bzip2, \
diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile
index ca6cb779876a..fc1502098595 100644
--- a/tools/lib/traceevent/Makefile
+++ b/tools/lib/traceevent/Makefile
@@ -134,14 +134,14 @@ ifeq ($(VERBOSE),1)
134 print_install = 134 print_install =
135else 135else
136 Q = @ 136 Q = @
137 print_compile = echo ' CC '$(OBJ); 137 print_compile = echo ' CC '$(OBJ);
138 print_app_build = echo ' BUILD '$(OBJ); 138 print_app_build = echo ' BUILD '$(OBJ);
139 print_fpic_compile = echo ' CC FPIC '$(OBJ); 139 print_fpic_compile = echo ' CC FPIC '$(OBJ);
140 print_shared_lib_compile = echo ' BUILD SHARED LIB '$(OBJ); 140 print_shared_lib_compile = echo ' BUILD SHARED LIB '$(OBJ);
141 print_plugin_obj_compile = echo ' CC PLUGIN OBJ '$(OBJ); 141 print_plugin_obj_compile = echo ' BUILD PLUGIN OBJ '$(OBJ);
142 print_plugin_build = echo ' CC PLUGI '$(OBJ); 142 print_plugin_build = echo ' BUILD PLUGIN '$(OBJ);
143 print_static_lib_build = echo ' BUILD STATIC LIB '$(OBJ); 143 print_static_lib_build = echo ' BUILD STATIC LIB '$(OBJ);
144 print_install = echo ' INSTALL '$1' to $(DESTDIR_SQ)$2'; 144 print_install = echo ' INSTALL '$1' to $(DESTDIR_SQ)$2';
145endif 145endif
146 146
147do_fpic_compile = \ 147do_fpic_compile = \
@@ -268,7 +268,7 @@ TRACK_CFLAGS = $(subst ','\'',$(CFLAGS)):$(ARCH):$(CROSS_COMPILE)
268TRACEEVENT-CFLAGS: force 268TRACEEVENT-CFLAGS: force
269 @FLAGS='$(TRACK_CFLAGS)'; \ 269 @FLAGS='$(TRACK_CFLAGS)'; \
270 if test x"$$FLAGS" != x"`cat TRACEEVENT-CFLAGS 2>/dev/null`" ; then \ 270 if test x"$$FLAGS" != x"`cat TRACEEVENT-CFLAGS 2>/dev/null`" ; then \
271 echo 1>&2 " * new build flags or cross compiler"; \ 271 echo 1>&2 " FLAGS: * new build flags or cross compiler"; \
272 echo "$$FLAGS" >TRACEEVENT-CFLAGS; \ 272 echo "$$FLAGS" >TRACEEVENT-CFLAGS; \
273 fi 273 fi
274 274
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
index d1c2a6a4cd32..8f450adaa9c2 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -305,6 +305,11 @@ int pevent_register_comm(struct pevent *pevent, const char *comm, int pid)
305 return 0; 305 return 0;
306} 306}
307 307
308void pevent_register_trace_clock(struct pevent *pevent, char *trace_clock)
309{
310 pevent->trace_clock = trace_clock;
311}
312
308struct func_map { 313struct func_map {
309 unsigned long long addr; 314 unsigned long long addr;
310 char *func; 315 char *func;
@@ -599,10 +604,11 @@ find_printk(struct pevent *pevent, unsigned long long addr)
599 * This registers a string by the address it was stored in the kernel. 604 * This registers a string by the address it was stored in the kernel.
600 * The @fmt passed in is duplicated. 605 * The @fmt passed in is duplicated.
601 */ 606 */
602int pevent_register_print_string(struct pevent *pevent, char *fmt, 607int pevent_register_print_string(struct pevent *pevent, const char *fmt,
603 unsigned long long addr) 608 unsigned long long addr)
604{ 609{
605 struct printk_list *item = malloc(sizeof(*item)); 610 struct printk_list *item = malloc(sizeof(*item));
611 char *p;
606 612
607 if (!item) 613 if (!item)
608 return -1; 614 return -1;
@@ -610,10 +616,21 @@ int pevent_register_print_string(struct pevent *pevent, char *fmt,
610 item->next = pevent->printklist; 616 item->next = pevent->printklist;
611 item->addr = addr; 617 item->addr = addr;
612 618
619 /* Strip off quotes and '\n' from the end */
620 if (fmt[0] == '"')
621 fmt++;
613 item->printk = strdup(fmt); 622 item->printk = strdup(fmt);
614 if (!item->printk) 623 if (!item->printk)
615 goto out_free; 624 goto out_free;
616 625
626 p = item->printk + strlen(item->printk) - 1;
627 if (*p == '"')
628 *p = 0;
629
630 p -= 2;
631 if (strcmp(p, "\\n") == 0)
632 *p = 0;
633
617 pevent->printklist = item; 634 pevent->printklist = item;
618 pevent->printk_count++; 635 pevent->printk_count++;
619 636
@@ -3488,6 +3505,7 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
3488 struct pevent *pevent = event->pevent; 3505 struct pevent *pevent = event->pevent;
3489 struct print_flag_sym *flag; 3506 struct print_flag_sym *flag;
3490 struct format_field *field; 3507 struct format_field *field;
3508 struct printk_map *printk;
3491 unsigned long long val, fval; 3509 unsigned long long val, fval;
3492 unsigned long addr; 3510 unsigned long addr;
3493 char *str; 3511 char *str;
@@ -3523,7 +3541,12 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
3523 if (!(field->flags & FIELD_IS_ARRAY) && 3541 if (!(field->flags & FIELD_IS_ARRAY) &&
3524 field->size == pevent->long_size) { 3542 field->size == pevent->long_size) {
3525 addr = *(unsigned long *)(data + field->offset); 3543 addr = *(unsigned long *)(data + field->offset);
3526 trace_seq_printf(s, "%lx", addr); 3544 /* Check if it matches a print format */
3545 printk = find_printk(pevent, addr);
3546 if (printk)
3547 trace_seq_puts(s, printk->printk);
3548 else
3549 trace_seq_printf(s, "%lx", addr);
3527 break; 3550 break;
3528 } 3551 }
3529 str = malloc(len + 1); 3552 str = malloc(len + 1);
@@ -3565,15 +3588,23 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
3565 } 3588 }
3566 break; 3589 break;
3567 case PRINT_HEX: 3590 case PRINT_HEX:
3568 field = arg->hex.field->field.field; 3591 if (arg->hex.field->type == PRINT_DYNAMIC_ARRAY) {
3569 if (!field) { 3592 unsigned long offset;
3570 str = arg->hex.field->field.name; 3593 offset = pevent_read_number(pevent,
3571 field = pevent_find_any_field(event, str); 3594 data + arg->hex.field->dynarray.field->offset,
3572 if (!field) 3595 arg->hex.field->dynarray.field->size);
3573 goto out_warning_field; 3596 hex = data + (offset & 0xffff);
3574 arg->hex.field->field.field = field; 3597 } else {
3598 field = arg->hex.field->field.field;
3599 if (!field) {
3600 str = arg->hex.field->field.name;
3601 field = pevent_find_any_field(event, str);
3602 if (!field)
3603 goto out_warning_field;
3604 arg->hex.field->field.field = field;
3605 }
3606 hex = data + field->offset;
3575 } 3607 }
3576 hex = data + field->offset;
3577 len = eval_num_arg(data, size, event, arg->hex.size); 3608 len = eval_num_arg(data, size, event, arg->hex.size);
3578 for (i = 0; i < len; i++) { 3609 for (i = 0; i < len; i++) {
3579 if (i) 3610 if (i)
@@ -3771,8 +3802,8 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc
3771 if (asprintf(&arg->atom.atom, "%lld", ip) < 0) 3802 if (asprintf(&arg->atom.atom, "%lld", ip) < 0)
3772 goto out_free; 3803 goto out_free;
3773 3804
3774 /* skip the first "%pf : " */ 3805 /* skip the first "%pf: " */
3775 for (ptr = fmt + 6, bptr = data + field->offset; 3806 for (ptr = fmt + 5, bptr = data + field->offset;
3776 bptr < data + size && *ptr; ptr++) { 3807 bptr < data + size && *ptr; ptr++) {
3777 int ls = 0; 3808 int ls = 0;
3778 3809
@@ -3882,7 +3913,6 @@ get_bprint_format(void *data, int size __maybe_unused,
3882 struct format_field *field; 3913 struct format_field *field;
3883 struct printk_map *printk; 3914 struct printk_map *printk;
3884 char *format; 3915 char *format;
3885 char *p;
3886 3916
3887 field = pevent->bprint_fmt_field; 3917 field = pevent->bprint_fmt_field;
3888 3918
@@ -3899,25 +3929,13 @@ get_bprint_format(void *data, int size __maybe_unused,
3899 3929
3900 printk = find_printk(pevent, addr); 3930 printk = find_printk(pevent, addr);
3901 if (!printk) { 3931 if (!printk) {
3902 if (asprintf(&format, "%%pf : (NO FORMAT FOUND at %llx)\n", addr) < 0) 3932 if (asprintf(&format, "%%pf: (NO FORMAT FOUND at %llx)\n", addr) < 0)
3903 return NULL; 3933 return NULL;
3904 return format; 3934 return format;
3905 } 3935 }
3906 3936
3907 p = printk->printk; 3937 if (asprintf(&format, "%s: %s", "%pf", printk->printk) < 0)
3908 /* Remove any quotes. */
3909 if (*p == '"')
3910 p++;
3911 if (asprintf(&format, "%s : %s", "%pf", p) < 0)
3912 return NULL; 3938 return NULL;
3913 /* remove ending quotes and new line since we will add one too */
3914 p = format + strlen(format) - 1;
3915 if (*p == '"')
3916 *p = 0;
3917
3918 p -= 2;
3919 if (strcmp(p, "\\n") == 0)
3920 *p = 0;
3921 3939
3922 return format; 3940 return format;
3923} 3941}
@@ -3963,7 +3981,7 @@ static int is_printable_array(char *p, unsigned int len)
3963 unsigned int i; 3981 unsigned int i;
3964 3982
3965 for (i = 0; i < len && p[i]; i++) 3983 for (i = 0; i < len && p[i]; i++)
3966 if (!isprint(p[i])) 3984 if (!isprint(p[i]) && !isspace(p[i]))
3967 return 0; 3985 return 0;
3968 return 1; 3986 return 1;
3969} 3987}
@@ -4428,11 +4446,11 @@ void pevent_event_info(struct trace_seq *s, struct event_format *event,
4428{ 4446{
4429 int print_pretty = 1; 4447 int print_pretty = 1;
4430 4448
4431 if (event->pevent->print_raw) 4449 if (event->pevent->print_raw || (event->flags & EVENT_FL_PRINTRAW))
4432 print_event_fields(s, record->data, record->size, event); 4450 print_event_fields(s, record->data, record->size, event);
4433 else { 4451 else {
4434 4452
4435 if (event->handler) 4453 if (event->handler && !(event->flags & EVENT_FL_NOHANDLE))
4436 print_pretty = event->handler(s, record, event, 4454 print_pretty = event->handler(s, record, event,
4437 event->context); 4455 event->context);
4438 4456
@@ -4443,8 +4461,21 @@ void pevent_event_info(struct trace_seq *s, struct event_format *event,
4443 trace_seq_terminate(s); 4461 trace_seq_terminate(s);
4444} 4462}
4445 4463
4464static bool is_timestamp_in_us(char *trace_clock, bool use_trace_clock)
4465{
4466 if (!use_trace_clock)
4467 return true;
4468
4469 if (!strcmp(trace_clock, "local") || !strcmp(trace_clock, "global")
4470 || !strcmp(trace_clock, "uptime") || !strcmp(trace_clock, "perf"))
4471 return true;
4472
4473 /* trace_clock is setting in tsc or counter mode */
4474 return false;
4475}
4476
4446void pevent_print_event(struct pevent *pevent, struct trace_seq *s, 4477void pevent_print_event(struct pevent *pevent, struct trace_seq *s,
4447 struct pevent_record *record) 4478 struct pevent_record *record, bool use_trace_clock)
4448{ 4479{
4449 static const char *spaces = " "; /* 20 spaces */ 4480 static const char *spaces = " "; /* 20 spaces */
4450 struct event_format *event; 4481 struct event_format *event;
@@ -4457,9 +4488,14 @@ void pevent_print_event(struct pevent *pevent, struct trace_seq *s,
4457 int pid; 4488 int pid;
4458 int len; 4489 int len;
4459 int p; 4490 int p;
4491 bool use_usec_format;
4460 4492
4461 secs = record->ts / NSECS_PER_SEC; 4493 use_usec_format = is_timestamp_in_us(pevent->trace_clock,
4462 nsecs = record->ts - secs * NSECS_PER_SEC; 4494 use_trace_clock);
4495 if (use_usec_format) {
4496 secs = record->ts / NSECS_PER_SEC;
4497 nsecs = record->ts - secs * NSECS_PER_SEC;
4498 }
4463 4499
4464 if (record->size < 0) { 4500 if (record->size < 0) {
4465 do_warning("ug! negative record size %d", record->size); 4501 do_warning("ug! negative record size %d", record->size);
@@ -4484,15 +4520,20 @@ void pevent_print_event(struct pevent *pevent, struct trace_seq *s,
4484 } else 4520 } else
4485 trace_seq_printf(s, "%16s-%-5d [%03d]", comm, pid, record->cpu); 4521 trace_seq_printf(s, "%16s-%-5d [%03d]", comm, pid, record->cpu);
4486 4522
4487 if (pevent->flags & PEVENT_NSEC_OUTPUT) { 4523 if (use_usec_format) {
4488 usecs = nsecs; 4524 if (pevent->flags & PEVENT_NSEC_OUTPUT) {
4489 p = 9; 4525 usecs = nsecs;
4490 } else { 4526 p = 9;
4491 usecs = (nsecs + 500) / NSECS_PER_USEC; 4527 } else {
4492 p = 6; 4528 usecs = (nsecs + 500) / NSECS_PER_USEC;
4493 } 4529 p = 6;
4530 }
4494 4531
4495 trace_seq_printf(s, " %5lu.%0*lu: %s: ", secs, p, usecs, event->name); 4532 trace_seq_printf(s, " %5lu.%0*lu: %s: ",
4533 secs, p, usecs, event->name);
4534 } else
4535 trace_seq_printf(s, " %12llu: %s: ",
4536 record->ts, event->name);
4496 4537
4497 /* Space out the event names evenly. */ 4538 /* Space out the event names evenly. */
4498 len = strlen(event->name); 4539 len = strlen(event->name);
@@ -5326,6 +5367,48 @@ int pevent_print_num_field(struct trace_seq *s, const char *fmt,
5326 return -1; 5367 return -1;
5327} 5368}
5328 5369
5370/**
5371 * pevent_print_func_field - print a field and a format for function pointers
5372 * @s: The seq to print to
5373 * @fmt: The printf format to print the field with.
5374 * @event: the event that the field is for
5375 * @name: The name of the field
5376 * @record: The record with the field name.
5377 * @err: print default error if failed.
5378 *
5379 * Returns: 0 on success, -1 field not found, or 1 if buffer is full.
5380 */
5381int pevent_print_func_field(struct trace_seq *s, const char *fmt,
5382 struct event_format *event, const char *name,
5383 struct pevent_record *record, int err)
5384{
5385 struct format_field *field = pevent_find_field(event, name);
5386 struct pevent *pevent = event->pevent;
5387 unsigned long long val;
5388 struct func_map *func;
5389 char tmp[128];
5390
5391 if (!field)
5392 goto failed;
5393
5394 if (pevent_read_number_field(field, record->data, &val))
5395 goto failed;
5396
5397 func = find_func(pevent, val);
5398
5399 if (func)
5400 snprintf(tmp, 128, "%s/0x%llx", func->func, func->addr - val);
5401 else
5402 sprintf(tmp, "0x%08llx", val);
5403
5404 return trace_seq_printf(s, fmt, tmp);
5405
5406 failed:
5407 if (err)
5408 trace_seq_printf(s, "CAN'T FIND FIELD \"%s\"", name);
5409 return -1;
5410}
5411
5329static void free_func_handle(struct pevent_function_handler *func) 5412static void free_func_handle(struct pevent_function_handler *func)
5330{ 5413{
5331 struct pevent_func_params *params; 5414 struct pevent_func_params *params;
diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h
index c37b2026d04a..8d73d2594f65 100644
--- a/tools/lib/traceevent/event-parse.h
+++ b/tools/lib/traceevent/event-parse.h
@@ -20,6 +20,7 @@
20#ifndef _PARSE_EVENTS_H 20#ifndef _PARSE_EVENTS_H
21#define _PARSE_EVENTS_H 21#define _PARSE_EVENTS_H
22 22
23#include <stdbool.h>
23#include <stdarg.h> 24#include <stdarg.h>
24#include <regex.h> 25#include <regex.h>
25 26
@@ -307,6 +308,8 @@ enum {
307 EVENT_FL_ISBPRINT = 0x04, 308 EVENT_FL_ISBPRINT = 0x04,
308 EVENT_FL_ISFUNCENT = 0x10, 309 EVENT_FL_ISFUNCENT = 0x10,
309 EVENT_FL_ISFUNCRET = 0x20, 310 EVENT_FL_ISFUNCRET = 0x20,
311 EVENT_FL_NOHANDLE = 0x40,
312 EVENT_FL_PRINTRAW = 0x80,
310 313
311 EVENT_FL_FAILED = 0x80000000 314 EVENT_FL_FAILED = 0x80000000
312}; 315};
@@ -450,6 +453,8 @@ struct pevent {
450 453
451 /* cache */ 454 /* cache */
452 struct event_format *last_event; 455 struct event_format *last_event;
456
457 char *trace_clock;
453}; 458};
454 459
455static inline void pevent_set_flag(struct pevent *pevent, int flag) 460static inline void pevent_set_flag(struct pevent *pevent, int flag)
@@ -527,14 +532,15 @@ enum trace_flag_type {
527}; 532};
528 533
529int pevent_register_comm(struct pevent *pevent, const char *comm, int pid); 534int pevent_register_comm(struct pevent *pevent, const char *comm, int pid);
535void pevent_register_trace_clock(struct pevent *pevent, char *trace_clock);
530int pevent_register_function(struct pevent *pevent, char *name, 536int pevent_register_function(struct pevent *pevent, char *name,
531 unsigned long long addr, char *mod); 537 unsigned long long addr, char *mod);
532int pevent_register_print_string(struct pevent *pevent, char *fmt, 538int pevent_register_print_string(struct pevent *pevent, const char *fmt,
533 unsigned long long addr); 539 unsigned long long addr);
534int pevent_pid_is_registered(struct pevent *pevent, int pid); 540int pevent_pid_is_registered(struct pevent *pevent, int pid);
535 541
536void pevent_print_event(struct pevent *pevent, struct trace_seq *s, 542void pevent_print_event(struct pevent *pevent, struct trace_seq *s,
537 struct pevent_record *record); 543 struct pevent_record *record, bool use_trace_clock);
538 544
539int pevent_parse_header_page(struct pevent *pevent, char *buf, unsigned long size, 545int pevent_parse_header_page(struct pevent *pevent, char *buf, unsigned long size,
540 int long_size); 546 int long_size);
@@ -563,6 +569,10 @@ int pevent_print_num_field(struct trace_seq *s, const char *fmt,
563 struct event_format *event, const char *name, 569 struct event_format *event, const char *name,
564 struct pevent_record *record, int err); 570 struct pevent_record *record, int err);
565 571
572int pevent_print_func_field(struct trace_seq *s, const char *fmt,
573 struct event_format *event, const char *name,
574 struct pevent_record *record, int err);
575
566int pevent_register_event_handler(struct pevent *pevent, int id, 576int pevent_register_event_handler(struct pevent *pevent, int id,
567 const char *sys_name, const char *event_name, 577 const char *sys_name, const char *event_name,
568 pevent_event_handler_func func, void *context); 578 pevent_event_handler_func func, void *context);
diff --git a/tools/perf/.gitignore b/tools/perf/.gitignore
index 8f8fbc227a46..782d86e961b9 100644
--- a/tools/perf/.gitignore
+++ b/tools/perf/.gitignore
@@ -13,6 +13,7 @@ perf*.html
13common-cmds.h 13common-cmds.h
14perf.data 14perf.data
15perf.data.old 15perf.data.old
16output.svg
16perf-archive 17perf-archive
17tags 18tags
18TAGS 19TAGS
diff --git a/tools/perf/Documentation/Makefile b/tools/perf/Documentation/Makefile
index 5a37a7c84e69..3ba1c0b09908 100644
--- a/tools/perf/Documentation/Makefile
+++ b/tools/perf/Documentation/Makefile
@@ -145,16 +145,17 @@ endif
145 145
146ifneq ($(findstring $(MAKEFLAGS),s),s) 146ifneq ($(findstring $(MAKEFLAGS),s),s)
147ifneq ($(V),1) 147ifneq ($(V),1)
148 QUIET_ASCIIDOC = @echo ' ' ASCIIDOC $@; 148 QUIET_ASCIIDOC = @echo ' ASCIIDOC '$@;
149 QUIET_XMLTO = @echo ' ' XMLTO $@; 149 QUIET_XMLTO = @echo ' XMLTO '$@;
150 QUIET_DB2TEXI = @echo ' ' DB2TEXI $@; 150 QUIET_DB2TEXI = @echo ' DB2TEXI '$@;
151 QUIET_MAKEINFO = @echo ' ' MAKEINFO $@; 151 QUIET_MAKEINFO = @echo ' MAKEINFO '$@;
152 QUIET_DBLATEX = @echo ' ' DBLATEX $@; 152 QUIET_DBLATEX = @echo ' DBLATEX '$@;
153 QUIET_XSLTPROC = @echo ' ' XSLTPROC $@; 153 QUIET_XSLTPROC = @echo ' XSLTPROC '$@;
154 QUIET_GEN = @echo ' ' GEN $@; 154 QUIET_GEN = @echo ' GEN '$@;
155 QUIET_STDERR = 2> /dev/null 155 QUIET_STDERR = 2> /dev/null
156 QUIET_SUBDIR0 = +@subdir= 156 QUIET_SUBDIR0 = +@subdir=
157 QUIET_SUBDIR1 = ;$(NO_SUBDIR) echo ' ' SUBDIR $$subdir; \ 157 QUIET_SUBDIR1 = ;$(NO_SUBDIR) \
158 echo ' SUBDIR ' $$subdir; \
158 $(MAKE) $(PRINT_DIR) -C $$subdir 159 $(MAKE) $(PRINT_DIR) -C $$subdir
159 export V 160 export V
160endif 161endif
@@ -183,47 +184,43 @@ ifdef missing_tools
183endif 184endif
184 185
185do-install-man: man 186do-install-man: man
186 $(INSTALL) -d -m 755 $(DESTDIR)$(man1dir) 187 $(call QUIET_INSTALL, Documentation-man) \
187# $(INSTALL) -d -m 755 $(DESTDIR)$(man5dir) 188 $(INSTALL) -d -m 755 $(DESTDIR)$(man1dir); \
188# $(INSTALL) -d -m 755 $(DESTDIR)$(man7dir) 189# $(INSTALL) -d -m 755 $(DESTDIR)$(man5dir); \
189 $(INSTALL) -m 644 $(DOC_MAN1) $(DESTDIR)$(man1dir) 190# $(INSTALL) -d -m 755 $(DESTDIR)$(man7dir); \
190# $(INSTALL) -m 644 $(DOC_MAN5) $(DESTDIR)$(man5dir) 191 $(INSTALL) -m 644 $(DOC_MAN1) $(DESTDIR)$(man1dir); \
191# $(INSTALL) -m 644 $(DOC_MAN7) $(DESTDIR)$(man7dir) 192# $(INSTALL) -m 644 $(DOC_MAN5) $(DESTDIR)$(man5dir); \
193# $(INSTALL) -m 644 $(DOC_MAN7) $(DESTDIR)$(man7dir)
192 194
193install-man: check-man-tools man 195install-man: check-man-tools man
194 196
195try-install-man:
196ifdef missing_tools 197ifdef missing_tools
197 $(warning Please install $(missing_tools) to have the man pages installed) 198 DO_INSTALL_MAN = $(warning Please install $(missing_tools) to have the man pages installed)
198else 199else
199 $(MAKE) do-install-man 200 DO_INSTALL_MAN = do-install-man
200endif 201endif
201 202
203try-install-man: $(DO_INSTALL_MAN)
204
202install-info: info 205install-info: info
203 $(INSTALL) -d -m 755 $(DESTDIR)$(infodir) 206 $(call QUIET_INSTALL, Documentation-info) \
204 $(INSTALL) -m 644 $(OUTPUT)perf.info $(OUTPUT)perfman.info $(DESTDIR)$(infodir) 207 $(INSTALL) -d -m 755 $(DESTDIR)$(infodir); \
208 $(INSTALL) -m 644 $(OUTPUT)perf.info $(OUTPUT)perfman.info $(DESTDIR)$(infodir); \
205 if test -r $(DESTDIR)$(infodir)/dir; then \ 209 if test -r $(DESTDIR)$(infodir)/dir; then \
206 $(INSTALL_INFO) --info-dir=$(DESTDIR)$(infodir) perf.info ;\ 210 $(INSTALL_INFO) --info-dir=$(DESTDIR)$(infodir) perf.info ;\
207 $(INSTALL_INFO) --info-dir=$(DESTDIR)$(infodir) perfman.info ;\ 211 $(INSTALL_INFO) --info-dir=$(DESTDIR)$(infodir) perfman.info ;\
208 else \ 212 else \
209 echo "No directory found in $(DESTDIR)$(infodir)" >&2 ; \ 213 echo "No directory found in $(DESTDIR)$(infodir)" >&2 ; \
210 fi 214 fi
211 215
212install-pdf: pdf 216install-pdf: pdf
213 $(INSTALL) -d -m 755 $(DESTDIR)$(pdfdir) 217 $(call QUIET_INSTALL, Documentation-pdf) \
214 $(INSTALL) -m 644 $(OUTPUT)user-manual.pdf $(DESTDIR)$(pdfdir) 218 $(INSTALL) -d -m 755 $(DESTDIR)$(pdfdir); \
219 $(INSTALL) -m 644 $(OUTPUT)user-manual.pdf $(DESTDIR)$(pdfdir)
215 220
216#install-html: html 221#install-html: html
217# '$(SHELL_PATH_SQ)' ./install-webdoc.sh $(DESTDIR)$(htmldir) 222# '$(SHELL_PATH_SQ)' ./install-webdoc.sh $(DESTDIR)$(htmldir)
218 223
219ifneq ($(MAKECMDGOALS),clean)
220ifneq ($(MAKECMDGOALS),tags)
221$(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE
222 $(QUIET_SUBDIR0)../ $(QUIET_SUBDIR1) $(OUTPUT)PERF-VERSION-FILE
223
224-include $(OUTPUT)PERF-VERSION-FILE
225endif
226endif
227 224
228# 225#
229# Determine "include::" file references in asciidoc files. 226# Determine "include::" file references in asciidoc files.
@@ -253,15 +250,17 @@ $(OUTPUT)cmd-list.made: cmd-list.perl ../command-list.txt $(MAN1_TXT)
253 $(PERL_PATH) ./cmd-list.perl ../command-list.txt $(QUIET_STDERR) && \ 250 $(PERL_PATH) ./cmd-list.perl ../command-list.txt $(QUIET_STDERR) && \
254 date >$@ 251 date >$@
255 252
253CLEAN_FILES = \
254 $(MAN_XML) $(addsuffix +,$(MAN_XML)) \
255 $(MAN_HTML) $(addsuffix +,$(MAN_HTML)) \
256 $(DOC_HTML) $(DOC_MAN1) $(DOC_MAN5) $(DOC_MAN7) \
257 $(OUTPUT)*.texi $(OUTPUT)*.texi+ $(OUTPUT)*.texi++ \
258 $(OUTPUT)perf.info $(OUTPUT)perfman.info \
259 $(OUTPUT)howto-index.txt $(OUTPUT)howto/*.html $(OUTPUT)doc.dep \
260 $(OUTPUT)technical/api-*.html $(OUTPUT)technical/api-index.txt \
261 $(cmds_txt) $(OUTPUT)*.made
256clean: 262clean:
257 $(RM) $(MAN_XML) $(addsuffix +,$(MAN_XML)) 263 $(call QUIET_CLEAN, Documentation) $(RM) $(CLEAN_FILES)
258 $(RM) $(MAN_HTML) $(addsuffix +,$(MAN_HTML))
259 $(RM) $(DOC_HTML) $(DOC_MAN1) $(DOC_MAN5) $(DOC_MAN7)
260 $(RM) $(OUTPUT)*.texi $(OUTPUT)*.texi+ $(OUTPUT)*.texi++
261 $(RM) $(OUTPUT)perf.info $(OUTPUT)perfman.info
262 $(RM) $(OUTPUT)howto-index.txt $(OUTPUT)howto/*.html $(OUTPUT)doc.dep
263 $(RM) $(OUTPUT)technical/api-*.html $(OUTPUT)technical/api-index.txt
264 $(RM) $(cmds_txt) $(OUTPUT)*.made
265 264
266$(MAN_HTML): $(OUTPUT)%.html : %.txt 265$(MAN_HTML): $(OUTPUT)%.html : %.txt
267 $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \ 266 $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \
@@ -342,5 +341,3 @@ $(patsubst %.txt,%.html,$(wildcard howto/*.txt)): %.html : %.txt
342 341
343#quick-install-html: 342#quick-install-html:
344# '$(SHELL_PATH_SQ)' ./install-doc-quick.sh $(HTML_REF) $(DESTDIR)$(htmldir) 343# '$(SHELL_PATH_SQ)' ./install-doc-quick.sh $(HTML_REF) $(DESTDIR)$(htmldir)
345
346.PHONY: .FORCE-PERF-VERSION-FILE
diff --git a/tools/perf/Documentation/perf-buildid-cache.txt b/tools/perf/Documentation/perf-buildid-cache.txt
index e9a8349a7172..fd77d81ea748 100644
--- a/tools/perf/Documentation/perf-buildid-cache.txt
+++ b/tools/perf/Documentation/perf-buildid-cache.txt
@@ -21,6 +21,19 @@ OPTIONS
21-a:: 21-a::
22--add=:: 22--add=::
23 Add specified file to the cache. 23 Add specified file to the cache.
24-k::
25--kcore::
26 Add specified kcore file to the cache. For the current host that is
27 /proc/kcore which requires root permissions to read. Be aware that
28 running 'perf buildid-cache' as root may update root's build-id cache
29 not the user's. Use the -v option to see where the file is created.
30 Note that the copied file contains only code sections not the whole core
31 image. Note also that files "kallsyms" and "modules" must also be in the
32 same directory and are also copied. All 3 files are created with read
33 permissions for root only. kcore will not be added if there is already a
34 kcore in the cache (with the same build-id) that has the same modules at
35 the same addresses. Use the -v option to see if a copy of kcore is
36 actually made.
24-r:: 37-r::
25--remove=:: 38--remove=::
26 Remove specified file from the cache. 39 Remove specified file from the cache.
diff --git a/tools/perf/Documentation/perf-kvm.txt b/tools/perf/Documentation/perf-kvm.txt
index ac84db2d2334..6a06cefe9642 100644
--- a/tools/perf/Documentation/perf-kvm.txt
+++ b/tools/perf/Documentation/perf-kvm.txt
@@ -109,7 +109,9 @@ STAT LIVE OPTIONS
109 109
110-m:: 110-m::
111--mmap-pages=:: 111--mmap-pages=::
112 Number of mmap data pages. Must be a power of two. 112 Number of mmap data pages (must be a power of two) or size
113 specification with appended unit character - B/K/M/G. The
114 size is rounded up to have nearest pages power of two value.
113 115
114-a:: 116-a::
115--all-cpus:: 117--all-cpus::
diff --git a/tools/perf/Documentation/perf-lock.txt b/tools/perf/Documentation/perf-lock.txt
index c7f5f55634ac..ab25be28c9dc 100644
--- a/tools/perf/Documentation/perf-lock.txt
+++ b/tools/perf/Documentation/perf-lock.txt
@@ -48,7 +48,7 @@ REPORT OPTIONS
48-k:: 48-k::
49--key=<value>:: 49--key=<value>::
50 Sorting key. Possible values: acquired (default), contended, 50 Sorting key. Possible values: acquired (default), contended,
51 wait_total, wait_max, wait_min. 51 avg_wait, wait_total, wait_max, wait_min.
52 52
53INFO OPTIONS 53INFO OPTIONS
54------------ 54------------
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index ca0d3d9f4bac..052f7c4dc00c 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -87,7 +87,9 @@ OPTIONS
87 87
88-m:: 88-m::
89--mmap-pages=:: 89--mmap-pages=::
90 Number of mmap data pages. Must be a power of two. 90 Number of mmap data pages (must be a power of two) or size
91 specification with appended unit character - B/K/M/G. The
92 size is rounded up to have nearest pages power of two value.
91 93
92-g:: 94-g::
93 Enables call-graph (stack chain/backtrace) recording. 95 Enables call-graph (stack chain/backtrace) recording.
@@ -178,6 +180,9 @@ following filters are defined:
178 - u: only when the branch target is at the user level 180 - u: only when the branch target is at the user level
179 - k: only when the branch target is in the kernel 181 - k: only when the branch target is in the kernel
180 - hv: only when the target is at the hypervisor level 182 - hv: only when the target is at the hypervisor level
183 - in_tx: only when the target is in a hardware transaction
184 - no_tx: only when the target is not in a hardware transaction
185 - abort_tx: only when the target is a hardware transaction abort
181 186
182+ 187+
183The option requires at least one branch type among any, any_call, any_ret, ind_call. 188The option requires at least one branch type among any, any_call, any_ret, ind_call.
@@ -188,12 +193,14 @@ is enabled for all the sampling events. The sampled branch type is the same for
188The various filters must be specified as a comma separated list: --branch-filter any_ret,u,k 193The various filters must be specified as a comma separated list: --branch-filter any_ret,u,k
189Note that this feature may not be available on all processors. 194Note that this feature may not be available on all processors.
190 195
191-W::
192--weight:: 196--weight::
193Enable weightened sampling. An additional weight is recorded per sample and can be 197Enable weightened sampling. An additional weight is recorded per sample and can be
194displayed with the weight and local_weight sort keys. This currently works for TSX 198displayed with the weight and local_weight sort keys. This currently works for TSX
195abort events and some memory events in precise mode on modern Intel CPUs. 199abort events and some memory events in precise mode on modern Intel CPUs.
196 200
201--transaction::
202Record transaction flags for transaction related events.
203
197SEE ALSO 204SEE ALSO
198-------- 205--------
199linkperf:perf-stat[1], linkperf:perf-list[1] 206linkperf:perf-stat[1], linkperf:perf-list[1]
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 2b8097ee39d8..10a279871251 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -71,7 +71,11 @@ OPTIONS
71 entries are displayed as "[other]". 71 entries are displayed as "[other]".
72 - cpu: cpu number the task ran at the time of sample 72 - cpu: cpu number the task ran at the time of sample
73 - srcline: filename and line number executed at the time of sample. The 73 - srcline: filename and line number executed at the time of sample. The
74 DWARF debuggin info must be provided. 74 DWARF debugging info must be provided.
75 - weight: Event specific weight, e.g. memory latency or transaction
76 abort cost. This is the global weight.
77 - local_weight: Local weight version of the weight above.
78 - transaction: Transaction abort flags.
75 79
76 By default, comm, dso and symbol keys are used. 80 By default, comm, dso and symbol keys are used.
77 (i.e. --sort comm,dso,symbol) 81 (i.e. --sort comm,dso,symbol)
@@ -85,6 +89,8 @@ OPTIONS
85 - symbol_from: name of function branched from 89 - symbol_from: name of function branched from
86 - symbol_to: name of function branched to 90 - symbol_to: name of function branched to
87 - mispredict: "N" for predicted branch, "Y" for mispredicted branch 91 - mispredict: "N" for predicted branch, "Y" for mispredicted branch
92 - in_tx: branch in TSX transaction
93 - abort: TSX transaction abort.
88 94
89 And default sort keys are changed to comm, dso_from, symbol_from, dso_to 95 And default sort keys are changed to comm, dso_from, symbol_from, dso_to
90 and symbol_to, see '--branch-stack'. 96 and symbol_to, see '--branch-stack'.
@@ -135,6 +141,14 @@ OPTIONS
135 141
136 Default: fractal,0.5,callee,function. 142 Default: fractal,0.5,callee,function.
137 143
144--max-stack::
145 Set the stack depth limit when parsing the callchain, anything
146 beyond the specified depth will be ignored. This is a trade-off
147 between information loss and faster processing especially for
148 workloads that can have a very long callchain stack.
149
150 Default: 127
151
138-G:: 152-G::
139--inverted:: 153--inverted::
140 alias for inverted caller based call graph. 154 alias for inverted caller based call graph.
diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index 73c9759005a3..80c7da6732f2 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -137,6 +137,11 @@ core number and the number of online logical processors on that physical process
137After starting the program, wait msecs before measuring. This is useful to 137After starting the program, wait msecs before measuring. This is useful to
138filter out the startup phase of the program, which is often very different. 138filter out the startup phase of the program, which is often very different.
139 139
140-T::
141--transaction::
142
143Print statistics of transactional execution if supported.
144
140EXAMPLES 145EXAMPLES
141-------- 146--------
142 147
diff --git a/tools/perf/Documentation/perf-timechart.txt b/tools/perf/Documentation/perf-timechart.txt
index 1632b0efc757..3ff8bd4f0b4d 100644
--- a/tools/perf/Documentation/perf-timechart.txt
+++ b/tools/perf/Documentation/perf-timechart.txt
@@ -8,7 +8,8 @@ perf-timechart - Tool to visualize total system behavior during a workload
8SYNOPSIS 8SYNOPSIS
9-------- 9--------
10[verse] 10[verse]
11'perf timechart' {record} 11'perf timechart' record <command>
12'perf timechart' [<options>]
12 13
13DESCRIPTION 14DESCRIPTION
14----------- 15-----------
@@ -41,6 +42,18 @@ OPTIONS
41--symfs=<directory>:: 42--symfs=<directory>::
42 Look for files with symbols relative to this directory. 43 Look for files with symbols relative to this directory.
43 44
45EXAMPLES
46--------
47
48$ perf timechart record git pull
49
50 [ perf record: Woken up 13 times to write data ]
51 [ perf record: Captured and wrote 4.253 MB perf.data (~185801 samples) ]
52
53$ perf timechart
54
55 Written 10.2 seconds of trace to output.svg.
56
44SEE ALSO 57SEE ALSO
45-------- 58--------
46linkperf:perf-record[1] 59linkperf:perf-record[1]
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt
index 6a118e71d003..7de01dd79688 100644
--- a/tools/perf/Documentation/perf-top.txt
+++ b/tools/perf/Documentation/perf-top.txt
@@ -68,7 +68,9 @@ Default is to monitor all CPUS.
68 68
69-m <pages>:: 69-m <pages>::
70--mmap-pages=<pages>:: 70--mmap-pages=<pages>::
71 Number of mmapped data pages. 71 Number of mmap data pages (must be a power of two) or size
72 specification with appended unit character - B/K/M/G. The
73 size is rounded up to have nearest pages power of two value.
72 74
73-p <pid>:: 75-p <pid>::
74--pid=<pid>:: 76--pid=<pid>::
@@ -112,7 +114,8 @@ Default is to monitor all CPUS.
112 114
113-s:: 115-s::
114--sort:: 116--sort::
115 Sort by key(s): pid, comm, dso, symbol, parent, srcline, weight, local_weight. 117 Sort by key(s): pid, comm, dso, symbol, parent, srcline, weight,
118 local_weight, abort, in_tx, transaction
116 119
117-n:: 120-n::
118--show-nr-samples:: 121--show-nr-samples::
@@ -147,6 +150,14 @@ Default is to monitor all CPUS.
147 Setup and enable call-graph (stack chain/backtrace) recording, 150 Setup and enable call-graph (stack chain/backtrace) recording,
148 implies -G. 151 implies -G.
149 152
153--max-stack::
154 Set the stack depth limit when parsing the callchain, anything
155 beyond the specified depth will be ignored. This is a trade-off
156 between information loss and faster processing especially for
157 workloads that can have a very long callchain stack.
158
159 Default: 127
160
150--ignore-callees=<regex>:: 161--ignore-callees=<regex>::
151 Ignore callees of the function(s) matching the given regex. 162 Ignore callees of the function(s) matching the given regex.
152 This has the effect of collecting the callers of each such 163 This has the effect of collecting the callers of each such
diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt
index daccd2c0a48f..7b0497f95a75 100644
--- a/tools/perf/Documentation/perf-trace.txt
+++ b/tools/perf/Documentation/perf-trace.txt
@@ -9,6 +9,7 @@ SYNOPSIS
9-------- 9--------
10[verse] 10[verse]
11'perf trace' 11'perf trace'
12'perf trace record'
12 13
13DESCRIPTION 14DESCRIPTION
14----------- 15-----------
@@ -16,9 +17,14 @@ This command will show the events associated with the target, initially
16syscalls, but other system events like pagefaults, task lifetime events, 17syscalls, but other system events like pagefaults, task lifetime events,
17scheduling events, etc. 18scheduling events, etc.
18 19
19Initially this is a live mode only tool, but eventually will work with 20This is a live mode tool in addition to working with perf.data files like
20perf.data files like the other tools, allowing a detached 'record' from 21the other perf tools. Files can be generated using the 'perf record' command
21analysis phases. 22but the session needs to include the raw_syscalls events (-e 'raw_syscalls:*').
23Alernatively, the 'perf trace record' can be used as a shortcut to
24automatically include the raw_syscalls events when writing events to a file.
25
26The following options apply to perf trace; options to perf trace record are
27found in the perf record man page.
22 28
23OPTIONS 29OPTIONS
24------- 30-------
@@ -59,7 +65,9 @@ OPTIONS
59 65
60-m:: 66-m::
61--mmap-pages=:: 67--mmap-pages=::
62 Number of mmap data pages. Must be a power of two. 68 Number of mmap data pages (must be a power of two) or size
69 specification with appended unit character - B/K/M/G. The
70 size is rounded up to have nearest pages power of two value.
63 71
64-C:: 72-C::
65--cpu:: 73--cpu::
@@ -78,6 +86,21 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs.
78--input 86--input
79 Process events from a given perf data file. 87 Process events from a given perf data file.
80 88
89-T
90--time
91 Print full timestamp rather time relative to first sample.
92
93--comm::
94 Show process COMM right beside its ID, on by default, disable with --no-comm.
95
96--summary::
97 Show a summary of syscalls by thread with min, max, and average times (in
98 msec) and relative stddev.
99
100--tool_stats::
101 Show tool stats such as number of times fd->pathname was discovered thru
102 hooking the open syscall return + vfs_getname or via reading /proc/pid/fd, etc.
103
81SEE ALSO 104SEE ALSO
82-------- 105--------
83linkperf:perf-record[1], linkperf:perf-script[1] 106linkperf:perf-record[1], linkperf:perf-script[1]
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 64c043b7a438..4835618a5608 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -1,819 +1,79 @@
1include ../scripts/Makefile.include
2
3# The default target of this Makefile is...
4all:
5
6include config/utilities.mak
7
8# Define V to have a more verbose compile.
9#
10# Define O to save output files in a separate directory.
11#
12# Define ARCH as name of target architecture if you want cross-builds.
13#
14# Define CROSS_COMPILE as prefix name of compiler if you want cross-builds.
15#
16# Define NO_LIBPERL to disable perl script extension.
17#
18# Define NO_LIBPYTHON to disable python script extension.
19#
20# Define PYTHON to point to the python binary if the default
21# `python' is not correct; for example: PYTHON=python2
22#
23# Define PYTHON_CONFIG to point to the python-config binary if
24# the default `$(PYTHON)-config' is not correct.
25# 1#
26# Define ASCIIDOC8 if you want to format documentation with AsciiDoc 8 2# This is a simple wrapper Makefile that calls the main Makefile.perf
3# with a -j option to do parallel builds
27# 4#
28# Define DOCBOOK_XSL_172 if you want to format man pages with DocBook XSL v1.72. 5# If you want to invoke the perf build in some non-standard way then
6# you can use the 'make -f Makefile.perf' method to invoke it.
29# 7#
30# Define LDFLAGS=-static to build a static binary. 8
31#
32# Define EXTRA_CFLAGS=-m64 or EXTRA_CFLAGS=-m32 as appropriate for cross-builds.
33#
34# Define NO_DWARF if you do not want debug-info analysis feature at all.
35#
36# Define WERROR=0 to disable treating any warnings as errors.
37#
38# Define NO_NEWT if you do not want TUI support. (deprecated)
39#
40# Define NO_SLANG if you do not want TUI support.
41#
42# Define NO_GTK2 if you do not want GTK+ GUI support.
43# 9#
44# Define NO_DEMANGLE if you do not want C++ symbol demangling. 10# Clear out the built-in rules GNU make defines by default (such as .o targets),
11# so that we pass through all targets to Makefile.perf:
45# 12#
46# Define NO_LIBELF if you do not want libelf dependency (e.g. cross-builds) 13.SUFFIXES:
14
47# 15#
48# Define NO_LIBUNWIND if you do not want libunwind dependency for dwarf 16# We don't want to pass along options like -j:
49# backtrace post unwind.
50# 17#
51# Define NO_BACKTRACE if you do not want stack backtrace debug feature 18unexport MAKEFLAGS
19
52# 20#
53# Define NO_LIBNUMA if you do not want numa perf benchmark 21# Do a parallel build with multiple jobs, based on the number of CPUs online
22# in this system: 'make -j8' on a 8-CPU system, etc.
54# 23#
55# Define NO_LIBAUDIT if you do not want libaudit support 24# (To override it, run 'make JOBS=1' and similar.)
56# 25#
57# Define NO_LIBBIONIC if you do not want bionic support 26ifeq ($(JOBS),)
58 27 JOBS := $(shell grep -c ^processor /proc/cpuinfo 2>/dev/null)
59ifeq ($(srctree),) 28 ifeq ($(JOBS),)
60srctree := $(patsubst %/,%,$(dir $(shell pwd))) 29 JOBS := 1
61srctree := $(patsubst %/,%,$(dir $(srctree))) 30 endif
62#$(info Determined 'srctree' to be $(srctree))
63endif
64
65ifneq ($(objtree),)
66#$(info Determined 'objtree' to be $(objtree))
67endif
68
69ifneq ($(OUTPUT),)
70#$(info Determined 'OUTPUT' to be $(OUTPUT))
71endif
72
73$(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE
74 @$(SHELL_PATH) util/PERF-VERSION-GEN $(OUTPUT)
75
76CC = $(CROSS_COMPILE)gcc
77AR = $(CROSS_COMPILE)ar
78
79RM = rm -f
80MKDIR = mkdir
81FIND = find
82INSTALL = install
83FLEX = flex
84BISON = bison
85STRIP = strip
86
87LK_DIR = $(srctree)/tools/lib/lk/
88TRACE_EVENT_DIR = $(srctree)/tools/lib/traceevent/
89
90# include config/Makefile by default and rule out
91# non-config cases
92config := 1
93
94NON_CONFIG_TARGETS := clean TAGS tags cscope help
95
96ifdef MAKECMDGOALS
97ifeq ($(filter-out $(NON_CONFIG_TARGETS),$(MAKECMDGOALS)),)
98 config := 0
99endif
100endif 31endif
101 32
102ifeq ($(config),1) 33#
103include config/Makefile 34# Only pass canonical directory names as the output directory:
35#
36ifneq ($(O),)
37 FULL_O := $(shell readlink -f $(O) || echo $(O))
104endif 38endif
105 39
106export prefix bindir sharedir sysconfdir 40#
107 41# Only accept the 'DEBUG' variable from the command line:
108# sparse is architecture-neutral, which means that we need to tell it 42#
109# explicitly what architecture to check for. Fix this up for yours.. 43ifeq ("$(origin DEBUG)", "command line")
110SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__ 44 ifeq ($(DEBUG),)
111 45 override DEBUG = 0
112# Guard against environment variables 46 else
113BUILTIN_OBJS = 47 SET_DEBUG = "DEBUG=$(DEBUG)"
114LIB_H = 48 endif
115LIB_OBJS =
116PYRF_OBJS =
117SCRIPT_SH =
118
119SCRIPT_SH += perf-archive.sh
120
121grep-libs = $(filter -l%,$(1))
122strip-libs = $(filter-out -l%,$(1))
123
124ifneq ($(OUTPUT),)
125 TE_PATH=$(OUTPUT)
126ifneq ($(subdir),)
127 LK_PATH=$(OUTPUT)/../lib/lk/
128else
129 LK_PATH=$(OUTPUT)
130endif
131else 49else
132 TE_PATH=$(TRACE_EVENT_DIR) 50 override DEBUG = 0
133 LK_PATH=$(LK_DIR)
134endif 51endif
135 52
136LIBTRACEEVENT = $(TE_PATH)libtraceevent.a 53define print_msg
137export LIBTRACEEVENT 54 @printf ' BUILD: Doing '\''make \033[33m-j'$(JOBS)'\033[m'\'' parallel build\n'
138 55endef
139LIBLK = $(LK_PATH)liblk.a
140export LIBLK
141
142# python extension build directories
143PYTHON_EXTBUILD := $(OUTPUT)python_ext_build/
144PYTHON_EXTBUILD_LIB := $(PYTHON_EXTBUILD)lib/
145PYTHON_EXTBUILD_TMP := $(PYTHON_EXTBUILD)tmp/
146export PYTHON_EXTBUILD_LIB PYTHON_EXTBUILD_TMP
147 56
148python-clean := rm -rf $(PYTHON_EXTBUILD) $(OUTPUT)python/perf.so 57define make
58 @$(MAKE) -f Makefile.perf --no-print-directory -j$(JOBS) O=$(FULL_O) $(SET_DEBUG) $@
59endef
149 60
150PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources)
151PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBLK)
152
153$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS)
154 $(QUIET_GEN)CFLAGS='$(CFLAGS)' $(PYTHON_WORD) util/setup.py \
155 --quiet build_ext; \
156 mkdir -p $(OUTPUT)python && \
157 cp $(PYTHON_EXTBUILD_LIB)perf.so $(OUTPUT)python/
158# 61#
159# No Perl scripts right now: 62# Needed if no target specified:
160# 63#
161 64all:
162SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) 65 $(print_msg)
66 $(make)
163 67
164# 68#
165# Single 'perf' binary right now: 69# The clean target is not really parallel, don't print the jobs info:
166# 70#
167PROGRAMS += $(OUTPUT)perf 71clean:
168 72 $(make)
169# what 'all' will build and 'install' will install, in perfexecdir
170ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS)
171
172# what 'all' will build but not install in perfexecdir
173OTHER_PROGRAMS = $(OUTPUT)perf
174
175# Set paths to tools early so that they can be used for version tests.
176ifndef SHELL_PATH
177 SHELL_PATH = /bin/sh
178endif
179ifndef PERL_PATH
180 PERL_PATH = /usr/bin/perl
181endif
182
183export PERL_PATH
184
185$(OUTPUT)util/parse-events-flex.c: util/parse-events.l $(OUTPUT)util/parse-events-bison.c
186 $(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) -t util/parse-events.l > $(OUTPUT)util/parse-events-flex.c
187
188$(OUTPUT)util/parse-events-bison.c: util/parse-events.y
189 $(QUIET_BISON)$(BISON) -v util/parse-events.y -d $(PARSER_DEBUG_BISON) -o $(OUTPUT)util/parse-events-bison.c -p parse_events_
190
191$(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c
192 $(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/pmu-flex.h -t util/pmu.l > $(OUTPUT)util/pmu-flex.c
193
194$(OUTPUT)util/pmu-bison.c: util/pmu.y
195 $(QUIET_BISON)$(BISON) -v util/pmu.y -d -o $(OUTPUT)util/pmu-bison.c -p perf_pmu_
196
197$(OUTPUT)util/parse-events.o: $(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-bison.c
198$(OUTPUT)util/pmu.o: $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-bison.c
199
200LIB_FILE=$(OUTPUT)libperf.a
201
202LIB_H += ../../include/uapi/linux/perf_event.h
203LIB_H += ../../include/linux/rbtree.h
204LIB_H += ../../include/linux/list.h
205LIB_H += ../../include/uapi/linux/const.h
206LIB_H += ../../include/linux/hash.h
207LIB_H += ../../include/linux/stringify.h
208LIB_H += util/include/linux/bitmap.h
209LIB_H += util/include/linux/bitops.h
210LIB_H += util/include/linux/compiler.h
211LIB_H += util/include/linux/const.h
212LIB_H += util/include/linux/ctype.h
213LIB_H += util/include/linux/kernel.h
214LIB_H += util/include/linux/list.h
215LIB_H += util/include/linux/export.h
216LIB_H += util/include/linux/magic.h
217LIB_H += util/include/linux/poison.h
218LIB_H += util/include/linux/prefetch.h
219LIB_H += util/include/linux/rbtree.h
220LIB_H += util/include/linux/rbtree_augmented.h
221LIB_H += util/include/linux/string.h
222LIB_H += util/include/linux/types.h
223LIB_H += util/include/linux/linkage.h
224LIB_H += util/include/asm/asm-offsets.h
225LIB_H += util/include/asm/bug.h
226LIB_H += util/include/asm/byteorder.h
227LIB_H += util/include/asm/hweight.h
228LIB_H += util/include/asm/swab.h
229LIB_H += util/include/asm/system.h
230LIB_H += util/include/asm/uaccess.h
231LIB_H += util/include/dwarf-regs.h
232LIB_H += util/include/asm/dwarf2.h
233LIB_H += util/include/asm/cpufeature.h
234LIB_H += util/include/asm/unistd_32.h
235LIB_H += util/include/asm/unistd_64.h
236LIB_H += perf.h
237LIB_H += util/annotate.h
238LIB_H += util/cache.h
239LIB_H += util/callchain.h
240LIB_H += util/build-id.h
241LIB_H += util/debug.h
242LIB_H += util/sysfs.h
243LIB_H += util/pmu.h
244LIB_H += util/event.h
245LIB_H += util/evsel.h
246LIB_H += util/evlist.h
247LIB_H += util/exec_cmd.h
248LIB_H += util/types.h
249LIB_H += util/levenshtein.h
250LIB_H += util/machine.h
251LIB_H += util/map.h
252LIB_H += util/parse-options.h
253LIB_H += util/parse-events.h
254LIB_H += util/quote.h
255LIB_H += util/util.h
256LIB_H += util/xyarray.h
257LIB_H += util/header.h
258LIB_H += util/help.h
259LIB_H += util/session.h
260LIB_H += util/strbuf.h
261LIB_H += util/strlist.h
262LIB_H += util/strfilter.h
263LIB_H += util/svghelper.h
264LIB_H += util/tool.h
265LIB_H += util/run-command.h
266LIB_H += util/sigchain.h
267LIB_H += util/dso.h
268LIB_H += util/symbol.h
269LIB_H += util/color.h
270LIB_H += util/values.h
271LIB_H += util/sort.h
272LIB_H += util/hist.h
273LIB_H += util/thread.h
274LIB_H += util/thread_map.h
275LIB_H += util/trace-event.h
276LIB_H += util/probe-finder.h
277LIB_H += util/dwarf-aux.h
278LIB_H += util/probe-event.h
279LIB_H += util/pstack.h
280LIB_H += util/cpumap.h
281LIB_H += util/top.h
282LIB_H += $(ARCH_INCLUDE)
283LIB_H += util/cgroup.h
284LIB_H += $(LIB_INCLUDE)traceevent/event-parse.h
285LIB_H += util/target.h
286LIB_H += util/rblist.h
287LIB_H += util/intlist.h
288LIB_H += util/perf_regs.h
289LIB_H += util/unwind.h
290LIB_H += util/vdso.h
291LIB_H += ui/helpline.h
292LIB_H += ui/progress.h
293LIB_H += ui/util.h
294LIB_H += ui/ui.h
295
296LIB_OBJS += $(OUTPUT)util/abspath.o
297LIB_OBJS += $(OUTPUT)util/alias.o
298LIB_OBJS += $(OUTPUT)util/annotate.o
299LIB_OBJS += $(OUTPUT)util/build-id.o
300LIB_OBJS += $(OUTPUT)util/config.o
301LIB_OBJS += $(OUTPUT)util/ctype.o
302LIB_OBJS += $(OUTPUT)util/sysfs.o
303LIB_OBJS += $(OUTPUT)util/pmu.o
304LIB_OBJS += $(OUTPUT)util/environment.o
305LIB_OBJS += $(OUTPUT)util/event.o
306LIB_OBJS += $(OUTPUT)util/evlist.o
307LIB_OBJS += $(OUTPUT)util/evsel.o
308LIB_OBJS += $(OUTPUT)util/exec_cmd.o
309LIB_OBJS += $(OUTPUT)util/help.o
310LIB_OBJS += $(OUTPUT)util/levenshtein.o
311LIB_OBJS += $(OUTPUT)util/parse-options.o
312LIB_OBJS += $(OUTPUT)util/parse-events.o
313LIB_OBJS += $(OUTPUT)util/path.o
314LIB_OBJS += $(OUTPUT)util/rbtree.o
315LIB_OBJS += $(OUTPUT)util/bitmap.o
316LIB_OBJS += $(OUTPUT)util/hweight.o
317LIB_OBJS += $(OUTPUT)util/run-command.o
318LIB_OBJS += $(OUTPUT)util/quote.o
319LIB_OBJS += $(OUTPUT)util/strbuf.o
320LIB_OBJS += $(OUTPUT)util/string.o
321LIB_OBJS += $(OUTPUT)util/strlist.o
322LIB_OBJS += $(OUTPUT)util/strfilter.o
323LIB_OBJS += $(OUTPUT)util/top.o
324LIB_OBJS += $(OUTPUT)util/usage.o
325LIB_OBJS += $(OUTPUT)util/wrapper.o
326LIB_OBJS += $(OUTPUT)util/sigchain.o
327LIB_OBJS += $(OUTPUT)util/dso.o
328LIB_OBJS += $(OUTPUT)util/symbol.o
329LIB_OBJS += $(OUTPUT)util/symbol-elf.o
330LIB_OBJS += $(OUTPUT)util/color.o
331LIB_OBJS += $(OUTPUT)util/pager.o
332LIB_OBJS += $(OUTPUT)util/header.o
333LIB_OBJS += $(OUTPUT)util/callchain.o
334LIB_OBJS += $(OUTPUT)util/values.o
335LIB_OBJS += $(OUTPUT)util/debug.o
336LIB_OBJS += $(OUTPUT)util/machine.o
337LIB_OBJS += $(OUTPUT)util/map.o
338LIB_OBJS += $(OUTPUT)util/pstack.o
339LIB_OBJS += $(OUTPUT)util/session.o
340LIB_OBJS += $(OUTPUT)util/thread.o
341LIB_OBJS += $(OUTPUT)util/thread_map.o
342LIB_OBJS += $(OUTPUT)util/trace-event-parse.o
343LIB_OBJS += $(OUTPUT)util/parse-events-flex.o
344LIB_OBJS += $(OUTPUT)util/parse-events-bison.o
345LIB_OBJS += $(OUTPUT)util/pmu-flex.o
346LIB_OBJS += $(OUTPUT)util/pmu-bison.o
347LIB_OBJS += $(OUTPUT)util/trace-event-read.o
348LIB_OBJS += $(OUTPUT)util/trace-event-info.o
349LIB_OBJS += $(OUTPUT)util/trace-event-scripting.o
350LIB_OBJS += $(OUTPUT)util/svghelper.o
351LIB_OBJS += $(OUTPUT)util/sort.o
352LIB_OBJS += $(OUTPUT)util/hist.o
353LIB_OBJS += $(OUTPUT)util/probe-event.o
354LIB_OBJS += $(OUTPUT)util/util.o
355LIB_OBJS += $(OUTPUT)util/xyarray.o
356LIB_OBJS += $(OUTPUT)util/cpumap.o
357LIB_OBJS += $(OUTPUT)util/cgroup.o
358LIB_OBJS += $(OUTPUT)util/target.o
359LIB_OBJS += $(OUTPUT)util/rblist.o
360LIB_OBJS += $(OUTPUT)util/intlist.o
361LIB_OBJS += $(OUTPUT)util/vdso.o
362LIB_OBJS += $(OUTPUT)util/stat.o
363LIB_OBJS += $(OUTPUT)util/record.o
364
365LIB_OBJS += $(OUTPUT)ui/setup.o
366LIB_OBJS += $(OUTPUT)ui/helpline.o
367LIB_OBJS += $(OUTPUT)ui/progress.o
368LIB_OBJS += $(OUTPUT)ui/util.o
369LIB_OBJS += $(OUTPUT)ui/hist.o
370LIB_OBJS += $(OUTPUT)ui/stdio/hist.o
371
372LIB_OBJS += $(OUTPUT)arch/common.o
373
374LIB_OBJS += $(OUTPUT)tests/parse-events.o
375LIB_OBJS += $(OUTPUT)tests/dso-data.o
376LIB_OBJS += $(OUTPUT)tests/attr.o
377LIB_OBJS += $(OUTPUT)tests/vmlinux-kallsyms.o
378LIB_OBJS += $(OUTPUT)tests/open-syscall.o
379LIB_OBJS += $(OUTPUT)tests/open-syscall-all-cpus.o
380LIB_OBJS += $(OUTPUT)tests/open-syscall-tp-fields.o
381LIB_OBJS += $(OUTPUT)tests/mmap-basic.o
382LIB_OBJS += $(OUTPUT)tests/perf-record.o
383LIB_OBJS += $(OUTPUT)tests/rdpmc.o
384LIB_OBJS += $(OUTPUT)tests/evsel-roundtrip-name.o
385LIB_OBJS += $(OUTPUT)tests/evsel-tp-sched.o
386LIB_OBJS += $(OUTPUT)tests/pmu.o
387LIB_OBJS += $(OUTPUT)tests/hists_link.o
388LIB_OBJS += $(OUTPUT)tests/python-use.o
389LIB_OBJS += $(OUTPUT)tests/bp_signal.o
390LIB_OBJS += $(OUTPUT)tests/bp_signal_overflow.o
391LIB_OBJS += $(OUTPUT)tests/task-exit.o
392LIB_OBJS += $(OUTPUT)tests/sw-clock.o
393ifeq ($(ARCH),x86)
394LIB_OBJS += $(OUTPUT)tests/perf-time-to-tsc.o
395endif
396LIB_OBJS += $(OUTPUT)tests/code-reading.o
397LIB_OBJS += $(OUTPUT)tests/sample-parsing.o
398LIB_OBJS += $(OUTPUT)tests/parse-no-sample-id-all.o
399
400BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
401BUILTIN_OBJS += $(OUTPUT)builtin-bench.o
402# Benchmark modules
403BUILTIN_OBJS += $(OUTPUT)bench/sched-messaging.o
404BUILTIN_OBJS += $(OUTPUT)bench/sched-pipe.o
405ifeq ($(RAW_ARCH),x86_64)
406BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy-x86-64-asm.o
407BUILTIN_OBJS += $(OUTPUT)bench/mem-memset-x86-64-asm.o
408endif
409BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o
410BUILTIN_OBJS += $(OUTPUT)bench/mem-memset.o
411
412BUILTIN_OBJS += $(OUTPUT)builtin-diff.o
413BUILTIN_OBJS += $(OUTPUT)builtin-evlist.o
414BUILTIN_OBJS += $(OUTPUT)builtin-help.o
415BUILTIN_OBJS += $(OUTPUT)builtin-sched.o
416BUILTIN_OBJS += $(OUTPUT)builtin-buildid-list.o
417BUILTIN_OBJS += $(OUTPUT)builtin-buildid-cache.o
418BUILTIN_OBJS += $(OUTPUT)builtin-list.o
419BUILTIN_OBJS += $(OUTPUT)builtin-record.o
420BUILTIN_OBJS += $(OUTPUT)builtin-report.o
421BUILTIN_OBJS += $(OUTPUT)builtin-stat.o
422BUILTIN_OBJS += $(OUTPUT)builtin-timechart.o
423BUILTIN_OBJS += $(OUTPUT)builtin-top.o
424BUILTIN_OBJS += $(OUTPUT)builtin-script.o
425BUILTIN_OBJS += $(OUTPUT)builtin-probe.o
426BUILTIN_OBJS += $(OUTPUT)builtin-kmem.o
427BUILTIN_OBJS += $(OUTPUT)builtin-lock.o
428BUILTIN_OBJS += $(OUTPUT)builtin-kvm.o
429BUILTIN_OBJS += $(OUTPUT)builtin-inject.o
430BUILTIN_OBJS += $(OUTPUT)tests/builtin-test.o
431BUILTIN_OBJS += $(OUTPUT)builtin-mem.o
432
433PERFLIBS = $(LIB_FILE) $(LIBLK) $(LIBTRACEEVENT)
434
435# We choose to avoid "if .. else if .. else .. endif endif"
436# because maintaining the nesting to match is a pain. If
437# we had "elif" things would have been much nicer...
438
439-include arch/$(ARCH)/Makefile
440
441ifneq ($(OUTPUT),)
442 CFLAGS += -I$(OUTPUT)
443endif
444
445ifdef NO_LIBELF
446EXTLIBS := $(filter-out -lelf,$(EXTLIBS))
447
448# Remove ELF/DWARF dependent codes
449LIB_OBJS := $(filter-out $(OUTPUT)util/symbol-elf.o,$(LIB_OBJS))
450LIB_OBJS := $(filter-out $(OUTPUT)util/dwarf-aux.o,$(LIB_OBJS))
451LIB_OBJS := $(filter-out $(OUTPUT)util/probe-event.o,$(LIB_OBJS))
452LIB_OBJS := $(filter-out $(OUTPUT)util/probe-finder.o,$(LIB_OBJS))
453
454BUILTIN_OBJS := $(filter-out $(OUTPUT)builtin-probe.o,$(BUILTIN_OBJS))
455
456# Use minimal symbol handling
457LIB_OBJS += $(OUTPUT)util/symbol-minimal.o
458
459else # NO_LIBELF
460ifndef NO_DWARF
461 LIB_OBJS += $(OUTPUT)util/probe-finder.o
462 LIB_OBJS += $(OUTPUT)util/dwarf-aux.o
463endif # NO_DWARF
464endif # NO_LIBELF
465
466ifndef NO_LIBUNWIND
467 LIB_OBJS += $(OUTPUT)util/unwind.o
468endif
469LIB_OBJS += $(OUTPUT)tests/keep-tracking.o
470
471ifndef NO_LIBAUDIT
472 BUILTIN_OBJS += $(OUTPUT)builtin-trace.o
473endif
474
475ifndef NO_SLANG
476 LIB_OBJS += $(OUTPUT)ui/browser.o
477 LIB_OBJS += $(OUTPUT)ui/browsers/annotate.o
478 LIB_OBJS += $(OUTPUT)ui/browsers/hists.o
479 LIB_OBJS += $(OUTPUT)ui/browsers/map.o
480 LIB_OBJS += $(OUTPUT)ui/browsers/scripts.o
481 LIB_OBJS += $(OUTPUT)ui/tui/setup.o
482 LIB_OBJS += $(OUTPUT)ui/tui/util.o
483 LIB_OBJS += $(OUTPUT)ui/tui/helpline.o
484 LIB_OBJS += $(OUTPUT)ui/tui/progress.o
485 LIB_H += ui/browser.h
486 LIB_H += ui/browsers/map.h
487 LIB_H += ui/keysyms.h
488 LIB_H += ui/libslang.h
489endif
490
491ifndef NO_GTK2
492 LIB_OBJS += $(OUTPUT)ui/gtk/browser.o
493 LIB_OBJS += $(OUTPUT)ui/gtk/hists.o
494 LIB_OBJS += $(OUTPUT)ui/gtk/setup.o
495 LIB_OBJS += $(OUTPUT)ui/gtk/util.o
496 LIB_OBJS += $(OUTPUT)ui/gtk/helpline.o
497 LIB_OBJS += $(OUTPUT)ui/gtk/progress.o
498 LIB_OBJS += $(OUTPUT)ui/gtk/annotate.o
499endif
500
501ifndef NO_LIBPERL
502 LIB_OBJS += $(OUTPUT)util/scripting-engines/trace-event-perl.o
503 LIB_OBJS += $(OUTPUT)scripts/perl/Perf-Trace-Util/Context.o
504endif
505
506ifndef NO_LIBPYTHON
507 LIB_OBJS += $(OUTPUT)util/scripting-engines/trace-event-python.o
508 LIB_OBJS += $(OUTPUT)scripts/python/Perf-Trace-Util/Context.o
509endif
510
511ifeq ($(NO_PERF_REGS),0)
512 ifeq ($(ARCH),x86)
513 LIB_H += arch/x86/include/perf_regs.h
514 endif
515endif
516
517ifndef NO_LIBNUMA
518 BUILTIN_OBJS += $(OUTPUT)bench/numa.o
519endif
520
521ifdef ASCIIDOC8
522 export ASCIIDOC8
523endif
524
525LIBS = -Wl,--whole-archive $(PERFLIBS) -Wl,--no-whole-archive -Wl,--start-group $(EXTLIBS) -Wl,--end-group
526
527export INSTALL SHELL_PATH
528
529### Build rules
530
531SHELL = $(SHELL_PATH)
532
533all: shell_compatibility_test $(ALL_PROGRAMS) $(LANG_BINDINGS) $(OTHER_PROGRAMS)
534
535please_set_SHELL_PATH_to_a_more_modern_shell:
536 @$$(:)
537
538shell_compatibility_test: please_set_SHELL_PATH_to_a_more_modern_shell
539
540strip: $(PROGRAMS) $(OUTPUT)perf
541 $(STRIP) $(STRIP_OPTS) $(PROGRAMS) $(OUTPUT)perf
542
543$(OUTPUT)perf.o: perf.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS
544 $(QUIET_CC)$(CC) -include $(OUTPUT)PERF-VERSION-FILE \
545 '-DPERF_HTML_PATH="$(htmldir_SQ)"' \
546 $(CFLAGS) -c $(filter %.c,$^) -o $@
547
548$(OUTPUT)perf: $(OUTPUT)perf.o $(BUILTIN_OBJS) $(PERFLIBS)
549 $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $(OUTPUT)perf.o \
550 $(BUILTIN_OBJS) $(LIBS) -o $@
551
552$(OUTPUT)builtin-help.o: builtin-help.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS
553 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
554 '-DPERF_HTML_PATH="$(htmldir_SQ)"' \
555 '-DPERF_MAN_PATH="$(mandir_SQ)"' \
556 '-DPERF_INFO_PATH="$(infodir_SQ)"' $<
557
558$(OUTPUT)builtin-timechart.o: builtin-timechart.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS
559 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
560 '-DPERF_HTML_PATH="$(htmldir_SQ)"' \
561 '-DPERF_MAN_PATH="$(mandir_SQ)"' \
562 '-DPERF_INFO_PATH="$(infodir_SQ)"' $<
563
564$(OUTPUT)common-cmds.h: util/generate-cmdlist.sh command-list.txt
565
566$(OUTPUT)common-cmds.h: $(wildcard Documentation/perf-*.txt)
567 $(QUIET_GEN). util/generate-cmdlist.sh > $@+ && mv $@+ $@
568
569$(SCRIPTS) : % : %.sh
570 $(QUIET_GEN)$(INSTALL) '$@.sh' '$(OUTPUT)$@'
571
572# These can record PERF_VERSION
573$(OUTPUT)perf.o perf.spec \
574 $(SCRIPTS) \
575 : $(OUTPUT)PERF-VERSION-FILE
576
577.SUFFIXES:
578.SUFFIXES: .o .c .S .s
579
580# These two need to be here so that when O= is not used they take precedence
581# over the general rule for .o
582
583$(OUTPUT)util/%-flex.o: $(OUTPUT)util/%-flex.c $(OUTPUT)PERF-CFLAGS
584 $(QUIET_CC)$(CC) -o $@ -c -Iutil/ $(CFLAGS) -w $<
585
586$(OUTPUT)util/%-bison.o: $(OUTPUT)util/%-bison.c $(OUTPUT)PERF-CFLAGS
587 $(QUIET_CC)$(CC) -o $@ -c -Iutil/ $(CFLAGS) -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w $<
588
589$(OUTPUT)%.o: %.c $(OUTPUT)PERF-CFLAGS
590 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $<
591$(OUTPUT)%.i: %.c $(OUTPUT)PERF-CFLAGS
592 $(QUIET_CC)$(CC) -o $@ -E $(CFLAGS) $<
593$(OUTPUT)%.s: %.c $(OUTPUT)PERF-CFLAGS
594 $(QUIET_CC)$(CC) -o $@ -S $(CFLAGS) $<
595$(OUTPUT)%.o: %.S
596 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $<
597$(OUTPUT)%.s: %.S
598 $(QUIET_CC)$(CC) -o $@ -E $(CFLAGS) $<
599
600$(OUTPUT)util/exec_cmd.o: util/exec_cmd.c $(OUTPUT)PERF-CFLAGS
601 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
602 '-DPERF_EXEC_PATH="$(perfexecdir_SQ)"' \
603 '-DPREFIX="$(prefix_SQ)"' \
604 $<
605
606$(OUTPUT)tests/attr.o: tests/attr.c $(OUTPUT)PERF-CFLAGS
607 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
608 '-DBINDIR="$(bindir_SQ)"' -DPYTHON='"$(PYTHON_WORD)"' \
609 $<
610
611$(OUTPUT)tests/python-use.o: tests/python-use.c $(OUTPUT)PERF-CFLAGS
612 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
613 -DPYTHONPATH='"$(OUTPUT)python"' \
614 -DPYTHON='"$(PYTHON_WORD)"' \
615 $<
616
617$(OUTPUT)util/config.o: util/config.c $(OUTPUT)PERF-CFLAGS
618 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
619
620$(OUTPUT)ui/browser.o: ui/browser.c $(OUTPUT)PERF-CFLAGS
621 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $<
622
623$(OUTPUT)ui/browsers/annotate.o: ui/browsers/annotate.c $(OUTPUT)PERF-CFLAGS
624 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $<
625 73
626$(OUTPUT)ui/browsers/hists.o: ui/browsers/hists.c $(OUTPUT)PERF-CFLAGS 74#
627 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $< 75# All other targets get passed through:
628 76#
629$(OUTPUT)ui/browsers/map.o: ui/browsers/map.c $(OUTPUT)PERF-CFLAGS 77%:
630 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $< 78 $(print_msg)
631 79 $(make)
632$(OUTPUT)ui/browsers/scripts.o: ui/browsers/scripts.c $(OUTPUT)PERF-CFLAGS
633 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $<
634
635$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS
636 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
637
638$(OUTPUT)util/parse-events.o: util/parse-events.c $(OUTPUT)PERF-CFLAGS
639 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-redundant-decls $<
640
641$(OUTPUT)util/scripting-engines/trace-event-perl.o: util/scripting-engines/trace-event-perl.c $(OUTPUT)PERF-CFLAGS
642 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow -Wno-undef -Wno-switch-default $<
643
644$(OUTPUT)scripts/perl/Perf-Trace-Util/Context.o: scripts/perl/Perf-Trace-Util/Context.c $(OUTPUT)PERF-CFLAGS
645 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs -Wno-undef -Wno-switch-default $<
646
647$(OUTPUT)util/scripting-engines/trace-event-python.o: util/scripting-engines/trace-event-python.c $(OUTPUT)PERF-CFLAGS
648 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow $<
649
650$(OUTPUT)scripts/python/Perf-Trace-Util/Context.o: scripts/python/Perf-Trace-Util/Context.c $(OUTPUT)PERF-CFLAGS
651 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs $<
652
653$(OUTPUT)perf-%: %.o $(PERFLIBS)
654 $(QUIET_LINK)$(CC) $(CFLAGS) -o $@ $(LDFLAGS) $(filter %.o,$^) $(LIBS)
655
656$(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H)
657$(patsubst perf-%,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h)
658
659# we compile into subdirectories. if the target directory is not the source directory, they might not exists. So
660# we depend the various files onto their directories.
661DIRECTORY_DEPS = $(LIB_OBJS) $(BUILTIN_OBJS) $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h
662$(DIRECTORY_DEPS): | $(sort $(dir $(DIRECTORY_DEPS)))
663# In the second step, we make a rule to actually create these directories
664$(sort $(dir $(DIRECTORY_DEPS))):
665 $(QUIET_MKDIR)$(MKDIR) -p $@ 2>/dev/null
666
667$(LIB_FILE): $(LIB_OBJS)
668 $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIB_OBJS)
669
670# libtraceevent.a
671$(LIBTRACEEVENT):
672 $(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(QUIET_SUBDIR1) O=$(OUTPUT) libtraceevent.a
673
674$(LIBTRACEEVENT)-clean:
675 $(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(QUIET_SUBDIR1) O=$(OUTPUT) clean
676
677# if subdir is set, we've been called from above so target has been built
678# already
679$(LIBLK):
680ifeq ($(subdir),)
681 $(QUIET_SUBDIR0)$(LK_DIR) $(QUIET_SUBDIR1) O=$(OUTPUT) liblk.a
682endif
683
684$(LIBLK)-clean:
685ifeq ($(subdir),)
686 $(QUIET_SUBDIR0)$(LK_DIR) $(QUIET_SUBDIR1) O=$(OUTPUT) clean
687endif
688
689help:
690 @echo 'Perf make targets:'
691 @echo ' doc - make *all* documentation (see below)'
692 @echo ' man - make manpage documentation (access with man <foo>)'
693 @echo ' html - make html documentation'
694 @echo ' info - make GNU info documentation (access with info <foo>)'
695 @echo ' pdf - make pdf documentation'
696 @echo ' TAGS - use etags to make tag information for source browsing'
697 @echo ' tags - use ctags to make tag information for source browsing'
698 @echo ' cscope - use cscope to make interactive browsing database'
699 @echo ''
700 @echo 'Perf install targets:'
701 @echo ' NOTE: documentation build requires asciidoc, xmlto packages to be installed'
702 @echo ' HINT: use "make prefix=<path> <install target>" to install to a particular'
703 @echo ' path like make prefix=/usr/local install install-doc'
704 @echo ' install - install compiled binaries'
705 @echo ' install-doc - install *all* documentation'
706 @echo ' install-man - install manpage documentation'
707 @echo ' install-html - install html documentation'
708 @echo ' install-info - install GNU info documentation'
709 @echo ' install-pdf - install pdf documentation'
710 @echo ''
711 @echo ' quick-install-doc - alias for quick-install-man'
712 @echo ' quick-install-man - install the documentation quickly'
713 @echo ' quick-install-html - install the html documentation quickly'
714 @echo ''
715 @echo 'Perf maintainer targets:'
716 @echo ' clean - clean all binary objects and build output'
717
718
719DOC_TARGETS := doc man html info pdf
720
721INSTALL_DOC_TARGETS := $(patsubst %,install-%,$(DOC_TARGETS)) try-install-man
722INSTALL_DOC_TARGETS += quick-install-doc quick-install-man quick-install-html
723
724# 'make doc' should call 'make -C Documentation all'
725$(DOC_TARGETS):
726 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) $(@:doc=all)
727
728TAGS:
729 $(RM) TAGS
730 $(FIND) . -name '*.[hcS]' -print | xargs etags -a
731
732tags:
733 $(RM) tags
734 $(FIND) . -name '*.[hcS]' -print | xargs ctags -a
735
736cscope:
737 $(RM) cscope*
738 $(FIND) . -name '*.[hcS]' -print | xargs cscope -b
739
740### Detect prefix changes
741TRACK_CFLAGS = $(subst ','\'',$(CFLAGS)):\
742 $(bindir_SQ):$(perfexecdir_SQ):$(template_dir_SQ):$(prefix_SQ)
743
744$(OUTPUT)PERF-CFLAGS: .FORCE-PERF-CFLAGS
745 @FLAGS='$(TRACK_CFLAGS)'; \
746 if test x"$$FLAGS" != x"`cat $(OUTPUT)PERF-CFLAGS 2>/dev/null`" ; then \
747 echo 1>&2 " * new build flags or prefix"; \
748 echo "$$FLAGS" >$(OUTPUT)PERF-CFLAGS; \
749 fi
750
751### Testing rules
752
753# GNU make supports exporting all variables by "export" without parameters.
754# However, the environment gets quite big, and some programs have problems
755# with that.
756
757check: $(OUTPUT)common-cmds.h
758 if sparse; \
759 then \
760 for i in *.c */*.c; \
761 do \
762 sparse $(CFLAGS) $(SPARSE_FLAGS) $$i || exit; \
763 done; \
764 else \
765 exit 1; \
766 fi
767
768### Installation rules
769
770install-bin: all
771 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)'
772 $(INSTALL) $(OUTPUT)perf '$(DESTDIR_SQ)$(bindir_SQ)'
773 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
774 $(INSTALL) $(OUTPUT)perf-archive -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
775ifndef NO_LIBPERL
776 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'
777 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/bin'
778 $(INSTALL) scripts/perl/Perf-Trace-Util/lib/Perf/Trace/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'
779 $(INSTALL) scripts/perl/*.pl -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl'
780 $(INSTALL) scripts/perl/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/bin'
781endif
782ifndef NO_LIBPYTHON
783 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/Perf-Trace-Util/lib/Perf/Trace'
784 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin'
785 $(INSTALL) scripts/python/Perf-Trace-Util/lib/Perf/Trace/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/Perf-Trace-Util/lib/Perf/Trace'
786 $(INSTALL) scripts/python/*.py -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python'
787 $(INSTALL) scripts/python/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin'
788endif
789 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d'
790 $(INSTALL) bash_completion '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d/perf'
791 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'
792 $(INSTALL) tests/attr.py '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'
793 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'
794 $(INSTALL) tests/attr/* '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'
795
796install: install-bin try-install-man
797
798install-python_ext:
799 $(PYTHON_WORD) util/setup.py --quiet install --root='/$(DESTDIR_SQ)'
800
801# 'make install-doc' should call 'make -C Documentation install'
802$(INSTALL_DOC_TARGETS):
803 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) $(@:-doc=)
804
805### Cleaning rules
806
807clean: $(LIBTRACEEVENT)-clean $(LIBLK)-clean
808 $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf.o $(LANG_BINDINGS)
809 $(RM) $(ALL_PROGRAMS) perf
810 $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope*
811 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean
812 $(RM) $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS
813 $(RM) $(OUTPUT)util/*-bison*
814 $(RM) $(OUTPUT)util/*-flex*
815 $(python-clean)
816
817.PHONY: all install clean strip $(LIBTRACEEVENT) $(LIBLK)
818.PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell
819.PHONY: .FORCE-PERF-VERSION-FILE TAGS tags cscope .FORCE-PERF-CFLAGS
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
new file mode 100644
index 000000000000..7fc8f179cae7
--- /dev/null
+++ b/tools/perf/Makefile.perf
@@ -0,0 +1,892 @@
1include ../scripts/Makefile.include
2
3# The default target of this Makefile is...
4all:
5
6include config/utilities.mak
7
8# Define V to have a more verbose compile.
9#
10# Define O to save output files in a separate directory.
11#
12# Define ARCH as name of target architecture if you want cross-builds.
13#
14# Define CROSS_COMPILE as prefix name of compiler if you want cross-builds.
15#
16# Define NO_LIBPERL to disable perl script extension.
17#
18# Define NO_LIBPYTHON to disable python script extension.
19#
20# Define PYTHON to point to the python binary if the default
21# `python' is not correct; for example: PYTHON=python2
22#
23# Define PYTHON_CONFIG to point to the python-config binary if
24# the default `$(PYTHON)-config' is not correct.
25#
26# Define ASCIIDOC8 if you want to format documentation with AsciiDoc 8
27#
28# Define DOCBOOK_XSL_172 if you want to format man pages with DocBook XSL v1.72.
29#
30# Define LDFLAGS=-static to build a static binary.
31#
32# Define EXTRA_CFLAGS=-m64 or EXTRA_CFLAGS=-m32 as appropriate for cross-builds.
33#
34# Define NO_DWARF if you do not want debug-info analysis feature at all.
35#
36# Define WERROR=0 to disable treating any warnings as errors.
37#
38# Define NO_NEWT if you do not want TUI support. (deprecated)
39#
40# Define NO_SLANG if you do not want TUI support.
41#
42# Define NO_GTK2 if you do not want GTK+ GUI support.
43#
44# Define NO_DEMANGLE if you do not want C++ symbol demangling.
45#
46# Define NO_LIBELF if you do not want libelf dependency (e.g. cross-builds)
47#
48# Define NO_LIBUNWIND if you do not want libunwind dependency for dwarf
49# backtrace post unwind.
50#
51# Define NO_BACKTRACE if you do not want stack backtrace debug feature
52#
53# Define NO_LIBNUMA if you do not want numa perf benchmark
54#
55# Define NO_LIBAUDIT if you do not want libaudit support
56#
57# Define NO_LIBBIONIC if you do not want bionic support
58
59ifeq ($(srctree),)
60srctree := $(patsubst %/,%,$(dir $(shell pwd)))
61srctree := $(patsubst %/,%,$(dir $(srctree)))
62#$(info Determined 'srctree' to be $(srctree))
63endif
64
65ifneq ($(objtree),)
66#$(info Determined 'objtree' to be $(objtree))
67endif
68
69ifneq ($(OUTPUT),)
70#$(info Determined 'OUTPUT' to be $(OUTPUT))
71endif
72
73$(OUTPUT)PERF-VERSION-FILE: ../../.git/HEAD
74 @$(SHELL_PATH) util/PERF-VERSION-GEN $(OUTPUT)
75 @touch $(OUTPUT)PERF-VERSION-FILE
76
77CC = $(CROSS_COMPILE)gcc
78AR = $(CROSS_COMPILE)ar
79
80RM = rm -f
81LN = ln -f
82MKDIR = mkdir
83FIND = find
84INSTALL = install
85FLEX = flex
86BISON = bison
87STRIP = strip
88
89LK_DIR = $(srctree)/tools/lib/lk/
90TRACE_EVENT_DIR = $(srctree)/tools/lib/traceevent/
91
92# include config/Makefile by default and rule out
93# non-config cases
94config := 1
95
96NON_CONFIG_TARGETS := clean TAGS tags cscope help
97
98ifdef MAKECMDGOALS
99ifeq ($(filter-out $(NON_CONFIG_TARGETS),$(MAKECMDGOALS)),)
100 config := 0
101endif
102endif
103
104ifeq ($(config),1)
105include config/Makefile
106endif
107
108export prefix bindir sharedir sysconfdir
109
110# sparse is architecture-neutral, which means that we need to tell it
111# explicitly what architecture to check for. Fix this up for yours..
112SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__
113
114# Guard against environment variables
115BUILTIN_OBJS =
116LIB_H =
117LIB_OBJS =
118GTK_OBJS =
119PYRF_OBJS =
120SCRIPT_SH =
121
122SCRIPT_SH += perf-archive.sh
123
124grep-libs = $(filter -l%,$(1))
125strip-libs = $(filter-out -l%,$(1))
126
127ifneq ($(OUTPUT),)
128 TE_PATH=$(OUTPUT)
129ifneq ($(subdir),)
130 LK_PATH=$(OUTPUT)/../lib/lk/
131else
132 LK_PATH=$(OUTPUT)
133endif
134else
135 TE_PATH=$(TRACE_EVENT_DIR)
136 LK_PATH=$(LK_DIR)
137endif
138
139LIBTRACEEVENT = $(TE_PATH)libtraceevent.a
140export LIBTRACEEVENT
141
142LIBLK = $(LK_PATH)liblk.a
143export LIBLK
144
145# python extension build directories
146PYTHON_EXTBUILD := $(OUTPUT)python_ext_build/
147PYTHON_EXTBUILD_LIB := $(PYTHON_EXTBUILD)lib/
148PYTHON_EXTBUILD_TMP := $(PYTHON_EXTBUILD)tmp/
149export PYTHON_EXTBUILD_LIB PYTHON_EXTBUILD_TMP
150
151python-clean := $(call QUIET_CLEAN, python) $(RM) -r $(PYTHON_EXTBUILD) $(OUTPUT)python/perf.so
152
153PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources)
154PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBLK)
155
156$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS)
157 $(QUIET_GEN)CFLAGS='$(CFLAGS)' $(PYTHON_WORD) util/setup.py \
158 --quiet build_ext; \
159 mkdir -p $(OUTPUT)python && \
160 cp $(PYTHON_EXTBUILD_LIB)perf.so $(OUTPUT)python/
161#
162# No Perl scripts right now:
163#
164
165SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH))
166
167#
168# Single 'perf' binary right now:
169#
170PROGRAMS += $(OUTPUT)perf
171
172# what 'all' will build and 'install' will install, in perfexecdir
173ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS)
174
175# what 'all' will build but not install in perfexecdir
176OTHER_PROGRAMS = $(OUTPUT)perf
177
178# Set paths to tools early so that they can be used for version tests.
179ifndef SHELL_PATH
180 SHELL_PATH = /bin/sh
181endif
182ifndef PERL_PATH
183 PERL_PATH = /usr/bin/perl
184endif
185
186export PERL_PATH
187
188$(OUTPUT)util/parse-events-flex.c: util/parse-events.l $(OUTPUT)util/parse-events-bison.c
189 $(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) -t util/parse-events.l > $(OUTPUT)util/parse-events-flex.c
190
191$(OUTPUT)util/parse-events-bison.c: util/parse-events.y
192 $(QUIET_BISON)$(BISON) -v util/parse-events.y -d $(PARSER_DEBUG_BISON) -o $(OUTPUT)util/parse-events-bison.c -p parse_events_
193
194$(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c
195 $(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/pmu-flex.h -t util/pmu.l > $(OUTPUT)util/pmu-flex.c
196
197$(OUTPUT)util/pmu-bison.c: util/pmu.y
198 $(QUIET_BISON)$(BISON) -v util/pmu.y -d -o $(OUTPUT)util/pmu-bison.c -p perf_pmu_
199
200$(OUTPUT)util/parse-events.o: $(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-bison.c
201$(OUTPUT)util/pmu.o: $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-bison.c
202
203LIB_FILE=$(OUTPUT)libperf.a
204
205LIB_H += ../../include/uapi/linux/perf_event.h
206LIB_H += ../../include/linux/rbtree.h
207LIB_H += ../../include/linux/list.h
208LIB_H += ../../include/uapi/linux/const.h
209LIB_H += ../../include/linux/hash.h
210LIB_H += ../../include/linux/stringify.h
211LIB_H += util/include/linux/bitmap.h
212LIB_H += util/include/linux/bitops.h
213LIB_H += util/include/linux/compiler.h
214LIB_H += util/include/linux/const.h
215LIB_H += util/include/linux/ctype.h
216LIB_H += util/include/linux/kernel.h
217LIB_H += util/include/linux/list.h
218LIB_H += util/include/linux/export.h
219LIB_H += util/include/linux/magic.h
220LIB_H += util/include/linux/poison.h
221LIB_H += util/include/linux/prefetch.h
222LIB_H += util/include/linux/rbtree.h
223LIB_H += util/include/linux/rbtree_augmented.h
224LIB_H += util/include/linux/string.h
225LIB_H += util/include/linux/types.h
226LIB_H += util/include/linux/linkage.h
227LIB_H += util/include/asm/asm-offsets.h
228LIB_H += util/include/asm/bug.h
229LIB_H += util/include/asm/byteorder.h
230LIB_H += util/include/asm/hweight.h
231LIB_H += util/include/asm/swab.h
232LIB_H += util/include/asm/system.h
233LIB_H += util/include/asm/uaccess.h
234LIB_H += util/include/dwarf-regs.h
235LIB_H += util/include/asm/dwarf2.h
236LIB_H += util/include/asm/cpufeature.h
237LIB_H += util/include/asm/unistd_32.h
238LIB_H += util/include/asm/unistd_64.h
239LIB_H += perf.h
240LIB_H += util/annotate.h
241LIB_H += util/cache.h
242LIB_H += util/callchain.h
243LIB_H += util/build-id.h
244LIB_H += util/debug.h
245LIB_H += util/fs.h
246LIB_H += util/pmu.h
247LIB_H += util/event.h
248LIB_H += util/evsel.h
249LIB_H += util/evlist.h
250LIB_H += util/exec_cmd.h
251LIB_H += util/types.h
252LIB_H += util/levenshtein.h
253LIB_H += util/machine.h
254LIB_H += util/map.h
255LIB_H += util/parse-options.h
256LIB_H += util/parse-events.h
257LIB_H += util/quote.h
258LIB_H += util/util.h
259LIB_H += util/xyarray.h
260LIB_H += util/header.h
261LIB_H += util/help.h
262LIB_H += util/session.h
263LIB_H += util/strbuf.h
264LIB_H += util/strlist.h
265LIB_H += util/strfilter.h
266LIB_H += util/svghelper.h
267LIB_H += util/tool.h
268LIB_H += util/run-command.h
269LIB_H += util/sigchain.h
270LIB_H += util/dso.h
271LIB_H += util/symbol.h
272LIB_H += util/color.h
273LIB_H += util/values.h
274LIB_H += util/sort.h
275LIB_H += util/hist.h
276LIB_H += util/comm.h
277LIB_H += util/thread.h
278LIB_H += util/thread_map.h
279LIB_H += util/trace-event.h
280LIB_H += util/probe-finder.h
281LIB_H += util/dwarf-aux.h
282LIB_H += util/probe-event.h
283LIB_H += util/pstack.h
284LIB_H += util/cpumap.h
285LIB_H += util/top.h
286LIB_H += $(ARCH_INCLUDE)
287LIB_H += util/cgroup.h
288LIB_H += $(LIB_INCLUDE)traceevent/event-parse.h
289LIB_H += util/target.h
290LIB_H += util/rblist.h
291LIB_H += util/intlist.h
292LIB_H += util/perf_regs.h
293LIB_H += util/unwind.h
294LIB_H += util/vdso.h
295LIB_H += ui/helpline.h
296LIB_H += ui/progress.h
297LIB_H += ui/util.h
298LIB_H += ui/ui.h
299LIB_H += util/data.h
300
301LIB_OBJS += $(OUTPUT)util/abspath.o
302LIB_OBJS += $(OUTPUT)util/alias.o
303LIB_OBJS += $(OUTPUT)util/annotate.o
304LIB_OBJS += $(OUTPUT)util/build-id.o
305LIB_OBJS += $(OUTPUT)util/config.o
306LIB_OBJS += $(OUTPUT)util/ctype.o
307LIB_OBJS += $(OUTPUT)util/fs.o
308LIB_OBJS += $(OUTPUT)util/pmu.o
309LIB_OBJS += $(OUTPUT)util/environment.o
310LIB_OBJS += $(OUTPUT)util/event.o
311LIB_OBJS += $(OUTPUT)util/evlist.o
312LIB_OBJS += $(OUTPUT)util/evsel.o
313LIB_OBJS += $(OUTPUT)util/exec_cmd.o
314LIB_OBJS += $(OUTPUT)util/help.o
315LIB_OBJS += $(OUTPUT)util/levenshtein.o
316LIB_OBJS += $(OUTPUT)util/parse-options.o
317LIB_OBJS += $(OUTPUT)util/parse-events.o
318LIB_OBJS += $(OUTPUT)util/path.o
319LIB_OBJS += $(OUTPUT)util/rbtree.o
320LIB_OBJS += $(OUTPUT)util/bitmap.o
321LIB_OBJS += $(OUTPUT)util/hweight.o
322LIB_OBJS += $(OUTPUT)util/run-command.o
323LIB_OBJS += $(OUTPUT)util/quote.o
324LIB_OBJS += $(OUTPUT)util/strbuf.o
325LIB_OBJS += $(OUTPUT)util/string.o
326LIB_OBJS += $(OUTPUT)util/strlist.o
327LIB_OBJS += $(OUTPUT)util/strfilter.o
328LIB_OBJS += $(OUTPUT)util/top.o
329LIB_OBJS += $(OUTPUT)util/usage.o
330LIB_OBJS += $(OUTPUT)util/wrapper.o
331LIB_OBJS += $(OUTPUT)util/sigchain.o
332LIB_OBJS += $(OUTPUT)util/dso.o
333LIB_OBJS += $(OUTPUT)util/symbol.o
334LIB_OBJS += $(OUTPUT)util/symbol-elf.o
335LIB_OBJS += $(OUTPUT)util/color.o
336LIB_OBJS += $(OUTPUT)util/pager.o
337LIB_OBJS += $(OUTPUT)util/header.o
338LIB_OBJS += $(OUTPUT)util/callchain.o
339LIB_OBJS += $(OUTPUT)util/values.o
340LIB_OBJS += $(OUTPUT)util/debug.o
341LIB_OBJS += $(OUTPUT)util/machine.o
342LIB_OBJS += $(OUTPUT)util/map.o
343LIB_OBJS += $(OUTPUT)util/pstack.o
344LIB_OBJS += $(OUTPUT)util/session.o
345LIB_OBJS += $(OUTPUT)util/comm.o
346LIB_OBJS += $(OUTPUT)util/thread.o
347LIB_OBJS += $(OUTPUT)util/thread_map.o
348LIB_OBJS += $(OUTPUT)util/trace-event-parse.o
349LIB_OBJS += $(OUTPUT)util/parse-events-flex.o
350LIB_OBJS += $(OUTPUT)util/parse-events-bison.o
351LIB_OBJS += $(OUTPUT)util/pmu-flex.o
352LIB_OBJS += $(OUTPUT)util/pmu-bison.o
353LIB_OBJS += $(OUTPUT)util/trace-event-read.o
354LIB_OBJS += $(OUTPUT)util/trace-event-info.o
355LIB_OBJS += $(OUTPUT)util/trace-event-scripting.o
356LIB_OBJS += $(OUTPUT)util/svghelper.o
357LIB_OBJS += $(OUTPUT)util/sort.o
358LIB_OBJS += $(OUTPUT)util/hist.o
359LIB_OBJS += $(OUTPUT)util/probe-event.o
360LIB_OBJS += $(OUTPUT)util/util.o
361LIB_OBJS += $(OUTPUT)util/xyarray.o
362LIB_OBJS += $(OUTPUT)util/cpumap.o
363LIB_OBJS += $(OUTPUT)util/cgroup.o
364LIB_OBJS += $(OUTPUT)util/target.o
365LIB_OBJS += $(OUTPUT)util/rblist.o
366LIB_OBJS += $(OUTPUT)util/intlist.o
367LIB_OBJS += $(OUTPUT)util/vdso.o
368LIB_OBJS += $(OUTPUT)util/stat.o
369LIB_OBJS += $(OUTPUT)util/record.o
370LIB_OBJS += $(OUTPUT)util/srcline.o
371LIB_OBJS += $(OUTPUT)util/data.o
372
373LIB_OBJS += $(OUTPUT)ui/setup.o
374LIB_OBJS += $(OUTPUT)ui/helpline.o
375LIB_OBJS += $(OUTPUT)ui/progress.o
376LIB_OBJS += $(OUTPUT)ui/util.o
377LIB_OBJS += $(OUTPUT)ui/hist.o
378LIB_OBJS += $(OUTPUT)ui/stdio/hist.o
379
380LIB_OBJS += $(OUTPUT)arch/common.o
381
382LIB_OBJS += $(OUTPUT)tests/parse-events.o
383LIB_OBJS += $(OUTPUT)tests/dso-data.o
384LIB_OBJS += $(OUTPUT)tests/attr.o
385LIB_OBJS += $(OUTPUT)tests/vmlinux-kallsyms.o
386LIB_OBJS += $(OUTPUT)tests/open-syscall.o
387LIB_OBJS += $(OUTPUT)tests/open-syscall-all-cpus.o
388LIB_OBJS += $(OUTPUT)tests/open-syscall-tp-fields.o
389LIB_OBJS += $(OUTPUT)tests/mmap-basic.o
390LIB_OBJS += $(OUTPUT)tests/perf-record.o
391LIB_OBJS += $(OUTPUT)tests/rdpmc.o
392LIB_OBJS += $(OUTPUT)tests/evsel-roundtrip-name.o
393LIB_OBJS += $(OUTPUT)tests/evsel-tp-sched.o
394LIB_OBJS += $(OUTPUT)tests/pmu.o
395LIB_OBJS += $(OUTPUT)tests/hists_link.o
396LIB_OBJS += $(OUTPUT)tests/python-use.o
397LIB_OBJS += $(OUTPUT)tests/bp_signal.o
398LIB_OBJS += $(OUTPUT)tests/bp_signal_overflow.o
399LIB_OBJS += $(OUTPUT)tests/task-exit.o
400LIB_OBJS += $(OUTPUT)tests/sw-clock.o
401ifeq ($(ARCH),x86)
402LIB_OBJS += $(OUTPUT)tests/perf-time-to-tsc.o
403endif
404LIB_OBJS += $(OUTPUT)tests/code-reading.o
405LIB_OBJS += $(OUTPUT)tests/sample-parsing.o
406LIB_OBJS += $(OUTPUT)tests/parse-no-sample-id-all.o
407
408BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
409BUILTIN_OBJS += $(OUTPUT)builtin-bench.o
410# Benchmark modules
411BUILTIN_OBJS += $(OUTPUT)bench/sched-messaging.o
412BUILTIN_OBJS += $(OUTPUT)bench/sched-pipe.o
413ifeq ($(RAW_ARCH),x86_64)
414BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy-x86-64-asm.o
415BUILTIN_OBJS += $(OUTPUT)bench/mem-memset-x86-64-asm.o
416endif
417BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o
418BUILTIN_OBJS += $(OUTPUT)bench/mem-memset.o
419
420BUILTIN_OBJS += $(OUTPUT)builtin-diff.o
421BUILTIN_OBJS += $(OUTPUT)builtin-evlist.o
422BUILTIN_OBJS += $(OUTPUT)builtin-help.o
423BUILTIN_OBJS += $(OUTPUT)builtin-sched.o
424BUILTIN_OBJS += $(OUTPUT)builtin-buildid-list.o
425BUILTIN_OBJS += $(OUTPUT)builtin-buildid-cache.o
426BUILTIN_OBJS += $(OUTPUT)builtin-list.o
427BUILTIN_OBJS += $(OUTPUT)builtin-record.o
428BUILTIN_OBJS += $(OUTPUT)builtin-report.o
429BUILTIN_OBJS += $(OUTPUT)builtin-stat.o
430BUILTIN_OBJS += $(OUTPUT)builtin-timechart.o
431BUILTIN_OBJS += $(OUTPUT)builtin-top.o
432BUILTIN_OBJS += $(OUTPUT)builtin-script.o
433BUILTIN_OBJS += $(OUTPUT)builtin-probe.o
434BUILTIN_OBJS += $(OUTPUT)builtin-kmem.o
435BUILTIN_OBJS += $(OUTPUT)builtin-lock.o
436BUILTIN_OBJS += $(OUTPUT)builtin-kvm.o
437BUILTIN_OBJS += $(OUTPUT)builtin-inject.o
438BUILTIN_OBJS += $(OUTPUT)tests/builtin-test.o
439BUILTIN_OBJS += $(OUTPUT)builtin-mem.o
440
441PERFLIBS = $(LIB_FILE) $(LIBLK) $(LIBTRACEEVENT)
442
443# We choose to avoid "if .. else if .. else .. endif endif"
444# because maintaining the nesting to match is a pain. If
445# we had "elif" things would have been much nicer...
446
447-include arch/$(ARCH)/Makefile
448
449ifneq ($(OUTPUT),)
450 CFLAGS += -I$(OUTPUT)
451endif
452
453ifdef NO_LIBELF
454EXTLIBS := $(filter-out -lelf,$(EXTLIBS))
455
456# Remove ELF/DWARF dependent codes
457LIB_OBJS := $(filter-out $(OUTPUT)util/symbol-elf.o,$(LIB_OBJS))
458LIB_OBJS := $(filter-out $(OUTPUT)util/dwarf-aux.o,$(LIB_OBJS))
459LIB_OBJS := $(filter-out $(OUTPUT)util/probe-event.o,$(LIB_OBJS))
460LIB_OBJS := $(filter-out $(OUTPUT)util/probe-finder.o,$(LIB_OBJS))
461
462BUILTIN_OBJS := $(filter-out $(OUTPUT)builtin-probe.o,$(BUILTIN_OBJS))
463
464# Use minimal symbol handling
465LIB_OBJS += $(OUTPUT)util/symbol-minimal.o
466
467else # NO_LIBELF
468ifndef NO_DWARF
469 LIB_OBJS += $(OUTPUT)util/probe-finder.o
470 LIB_OBJS += $(OUTPUT)util/dwarf-aux.o
471endif # NO_DWARF
472endif # NO_LIBELF
473
474ifndef NO_LIBUNWIND
475 LIB_OBJS += $(OUTPUT)util/unwind.o
476endif
477LIB_OBJS += $(OUTPUT)tests/keep-tracking.o
478
479ifndef NO_LIBAUDIT
480 BUILTIN_OBJS += $(OUTPUT)builtin-trace.o
481endif
482
483ifndef NO_SLANG
484 LIB_OBJS += $(OUTPUT)ui/browser.o
485 LIB_OBJS += $(OUTPUT)ui/browsers/annotate.o
486 LIB_OBJS += $(OUTPUT)ui/browsers/hists.o
487 LIB_OBJS += $(OUTPUT)ui/browsers/map.o
488 LIB_OBJS += $(OUTPUT)ui/browsers/scripts.o
489 LIB_OBJS += $(OUTPUT)ui/tui/setup.o
490 LIB_OBJS += $(OUTPUT)ui/tui/util.o
491 LIB_OBJS += $(OUTPUT)ui/tui/helpline.o
492 LIB_OBJS += $(OUTPUT)ui/tui/progress.o
493 LIB_H += ui/tui/tui.h
494 LIB_H += ui/browser.h
495 LIB_H += ui/browsers/map.h
496 LIB_H += ui/keysyms.h
497 LIB_H += ui/libslang.h
498endif
499
500ifndef NO_GTK2
501 ALL_PROGRAMS += $(OUTPUT)libperf-gtk.so
502
503 GTK_OBJS += $(OUTPUT)ui/gtk/browser.o
504 GTK_OBJS += $(OUTPUT)ui/gtk/hists.o
505 GTK_OBJS += $(OUTPUT)ui/gtk/setup.o
506 GTK_OBJS += $(OUTPUT)ui/gtk/util.o
507 GTK_OBJS += $(OUTPUT)ui/gtk/helpline.o
508 GTK_OBJS += $(OUTPUT)ui/gtk/progress.o
509 GTK_OBJS += $(OUTPUT)ui/gtk/annotate.o
510
511install-gtk: $(OUTPUT)libperf-gtk.so
512 $(call QUIET_INSTALL, 'GTK UI') \
513 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(libdir_SQ)'; \
514 $(INSTALL) $(OUTPUT)libperf-gtk.so '$(DESTDIR_SQ)$(libdir_SQ)'
515endif
516
517ifndef NO_LIBPERL
518 LIB_OBJS += $(OUTPUT)util/scripting-engines/trace-event-perl.o
519 LIB_OBJS += $(OUTPUT)scripts/perl/Perf-Trace-Util/Context.o
520endif
521
522ifndef NO_LIBPYTHON
523 LIB_OBJS += $(OUTPUT)util/scripting-engines/trace-event-python.o
524 LIB_OBJS += $(OUTPUT)scripts/python/Perf-Trace-Util/Context.o
525endif
526
527ifeq ($(NO_PERF_REGS),0)
528 ifeq ($(ARCH),x86)
529 LIB_H += arch/x86/include/perf_regs.h
530 endif
531endif
532
533ifndef NO_LIBNUMA
534 BUILTIN_OBJS += $(OUTPUT)bench/numa.o
535endif
536
537ifdef ASCIIDOC8
538 export ASCIIDOC8
539endif
540
541LIBS = -Wl,--whole-archive $(PERFLIBS) -Wl,--no-whole-archive -Wl,--start-group $(EXTLIBS) -Wl,--end-group
542
543export INSTALL SHELL_PATH
544
545### Build rules
546
547SHELL = $(SHELL_PATH)
548
549all: shell_compatibility_test $(ALL_PROGRAMS) $(LANG_BINDINGS) $(OTHER_PROGRAMS)
550
551please_set_SHELL_PATH_to_a_more_modern_shell:
552 @$$(:)
553
554shell_compatibility_test: please_set_SHELL_PATH_to_a_more_modern_shell
555
556strip: $(PROGRAMS) $(OUTPUT)perf
557 $(STRIP) $(STRIP_OPTS) $(PROGRAMS) $(OUTPUT)perf
558
559$(OUTPUT)perf.o: perf.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS
560 $(QUIET_CC)$(CC) -include $(OUTPUT)PERF-VERSION-FILE \
561 '-DPERF_HTML_PATH="$(htmldir_SQ)"' \
562 $(CFLAGS) -c $(filter %.c,$^) -o $@
563
564$(OUTPUT)perf: $(OUTPUT)perf.o $(BUILTIN_OBJS) $(PERFLIBS)
565 $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $(OUTPUT)perf.o \
566 $(BUILTIN_OBJS) $(LIBS) -o $@
567
568$(GTK_OBJS): $(OUTPUT)%.o: %.c $(LIB_H)
569 $(QUIET_CC)$(CC) -o $@ -c -fPIC $(CFLAGS) $(GTK_CFLAGS) $<
570
571$(OUTPUT)libperf-gtk.so: $(GTK_OBJS) $(PERFLIBS)
572 $(QUIET_LINK)$(CC) -o $@ -shared $(ALL_LDFLAGS) $(filter %.o,$^) $(GTK_LIBS)
573
574$(OUTPUT)builtin-help.o: builtin-help.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS
575 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
576 '-DPERF_HTML_PATH="$(htmldir_SQ)"' \
577 '-DPERF_MAN_PATH="$(mandir_SQ)"' \
578 '-DPERF_INFO_PATH="$(infodir_SQ)"' $<
579
580$(OUTPUT)builtin-timechart.o: builtin-timechart.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS
581 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
582 '-DPERF_HTML_PATH="$(htmldir_SQ)"' \
583 '-DPERF_MAN_PATH="$(mandir_SQ)"' \
584 '-DPERF_INFO_PATH="$(infodir_SQ)"' $<
585
586$(OUTPUT)common-cmds.h: util/generate-cmdlist.sh command-list.txt
587
588$(OUTPUT)common-cmds.h: $(wildcard Documentation/perf-*.txt)
589 $(QUIET_GEN). util/generate-cmdlist.sh > $@+ && mv $@+ $@
590
591$(SCRIPTS) : % : %.sh
592 $(QUIET_GEN)$(INSTALL) '$@.sh' '$(OUTPUT)$@'
593
594# These can record PERF_VERSION
595$(OUTPUT)perf.o perf.spec \
596 $(SCRIPTS) \
597 : $(OUTPUT)PERF-VERSION-FILE
598
599.SUFFIXES:
600
601#
602# If a target does not match any of the later rules then prefix it by $(OUTPUT)
603# This makes targets like 'make O=/tmp/perf perf.o' work in a natural way.
604#
605ifneq ($(OUTPUT),)
606%.o: $(OUTPUT)%.o
607 @echo " # Redirected target $@ => $(OUTPUT)$@"
608util/%.o: $(OUTPUT)util/%.o
609 @echo " # Redirected target $@ => $(OUTPUT)$@"
610bench/%.o: $(OUTPUT)bench/%.o
611 @echo " # Redirected target $@ => $(OUTPUT)$@"
612tests/%.o: $(OUTPUT)tests/%.o
613 @echo " # Redirected target $@ => $(OUTPUT)$@"
614endif
615
616# These two need to be here so that when O= is not used they take precedence
617# over the general rule for .o
618
619$(OUTPUT)util/%-flex.o: $(OUTPUT)util/%-flex.c $(OUTPUT)PERF-CFLAGS
620 $(QUIET_CC)$(CC) -o $@ -c -Iutil/ $(CFLAGS) -w $<
621
622$(OUTPUT)util/%-bison.o: $(OUTPUT)util/%-bison.c $(OUTPUT)PERF-CFLAGS
623 $(QUIET_CC)$(CC) -o $@ -c -Iutil/ $(CFLAGS) -DYYENABLE_NLS=0 -DYYLTYPE_IS_TRIVIAL=0 -w $<
624
625$(OUTPUT)%.o: %.c $(OUTPUT)PERF-CFLAGS
626 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $<
627$(OUTPUT)%.i: %.c $(OUTPUT)PERF-CFLAGS
628 $(QUIET_CC)$(CC) -o $@ -E $(CFLAGS) $<
629$(OUTPUT)%.s: %.c $(OUTPUT)PERF-CFLAGS
630 $(QUIET_CC)$(CC) -o $@ -S $(CFLAGS) $<
631$(OUTPUT)%.o: %.S
632 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $<
633$(OUTPUT)%.s: %.S
634 $(QUIET_CC)$(CC) -o $@ -E $(CFLAGS) $<
635
636$(OUTPUT)util/exec_cmd.o: util/exec_cmd.c $(OUTPUT)PERF-CFLAGS
637 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
638 '-DPERF_EXEC_PATH="$(perfexecdir_SQ)"' \
639 '-DPREFIX="$(prefix_SQ)"' \
640 $<
641
642$(OUTPUT)tests/attr.o: tests/attr.c $(OUTPUT)PERF-CFLAGS
643 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
644 '-DBINDIR="$(bindir_SQ)"' -DPYTHON='"$(PYTHON_WORD)"' \
645 $<
646
647$(OUTPUT)tests/python-use.o: tests/python-use.c $(OUTPUT)PERF-CFLAGS
648 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) \
649 -DPYTHONPATH='"$(OUTPUT)python"' \
650 -DPYTHON='"$(PYTHON_WORD)"' \
651 $<
652
653$(OUTPUT)util/config.o: util/config.c $(OUTPUT)PERF-CFLAGS
654 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
655
656$(OUTPUT)ui/setup.o: ui/setup.c $(OUTPUT)PERF-CFLAGS
657 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DLIBDIR='"$(libdir_SQ)"' $<
658
659$(OUTPUT)ui/browser.o: ui/browser.c $(OUTPUT)PERF-CFLAGS
660 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $<
661
662$(OUTPUT)ui/browsers/annotate.o: ui/browsers/annotate.c $(OUTPUT)PERF-CFLAGS
663 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $<
664
665$(OUTPUT)ui/browsers/hists.o: ui/browsers/hists.c $(OUTPUT)PERF-CFLAGS
666 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $<
667
668$(OUTPUT)ui/browsers/map.o: ui/browsers/map.c $(OUTPUT)PERF-CFLAGS
669 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $<
670
671$(OUTPUT)ui/browsers/scripts.o: ui/browsers/scripts.c $(OUTPUT)PERF-CFLAGS
672 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -DENABLE_SLFUTURE_CONST $<
673
674$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS
675 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
676
677$(OUTPUT)util/parse-events.o: util/parse-events.c $(OUTPUT)PERF-CFLAGS
678 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-redundant-decls $<
679
680$(OUTPUT)util/scripting-engines/trace-event-perl.o: util/scripting-engines/trace-event-perl.c $(OUTPUT)PERF-CFLAGS
681 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow -Wno-undef -Wno-switch-default $<
682
683$(OUTPUT)scripts/perl/Perf-Trace-Util/Context.o: scripts/perl/Perf-Trace-Util/Context.c $(OUTPUT)PERF-CFLAGS
684 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs -Wno-undef -Wno-switch-default $<
685
686$(OUTPUT)util/scripting-engines/trace-event-python.o: util/scripting-engines/trace-event-python.c $(OUTPUT)PERF-CFLAGS
687 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow $<
688
689$(OUTPUT)scripts/python/Perf-Trace-Util/Context.o: scripts/python/Perf-Trace-Util/Context.c $(OUTPUT)PERF-CFLAGS
690 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs $<
691
692$(OUTPUT)perf-%: %.o $(PERFLIBS)
693 $(QUIET_LINK)$(CC) $(CFLAGS) -o $@ $(LDFLAGS) $(filter %.o,$^) $(LIBS)
694
695$(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H)
696$(patsubst perf-%,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h)
697
698# we compile into subdirectories. if the target directory is not the source directory, they might not exists. So
699# we depend the various files onto their directories.
700DIRECTORY_DEPS = $(LIB_OBJS) $(BUILTIN_OBJS) $(GTK_OBJS)
701DIRECTORY_DEPS += $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h
702$(DIRECTORY_DEPS): | $(sort $(dir $(DIRECTORY_DEPS)))
703# In the second step, we make a rule to actually create these directories
704$(sort $(dir $(DIRECTORY_DEPS))):
705 $(QUIET_MKDIR)$(MKDIR) -p $@ 2>/dev/null
706
707$(LIB_FILE): $(LIB_OBJS)
708 $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIB_OBJS)
709
710# libtraceevent.a
711TE_SOURCES = $(wildcard $(TRACE_EVENT_DIR)*.[ch])
712
713$(LIBTRACEEVENT): $(TE_SOURCES)
714 $(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(QUIET_SUBDIR1) O=$(OUTPUT) CFLAGS="-g -Wall $(EXTRA_CFLAGS)" libtraceevent.a
715
716$(LIBTRACEEVENT)-clean:
717 $(call QUIET_CLEAN, libtraceevent)
718 @$(MAKE) -C $(TRACE_EVENT_DIR) O=$(OUTPUT) clean >/dev/null
719
720LIBLK_SOURCES = $(wildcard $(LK_PATH)*.[ch])
721
722# if subdir is set, we've been called from above so target has been built
723# already
724$(LIBLK): $(LIBLK_SOURCES)
725ifeq ($(subdir),)
726 $(QUIET_SUBDIR0)$(LK_DIR) $(QUIET_SUBDIR1) O=$(OUTPUT) liblk.a
727endif
728
729$(LIBLK)-clean:
730ifeq ($(subdir),)
731 $(call QUIET_CLEAN, liblk)
732 @$(MAKE) -C $(LK_DIR) O=$(OUTPUT) clean >/dev/null
733endif
734
735help:
736 @echo 'Perf make targets:'
737 @echo ' doc - make *all* documentation (see below)'
738 @echo ' man - make manpage documentation (access with man <foo>)'
739 @echo ' html - make html documentation'
740 @echo ' info - make GNU info documentation (access with info <foo>)'
741 @echo ' pdf - make pdf documentation'
742 @echo ' TAGS - use etags to make tag information for source browsing'
743 @echo ' tags - use ctags to make tag information for source browsing'
744 @echo ' cscope - use cscope to make interactive browsing database'
745 @echo ''
746 @echo 'Perf install targets:'
747 @echo ' NOTE: documentation build requires asciidoc, xmlto packages to be installed'
748 @echo ' HINT: use "make prefix=<path> <install target>" to install to a particular'
749 @echo ' path like make prefix=/usr/local install install-doc'
750 @echo ' install - install compiled binaries'
751 @echo ' install-doc - install *all* documentation'
752 @echo ' install-man - install manpage documentation'
753 @echo ' install-html - install html documentation'
754 @echo ' install-info - install GNU info documentation'
755 @echo ' install-pdf - install pdf documentation'
756 @echo ''
757 @echo ' quick-install-doc - alias for quick-install-man'
758 @echo ' quick-install-man - install the documentation quickly'
759 @echo ' quick-install-html - install the html documentation quickly'
760 @echo ''
761 @echo 'Perf maintainer targets:'
762 @echo ' clean - clean all binary objects and build output'
763
764
765DOC_TARGETS := doc man html info pdf
766
767INSTALL_DOC_TARGETS := $(patsubst %,install-%,$(DOC_TARGETS)) try-install-man
768INSTALL_DOC_TARGETS += quick-install-doc quick-install-man quick-install-html
769
770# 'make doc' should call 'make -C Documentation all'
771$(DOC_TARGETS):
772 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) $(@:doc=all)
773
774TAGS:
775 $(RM) TAGS
776 $(FIND) . -name '*.[hcS]' -print | xargs etags -a
777
778tags:
779 $(RM) tags
780 $(FIND) . -name '*.[hcS]' -print | xargs ctags -a
781
782cscope:
783 $(RM) cscope*
784 $(FIND) . -name '*.[hcS]' -print | xargs cscope -b
785
786### Detect prefix changes
787TRACK_CFLAGS = $(subst ','\'',$(CFLAGS)):\
788 $(bindir_SQ):$(perfexecdir_SQ):$(template_dir_SQ):$(prefix_SQ)
789
790$(OUTPUT)PERF-CFLAGS: .FORCE-PERF-CFLAGS
791 @FLAGS='$(TRACK_CFLAGS)'; \
792 if test x"$$FLAGS" != x"`cat $(OUTPUT)PERF-CFLAGS 2>/dev/null`" ; then \
793 echo 1>&2 " FLAGS: * new build flags or prefix"; \
794 echo "$$FLAGS" >$(OUTPUT)PERF-CFLAGS; \
795 fi
796
797### Testing rules
798
799# GNU make supports exporting all variables by "export" without parameters.
800# However, the environment gets quite big, and some programs have problems
801# with that.
802
803check: $(OUTPUT)common-cmds.h
804 if sparse; \
805 then \
806 for i in *.c */*.c; \
807 do \
808 sparse $(CFLAGS) $(SPARSE_FLAGS) $$i || exit; \
809 done; \
810 else \
811 exit 1; \
812 fi
813
814### Installation rules
815
816install-gtk:
817
818install-bin: all install-gtk
819 $(call QUIET_INSTALL, binaries) \
820 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)'; \
821 $(INSTALL) $(OUTPUT)perf '$(DESTDIR_SQ)$(bindir_SQ)'; \
822 $(LN) '$(DESTDIR_SQ)$(bindir_SQ)/perf' '$(DESTDIR_SQ)$(bindir_SQ)/trace'
823 $(call QUIET_INSTALL, libexec) \
824 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
825 $(call QUIET_INSTALL, perf-archive) \
826 $(INSTALL) $(OUTPUT)perf-archive -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
827ifndef NO_LIBPERL
828 $(call QUIET_INSTALL, perl-scripts) \
829 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'; \
830 $(INSTALL) scripts/perl/Perf-Trace-Util/lib/Perf/Trace/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'; \
831 $(INSTALL) scripts/perl/*.pl -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl'; \
832 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/bin'; \
833 $(INSTALL) scripts/perl/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/bin'
834endif
835ifndef NO_LIBPYTHON
836 $(call QUIET_INSTALL, python-scripts) \
837 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/Perf-Trace-Util/lib/Perf/Trace'; \
838 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin'; \
839 $(INSTALL) scripts/python/Perf-Trace-Util/lib/Perf/Trace/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/Perf-Trace-Util/lib/Perf/Trace'; \
840 $(INSTALL) scripts/python/*.py -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python'; \
841 $(INSTALL) scripts/python/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin'
842endif
843 $(call QUIET_INSTALL, bash_completion-script) \
844 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d'; \
845 $(INSTALL) bash_completion '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d/perf'
846 $(call QUIET_INSTALL, tests) \
847 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'; \
848 $(INSTALL) tests/attr.py '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'; \
849 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'; \
850 $(INSTALL) tests/attr/* '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'
851
852install: install-bin try-install-man
853
854install-python_ext:
855 $(PYTHON_WORD) util/setup.py --quiet install --root='/$(DESTDIR_SQ)'
856
857# 'make install-doc' should call 'make -C Documentation install'
858$(INSTALL_DOC_TARGETS):
859 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) $(@:-doc=)
860
861### Cleaning rules
862
863#
864# This is here, not in config/Makefile, because config/Makefile does
865# not get included for the clean target:
866#
867config-clean:
868 $(call QUIET_CLEAN, config)
869 @$(MAKE) -C config/feature-checks clean >/dev/null
870
871clean: $(LIBTRACEEVENT)-clean $(LIBLK)-clean config-clean
872 $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf.o $(LANG_BINDINGS) $(GTK_OBJS)
873 $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf
874 $(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)util/*-bison* $(OUTPUT)util/*-flex*
875 $(call QUIET_CLEAN, Documentation)
876 @$(MAKE) -C Documentation O=$(OUTPUT) clean >/dev/null
877 $(python-clean)
878
879#
880# Trick: if ../../.git does not exist - we are building out of tree for example,
881# then force version regeneration:
882#
883ifeq ($(wildcard ../../.git/HEAD),)
884 GIT-HEAD-PHONY = ../../.git/HEAD
885else
886 GIT-HEAD-PHONY =
887endif
888
889.PHONY: all install clean config-clean strip install-gtk
890.PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell
891.PHONY: $(GIT-HEAD-PHONY) TAGS tags cscope .FORCE-PERF-CFLAGS
892
diff --git a/tools/perf/arch/x86/include/perf_regs.h b/tools/perf/arch/x86/include/perf_regs.h
index 7fcdcdbee917..e84ca76aae77 100644
--- a/tools/perf/arch/x86/include/perf_regs.h
+++ b/tools/perf/arch/x86/include/perf_regs.h
@@ -5,7 +5,7 @@
5#include "../../util/types.h" 5#include "../../util/types.h"
6#include <asm/perf_regs.h> 6#include <asm/perf_regs.h>
7 7
8#ifndef ARCH_X86_64 8#ifndef HAVE_ARCH_X86_64_SUPPORT
9#define PERF_REGS_MASK ((1ULL << PERF_REG_X86_32_MAX) - 1) 9#define PERF_REGS_MASK ((1ULL << PERF_REG_X86_32_MAX) - 1)
10#else 10#else
11#define REG_NOSUPPORT ((1ULL << PERF_REG_X86_DS) | \ 11#define REG_NOSUPPORT ((1ULL << PERF_REG_X86_DS) | \
@@ -52,7 +52,7 @@ static inline const char *perf_reg_name(int id)
52 return "FS"; 52 return "FS";
53 case PERF_REG_X86_GS: 53 case PERF_REG_X86_GS:
54 return "GS"; 54 return "GS";
55#ifdef ARCH_X86_64 55#ifdef HAVE_ARCH_X86_64_SUPPORT
56 case PERF_REG_X86_R8: 56 case PERF_REG_X86_R8:
57 return "R8"; 57 return "R8";
58 case PERF_REG_X86_R9: 58 case PERF_REG_X86_R9:
@@ -69,7 +69,7 @@ static inline const char *perf_reg_name(int id)
69 return "R14"; 69 return "R14";
70 case PERF_REG_X86_R15: 70 case PERF_REG_X86_R15:
71 return "R15"; 71 return "R15";
72#endif /* ARCH_X86_64 */ 72#endif /* HAVE_ARCH_X86_64_SUPPORT */
73 default: 73 default:
74 return NULL; 74 return NULL;
75 } 75 }
diff --git a/tools/perf/arch/x86/util/unwind.c b/tools/perf/arch/x86/util/unwind.c
index 78d956eff96f..456a88cf5b37 100644
--- a/tools/perf/arch/x86/util/unwind.c
+++ b/tools/perf/arch/x86/util/unwind.c
@@ -4,7 +4,7 @@
4#include "perf_regs.h" 4#include "perf_regs.h"
5#include "../../util/unwind.h" 5#include "../../util/unwind.h"
6 6
7#ifdef ARCH_X86_64 7#ifdef HAVE_ARCH_X86_64_SUPPORT
8int unwind__arch_reg_id(int regnum) 8int unwind__arch_reg_id(int regnum)
9{ 9{
10 int id; 10 int id;
@@ -108,4 +108,4 @@ int unwind__arch_reg_id(int regnum)
108 108
109 return id; 109 return id;
110} 110}
111#endif /* ARCH_X86_64 */ 111#endif /* HAVE_ARCH_X86_64_SUPPORT */
diff --git a/tools/perf/bash_completion b/tools/perf/bash_completion
index 56e6a12aab59..62e157db2e2b 100644
--- a/tools/perf/bash_completion
+++ b/tools/perf/bash_completion
@@ -1,17 +1,87 @@
1# perf completion 1# perf completion
2 2
3function_exists() 3# Taken from git.git's completion script.
4__my_reassemble_comp_words_by_ref()
4{ 5{
5 declare -F $1 > /dev/null 6 local exclude i j first
6 return $? 7 # Which word separators to exclude?
8 exclude="${1//[^$COMP_WORDBREAKS]}"
9 cword_=$COMP_CWORD
10 if [ -z "$exclude" ]; then
11 words_=("${COMP_WORDS[@]}")
12 return
13 fi
14 # List of word completion separators has shrunk;
15 # re-assemble words to complete.
16 for ((i=0, j=0; i < ${#COMP_WORDS[@]}; i++, j++)); do
17 # Append each nonempty word consisting of just
18 # word separator characters to the current word.
19 first=t
20 while
21 [ $i -gt 0 ] &&
22 [ -n "${COMP_WORDS[$i]}" ] &&
23 # word consists of excluded word separators
24 [ "${COMP_WORDS[$i]//[^$exclude]}" = "${COMP_WORDS[$i]}" ]
25 do
26 # Attach to the previous token,
27 # unless the previous token is the command name.
28 if [ $j -ge 2 ] && [ -n "$first" ]; then
29 ((j--))
30 fi
31 first=
32 words_[$j]=${words_[j]}${COMP_WORDS[i]}
33 if [ $i = $COMP_CWORD ]; then
34 cword_=$j
35 fi
36 if (($i < ${#COMP_WORDS[@]} - 1)); then
37 ((i++))
38 else
39 # Done.
40 return
41 fi
42 done
43 words_[$j]=${words_[j]}${COMP_WORDS[i]}
44 if [ $i = $COMP_CWORD ]; then
45 cword_=$j
46 fi
47 done
7} 48}
8 49
9function_exists __ltrim_colon_completions || 50type _get_comp_words_by_ref &>/dev/null ||
51_get_comp_words_by_ref()
52{
53 local exclude cur_ words_ cword_
54 if [ "$1" = "-n" ]; then
55 exclude=$2
56 shift 2
57 fi
58 __my_reassemble_comp_words_by_ref "$exclude"
59 cur_=${words_[cword_]}
60 while [ $# -gt 0 ]; do
61 case "$1" in
62 cur)
63 cur=$cur_
64 ;;
65 prev)
66 prev=${words_[$cword_-1]}
67 ;;
68 words)
69 words=("${words_[@]}")
70 ;;
71 cword)
72 cword=$cword_
73 ;;
74 esac
75 shift
76 done
77}
78
79type __ltrim_colon_completions &>/dev/null ||
10__ltrim_colon_completions() 80__ltrim_colon_completions()
11{ 81{
12 if [[ "$1" == *:* && "$COMP_WORDBREAKS" == *:* ]]; then 82 if [[ "$1" == *:* && "$COMP_WORDBREAKS" == *:* ]]; then
13 # Remove colon-word prefix from COMPREPLY items 83 # Remove colon-word prefix from COMPREPLY items
14 local colon_word=${1%${1##*:}} 84 local colon_word=${1%"${1##*:}"}
15 local i=${#COMPREPLY[*]} 85 local i=${#COMPREPLY[*]}
16 while [[ $((--i)) -ge 0 ]]; do 86 while [[ $((--i)) -ge 0 ]]; do
17 COMPREPLY[$i]=${COMPREPLY[$i]#"$colon_word"} 87 COMPREPLY[$i]=${COMPREPLY[$i]#"$colon_word"}
@@ -19,23 +89,18 @@ __ltrim_colon_completions()
19 fi 89 fi
20} 90}
21 91
22have perf && 92type perf &>/dev/null &&
23_perf() 93_perf()
24{ 94{
25 local cur prev cmd 95 local cur words cword prev cmd
26 96
27 COMPREPLY=() 97 COMPREPLY=()
28 if function_exists _get_comp_words_by_ref; then 98 _get_comp_words_by_ref -n =: cur words cword prev
29 _get_comp_words_by_ref -n : cur prev
30 else
31 cur=$(_get_cword :)
32 prev=${COMP_WORDS[COMP_CWORD-1]}
33 fi
34 99
35 cmd=${COMP_WORDS[0]} 100 cmd=${words[0]}
36 101
37 # List perf subcommands or long options 102 # List perf subcommands or long options
38 if [ $COMP_CWORD -eq 1 ]; then 103 if [ $cword -eq 1 ]; then
39 if [[ $cur == --* ]]; then 104 if [[ $cur == --* ]]; then
40 COMPREPLY=( $( compgen -W '--help --version \ 105 COMPREPLY=( $( compgen -W '--help --version \
41 --exec-path --html-path --paginate --no-pager \ 106 --exec-path --html-path --paginate --no-pager \
@@ -45,18 +110,17 @@ _perf()
45 COMPREPLY=( $( compgen -W '$cmds' -- "$cur" ) ) 110 COMPREPLY=( $( compgen -W '$cmds' -- "$cur" ) )
46 fi 111 fi
47 # List possible events for -e option 112 # List possible events for -e option
48 elif [[ $prev == "-e" && "${COMP_WORDS[1]}" == @(record|stat|top) ]]; then 113 elif [[ $prev == "-e" && "${words[1]}" == @(record|stat|top) ]]; then
49 evts=$($cmd list --raw-dump) 114 evts=$($cmd list --raw-dump)
50 COMPREPLY=( $( compgen -W '$evts' -- "$cur" ) ) 115 COMPREPLY=( $( compgen -W '$evts' -- "$cur" ) )
51 __ltrim_colon_completions $cur 116 __ltrim_colon_completions $cur
52 # List long option names 117 # List long option names
53 elif [[ $cur == --* ]]; then 118 elif [[ $cur == --* ]]; then
54 subcmd=${COMP_WORDS[1]} 119 subcmd=${words[1]}
55 opts=$($cmd $subcmd --list-opts) 120 opts=$($cmd $subcmd --list-opts)
56 COMPREPLY=( $( compgen -W '$opts' -- "$cur" ) ) 121 COMPREPLY=( $( compgen -W '$opts' -- "$cur" ) )
57 # Fall down to list regular files
58 else
59 _filedir
60 fi 122 fi
61} && 123} &&
62complete -F _perf perf 124
125complete -o bashdefault -o default -o nospace -F _perf perf 2>/dev/null \
126 || complete -o default -o nospace -F _perf perf
diff --git a/tools/perf/bench/mem-memcpy-arch.h b/tools/perf/bench/mem-memcpy-arch.h
index a72e36cb5394..57b4ed871459 100644
--- a/tools/perf/bench/mem-memcpy-arch.h
+++ b/tools/perf/bench/mem-memcpy-arch.h
@@ -1,5 +1,5 @@
1 1
2#ifdef ARCH_X86_64 2#ifdef HAVE_ARCH_X86_64_SUPPORT
3 3
4#define MEMCPY_FN(fn, name, desc) \ 4#define MEMCPY_FN(fn, name, desc) \
5 extern void *fn(void *, const void *, size_t); 5 extern void *fn(void *, const void *, size_t);
diff --git a/tools/perf/bench/mem-memcpy.c b/tools/perf/bench/mem-memcpy.c
index 8cdca43016b2..5ce71d3b72cf 100644
--- a/tools/perf/bench/mem-memcpy.c
+++ b/tools/perf/bench/mem-memcpy.c
@@ -58,7 +58,7 @@ struct routine routines[] = {
58 { "default", 58 { "default",
59 "Default memcpy() provided by glibc", 59 "Default memcpy() provided by glibc",
60 memcpy }, 60 memcpy },
61#ifdef ARCH_X86_64 61#ifdef HAVE_ARCH_X86_64_SUPPORT
62 62
63#define MEMCPY_FN(fn, name, desc) { name, desc, fn }, 63#define MEMCPY_FN(fn, name, desc) { name, desc, fn },
64#include "mem-memcpy-x86-64-asm-def.h" 64#include "mem-memcpy-x86-64-asm-def.h"
diff --git a/tools/perf/bench/mem-memset-arch.h b/tools/perf/bench/mem-memset-arch.h
index a040fa77665b..633800cb0dcb 100644
--- a/tools/perf/bench/mem-memset-arch.h
+++ b/tools/perf/bench/mem-memset-arch.h
@@ -1,5 +1,5 @@
1 1
2#ifdef ARCH_X86_64 2#ifdef HAVE_ARCH_X86_64_SUPPORT
3 3
4#define MEMSET_FN(fn, name, desc) \ 4#define MEMSET_FN(fn, name, desc) \
5 extern void *fn(void *, int, size_t); 5 extern void *fn(void *, int, size_t);
diff --git a/tools/perf/bench/mem-memset.c b/tools/perf/bench/mem-memset.c
index 4a2f12081964..9af79d2b18e5 100644
--- a/tools/perf/bench/mem-memset.c
+++ b/tools/perf/bench/mem-memset.c
@@ -58,7 +58,7 @@ static const struct routine routines[] = {
58 { "default", 58 { "default",
59 "Default memset() provided by glibc", 59 "Default memset() provided by glibc",
60 memset }, 60 memset },
61#ifdef ARCH_X86_64 61#ifdef HAVE_ARCH_X86_64_SUPPORT
62 62
63#define MEMSET_FN(fn, name, desc) { name, desc, fn }, 63#define MEMSET_FN(fn, name, desc) { name, desc, fn },
64#include "mem-memset-x86-64-asm-def.h" 64#include "mem-memset-x86-64-asm-def.h"
diff --git a/tools/perf/bench/numa.c b/tools/perf/bench/numa.c
index 30d1c3225b46..d4c83c60b9b2 100644
--- a/tools/perf/bench/numa.c
+++ b/tools/perf/bench/numa.c
@@ -429,14 +429,14 @@ static int parse_cpu_list(const char *arg)
429 return 0; 429 return 0;
430} 430}
431 431
432static void parse_setup_cpu_list(void) 432static int parse_setup_cpu_list(void)
433{ 433{
434 struct thread_data *td; 434 struct thread_data *td;
435 char *str0, *str; 435 char *str0, *str;
436 int t; 436 int t;
437 437
438 if (!g->p.cpu_list_str) 438 if (!g->p.cpu_list_str)
439 return; 439 return 0;
440 440
441 dprintf("g->p.nr_tasks: %d\n", g->p.nr_tasks); 441 dprintf("g->p.nr_tasks: %d\n", g->p.nr_tasks);
442 442
@@ -500,8 +500,12 @@ static void parse_setup_cpu_list(void)
500 500
501 dprintf("CPUs: %d_%d-%d#%dx%d\n", bind_cpu_0, bind_len, bind_cpu_1, step, mul); 501 dprintf("CPUs: %d_%d-%d#%dx%d\n", bind_cpu_0, bind_len, bind_cpu_1, step, mul);
502 502
503 BUG_ON(bind_cpu_0 < 0 || bind_cpu_0 >= g->p.nr_cpus); 503 if (bind_cpu_0 >= g->p.nr_cpus || bind_cpu_1 >= g->p.nr_cpus) {
504 BUG_ON(bind_cpu_1 < 0 || bind_cpu_1 >= g->p.nr_cpus); 504 printf("\nTest not applicable, system has only %d CPUs.\n", g->p.nr_cpus);
505 return -1;
506 }
507
508 BUG_ON(bind_cpu_0 < 0 || bind_cpu_1 < 0);
505 BUG_ON(bind_cpu_0 > bind_cpu_1); 509 BUG_ON(bind_cpu_0 > bind_cpu_1);
506 510
507 for (bind_cpu = bind_cpu_0; bind_cpu <= bind_cpu_1; bind_cpu += step) { 511 for (bind_cpu = bind_cpu_0; bind_cpu <= bind_cpu_1; bind_cpu += step) {
@@ -541,6 +545,7 @@ out:
541 printf("# NOTE: %d tasks bound, %d tasks unbound\n", t, g->p.nr_tasks - t); 545 printf("# NOTE: %d tasks bound, %d tasks unbound\n", t, g->p.nr_tasks - t);
542 546
543 free(str0); 547 free(str0);
548 return 0;
544} 549}
545 550
546static int parse_cpus_opt(const struct option *opt __maybe_unused, 551static int parse_cpus_opt(const struct option *opt __maybe_unused,
@@ -561,14 +566,14 @@ static int parse_node_list(const char *arg)
561 return 0; 566 return 0;
562} 567}
563 568
564static void parse_setup_node_list(void) 569static int parse_setup_node_list(void)
565{ 570{
566 struct thread_data *td; 571 struct thread_data *td;
567 char *str0, *str; 572 char *str0, *str;
568 int t; 573 int t;
569 574
570 if (!g->p.node_list_str) 575 if (!g->p.node_list_str)
571 return; 576 return 0;
572 577
573 dprintf("g->p.nr_tasks: %d\n", g->p.nr_tasks); 578 dprintf("g->p.nr_tasks: %d\n", g->p.nr_tasks);
574 579
@@ -619,8 +624,12 @@ static void parse_setup_node_list(void)
619 624
620 dprintf("NODEs: %d-%d #%d\n", bind_node_0, bind_node_1, step); 625 dprintf("NODEs: %d-%d #%d\n", bind_node_0, bind_node_1, step);
621 626
622 BUG_ON(bind_node_0 < 0 || bind_node_0 >= g->p.nr_nodes); 627 if (bind_node_0 >= g->p.nr_nodes || bind_node_1 >= g->p.nr_nodes) {
623 BUG_ON(bind_node_1 < 0 || bind_node_1 >= g->p.nr_nodes); 628 printf("\nTest not applicable, system has only %d nodes.\n", g->p.nr_nodes);
629 return -1;
630 }
631
632 BUG_ON(bind_node_0 < 0 || bind_node_1 < 0);
624 BUG_ON(bind_node_0 > bind_node_1); 633 BUG_ON(bind_node_0 > bind_node_1);
625 634
626 for (bind_node = bind_node_0; bind_node <= bind_node_1; bind_node += step) { 635 for (bind_node = bind_node_0; bind_node <= bind_node_1; bind_node += step) {
@@ -651,6 +660,7 @@ out:
651 printf("# NOTE: %d tasks mem-bound, %d tasks unbound\n", t, g->p.nr_tasks - t); 660 printf("# NOTE: %d tasks mem-bound, %d tasks unbound\n", t, g->p.nr_tasks - t);
652 661
653 free(str0); 662 free(str0);
663 return 0;
654} 664}
655 665
656static int parse_nodes_opt(const struct option *opt __maybe_unused, 666static int parse_nodes_opt(const struct option *opt __maybe_unused,
@@ -1110,7 +1120,7 @@ static void *worker_thread(void *__tdata)
1110 /* Check whether our max runtime timed out: */ 1120 /* Check whether our max runtime timed out: */
1111 if (g->p.nr_secs) { 1121 if (g->p.nr_secs) {
1112 timersub(&stop, &start0, &diff); 1122 timersub(&stop, &start0, &diff);
1113 if (diff.tv_sec >= g->p.nr_secs) { 1123 if ((u32)diff.tv_sec >= g->p.nr_secs) {
1114 g->stop_work = true; 1124 g->stop_work = true;
1115 break; 1125 break;
1116 } 1126 }
@@ -1157,7 +1167,7 @@ static void *worker_thread(void *__tdata)
1157 runtime_ns_max += diff.tv_usec * 1000; 1167 runtime_ns_max += diff.tv_usec * 1000;
1158 1168
1159 if (details >= 0) { 1169 if (details >= 0) {
1160 printf(" #%2d / %2d: %14.2lf nsecs/op [val: %016lx]\n", 1170 printf(" #%2d / %2d: %14.2lf nsecs/op [val: %016"PRIx64"]\n",
1161 process_nr, thread_nr, runtime_ns_max / bytes_done, val); 1171 process_nr, thread_nr, runtime_ns_max / bytes_done, val);
1162 } 1172 }
1163 fflush(stdout); 1173 fflush(stdout);
@@ -1356,8 +1366,8 @@ static int init(void)
1356 init_thread_data(); 1366 init_thread_data();
1357 1367
1358 tprintf("#\n"); 1368 tprintf("#\n");
1359 parse_setup_cpu_list(); 1369 if (parse_setup_cpu_list() || parse_setup_node_list())
1360 parse_setup_node_list(); 1370 return -1;
1361 tprintf("#\n"); 1371 tprintf("#\n");
1362 1372
1363 print_summary(); 1373 print_summary();
@@ -1600,7 +1610,6 @@ static int run_bench_numa(const char *name, const char **argv)
1600 return 0; 1610 return 0;
1601 1611
1602err: 1612err:
1603 usage_with_options(numa_usage, options);
1604 return -1; 1613 return -1;
1605} 1614}
1606 1615
@@ -1701,8 +1710,7 @@ static int bench_all(void)
1701 BUG_ON(ret < 0); 1710 BUG_ON(ret < 0);
1702 1711
1703 for (i = 0; i < nr; i++) { 1712 for (i = 0; i < nr; i++) {
1704 if (run_bench_numa(tests[i][0], tests[i] + 1)) 1713 run_bench_numa(tests[i][0], tests[i] + 1);
1705 return -1;
1706 } 1714 }
1707 1715
1708 printf("\n"); 1716 printf("\n");
diff --git a/tools/perf/bench/sched-pipe.c b/tools/perf/bench/sched-pipe.c
index 69cfba8d4c6c..07a8d7646a15 100644
--- a/tools/perf/bench/sched-pipe.c
+++ b/tools/perf/bench/sched-pipe.c
@@ -7,9 +7,7 @@
7 * Based on pipe-test-1m.c by Ingo Molnar <mingo@redhat.com> 7 * Based on pipe-test-1m.c by Ingo Molnar <mingo@redhat.com>
8 * http://people.redhat.com/mingo/cfs-scheduler/tools/pipe-test-1m.c 8 * http://people.redhat.com/mingo/cfs-scheduler/tools/pipe-test-1m.c
9 * Ported to perf by Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp> 9 * Ported to perf by Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
10 *
11 */ 10 */
12
13#include "../perf.h" 11#include "../perf.h"
14#include "../util/util.h" 12#include "../util/util.h"
15#include "../util/parse-options.h" 13#include "../util/parse-options.h"
@@ -28,12 +26,24 @@
28#include <sys/time.h> 26#include <sys/time.h>
29#include <sys/types.h> 27#include <sys/types.h>
30 28
29#include <pthread.h>
30
31struct thread_data {
32 int nr;
33 int pipe_read;
34 int pipe_write;
35 pthread_t pthread;
36};
37
31#define LOOPS_DEFAULT 1000000 38#define LOOPS_DEFAULT 1000000
32static int loops = LOOPS_DEFAULT; 39static int loops = LOOPS_DEFAULT;
40
41/* Use processes by default: */
42static bool threaded;
33 43
34static const struct option options[] = { 44static const struct option options[] = {
35 OPT_INTEGER('l', "loop", &loops, 45 OPT_INTEGER('l', "loop", &loops, "Specify number of loops"),
36 "Specify number of loops"), 46 OPT_BOOLEAN('T', "threaded", &threaded, "Specify threads/process based task setup"),
37 OPT_END() 47 OPT_END()
38}; 48};
39 49
@@ -42,13 +52,37 @@ static const char * const bench_sched_pipe_usage[] = {
42 NULL 52 NULL
43}; 53};
44 54
45int bench_sched_pipe(int argc, const char **argv, 55static void *worker_thread(void *__tdata)
46 const char *prefix __maybe_unused)
47{ 56{
48 int pipe_1[2], pipe_2[2]; 57 struct thread_data *td = __tdata;
49 int m = 0, i; 58 int m = 0, i;
59 int ret;
60
61 for (i = 0; i < loops; i++) {
62 if (!td->nr) {
63 ret = read(td->pipe_read, &m, sizeof(int));
64 BUG_ON(ret != sizeof(int));
65 ret = write(td->pipe_write, &m, sizeof(int));
66 BUG_ON(ret != sizeof(int));
67 } else {
68 ret = write(td->pipe_write, &m, sizeof(int));
69 BUG_ON(ret != sizeof(int));
70 ret = read(td->pipe_read, &m, sizeof(int));
71 BUG_ON(ret != sizeof(int));
72 }
73 }
74
75 return NULL;
76}
77
78int bench_sched_pipe(int argc, const char **argv, const char *prefix __maybe_unused)
79{
80 struct thread_data threads[2], *td;
81 int pipe_1[2], pipe_2[2];
50 struct timeval start, stop, diff; 82 struct timeval start, stop, diff;
51 unsigned long long result_usec = 0; 83 unsigned long long result_usec = 0;
84 int nr_threads = 2;
85 int t;
52 86
53 /* 87 /*
54 * why does "ret" exist? 88 * why does "ret" exist?
@@ -58,43 +92,66 @@ int bench_sched_pipe(int argc, const char **argv,
58 int __maybe_unused ret, wait_stat; 92 int __maybe_unused ret, wait_stat;
59 pid_t pid, retpid __maybe_unused; 93 pid_t pid, retpid __maybe_unused;
60 94
61 argc = parse_options(argc, argv, options, 95 argc = parse_options(argc, argv, options, bench_sched_pipe_usage, 0);
62 bench_sched_pipe_usage, 0);
63 96
64 BUG_ON(pipe(pipe_1)); 97 BUG_ON(pipe(pipe_1));
65 BUG_ON(pipe(pipe_2)); 98 BUG_ON(pipe(pipe_2));
66 99
67 pid = fork();
68 assert(pid >= 0);
69
70 gettimeofday(&start, NULL); 100 gettimeofday(&start, NULL);
71 101
72 if (!pid) { 102 for (t = 0; t < nr_threads; t++) {
73 for (i = 0; i < loops; i++) { 103 td = threads + t;
74 ret = read(pipe_1[0], &m, sizeof(int)); 104
75 ret = write(pipe_2[1], &m, sizeof(int)); 105 td->nr = t;
76 } 106
77 } else { 107 if (t == 0) {
78 for (i = 0; i < loops; i++) { 108 td->pipe_read = pipe_1[0];
79 ret = write(pipe_1[1], &m, sizeof(int)); 109 td->pipe_write = pipe_2[1];
80 ret = read(pipe_2[0], &m, sizeof(int)); 110 } else {
111 td->pipe_write = pipe_1[1];
112 td->pipe_read = pipe_2[0];
81 } 113 }
82 } 114 }
83 115
84 gettimeofday(&stop, NULL);
85 timersub(&stop, &start, &diff);
86 116
87 if (pid) { 117 if (threaded) {
118
119 for (t = 0; t < nr_threads; t++) {
120 td = threads + t;
121
122 ret = pthread_create(&td->pthread, NULL, worker_thread, td);
123 BUG_ON(ret);
124 }
125
126 for (t = 0; t < nr_threads; t++) {
127 td = threads + t;
128
129 ret = pthread_join(td->pthread, NULL);
130 BUG_ON(ret);
131 }
132
133 } else {
134 pid = fork();
135 assert(pid >= 0);
136
137 if (!pid) {
138 worker_thread(threads + 0);
139 exit(0);
140 } else {
141 worker_thread(threads + 1);
142 }
143
88 retpid = waitpid(pid, &wait_stat, 0); 144 retpid = waitpid(pid, &wait_stat, 0);
89 assert((retpid == pid) && WIFEXITED(wait_stat)); 145 assert((retpid == pid) && WIFEXITED(wait_stat));
90 } else {
91 exit(0);
92 } 146 }
93 147
148 gettimeofday(&stop, NULL);
149 timersub(&stop, &start, &diff);
150
94 switch (bench_format) { 151 switch (bench_format) {
95 case BENCH_FORMAT_DEFAULT: 152 case BENCH_FORMAT_DEFAULT:
96 printf("# Executed %d pipe operations between two tasks\n\n", 153 printf("# Executed %d pipe operations between two %s\n\n",
97 loops); 154 loops, threaded ? "threads" : "processes");
98 155
99 result_usec = diff.tv_sec * 1000000; 156 result_usec = diff.tv_sec * 1000000;
100 result_usec += diff.tv_usec; 157 result_usec += diff.tv_usec;
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 5ebd0c3b71b6..4087ab19823c 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -28,8 +28,10 @@
28#include "util/hist.h" 28#include "util/hist.h"
29#include "util/session.h" 29#include "util/session.h"
30#include "util/tool.h" 30#include "util/tool.h"
31#include "util/data.h"
31#include "arch/common.h" 32#include "arch/common.h"
32 33
34#include <dlfcn.h>
33#include <linux/bitmap.h> 35#include <linux/bitmap.h>
34 36
35struct perf_annotate { 37struct perf_annotate {
@@ -63,7 +65,7 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,
63 return 0; 65 return 0;
64 } 66 }
65 67
66 he = __hists__add_entry(&evsel->hists, al, NULL, 1, 1); 68 he = __hists__add_entry(&evsel->hists, al, NULL, NULL, NULL, 1, 1, 0);
67 if (he == NULL) 69 if (he == NULL)
68 return -ENOMEM; 70 return -ENOMEM;
69 71
@@ -116,11 +118,11 @@ static int hist_entry__tty_annotate(struct hist_entry *he,
116 ann->print_line, ann->full_paths, 0, 0); 118 ann->print_line, ann->full_paths, 0, 0);
117} 119}
118 120
119static void hists__find_annotations(struct hists *self, 121static void hists__find_annotations(struct hists *hists,
120 struct perf_evsel *evsel, 122 struct perf_evsel *evsel,
121 struct perf_annotate *ann) 123 struct perf_annotate *ann)
122{ 124{
123 struct rb_node *nd = rb_first(&self->entries), *next; 125 struct rb_node *nd = rb_first(&hists->entries), *next;
124 int key = K_RIGHT; 126 int key = K_RIGHT;
125 127
126 while (nd) { 128 while (nd) {
@@ -142,8 +144,18 @@ find_next:
142 144
143 if (use_browser == 2) { 145 if (use_browser == 2) {
144 int ret; 146 int ret;
147 int (*annotate)(struct hist_entry *he,
148 struct perf_evsel *evsel,
149 struct hist_browser_timer *hbt);
150
151 annotate = dlsym(perf_gtk_handle,
152 "hist_entry__gtk_annotate");
153 if (annotate == NULL) {
154 ui__error("GTK browser not found!\n");
155 return;
156 }
145 157
146 ret = hist_entry__gtk_annotate(he, evsel, NULL); 158 ret = annotate(he, evsel, NULL);
147 if (!ret || !ann->skip_missing) 159 if (!ret || !ann->skip_missing)
148 return; 160 return;
149 161
@@ -188,9 +200,13 @@ static int __cmd_annotate(struct perf_annotate *ann)
188 struct perf_session *session; 200 struct perf_session *session;
189 struct perf_evsel *pos; 201 struct perf_evsel *pos;
190 u64 total_nr_samples; 202 u64 total_nr_samples;
203 struct perf_data_file file = {
204 .path = input_name,
205 .mode = PERF_DATA_MODE_READ,
206 .force = ann->force,
207 };
191 208
192 session = perf_session__new(input_name, O_RDONLY, 209 session = perf_session__new(&file, false, &ann->tool);
193 ann->force, false, &ann->tool);
194 if (session == NULL) 210 if (session == NULL)
195 return -ENOMEM; 211 return -ENOMEM;
196 212
@@ -231,7 +247,7 @@ static int __cmd_annotate(struct perf_annotate *ann)
231 247
232 if (nr_samples > 0) { 248 if (nr_samples > 0) {
233 total_nr_samples += nr_samples; 249 total_nr_samples += nr_samples;
234 hists__collapse_resort(hists); 250 hists__collapse_resort(hists, NULL);
235 hists__output_resort(hists); 251 hists__output_resort(hists);
236 252
237 if (symbol_conf.event_group && 253 if (symbol_conf.event_group &&
@@ -243,12 +259,21 @@ static int __cmd_annotate(struct perf_annotate *ann)
243 } 259 }
244 260
245 if (total_nr_samples == 0) { 261 if (total_nr_samples == 0) {
246 ui__error("The %s file has no samples!\n", session->filename); 262 ui__error("The %s file has no samples!\n", file.path);
247 goto out_delete; 263 goto out_delete;
248 } 264 }
249 265
250 if (use_browser == 2) 266 if (use_browser == 2) {
251 perf_gtk__show_annotations(); 267 void (*show_annotations)(void);
268
269 show_annotations = dlsym(perf_gtk_handle,
270 "perf_gtk__show_annotations");
271 if (show_annotations == NULL) {
272 ui__error("GTK browser not found!\n");
273 goto out_delete;
274 }
275 show_annotations();
276 }
252 277
253out_delete: 278out_delete:
254 /* 279 /*
diff --git a/tools/perf/builtin-bench.c b/tools/perf/builtin-bench.c
index 77298bf892b8..e47f90cc7b98 100644
--- a/tools/perf/builtin-bench.c
+++ b/tools/perf/builtin-bench.c
@@ -1,21 +1,18 @@
1/* 1/*
2 *
3 * builtin-bench.c 2 * builtin-bench.c
4 * 3 *
5 * General benchmarking subsystem provided by perf 4 * General benchmarking collections provided by perf
6 * 5 *
7 * Copyright (C) 2009, Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp> 6 * Copyright (C) 2009, Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
8 *
9 */ 7 */
10 8
11/* 9/*
10 * Available benchmark collection list:
12 * 11 *
13 * Available subsystem list: 12 * sched ... scheduler and IPC performance
14 * sched ... scheduler and IPC mechanism
15 * mem ... memory access performance 13 * mem ... memory access performance
16 * 14 * numa ... NUMA scheduling and MM performance
17 */ 15 */
18
19#include "perf.h" 16#include "perf.h"
20#include "util/util.h" 17#include "util/util.h"
21#include "util/parse-options.h" 18#include "util/parse-options.h"
@@ -25,112 +22,92 @@
25#include <stdio.h> 22#include <stdio.h>
26#include <stdlib.h> 23#include <stdlib.h>
27#include <string.h> 24#include <string.h>
25#include <sys/prctl.h>
28 26
29struct bench_suite { 27typedef int (*bench_fn_t)(int argc, const char **argv, const char *prefix);
30 const char *name; 28
31 const char *summary; 29struct bench {
32 int (*fn)(int, const char **, const char *); 30 const char *name;
31 const char *summary;
32 bench_fn_t fn;
33}; 33};
34 \ 34
35/* sentinel: easy for help */ 35#ifdef HAVE_LIBNUMA_SUPPORT
36#define suite_all { "all", "Test all benchmark suites", NULL } 36static struct bench numa_benchmarks[] = {
37 37 { "mem", "Benchmark for NUMA workloads", bench_numa },
38#ifdef LIBNUMA_SUPPORT 38 { "all", "Test all NUMA benchmarks", NULL },
39static struct bench_suite numa_suites[] = { 39 { NULL, NULL, NULL }
40 { "mem",
41 "Benchmark for NUMA workloads",
42 bench_numa },
43 suite_all,
44 { NULL,
45 NULL,
46 NULL }
47}; 40};
48#endif 41#endif
49 42
50static struct bench_suite sched_suites[] = { 43static struct bench sched_benchmarks[] = {
51 { "messaging", 44 { "messaging", "Benchmark for scheduling and IPC", bench_sched_messaging },
52 "Benchmark for scheduler and IPC mechanisms", 45 { "pipe", "Benchmark for pipe() between two processes", bench_sched_pipe },
53 bench_sched_messaging }, 46 { "all", "Test all scheduler benchmarks", NULL },
54 { "pipe", 47 { NULL, NULL, NULL }
55 "Flood of communication over pipe() between two processes",
56 bench_sched_pipe },
57 suite_all,
58 { NULL,
59 NULL,
60 NULL }
61}; 48};
62 49
63static struct bench_suite mem_suites[] = { 50static struct bench mem_benchmarks[] = {
64 { "memcpy", 51 { "memcpy", "Benchmark for memcpy()", bench_mem_memcpy },
65 "Simple memory copy in various ways", 52 { "memset", "Benchmark for memset() tests", bench_mem_memset },
66 bench_mem_memcpy }, 53 { "all", "Test all memory benchmarks", NULL },
67 { "memset", 54 { NULL, NULL, NULL }
68 "Simple memory set in various ways",
69 bench_mem_memset },
70 suite_all,
71 { NULL,
72 NULL,
73 NULL }
74}; 55};
75 56
76struct bench_subsys { 57struct collection {
77 const char *name; 58 const char *name;
78 const char *summary; 59 const char *summary;
79 struct bench_suite *suites; 60 struct bench *benchmarks;
80}; 61};
81 62
82static struct bench_subsys subsystems[] = { 63static struct collection collections[] = {
83#ifdef LIBNUMA_SUPPORT 64 { "sched", "Scheduler and IPC benchmarks", sched_benchmarks },
84 { "numa", 65 { "mem", "Memory access benchmarks", mem_benchmarks },
85 "NUMA scheduling and MM behavior", 66#ifdef HAVE_LIBNUMA_SUPPORT
86 numa_suites }, 67 { "numa", "NUMA scheduling and MM benchmarks", numa_benchmarks },
87#endif 68#endif
88 { "sched", 69 { "all", "All benchmarks", NULL },
89 "scheduler and IPC mechanism", 70 { NULL, NULL, NULL }
90 sched_suites },
91 { "mem",
92 "memory access performance",
93 mem_suites },
94 { "all", /* sentinel: easy for help */
95 "all benchmark subsystem",
96 NULL },
97 { NULL,
98 NULL,
99 NULL }
100}; 71};
101 72
102static void dump_suites(int subsys_index) 73/* Iterate over all benchmark collections: */
74#define for_each_collection(coll) \
75 for (coll = collections; coll->name; coll++)
76
77/* Iterate over all benchmarks within a collection: */
78#define for_each_bench(coll, bench) \
79 for (bench = coll->benchmarks; bench->name; bench++)
80
81static void dump_benchmarks(struct collection *coll)
103{ 82{
104 int i; 83 struct bench *bench;
105 84
106 printf("# List of available suites for %s...\n\n", 85 printf("\n # List of available benchmarks for collection '%s':\n\n", coll->name);
107 subsystems[subsys_index].name);
108 86
109 for (i = 0; subsystems[subsys_index].suites[i].name; i++) 87 for_each_bench(coll, bench)
110 printf("%14s: %s\n", 88 printf("%14s: %s\n", bench->name, bench->summary);
111 subsystems[subsys_index].suites[i].name,
112 subsystems[subsys_index].suites[i].summary);
113 89
114 printf("\n"); 90 printf("\n");
115 return;
116} 91}
117 92
118static const char *bench_format_str; 93static const char *bench_format_str;
94
95/* Output/formatting style, exported to benchmark modules: */
119int bench_format = BENCH_FORMAT_DEFAULT; 96int bench_format = BENCH_FORMAT_DEFAULT;
120 97
121static const struct option bench_options[] = { 98static const struct option bench_options[] = {
122 OPT_STRING('f', "format", &bench_format_str, "default", 99 OPT_STRING('f', "format", &bench_format_str, "default", "Specify format style"),
123 "Specify format style"),
124 OPT_END() 100 OPT_END()
125}; 101};
126 102
127static const char * const bench_usage[] = { 103static const char * const bench_usage[] = {
128 "perf bench [<common options>] <subsystem> <suite> [<options>]", 104 "perf bench [<common options>] <collection> <benchmark> [<options>]",
129 NULL 105 NULL
130}; 106};
131 107
132static void print_usage(void) 108static void print_usage(void)
133{ 109{
110 struct collection *coll;
134 int i; 111 int i;
135 112
136 printf("Usage: \n"); 113 printf("Usage: \n");
@@ -138,11 +115,10 @@ static void print_usage(void)
138 printf("\t%s\n", bench_usage[i]); 115 printf("\t%s\n", bench_usage[i]);
139 printf("\n"); 116 printf("\n");
140 117
141 printf("# List of available subsystems...\n\n"); 118 printf(" # List of all available benchmark collections:\n\n");
142 119
143 for (i = 0; subsystems[i].name; i++) 120 for_each_collection(coll)
144 printf("%14s: %s\n", 121 printf("%14s: %s\n", coll->name, coll->summary);
145 subsystems[i].name, subsystems[i].summary);
146 printf("\n"); 122 printf("\n");
147} 123}
148 124
@@ -159,44 +135,74 @@ static int bench_str2int(const char *str)
159 return BENCH_FORMAT_UNKNOWN; 135 return BENCH_FORMAT_UNKNOWN;
160} 136}
161 137
162static void all_suite(struct bench_subsys *subsys) /* FROM HERE */ 138/*
139 * Run a specific benchmark but first rename the running task's ->comm[]
140 * to something meaningful:
141 */
142static int run_bench(const char *coll_name, const char *bench_name, bench_fn_t fn,
143 int argc, const char **argv, const char *prefix)
163{ 144{
164 int i; 145 int size;
146 char *name;
147 int ret;
148
149 size = strlen(coll_name) + 1 + strlen(bench_name) + 1;
150
151 name = zalloc(size);
152 BUG_ON(!name);
153
154 scnprintf(name, size, "%s-%s", coll_name, bench_name);
155
156 prctl(PR_SET_NAME, name);
157 argv[0] = name;
158
159 ret = fn(argc, argv, prefix);
160
161 free(name);
162
163 return ret;
164}
165
166static void run_collection(struct collection *coll)
167{
168 struct bench *bench;
165 const char *argv[2]; 169 const char *argv[2];
166 struct bench_suite *suites = subsys->suites;
167 170
168 argv[1] = NULL; 171 argv[1] = NULL;
169 /* 172 /*
170 * TODO: 173 * TODO:
171 * preparing preset parameters for 174 *
175 * Preparing preset parameters for
172 * embedded, ordinary PC, HPC, etc... 176 * embedded, ordinary PC, HPC, etc...
173 * will be helpful 177 * would be helpful.
174 */ 178 */
175 for (i = 0; suites[i].fn; i++) { 179 for_each_bench(coll, bench) {
176 printf("# Running %s/%s benchmark...\n", 180 if (!bench->fn)
177 subsys->name, 181 break;
178 suites[i].name); 182 printf("# Running %s/%s benchmark...\n", coll->name, bench->name);
179 fflush(stdout); 183 fflush(stdout);
180 184
181 argv[1] = suites[i].name; 185 argv[1] = bench->name;
182 suites[i].fn(1, argv, NULL); 186 run_bench(coll->name, bench->name, bench->fn, 1, argv, NULL);
183 printf("\n"); 187 printf("\n");
184 } 188 }
185} 189}
186 190
187static void all_subsystem(void) 191static void run_all_collections(void)
188{ 192{
189 int i; 193 struct collection *coll;
190 for (i = 0; subsystems[i].suites; i++) 194
191 all_suite(&subsystems[i]); 195 for_each_collection(coll)
196 run_collection(coll);
192} 197}
193 198
194int cmd_bench(int argc, const char **argv, const char *prefix __maybe_unused) 199int cmd_bench(int argc, const char **argv, const char *prefix __maybe_unused)
195{ 200{
196 int i, j, status = 0; 201 struct collection *coll;
202 int ret = 0;
197 203
198 if (argc < 2) { 204 if (argc < 2) {
199 /* No subsystem specified. */ 205 /* No collection specified. */
200 print_usage(); 206 print_usage();
201 goto end; 207 goto end;
202 } 208 }
@@ -206,7 +212,7 @@ int cmd_bench(int argc, const char **argv, const char *prefix __maybe_unused)
206 212
207 bench_format = bench_str2int(bench_format_str); 213 bench_format = bench_str2int(bench_format_str);
208 if (bench_format == BENCH_FORMAT_UNKNOWN) { 214 if (bench_format == BENCH_FORMAT_UNKNOWN) {
209 printf("Unknown format descriptor:%s\n", bench_format_str); 215 printf("Unknown format descriptor: '%s'\n", bench_format_str);
210 goto end; 216 goto end;
211 } 217 }
212 218
@@ -216,52 +222,51 @@ int cmd_bench(int argc, const char **argv, const char *prefix __maybe_unused)
216 } 222 }
217 223
218 if (!strcmp(argv[0], "all")) { 224 if (!strcmp(argv[0], "all")) {
219 all_subsystem(); 225 run_all_collections();
220 goto end; 226 goto end;
221 } 227 }
222 228
223 for (i = 0; subsystems[i].name; i++) { 229 for_each_collection(coll) {
224 if (strcmp(subsystems[i].name, argv[0])) 230 struct bench *bench;
231
232 if (strcmp(coll->name, argv[0]))
225 continue; 233 continue;
226 234
227 if (argc < 2) { 235 if (argc < 2) {
228 /* No suite specified. */ 236 /* No bench specified. */
229 dump_suites(i); 237 dump_benchmarks(coll);
230 goto end; 238 goto end;
231 } 239 }
232 240
233 if (!strcmp(argv[1], "all")) { 241 if (!strcmp(argv[1], "all")) {
234 all_suite(&subsystems[i]); 242 run_collection(coll);
235 goto end; 243 goto end;
236 } 244 }
237 245
238 for (j = 0; subsystems[i].suites[j].name; j++) { 246 for_each_bench(coll, bench) {
239 if (strcmp(subsystems[i].suites[j].name, argv[1])) 247 if (strcmp(bench->name, argv[1]))
240 continue; 248 continue;
241 249
242 if (bench_format == BENCH_FORMAT_DEFAULT) 250 if (bench_format == BENCH_FORMAT_DEFAULT)
243 printf("# Running %s/%s benchmark...\n", 251 printf("# Running '%s/%s' benchmark:\n", coll->name, bench->name);
244 subsystems[i].name,
245 subsystems[i].suites[j].name);
246 fflush(stdout); 252 fflush(stdout);
247 status = subsystems[i].suites[j].fn(argc - 1, 253 ret = run_bench(coll->name, bench->name, bench->fn, argc-1, argv+1, prefix);
248 argv + 1, prefix);
249 goto end; 254 goto end;
250 } 255 }
251 256
252 if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) { 257 if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
253 dump_suites(i); 258 dump_benchmarks(coll);
254 goto end; 259 goto end;
255 } 260 }
256 261
257 printf("Unknown suite:%s for %s\n", argv[1], argv[0]); 262 printf("Unknown benchmark: '%s' for collection '%s'\n", argv[1], argv[0]);
258 status = 1; 263 ret = 1;
259 goto end; 264 goto end;
260 } 265 }
261 266
262 printf("Unknown subsystem:%s\n", argv[0]); 267 printf("Unknown collection: '%s'\n", argv[0]);
263 status = 1; 268 ret = 1;
264 269
265end: 270end:
266 return status; 271 return ret;
267} 272}
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c
index c96c8fa38243..cfede86161d8 100644
--- a/tools/perf/builtin-buildid-cache.c
+++ b/tools/perf/builtin-buildid-cache.c
@@ -6,6 +6,11 @@
6 * Copyright (C) 2010, Red Hat Inc. 6 * Copyright (C) 2010, Red Hat Inc.
7 * Copyright (C) 2010, Arnaldo Carvalho de Melo <acme@redhat.com> 7 * Copyright (C) 2010, Arnaldo Carvalho de Melo <acme@redhat.com>
8 */ 8 */
9#include <sys/types.h>
10#include <sys/time.h>
11#include <time.h>
12#include <dirent.h>
13#include <unistd.h>
9#include "builtin.h" 14#include "builtin.h"
10#include "perf.h" 15#include "perf.h"
11#include "util/cache.h" 16#include "util/cache.h"
@@ -17,6 +22,140 @@
17#include "util/session.h" 22#include "util/session.h"
18#include "util/symbol.h" 23#include "util/symbol.h"
19 24
25static int build_id_cache__kcore_buildid(const char *proc_dir, char *sbuildid)
26{
27 char root_dir[PATH_MAX];
28 char notes[PATH_MAX];
29 u8 build_id[BUILD_ID_SIZE];
30 char *p;
31
32 strlcpy(root_dir, proc_dir, sizeof(root_dir));
33
34 p = strrchr(root_dir, '/');
35 if (!p)
36 return -1;
37 *p = '\0';
38
39 scnprintf(notes, sizeof(notes), "%s/sys/kernel/notes", root_dir);
40
41 if (sysfs__read_build_id(notes, build_id, sizeof(build_id)))
42 return -1;
43
44 build_id__sprintf(build_id, sizeof(build_id), sbuildid);
45
46 return 0;
47}
48
49static int build_id_cache__kcore_dir(char *dir, size_t sz)
50{
51 struct timeval tv;
52 struct tm tm;
53 char dt[32];
54
55 if (gettimeofday(&tv, NULL) || !localtime_r(&tv.tv_sec, &tm))
56 return -1;
57
58 if (!strftime(dt, sizeof(dt), "%Y%m%d%H%M%S", &tm))
59 return -1;
60
61 scnprintf(dir, sz, "%s%02u", dt, (unsigned)tv.tv_usec / 10000);
62
63 return 0;
64}
65
66static int build_id_cache__kcore_existing(const char *from_dir, char *to_dir,
67 size_t to_dir_sz)
68{
69 char from[PATH_MAX];
70 char to[PATH_MAX];
71 struct dirent *dent;
72 int ret = -1;
73 DIR *d;
74
75 d = opendir(to_dir);
76 if (!d)
77 return -1;
78
79 scnprintf(from, sizeof(from), "%s/modules", from_dir);
80
81 while (1) {
82 dent = readdir(d);
83 if (!dent)
84 break;
85 if (dent->d_type != DT_DIR)
86 continue;
87 scnprintf(to, sizeof(to), "%s/%s/modules", to_dir,
88 dent->d_name);
89 if (!compare_proc_modules(from, to)) {
90 scnprintf(to, sizeof(to), "%s/%s", to_dir,
91 dent->d_name);
92 strlcpy(to_dir, to, to_dir_sz);
93 ret = 0;
94 break;
95 }
96 }
97
98 closedir(d);
99
100 return ret;
101}
102
103static int build_id_cache__add_kcore(const char *filename, const char *debugdir)
104{
105 char dir[32], sbuildid[BUILD_ID_SIZE * 2 + 1];
106 char from_dir[PATH_MAX], to_dir[PATH_MAX];
107 char *p;
108
109 strlcpy(from_dir, filename, sizeof(from_dir));
110
111 p = strrchr(from_dir, '/');
112 if (!p || strcmp(p + 1, "kcore"))
113 return -1;
114 *p = '\0';
115
116 if (build_id_cache__kcore_buildid(from_dir, sbuildid))
117 return -1;
118
119 scnprintf(to_dir, sizeof(to_dir), "%s/[kernel.kcore]/%s",
120 debugdir, sbuildid);
121
122 if (!build_id_cache__kcore_existing(from_dir, to_dir, sizeof(to_dir))) {
123 pr_debug("same kcore found in %s\n", to_dir);
124 return 0;
125 }
126
127 if (build_id_cache__kcore_dir(dir, sizeof(dir)))
128 return -1;
129
130 scnprintf(to_dir, sizeof(to_dir), "%s/[kernel.kcore]/%s/%s",
131 debugdir, sbuildid, dir);
132
133 if (mkdir_p(to_dir, 0755))
134 return -1;
135
136 if (kcore_copy(from_dir, to_dir)) {
137 /* Remove YYYYmmddHHMMSShh directory */
138 if (!rmdir(to_dir)) {
139 p = strrchr(to_dir, '/');
140 if (p)
141 *p = '\0';
142 /* Try to remove buildid directory */
143 if (!rmdir(to_dir)) {
144 p = strrchr(to_dir, '/');
145 if (p)
146 *p = '\0';
147 /* Try to remove [kernel.kcore] directory */
148 rmdir(to_dir);
149 }
150 }
151 return -1;
152 }
153
154 pr_debug("kcore added to build-id cache directory %s\n", to_dir);
155
156 return 0;
157}
158
20static int build_id_cache__add_file(const char *filename, const char *debugdir) 159static int build_id_cache__add_file(const char *filename, const char *debugdir)
21{ 160{
22 char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 161 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
@@ -82,8 +221,12 @@ static bool dso__missing_buildid_cache(struct dso *dso, int parm __maybe_unused)
82 221
83static int build_id_cache__fprintf_missing(const char *filename, bool force, FILE *fp) 222static int build_id_cache__fprintf_missing(const char *filename, bool force, FILE *fp)
84{ 223{
85 struct perf_session *session = perf_session__new(filename, O_RDONLY, 224 struct perf_data_file file = {
86 force, false, NULL); 225 .path = filename,
226 .mode = PERF_DATA_MODE_READ,
227 .force = force,
228 };
229 struct perf_session *session = perf_session__new(&file, false, NULL);
87 if (session == NULL) 230 if (session == NULL)
88 return -1; 231 return -1;
89 232
@@ -130,11 +273,14 @@ int cmd_buildid_cache(int argc, const char **argv,
130 char const *add_name_list_str = NULL, 273 char const *add_name_list_str = NULL,
131 *remove_name_list_str = NULL, 274 *remove_name_list_str = NULL,
132 *missing_filename = NULL, 275 *missing_filename = NULL,
133 *update_name_list_str = NULL; 276 *update_name_list_str = NULL,
277 *kcore_filename;
134 278
135 const struct option buildid_cache_options[] = { 279 const struct option buildid_cache_options[] = {
136 OPT_STRING('a', "add", &add_name_list_str, 280 OPT_STRING('a', "add", &add_name_list_str,
137 "file list", "file(s) to add"), 281 "file list", "file(s) to add"),
282 OPT_STRING('k', "kcore", &kcore_filename,
283 "file", "kcore file to add"),
138 OPT_STRING('r', "remove", &remove_name_list_str, "file list", 284 OPT_STRING('r', "remove", &remove_name_list_str, "file list",
139 "file(s) to remove"), 285 "file(s) to remove"),
140 OPT_STRING('M', "missing", &missing_filename, "file", 286 OPT_STRING('M', "missing", &missing_filename, "file",
@@ -217,5 +363,9 @@ int cmd_buildid_cache(int argc, const char **argv,
217 } 363 }
218 } 364 }
219 365
366 if (kcore_filename &&
367 build_id_cache__add_kcore(kcore_filename, debugdir))
368 pr_warning("Couldn't add %s\n", kcore_filename);
369
220 return ret; 370 return ret;
221} 371}
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index e74366a13218..ed3873b3e238 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -15,6 +15,7 @@
15#include "util/parse-options.h" 15#include "util/parse-options.h"
16#include "util/session.h" 16#include "util/session.h"
17#include "util/symbol.h" 17#include "util/symbol.h"
18#include "util/data.h"
18 19
19static int sysfs__fprintf_build_id(FILE *fp) 20static int sysfs__fprintf_build_id(FILE *fp)
20{ 21{
@@ -52,6 +53,11 @@ static bool dso__skip_buildid(struct dso *dso, int with_hits)
52static int perf_session__list_build_ids(bool force, bool with_hits) 53static int perf_session__list_build_ids(bool force, bool with_hits)
53{ 54{
54 struct perf_session *session; 55 struct perf_session *session;
56 struct perf_data_file file = {
57 .path = input_name,
58 .mode = PERF_DATA_MODE_READ,
59 .force = force,
60 };
55 61
56 symbol__elf_init(); 62 symbol__elf_init();
57 /* 63 /*
@@ -60,15 +66,14 @@ static int perf_session__list_build_ids(bool force, bool with_hits)
60 if (filename__fprintf_build_id(input_name, stdout)) 66 if (filename__fprintf_build_id(input_name, stdout))
61 goto out; 67 goto out;
62 68
63 session = perf_session__new(input_name, O_RDONLY, force, false, 69 session = perf_session__new(&file, false, &build_id__mark_dso_hit_ops);
64 &build_id__mark_dso_hit_ops);
65 if (session == NULL) 70 if (session == NULL)
66 return -1; 71 return -1;
67 /* 72 /*
68 * in pipe-mode, the only way to get the buildids is to parse 73 * in pipe-mode, the only way to get the buildids is to parse
69 * the record stream. Buildids are stored as RECORD_HEADER_BUILD_ID 74 * the record stream. Buildids are stored as RECORD_HEADER_BUILD_ID
70 */ 75 */
71 if (with_hits || session->fd_pipe) 76 if (with_hits || perf_data_file__is_pipe(&file))
72 perf_session__process_events(session, &build_id__mark_dso_hit_ops); 77 perf_session__process_events(session, &build_id__mark_dso_hit_ops);
73 78
74 perf_session__fprintf_dsos_buildid(session, stdout, dso__skip_buildid, with_hits); 79 perf_session__fprintf_dsos_buildid(session, stdout, dso__skip_buildid, with_hits);
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index f28799e94f2a..3b67ea2444bd 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -16,6 +16,7 @@
16#include "util/sort.h" 16#include "util/sort.h"
17#include "util/symbol.h" 17#include "util/symbol.h"
18#include "util/util.h" 18#include "util/util.h"
19#include "util/data.h"
19 20
20#include <stdlib.h> 21#include <stdlib.h>
21#include <math.h> 22#include <math.h>
@@ -42,7 +43,7 @@ struct diff_hpp_fmt {
42 43
43struct data__file { 44struct data__file {
44 struct perf_session *session; 45 struct perf_session *session;
45 const char *file; 46 struct perf_data_file file;
46 int idx; 47 int idx;
47 struct hists *hists; 48 struct hists *hists;
48 struct diff_hpp_fmt fmt[PERF_HPP_DIFF__MAX_INDEX]; 49 struct diff_hpp_fmt fmt[PERF_HPP_DIFF__MAX_INDEX];
@@ -302,11 +303,12 @@ static int formula_fprintf(struct hist_entry *he, struct hist_entry *pair,
302 return -1; 303 return -1;
303} 304}
304 305
305static int hists__add_entry(struct hists *self, 306static int hists__add_entry(struct hists *hists,
306 struct addr_location *al, u64 period, 307 struct addr_location *al, u64 period,
307 u64 weight) 308 u64 weight, u64 transaction)
308{ 309{
309 if (__hists__add_entry(self, al, NULL, period, weight) != NULL) 310 if (__hists__add_entry(hists, al, NULL, NULL, NULL, period, weight,
311 transaction) != NULL)
310 return 0; 312 return 0;
311 return -ENOMEM; 313 return -ENOMEM;
312} 314}
@@ -328,7 +330,8 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused,
328 if (al.filtered) 330 if (al.filtered)
329 return 0; 331 return 0;
330 332
331 if (hists__add_entry(&evsel->hists, &al, sample->period, sample->weight)) { 333 if (hists__add_entry(&evsel->hists, &al, sample->period,
334 sample->weight, sample->transaction)) {
332 pr_warning("problem incrementing symbol period, skipping event\n"); 335 pr_warning("problem incrementing symbol period, skipping event\n");
333 return -1; 336 return -1;
334 } 337 }
@@ -367,7 +370,7 @@ static void perf_evlist__collapse_resort(struct perf_evlist *evlist)
367 list_for_each_entry(evsel, &evlist->entries, node) { 370 list_for_each_entry(evsel, &evlist->entries, node) {
368 struct hists *hists = &evsel->hists; 371 struct hists *hists = &evsel->hists;
369 372
370 hists__collapse_resort(hists); 373 hists__collapse_resort(hists, NULL);
371 } 374 }
372} 375}
373 376
@@ -599,7 +602,7 @@ static void data__fprintf(void)
599 602
600 data__for_each_file(i, d) 603 data__for_each_file(i, d)
601 fprintf(stdout, "# [%d] %s %s\n", 604 fprintf(stdout, "# [%d] %s %s\n",
602 d->idx, d->file, 605 d->idx, d->file.path,
603 !d->idx ? "(Baseline)" : ""); 606 !d->idx ? "(Baseline)" : "");
604 607
605 fprintf(stdout, "#\n"); 608 fprintf(stdout, "#\n");
@@ -661,17 +664,16 @@ static int __cmd_diff(void)
661 int ret = -EINVAL, i; 664 int ret = -EINVAL, i;
662 665
663 data__for_each_file(i, d) { 666 data__for_each_file(i, d) {
664 d->session = perf_session__new(d->file, O_RDONLY, force, 667 d->session = perf_session__new(&d->file, false, &tool);
665 false, &tool);
666 if (!d->session) { 668 if (!d->session) {
667 pr_err("Failed to open %s\n", d->file); 669 pr_err("Failed to open %s\n", d->file.path);
668 ret = -ENOMEM; 670 ret = -ENOMEM;
669 goto out_delete; 671 goto out_delete;
670 } 672 }
671 673
672 ret = perf_session__process_events(d->session, &tool); 674 ret = perf_session__process_events(d->session, &tool);
673 if (ret) { 675 if (ret) {
674 pr_err("Failed to process %s\n", d->file); 676 pr_err("Failed to process %s\n", d->file.path);
675 goto out_delete; 677 goto out_delete;
676 } 678 }
677 679
@@ -1014,7 +1016,12 @@ static int data_init(int argc, const char **argv)
1014 return -ENOMEM; 1016 return -ENOMEM;
1015 1017
1016 data__for_each_file(i, d) { 1018 data__for_each_file(i, d) {
1017 d->file = use_default ? defaults[i] : argv[i]; 1019 struct perf_data_file *file = &d->file;
1020
1021 file->path = use_default ? defaults[i] : argv[i];
1022 file->mode = PERF_DATA_MODE_READ,
1023 file->force = force,
1024
1018 d->idx = i; 1025 d->idx = i;
1019 } 1026 }
1020 1027
diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c
index 05bd9dfe875c..20b0f12763b0 100644
--- a/tools/perf/builtin-evlist.c
+++ b/tools/perf/builtin-evlist.c
@@ -14,13 +14,18 @@
14#include "util/parse-events.h" 14#include "util/parse-events.h"
15#include "util/parse-options.h" 15#include "util/parse-options.h"
16#include "util/session.h" 16#include "util/session.h"
17#include "util/data.h"
17 18
18static int __cmd_evlist(const char *file_name, struct perf_attr_details *details) 19static int __cmd_evlist(const char *file_name, struct perf_attr_details *details)
19{ 20{
20 struct perf_session *session; 21 struct perf_session *session;
21 struct perf_evsel *pos; 22 struct perf_evsel *pos;
23 struct perf_data_file file = {
24 .path = file_name,
25 .mode = PERF_DATA_MODE_READ,
26 };
22 27
23 session = perf_session__new(file_name, O_RDONLY, 0, false, NULL); 28 session = perf_session__new(&file, 0, NULL);
24 if (session == NULL) 29 if (session == NULL)
25 return -ENOMEM; 30 return -ENOMEM;
26 31
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index afe377b2884f..6a2508589460 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -15,6 +15,7 @@
15#include "util/tool.h" 15#include "util/tool.h"
16#include "util/debug.h" 16#include "util/debug.h"
17#include "util/build-id.h" 17#include "util/build-id.h"
18#include "util/data.h"
18 19
19#include "util/parse-options.h" 20#include "util/parse-options.h"
20 21
@@ -71,12 +72,17 @@ static int perf_event__repipe_attr(struct perf_tool *tool,
71 union perf_event *event, 72 union perf_event *event,
72 struct perf_evlist **pevlist) 73 struct perf_evlist **pevlist)
73{ 74{
75 struct perf_inject *inject = container_of(tool, struct perf_inject,
76 tool);
74 int ret; 77 int ret;
75 78
76 ret = perf_event__process_attr(tool, event, pevlist); 79 ret = perf_event__process_attr(tool, event, pevlist);
77 if (ret) 80 if (ret)
78 return ret; 81 return ret;
79 82
83 if (!inject->pipe_output)
84 return 0;
85
80 return perf_event__repipe_synth(tool, event); 86 return perf_event__repipe_synth(tool, event);
81} 87}
82 88
@@ -100,8 +106,8 @@ static int perf_event__repipe_sample(struct perf_tool *tool,
100 struct perf_evsel *evsel, 106 struct perf_evsel *evsel,
101 struct machine *machine) 107 struct machine *machine)
102{ 108{
103 if (evsel->handler.func) { 109 if (evsel->handler) {
104 inject_handler f = evsel->handler.func; 110 inject_handler f = evsel->handler;
105 return f(tool, event, sample, evsel, machine); 111 return f(tool, event, sample, evsel, machine);
106 } 112 }
107 113
@@ -161,38 +167,38 @@ static int perf_event__repipe_tracing_data(struct perf_tool *tool,
161 return err; 167 return err;
162} 168}
163 169
164static int dso__read_build_id(struct dso *self) 170static int dso__read_build_id(struct dso *dso)
165{ 171{
166 if (self->has_build_id) 172 if (dso->has_build_id)
167 return 0; 173 return 0;
168 174
169 if (filename__read_build_id(self->long_name, self->build_id, 175 if (filename__read_build_id(dso->long_name, dso->build_id,
170 sizeof(self->build_id)) > 0) { 176 sizeof(dso->build_id)) > 0) {
171 self->has_build_id = true; 177 dso->has_build_id = true;
172 return 0; 178 return 0;
173 } 179 }
174 180
175 return -1; 181 return -1;
176} 182}
177 183
178static int dso__inject_build_id(struct dso *self, struct perf_tool *tool, 184static int dso__inject_build_id(struct dso *dso, struct perf_tool *tool,
179 struct machine *machine) 185 struct machine *machine)
180{ 186{
181 u16 misc = PERF_RECORD_MISC_USER; 187 u16 misc = PERF_RECORD_MISC_USER;
182 int err; 188 int err;
183 189
184 if (dso__read_build_id(self) < 0) { 190 if (dso__read_build_id(dso) < 0) {
185 pr_debug("no build_id found for %s\n", self->long_name); 191 pr_debug("no build_id found for %s\n", dso->long_name);
186 return -1; 192 return -1;
187 } 193 }
188 194
189 if (self->kernel) 195 if (dso->kernel)
190 misc = PERF_RECORD_MISC_KERNEL; 196 misc = PERF_RECORD_MISC_KERNEL;
191 197
192 err = perf_event__synthesize_build_id(tool, self, misc, perf_event__repipe, 198 err = perf_event__synthesize_build_id(tool, dso, misc, perf_event__repipe,
193 machine); 199 machine);
194 if (err) { 200 if (err) {
195 pr_err("Can't synthesize build_id event for %s\n", self->long_name); 201 pr_err("Can't synthesize build_id event for %s\n", dso->long_name);
196 return -1; 202 return -1;
197 } 203 }
198 204
@@ -231,7 +237,7 @@ static int perf_event__inject_buildid(struct perf_tool *tool,
231 * account this as unresolved. 237 * account this as unresolved.
232 */ 238 */
233 } else { 239 } else {
234#ifdef LIBELF_SUPPORT 240#ifdef HAVE_LIBELF_SUPPORT
235 pr_warning("no symbols found in %s, maybe " 241 pr_warning("no symbols found in %s, maybe "
236 "install a debug package?\n", 242 "install a debug package?\n",
237 al.map->dso->long_name); 243 al.map->dso->long_name);
@@ -345,6 +351,10 @@ static int __cmd_inject(struct perf_inject *inject)
345{ 351{
346 struct perf_session *session; 352 struct perf_session *session;
347 int ret = -EINVAL; 353 int ret = -EINVAL;
354 struct perf_data_file file = {
355 .path = inject->input_name,
356 .mode = PERF_DATA_MODE_READ,
357 };
348 358
349 signal(SIGINT, sig_handler); 359 signal(SIGINT, sig_handler);
350 360
@@ -355,7 +365,7 @@ static int __cmd_inject(struct perf_inject *inject)
355 inject->tool.tracing_data = perf_event__repipe_tracing_data; 365 inject->tool.tracing_data = perf_event__repipe_tracing_data;
356 } 366 }
357 367
358 session = perf_session__new(inject->input_name, O_RDONLY, false, true, &inject->tool); 368 session = perf_session__new(&file, true, &inject->tool);
359 if (session == NULL) 369 if (session == NULL)
360 return -ENOMEM; 370 return -ENOMEM;
361 371
@@ -373,11 +383,11 @@ static int __cmd_inject(struct perf_inject *inject)
373 if (perf_evsel__check_stype(evsel, PERF_SAMPLE_TID, "TID")) 383 if (perf_evsel__check_stype(evsel, PERF_SAMPLE_TID, "TID"))
374 return -EINVAL; 384 return -EINVAL;
375 385
376 evsel->handler.func = perf_inject__sched_switch; 386 evsel->handler = perf_inject__sched_switch;
377 } else if (!strcmp(name, "sched:sched_process_exit")) 387 } else if (!strcmp(name, "sched:sched_process_exit"))
378 evsel->handler.func = perf_inject__sched_process_exit; 388 evsel->handler = perf_inject__sched_process_exit;
379 else if (!strncmp(name, "sched:sched_stat_", 17)) 389 else if (!strncmp(name, "sched:sched_stat_", 17))
380 evsel->handler.func = perf_inject__sched_stat; 390 evsel->handler = perf_inject__sched_stat;
381 } 391 }
382 } 392 }
383 393
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index 9b5f077fee5b..929462aa4943 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -13,6 +13,7 @@
13 13
14#include "util/parse-options.h" 14#include "util/parse-options.h"
15#include "util/trace-event.h" 15#include "util/trace-event.h"
16#include "util/data.h"
16 17
17#include "util/debug.h" 18#include "util/debug.h"
18 19
@@ -314,10 +315,10 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
314 return -1; 315 return -1;
315 } 316 }
316 317
317 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->tid); 318 dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread), thread->tid);
318 319
319 if (evsel->handler.func != NULL) { 320 if (evsel->handler != NULL) {
320 tracepoint_handler f = evsel->handler.func; 321 tracepoint_handler f = evsel->handler;
321 return f(evsel, sample); 322 return f(evsel, sample);
322 } 323 }
323 324
@@ -486,8 +487,12 @@ static int __cmd_kmem(void)
486 { "kmem:kfree", perf_evsel__process_free_event, }, 487 { "kmem:kfree", perf_evsel__process_free_event, },
487 { "kmem:kmem_cache_free", perf_evsel__process_free_event, }, 488 { "kmem:kmem_cache_free", perf_evsel__process_free_event, },
488 }; 489 };
490 struct perf_data_file file = {
491 .path = input_name,
492 .mode = PERF_DATA_MODE_READ,
493 };
489 494
490 session = perf_session__new(input_name, O_RDONLY, 0, false, &perf_kmem); 495 session = perf_session__new(&file, false, &perf_kmem);
491 if (session == NULL) 496 if (session == NULL)
492 return -ENOMEM; 497 return -ENOMEM;
493 498
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index fbc2888d6495..cd9f92078aba 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -17,9 +17,12 @@
17#include "util/tool.h" 17#include "util/tool.h"
18#include "util/stat.h" 18#include "util/stat.h"
19#include "util/top.h" 19#include "util/top.h"
20#include "util/data.h"
20 21
21#include <sys/prctl.h> 22#include <sys/prctl.h>
23#ifdef HAVE_TIMERFD_SUPPORT
22#include <sys/timerfd.h> 24#include <sys/timerfd.h>
25#endif
23 26
24#include <termios.h> 27#include <termios.h>
25#include <semaphore.h> 28#include <semaphore.h>
@@ -336,6 +339,7 @@ static void init_kvm_event_record(struct perf_kvm_stat *kvm)
336 INIT_LIST_HEAD(&kvm->kvm_events_cache[i]); 339 INIT_LIST_HEAD(&kvm->kvm_events_cache[i]);
337} 340}
338 341
342#ifdef HAVE_TIMERFD_SUPPORT
339static void clear_events_cache_stats(struct list_head *kvm_events_cache) 343static void clear_events_cache_stats(struct list_head *kvm_events_cache)
340{ 344{
341 struct list_head *head; 345 struct list_head *head;
@@ -357,6 +361,7 @@ static void clear_events_cache_stats(struct list_head *kvm_events_cache)
357 } 361 }
358 } 362 }
359} 363}
364#endif
360 365
361static int kvm_events_hash_fn(u64 key) 366static int kvm_events_hash_fn(u64 key)
362{ 367{
@@ -782,6 +787,7 @@ static void print_result(struct perf_kvm_stat *kvm)
782 pr_info("\nLost events: %" PRIu64 "\n\n", kvm->lost_events); 787 pr_info("\nLost events: %" PRIu64 "\n\n", kvm->lost_events);
783} 788}
784 789
790#ifdef HAVE_TIMERFD_SUPPORT
785static int process_lost_event(struct perf_tool *tool, 791static int process_lost_event(struct perf_tool *tool,
786 union perf_event *event __maybe_unused, 792 union perf_event *event __maybe_unused,
787 struct perf_sample *sample __maybe_unused, 793 struct perf_sample *sample __maybe_unused,
@@ -792,6 +798,7 @@ static int process_lost_event(struct perf_tool *tool,
792 kvm->lost_events++; 798 kvm->lost_events++;
793 return 0; 799 return 0;
794} 800}
801#endif
795 802
796static bool skip_sample(struct perf_kvm_stat *kvm, 803static bool skip_sample(struct perf_kvm_stat *kvm,
797 struct perf_sample *sample) 804 struct perf_sample *sample)
@@ -871,6 +878,7 @@ static bool verify_vcpu(int vcpu)
871 return true; 878 return true;
872} 879}
873 880
881#ifdef HAVE_TIMERFD_SUPPORT
874/* keeping the max events to a modest level to keep 882/* keeping the max events to a modest level to keep
875 * the processing of samples per mmap smooth. 883 * the processing of samples per mmap smooth.
876 */ 884 */
@@ -1212,6 +1220,7 @@ static int kvm_live_open_events(struct perf_kvm_stat *kvm)
1212out: 1220out:
1213 return rc; 1221 return rc;
1214} 1222}
1223#endif
1215 1224
1216static int read_events(struct perf_kvm_stat *kvm) 1225static int read_events(struct perf_kvm_stat *kvm)
1217{ 1226{
@@ -1222,10 +1231,13 @@ static int read_events(struct perf_kvm_stat *kvm)
1222 .comm = perf_event__process_comm, 1231 .comm = perf_event__process_comm,
1223 .ordered_samples = true, 1232 .ordered_samples = true,
1224 }; 1233 };
1234 struct perf_data_file file = {
1235 .path = input_name,
1236 .mode = PERF_DATA_MODE_READ,
1237 };
1225 1238
1226 kvm->tool = eops; 1239 kvm->tool = eops;
1227 kvm->session = perf_session__new(kvm->file_name, O_RDONLY, 0, false, 1240 kvm->session = perf_session__new(&file, false, &kvm->tool);
1228 &kvm->tool);
1229 if (!kvm->session) { 1241 if (!kvm->session) {
1230 pr_err("Initializing perf session failed\n"); 1242 pr_err("Initializing perf session failed\n");
1231 return -EINVAL; 1243 return -EINVAL;
@@ -1375,6 +1387,7 @@ kvm_events_report(struct perf_kvm_stat *kvm, int argc, const char **argv)
1375 return kvm_events_report_vcpu(kvm); 1387 return kvm_events_report_vcpu(kvm);
1376} 1388}
1377 1389
1390#ifdef HAVE_TIMERFD_SUPPORT
1378static struct perf_evlist *kvm_live_event_list(void) 1391static struct perf_evlist *kvm_live_event_list(void)
1379{ 1392{
1380 struct perf_evlist *evlist; 1393 struct perf_evlist *evlist;
@@ -1433,8 +1446,9 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
1433 const struct option live_options[] = { 1446 const struct option live_options[] = {
1434 OPT_STRING('p', "pid", &kvm->opts.target.pid, "pid", 1447 OPT_STRING('p', "pid", &kvm->opts.target.pid, "pid",
1435 "record events on existing process id"), 1448 "record events on existing process id"),
1436 OPT_UINTEGER('m', "mmap-pages", &kvm->opts.mmap_pages, 1449 OPT_CALLBACK('m', "mmap-pages", &kvm->opts.mmap_pages, "pages",
1437 "number of mmap data pages"), 1450 "number of mmap data pages",
1451 perf_evlist__parse_mmap_pages),
1438 OPT_INCR('v', "verbose", &verbose, 1452 OPT_INCR('v', "verbose", &verbose,
1439 "be more verbose (show counter open errors, etc)"), 1453 "be more verbose (show counter open errors, etc)"),
1440 OPT_BOOLEAN('a', "all-cpus", &kvm->opts.target.system_wide, 1454 OPT_BOOLEAN('a', "all-cpus", &kvm->opts.target.system_wide,
@@ -1456,6 +1470,9 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
1456 "perf kvm stat live [<options>]", 1470 "perf kvm stat live [<options>]",
1457 NULL 1471 NULL
1458 }; 1472 };
1473 struct perf_data_file file = {
1474 .mode = PERF_DATA_MODE_WRITE,
1475 };
1459 1476
1460 1477
1461 /* event handling */ 1478 /* event handling */
@@ -1520,7 +1537,7 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
1520 /* 1537 /*
1521 * perf session 1538 * perf session
1522 */ 1539 */
1523 kvm->session = perf_session__new(NULL, O_WRONLY, false, false, &kvm->tool); 1540 kvm->session = perf_session__new(&file, false, &kvm->tool);
1524 if (kvm->session == NULL) { 1541 if (kvm->session == NULL) {
1525 err = -ENOMEM; 1542 err = -ENOMEM;
1526 goto out; 1543 goto out;
@@ -1558,6 +1575,7 @@ out:
1558 1575
1559 return err; 1576 return err;
1560} 1577}
1578#endif
1561 1579
1562static void print_kvm_stat_usage(void) 1580static void print_kvm_stat_usage(void)
1563{ 1581{
@@ -1596,8 +1614,10 @@ static int kvm_cmd_stat(const char *file_name, int argc, const char **argv)
1596 if (!strncmp(argv[1], "rep", 3)) 1614 if (!strncmp(argv[1], "rep", 3))
1597 return kvm_events_report(&kvm, argc - 1 , argv + 1); 1615 return kvm_events_report(&kvm, argc - 1 , argv + 1);
1598 1616
1617#ifdef HAVE_TIMERFD_SUPPORT
1599 if (!strncmp(argv[1], "live", 4)) 1618 if (!strncmp(argv[1], "live", 4))
1600 return kvm_events_live(&kvm, argc - 1 , argv + 1); 1619 return kvm_events_live(&kvm, argc - 1 , argv + 1);
1620#endif
1601 1621
1602perf_stat: 1622perf_stat:
1603 return cmd_stat(argc, argv, NULL); 1623 return cmd_stat(argc, argv, NULL);
diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
index e79f423cc302..011195e38f21 100644
--- a/tools/perf/builtin-list.c
+++ b/tools/perf/builtin-list.c
@@ -14,51 +14,63 @@
14#include "util/parse-events.h" 14#include "util/parse-events.h"
15#include "util/cache.h" 15#include "util/cache.h"
16#include "util/pmu.h" 16#include "util/pmu.h"
17#include "util/parse-options.h"
17 18
18int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused) 19int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
19{ 20{
21 int i;
22 const struct option list_options[] = {
23 OPT_END()
24 };
25 const char * const list_usage[] = {
26 "perf list [hw|sw|cache|tracepoint|pmu|event_glob]",
27 NULL
28 };
29
30 argc = parse_options(argc, argv, list_options, list_usage,
31 PARSE_OPT_STOP_AT_NON_OPTION);
32
20 setup_pager(); 33 setup_pager();
21 34
22 if (argc == 1) 35 if (argc == 0) {
23 print_events(NULL, false); 36 print_events(NULL, false);
24 else { 37 return 0;
25 int i; 38 }
26
27 for (i = 1; i < argc; ++i) {
28 if (i > 2)
29 putchar('\n');
30 if (strncmp(argv[i], "tracepoint", 10) == 0)
31 print_tracepoint_events(NULL, NULL, false);
32 else if (strcmp(argv[i], "hw") == 0 ||
33 strcmp(argv[i], "hardware") == 0)
34 print_events_type(PERF_TYPE_HARDWARE);
35 else if (strcmp(argv[i], "sw") == 0 ||
36 strcmp(argv[i], "software") == 0)
37 print_events_type(PERF_TYPE_SOFTWARE);
38 else if (strcmp(argv[i], "cache") == 0 ||
39 strcmp(argv[i], "hwcache") == 0)
40 print_hwcache_events(NULL, false);
41 else if (strcmp(argv[i], "pmu") == 0)
42 print_pmu_events(NULL, false);
43 else if (strcmp(argv[i], "--raw-dump") == 0)
44 print_events(NULL, true);
45 else {
46 char *sep = strchr(argv[i], ':'), *s;
47 int sep_idx;
48 39
49 if (sep == NULL) { 40 for (i = 0; i < argc; ++i) {
50 print_events(argv[i], false); 41 if (i)
51 continue; 42 putchar('\n');
52 } 43 if (strncmp(argv[i], "tracepoint", 10) == 0)
53 sep_idx = sep - argv[i]; 44 print_tracepoint_events(NULL, NULL, false);
54 s = strdup(argv[i]); 45 else if (strcmp(argv[i], "hw") == 0 ||
55 if (s == NULL) 46 strcmp(argv[i], "hardware") == 0)
56 return -1; 47 print_events_type(PERF_TYPE_HARDWARE);
48 else if (strcmp(argv[i], "sw") == 0 ||
49 strcmp(argv[i], "software") == 0)
50 print_events_type(PERF_TYPE_SOFTWARE);
51 else if (strcmp(argv[i], "cache") == 0 ||
52 strcmp(argv[i], "hwcache") == 0)
53 print_hwcache_events(NULL, false);
54 else if (strcmp(argv[i], "pmu") == 0)
55 print_pmu_events(NULL, false);
56 else if (strcmp(argv[i], "--raw-dump") == 0)
57 print_events(NULL, true);
58 else {
59 char *sep = strchr(argv[i], ':'), *s;
60 int sep_idx;
57 61
58 s[sep_idx] = '\0'; 62 if (sep == NULL) {
59 print_tracepoint_events(s, s + sep_idx + 1, false); 63 print_events(argv[i], false);
60 free(s); 64 continue;
61 } 65 }
66 sep_idx = sep - argv[i];
67 s = strdup(argv[i]);
68 if (s == NULL)
69 return -1;
70
71 s[sep_idx] = '\0';
72 print_tracepoint_events(s, s + sep_idx + 1, false);
73 free(s);
62 } 74 }
63 } 75 }
64 return 0; 76 return 0;
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index ee33ba2f05dd..c852c7a85d32 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -15,6 +15,7 @@
15#include "util/debug.h" 15#include "util/debug.h"
16#include "util/session.h" 16#include "util/session.h"
17#include "util/tool.h" 17#include "util/tool.h"
18#include "util/data.h"
18 19
19#include <sys/types.h> 20#include <sys/types.h>
20#include <sys/prctl.h> 21#include <sys/prctl.h>
@@ -56,7 +57,9 @@ struct lock_stat {
56 57
57 unsigned int nr_readlock; 58 unsigned int nr_readlock;
58 unsigned int nr_trylock; 59 unsigned int nr_trylock;
60
59 /* these times are in nano sec. */ 61 /* these times are in nano sec. */
62 u64 avg_wait_time;
60 u64 wait_time_total; 63 u64 wait_time_total;
61 u64 wait_time_min; 64 u64 wait_time_min;
62 u64 wait_time_max; 65 u64 wait_time_max;
@@ -208,6 +211,7 @@ static struct thread_stat *thread_stat_findnew_first(u32 tid)
208 211
209SINGLE_KEY(nr_acquired) 212SINGLE_KEY(nr_acquired)
210SINGLE_KEY(nr_contended) 213SINGLE_KEY(nr_contended)
214SINGLE_KEY(avg_wait_time)
211SINGLE_KEY(wait_time_total) 215SINGLE_KEY(wait_time_total)
212SINGLE_KEY(wait_time_max) 216SINGLE_KEY(wait_time_max)
213 217
@@ -244,6 +248,7 @@ static struct rb_root result; /* place to store sorted data */
244struct lock_key keys[] = { 248struct lock_key keys[] = {
245 DEF_KEY_LOCK(acquired, nr_acquired), 249 DEF_KEY_LOCK(acquired, nr_acquired),
246 DEF_KEY_LOCK(contended, nr_contended), 250 DEF_KEY_LOCK(contended, nr_contended),
251 DEF_KEY_LOCK(avg_wait, avg_wait_time),
247 DEF_KEY_LOCK(wait_total, wait_time_total), 252 DEF_KEY_LOCK(wait_total, wait_time_total),
248 DEF_KEY_LOCK(wait_min, wait_time_min), 253 DEF_KEY_LOCK(wait_min, wait_time_min),
249 DEF_KEY_LOCK(wait_max, wait_time_max), 254 DEF_KEY_LOCK(wait_max, wait_time_max),
@@ -321,10 +326,12 @@ static struct lock_stat *lock_stat_findnew(void *addr, const char *name)
321 326
322 new->addr = addr; 327 new->addr = addr;
323 new->name = zalloc(sizeof(char) * strlen(name) + 1); 328 new->name = zalloc(sizeof(char) * strlen(name) + 1);
324 if (!new->name) 329 if (!new->name) {
330 free(new);
325 goto alloc_failed; 331 goto alloc_failed;
326 strcpy(new->name, name); 332 }
327 333
334 strcpy(new->name, name);
328 new->wait_time_min = ULLONG_MAX; 335 new->wait_time_min = ULLONG_MAX;
329 336
330 list_add(&new->hash_entry, entry); 337 list_add(&new->hash_entry, entry);
@@ -400,17 +407,17 @@ static int report_lock_acquire_event(struct perf_evsel *evsel,
400 407
401 ls = lock_stat_findnew(addr, name); 408 ls = lock_stat_findnew(addr, name);
402 if (!ls) 409 if (!ls)
403 return -1; 410 return -ENOMEM;
404 if (ls->discard) 411 if (ls->discard)
405 return 0; 412 return 0;
406 413
407 ts = thread_stat_findnew(sample->tid); 414 ts = thread_stat_findnew(sample->tid);
408 if (!ts) 415 if (!ts)
409 return -1; 416 return -ENOMEM;
410 417
411 seq = get_seq(ts, addr); 418 seq = get_seq(ts, addr);
412 if (!seq) 419 if (!seq)
413 return -1; 420 return -ENOMEM;
414 421
415 switch (seq->state) { 422 switch (seq->state) {
416 case SEQ_STATE_UNINITIALIZED: 423 case SEQ_STATE_UNINITIALIZED:
@@ -446,7 +453,6 @@ broken:
446 list_del(&seq->list); 453 list_del(&seq->list);
447 free(seq); 454 free(seq);
448 goto end; 455 goto end;
449 break;
450 default: 456 default:
451 BUG_ON("Unknown state of lock sequence found!\n"); 457 BUG_ON("Unknown state of lock sequence found!\n");
452 break; 458 break;
@@ -473,17 +479,17 @@ static int report_lock_acquired_event(struct perf_evsel *evsel,
473 479
474 ls = lock_stat_findnew(addr, name); 480 ls = lock_stat_findnew(addr, name);
475 if (!ls) 481 if (!ls)
476 return -1; 482 return -ENOMEM;
477 if (ls->discard) 483 if (ls->discard)
478 return 0; 484 return 0;
479 485
480 ts = thread_stat_findnew(sample->tid); 486 ts = thread_stat_findnew(sample->tid);
481 if (!ts) 487 if (!ts)
482 return -1; 488 return -ENOMEM;
483 489
484 seq = get_seq(ts, addr); 490 seq = get_seq(ts, addr);
485 if (!seq) 491 if (!seq)
486 return -1; 492 return -ENOMEM;
487 493
488 switch (seq->state) { 494 switch (seq->state) {
489 case SEQ_STATE_UNINITIALIZED: 495 case SEQ_STATE_UNINITIALIZED:
@@ -508,8 +514,6 @@ static int report_lock_acquired_event(struct perf_evsel *evsel,
508 list_del(&seq->list); 514 list_del(&seq->list);
509 free(seq); 515 free(seq);
510 goto end; 516 goto end;
511 break;
512
513 default: 517 default:
514 BUG_ON("Unknown state of lock sequence found!\n"); 518 BUG_ON("Unknown state of lock sequence found!\n");
515 break; 519 break;
@@ -517,6 +521,7 @@ static int report_lock_acquired_event(struct perf_evsel *evsel,
517 521
518 seq->state = SEQ_STATE_ACQUIRED; 522 seq->state = SEQ_STATE_ACQUIRED;
519 ls->nr_acquired++; 523 ls->nr_acquired++;
524 ls->avg_wait_time = ls->nr_contended ? ls->wait_time_total/ls->nr_contended : 0;
520 seq->prev_event_time = sample->time; 525 seq->prev_event_time = sample->time;
521end: 526end:
522 return 0; 527 return 0;
@@ -536,17 +541,17 @@ static int report_lock_contended_event(struct perf_evsel *evsel,
536 541
537 ls = lock_stat_findnew(addr, name); 542 ls = lock_stat_findnew(addr, name);
538 if (!ls) 543 if (!ls)
539 return -1; 544 return -ENOMEM;
540 if (ls->discard) 545 if (ls->discard)
541 return 0; 546 return 0;
542 547
543 ts = thread_stat_findnew(sample->tid); 548 ts = thread_stat_findnew(sample->tid);
544 if (!ts) 549 if (!ts)
545 return -1; 550 return -ENOMEM;
546 551
547 seq = get_seq(ts, addr); 552 seq = get_seq(ts, addr);
548 if (!seq) 553 if (!seq)
549 return -1; 554 return -ENOMEM;
550 555
551 switch (seq->state) { 556 switch (seq->state) {
552 case SEQ_STATE_UNINITIALIZED: 557 case SEQ_STATE_UNINITIALIZED:
@@ -564,7 +569,6 @@ static int report_lock_contended_event(struct perf_evsel *evsel,
564 list_del(&seq->list); 569 list_del(&seq->list);
565 free(seq); 570 free(seq);
566 goto end; 571 goto end;
567 break;
568 default: 572 default:
569 BUG_ON("Unknown state of lock sequence found!\n"); 573 BUG_ON("Unknown state of lock sequence found!\n");
570 break; 574 break;
@@ -572,6 +576,7 @@ static int report_lock_contended_event(struct perf_evsel *evsel,
572 576
573 seq->state = SEQ_STATE_CONTENDED; 577 seq->state = SEQ_STATE_CONTENDED;
574 ls->nr_contended++; 578 ls->nr_contended++;
579 ls->avg_wait_time = ls->wait_time_total/ls->nr_contended;
575 seq->prev_event_time = sample->time; 580 seq->prev_event_time = sample->time;
576end: 581end:
577 return 0; 582 return 0;
@@ -591,22 +596,21 @@ static int report_lock_release_event(struct perf_evsel *evsel,
591 596
592 ls = lock_stat_findnew(addr, name); 597 ls = lock_stat_findnew(addr, name);
593 if (!ls) 598 if (!ls)
594 return -1; 599 return -ENOMEM;
595 if (ls->discard) 600 if (ls->discard)
596 return 0; 601 return 0;
597 602
598 ts = thread_stat_findnew(sample->tid); 603 ts = thread_stat_findnew(sample->tid);
599 if (!ts) 604 if (!ts)
600 return -1; 605 return -ENOMEM;
601 606
602 seq = get_seq(ts, addr); 607 seq = get_seq(ts, addr);
603 if (!seq) 608 if (!seq)
604 return -1; 609 return -ENOMEM;
605 610
606 switch (seq->state) { 611 switch (seq->state) {
607 case SEQ_STATE_UNINITIALIZED: 612 case SEQ_STATE_UNINITIALIZED:
608 goto end; 613 goto end;
609 break;
610 case SEQ_STATE_ACQUIRED: 614 case SEQ_STATE_ACQUIRED:
611 break; 615 break;
612 case SEQ_STATE_READ_ACQUIRED: 616 case SEQ_STATE_READ_ACQUIRED:
@@ -624,7 +628,6 @@ static int report_lock_release_event(struct perf_evsel *evsel,
624 ls->discard = 1; 628 ls->discard = 1;
625 bad_hist[BROKEN_RELEASE]++; 629 bad_hist[BROKEN_RELEASE]++;
626 goto free_seq; 630 goto free_seq;
627 break;
628 default: 631 default:
629 BUG_ON("Unknown state of lock sequence found!\n"); 632 BUG_ON("Unknown state of lock sequence found!\n");
630 break; 633 break;
@@ -690,7 +693,7 @@ static void print_bad_events(int bad, int total)
690 693
691 pr_info("\n=== output for debug===\n\n"); 694 pr_info("\n=== output for debug===\n\n");
692 pr_info("bad: %d, total: %d\n", bad, total); 695 pr_info("bad: %d, total: %d\n", bad, total);
693 pr_info("bad rate: %f %%\n", (double)bad / (double)total * 100); 696 pr_info("bad rate: %.2f %%\n", (double)bad / (double)total * 100);
694 pr_info("histogram of events caused bad sequence\n"); 697 pr_info("histogram of events caused bad sequence\n");
695 for (i = 0; i < BROKEN_MAX; i++) 698 for (i = 0; i < BROKEN_MAX; i++)
696 pr_info(" %10s: %d\n", name[i], bad_hist[i]); 699 pr_info(" %10s: %d\n", name[i], bad_hist[i]);
@@ -707,6 +710,7 @@ static void print_result(void)
707 pr_info("%10s ", "acquired"); 710 pr_info("%10s ", "acquired");
708 pr_info("%10s ", "contended"); 711 pr_info("%10s ", "contended");
709 712
713 pr_info("%15s ", "avg wait (ns)");
710 pr_info("%15s ", "total wait (ns)"); 714 pr_info("%15s ", "total wait (ns)");
711 pr_info("%15s ", "max wait (ns)"); 715 pr_info("%15s ", "max wait (ns)");
712 pr_info("%15s ", "min wait (ns)"); 716 pr_info("%15s ", "min wait (ns)");
@@ -738,6 +742,7 @@ static void print_result(void)
738 pr_info("%10u ", st->nr_acquired); 742 pr_info("%10u ", st->nr_acquired);
739 pr_info("%10u ", st->nr_contended); 743 pr_info("%10u ", st->nr_contended);
740 744
745 pr_info("%15" PRIu64 " ", st->avg_wait_time);
741 pr_info("%15" PRIu64 " ", st->wait_time_total); 746 pr_info("%15" PRIu64 " ", st->wait_time_total);
742 pr_info("%15" PRIu64 " ", st->wait_time_max); 747 pr_info("%15" PRIu64 " ", st->wait_time_max);
743 pr_info("%15" PRIu64 " ", st->wait_time_min == ULLONG_MAX ? 748 pr_info("%15" PRIu64 " ", st->wait_time_min == ULLONG_MAX ?
@@ -762,7 +767,7 @@ static void dump_threads(void)
762 while (node) { 767 while (node) {
763 st = container_of(node, struct thread_stat, rb); 768 st = container_of(node, struct thread_stat, rb);
764 t = perf_session__findnew(session, st->tid); 769 t = perf_session__findnew(session, st->tid);
765 pr_info("%10d: %s\n", st->tid, t->comm); 770 pr_info("%10d: %s\n", st->tid, thread__comm_str(t));
766 node = rb_next(node); 771 node = rb_next(node);
767 }; 772 };
768} 773}
@@ -814,14 +819,26 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
814 return -1; 819 return -1;
815 } 820 }
816 821
817 if (evsel->handler.func != NULL) { 822 if (evsel->handler != NULL) {
818 tracepoint_handler f = evsel->handler.func; 823 tracepoint_handler f = evsel->handler;
819 return f(evsel, sample); 824 return f(evsel, sample);
820 } 825 }
821 826
822 return 0; 827 return 0;
823} 828}
824 829
830static void sort_result(void)
831{
832 unsigned int i;
833 struct lock_stat *st;
834
835 for (i = 0; i < LOCKHASH_SIZE; i++) {
836 list_for_each_entry(st, &lockhash_table[i], hash_entry) {
837 insert_to_result(st, compare);
838 }
839 }
840}
841
825static const struct perf_evsel_str_handler lock_tracepoints[] = { 842static const struct perf_evsel_str_handler lock_tracepoints[] = {
826 { "lock:lock_acquire", perf_evsel__process_lock_acquire, }, /* CONFIG_LOCKDEP */ 843 { "lock:lock_acquire", perf_evsel__process_lock_acquire, }, /* CONFIG_LOCKDEP */
827 { "lock:lock_acquired", perf_evsel__process_lock_acquired, }, /* CONFIG_LOCKDEP, CONFIG_LOCK_STAT */ 844 { "lock:lock_acquired", perf_evsel__process_lock_acquired, }, /* CONFIG_LOCKDEP, CONFIG_LOCK_STAT */
@@ -829,51 +846,51 @@ static const struct perf_evsel_str_handler lock_tracepoints[] = {
829 { "lock:lock_release", perf_evsel__process_lock_release, }, /* CONFIG_LOCKDEP */ 846 { "lock:lock_release", perf_evsel__process_lock_release, }, /* CONFIG_LOCKDEP */
830}; 847};
831 848
832static int read_events(void) 849static int __cmd_report(bool display_info)
833{ 850{
851 int err = -EINVAL;
834 struct perf_tool eops = { 852 struct perf_tool eops = {
835 .sample = process_sample_event, 853 .sample = process_sample_event,
836 .comm = perf_event__process_comm, 854 .comm = perf_event__process_comm,
837 .ordered_samples = true, 855 .ordered_samples = true,
838 }; 856 };
839 session = perf_session__new(input_name, O_RDONLY, 0, false, &eops); 857 struct perf_data_file file = {
858 .path = input_name,
859 .mode = PERF_DATA_MODE_READ,
860 };
861
862 session = perf_session__new(&file, false, &eops);
840 if (!session) { 863 if (!session) {
841 pr_err("Initializing perf session failed\n"); 864 pr_err("Initializing perf session failed\n");
842 return -1; 865 return -ENOMEM;
843 } 866 }
844 867
868 if (!perf_session__has_traces(session, "lock record"))
869 goto out_delete;
870
845 if (perf_session__set_tracepoints_handlers(session, lock_tracepoints)) { 871 if (perf_session__set_tracepoints_handlers(session, lock_tracepoints)) {
846 pr_err("Initializing perf session tracepoint handlers failed\n"); 872 pr_err("Initializing perf session tracepoint handlers failed\n");
847 return -1; 873 goto out_delete;
848 } 874 }
849 875
850 return perf_session__process_events(session, &eops); 876 if (select_key())
851} 877 goto out_delete;
852
853static void sort_result(void)
854{
855 unsigned int i;
856 struct lock_stat *st;
857 878
858 for (i = 0; i < LOCKHASH_SIZE; i++) { 879 err = perf_session__process_events(session, &eops);
859 list_for_each_entry(st, &lockhash_table[i], hash_entry) { 880 if (err)
860 insert_to_result(st, compare); 881 goto out_delete;
861 }
862 }
863}
864 882
865static int __cmd_report(void)
866{
867 setup_pager(); 883 setup_pager();
884 if (display_info) /* used for info subcommand */
885 err = dump_info();
886 else {
887 sort_result();
888 print_result();
889 }
868 890
869 if ((select_key() != 0) || 891out_delete:
870 (read_events() != 0)) 892 perf_session__delete(session);
871 return -1; 893 return err;
872
873 sort_result();
874 print_result();
875
876 return 0;
877} 894}
878 895
879static int __cmd_record(int argc, const char **argv) 896static int __cmd_record(int argc, const char **argv)
@@ -881,7 +898,7 @@ static int __cmd_record(int argc, const char **argv)
881 const char *record_args[] = { 898 const char *record_args[] = {
882 "record", "-R", "-m", "1024", "-c", "1", 899 "record", "-R", "-m", "1024", "-c", "1",
883 }; 900 };
884 unsigned int rec_argc, i, j; 901 unsigned int rec_argc, i, j, ret;
885 const char **rec_argv; 902 const char **rec_argv;
886 903
887 for (i = 0; i < ARRAY_SIZE(lock_tracepoints); i++) { 904 for (i = 0; i < ARRAY_SIZE(lock_tracepoints); i++) {
@@ -898,7 +915,7 @@ static int __cmd_record(int argc, const char **argv)
898 rec_argc += 2 * ARRAY_SIZE(lock_tracepoints); 915 rec_argc += 2 * ARRAY_SIZE(lock_tracepoints);
899 916
900 rec_argv = calloc(rec_argc + 1, sizeof(char *)); 917 rec_argv = calloc(rec_argc + 1, sizeof(char *));
901 if (rec_argv == NULL) 918 if (!rec_argv)
902 return -ENOMEM; 919 return -ENOMEM;
903 920
904 for (i = 0; i < ARRAY_SIZE(record_args); i++) 921 for (i = 0; i < ARRAY_SIZE(record_args); i++)
@@ -914,7 +931,9 @@ static int __cmd_record(int argc, const char **argv)
914 931
915 BUG_ON(i != rec_argc); 932 BUG_ON(i != rec_argc);
916 933
917 return cmd_record(i, rec_argv, NULL); 934 ret = cmd_record(i, rec_argv, NULL);
935 free(rec_argv);
936 return ret;
918} 937}
919 938
920int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused) 939int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused)
@@ -934,7 +953,7 @@ int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused)
934 }; 953 };
935 const struct option report_options[] = { 954 const struct option report_options[] = {
936 OPT_STRING('k', "key", &sort_key, "acquired", 955 OPT_STRING('k', "key", &sort_key, "acquired",
937 "key for sorting (acquired / contended / wait_total / wait_max / wait_min)"), 956 "key for sorting (acquired / contended / avg_wait / wait_total / wait_max / wait_min)"),
938 /* TODO: type */ 957 /* TODO: type */
939 OPT_END() 958 OPT_END()
940 }; 959 };
@@ -972,7 +991,7 @@ int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused)
972 if (argc) 991 if (argc)
973 usage_with_options(report_usage, report_options); 992 usage_with_options(report_usage, report_options);
974 } 993 }
975 __cmd_report(); 994 rc = __cmd_report(false);
976 } else if (!strcmp(argv[0], "script")) { 995 } else if (!strcmp(argv[0], "script")) {
977 /* Aliased to 'perf script' */ 996 /* Aliased to 'perf script' */
978 return cmd_script(argc, argv, prefix); 997 return cmd_script(argc, argv, prefix);
@@ -985,11 +1004,7 @@ int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused)
985 } 1004 }
986 /* recycling report_lock_ops */ 1005 /* recycling report_lock_ops */
987 trace_handler = &report_lock_ops; 1006 trace_handler = &report_lock_ops;
988 setup_pager(); 1007 rc = __cmd_report(true);
989 if (read_events() != 0)
990 rc = -1;
991 else
992 rc = dump_info();
993 } else { 1008 } else {
994 usage_with_options(lock_usage, lock_options); 1009 usage_with_options(lock_usage, lock_options);
995 } 1010 }
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
index 253133a6251d..31c00f186da1 100644
--- a/tools/perf/builtin-mem.c
+++ b/tools/perf/builtin-mem.c
@@ -5,6 +5,7 @@
5#include "util/trace-event.h" 5#include "util/trace-event.h"
6#include "util/tool.h" 6#include "util/tool.h"
7#include "util/session.h" 7#include "util/session.h"
8#include "util/data.h"
8 9
9#define MEM_OPERATION_LOAD "load" 10#define MEM_OPERATION_LOAD "load"
10#define MEM_OPERATION_STORE "store" 11#define MEM_OPERATION_STORE "store"
@@ -119,10 +120,14 @@ static int process_sample_event(struct perf_tool *tool,
119 120
120static int report_raw_events(struct perf_mem *mem) 121static int report_raw_events(struct perf_mem *mem)
121{ 122{
123 struct perf_data_file file = {
124 .path = input_name,
125 .mode = PERF_DATA_MODE_READ,
126 };
122 int err = -EINVAL; 127 int err = -EINVAL;
123 int ret; 128 int ret;
124 struct perf_session *session = perf_session__new(input_name, O_RDONLY, 129 struct perf_session *session = perf_session__new(&file, false,
125 0, false, &mem->tool); 130 &mem->tool);
126 131
127 if (session == NULL) 132 if (session == NULL)
128 return -ENOMEM; 133 return -ENOMEM;
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index e8a66f9a6715..89acc17cf2a0 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -173,7 +173,7 @@ static int opt_set_target(const struct option *opt, const char *str,
173 if (str && !params.target) { 173 if (str && !params.target) {
174 if (!strcmp(opt->long_name, "exec")) 174 if (!strcmp(opt->long_name, "exec"))
175 params.uprobes = true; 175 params.uprobes = true;
176#ifdef DWARF_SUPPORT 176#ifdef HAVE_DWARF_SUPPORT
177 else if (!strcmp(opt->long_name, "module")) 177 else if (!strcmp(opt->long_name, "module"))
178 params.uprobes = false; 178 params.uprobes = false;
179#endif 179#endif
@@ -187,7 +187,7 @@ static int opt_set_target(const struct option *opt, const char *str,
187 return ret; 187 return ret;
188} 188}
189 189
190#ifdef DWARF_SUPPORT 190#ifdef HAVE_DWARF_SUPPORT
191static int opt_show_lines(const struct option *opt __maybe_unused, 191static int opt_show_lines(const struct option *opt __maybe_unused,
192 const char *str, int unset __maybe_unused) 192 const char *str, int unset __maybe_unused)
193{ 193{
@@ -257,7 +257,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
257 "perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]", 257 "perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]",
258 "perf probe [<options>] --del '[GROUP:]EVENT' ...", 258 "perf probe [<options>] --del '[GROUP:]EVENT' ...",
259 "perf probe --list", 259 "perf probe --list",
260#ifdef DWARF_SUPPORT 260#ifdef HAVE_DWARF_SUPPORT
261 "perf probe [<options>] --line 'LINEDESC'", 261 "perf probe [<options>] --line 'LINEDESC'",
262 "perf probe [<options>] --vars 'PROBEPOINT'", 262 "perf probe [<options>] --vars 'PROBEPOINT'",
263#endif 263#endif
@@ -271,7 +271,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
271 OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.", 271 OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.",
272 opt_del_probe_event), 272 opt_del_probe_event),
273 OPT_CALLBACK('a', "add", NULL, 273 OPT_CALLBACK('a', "add", NULL,
274#ifdef DWARF_SUPPORT 274#ifdef HAVE_DWARF_SUPPORT
275 "[EVENT=]FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT" 275 "[EVENT=]FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT"
276 " [[NAME=]ARG ...]", 276 " [[NAME=]ARG ...]",
277#else 277#else
@@ -283,7 +283,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
283 "\t\tFUNC:\tFunction name\n" 283 "\t\tFUNC:\tFunction name\n"
284 "\t\tOFF:\tOffset from function entry (in byte)\n" 284 "\t\tOFF:\tOffset from function entry (in byte)\n"
285 "\t\t%return:\tPut the probe at function return\n" 285 "\t\t%return:\tPut the probe at function return\n"
286#ifdef DWARF_SUPPORT 286#ifdef HAVE_DWARF_SUPPORT
287 "\t\tSRC:\tSource code path\n" 287 "\t\tSRC:\tSource code path\n"
288 "\t\tRL:\tRelative line number from function entry.\n" 288 "\t\tRL:\tRelative line number from function entry.\n"
289 "\t\tAL:\tAbsolute line number in file.\n" 289 "\t\tAL:\tAbsolute line number in file.\n"
@@ -296,7 +296,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
296 opt_add_probe_event), 296 opt_add_probe_event),
297 OPT_BOOLEAN('f', "force", &params.force_add, "forcibly add events" 297 OPT_BOOLEAN('f', "force", &params.force_add, "forcibly add events"
298 " with existing name"), 298 " with existing name"),
299#ifdef DWARF_SUPPORT 299#ifdef HAVE_DWARF_SUPPORT
300 OPT_CALLBACK('L', "line", NULL, 300 OPT_CALLBACK('L', "line", NULL,
301 "FUNC[:RLN[+NUM|-RLN2]]|SRC:ALN[+NUM|-ALN2]", 301 "FUNC[:RLN[+NUM|-RLN2]]|SRC:ALN[+NUM|-ALN2]",
302 "Show source code lines.", opt_show_lines), 302 "Show source code lines.", opt_show_lines),
@@ -408,7 +408,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
408 return ret; 408 return ret;
409 } 409 }
410 410
411#ifdef DWARF_SUPPORT 411#ifdef HAVE_DWARF_SUPPORT
412 if (params.show_lines && !params.uprobes) { 412 if (params.show_lines && !params.uprobes) {
413 if (params.mod_events) { 413 if (params.mod_events) {
414 pr_err(" Error: Don't use --line with" 414 pr_err(" Error: Don't use --line with"
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index d04651484640..15280b5e5574 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -24,12 +24,13 @@
24#include "util/symbol.h" 24#include "util/symbol.h"
25#include "util/cpumap.h" 25#include "util/cpumap.h"
26#include "util/thread_map.h" 26#include "util/thread_map.h"
27#include "util/data.h"
27 28
28#include <unistd.h> 29#include <unistd.h>
29#include <sched.h> 30#include <sched.h>
30#include <sys/mman.h> 31#include <sys/mman.h>
31 32
32#ifndef HAVE_ON_EXIT 33#ifndef HAVE_ON_EXIT_SUPPORT
33#ifndef ATEXIT_MAX 34#ifndef ATEXIT_MAX
34#define ATEXIT_MAX 32 35#define ATEXIT_MAX 32
35#endif 36#endif
@@ -65,31 +66,25 @@ struct perf_record {
65 struct perf_tool tool; 66 struct perf_tool tool;
66 struct perf_record_opts opts; 67 struct perf_record_opts opts;
67 u64 bytes_written; 68 u64 bytes_written;
68 const char *output_name; 69 struct perf_data_file file;
69 struct perf_evlist *evlist; 70 struct perf_evlist *evlist;
70 struct perf_session *session; 71 struct perf_session *session;
71 const char *progname; 72 const char *progname;
72 int output;
73 unsigned int page_size;
74 int realtime_prio; 73 int realtime_prio;
75 bool no_buildid; 74 bool no_buildid;
76 bool no_buildid_cache; 75 bool no_buildid_cache;
77 long samples; 76 long samples;
78 off_t post_processing_offset;
79}; 77};
80 78
81static void advance_output(struct perf_record *rec, size_t size)
82{
83 rec->bytes_written += size;
84}
85
86static int write_output(struct perf_record *rec, void *buf, size_t size) 79static int write_output(struct perf_record *rec, void *buf, size_t size)
87{ 80{
81 struct perf_data_file *file = &rec->file;
82
88 while (size) { 83 while (size) {
89 int ret = write(rec->output, buf, size); 84 int ret = write(file->fd, buf, size);
90 85
91 if (ret < 0) { 86 if (ret < 0) {
92 pr_err("failed to write\n"); 87 pr_err("failed to write perf data, error: %m\n");
93 return -1; 88 return -1;
94 } 89 }
95 90
@@ -119,7 +114,7 @@ static int perf_record__mmap_read(struct perf_record *rec,
119{ 114{
120 unsigned int head = perf_mmap__read_head(md); 115 unsigned int head = perf_mmap__read_head(md);
121 unsigned int old = md->prev; 116 unsigned int old = md->prev;
122 unsigned char *data = md->base + rec->page_size; 117 unsigned char *data = md->base + page_size;
123 unsigned long size; 118 unsigned long size;
124 void *buf; 119 void *buf;
125 int rc = 0; 120 int rc = 0;
@@ -234,10 +229,6 @@ try_again:
234 "or try again with a smaller value of -m/--mmap_pages.\n" 229 "or try again with a smaller value of -m/--mmap_pages.\n"
235 "(current value: %d)\n", opts->mmap_pages); 230 "(current value: %d)\n", opts->mmap_pages);
236 rc = -errno; 231 rc = -errno;
237 } else if (!is_power_of_2(opts->mmap_pages) &&
238 (opts->mmap_pages != UINT_MAX)) {
239 pr_err("--mmap_pages/-m value must be a power of two.");
240 rc = -EINVAL;
241 } else { 232 } else {
242 pr_err("failed to mmap with %d (%s)\n", errno, strerror(errno)); 233 pr_err("failed to mmap with %d (%s)\n", errno, strerror(errno));
243 rc = -errno; 234 rc = -errno;
@@ -253,31 +244,34 @@ out:
253 244
254static int process_buildids(struct perf_record *rec) 245static int process_buildids(struct perf_record *rec)
255{ 246{
256 u64 size = lseek(rec->output, 0, SEEK_CUR); 247 struct perf_data_file *file = &rec->file;
248 struct perf_session *session = rec->session;
249 u64 start = session->header.data_offset;
257 250
251 u64 size = lseek(file->fd, 0, SEEK_CUR);
258 if (size == 0) 252 if (size == 0)
259 return 0; 253 return 0;
260 254
261 rec->session->fd = rec->output; 255 return __perf_session__process_events(session, start,
262 return __perf_session__process_events(rec->session, rec->post_processing_offset, 256 size - start,
263 size - rec->post_processing_offset,
264 size, &build_id__mark_dso_hit_ops); 257 size, &build_id__mark_dso_hit_ops);
265} 258}
266 259
267static void perf_record__exit(int status, void *arg) 260static void perf_record__exit(int status, void *arg)
268{ 261{
269 struct perf_record *rec = arg; 262 struct perf_record *rec = arg;
263 struct perf_data_file *file = &rec->file;
270 264
271 if (status != 0) 265 if (status != 0)
272 return; 266 return;
273 267
274 if (!rec->opts.pipe_output) { 268 if (!file->is_pipe) {
275 rec->session->header.data_size += rec->bytes_written; 269 rec->session->header.data_size += rec->bytes_written;
276 270
277 if (!rec->no_buildid) 271 if (!rec->no_buildid)
278 process_buildids(rec); 272 process_buildids(rec);
279 perf_session__write_header(rec->session, rec->evlist, 273 perf_session__write_header(rec->session, rec->evlist,
280 rec->output, true); 274 file->fd, true);
281 perf_session__delete(rec->session); 275 perf_session__delete(rec->session);
282 perf_evlist__delete(rec->evlist); 276 perf_evlist__delete(rec->evlist);
283 symbol__exit(); 277 symbol__exit();
@@ -343,64 +337,47 @@ out:
343 return rc; 337 return rc;
344} 338}
345 339
340static void perf_record__init_features(struct perf_record *rec)
341{
342 struct perf_evlist *evsel_list = rec->evlist;
343 struct perf_session *session = rec->session;
344 int feat;
345
346 for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++)
347 perf_header__set_feat(&session->header, feat);
348
349 if (rec->no_buildid)
350 perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
351
352 if (!have_tracepoints(&evsel_list->entries))
353 perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
354
355 if (!rec->opts.branch_stack)
356 perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
357}
358
346static int __cmd_record(struct perf_record *rec, int argc, const char **argv) 359static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
347{ 360{
348 struct stat st; 361 int err;
349 int flags;
350 int err, output, feat;
351 unsigned long waking = 0; 362 unsigned long waking = 0;
352 const bool forks = argc > 0; 363 const bool forks = argc > 0;
353 struct machine *machine; 364 struct machine *machine;
354 struct perf_tool *tool = &rec->tool; 365 struct perf_tool *tool = &rec->tool;
355 struct perf_record_opts *opts = &rec->opts; 366 struct perf_record_opts *opts = &rec->opts;
356 struct perf_evlist *evsel_list = rec->evlist; 367 struct perf_evlist *evsel_list = rec->evlist;
357 const char *output_name = rec->output_name; 368 struct perf_data_file *file = &rec->file;
358 struct perf_session *session; 369 struct perf_session *session;
359 bool disabled = false; 370 bool disabled = false;
360 371
361 rec->progname = argv[0]; 372 rec->progname = argv[0];
362 373
363 rec->page_size = sysconf(_SC_PAGE_SIZE);
364
365 on_exit(perf_record__sig_exit, rec); 374 on_exit(perf_record__sig_exit, rec);
366 signal(SIGCHLD, sig_handler); 375 signal(SIGCHLD, sig_handler);
367 signal(SIGINT, sig_handler); 376 signal(SIGINT, sig_handler);
368 signal(SIGUSR1, sig_handler); 377 signal(SIGUSR1, sig_handler);
369 signal(SIGTERM, sig_handler); 378 signal(SIGTERM, sig_handler);
370 379
371 if (!output_name) { 380 session = perf_session__new(file, false, NULL);
372 if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode))
373 opts->pipe_output = true;
374 else
375 rec->output_name = output_name = "perf.data";
376 }
377 if (output_name) {
378 if (!strcmp(output_name, "-"))
379 opts->pipe_output = true;
380 else if (!stat(output_name, &st) && st.st_size) {
381 char oldname[PATH_MAX];
382 snprintf(oldname, sizeof(oldname), "%s.old",
383 output_name);
384 unlink(oldname);
385 rename(output_name, oldname);
386 }
387 }
388
389 flags = O_CREAT|O_RDWR|O_TRUNC;
390
391 if (opts->pipe_output)
392 output = STDOUT_FILENO;
393 else
394 output = open(output_name, flags, S_IRUSR | S_IWUSR);
395 if (output < 0) {
396 perror("failed to create output file");
397 return -1;
398 }
399
400 rec->output = output;
401
402 session = perf_session__new(output_name, O_WRONLY,
403 true, false, NULL);
404 if (session == NULL) { 381 if (session == NULL) {
405 pr_err("Not enough memory for reading perf file header\n"); 382 pr_err("Not enough memory for reading perf file header\n");
406 return -1; 383 return -1;
@@ -408,21 +385,11 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
408 385
409 rec->session = session; 386 rec->session = session;
410 387
411 for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++) 388 perf_record__init_features(rec);
412 perf_header__set_feat(&session->header, feat);
413
414 if (rec->no_buildid)
415 perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
416
417 if (!have_tracepoints(&evsel_list->entries))
418 perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
419
420 if (!rec->opts.branch_stack)
421 perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
422 389
423 if (forks) { 390 if (forks) {
424 err = perf_evlist__prepare_workload(evsel_list, &opts->target, 391 err = perf_evlist__prepare_workload(evsel_list, &opts->target,
425 argv, opts->pipe_output, 392 argv, file->is_pipe,
426 true); 393 true);
427 if (err < 0) { 394 if (err < 0) {
428 pr_err("Couldn't run the workload!\n"); 395 pr_err("Couldn't run the workload!\n");
@@ -443,13 +410,13 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
443 */ 410 */
444 on_exit(perf_record__exit, rec); 411 on_exit(perf_record__exit, rec);
445 412
446 if (opts->pipe_output) { 413 if (file->is_pipe) {
447 err = perf_header__write_pipe(output); 414 err = perf_header__write_pipe(file->fd);
448 if (err < 0) 415 if (err < 0)
449 goto out_delete_session; 416 goto out_delete_session;
450 } else { 417 } else {
451 err = perf_session__write_header(session, evsel_list, 418 err = perf_session__write_header(session, evsel_list,
452 output, false); 419 file->fd, false);
453 if (err < 0) 420 if (err < 0)
454 goto out_delete_session; 421 goto out_delete_session;
455 } 422 }
@@ -462,11 +429,9 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
462 goto out_delete_session; 429 goto out_delete_session;
463 } 430 }
464 431
465 rec->post_processing_offset = lseek(output, 0, SEEK_CUR);
466
467 machine = &session->machines.host; 432 machine = &session->machines.host;
468 433
469 if (opts->pipe_output) { 434 if (file->is_pipe) {
470 err = perf_event__synthesize_attrs(tool, session, 435 err = perf_event__synthesize_attrs(tool, session,
471 process_synthesized_event); 436 process_synthesized_event);
472 if (err < 0) { 437 if (err < 0) {
@@ -483,13 +448,13 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
483 * return this more properly and also 448 * return this more properly and also
484 * propagate errors that now are calling die() 449 * propagate errors that now are calling die()
485 */ 450 */
486 err = perf_event__synthesize_tracing_data(tool, output, evsel_list, 451 err = perf_event__synthesize_tracing_data(tool, file->fd, evsel_list,
487 process_synthesized_event); 452 process_synthesized_event);
488 if (err <= 0) { 453 if (err <= 0) {
489 pr_err("Couldn't record tracing data.\n"); 454 pr_err("Couldn't record tracing data.\n");
490 goto out_delete_session; 455 goto out_delete_session;
491 } 456 }
492 advance_output(rec, err); 457 rec->bytes_written += err;
493 } 458 }
494 } 459 }
495 460
@@ -590,7 +555,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
590 fprintf(stderr, 555 fprintf(stderr,
591 "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n", 556 "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n",
592 (double)rec->bytes_written / 1024.0 / 1024.0, 557 (double)rec->bytes_written / 1024.0 / 1024.0,
593 output_name, 558 file->path,
594 rec->bytes_written / 24); 559 rec->bytes_written / 24);
595 560
596 return 0; 561 return 0;
@@ -618,6 +583,9 @@ static const struct branch_mode branch_modes[] = {
618 BRANCH_OPT("any_call", PERF_SAMPLE_BRANCH_ANY_CALL), 583 BRANCH_OPT("any_call", PERF_SAMPLE_BRANCH_ANY_CALL),
619 BRANCH_OPT("any_ret", PERF_SAMPLE_BRANCH_ANY_RETURN), 584 BRANCH_OPT("any_ret", PERF_SAMPLE_BRANCH_ANY_RETURN),
620 BRANCH_OPT("ind_call", PERF_SAMPLE_BRANCH_IND_CALL), 585 BRANCH_OPT("ind_call", PERF_SAMPLE_BRANCH_IND_CALL),
586 BRANCH_OPT("abort_tx", PERF_SAMPLE_BRANCH_ABORT_TX),
587 BRANCH_OPT("in_tx", PERF_SAMPLE_BRANCH_IN_TX),
588 BRANCH_OPT("no_tx", PERF_SAMPLE_BRANCH_NO_TX),
621 BRANCH_END 589 BRANCH_END
622}; 590};
623 591
@@ -684,7 +652,7 @@ error:
684 return ret; 652 return ret;
685} 653}
686 654
687#ifdef LIBUNWIND_SUPPORT 655#ifdef HAVE_LIBUNWIND_SUPPORT
688static int get_stack_size(char *str, unsigned long *_size) 656static int get_stack_size(char *str, unsigned long *_size)
689{ 657{
690 char *endptr; 658 char *endptr;
@@ -710,7 +678,7 @@ static int get_stack_size(char *str, unsigned long *_size)
710 max_size, str); 678 max_size, str);
711 return -1; 679 return -1;
712} 680}
713#endif /* LIBUNWIND_SUPPORT */ 681#endif /* HAVE_LIBUNWIND_SUPPORT */
714 682
715int record_parse_callchain(const char *arg, struct perf_record_opts *opts) 683int record_parse_callchain(const char *arg, struct perf_record_opts *opts)
716{ 684{
@@ -739,7 +707,7 @@ int record_parse_callchain(const char *arg, struct perf_record_opts *opts)
739 "needed for -g fp\n"); 707 "needed for -g fp\n");
740 break; 708 break;
741 709
742#ifdef LIBUNWIND_SUPPORT 710#ifdef HAVE_LIBUNWIND_SUPPORT
743 /* Dwarf style */ 711 /* Dwarf style */
744 } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) { 712 } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
745 const unsigned long default_stack_dump_size = 8192; 713 const unsigned long default_stack_dump_size = 8192;
@@ -755,7 +723,7 @@ int record_parse_callchain(const char *arg, struct perf_record_opts *opts)
755 ret = get_stack_size(tok, &size); 723 ret = get_stack_size(tok, &size);
756 opts->stack_dump_size = size; 724 opts->stack_dump_size = size;
757 } 725 }
758#endif /* LIBUNWIND_SUPPORT */ 726#endif /* HAVE_LIBUNWIND_SUPPORT */
759 } else { 727 } else {
760 pr_err("callchain: Unknown --call-graph option " 728 pr_err("callchain: Unknown --call-graph option "
761 "value: %s\n", arg); 729 "value: %s\n", arg);
@@ -841,7 +809,7 @@ static struct perf_record record = {
841 809
842#define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace) recording: " 810#define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace) recording: "
843 811
844#ifdef LIBUNWIND_SUPPORT 812#ifdef HAVE_LIBUNWIND_SUPPORT
845const char record_callchain_help[] = CALLCHAIN_HELP "fp dwarf"; 813const char record_callchain_help[] = CALLCHAIN_HELP "fp dwarf";
846#else 814#else
847const char record_callchain_help[] = CALLCHAIN_HELP "fp"; 815const char record_callchain_help[] = CALLCHAIN_HELP "fp";
@@ -875,13 +843,14 @@ const struct option record_options[] = {
875 OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu", 843 OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu",
876 "list of cpus to monitor"), 844 "list of cpus to monitor"),
877 OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), 845 OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
878 OPT_STRING('o', "output", &record.output_name, "file", 846 OPT_STRING('o', "output", &record.file.path, "file",
879 "output file name"), 847 "output file name"),
880 OPT_BOOLEAN('i', "no-inherit", &record.opts.no_inherit, 848 OPT_BOOLEAN('i', "no-inherit", &record.opts.no_inherit,
881 "child tasks do not inherit counters"), 849 "child tasks do not inherit counters"),
882 OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), 850 OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"),
883 OPT_UINTEGER('m', "mmap-pages", &record.opts.mmap_pages, 851 OPT_CALLBACK('m', "mmap-pages", &record.opts.mmap_pages, "pages",
884 "number of mmap data pages"), 852 "number of mmap data pages",
853 perf_evlist__parse_mmap_pages),
885 OPT_BOOLEAN(0, "group", &record.opts.group, 854 OPT_BOOLEAN(0, "group", &record.opts.group,
886 "put the counters into a counter group"), 855 "put the counters into a counter group"),
887 OPT_CALLBACK_NOOPT('g', NULL, &record.opts, 856 OPT_CALLBACK_NOOPT('g', NULL, &record.opts,
@@ -920,6 +889,8 @@ const struct option record_options[] = {
920 parse_branch_stack), 889 parse_branch_stack),
921 OPT_BOOLEAN('W', "weight", &record.opts.sample_weight, 890 OPT_BOOLEAN('W', "weight", &record.opts.sample_weight,
922 "sample by weight (on special events only)"), 891 "sample by weight (on special events only)"),
892 OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction,
893 "sample transaction flags (special events only)"),
923 OPT_END() 894 OPT_END()
924}; 895};
925 896
@@ -989,20 +960,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
989 if (perf_evlist__create_maps(evsel_list, &rec->opts.target) < 0) 960 if (perf_evlist__create_maps(evsel_list, &rec->opts.target) < 0)
990 usage_with_options(record_usage, record_options); 961 usage_with_options(record_usage, record_options);
991 962
992 if (rec->opts.user_interval != ULLONG_MAX) 963 if (perf_record_opts__config(&rec->opts)) {
993 rec->opts.default_interval = rec->opts.user_interval;
994 if (rec->opts.user_freq != UINT_MAX)
995 rec->opts.freq = rec->opts.user_freq;
996
997 /*
998 * User specified count overrides default frequency.
999 */
1000 if (rec->opts.default_interval)
1001 rec->opts.freq = 0;
1002 else if (rec->opts.freq) {
1003 rec->opts.default_interval = rec->opts.freq;
1004 } else {
1005 ui__error("frequency and count are zero, aborting\n");
1006 err = -EINVAL; 964 err = -EINVAL;
1007 goto out_free_fd; 965 goto out_free_fd;
1008 } 966 }
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 72eae7498c09..8cf8e66ba594 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -33,8 +33,10 @@
33#include "util/thread.h" 33#include "util/thread.h"
34#include "util/sort.h" 34#include "util/sort.h"
35#include "util/hist.h" 35#include "util/hist.h"
36#include "util/data.h"
36#include "arch/common.h" 37#include "arch/common.h"
37 38
39#include <dlfcn.h>
38#include <linux/bitmap.h> 40#include <linux/bitmap.h>
39 41
40struct perf_report { 42struct perf_report {
@@ -47,6 +49,7 @@ struct perf_report {
47 bool show_threads; 49 bool show_threads;
48 bool inverted_callchain; 50 bool inverted_callchain;
49 bool mem_mode; 51 bool mem_mode;
52 int max_stack;
50 struct perf_read_values show_threads_values; 53 struct perf_read_values show_threads_values;
51 const char *pretty_printing_style; 54 const char *pretty_printing_style;
52 const char *cpu_list; 55 const char *cpu_list;
@@ -88,7 +91,8 @@ static int perf_report__add_mem_hist_entry(struct perf_tool *tool,
88 if ((sort__has_parent || symbol_conf.use_callchain) && 91 if ((sort__has_parent || symbol_conf.use_callchain) &&
89 sample->callchain) { 92 sample->callchain) {
90 err = machine__resolve_callchain(machine, evsel, al->thread, 93 err = machine__resolve_callchain(machine, evsel, al->thread,
91 sample, &parent, al); 94 sample, &parent, al,
95 rep->max_stack);
92 if (err) 96 if (err)
93 return err; 97 return err;
94 } 98 }
@@ -111,7 +115,8 @@ static int perf_report__add_mem_hist_entry(struct perf_tool *tool,
111 * and this is indirectly achieved by passing period=weight here 115 * and this is indirectly achieved by passing period=weight here
112 * and the he_stat__add_period() function. 116 * and the he_stat__add_period() function.
113 */ 117 */
114 he = __hists__add_mem_entry(&evsel->hists, al, parent, mi, cost, cost); 118 he = __hists__add_entry(&evsel->hists, al, parent, NULL, mi,
119 cost, cost, 0);
115 if (!he) 120 if (!he)
116 return -ENOMEM; 121 return -ENOMEM;
117 122
@@ -179,7 +184,8 @@ static int perf_report__add_branch_hist_entry(struct perf_tool *tool,
179 if ((sort__has_parent || symbol_conf.use_callchain) 184 if ((sort__has_parent || symbol_conf.use_callchain)
180 && sample->callchain) { 185 && sample->callchain) {
181 err = machine__resolve_callchain(machine, evsel, al->thread, 186 err = machine__resolve_callchain(machine, evsel, al->thread,
182 sample, &parent, al); 187 sample, &parent, al,
188 rep->max_stack);
183 if (err) 189 if (err)
184 return err; 190 return err;
185 } 191 }
@@ -195,12 +201,16 @@ static int perf_report__add_branch_hist_entry(struct perf_tool *tool,
195 201
196 err = -ENOMEM; 202 err = -ENOMEM;
197 203
204 /* overwrite the 'al' to branch-to info */
205 al->map = bi[i].to.map;
206 al->sym = bi[i].to.sym;
207 al->addr = bi[i].to.addr;
198 /* 208 /*
199 * The report shows the percentage of total branches captured 209 * The report shows the percentage of total branches captured
200 * and not events sampled. Thus we use a pseudo period of 1. 210 * and not events sampled. Thus we use a pseudo period of 1.
201 */ 211 */
202 he = __hists__add_branch_entry(&evsel->hists, al, parent, 212 he = __hists__add_entry(&evsel->hists, al, parent, &bi[i], NULL,
203 &bi[i], 1, 1); 213 1, 1, 0);
204 if (he) { 214 if (he) {
205 struct annotation *notes; 215 struct annotation *notes;
206 bx = he->branch_info; 216 bx = he->branch_info;
@@ -242,24 +252,28 @@ out:
242 return err; 252 return err;
243} 253}
244 254
245static int perf_evsel__add_hist_entry(struct perf_evsel *evsel, 255static int perf_evsel__add_hist_entry(struct perf_tool *tool,
256 struct perf_evsel *evsel,
246 struct addr_location *al, 257 struct addr_location *al,
247 struct perf_sample *sample, 258 struct perf_sample *sample,
248 struct machine *machine) 259 struct machine *machine)
249{ 260{
261 struct perf_report *rep = container_of(tool, struct perf_report, tool);
250 struct symbol *parent = NULL; 262 struct symbol *parent = NULL;
251 int err = 0; 263 int err = 0;
252 struct hist_entry *he; 264 struct hist_entry *he;
253 265
254 if ((sort__has_parent || symbol_conf.use_callchain) && sample->callchain) { 266 if ((sort__has_parent || symbol_conf.use_callchain) && sample->callchain) {
255 err = machine__resolve_callchain(machine, evsel, al->thread, 267 err = machine__resolve_callchain(machine, evsel, al->thread,
256 sample, &parent, al); 268 sample, &parent, al,
269 rep->max_stack);
257 if (err) 270 if (err)
258 return err; 271 return err;
259 } 272 }
260 273
261 he = __hists__add_entry(&evsel->hists, al, parent, sample->period, 274 he = __hists__add_entry(&evsel->hists, al, parent, NULL, NULL,
262 sample->weight); 275 sample->period, sample->weight,
276 sample->transaction);
263 if (he == NULL) 277 if (he == NULL)
264 return -ENOMEM; 278 return -ENOMEM;
265 279
@@ -330,7 +344,8 @@ static int process_sample_event(struct perf_tool *tool,
330 if (al.map != NULL) 344 if (al.map != NULL)
331 al.map->dso->hit = 1; 345 al.map->dso->hit = 1;
332 346
333 ret = perf_evsel__add_hist_entry(evsel, &al, sample, machine); 347 ret = perf_evsel__add_hist_entry(tool, evsel, &al, sample,
348 machine);
334 if (ret < 0) 349 if (ret < 0)
335 pr_debug("problem incrementing symbol period, skipping event\n"); 350 pr_debug("problem incrementing symbol period, skipping event\n");
336 } 351 }
@@ -364,10 +379,11 @@ static int process_read_event(struct perf_tool *tool,
364/* For pipe mode, sample_type is not currently set */ 379/* For pipe mode, sample_type is not currently set */
365static int perf_report__setup_sample_type(struct perf_report *rep) 380static int perf_report__setup_sample_type(struct perf_report *rep)
366{ 381{
367 struct perf_session *self = rep->session; 382 struct perf_session *session = rep->session;
368 u64 sample_type = perf_evlist__combined_sample_type(self->evlist); 383 u64 sample_type = perf_evlist__combined_sample_type(session->evlist);
384 bool is_pipe = perf_data_file__is_pipe(session->file);
369 385
370 if (!self->fd_pipe && !(sample_type & PERF_SAMPLE_CALLCHAIN)) { 386 if (!is_pipe && !(sample_type & PERF_SAMPLE_CALLCHAIN)) {
371 if (sort__has_parent) { 387 if (sort__has_parent) {
372 ui__error("Selected --sort parent, but no " 388 ui__error("Selected --sort parent, but no "
373 "callchain data. Did you call " 389 "callchain data. Did you call "
@@ -390,7 +406,7 @@ static int perf_report__setup_sample_type(struct perf_report *rep)
390 } 406 }
391 407
392 if (sort__mode == SORT_MODE__BRANCH) { 408 if (sort__mode == SORT_MODE__BRANCH) {
393 if (!self->fd_pipe && 409 if (!is_pipe &&
394 !(sample_type & PERF_SAMPLE_BRANCH_STACK)) { 410 !(sample_type & PERF_SAMPLE_BRANCH_STACK)) {
395 ui__error("Selected -b but no branch data. " 411 ui__error("Selected -b but no branch data. "
396 "Did you call perf record without -b?\n"); 412 "Did you call perf record without -b?\n");
@@ -407,14 +423,14 @@ static void sig_handler(int sig __maybe_unused)
407} 423}
408 424
409static size_t hists__fprintf_nr_sample_events(struct perf_report *rep, 425static size_t hists__fprintf_nr_sample_events(struct perf_report *rep,
410 struct hists *self, 426 struct hists *hists,
411 const char *evname, FILE *fp) 427 const char *evname, FILE *fp)
412{ 428{
413 size_t ret; 429 size_t ret;
414 char unit; 430 char unit;
415 unsigned long nr_samples = self->stats.nr_events[PERF_RECORD_SAMPLE]; 431 unsigned long nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE];
416 u64 nr_events = self->stats.total_period; 432 u64 nr_events = hists->stats.total_period;
417 struct perf_evsel *evsel = hists_to_evsel(self); 433 struct perf_evsel *evsel = hists_to_evsel(hists);
418 char buf[512]; 434 char buf[512];
419 size_t size = sizeof(buf); 435 size_t size = sizeof(buf);
420 436
@@ -486,6 +502,8 @@ static int __cmd_report(struct perf_report *rep)
486 struct map *kernel_map; 502 struct map *kernel_map;
487 struct kmap *kernel_kmap; 503 struct kmap *kernel_kmap;
488 const char *help = "For a higher level overview, try: perf report --sort comm,dso"; 504 const char *help = "For a higher level overview, try: perf report --sort comm,dso";
505 struct ui_progress prog;
506 struct perf_data_file *file = session->file;
489 507
490 signal(SIGINT, sig_handler); 508 signal(SIGINT, sig_handler);
491 509
@@ -547,13 +565,19 @@ static int __cmd_report(struct perf_report *rep)
547 } 565 }
548 566
549 nr_samples = 0; 567 nr_samples = 0;
568 list_for_each_entry(pos, &session->evlist->entries, node)
569 nr_samples += pos->hists.nr_entries;
570
571 ui_progress__init(&prog, nr_samples, "Merging related events...");
572
573 nr_samples = 0;
550 list_for_each_entry(pos, &session->evlist->entries, node) { 574 list_for_each_entry(pos, &session->evlist->entries, node) {
551 struct hists *hists = &pos->hists; 575 struct hists *hists = &pos->hists;
552 576
553 if (pos->idx == 0) 577 if (pos->idx == 0)
554 hists->symbol_filter_str = rep->symbol_filter_str; 578 hists->symbol_filter_str = rep->symbol_filter_str;
555 579
556 hists__collapse_resort(hists); 580 hists__collapse_resort(hists, &prog);
557 nr_samples += hists->stats.nr_events[PERF_RECORD_SAMPLE]; 581 nr_samples += hists->stats.nr_events[PERF_RECORD_SAMPLE];
558 582
559 /* Non-group events are considered as leader */ 583 /* Non-group events are considered as leader */
@@ -565,12 +589,13 @@ static int __cmd_report(struct perf_report *rep)
565 hists__link(leader_hists, hists); 589 hists__link(leader_hists, hists);
566 } 590 }
567 } 591 }
592 ui_progress__finish();
568 593
569 if (session_done()) 594 if (session_done())
570 return 0; 595 return 0;
571 596
572 if (nr_samples == 0) { 597 if (nr_samples == 0) {
573 ui__error("The %s file has no samples!\n", session->filename); 598 ui__error("The %s file has no samples!\n", file->path);
574 return 0; 599 return 0;
575 } 600 }
576 601
@@ -591,8 +616,19 @@ static int __cmd_report(struct perf_report *rep)
591 ret = 0; 616 ret = 0;
592 617
593 } else if (use_browser == 2) { 618 } else if (use_browser == 2) {
594 perf_evlist__gtk_browse_hists(session->evlist, help, 619 int (*hist_browser)(struct perf_evlist *,
595 NULL, rep->min_percent); 620 const char *,
621 struct hist_browser_timer *,
622 float min_pcnt);
623
624 hist_browser = dlsym(perf_gtk_handle,
625 "perf_evlist__gtk_browse_hists");
626 if (hist_browser == NULL) {
627 ui__error("GTK browser not found!\n");
628 return ret;
629 }
630 hist_browser(session->evlist, help, NULL,
631 rep->min_percent);
596 } 632 }
597 } else 633 } else
598 perf_evlist__tty_browse_hists(session->evlist, rep, help); 634 perf_evlist__tty_browse_hists(session->evlist, rep, help);
@@ -757,6 +793,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
757 .ordered_samples = true, 793 .ordered_samples = true,
758 .ordering_requires_timestamps = true, 794 .ordering_requires_timestamps = true,
759 }, 795 },
796 .max_stack = PERF_MAX_STACK_DEPTH,
760 .pretty_printing_style = "normal", 797 .pretty_printing_style = "normal",
761 }; 798 };
762 const struct option options[] = { 799 const struct option options[] = {
@@ -787,7 +824,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
787 "sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline," 824 "sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline,"
788 " dso_to, dso_from, symbol_to, symbol_from, mispredict," 825 " dso_to, dso_from, symbol_to, symbol_from, mispredict,"
789 " weight, local_weight, mem, symbol_daddr, dso_daddr, tlb, " 826 " weight, local_weight, mem, symbol_daddr, dso_daddr, tlb, "
790 "snoop, locked"), 827 "snoop, locked, abort, in_tx, transaction"),
791 OPT_BOOLEAN(0, "showcpuutilization", &symbol_conf.show_cpu_utilization, 828 OPT_BOOLEAN(0, "showcpuutilization", &symbol_conf.show_cpu_utilization,
792 "Show sample percentage for different cpu modes"), 829 "Show sample percentage for different cpu modes"),
793 OPT_STRING('p', "parent", &parent_pattern, "regex", 830 OPT_STRING('p', "parent", &parent_pattern, "regex",
@@ -797,6 +834,10 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
797 OPT_CALLBACK_DEFAULT('g', "call-graph", &report, "output_type,min_percent[,print_limit],call_order", 834 OPT_CALLBACK_DEFAULT('g', "call-graph", &report, "output_type,min_percent[,print_limit],call_order",
798 "Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold, optional print limit, callchain order, key (function or address). " 835 "Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold, optional print limit, callchain order, key (function or address). "
799 "Default: fractal,0.5,callee,function", &parse_callchain_opt, callchain_default_opt), 836 "Default: fractal,0.5,callee,function", &parse_callchain_opt, callchain_default_opt),
837 OPT_INTEGER(0, "max-stack", &report.max_stack,
838 "Set the maximum stack depth when parsing the callchain, "
839 "anything beyond the specified depth will be ignored. "
840 "Default: " __stringify(PERF_MAX_STACK_DEPTH)),
800 OPT_BOOLEAN('G', "inverted", &report.inverted_callchain, 841 OPT_BOOLEAN('G', "inverted", &report.inverted_callchain,
801 "alias for inverted call graph"), 842 "alias for inverted call graph"),
802 OPT_CALLBACK(0, "ignore-callees", NULL, "regex", 843 OPT_CALLBACK(0, "ignore-callees", NULL, "regex",
@@ -845,6 +886,9 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
845 "Don't show entries under that percent", parse_percent_limit), 886 "Don't show entries under that percent", parse_percent_limit),
846 OPT_END() 887 OPT_END()
847 }; 888 };
889 struct perf_data_file file = {
890 .mode = PERF_DATA_MODE_READ,
891 };
848 892
849 perf_config(perf_report_config, &report); 893 perf_config(perf_report_config, &report);
850 894
@@ -867,16 +911,11 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
867 input_name = "perf.data"; 911 input_name = "perf.data";
868 } 912 }
869 913
870 if (strcmp(input_name, "-") != 0) 914 file.path = input_name;
871 setup_browser(true); 915 file.force = report.force;
872 else {
873 use_browser = 0;
874 perf_hpp__init();
875 }
876 916
877repeat: 917repeat:
878 session = perf_session__new(input_name, O_RDONLY, 918 session = perf_session__new(&file, false, &report.tool);
879 report.force, false, &report.tool);
880 if (session == NULL) 919 if (session == NULL)
881 return -ENOMEM; 920 return -ENOMEM;
882 921
@@ -914,8 +953,22 @@ repeat:
914 sort_order = "local_weight,mem,sym,dso,symbol_daddr,dso_daddr,snoop,tlb,locked"; 953 sort_order = "local_weight,mem,sym,dso,symbol_daddr,dso_daddr,snoop,tlb,locked";
915 } 954 }
916 955
917 if (setup_sorting() < 0) 956 if (setup_sorting() < 0) {
918 usage_with_options(report_usage, options); 957 parse_options_usage(report_usage, options, "s", 1);
958 goto error;
959 }
960
961 if (parent_pattern != default_parent_pattern) {
962 if (sort_dimension__add("parent") < 0)
963 goto error;
964 }
965
966 if (strcmp(input_name, "-") != 0)
967 setup_browser(true);
968 else {
969 use_browser = 0;
970 perf_hpp__init();
971 }
919 972
920 /* 973 /*
921 * Only in the TUI browser we are doing integrated annotation, 974 * Only in the TUI browser we are doing integrated annotation,
@@ -946,11 +999,6 @@ repeat:
946 if (symbol__init() < 0) 999 if (symbol__init() < 0)
947 goto error; 1000 goto error;
948 1001
949 if (parent_pattern != default_parent_pattern) {
950 if (sort_dimension__add("parent") < 0)
951 goto error;
952 }
953
954 if (argc) { 1002 if (argc) {
955 /* 1003 /*
956 * Special case: if there's an argument left then assume that 1004 * Special case: if there's an argument left then assume that
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index d8c51b2f263f..0f3c65518a2c 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -737,12 +737,12 @@ static int replay_fork_event(struct perf_sched *sched,
737 737
738 if (verbose) { 738 if (verbose) {
739 printf("fork event\n"); 739 printf("fork event\n");
740 printf("... parent: %s/%d\n", parent->comm, parent->tid); 740 printf("... parent: %s/%d\n", thread__comm_str(parent), parent->tid);
741 printf("... child: %s/%d\n", child->comm, child->tid); 741 printf("... child: %s/%d\n", thread__comm_str(child), child->tid);
742 } 742 }
743 743
744 register_pid(sched, parent->tid, parent->comm); 744 register_pid(sched, parent->tid, thread__comm_str(parent));
745 register_pid(sched, child->tid, child->comm); 745 register_pid(sched, child->tid, thread__comm_str(child));
746 return 0; 746 return 0;
747} 747}
748 748
@@ -1077,7 +1077,7 @@ static int latency_migrate_task_event(struct perf_sched *sched,
1077 if (!atoms) { 1077 if (!atoms) {
1078 if (thread_atoms_insert(sched, migrant)) 1078 if (thread_atoms_insert(sched, migrant))
1079 return -1; 1079 return -1;
1080 register_pid(sched, migrant->tid, migrant->comm); 1080 register_pid(sched, migrant->tid, thread__comm_str(migrant));
1081 atoms = thread_atoms_search(&sched->atom_root, migrant, &sched->cmp_pid); 1081 atoms = thread_atoms_search(&sched->atom_root, migrant, &sched->cmp_pid);
1082 if (!atoms) { 1082 if (!atoms) {
1083 pr_err("migration-event: Internal tree error"); 1083 pr_err("migration-event: Internal tree error");
@@ -1111,13 +1111,13 @@ static void output_lat_thread(struct perf_sched *sched, struct work_atoms *work_
1111 /* 1111 /*
1112 * Ignore idle threads: 1112 * Ignore idle threads:
1113 */ 1113 */
1114 if (!strcmp(work_list->thread->comm, "swapper")) 1114 if (!strcmp(thread__comm_str(work_list->thread), "swapper"))
1115 return; 1115 return;
1116 1116
1117 sched->all_runtime += work_list->total_runtime; 1117 sched->all_runtime += work_list->total_runtime;
1118 sched->all_count += work_list->nb_atoms; 1118 sched->all_count += work_list->nb_atoms;
1119 1119
1120 ret = printf(" %s:%d ", work_list->thread->comm, work_list->thread->tid); 1120 ret = printf(" %s:%d ", thread__comm_str(work_list->thread), work_list->thread->tid);
1121 1121
1122 for (i = 0; i < 24 - ret; i++) 1122 for (i = 0; i < 24 - ret; i++)
1123 printf(" "); 1123 printf(" ");
@@ -1334,7 +1334,7 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,
1334 printf(" %12.6f secs ", (double)timestamp/1e9); 1334 printf(" %12.6f secs ", (double)timestamp/1e9);
1335 if (new_shortname) { 1335 if (new_shortname) {
1336 printf("%s => %s:%d\n", 1336 printf("%s => %s:%d\n",
1337 sched_in->shortname, sched_in->comm, sched_in->tid); 1337 sched_in->shortname, thread__comm_str(sched_in), sched_in->tid);
1338 } else { 1338 } else {
1339 printf("\n"); 1339 printf("\n");
1340 } 1340 }
@@ -1427,8 +1427,8 @@ static int perf_sched__process_tracepoint_sample(struct perf_tool *tool __maybe_
1427 evsel->hists.stats.total_period += sample->period; 1427 evsel->hists.stats.total_period += sample->period;
1428 hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); 1428 hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
1429 1429
1430 if (evsel->handler.func != NULL) { 1430 if (evsel->handler != NULL) {
1431 tracepoint_handler f = evsel->handler.func; 1431 tracepoint_handler f = evsel->handler;
1432 err = f(tool, evsel, sample, machine); 1432 err = f(tool, evsel, sample, machine);
1433 } 1433 }
1434 1434
@@ -1446,8 +1446,12 @@ static int perf_sched__read_events(struct perf_sched *sched,
1446 { "sched:sched_migrate_task", process_sched_migrate_task_event, }, 1446 { "sched:sched_migrate_task", process_sched_migrate_task_event, },
1447 }; 1447 };
1448 struct perf_session *session; 1448 struct perf_session *session;
1449 struct perf_data_file file = {
1450 .path = input_name,
1451 .mode = PERF_DATA_MODE_READ,
1452 };
1449 1453
1450 session = perf_session__new(input_name, O_RDONLY, 0, false, &sched->tool); 1454 session = perf_session__new(&file, false, &sched->tool);
1451 if (session == NULL) { 1455 if (session == NULL) {
1452 pr_debug("No Memory for session\n"); 1456 pr_debug("No Memory for session\n");
1453 return -1; 1457 return -1;
@@ -1651,29 +1655,27 @@ static int __cmd_record(int argc, const char **argv)
1651 return cmd_record(i, rec_argv, NULL); 1655 return cmd_record(i, rec_argv, NULL);
1652} 1656}
1653 1657
1654static const char default_sort_order[] = "avg, max, switch, runtime";
1655static struct perf_sched sched = {
1656 .tool = {
1657 .sample = perf_sched__process_tracepoint_sample,
1658 .comm = perf_event__process_comm,
1659 .lost = perf_event__process_lost,
1660 .fork = perf_sched__process_fork_event,
1661 .ordered_samples = true,
1662 },
1663 .cmp_pid = LIST_HEAD_INIT(sched.cmp_pid),
1664 .sort_list = LIST_HEAD_INIT(sched.sort_list),
1665 .start_work_mutex = PTHREAD_MUTEX_INITIALIZER,
1666 .work_done_wait_mutex = PTHREAD_MUTEX_INITIALIZER,
1667 .curr_pid = { [0 ... MAX_CPUS - 1] = -1 },
1668 .sort_order = default_sort_order,
1669 .replay_repeat = 10,
1670 .profile_cpu = -1,
1671 .next_shortname1 = 'A',
1672 .next_shortname2 = '0',
1673};
1674
1675int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused) 1658int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
1676{ 1659{
1660 const char default_sort_order[] = "avg, max, switch, runtime";
1661 struct perf_sched sched = {
1662 .tool = {
1663 .sample = perf_sched__process_tracepoint_sample,
1664 .comm = perf_event__process_comm,
1665 .lost = perf_event__process_lost,
1666 .fork = perf_sched__process_fork_event,
1667 .ordered_samples = true,
1668 },
1669 .cmp_pid = LIST_HEAD_INIT(sched.cmp_pid),
1670 .sort_list = LIST_HEAD_INIT(sched.sort_list),
1671 .start_work_mutex = PTHREAD_MUTEX_INITIALIZER,
1672 .work_done_wait_mutex = PTHREAD_MUTEX_INITIALIZER,
1673 .sort_order = default_sort_order,
1674 .replay_repeat = 10,
1675 .profile_cpu = -1,
1676 .next_shortname1 = 'A',
1677 .next_shortname2 = '0',
1678 };
1677 const struct option latency_options[] = { 1679 const struct option latency_options[] = {
1678 OPT_STRING('s', "sort", &sched.sort_order, "key[,key2...]", 1680 OPT_STRING('s', "sort", &sched.sort_order, "key[,key2...]",
1679 "sort by key(s): runtime, switch, avg, max"), 1681 "sort by key(s): runtime, switch, avg, max"),
@@ -1729,6 +1731,10 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
1729 .switch_event = replay_switch_event, 1731 .switch_event = replay_switch_event,
1730 .fork_event = replay_fork_event, 1732 .fork_event = replay_fork_event,
1731 }; 1733 };
1734 unsigned int i;
1735
1736 for (i = 0; i < ARRAY_SIZE(sched.curr_pid); i++)
1737 sched.curr_pid[i] = -1;
1732 1738
1733 argc = parse_options(argc, argv, sched_options, sched_usage, 1739 argc = parse_options(argc, argv, sched_options, sched_usage,
1734 PARSE_OPT_STOP_AT_NON_OPTION); 1740 PARSE_OPT_STOP_AT_NON_OPTION);
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 9c333ff3dfeb..baf17989a216 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -15,6 +15,7 @@
15#include "util/evlist.h" 15#include "util/evlist.h"
16#include "util/evsel.h" 16#include "util/evsel.h"
17#include "util/sort.h" 17#include "util/sort.h"
18#include "util/data.h"
18#include <linux/bitmap.h> 19#include <linux/bitmap.h>
19 20
20static char const *script_name; 21static char const *script_name;
@@ -228,6 +229,24 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
228 return 0; 229 return 0;
229} 230}
230 231
232static void set_print_ip_opts(struct perf_event_attr *attr)
233{
234 unsigned int type = attr->type;
235
236 output[type].print_ip_opts = 0;
237 if (PRINT_FIELD(IP))
238 output[type].print_ip_opts |= PRINT_IP_OPT_IP;
239
240 if (PRINT_FIELD(SYM))
241 output[type].print_ip_opts |= PRINT_IP_OPT_SYM;
242
243 if (PRINT_FIELD(DSO))
244 output[type].print_ip_opts |= PRINT_IP_OPT_DSO;
245
246 if (PRINT_FIELD(SYMOFFSET))
247 output[type].print_ip_opts |= PRINT_IP_OPT_SYMOFFSET;
248}
249
231/* 250/*
232 * verify all user requested events exist and the samples 251 * verify all user requested events exist and the samples
233 * have the expected data 252 * have the expected data
@@ -236,7 +255,6 @@ static int perf_session__check_output_opt(struct perf_session *session)
236{ 255{
237 int j; 256 int j;
238 struct perf_evsel *evsel; 257 struct perf_evsel *evsel;
239 struct perf_event_attr *attr;
240 258
241 for (j = 0; j < PERF_TYPE_MAX; ++j) { 259 for (j = 0; j < PERF_TYPE_MAX; ++j) {
242 evsel = perf_session__find_first_evtype(session, j); 260 evsel = perf_session__find_first_evtype(session, j);
@@ -259,20 +277,7 @@ static int perf_session__check_output_opt(struct perf_session *session)
259 if (evsel == NULL) 277 if (evsel == NULL)
260 continue; 278 continue;
261 279
262 attr = &evsel->attr; 280 set_print_ip_opts(&evsel->attr);
263
264 output[j].print_ip_opts = 0;
265 if (PRINT_FIELD(IP))
266 output[j].print_ip_opts |= PRINT_IP_OPT_IP;
267
268 if (PRINT_FIELD(SYM))
269 output[j].print_ip_opts |= PRINT_IP_OPT_SYM;
270
271 if (PRINT_FIELD(DSO))
272 output[j].print_ip_opts |= PRINT_IP_OPT_DSO;
273
274 if (PRINT_FIELD(SYMOFFSET))
275 output[j].print_ip_opts |= PRINT_IP_OPT_SYMOFFSET;
276 } 281 }
277 282
278 return 0; 283 return 0;
@@ -290,11 +295,11 @@ static void print_sample_start(struct perf_sample *sample,
290 295
291 if (PRINT_FIELD(COMM)) { 296 if (PRINT_FIELD(COMM)) {
292 if (latency_format) 297 if (latency_format)
293 printf("%8.8s ", thread->comm); 298 printf("%8.8s ", thread__comm_str(thread));
294 else if (PRINT_FIELD(IP) && symbol_conf.use_callchain) 299 else if (PRINT_FIELD(IP) && symbol_conf.use_callchain)
295 printf("%s ", thread->comm); 300 printf("%s ", thread__comm_str(thread));
296 else 301 else
297 printf("%16s ", thread->comm); 302 printf("%16s ", thread__comm_str(thread));
298 } 303 }
299 304
300 if (PRINT_FIELD(PID) && PRINT_FIELD(TID)) 305 if (PRINT_FIELD(PID) && PRINT_FIELD(TID))
@@ -409,7 +414,9 @@ static void print_sample_bts(union perf_event *event,
409 printf(" => "); 414 printf(" => ");
410 415
411 /* print branch_to information */ 416 /* print branch_to information */
412 if (PRINT_FIELD(ADDR)) 417 if (PRINT_FIELD(ADDR) ||
418 ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) &&
419 !output[attr->type].user_set))
413 print_sample_addr(event, sample, machine, thread, attr); 420 print_sample_addr(event, sample, machine, thread, attr);
414 421
415 printf("\n"); 422 printf("\n");
@@ -539,32 +546,51 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
539 return 0; 546 return 0;
540} 547}
541 548
542static struct perf_tool perf_script = { 549struct perf_script {
543 .sample = process_sample_event, 550 struct perf_tool tool;
544 .mmap = perf_event__process_mmap, 551 struct perf_session *session;
545 .mmap2 = perf_event__process_mmap2,
546 .comm = perf_event__process_comm,
547 .exit = perf_event__process_exit,
548 .fork = perf_event__process_fork,
549 .attr = perf_event__process_attr,
550 .tracing_data = perf_event__process_tracing_data,
551 .build_id = perf_event__process_build_id,
552 .ordered_samples = true,
553 .ordering_requires_timestamps = true,
554}; 552};
555 553
554static int process_attr(struct perf_tool *tool, union perf_event *event,
555 struct perf_evlist **pevlist)
556{
557 struct perf_script *scr = container_of(tool, struct perf_script, tool);
558 struct perf_evlist *evlist;
559 struct perf_evsel *evsel, *pos;
560 int err;
561
562 err = perf_event__process_attr(tool, event, pevlist);
563 if (err)
564 return err;
565
566 evlist = *pevlist;
567 evsel = perf_evlist__last(*pevlist);
568
569 if (evsel->attr.type >= PERF_TYPE_MAX)
570 return 0;
571
572 list_for_each_entry(pos, &evlist->entries, node) {
573 if (pos->attr.type == evsel->attr.type && pos != evsel)
574 return 0;
575 }
576
577 set_print_ip_opts(&evsel->attr);
578
579 return perf_evsel__check_attr(evsel, scr->session);
580}
581
556static void sig_handler(int sig __maybe_unused) 582static void sig_handler(int sig __maybe_unused)
557{ 583{
558 session_done = 1; 584 session_done = 1;
559} 585}
560 586
561static int __cmd_script(struct perf_session *session) 587static int __cmd_script(struct perf_script *script)
562{ 588{
563 int ret; 589 int ret;
564 590
565 signal(SIGINT, sig_handler); 591 signal(SIGINT, sig_handler);
566 592
567 ret = perf_session__process_events(session, &perf_script); 593 ret = perf_session__process_events(script->session, &script->tool);
568 594
569 if (debug_mode) 595 if (debug_mode)
570 pr_err("Misordered timestamps: %" PRIu64 "\n", nr_unordered); 596 pr_err("Misordered timestamps: %" PRIu64 "\n", nr_unordered);
@@ -1113,10 +1139,14 @@ int find_scripts(char **scripts_array, char **scripts_path_array)
1113 char scripts_path[MAXPATHLEN], lang_path[MAXPATHLEN]; 1139 char scripts_path[MAXPATHLEN], lang_path[MAXPATHLEN];
1114 DIR *scripts_dir, *lang_dir; 1140 DIR *scripts_dir, *lang_dir;
1115 struct perf_session *session; 1141 struct perf_session *session;
1142 struct perf_data_file file = {
1143 .path = input_name,
1144 .mode = PERF_DATA_MODE_READ,
1145 };
1116 char *temp; 1146 char *temp;
1117 int i = 0; 1147 int i = 0;
1118 1148
1119 session = perf_session__new(input_name, O_RDONLY, 0, false, NULL); 1149 session = perf_session__new(&file, false, NULL);
1120 if (!session) 1150 if (!session)
1121 return -1; 1151 return -1;
1122 1152
@@ -1266,6 +1296,21 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1266 char *script_path = NULL; 1296 char *script_path = NULL;
1267 const char **__argv; 1297 const char **__argv;
1268 int i, j, err; 1298 int i, j, err;
1299 struct perf_script script = {
1300 .tool = {
1301 .sample = process_sample_event,
1302 .mmap = perf_event__process_mmap,
1303 .mmap2 = perf_event__process_mmap2,
1304 .comm = perf_event__process_comm,
1305 .exit = perf_event__process_exit,
1306 .fork = perf_event__process_fork,
1307 .attr = process_attr,
1308 .tracing_data = perf_event__process_tracing_data,
1309 .build_id = perf_event__process_build_id,
1310 .ordered_samples = true,
1311 .ordering_requires_timestamps = true,
1312 },
1313 };
1269 const struct option options[] = { 1314 const struct option options[] = {
1270 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 1315 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
1271 "dump raw trace in ASCII"), 1316 "dump raw trace in ASCII"),
@@ -1317,12 +1362,17 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1317 "perf script [<options>] <top-script> [script-args]", 1362 "perf script [<options>] <top-script> [script-args]",
1318 NULL 1363 NULL
1319 }; 1364 };
1365 struct perf_data_file file = {
1366 .mode = PERF_DATA_MODE_READ,
1367 };
1320 1368
1321 setup_scripting(); 1369 setup_scripting();
1322 1370
1323 argc = parse_options(argc, argv, options, script_usage, 1371 argc = parse_options(argc, argv, options, script_usage,
1324 PARSE_OPT_STOP_AT_NON_OPTION); 1372 PARSE_OPT_STOP_AT_NON_OPTION);
1325 1373
1374 file.path = input_name;
1375
1326 if (argc > 1 && !strncmp(argv[0], "rec", strlen("rec"))) { 1376 if (argc > 1 && !strncmp(argv[0], "rec", strlen("rec"))) {
1327 rec_script_path = get_script_path(argv[1], RECORD_SUFFIX); 1377 rec_script_path = get_script_path(argv[1], RECORD_SUFFIX);
1328 if (!rec_script_path) 1378 if (!rec_script_path)
@@ -1486,11 +1536,12 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1486 if (!script_name) 1536 if (!script_name)
1487 setup_pager(); 1537 setup_pager();
1488 1538
1489 session = perf_session__new(input_name, O_RDONLY, 0, false, 1539 session = perf_session__new(&file, false, &script.tool);
1490 &perf_script);
1491 if (session == NULL) 1540 if (session == NULL)
1492 return -ENOMEM; 1541 return -ENOMEM;
1493 1542
1543 script.session = session;
1544
1494 if (cpu_list) { 1545 if (cpu_list) {
1495 if (perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap)) 1546 if (perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap))
1496 return -1; 1547 return -1;
@@ -1514,7 +1565,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1514 return -1; 1565 return -1;
1515 } 1566 }
1516 1567
1517 input = open(session->filename, O_RDONLY); /* input_name */ 1568 input = open(file.path, O_RDONLY); /* input_name */
1518 if (input < 0) { 1569 if (input < 0) {
1519 perror("failed to open file"); 1570 perror("failed to open file");
1520 return -1; 1571 return -1;
@@ -1554,7 +1605,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1554 if (err < 0) 1605 if (err < 0)
1555 goto out; 1606 goto out;
1556 1607
1557 err = __cmd_script(session); 1608 err = __cmd_script(&script);
1558 1609
1559 perf_session__delete(session); 1610 perf_session__delete(session);
1560 cleanup_scripting(); 1611 cleanup_scripting();
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 5098f144b92d..0fc1c941a73c 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -46,6 +46,7 @@
46#include "util/util.h" 46#include "util/util.h"
47#include "util/parse-options.h" 47#include "util/parse-options.h"
48#include "util/parse-events.h" 48#include "util/parse-events.h"
49#include "util/pmu.h"
49#include "util/event.h" 50#include "util/event.h"
50#include "util/evlist.h" 51#include "util/evlist.h"
51#include "util/evsel.h" 52#include "util/evsel.h"
@@ -70,6 +71,41 @@ static void print_counter_aggr(struct perf_evsel *counter, char *prefix);
70static void print_counter(struct perf_evsel *counter, char *prefix); 71static void print_counter(struct perf_evsel *counter, char *prefix);
71static void print_aggr(char *prefix); 72static void print_aggr(char *prefix);
72 73
74/* Default events used for perf stat -T */
75static const char * const transaction_attrs[] = {
76 "task-clock",
77 "{"
78 "instructions,"
79 "cycles,"
80 "cpu/cycles-t/,"
81 "cpu/tx-start/,"
82 "cpu/el-start/,"
83 "cpu/cycles-ct/"
84 "}"
85};
86
87/* More limited version when the CPU does not have all events. */
88static const char * const transaction_limited_attrs[] = {
89 "task-clock",
90 "{"
91 "instructions,"
92 "cycles,"
93 "cpu/cycles-t/,"
94 "cpu/tx-start/"
95 "}"
96};
97
98/* must match transaction_attrs and the beginning limited_attrs */
99enum {
100 T_TASK_CLOCK,
101 T_INSTRUCTIONS,
102 T_CYCLES,
103 T_CYCLES_IN_TX,
104 T_TRANSACTION_START,
105 T_ELISION_START,
106 T_CYCLES_IN_TX_CP,
107};
108
73static struct perf_evlist *evsel_list; 109static struct perf_evlist *evsel_list;
74 110
75static struct perf_target target = { 111static struct perf_target target = {
@@ -90,6 +126,7 @@ static enum aggr_mode aggr_mode = AGGR_GLOBAL;
90static volatile pid_t child_pid = -1; 126static volatile pid_t child_pid = -1;
91static bool null_run = false; 127static bool null_run = false;
92static int detailed_run = 0; 128static int detailed_run = 0;
129static bool transaction_run;
93static bool big_num = true; 130static bool big_num = true;
94static int big_num_opt = -1; 131static int big_num_opt = -1;
95static const char *csv_sep = NULL; 132static const char *csv_sep = NULL;
@@ -214,7 +251,10 @@ static struct stats runtime_l1_icache_stats[MAX_NR_CPUS];
214static struct stats runtime_ll_cache_stats[MAX_NR_CPUS]; 251static struct stats runtime_ll_cache_stats[MAX_NR_CPUS];
215static struct stats runtime_itlb_cache_stats[MAX_NR_CPUS]; 252static struct stats runtime_itlb_cache_stats[MAX_NR_CPUS];
216static struct stats runtime_dtlb_cache_stats[MAX_NR_CPUS]; 253static struct stats runtime_dtlb_cache_stats[MAX_NR_CPUS];
254static struct stats runtime_cycles_in_tx_stats[MAX_NR_CPUS];
217static struct stats walltime_nsecs_stats; 255static struct stats walltime_nsecs_stats;
256static struct stats runtime_transaction_stats[MAX_NR_CPUS];
257static struct stats runtime_elision_stats[MAX_NR_CPUS];
218 258
219static void perf_stat__reset_stats(struct perf_evlist *evlist) 259static void perf_stat__reset_stats(struct perf_evlist *evlist)
220{ 260{
@@ -236,6 +276,11 @@ static void perf_stat__reset_stats(struct perf_evlist *evlist)
236 memset(runtime_ll_cache_stats, 0, sizeof(runtime_ll_cache_stats)); 276 memset(runtime_ll_cache_stats, 0, sizeof(runtime_ll_cache_stats));
237 memset(runtime_itlb_cache_stats, 0, sizeof(runtime_itlb_cache_stats)); 277 memset(runtime_itlb_cache_stats, 0, sizeof(runtime_itlb_cache_stats));
238 memset(runtime_dtlb_cache_stats, 0, sizeof(runtime_dtlb_cache_stats)); 278 memset(runtime_dtlb_cache_stats, 0, sizeof(runtime_dtlb_cache_stats));
279 memset(runtime_cycles_in_tx_stats, 0,
280 sizeof(runtime_cycles_in_tx_stats));
281 memset(runtime_transaction_stats, 0,
282 sizeof(runtime_transaction_stats));
283 memset(runtime_elision_stats, 0, sizeof(runtime_elision_stats));
239 memset(&walltime_nsecs_stats, 0, sizeof(walltime_nsecs_stats)); 284 memset(&walltime_nsecs_stats, 0, sizeof(walltime_nsecs_stats));
240} 285}
241 286
@@ -274,6 +319,29 @@ static inline int nsec_counter(struct perf_evsel *evsel)
274 return 0; 319 return 0;
275} 320}
276 321
322static struct perf_evsel *nth_evsel(int n)
323{
324 static struct perf_evsel **array;
325 static int array_len;
326 struct perf_evsel *ev;
327 int j;
328
329 /* Assumes this only called when evsel_list does not change anymore. */
330 if (!array) {
331 list_for_each_entry(ev, &evsel_list->entries, node)
332 array_len++;
333 array = malloc(array_len * sizeof(void *));
334 if (!array)
335 exit(ENOMEM);
336 j = 0;
337 list_for_each_entry(ev, &evsel_list->entries, node)
338 array[j++] = ev;
339 }
340 if (n < array_len)
341 return array[n];
342 return NULL;
343}
344
277/* 345/*
278 * Update various tracking values we maintain to print 346 * Update various tracking values we maintain to print
279 * more semantic information such as miss/hit ratios, 347 * more semantic information such as miss/hit ratios,
@@ -285,6 +353,15 @@ static void update_shadow_stats(struct perf_evsel *counter, u64 *count)
285 update_stats(&runtime_nsecs_stats[0], count[0]); 353 update_stats(&runtime_nsecs_stats[0], count[0]);
286 else if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES)) 354 else if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES))
287 update_stats(&runtime_cycles_stats[0], count[0]); 355 update_stats(&runtime_cycles_stats[0], count[0]);
356 else if (transaction_run &&
357 perf_evsel__cmp(counter, nth_evsel(T_CYCLES_IN_TX)))
358 update_stats(&runtime_cycles_in_tx_stats[0], count[0]);
359 else if (transaction_run &&
360 perf_evsel__cmp(counter, nth_evsel(T_TRANSACTION_START)))
361 update_stats(&runtime_transaction_stats[0], count[0]);
362 else if (transaction_run &&
363 perf_evsel__cmp(counter, nth_evsel(T_ELISION_START)))
364 update_stats(&runtime_elision_stats[0], count[0]);
288 else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_FRONTEND)) 365 else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_FRONTEND))
289 update_stats(&runtime_stalled_cycles_front_stats[0], count[0]); 366 update_stats(&runtime_stalled_cycles_front_stats[0], count[0]);
290 else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_BACKEND)) 367 else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_BACKEND))
@@ -629,10 +706,13 @@ static void nsec_printout(int cpu, int nr, struct perf_evsel *evsel, double avg)
629{ 706{
630 double msecs = avg / 1e6; 707 double msecs = avg / 1e6;
631 const char *fmt = csv_output ? "%.6f%s%s" : "%18.6f%s%-25s"; 708 const char *fmt = csv_output ? "%.6f%s%s" : "%18.6f%s%-25s";
709 char name[25];
632 710
633 aggr_printout(evsel, cpu, nr); 711 aggr_printout(evsel, cpu, nr);
634 712
635 fprintf(output, fmt, msecs, csv_sep, perf_evsel__name(evsel)); 713 scnprintf(name, sizeof(name), "%s%s",
714 perf_evsel__name(evsel), csv_output ? "" : " (msec)");
715 fprintf(output, fmt, msecs, csv_sep, name);
636 716
637 if (evsel->cgrp) 717 if (evsel->cgrp)
638 fprintf(output, "%s%s", csv_sep, evsel->cgrp->name); 718 fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
@@ -828,7 +908,7 @@ static void print_ll_cache_misses(int cpu,
828 908
829static void abs_printout(int cpu, int nr, struct perf_evsel *evsel, double avg) 909static void abs_printout(int cpu, int nr, struct perf_evsel *evsel, double avg)
830{ 910{
831 double total, ratio = 0.0; 911 double total, ratio = 0.0, total2;
832 const char *fmt; 912 const char *fmt;
833 913
834 if (csv_output) 914 if (csv_output)
@@ -853,11 +933,10 @@ static void abs_printout(int cpu, int nr, struct perf_evsel *evsel, double avg)
853 933
854 if (perf_evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)) { 934 if (perf_evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)) {
855 total = avg_stats(&runtime_cycles_stats[cpu]); 935 total = avg_stats(&runtime_cycles_stats[cpu]);
856 if (total) 936 if (total) {
857 ratio = avg / total; 937 ratio = avg / total;
858 938 fprintf(output, " # %5.2f insns per cycle ", ratio);
859 fprintf(output, " # %5.2f insns per cycle ", ratio); 939 }
860
861 total = avg_stats(&runtime_stalled_cycles_front_stats[cpu]); 940 total = avg_stats(&runtime_stalled_cycles_front_stats[cpu]);
862 total = max(total, avg_stats(&runtime_stalled_cycles_back_stats[cpu])); 941 total = max(total, avg_stats(&runtime_stalled_cycles_back_stats[cpu]));
863 942
@@ -920,10 +999,47 @@ static void abs_printout(int cpu, int nr, struct perf_evsel *evsel, double avg)
920 } else if (perf_evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)) { 999 } else if (perf_evsel__match(evsel, HARDWARE, HW_CPU_CYCLES)) {
921 total = avg_stats(&runtime_nsecs_stats[cpu]); 1000 total = avg_stats(&runtime_nsecs_stats[cpu]);
922 1001
1002 if (total) {
1003 ratio = avg / total;
1004 fprintf(output, " # %8.3f GHz ", ratio);
1005 }
1006 } else if (transaction_run &&
1007 perf_evsel__cmp(evsel, nth_evsel(T_CYCLES_IN_TX))) {
1008 total = avg_stats(&runtime_cycles_stats[cpu]);
1009 if (total)
1010 fprintf(output,
1011 " # %5.2f%% transactional cycles ",
1012 100.0 * (avg / total));
1013 } else if (transaction_run &&
1014 perf_evsel__cmp(evsel, nth_evsel(T_CYCLES_IN_TX_CP))) {
1015 total = avg_stats(&runtime_cycles_stats[cpu]);
1016 total2 = avg_stats(&runtime_cycles_in_tx_stats[cpu]);
1017 if (total2 < avg)
1018 total2 = avg;
1019 if (total)
1020 fprintf(output,
1021 " # %5.2f%% aborted cycles ",
1022 100.0 * ((total2-avg) / total));
1023 } else if (transaction_run &&
1024 perf_evsel__cmp(evsel, nth_evsel(T_TRANSACTION_START)) &&
1025 avg > 0 &&
1026 runtime_cycles_in_tx_stats[cpu].n != 0) {
1027 total = avg_stats(&runtime_cycles_in_tx_stats[cpu]);
1028
923 if (total) 1029 if (total)
924 ratio = 1.0 * avg / total; 1030 ratio = total / avg;
925 1031
926 fprintf(output, " # %8.3f GHz ", ratio); 1032 fprintf(output, " # %8.0f cycles / transaction ", ratio);
1033 } else if (transaction_run &&
1034 perf_evsel__cmp(evsel, nth_evsel(T_ELISION_START)) &&
1035 avg > 0 &&
1036 runtime_cycles_in_tx_stats[cpu].n != 0) {
1037 total = avg_stats(&runtime_cycles_in_tx_stats[cpu]);
1038
1039 if (total)
1040 ratio = total / avg;
1041
1042 fprintf(output, " # %8.0f cycles / elision ", ratio);
927 } else if (runtime_nsecs_stats[cpu].n != 0) { 1043 } else if (runtime_nsecs_stats[cpu].n != 0) {
928 char unit = 'M'; 1044 char unit = 'M';
929 1045
@@ -1116,7 +1232,11 @@ static void print_stat(int argc, const char **argv)
1116 if (!csv_output) { 1232 if (!csv_output) {
1117 fprintf(output, "\n"); 1233 fprintf(output, "\n");
1118 fprintf(output, " Performance counter stats for "); 1234 fprintf(output, " Performance counter stats for ");
1119 if (!perf_target__has_task(&target)) { 1235 if (target.system_wide)
1236 fprintf(output, "\'system wide");
1237 else if (target.cpu_list)
1238 fprintf(output, "\'CPU(s) %s", target.cpu_list);
1239 else if (!perf_target__has_task(&target)) {
1120 fprintf(output, "\'%s", argv[0]); 1240 fprintf(output, "\'%s", argv[0]);
1121 for (i = 1; i < argc; i++) 1241 for (i = 1; i < argc; i++)
1122 fprintf(output, " %s", argv[i]); 1242 fprintf(output, " %s", argv[i]);
@@ -1237,6 +1357,16 @@ static int perf_stat_init_aggr_mode(void)
1237 return 0; 1357 return 0;
1238} 1358}
1239 1359
1360static int setup_events(const char * const *attrs, unsigned len)
1361{
1362 unsigned i;
1363
1364 for (i = 0; i < len; i++) {
1365 if (parse_events(evsel_list, attrs[i]))
1366 return -1;
1367 }
1368 return 0;
1369}
1240 1370
1241/* 1371/*
1242 * Add default attributes, if there were no attributes specified or 1372 * Add default attributes, if there were no attributes specified or
@@ -1355,6 +1485,22 @@ static int add_default_attributes(void)
1355 if (null_run) 1485 if (null_run)
1356 return 0; 1486 return 0;
1357 1487
1488 if (transaction_run) {
1489 int err;
1490 if (pmu_have_event("cpu", "cycles-ct") &&
1491 pmu_have_event("cpu", "el-start"))
1492 err = setup_events(transaction_attrs,
1493 ARRAY_SIZE(transaction_attrs));
1494 else
1495 err = setup_events(transaction_limited_attrs,
1496 ARRAY_SIZE(transaction_limited_attrs));
1497 if (err < 0) {
1498 fprintf(stderr, "Cannot set up transaction events\n");
1499 return -1;
1500 }
1501 return 0;
1502 }
1503
1358 if (!evsel_list->nr_entries) { 1504 if (!evsel_list->nr_entries) {
1359 if (perf_evlist__add_default_attrs(evsel_list, default_attrs) < 0) 1505 if (perf_evlist__add_default_attrs(evsel_list, default_attrs) < 0)
1360 return -1; 1506 return -1;
@@ -1389,6 +1535,8 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
1389 int output_fd = 0; 1535 int output_fd = 0;
1390 const char *output_name = NULL; 1536 const char *output_name = NULL;
1391 const struct option options[] = { 1537 const struct option options[] = {
1538 OPT_BOOLEAN('T', "transaction", &transaction_run,
1539 "hardware transaction statistics"),
1392 OPT_CALLBACK('e', "event", &evsel_list, "event", 1540 OPT_CALLBACK('e', "event", &evsel_list, "event",
1393 "event selector. use 'perf list' to list available events", 1541 "event selector. use 'perf list' to list available events",
1394 parse_events_option), 1542 parse_events_option),
@@ -1448,7 +1596,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
1448 "perf stat [<options>] [<command>]", 1596 "perf stat [<options>] [<command>]",
1449 NULL 1597 NULL
1450 }; 1598 };
1451 int status = -ENOMEM, run_idx; 1599 int status = -EINVAL, run_idx;
1452 const char *mode; 1600 const char *mode;
1453 1601
1454 setlocale(LC_ALL, ""); 1602 setlocale(LC_ALL, "");
@@ -1466,12 +1614,15 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
1466 1614
1467 if (output_name && output_fd) { 1615 if (output_name && output_fd) {
1468 fprintf(stderr, "cannot use both --output and --log-fd\n"); 1616 fprintf(stderr, "cannot use both --output and --log-fd\n");
1469 usage_with_options(stat_usage, options); 1617 parse_options_usage(stat_usage, options, "o", 1);
1618 parse_options_usage(NULL, options, "log-fd", 0);
1619 goto out;
1470 } 1620 }
1471 1621
1472 if (output_fd < 0) { 1622 if (output_fd < 0) {
1473 fprintf(stderr, "argument to --log-fd must be a > 0\n"); 1623 fprintf(stderr, "argument to --log-fd must be a > 0\n");
1474 usage_with_options(stat_usage, options); 1624 parse_options_usage(stat_usage, options, "log-fd", 0);
1625 goto out;
1475 } 1626 }
1476 1627
1477 if (!output) { 1628 if (!output) {
@@ -1508,16 +1659,21 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
1508 /* User explicitly passed -B? */ 1659 /* User explicitly passed -B? */
1509 if (big_num_opt == 1) { 1660 if (big_num_opt == 1) {
1510 fprintf(stderr, "-B option not supported with -x\n"); 1661 fprintf(stderr, "-B option not supported with -x\n");
1511 usage_with_options(stat_usage, options); 1662 parse_options_usage(stat_usage, options, "B", 1);
1663 parse_options_usage(NULL, options, "x", 1);
1664 goto out;
1512 } else /* Nope, so disable big number formatting */ 1665 } else /* Nope, so disable big number formatting */
1513 big_num = false; 1666 big_num = false;
1514 } else if (big_num_opt == 0) /* User passed --no-big-num */ 1667 } else if (big_num_opt == 0) /* User passed --no-big-num */
1515 big_num = false; 1668 big_num = false;
1516 1669
1517 if (!argc && !perf_target__has_task(&target)) 1670 if (!argc && perf_target__none(&target))
1518 usage_with_options(stat_usage, options); 1671 usage_with_options(stat_usage, options);
1672
1519 if (run_count < 0) { 1673 if (run_count < 0) {
1520 usage_with_options(stat_usage, options); 1674 pr_err("Run count must be a positive number\n");
1675 parse_options_usage(stat_usage, options, "r", 1);
1676 goto out;
1521 } else if (run_count == 0) { 1677 } else if (run_count == 0) {
1522 forever = true; 1678 forever = true;
1523 run_count = 1; 1679 run_count = 1;
@@ -1529,8 +1685,10 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
1529 fprintf(stderr, "both cgroup and no-aggregation " 1685 fprintf(stderr, "both cgroup and no-aggregation "
1530 "modes only available in system-wide mode\n"); 1686 "modes only available in system-wide mode\n");
1531 1687
1532 usage_with_options(stat_usage, options); 1688 parse_options_usage(stat_usage, options, "G", 1);
1533 return -1; 1689 parse_options_usage(NULL, options, "A", 1);
1690 parse_options_usage(NULL, options, "a", 1);
1691 goto out;
1534 } 1692 }
1535 1693
1536 if (add_default_attributes()) 1694 if (add_default_attributes())
@@ -1539,25 +1697,28 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
1539 perf_target__validate(&target); 1697 perf_target__validate(&target);
1540 1698
1541 if (perf_evlist__create_maps(evsel_list, &target) < 0) { 1699 if (perf_evlist__create_maps(evsel_list, &target) < 0) {
1542 if (perf_target__has_task(&target)) 1700 if (perf_target__has_task(&target)) {
1543 pr_err("Problems finding threads of monitor\n"); 1701 pr_err("Problems finding threads of monitor\n");
1544 if (perf_target__has_cpu(&target)) 1702 parse_options_usage(stat_usage, options, "p", 1);
1703 parse_options_usage(NULL, options, "t", 1);
1704 } else if (perf_target__has_cpu(&target)) {
1545 perror("failed to parse CPUs map"); 1705 perror("failed to parse CPUs map");
1546 1706 parse_options_usage(stat_usage, options, "C", 1);
1547 usage_with_options(stat_usage, options); 1707 parse_options_usage(NULL, options, "a", 1);
1548 return -1; 1708 }
1709 goto out;
1549 } 1710 }
1550 if (interval && interval < 100) { 1711 if (interval && interval < 100) {
1551 pr_err("print interval must be >= 100ms\n"); 1712 pr_err("print interval must be >= 100ms\n");
1552 usage_with_options(stat_usage, options); 1713 parse_options_usage(stat_usage, options, "I", 1);
1553 return -1; 1714 goto out_free_maps;
1554 } 1715 }
1555 1716
1556 if (perf_evlist__alloc_stats(evsel_list, interval)) 1717 if (perf_evlist__alloc_stats(evsel_list, interval))
1557 goto out_free_maps; 1718 goto out_free_maps;
1558 1719
1559 if (perf_stat_init_aggr_mode()) 1720 if (perf_stat_init_aggr_mode())
1560 goto out; 1721 goto out_free_maps;
1561 1722
1562 /* 1723 /*
1563 * We dont want to block the signals - that would cause 1724 * We dont want to block the signals - that would cause
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index c2e02319347a..41c9bde2fb67 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -36,6 +36,7 @@
36#include "util/session.h" 36#include "util/session.h"
37#include "util/svghelper.h" 37#include "util/svghelper.h"
38#include "util/tool.h" 38#include "util/tool.h"
39#include "util/data.h"
39 40
40#define SUPPORT_OLD_POWER_EVENTS 1 41#define SUPPORT_OLD_POWER_EVENTS 1
41#define PWR_EVENT_EXIT -1 42#define PWR_EVENT_EXIT -1
@@ -482,8 +483,8 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
482 if (sample->cpu > numcpus) 483 if (sample->cpu > numcpus)
483 numcpus = sample->cpu; 484 numcpus = sample->cpu;
484 485
485 if (evsel->handler.func != NULL) { 486 if (evsel->handler != NULL) {
486 tracepoint_handler f = evsel->handler.func; 487 tracepoint_handler f = evsel->handler;
487 return f(evsel, sample); 488 return f(evsel, sample);
488 } 489 }
489 490
@@ -990,8 +991,13 @@ static int __cmd_timechart(const char *output_name)
990 { "power:power_frequency", process_sample_power_frequency }, 991 { "power:power_frequency", process_sample_power_frequency },
991#endif 992#endif
992 }; 993 };
993 struct perf_session *session = perf_session__new(input_name, O_RDONLY, 994 struct perf_data_file file = {
994 0, false, &perf_timechart); 995 .path = input_name,
996 .mode = PERF_DATA_MODE_READ,
997 };
998
999 struct perf_session *session = perf_session__new(&file, false,
1000 &perf_timechart);
995 int ret = -EINVAL; 1001 int ret = -EINVAL;
996 1002
997 if (session == NULL) 1003 if (session == NULL)
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 5a11f13e56f9..9acca8856ccb 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -246,10 +246,10 @@ static struct hist_entry *perf_evsel__add_hist_entry(struct perf_evsel *evsel,
246 struct hist_entry *he; 246 struct hist_entry *he;
247 247
248 pthread_mutex_lock(&evsel->hists.lock); 248 pthread_mutex_lock(&evsel->hists.lock);
249 he = __hists__add_entry(&evsel->hists, al, NULL, sample->period, 249 he = __hists__add_entry(&evsel->hists, al, NULL, NULL, NULL,
250 sample->weight); 250 sample->period, sample->weight,
251 sample->transaction);
251 pthread_mutex_unlock(&evsel->hists.lock); 252 pthread_mutex_unlock(&evsel->hists.lock);
252
253 if (he == NULL) 253 if (he == NULL)
254 return NULL; 254 return NULL;
255 255
@@ -287,7 +287,7 @@ static void perf_top__print_sym_table(struct perf_top *top)
287 return; 287 return;
288 } 288 }
289 289
290 hists__collapse_resort(&top->sym_evsel->hists); 290 hists__collapse_resort(&top->sym_evsel->hists, NULL);
291 hists__output_resort(&top->sym_evsel->hists); 291 hists__output_resort(&top->sym_evsel->hists);
292 hists__decay_entries(&top->sym_evsel->hists, 292 hists__decay_entries(&top->sym_evsel->hists,
293 top->hide_user_symbols, 293 top->hide_user_symbols,
@@ -553,7 +553,7 @@ static void perf_top__sort_new_samples(void *arg)
553 if (t->evlist->selected != NULL) 553 if (t->evlist->selected != NULL)
554 t->sym_evsel = t->evlist->selected; 554 t->sym_evsel = t->evlist->selected;
555 555
556 hists__collapse_resort(&t->sym_evsel->hists); 556 hists__collapse_resort(&t->sym_evsel->hists, NULL);
557 hists__output_resort(&t->sym_evsel->hists); 557 hists__output_resort(&t->sym_evsel->hists);
558 hists__decay_entries(&t->sym_evsel->hists, 558 hists__decay_entries(&t->sym_evsel->hists,
559 t->hide_user_symbols, 559 t->hide_user_symbols,
@@ -771,7 +771,8 @@ static void perf_event__process_sample(struct perf_tool *tool,
771 sample->callchain) { 771 sample->callchain) {
772 err = machine__resolve_callchain(machine, evsel, 772 err = machine__resolve_callchain(machine, evsel,
773 al.thread, sample, 773 al.thread, sample,
774 &parent, &al); 774 &parent, &al,
775 top->max_stack);
775 if (err) 776 if (err)
776 return; 777 return;
777 } 778 }
@@ -856,7 +857,7 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
856 &sample, machine); 857 &sample, machine);
857 } else if (event->header.type < PERF_RECORD_MAX) { 858 } else if (event->header.type < PERF_RECORD_MAX) {
858 hists__inc_nr_events(&evsel->hists, event->header.type); 859 hists__inc_nr_events(&evsel->hists, event->header.type);
859 machine__process_event(machine, event); 860 machine__process_event(machine, event, &sample);
860 } else 861 } else
861 ++session->stats.nr_unknown_events; 862 ++session->stats.nr_unknown_events;
862next_event: 863next_event:
@@ -932,11 +933,8 @@ static int __cmd_top(struct perf_top *top)
932 struct perf_record_opts *opts = &top->record_opts; 933 struct perf_record_opts *opts = &top->record_opts;
933 pthread_t thread; 934 pthread_t thread;
934 int ret; 935 int ret;
935 /* 936
936 * FIXME: perf_session__new should allow passing a O_MMAP, so that all this 937 top->session = perf_session__new(NULL, false, NULL);
937 * mmap reading, etc is encapsulated in it. Use O_WRONLY for now.
938 */
939 top->session = perf_session__new(NULL, O_WRONLY, false, false, NULL);
940 if (top->session == NULL) 938 if (top->session == NULL)
941 return -ENOMEM; 939 return -ENOMEM;
942 940
@@ -1043,7 +1041,7 @@ parse_percent_limit(const struct option *opt, const char *arg,
1043 1041
1044int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) 1042int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1045{ 1043{
1046 int status; 1044 int status = -1;
1047 char errbuf[BUFSIZ]; 1045 char errbuf[BUFSIZ];
1048 struct perf_top top = { 1046 struct perf_top top = {
1049 .count_filter = 5, 1047 .count_filter = 5,
@@ -1053,10 +1051,11 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1053 .user_freq = UINT_MAX, 1051 .user_freq = UINT_MAX,
1054 .user_interval = ULLONG_MAX, 1052 .user_interval = ULLONG_MAX,
1055 .freq = 4000, /* 4 KHz */ 1053 .freq = 4000, /* 4 KHz */
1056 .target = { 1054 .target = {
1057 .uses_mmap = true, 1055 .uses_mmap = true,
1058 }, 1056 },
1059 }, 1057 },
1058 .max_stack = PERF_MAX_STACK_DEPTH,
1060 .sym_pcnt_filter = 5, 1059 .sym_pcnt_filter = 5,
1061 }; 1060 };
1062 struct perf_record_opts *opts = &top.record_opts; 1061 struct perf_record_opts *opts = &top.record_opts;
@@ -1076,10 +1075,13 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1076 "list of cpus to monitor"), 1075 "list of cpus to monitor"),
1077 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, 1076 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
1078 "file", "vmlinux pathname"), 1077 "file", "vmlinux pathname"),
1078 OPT_BOOLEAN(0, "ignore-vmlinux", &symbol_conf.ignore_vmlinux,
1079 "don't load vmlinux even if found"),
1079 OPT_BOOLEAN('K', "hide_kernel_symbols", &top.hide_kernel_symbols, 1080 OPT_BOOLEAN('K', "hide_kernel_symbols", &top.hide_kernel_symbols,
1080 "hide kernel symbols"), 1081 "hide kernel symbols"),
1081 OPT_UINTEGER('m', "mmap-pages", &opts->mmap_pages, 1082 OPT_CALLBACK('m', "mmap-pages", &opts->mmap_pages, "pages",
1082 "number of mmap data pages"), 1083 "number of mmap data pages",
1084 perf_evlist__parse_mmap_pages),
1083 OPT_INTEGER('r', "realtime", &top.realtime_prio, 1085 OPT_INTEGER('r', "realtime", &top.realtime_prio,
1084 "collect data with this RT SCHED_FIFO priority"), 1086 "collect data with this RT SCHED_FIFO priority"),
1085 OPT_INTEGER('d', "delay", &top.delay_secs, 1087 OPT_INTEGER('d', "delay", &top.delay_secs,
@@ -1105,7 +1107,8 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1105 OPT_INCR('v', "verbose", &verbose, 1107 OPT_INCR('v', "verbose", &verbose,
1106 "be more verbose (show counter open errors, etc)"), 1108 "be more verbose (show counter open errors, etc)"),
1107 OPT_STRING('s', "sort", &sort_order, "key[,key2...]", 1109 OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
1108 "sort by key(s): pid, comm, dso, symbol, parent, weight, local_weight"), 1110 "sort by key(s): pid, comm, dso, symbol, parent, weight, local_weight,"
1111 " abort, in_tx, transaction"),
1109 OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples, 1112 OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples,
1110 "Show a column with the number of samples"), 1113 "Show a column with the number of samples"),
1111 OPT_CALLBACK_NOOPT('G', NULL, &top.record_opts, 1114 OPT_CALLBACK_NOOPT('G', NULL, &top.record_opts,
@@ -1114,6 +1117,9 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1114 OPT_CALLBACK(0, "call-graph", &top.record_opts, 1117 OPT_CALLBACK(0, "call-graph", &top.record_opts,
1115 "mode[,dump_size]", record_callchain_help, 1118 "mode[,dump_size]", record_callchain_help,
1116 &parse_callchain_opt), 1119 &parse_callchain_opt),
1120 OPT_INTEGER(0, "max-stack", &top.max_stack,
1121 "Set the maximum stack depth when parsing the callchain. "
1122 "Default: " __stringify(PERF_MAX_STACK_DEPTH)),
1117 OPT_CALLBACK(0, "ignore-callees", NULL, "regex", 1123 OPT_CALLBACK(0, "ignore-callees", NULL, "regex",
1118 "ignore callees of these functions in call graphs", 1124 "ignore callees of these functions in call graphs",
1119 report_parse_ignore_callees_opt), 1125 report_parse_ignore_callees_opt),
@@ -1154,8 +1160,10 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1154 if (sort_order == default_sort_order) 1160 if (sort_order == default_sort_order)
1155 sort_order = "dso,symbol"; 1161 sort_order = "dso,symbol";
1156 1162
1157 if (setup_sorting() < 0) 1163 if (setup_sorting() < 0) {
1158 usage_with_options(top_usage, options); 1164 parse_options_usage(top_usage, options, "s", 1);
1165 goto out_delete_evlist;
1166 }
1159 1167
1160 /* display thread wants entries to be collapsed in a different tree */ 1168 /* display thread wants entries to be collapsed in a different tree */
1161 sort__need_collapse = 1; 1169 sort__need_collapse = 1;
@@ -1201,20 +1209,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1201 if (top.delay_secs < 1) 1209 if (top.delay_secs < 1)
1202 top.delay_secs = 1; 1210 top.delay_secs = 1;
1203 1211
1204 if (opts->user_interval != ULLONG_MAX) 1212 if (perf_record_opts__config(opts)) {
1205 opts->default_interval = opts->user_interval;
1206 if (opts->user_freq != UINT_MAX)
1207 opts->freq = opts->user_freq;
1208
1209 /*
1210 * User specified count overrides default frequency.
1211 */
1212 if (opts->default_interval)
1213 opts->freq = 0;
1214 else if (opts->freq) {
1215 opts->default_interval = opts->freq;
1216 } else {
1217 ui__error("frequency and count are zero, aborting\n");
1218 status = -EINVAL; 1213 status = -EINVAL;
1219 goto out_delete_maps; 1214 goto out_delete_maps;
1220 } 1215 }
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 99c8d9ad6729..329b7832b5da 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -10,9 +10,11 @@
10#include "util/strlist.h" 10#include "util/strlist.h"
11#include "util/intlist.h" 11#include "util/intlist.h"
12#include "util/thread_map.h" 12#include "util/thread_map.h"
13#include "util/stat.h"
13 14
14#include <libaudit.h> 15#include <libaudit.h>
15#include <stdlib.h> 16#include <stdlib.h>
17#include <sys/eventfd.h>
16#include <sys/mman.h> 18#include <sys/mman.h>
17#include <linux/futex.h> 19#include <linux/futex.h>
18 20
@@ -33,49 +35,279 @@
33# define MADV_UNMERGEABLE 13 35# define MADV_UNMERGEABLE 13
34#endif 36#endif
35 37
36static size_t syscall_arg__scnprintf_hex(char *bf, size_t size, 38struct tp_field {
37 unsigned long arg, 39 int offset;
38 u8 arg_idx __maybe_unused, 40 union {
39 u8 *arg_mask __maybe_unused) 41 u64 (*integer)(struct tp_field *field, struct perf_sample *sample);
42 void *(*pointer)(struct tp_field *field, struct perf_sample *sample);
43 };
44};
45
46#define TP_UINT_FIELD(bits) \
47static u64 tp_field__u##bits(struct tp_field *field, struct perf_sample *sample) \
48{ \
49 return *(u##bits *)(sample->raw_data + field->offset); \
50}
51
52TP_UINT_FIELD(8);
53TP_UINT_FIELD(16);
54TP_UINT_FIELD(32);
55TP_UINT_FIELD(64);
56
57#define TP_UINT_FIELD__SWAPPED(bits) \
58static u64 tp_field__swapped_u##bits(struct tp_field *field, struct perf_sample *sample) \
59{ \
60 u##bits value = *(u##bits *)(sample->raw_data + field->offset); \
61 return bswap_##bits(value);\
62}
63
64TP_UINT_FIELD__SWAPPED(16);
65TP_UINT_FIELD__SWAPPED(32);
66TP_UINT_FIELD__SWAPPED(64);
67
68static int tp_field__init_uint(struct tp_field *field,
69 struct format_field *format_field,
70 bool needs_swap)
40{ 71{
41 return scnprintf(bf, size, "%#lx", arg); 72 field->offset = format_field->offset;
73
74 switch (format_field->size) {
75 case 1:
76 field->integer = tp_field__u8;
77 break;
78 case 2:
79 field->integer = needs_swap ? tp_field__swapped_u16 : tp_field__u16;
80 break;
81 case 4:
82 field->integer = needs_swap ? tp_field__swapped_u32 : tp_field__u32;
83 break;
84 case 8:
85 field->integer = needs_swap ? tp_field__swapped_u64 : tp_field__u64;
86 break;
87 default:
88 return -1;
89 }
90
91 return 0;
42} 92}
43 93
44#define SCA_HEX syscall_arg__scnprintf_hex 94static void *tp_field__ptr(struct tp_field *field, struct perf_sample *sample)
95{
96 return sample->raw_data + field->offset;
97}
45 98
46static size_t syscall_arg__scnprintf_whence(char *bf, size_t size, 99static int tp_field__init_ptr(struct tp_field *field, struct format_field *format_field)
47 unsigned long arg,
48 u8 arg_idx __maybe_unused,
49 u8 *arg_mask __maybe_unused)
50{ 100{
51 int whence = arg; 101 field->offset = format_field->offset;
102 field->pointer = tp_field__ptr;
103 return 0;
104}
52 105
53 switch (whence) { 106struct syscall_tp {
54#define P_WHENCE(n) case SEEK_##n: return scnprintf(bf, size, #n) 107 struct tp_field id;
55 P_WHENCE(SET); 108 union {
56 P_WHENCE(CUR); 109 struct tp_field args, ret;
57 P_WHENCE(END); 110 };
58#ifdef SEEK_DATA 111};
59 P_WHENCE(DATA); 112
60#endif 113static int perf_evsel__init_tp_uint_field(struct perf_evsel *evsel,
61#ifdef SEEK_HOLE 114 struct tp_field *field,
62 P_WHENCE(HOLE); 115 const char *name)
63#endif 116{
64#undef P_WHENCE 117 struct format_field *format_field = perf_evsel__field(evsel, name);
65 default: break; 118
119 if (format_field == NULL)
120 return -1;
121
122 return tp_field__init_uint(field, format_field, evsel->needs_swap);
123}
124
125#define perf_evsel__init_sc_tp_uint_field(evsel, name) \
126 ({ struct syscall_tp *sc = evsel->priv;\
127 perf_evsel__init_tp_uint_field(evsel, &sc->name, #name); })
128
129static int perf_evsel__init_tp_ptr_field(struct perf_evsel *evsel,
130 struct tp_field *field,
131 const char *name)
132{
133 struct format_field *format_field = perf_evsel__field(evsel, name);
134
135 if (format_field == NULL)
136 return -1;
137
138 return tp_field__init_ptr(field, format_field);
139}
140
141#define perf_evsel__init_sc_tp_ptr_field(evsel, name) \
142 ({ struct syscall_tp *sc = evsel->priv;\
143 perf_evsel__init_tp_ptr_field(evsel, &sc->name, #name); })
144
145static void perf_evsel__delete_priv(struct perf_evsel *evsel)
146{
147 free(evsel->priv);
148 evsel->priv = NULL;
149 perf_evsel__delete(evsel);
150}
151
152static struct perf_evsel *perf_evsel__syscall_newtp(const char *direction,
153 void *handler, int idx)
154{
155 struct perf_evsel *evsel = perf_evsel__newtp("raw_syscalls", direction, idx);
156
157 if (evsel) {
158 evsel->priv = malloc(sizeof(struct syscall_tp));
159
160 if (evsel->priv == NULL)
161 goto out_delete;
162
163 if (perf_evsel__init_sc_tp_uint_field(evsel, id))
164 goto out_delete;
165
166 evsel->handler = handler;
66 } 167 }
67 168
68 return scnprintf(bf, size, "%#x", whence); 169 return evsel;
170
171out_delete:
172 perf_evsel__delete_priv(evsel);
173 return NULL;
69} 174}
70 175
71#define SCA_WHENCE syscall_arg__scnprintf_whence 176#define perf_evsel__sc_tp_uint(evsel, name, sample) \
177 ({ struct syscall_tp *fields = evsel->priv; \
178 fields->name.integer(&fields->name, sample); })
179
180#define perf_evsel__sc_tp_ptr(evsel, name, sample) \
181 ({ struct syscall_tp *fields = evsel->priv; \
182 fields->name.pointer(&fields->name, sample); })
183
184static int perf_evlist__add_syscall_newtp(struct perf_evlist *evlist,
185 void *sys_enter_handler,
186 void *sys_exit_handler)
187{
188 int ret = -1;
189 int idx = evlist->nr_entries;
190 struct perf_evsel *sys_enter, *sys_exit;
191
192 sys_enter = perf_evsel__syscall_newtp("sys_enter", sys_enter_handler, idx++);
193 if (sys_enter == NULL)
194 goto out;
195
196 if (perf_evsel__init_sc_tp_ptr_field(sys_enter, args))
197 goto out_delete_sys_enter;
198
199 sys_exit = perf_evsel__syscall_newtp("sys_exit", sys_exit_handler, idx++);
200 if (sys_exit == NULL)
201 goto out_delete_sys_enter;
202
203 if (perf_evsel__init_sc_tp_uint_field(sys_exit, ret))
204 goto out_delete_sys_exit;
205
206 perf_evlist__add(evlist, sys_enter);
207 perf_evlist__add(evlist, sys_exit);
208
209 ret = 0;
210out:
211 return ret;
212
213out_delete_sys_exit:
214 perf_evsel__delete_priv(sys_exit);
215out_delete_sys_enter:
216 perf_evsel__delete_priv(sys_enter);
217 goto out;
218}
219
220
221struct syscall_arg {
222 unsigned long val;
223 struct thread *thread;
224 struct trace *trace;
225 void *parm;
226 u8 idx;
227 u8 mask;
228};
229
230struct strarray {
231 int offset;
232 int nr_entries;
233 const char **entries;
234};
235
236#define DEFINE_STRARRAY(array) struct strarray strarray__##array = { \
237 .nr_entries = ARRAY_SIZE(array), \
238 .entries = array, \
239}
240
241#define DEFINE_STRARRAY_OFFSET(array, off) struct strarray strarray__##array = { \
242 .offset = off, \
243 .nr_entries = ARRAY_SIZE(array), \
244 .entries = array, \
245}
246
247static size_t __syscall_arg__scnprintf_strarray(char *bf, size_t size,
248 const char *intfmt,
249 struct syscall_arg *arg)
250{
251 struct strarray *sa = arg->parm;
252 int idx = arg->val - sa->offset;
253
254 if (idx < 0 || idx >= sa->nr_entries)
255 return scnprintf(bf, size, intfmt, arg->val);
256
257 return scnprintf(bf, size, "%s", sa->entries[idx]);
258}
259
260static size_t syscall_arg__scnprintf_strarray(char *bf, size_t size,
261 struct syscall_arg *arg)
262{
263 return __syscall_arg__scnprintf_strarray(bf, size, "%d", arg);
264}
265
266#define SCA_STRARRAY syscall_arg__scnprintf_strarray
267
268static size_t syscall_arg__scnprintf_strhexarray(char *bf, size_t size,
269 struct syscall_arg *arg)
270{
271 return __syscall_arg__scnprintf_strarray(bf, size, "%#x", arg);
272}
273
274#define SCA_STRHEXARRAY syscall_arg__scnprintf_strhexarray
275
276static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
277 struct syscall_arg *arg);
278
279#define SCA_FD syscall_arg__scnprintf_fd
280
281static size_t syscall_arg__scnprintf_fd_at(char *bf, size_t size,
282 struct syscall_arg *arg)
283{
284 int fd = arg->val;
285
286 if (fd == AT_FDCWD)
287 return scnprintf(bf, size, "CWD");
288
289 return syscall_arg__scnprintf_fd(bf, size, arg);
290}
291
292#define SCA_FDAT syscall_arg__scnprintf_fd_at
293
294static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
295 struct syscall_arg *arg);
296
297#define SCA_CLOSE_FD syscall_arg__scnprintf_close_fd
298
299static size_t syscall_arg__scnprintf_hex(char *bf, size_t size,
300 struct syscall_arg *arg)
301{
302 return scnprintf(bf, size, "%#lx", arg->val);
303}
304
305#define SCA_HEX syscall_arg__scnprintf_hex
72 306
73static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size, 307static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size,
74 unsigned long arg, 308 struct syscall_arg *arg)
75 u8 arg_idx __maybe_unused,
76 u8 *arg_mask __maybe_unused)
77{ 309{
78 int printed = 0, prot = arg; 310 int printed = 0, prot = arg->val;
79 311
80 if (prot == PROT_NONE) 312 if (prot == PROT_NONE)
81 return scnprintf(bf, size, "NONE"); 313 return scnprintf(bf, size, "NONE");
@@ -104,10 +336,9 @@ static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size,
104#define SCA_MMAP_PROT syscall_arg__scnprintf_mmap_prot 336#define SCA_MMAP_PROT syscall_arg__scnprintf_mmap_prot
105 337
106static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size, 338static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size,
107 unsigned long arg, u8 arg_idx __maybe_unused, 339 struct syscall_arg *arg)
108 u8 *arg_mask __maybe_unused)
109{ 340{
110 int printed = 0, flags = arg; 341 int printed = 0, flags = arg->val;
111 342
112#define P_MMAP_FLAG(n) \ 343#define P_MMAP_FLAG(n) \
113 if (flags & MAP_##n) { \ 344 if (flags & MAP_##n) { \
@@ -148,10 +379,9 @@ static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size,
148#define SCA_MMAP_FLAGS syscall_arg__scnprintf_mmap_flags 379#define SCA_MMAP_FLAGS syscall_arg__scnprintf_mmap_flags
149 380
150static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size, 381static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size,
151 unsigned long arg, u8 arg_idx __maybe_unused, 382 struct syscall_arg *arg)
152 u8 *arg_mask __maybe_unused)
153{ 383{
154 int behavior = arg; 384 int behavior = arg->val;
155 385
156 switch (behavior) { 386 switch (behavior) {
157#define P_MADV_BHV(n) case MADV_##n: return scnprintf(bf, size, #n) 387#define P_MADV_BHV(n) case MADV_##n: return scnprintf(bf, size, #n)
@@ -190,8 +420,38 @@ static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size,
190 420
191#define SCA_MADV_BHV syscall_arg__scnprintf_madvise_behavior 421#define SCA_MADV_BHV syscall_arg__scnprintf_madvise_behavior
192 422
193static size_t syscall_arg__scnprintf_futex_op(char *bf, size_t size, unsigned long arg, 423static size_t syscall_arg__scnprintf_flock(char *bf, size_t size,
194 u8 arg_idx __maybe_unused, u8 *arg_mask) 424 struct syscall_arg *arg)
425{
426 int printed = 0, op = arg->val;
427
428 if (op == 0)
429 return scnprintf(bf, size, "NONE");
430#define P_CMD(cmd) \
431 if ((op & LOCK_##cmd) == LOCK_##cmd) { \
432 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #cmd); \
433 op &= ~LOCK_##cmd; \
434 }
435
436 P_CMD(SH);
437 P_CMD(EX);
438 P_CMD(NB);
439 P_CMD(UN);
440 P_CMD(MAND);
441 P_CMD(RW);
442 P_CMD(READ);
443 P_CMD(WRITE);
444#undef P_OP
445
446 if (op)
447 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", op);
448
449 return printed;
450}
451
452#define SCA_FLOCK syscall_arg__scnprintf_flock
453
454static size_t syscall_arg__scnprintf_futex_op(char *bf, size_t size, struct syscall_arg *arg)
195{ 455{
196 enum syscall_futex_args { 456 enum syscall_futex_args {
197 SCF_UADDR = (1 << 0), 457 SCF_UADDR = (1 << 0),
@@ -201,24 +461,24 @@ static size_t syscall_arg__scnprintf_futex_op(char *bf, size_t size, unsigned lo
201 SCF_UADDR2 = (1 << 4), 461 SCF_UADDR2 = (1 << 4),
202 SCF_VAL3 = (1 << 5), 462 SCF_VAL3 = (1 << 5),
203 }; 463 };
204 int op = arg; 464 int op = arg->val;
205 int cmd = op & FUTEX_CMD_MASK; 465 int cmd = op & FUTEX_CMD_MASK;
206 size_t printed = 0; 466 size_t printed = 0;
207 467
208 switch (cmd) { 468 switch (cmd) {
209#define P_FUTEX_OP(n) case FUTEX_##n: printed = scnprintf(bf, size, #n); 469#define P_FUTEX_OP(n) case FUTEX_##n: printed = scnprintf(bf, size, #n);
210 P_FUTEX_OP(WAIT); *arg_mask |= SCF_VAL3|SCF_UADDR2; break; 470 P_FUTEX_OP(WAIT); arg->mask |= SCF_VAL3|SCF_UADDR2; break;
211 P_FUTEX_OP(WAKE); *arg_mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break; 471 P_FUTEX_OP(WAKE); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
212 P_FUTEX_OP(FD); *arg_mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break; 472 P_FUTEX_OP(FD); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
213 P_FUTEX_OP(REQUEUE); *arg_mask |= SCF_VAL3|SCF_TIMEOUT; break; 473 P_FUTEX_OP(REQUEUE); arg->mask |= SCF_VAL3|SCF_TIMEOUT; break;
214 P_FUTEX_OP(CMP_REQUEUE); *arg_mask |= SCF_TIMEOUT; break; 474 P_FUTEX_OP(CMP_REQUEUE); arg->mask |= SCF_TIMEOUT; break;
215 P_FUTEX_OP(CMP_REQUEUE_PI); *arg_mask |= SCF_TIMEOUT; break; 475 P_FUTEX_OP(CMP_REQUEUE_PI); arg->mask |= SCF_TIMEOUT; break;
216 P_FUTEX_OP(WAKE_OP); break; 476 P_FUTEX_OP(WAKE_OP); break;
217 P_FUTEX_OP(LOCK_PI); *arg_mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break; 477 P_FUTEX_OP(LOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
218 P_FUTEX_OP(UNLOCK_PI); *arg_mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break; 478 P_FUTEX_OP(UNLOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
219 P_FUTEX_OP(TRYLOCK_PI); *arg_mask |= SCF_VAL3|SCF_UADDR2; break; 479 P_FUTEX_OP(TRYLOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2; break;
220 P_FUTEX_OP(WAIT_BITSET); *arg_mask |= SCF_UADDR2; break; 480 P_FUTEX_OP(WAIT_BITSET); arg->mask |= SCF_UADDR2; break;
221 P_FUTEX_OP(WAKE_BITSET); *arg_mask |= SCF_UADDR2; break; 481 P_FUTEX_OP(WAKE_BITSET); arg->mask |= SCF_UADDR2; break;
222 P_FUTEX_OP(WAIT_REQUEUE_PI); break; 482 P_FUTEX_OP(WAIT_REQUEUE_PI); break;
223 default: printed = scnprintf(bf, size, "%#x", cmd); break; 483 default: printed = scnprintf(bf, size, "%#x", cmd); break;
224 } 484 }
@@ -234,14 +494,194 @@ static size_t syscall_arg__scnprintf_futex_op(char *bf, size_t size, unsigned lo
234 494
235#define SCA_FUTEX_OP syscall_arg__scnprintf_futex_op 495#define SCA_FUTEX_OP syscall_arg__scnprintf_futex_op
236 496
497static const char *epoll_ctl_ops[] = { "ADD", "DEL", "MOD", };
498static DEFINE_STRARRAY_OFFSET(epoll_ctl_ops, 1);
499
500static const char *itimers[] = { "REAL", "VIRTUAL", "PROF", };
501static DEFINE_STRARRAY(itimers);
502
503static const char *whences[] = { "SET", "CUR", "END",
504#ifdef SEEK_DATA
505"DATA",
506#endif
507#ifdef SEEK_HOLE
508"HOLE",
509#endif
510};
511static DEFINE_STRARRAY(whences);
512
513static const char *fcntl_cmds[] = {
514 "DUPFD", "GETFD", "SETFD", "GETFL", "SETFL", "GETLK", "SETLK",
515 "SETLKW", "SETOWN", "GETOWN", "SETSIG", "GETSIG", "F_GETLK64",
516 "F_SETLK64", "F_SETLKW64", "F_SETOWN_EX", "F_GETOWN_EX",
517 "F_GETOWNER_UIDS",
518};
519static DEFINE_STRARRAY(fcntl_cmds);
520
521static const char *rlimit_resources[] = {
522 "CPU", "FSIZE", "DATA", "STACK", "CORE", "RSS", "NPROC", "NOFILE",
523 "MEMLOCK", "AS", "LOCKS", "SIGPENDING", "MSGQUEUE", "NICE", "RTPRIO",
524 "RTTIME",
525};
526static DEFINE_STRARRAY(rlimit_resources);
527
528static const char *sighow[] = { "BLOCK", "UNBLOCK", "SETMASK", };
529static DEFINE_STRARRAY(sighow);
530
531static const char *clockid[] = {
532 "REALTIME", "MONOTONIC", "PROCESS_CPUTIME_ID", "THREAD_CPUTIME_ID",
533 "MONOTONIC_RAW", "REALTIME_COARSE", "MONOTONIC_COARSE",
534};
535static DEFINE_STRARRAY(clockid);
536
537static const char *socket_families[] = {
538 "UNSPEC", "LOCAL", "INET", "AX25", "IPX", "APPLETALK", "NETROM",
539 "BRIDGE", "ATMPVC", "X25", "INET6", "ROSE", "DECnet", "NETBEUI",
540 "SECURITY", "KEY", "NETLINK", "PACKET", "ASH", "ECONET", "ATMSVC",
541 "RDS", "SNA", "IRDA", "PPPOX", "WANPIPE", "LLC", "IB", "CAN", "TIPC",
542 "BLUETOOTH", "IUCV", "RXRPC", "ISDN", "PHONET", "IEEE802154", "CAIF",
543 "ALG", "NFC", "VSOCK",
544};
545static DEFINE_STRARRAY(socket_families);
546
547#ifndef SOCK_TYPE_MASK
548#define SOCK_TYPE_MASK 0xf
549#endif
550
551static size_t syscall_arg__scnprintf_socket_type(char *bf, size_t size,
552 struct syscall_arg *arg)
553{
554 size_t printed;
555 int type = arg->val,
556 flags = type & ~SOCK_TYPE_MASK;
557
558 type &= SOCK_TYPE_MASK;
559 /*
560 * Can't use a strarray, MIPS may override for ABI reasons.
561 */
562 switch (type) {
563#define P_SK_TYPE(n) case SOCK_##n: printed = scnprintf(bf, size, #n); break;
564 P_SK_TYPE(STREAM);
565 P_SK_TYPE(DGRAM);
566 P_SK_TYPE(RAW);
567 P_SK_TYPE(RDM);
568 P_SK_TYPE(SEQPACKET);
569 P_SK_TYPE(DCCP);
570 P_SK_TYPE(PACKET);
571#undef P_SK_TYPE
572 default:
573 printed = scnprintf(bf, size, "%#x", type);
574 }
575
576#define P_SK_FLAG(n) \
577 if (flags & SOCK_##n) { \
578 printed += scnprintf(bf + printed, size - printed, "|%s", #n); \
579 flags &= ~SOCK_##n; \
580 }
581
582 P_SK_FLAG(CLOEXEC);
583 P_SK_FLAG(NONBLOCK);
584#undef P_SK_FLAG
585
586 if (flags)
587 printed += scnprintf(bf + printed, size - printed, "|%#x", flags);
588
589 return printed;
590}
591
592#define SCA_SK_TYPE syscall_arg__scnprintf_socket_type
593
594#ifndef MSG_PROBE
595#define MSG_PROBE 0x10
596#endif
597#ifndef MSG_WAITFORONE
598#define MSG_WAITFORONE 0x10000
599#endif
600#ifndef MSG_SENDPAGE_NOTLAST
601#define MSG_SENDPAGE_NOTLAST 0x20000
602#endif
603#ifndef MSG_FASTOPEN
604#define MSG_FASTOPEN 0x20000000
605#endif
606
607static size_t syscall_arg__scnprintf_msg_flags(char *bf, size_t size,
608 struct syscall_arg *arg)
609{
610 int printed = 0, flags = arg->val;
611
612 if (flags == 0)
613 return scnprintf(bf, size, "NONE");
614#define P_MSG_FLAG(n) \
615 if (flags & MSG_##n) { \
616 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
617 flags &= ~MSG_##n; \
618 }
619
620 P_MSG_FLAG(OOB);
621 P_MSG_FLAG(PEEK);
622 P_MSG_FLAG(DONTROUTE);
623 P_MSG_FLAG(TRYHARD);
624 P_MSG_FLAG(CTRUNC);
625 P_MSG_FLAG(PROBE);
626 P_MSG_FLAG(TRUNC);
627 P_MSG_FLAG(DONTWAIT);
628 P_MSG_FLAG(EOR);
629 P_MSG_FLAG(WAITALL);
630 P_MSG_FLAG(FIN);
631 P_MSG_FLAG(SYN);
632 P_MSG_FLAG(CONFIRM);
633 P_MSG_FLAG(RST);
634 P_MSG_FLAG(ERRQUEUE);
635 P_MSG_FLAG(NOSIGNAL);
636 P_MSG_FLAG(MORE);
637 P_MSG_FLAG(WAITFORONE);
638 P_MSG_FLAG(SENDPAGE_NOTLAST);
639 P_MSG_FLAG(FASTOPEN);
640 P_MSG_FLAG(CMSG_CLOEXEC);
641#undef P_MSG_FLAG
642
643 if (flags)
644 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
645
646 return printed;
647}
648
649#define SCA_MSG_FLAGS syscall_arg__scnprintf_msg_flags
650
651static size_t syscall_arg__scnprintf_access_mode(char *bf, size_t size,
652 struct syscall_arg *arg)
653{
654 size_t printed = 0;
655 int mode = arg->val;
656
657 if (mode == F_OK) /* 0 */
658 return scnprintf(bf, size, "F");
659#define P_MODE(n) \
660 if (mode & n##_OK) { \
661 printed += scnprintf(bf + printed, size - printed, "%s", #n); \
662 mode &= ~n##_OK; \
663 }
664
665 P_MODE(R);
666 P_MODE(W);
667 P_MODE(X);
668#undef P_MODE
669
670 if (mode)
671 printed += scnprintf(bf + printed, size - printed, "|%#x", mode);
672
673 return printed;
674}
675
676#define SCA_ACCMODE syscall_arg__scnprintf_access_mode
677
237static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size, 678static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
238 unsigned long arg, 679 struct syscall_arg *arg)
239 u8 arg_idx, u8 *arg_mask)
240{ 680{
241 int printed = 0, flags = arg; 681 int printed = 0, flags = arg->val;
242 682
243 if (!(flags & O_CREAT)) 683 if (!(flags & O_CREAT))
244 *arg_mask |= 1 << (arg_idx + 1); /* Mask the mode parm */ 684 arg->mask |= 1 << (arg->idx + 1); /* Mask the mode parm */
245 685
246 if (flags == 0) 686 if (flags == 0)
247 return scnprintf(bf, size, "RDONLY"); 687 return scnprintf(bf, size, "RDONLY");
@@ -291,32 +731,225 @@ static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
291 731
292#define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags 732#define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags
293 733
734static size_t syscall_arg__scnprintf_eventfd_flags(char *bf, size_t size,
735 struct syscall_arg *arg)
736{
737 int printed = 0, flags = arg->val;
738
739 if (flags == 0)
740 return scnprintf(bf, size, "NONE");
741#define P_FLAG(n) \
742 if (flags & EFD_##n) { \
743 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
744 flags &= ~EFD_##n; \
745 }
746
747 P_FLAG(SEMAPHORE);
748 P_FLAG(CLOEXEC);
749 P_FLAG(NONBLOCK);
750#undef P_FLAG
751
752 if (flags)
753 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
754
755 return printed;
756}
757
758#define SCA_EFD_FLAGS syscall_arg__scnprintf_eventfd_flags
759
760static size_t syscall_arg__scnprintf_pipe_flags(char *bf, size_t size,
761 struct syscall_arg *arg)
762{
763 int printed = 0, flags = arg->val;
764
765#define P_FLAG(n) \
766 if (flags & O_##n) { \
767 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
768 flags &= ~O_##n; \
769 }
770
771 P_FLAG(CLOEXEC);
772 P_FLAG(NONBLOCK);
773#undef P_FLAG
774
775 if (flags)
776 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
777
778 return printed;
779}
780
781#define SCA_PIPE_FLAGS syscall_arg__scnprintf_pipe_flags
782
783static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscall_arg *arg)
784{
785 int sig = arg->val;
786
787 switch (sig) {
788#define P_SIGNUM(n) case SIG##n: return scnprintf(bf, size, #n)
789 P_SIGNUM(HUP);
790 P_SIGNUM(INT);
791 P_SIGNUM(QUIT);
792 P_SIGNUM(ILL);
793 P_SIGNUM(TRAP);
794 P_SIGNUM(ABRT);
795 P_SIGNUM(BUS);
796 P_SIGNUM(FPE);
797 P_SIGNUM(KILL);
798 P_SIGNUM(USR1);
799 P_SIGNUM(SEGV);
800 P_SIGNUM(USR2);
801 P_SIGNUM(PIPE);
802 P_SIGNUM(ALRM);
803 P_SIGNUM(TERM);
804 P_SIGNUM(STKFLT);
805 P_SIGNUM(CHLD);
806 P_SIGNUM(CONT);
807 P_SIGNUM(STOP);
808 P_SIGNUM(TSTP);
809 P_SIGNUM(TTIN);
810 P_SIGNUM(TTOU);
811 P_SIGNUM(URG);
812 P_SIGNUM(XCPU);
813 P_SIGNUM(XFSZ);
814 P_SIGNUM(VTALRM);
815 P_SIGNUM(PROF);
816 P_SIGNUM(WINCH);
817 P_SIGNUM(IO);
818 P_SIGNUM(PWR);
819 P_SIGNUM(SYS);
820 default: break;
821 }
822
823 return scnprintf(bf, size, "%#x", sig);
824}
825
826#define SCA_SIGNUM syscall_arg__scnprintf_signum
827
828#define TCGETS 0x5401
829
830static const char *tioctls[] = {
831 "TCGETS", "TCSETS", "TCSETSW", "TCSETSF", "TCGETA", "TCSETA", "TCSETAW",
832 "TCSETAF", "TCSBRK", "TCXONC", "TCFLSH", "TIOCEXCL", "TIOCNXCL",
833 "TIOCSCTTY", "TIOCGPGRP", "TIOCSPGRP", "TIOCOUTQ", "TIOCSTI",
834 "TIOCGWINSZ", "TIOCSWINSZ", "TIOCMGET", "TIOCMBIS", "TIOCMBIC",
835 "TIOCMSET", "TIOCGSOFTCAR", "TIOCSSOFTCAR", "FIONREAD", "TIOCLINUX",
836 "TIOCCONS", "TIOCGSERIAL", "TIOCSSERIAL", "TIOCPKT", "FIONBIO",
837 "TIOCNOTTY", "TIOCSETD", "TIOCGETD", "TCSBRKP", [0x27] = "TIOCSBRK",
838 "TIOCCBRK", "TIOCGSID", "TCGETS2", "TCSETS2", "TCSETSW2", "TCSETSF2",
839 "TIOCGRS485", "TIOCSRS485", "TIOCGPTN", "TIOCSPTLCK",
840 "TIOCGDEV||TCGETX", "TCSETX", "TCSETXF", "TCSETXW", "TIOCSIG",
841 "TIOCVHANGUP", "TIOCGPKT", "TIOCGPTLCK", "TIOCGEXCL",
842 [0x50] = "FIONCLEX", "FIOCLEX", "FIOASYNC", "TIOCSERCONFIG",
843 "TIOCSERGWILD", "TIOCSERSWILD", "TIOCGLCKTRMIOS", "TIOCSLCKTRMIOS",
844 "TIOCSERGSTRUCT", "TIOCSERGETLSR", "TIOCSERGETMULTI", "TIOCSERSETMULTI",
845 "TIOCMIWAIT", "TIOCGICOUNT", [0x60] = "FIOQSIZE",
846};
847
848static DEFINE_STRARRAY_OFFSET(tioctls, 0x5401);
849
850#define STRARRAY(arg, name, array) \
851 .arg_scnprintf = { [arg] = SCA_STRARRAY, }, \
852 .arg_parm = { [arg] = &strarray__##array, }
853
294static struct syscall_fmt { 854static struct syscall_fmt {
295 const char *name; 855 const char *name;
296 const char *alias; 856 const char *alias;
297 size_t (*arg_scnprintf[6])(char *bf, size_t size, unsigned long arg, u8 arg_idx, u8 *arg_mask); 857 size_t (*arg_scnprintf[6])(char *bf, size_t size, struct syscall_arg *arg);
858 void *arg_parm[6];
298 bool errmsg; 859 bool errmsg;
299 bool timeout; 860 bool timeout;
300 bool hexret; 861 bool hexret;
301} syscall_fmts[] = { 862} syscall_fmts[] = {
302 { .name = "access", .errmsg = true, }, 863 { .name = "access", .errmsg = true,
864 .arg_scnprintf = { [1] = SCA_ACCMODE, /* mode */ }, },
303 { .name = "arch_prctl", .errmsg = true, .alias = "prctl", }, 865 { .name = "arch_prctl", .errmsg = true, .alias = "prctl", },
304 { .name = "brk", .hexret = true, 866 { .name = "brk", .hexret = true,
305 .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, }, 867 .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, },
306 { .name = "mmap", .hexret = true, }, 868 { .name = "clock_gettime", .errmsg = true, STRARRAY(0, clk_id, clockid), },
869 { .name = "close", .errmsg = true,
870 .arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, },
307 { .name = "connect", .errmsg = true, }, 871 { .name = "connect", .errmsg = true, },
308 { .name = "fstat", .errmsg = true, .alias = "newfstat", }, 872 { .name = "dup", .errmsg = true,
309 { .name = "fstatat", .errmsg = true, .alias = "newfstatat", }, 873 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
874 { .name = "dup2", .errmsg = true,
875 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
876 { .name = "dup3", .errmsg = true,
877 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
878 { .name = "epoll_ctl", .errmsg = true, STRARRAY(1, op, epoll_ctl_ops), },
879 { .name = "eventfd2", .errmsg = true,
880 .arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, },
881 { .name = "faccessat", .errmsg = true,
882 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
883 { .name = "fadvise64", .errmsg = true,
884 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
885 { .name = "fallocate", .errmsg = true,
886 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
887 { .name = "fchdir", .errmsg = true,
888 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
889 { .name = "fchmod", .errmsg = true,
890 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
891 { .name = "fchmodat", .errmsg = true,
892 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
893 { .name = "fchown", .errmsg = true,
894 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
895 { .name = "fchownat", .errmsg = true,
896 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
897 { .name = "fcntl", .errmsg = true,
898 .arg_scnprintf = { [0] = SCA_FD, /* fd */
899 [1] = SCA_STRARRAY, /* cmd */ },
900 .arg_parm = { [1] = &strarray__fcntl_cmds, /* cmd */ }, },
901 { .name = "fdatasync", .errmsg = true,
902 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
903 { .name = "flock", .errmsg = true,
904 .arg_scnprintf = { [0] = SCA_FD, /* fd */
905 [1] = SCA_FLOCK, /* cmd */ }, },
906 { .name = "fsetxattr", .errmsg = true,
907 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
908 { .name = "fstat", .errmsg = true, .alias = "newfstat",
909 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
910 { .name = "fstatat", .errmsg = true, .alias = "newfstatat",
911 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
912 { .name = "fstatfs", .errmsg = true,
913 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
914 { .name = "fsync", .errmsg = true,
915 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
916 { .name = "ftruncate", .errmsg = true,
917 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
310 { .name = "futex", .errmsg = true, 918 { .name = "futex", .errmsg = true,
311 .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, }, 919 .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, },
920 { .name = "futimesat", .errmsg = true,
921 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
922 { .name = "getdents", .errmsg = true,
923 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
924 { .name = "getdents64", .errmsg = true,
925 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
926 { .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), },
927 { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
312 { .name = "ioctl", .errmsg = true, 928 { .name = "ioctl", .errmsg = true,
313 .arg_scnprintf = { [2] = SCA_HEX, /* arg */ }, }, 929 .arg_scnprintf = { [0] = SCA_FD, /* fd */
930 [1] = SCA_STRHEXARRAY, /* cmd */
931 [2] = SCA_HEX, /* arg */ },
932 .arg_parm = { [1] = &strarray__tioctls, /* cmd */ }, },
933 { .name = "kill", .errmsg = true,
934 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
935 { .name = "linkat", .errmsg = true,
936 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
314 { .name = "lseek", .errmsg = true, 937 { .name = "lseek", .errmsg = true,
315 .arg_scnprintf = { [2] = SCA_WHENCE, /* whence */ }, }, 938 .arg_scnprintf = { [0] = SCA_FD, /* fd */
939 [2] = SCA_STRARRAY, /* whence */ },
940 .arg_parm = { [2] = &strarray__whences, /* whence */ }, },
316 { .name = "lstat", .errmsg = true, .alias = "newlstat", }, 941 { .name = "lstat", .errmsg = true, .alias = "newlstat", },
317 { .name = "madvise", .errmsg = true, 942 { .name = "madvise", .errmsg = true,
318 .arg_scnprintf = { [0] = SCA_HEX, /* start */ 943 .arg_scnprintf = { [0] = SCA_HEX, /* start */
319 [2] = SCA_MADV_BHV, /* behavior */ }, }, 944 [2] = SCA_MADV_BHV, /* behavior */ }, },
945 { .name = "mkdirat", .errmsg = true,
946 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
947 { .name = "mknodat", .errmsg = true,
948 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
949 { .name = "mlock", .errmsg = true,
950 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
951 { .name = "mlockall", .errmsg = true,
952 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
320 { .name = "mmap", .hexret = true, 953 { .name = "mmap", .hexret = true,
321 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ 954 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
322 [2] = SCA_MMAP_PROT, /* prot */ 955 [2] = SCA_MMAP_PROT, /* prot */
@@ -327,24 +960,91 @@ static struct syscall_fmt {
327 { .name = "mremap", .hexret = true, 960 { .name = "mremap", .hexret = true,
328 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ 961 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
329 [4] = SCA_HEX, /* new_addr */ }, }, 962 [4] = SCA_HEX, /* new_addr */ }, },
963 { .name = "munlock", .errmsg = true,
964 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
330 { .name = "munmap", .errmsg = true, 965 { .name = "munmap", .errmsg = true,
331 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, }, 966 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
967 { .name = "name_to_handle_at", .errmsg = true,
968 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
969 { .name = "newfstatat", .errmsg = true,
970 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
332 { .name = "open", .errmsg = true, 971 { .name = "open", .errmsg = true,
333 .arg_scnprintf = { [1] = SCA_OPEN_FLAGS, /* flags */ }, }, 972 .arg_scnprintf = { [1] = SCA_OPEN_FLAGS, /* flags */ }, },
334 { .name = "open_by_handle_at", .errmsg = true, 973 { .name = "open_by_handle_at", .errmsg = true,
335 .arg_scnprintf = { [2] = SCA_OPEN_FLAGS, /* flags */ }, }, 974 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
975 [2] = SCA_OPEN_FLAGS, /* flags */ }, },
336 { .name = "openat", .errmsg = true, 976 { .name = "openat", .errmsg = true,
337 .arg_scnprintf = { [2] = SCA_OPEN_FLAGS, /* flags */ }, }, 977 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
978 [2] = SCA_OPEN_FLAGS, /* flags */ }, },
979 { .name = "pipe2", .errmsg = true,
980 .arg_scnprintf = { [1] = SCA_PIPE_FLAGS, /* flags */ }, },
338 { .name = "poll", .errmsg = true, .timeout = true, }, 981 { .name = "poll", .errmsg = true, .timeout = true, },
339 { .name = "ppoll", .errmsg = true, .timeout = true, }, 982 { .name = "ppoll", .errmsg = true, .timeout = true, },
340 { .name = "pread", .errmsg = true, .alias = "pread64", }, 983 { .name = "pread", .errmsg = true, .alias = "pread64",
341 { .name = "pwrite", .errmsg = true, .alias = "pwrite64", }, 984 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
342 { .name = "read", .errmsg = true, }, 985 { .name = "preadv", .errmsg = true, .alias = "pread",
343 { .name = "recvfrom", .errmsg = true, }, 986 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
987 { .name = "prlimit64", .errmsg = true, STRARRAY(1, resource, rlimit_resources), },
988 { .name = "pwrite", .errmsg = true, .alias = "pwrite64",
989 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
990 { .name = "pwritev", .errmsg = true,
991 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
992 { .name = "read", .errmsg = true,
993 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
994 { .name = "readlinkat", .errmsg = true,
995 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
996 { .name = "readv", .errmsg = true,
997 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
998 { .name = "recvfrom", .errmsg = true,
999 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
1000 { .name = "recvmmsg", .errmsg = true,
1001 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
1002 { .name = "recvmsg", .errmsg = true,
1003 .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, },
1004 { .name = "renameat", .errmsg = true,
1005 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
1006 { .name = "rt_sigaction", .errmsg = true,
1007 .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, },
1008 { .name = "rt_sigprocmask", .errmsg = true, STRARRAY(0, how, sighow), },
1009 { .name = "rt_sigqueueinfo", .errmsg = true,
1010 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
1011 { .name = "rt_tgsigqueueinfo", .errmsg = true,
1012 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
344 { .name = "select", .errmsg = true, .timeout = true, }, 1013 { .name = "select", .errmsg = true, .timeout = true, },
345 { .name = "socket", .errmsg = true, }, 1014 { .name = "sendmmsg", .errmsg = true,
1015 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
1016 { .name = "sendmsg", .errmsg = true,
1017 .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, },
1018 { .name = "sendto", .errmsg = true,
1019 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
1020 { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), },
1021 { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
1022 { .name = "shutdown", .errmsg = true,
1023 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1024 { .name = "socket", .errmsg = true,
1025 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
1026 [1] = SCA_SK_TYPE, /* type */ },
1027 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
1028 { .name = "socketpair", .errmsg = true,
1029 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
1030 [1] = SCA_SK_TYPE, /* type */ },
1031 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
346 { .name = "stat", .errmsg = true, .alias = "newstat", }, 1032 { .name = "stat", .errmsg = true, .alias = "newstat", },
1033 { .name = "symlinkat", .errmsg = true,
1034 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
1035 { .name = "tgkill", .errmsg = true,
1036 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
1037 { .name = "tkill", .errmsg = true,
1038 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
347 { .name = "uname", .errmsg = true, .alias = "newuname", }, 1039 { .name = "uname", .errmsg = true, .alias = "newuname", },
1040 { .name = "unlinkat", .errmsg = true,
1041 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
1042 { .name = "utimensat", .errmsg = true,
1043 .arg_scnprintf = { [0] = SCA_FDAT, /* dirfd */ }, },
1044 { .name = "write", .errmsg = true,
1045 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1046 { .name = "writev", .errmsg = true,
1047 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
348}; 1048};
349 1049
350static int syscall_fmt__cmp(const void *name, const void *fmtp) 1050static int syscall_fmt__cmp(const void *name, const void *fmtp)
@@ -364,8 +1064,8 @@ struct syscall {
364 const char *name; 1064 const char *name;
365 bool filtered; 1065 bool filtered;
366 struct syscall_fmt *fmt; 1066 struct syscall_fmt *fmt;
367 size_t (**arg_scnprintf)(char *bf, size_t size, 1067 size_t (**arg_scnprintf)(char *bf, size_t size, struct syscall_arg *arg);
368 unsigned long arg, u8 arg_idx, u8 *args_mask); 1068 void **arg_parm;
369}; 1069};
370 1070
371static size_t fprintf_duration(unsigned long t, FILE *fp) 1071static size_t fprintf_duration(unsigned long t, FILE *fp)
@@ -389,11 +1089,24 @@ struct thread_trace {
389 unsigned long nr_events; 1089 unsigned long nr_events;
390 char *entry_str; 1090 char *entry_str;
391 double runtime_ms; 1091 double runtime_ms;
1092 struct {
1093 int max;
1094 char **table;
1095 } paths;
1096
1097 struct intlist *syscall_stats;
392}; 1098};
393 1099
394static struct thread_trace *thread_trace__new(void) 1100static struct thread_trace *thread_trace__new(void)
395{ 1101{
396 return zalloc(sizeof(struct thread_trace)); 1102 struct thread_trace *ttrace = zalloc(sizeof(struct thread_trace));
1103
1104 if (ttrace)
1105 ttrace->paths.max = -1;
1106
1107 ttrace->syscall_stats = intlist__new(NULL);
1108
1109 return ttrace;
397} 1110}
398 1111
399static struct thread_trace *thread__trace(struct thread *thread, FILE *fp) 1112static struct thread_trace *thread__trace(struct thread *thread, FILE *fp)
@@ -421,26 +1134,140 @@ fail:
421 1134
422struct trace { 1135struct trace {
423 struct perf_tool tool; 1136 struct perf_tool tool;
424 int audit_machine; 1137 struct {
1138 int machine;
1139 int open_id;
1140 } audit;
425 struct { 1141 struct {
426 int max; 1142 int max;
427 struct syscall *table; 1143 struct syscall *table;
428 } syscalls; 1144 } syscalls;
429 struct perf_record_opts opts; 1145 struct perf_record_opts opts;
430 struct machine host; 1146 struct machine *host;
431 u64 base_time; 1147 u64 base_time;
1148 bool full_time;
432 FILE *output; 1149 FILE *output;
433 unsigned long nr_events; 1150 unsigned long nr_events;
434 struct strlist *ev_qualifier; 1151 struct strlist *ev_qualifier;
435 bool not_ev_qualifier; 1152 bool not_ev_qualifier;
1153 bool live;
1154 const char *last_vfs_getname;
436 struct intlist *tid_list; 1155 struct intlist *tid_list;
437 struct intlist *pid_list; 1156 struct intlist *pid_list;
438 bool sched; 1157 bool sched;
439 bool multiple_threads; 1158 bool multiple_threads;
1159 bool summary;
1160 bool show_comm;
1161 bool show_tool_stats;
440 double duration_filter; 1162 double duration_filter;
441 double runtime_ms; 1163 double runtime_ms;
1164 struct {
1165 u64 vfs_getname, proc_getname;
1166 } stats;
442}; 1167};
443 1168
1169static int trace__set_fd_pathname(struct thread *thread, int fd, const char *pathname)
1170{
1171 struct thread_trace *ttrace = thread->priv;
1172
1173 if (fd > ttrace->paths.max) {
1174 char **npath = realloc(ttrace->paths.table, (fd + 1) * sizeof(char *));
1175
1176 if (npath == NULL)
1177 return -1;
1178
1179 if (ttrace->paths.max != -1) {
1180 memset(npath + ttrace->paths.max + 1, 0,
1181 (fd - ttrace->paths.max) * sizeof(char *));
1182 } else {
1183 memset(npath, 0, (fd + 1) * sizeof(char *));
1184 }
1185
1186 ttrace->paths.table = npath;
1187 ttrace->paths.max = fd;
1188 }
1189
1190 ttrace->paths.table[fd] = strdup(pathname);
1191
1192 return ttrace->paths.table[fd] != NULL ? 0 : -1;
1193}
1194
1195static int thread__read_fd_path(struct thread *thread, int fd)
1196{
1197 char linkname[PATH_MAX], pathname[PATH_MAX];
1198 struct stat st;
1199 int ret;
1200
1201 if (thread->pid_ == thread->tid) {
1202 scnprintf(linkname, sizeof(linkname),
1203 "/proc/%d/fd/%d", thread->pid_, fd);
1204 } else {
1205 scnprintf(linkname, sizeof(linkname),
1206 "/proc/%d/task/%d/fd/%d", thread->pid_, thread->tid, fd);
1207 }
1208
1209 if (lstat(linkname, &st) < 0 || st.st_size + 1 > (off_t)sizeof(pathname))
1210 return -1;
1211
1212 ret = readlink(linkname, pathname, sizeof(pathname));
1213
1214 if (ret < 0 || ret > st.st_size)
1215 return -1;
1216
1217 pathname[ret] = '\0';
1218 return trace__set_fd_pathname(thread, fd, pathname);
1219}
1220
1221static const char *thread__fd_path(struct thread *thread, int fd,
1222 struct trace *trace)
1223{
1224 struct thread_trace *ttrace = thread->priv;
1225
1226 if (ttrace == NULL)
1227 return NULL;
1228
1229 if (fd < 0)
1230 return NULL;
1231
1232 if ((fd > ttrace->paths.max || ttrace->paths.table[fd] == NULL))
1233 if (!trace->live)
1234 return NULL;
1235 ++trace->stats.proc_getname;
1236 if (thread__read_fd_path(thread, fd)) {
1237 return NULL;
1238 }
1239
1240 return ttrace->paths.table[fd];
1241}
1242
1243static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
1244 struct syscall_arg *arg)
1245{
1246 int fd = arg->val;
1247 size_t printed = scnprintf(bf, size, "%d", fd);
1248 const char *path = thread__fd_path(arg->thread, fd, arg->trace);
1249
1250 if (path)
1251 printed += scnprintf(bf + printed, size - printed, "<%s>", path);
1252
1253 return printed;
1254}
1255
1256static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
1257 struct syscall_arg *arg)
1258{
1259 int fd = arg->val;
1260 size_t printed = syscall_arg__scnprintf_fd(bf, size, arg);
1261 struct thread_trace *ttrace = arg->thread->priv;
1262
1263 if (ttrace && fd >= 0 && fd <= ttrace->paths.max) {
1264 free(ttrace->paths.table[fd]);
1265 ttrace->paths.table[fd] = NULL;
1266 }
1267
1268 return printed;
1269}
1270
444static bool trace__filter_duration(struct trace *trace, double t) 1271static bool trace__filter_duration(struct trace *trace, double t)
445{ 1272{
446 return t < (trace->duration_filter * NSEC_PER_MSEC); 1273 return t < (trace->duration_filter * NSEC_PER_MSEC);
@@ -454,10 +1281,12 @@ static size_t trace__fprintf_tstamp(struct trace *trace, u64 tstamp, FILE *fp)
454} 1281}
455 1282
456static bool done = false; 1283static bool done = false;
1284static bool interrupted = false;
457 1285
458static void sig_handler(int sig __maybe_unused) 1286static void sig_handler(int sig)
459{ 1287{
460 done = true; 1288 done = true;
1289 interrupted = sig == SIGINT;
461} 1290}
462 1291
463static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thread, 1292static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thread,
@@ -466,14 +1295,17 @@ static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thre
466 size_t printed = trace__fprintf_tstamp(trace, tstamp, fp); 1295 size_t printed = trace__fprintf_tstamp(trace, tstamp, fp);
467 printed += fprintf_duration(duration, fp); 1296 printed += fprintf_duration(duration, fp);
468 1297
469 if (trace->multiple_threads) 1298 if (trace->multiple_threads) {
1299 if (trace->show_comm)
1300 printed += fprintf(fp, "%.14s/", thread__comm_str(thread));
470 printed += fprintf(fp, "%d ", thread->tid); 1301 printed += fprintf(fp, "%d ", thread->tid);
1302 }
471 1303
472 return printed; 1304 return printed;
473} 1305}
474 1306
475static int trace__process_event(struct trace *trace, struct machine *machine, 1307static int trace__process_event(struct trace *trace, struct machine *machine,
476 union perf_event *event) 1308 union perf_event *event, struct perf_sample *sample)
477{ 1309{
478 int ret = 0; 1310 int ret = 0;
479 1311
@@ -481,9 +1313,9 @@ static int trace__process_event(struct trace *trace, struct machine *machine,
481 case PERF_RECORD_LOST: 1313 case PERF_RECORD_LOST:
482 color_fprintf(trace->output, PERF_COLOR_RED, 1314 color_fprintf(trace->output, PERF_COLOR_RED,
483 "LOST %" PRIu64 " events!\n", event->lost.lost); 1315 "LOST %" PRIu64 " events!\n", event->lost.lost);
484 ret = machine__process_lost_event(machine, event); 1316 ret = machine__process_lost_event(machine, event, sample);
485 default: 1317 default:
486 ret = machine__process_event(machine, event); 1318 ret = machine__process_event(machine, event, sample);
487 break; 1319 break;
488 } 1320 }
489 1321
@@ -492,11 +1324,11 @@ static int trace__process_event(struct trace *trace, struct machine *machine,
492 1324
493static int trace__tool_process(struct perf_tool *tool, 1325static int trace__tool_process(struct perf_tool *tool,
494 union perf_event *event, 1326 union perf_event *event,
495 struct perf_sample *sample __maybe_unused, 1327 struct perf_sample *sample,
496 struct machine *machine) 1328 struct machine *machine)
497{ 1329{
498 struct trace *trace = container_of(tool, struct trace, tool); 1330 struct trace *trace = container_of(tool, struct trace, tool);
499 return trace__process_event(trace, machine, event); 1331 return trace__process_event(trace, machine, event, sample);
500} 1332}
501 1333
502static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist) 1334static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
@@ -506,16 +1338,17 @@ static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
506 if (err) 1338 if (err)
507 return err; 1339 return err;
508 1340
509 machine__init(&trace->host, "", HOST_KERNEL_ID); 1341 trace->host = machine__new_host();
510 machine__create_kernel_maps(&trace->host); 1342 if (trace->host == NULL)
1343 return -ENOMEM;
511 1344
512 if (perf_target__has_task(&trace->opts.target)) { 1345 if (perf_target__has_task(&trace->opts.target)) {
513 err = perf_event__synthesize_thread_map(&trace->tool, evlist->threads, 1346 err = perf_event__synthesize_thread_map(&trace->tool, evlist->threads,
514 trace__tool_process, 1347 trace__tool_process,
515 &trace->host); 1348 trace->host);
516 } else { 1349 } else {
517 err = perf_event__synthesize_threads(&trace->tool, trace__tool_process, 1350 err = perf_event__synthesize_threads(&trace->tool, trace__tool_process,
518 &trace->host); 1351 trace->host);
519 } 1352 }
520 1353
521 if (err) 1354 if (err)
@@ -533,6 +1366,9 @@ static int syscall__set_arg_fmts(struct syscall *sc)
533 if (sc->arg_scnprintf == NULL) 1366 if (sc->arg_scnprintf == NULL)
534 return -1; 1367 return -1;
535 1368
1369 if (sc->fmt)
1370 sc->arg_parm = sc->fmt->arg_parm;
1371
536 for (field = sc->tp_format->format.fields->next; field; field = field->next) { 1372 for (field = sc->tp_format->format.fields->next; field; field = field->next) {
537 if (sc->fmt && sc->fmt->arg_scnprintf[idx]) 1373 if (sc->fmt && sc->fmt->arg_scnprintf[idx])
538 sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx]; 1374 sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx];
@@ -548,7 +1384,7 @@ static int trace__read_syscall_info(struct trace *trace, int id)
548{ 1384{
549 char tp_name[128]; 1385 char tp_name[128];
550 struct syscall *sc; 1386 struct syscall *sc;
551 const char *name = audit_syscall_to_name(id, trace->audit_machine); 1387 const char *name = audit_syscall_to_name(id, trace->audit.machine);
552 1388
553 if (name == NULL) 1389 if (name == NULL)
554 return -1; 1390 return -1;
@@ -603,32 +1439,52 @@ static int trace__read_syscall_info(struct trace *trace, int id)
603} 1439}
604 1440
605static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size, 1441static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
606 unsigned long *args) 1442 unsigned long *args, struct trace *trace,
1443 struct thread *thread)
607{ 1444{
608 int i = 0;
609 size_t printed = 0; 1445 size_t printed = 0;
610 1446
611 if (sc->tp_format != NULL) { 1447 if (sc->tp_format != NULL) {
612 struct format_field *field; 1448 struct format_field *field;
613 u8 mask = 0, bit = 1; 1449 u8 bit = 1;
1450 struct syscall_arg arg = {
1451 .idx = 0,
1452 .mask = 0,
1453 .trace = trace,
1454 .thread = thread,
1455 };
614 1456
615 for (field = sc->tp_format->format.fields->next; field; 1457 for (field = sc->tp_format->format.fields->next; field;
616 field = field->next, ++i, bit <<= 1) { 1458 field = field->next, ++arg.idx, bit <<= 1) {
617 if (mask & bit) 1459 if (arg.mask & bit)
1460 continue;
1461 /*
1462 * Suppress this argument if its value is zero and
1463 * and we don't have a string associated in an
1464 * strarray for it.
1465 */
1466 if (args[arg.idx] == 0 &&
1467 !(sc->arg_scnprintf &&
1468 sc->arg_scnprintf[arg.idx] == SCA_STRARRAY &&
1469 sc->arg_parm[arg.idx]))
618 continue; 1470 continue;
619 1471
620 printed += scnprintf(bf + printed, size - printed, 1472 printed += scnprintf(bf + printed, size - printed,
621 "%s%s: ", printed ? ", " : "", field->name); 1473 "%s%s: ", printed ? ", " : "", field->name);
622 1474 if (sc->arg_scnprintf && sc->arg_scnprintf[arg.idx]) {
623 if (sc->arg_scnprintf && sc->arg_scnprintf[i]) { 1475 arg.val = args[arg.idx];
624 printed += sc->arg_scnprintf[i](bf + printed, size - printed, 1476 if (sc->arg_parm)
625 args[i], i, &mask); 1477 arg.parm = sc->arg_parm[arg.idx];
1478 printed += sc->arg_scnprintf[arg.idx](bf + printed,
1479 size - printed, &arg);
626 } else { 1480 } else {
627 printed += scnprintf(bf + printed, size - printed, 1481 printed += scnprintf(bf + printed, size - printed,
628 "%ld", args[i]); 1482 "%ld", args[arg.idx]);
629 } 1483 }
630 } 1484 }
631 } else { 1485 } else {
1486 int i = 0;
1487
632 while (i < 6) { 1488 while (i < 6) {
633 printed += scnprintf(bf + printed, size - printed, 1489 printed += scnprintf(bf + printed, size - printed,
634 "%sarg%d: %ld", 1490 "%sarg%d: %ld",
@@ -644,10 +1500,8 @@ typedef int (*tracepoint_handler)(struct trace *trace, struct perf_evsel *evsel,
644 struct perf_sample *sample); 1500 struct perf_sample *sample);
645 1501
646static struct syscall *trace__syscall_info(struct trace *trace, 1502static struct syscall *trace__syscall_info(struct trace *trace,
647 struct perf_evsel *evsel, 1503 struct perf_evsel *evsel, int id)
648 struct perf_sample *sample)
649{ 1504{
650 int id = perf_evsel__intval(evsel, sample, "id");
651 1505
652 if (id < 0) { 1506 if (id < 0) {
653 1507
@@ -688,6 +1542,32 @@ out_cant_read:
688 return NULL; 1542 return NULL;
689} 1543}
690 1544
1545static void thread__update_stats(struct thread_trace *ttrace,
1546 int id, struct perf_sample *sample)
1547{
1548 struct int_node *inode;
1549 struct stats *stats;
1550 u64 duration = 0;
1551
1552 inode = intlist__findnew(ttrace->syscall_stats, id);
1553 if (inode == NULL)
1554 return;
1555
1556 stats = inode->priv;
1557 if (stats == NULL) {
1558 stats = malloc(sizeof(struct stats));
1559 if (stats == NULL)
1560 return;
1561 init_stats(stats);
1562 inode->priv = stats;
1563 }
1564
1565 if (ttrace->entry_time && sample->time > ttrace->entry_time)
1566 duration = sample->time - ttrace->entry_time;
1567
1568 update_stats(stats, duration);
1569}
1570
691static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel, 1571static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
692 struct perf_sample *sample) 1572 struct perf_sample *sample)
693{ 1573{
@@ -695,7 +1575,8 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
695 void *args; 1575 void *args;
696 size_t printed = 0; 1576 size_t printed = 0;
697 struct thread *thread; 1577 struct thread *thread;
698 struct syscall *sc = trace__syscall_info(trace, evsel, sample); 1578 int id = perf_evsel__sc_tp_uint(evsel, id, sample);
1579 struct syscall *sc = trace__syscall_info(trace, evsel, id);
699 struct thread_trace *ttrace; 1580 struct thread_trace *ttrace;
700 1581
701 if (sc == NULL) 1582 if (sc == NULL)
@@ -704,18 +1585,12 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
704 if (sc->filtered) 1585 if (sc->filtered)
705 return 0; 1586 return 0;
706 1587
707 thread = machine__findnew_thread(&trace->host, sample->pid, 1588 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
708 sample->tid);
709 ttrace = thread__trace(thread, trace->output); 1589 ttrace = thread__trace(thread, trace->output);
710 if (ttrace == NULL) 1590 if (ttrace == NULL)
711 return -1; 1591 return -1;
712 1592
713 args = perf_evsel__rawptr(evsel, sample, "args"); 1593 args = perf_evsel__sc_tp_ptr(evsel, args, sample);
714 if (args == NULL) {
715 fprintf(trace->output, "Problems reading syscall arguments\n");
716 return -1;
717 }
718
719 ttrace = thread->priv; 1594 ttrace = thread->priv;
720 1595
721 if (ttrace->entry_str == NULL) { 1596 if (ttrace->entry_str == NULL) {
@@ -728,7 +1603,8 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
728 msg = ttrace->entry_str; 1603 msg = ttrace->entry_str;
729 printed += scnprintf(msg + printed, 1024 - printed, "%s(", sc->name); 1604 printed += scnprintf(msg + printed, 1024 - printed, "%s(", sc->name);
730 1605
731 printed += syscall__scnprintf_args(sc, msg + printed, 1024 - printed, args); 1606 printed += syscall__scnprintf_args(sc, msg + printed, 1024 - printed,
1607 args, trace, thread);
732 1608
733 if (!strcmp(sc->name, "exit_group") || !strcmp(sc->name, "exit")) { 1609 if (!strcmp(sc->name, "exit_group") || !strcmp(sc->name, "exit")) {
734 if (!trace->duration_filter) { 1610 if (!trace->duration_filter) {
@@ -747,7 +1623,8 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
747 int ret; 1623 int ret;
748 u64 duration = 0; 1624 u64 duration = 0;
749 struct thread *thread; 1625 struct thread *thread;
750 struct syscall *sc = trace__syscall_info(trace, evsel, sample); 1626 int id = perf_evsel__sc_tp_uint(evsel, id, sample);
1627 struct syscall *sc = trace__syscall_info(trace, evsel, id);
751 struct thread_trace *ttrace; 1628 struct thread_trace *ttrace;
752 1629
753 if (sc == NULL) 1630 if (sc == NULL)
@@ -756,13 +1633,21 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
756 if (sc->filtered) 1633 if (sc->filtered)
757 return 0; 1634 return 0;
758 1635
759 thread = machine__findnew_thread(&trace->host, sample->pid, 1636 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
760 sample->tid);
761 ttrace = thread__trace(thread, trace->output); 1637 ttrace = thread__trace(thread, trace->output);
762 if (ttrace == NULL) 1638 if (ttrace == NULL)
763 return -1; 1639 return -1;
764 1640
765 ret = perf_evsel__intval(evsel, sample, "ret"); 1641 if (trace->summary)
1642 thread__update_stats(ttrace, id, sample);
1643
1644 ret = perf_evsel__sc_tp_uint(evsel, ret, sample);
1645
1646 if (id == trace->audit.open_id && ret >= 0 && trace->last_vfs_getname) {
1647 trace__set_fd_pathname(thread, ret, trace->last_vfs_getname);
1648 trace->last_vfs_getname = NULL;
1649 ++trace->stats.vfs_getname;
1650 }
766 1651
767 ttrace = thread->priv; 1652 ttrace = thread->priv;
768 1653
@@ -808,12 +1693,19 @@ out:
808 return 0; 1693 return 0;
809} 1694}
810 1695
1696static int trace__vfs_getname(struct trace *trace, struct perf_evsel *evsel,
1697 struct perf_sample *sample)
1698{
1699 trace->last_vfs_getname = perf_evsel__rawptr(evsel, sample, "pathname");
1700 return 0;
1701}
1702
811static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evsel, 1703static int trace__sched_stat_runtime(struct trace *trace, struct perf_evsel *evsel,
812 struct perf_sample *sample) 1704 struct perf_sample *sample)
813{ 1705{
814 u64 runtime = perf_evsel__intval(evsel, sample, "runtime"); 1706 u64 runtime = perf_evsel__intval(evsel, sample, "runtime");
815 double runtime_ms = (double)runtime / NSEC_PER_MSEC; 1707 double runtime_ms = (double)runtime / NSEC_PER_MSEC;
816 struct thread *thread = machine__findnew_thread(&trace->host, 1708 struct thread *thread = machine__findnew_thread(trace->host,
817 sample->pid, 1709 sample->pid,
818 sample->tid); 1710 sample->tid);
819 struct thread_trace *ttrace = thread__trace(thread, trace->output); 1711 struct thread_trace *ttrace = thread__trace(thread, trace->output);
@@ -856,12 +1748,12 @@ static int trace__process_sample(struct perf_tool *tool,
856 struct trace *trace = container_of(tool, struct trace, tool); 1748 struct trace *trace = container_of(tool, struct trace, tool);
857 int err = 0; 1749 int err = 0;
858 1750
859 tracepoint_handler handler = evsel->handler.func; 1751 tracepoint_handler handler = evsel->handler;
860 1752
861 if (skip_sample(trace, sample)) 1753 if (skip_sample(trace, sample))
862 return 0; 1754 return 0;
863 1755
864 if (trace->base_time == 0) 1756 if (!trace->full_time && trace->base_time == 0)
865 trace->base_time = sample->time; 1757 trace->base_time = sample->time;
866 1758
867 if (handler) 1759 if (handler)
@@ -901,6 +1793,51 @@ static int parse_target_str(struct trace *trace)
901 return 0; 1793 return 0;
902} 1794}
903 1795
1796static int trace__record(int argc, const char **argv)
1797{
1798 unsigned int rec_argc, i, j;
1799 const char **rec_argv;
1800 const char * const record_args[] = {
1801 "record",
1802 "-R",
1803 "-m", "1024",
1804 "-c", "1",
1805 "-e", "raw_syscalls:sys_enter,raw_syscalls:sys_exit",
1806 };
1807
1808 rec_argc = ARRAY_SIZE(record_args) + argc;
1809 rec_argv = calloc(rec_argc + 1, sizeof(char *));
1810
1811 if (rec_argv == NULL)
1812 return -ENOMEM;
1813
1814 for (i = 0; i < ARRAY_SIZE(record_args); i++)
1815 rec_argv[i] = record_args[i];
1816
1817 for (j = 0; j < (unsigned int)argc; j++, i++)
1818 rec_argv[i] = argv[j];
1819
1820 return cmd_record(i, rec_argv, NULL);
1821}
1822
1823static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp);
1824
1825static void perf_evlist__add_vfs_getname(struct perf_evlist *evlist)
1826{
1827 struct perf_evsel *evsel = perf_evsel__newtp("probe", "vfs_getname",
1828 evlist->nr_entries);
1829 if (evsel == NULL)
1830 return;
1831
1832 if (perf_evsel__field(evsel, "pathname") == NULL) {
1833 perf_evsel__delete(evsel);
1834 return;
1835 }
1836
1837 evsel->handler = trace__vfs_getname;
1838 perf_evlist__add(evlist, evsel);
1839}
1840
904static int trace__run(struct trace *trace, int argc, const char **argv) 1841static int trace__run(struct trace *trace, int argc, const char **argv)
905{ 1842{
906 struct perf_evlist *evlist = perf_evlist__new(); 1843 struct perf_evlist *evlist = perf_evlist__new();
@@ -909,23 +1846,22 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
909 unsigned long before; 1846 unsigned long before;
910 const bool forks = argc > 0; 1847 const bool forks = argc > 0;
911 1848
1849 trace->live = true;
1850
912 if (evlist == NULL) { 1851 if (evlist == NULL) {
913 fprintf(trace->output, "Not enough memory to run!\n"); 1852 fprintf(trace->output, "Not enough memory to run!\n");
914 goto out; 1853 goto out;
915 } 1854 }
916 1855
917 if (perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_enter", trace__sys_enter) || 1856 if (perf_evlist__add_syscall_newtp(evlist, trace__sys_enter, trace__sys_exit))
918 perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_exit", trace__sys_exit)) { 1857 goto out_error_tp;
919 fprintf(trace->output, "Couldn't read the raw_syscalls tracepoints information!\n"); 1858
920 goto out_delete_evlist; 1859 perf_evlist__add_vfs_getname(evlist);
921 }
922 1860
923 if (trace->sched && 1861 if (trace->sched &&
924 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime", 1862 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime",
925 trace__sched_stat_runtime)) { 1863 trace__sched_stat_runtime))
926 fprintf(trace->output, "Couldn't read the sched_stat_runtime tracepoint information!\n"); 1864 goto out_error_tp;
927 goto out_delete_evlist;
928 }
929 1865
930 err = perf_evlist__create_maps(evlist, &trace->opts.target); 1866 err = perf_evlist__create_maps(evlist, &trace->opts.target);
931 if (err < 0) { 1867 if (err < 0) {
@@ -954,10 +1890,8 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
954 } 1890 }
955 1891
956 err = perf_evlist__open(evlist); 1892 err = perf_evlist__open(evlist);
957 if (err < 0) { 1893 if (err < 0)
958 fprintf(trace->output, "Couldn't create the events: %s\n", strerror(errno)); 1894 goto out_error_open;
959 goto out_delete_maps;
960 }
961 1895
962 err = perf_evlist__mmap(evlist, UINT_MAX, false); 1896 err = perf_evlist__mmap(evlist, UINT_MAX, false);
963 if (err < 0) { 1897 if (err < 0) {
@@ -990,11 +1924,11 @@ again:
990 goto next_event; 1924 goto next_event;
991 } 1925 }
992 1926
993 if (trace->base_time == 0) 1927 if (!trace->full_time && trace->base_time == 0)
994 trace->base_time = sample.time; 1928 trace->base_time = sample.time;
995 1929
996 if (type != PERF_RECORD_SAMPLE) { 1930 if (type != PERF_RECORD_SAMPLE) {
997 trace__process_event(trace, &trace->host, event); 1931 trace__process_event(trace, trace->host, event, &sample);
998 continue; 1932 continue;
999 } 1933 }
1000 1934
@@ -1011,29 +1945,41 @@ again:
1011 goto next_event; 1945 goto next_event;
1012 } 1946 }
1013 1947
1014 handler = evsel->handler.func; 1948 handler = evsel->handler;
1015 handler(trace, evsel, &sample); 1949 handler(trace, evsel, &sample);
1016next_event: 1950next_event:
1017 perf_evlist__mmap_consume(evlist, i); 1951 perf_evlist__mmap_consume(evlist, i);
1018 1952
1019 if (done) 1953 if (interrupted)
1020 goto out_unmap_evlist; 1954 goto out_disable;
1021 } 1955 }
1022 } 1956 }
1023 1957
1024 if (trace->nr_events == before) { 1958 if (trace->nr_events == before) {
1025 if (done) 1959 int timeout = done ? 100 : -1;
1026 goto out_unmap_evlist;
1027 1960
1028 poll(evlist->pollfd, evlist->nr_fds, -1); 1961 if (poll(evlist->pollfd, evlist->nr_fds, timeout) > 0)
1962 goto again;
1963 } else {
1964 goto again;
1029 } 1965 }
1030 1966
1031 if (done) 1967out_disable:
1032 perf_evlist__disable(evlist); 1968 perf_evlist__disable(evlist);
1033 1969
1034 goto again; 1970 if (!err) {
1971 if (trace->summary)
1972 trace__fprintf_thread_summary(trace, trace->output);
1973
1974 if (trace->show_tool_stats) {
1975 fprintf(trace->output, "Stats:\n "
1976 " vfs_getname : %" PRIu64 "\n"
1977 " proc_getname: %" PRIu64 "\n",
1978 trace->stats.vfs_getname,
1979 trace->stats.proc_getname);
1980 }
1981 }
1035 1982
1036out_unmap_evlist:
1037 perf_evlist__munmap(evlist); 1983 perf_evlist__munmap(evlist);
1038out_close_evlist: 1984out_close_evlist:
1039 perf_evlist__close(evlist); 1985 perf_evlist__close(evlist);
@@ -1042,7 +1988,22 @@ out_delete_maps:
1042out_delete_evlist: 1988out_delete_evlist:
1043 perf_evlist__delete(evlist); 1989 perf_evlist__delete(evlist);
1044out: 1990out:
1991 trace->live = false;
1045 return err; 1992 return err;
1993{
1994 char errbuf[BUFSIZ];
1995
1996out_error_tp:
1997 perf_evlist__strerror_tp(evlist, errno, errbuf, sizeof(errbuf));
1998 goto out_error;
1999
2000out_error_open:
2001 perf_evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf));
2002
2003out_error:
2004 fprintf(trace->output, "%s\n", errbuf);
2005 goto out_delete_evlist;
2006}
1046} 2007}
1047 2008
1048static int trace__replay(struct trace *trace) 2009static int trace__replay(struct trace *trace)
@@ -1050,8 +2011,12 @@ static int trace__replay(struct trace *trace)
1050 const struct perf_evsel_str_handler handlers[] = { 2011 const struct perf_evsel_str_handler handlers[] = {
1051 { "raw_syscalls:sys_enter", trace__sys_enter, }, 2012 { "raw_syscalls:sys_enter", trace__sys_enter, },
1052 { "raw_syscalls:sys_exit", trace__sys_exit, }, 2013 { "raw_syscalls:sys_exit", trace__sys_exit, },
2014 { "probe:vfs_getname", trace__vfs_getname, },
2015 };
2016 struct perf_data_file file = {
2017 .path = input_name,
2018 .mode = PERF_DATA_MODE_READ,
1053 }; 2019 };
1054
1055 struct perf_session *session; 2020 struct perf_session *session;
1056 int err = -1; 2021 int err = -1;
1057 2022
@@ -1074,11 +2039,12 @@ static int trace__replay(struct trace *trace)
1074 if (symbol__init() < 0) 2039 if (symbol__init() < 0)
1075 return -1; 2040 return -1;
1076 2041
1077 session = perf_session__new(input_name, O_RDONLY, 0, false, 2042 session = perf_session__new(&file, false, &trace->tool);
1078 &trace->tool);
1079 if (session == NULL) 2043 if (session == NULL)
1080 return -ENOMEM; 2044 return -ENOMEM;
1081 2045
2046 trace->host = &session->machines.host;
2047
1082 err = perf_session__set_tracepoints_handlers(session, handlers); 2048 err = perf_session__set_tracepoints_handlers(session, handlers);
1083 if (err) 2049 if (err)
1084 goto out; 2050 goto out;
@@ -1103,6 +2069,9 @@ static int trace__replay(struct trace *trace)
1103 if (err) 2069 if (err)
1104 pr_err("Failed to process events, error %d", err); 2070 pr_err("Failed to process events, error %d", err);
1105 2071
2072 else if (trace->summary)
2073 trace__fprintf_thread_summary(trace, trace->output);
2074
1106out: 2075out:
1107 perf_session__delete(session); 2076 perf_session__delete(session);
1108 2077
@@ -1113,47 +2082,111 @@ static size_t trace__fprintf_threads_header(FILE *fp)
1113{ 2082{
1114 size_t printed; 2083 size_t printed;
1115 2084
1116 printed = fprintf(fp, "\n _____________________________________________________________________\n"); 2085 printed = fprintf(fp, "\n _____________________________________________________________________________\n");
1117 printed += fprintf(fp," __) Summary of events (__\n\n"); 2086 printed += fprintf(fp, " __) Summary of events (__\n\n");
1118 printed += fprintf(fp," [ task - pid ] [ events ] [ ratio ] [ runtime ]\n"); 2087 printed += fprintf(fp, " [ task - pid ] [ events ] [ ratio ] [ runtime ]\n");
1119 printed += fprintf(fp," _____________________________________________________________________\n\n"); 2088 printed += fprintf(fp, " syscall count min max avg stddev\n");
2089 printed += fprintf(fp, " msec msec msec %%\n");
2090 printed += fprintf(fp, " _____________________________________________________________________________\n\n");
1120 2091
1121 return printed; 2092 return printed;
1122} 2093}
1123 2094
1124static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp) 2095static size_t thread__dump_stats(struct thread_trace *ttrace,
2096 struct trace *trace, FILE *fp)
1125{ 2097{
1126 size_t printed = trace__fprintf_threads_header(fp); 2098 struct stats *stats;
1127 struct rb_node *nd; 2099 size_t printed = 0;
1128 2100 struct syscall *sc;
1129 for (nd = rb_first(&trace->host.threads); nd; nd = rb_next(nd)) { 2101 struct int_node *inode = intlist__first(ttrace->syscall_stats);
1130 struct thread *thread = rb_entry(nd, struct thread, rb_node);
1131 struct thread_trace *ttrace = thread->priv;
1132 const char *color;
1133 double ratio;
1134
1135 if (ttrace == NULL)
1136 continue;
1137 2102
1138 ratio = (double)ttrace->nr_events / trace->nr_events * 100.0; 2103 if (inode == NULL)
2104 return 0;
1139 2105
1140 color = PERF_COLOR_NORMAL; 2106 printed += fprintf(fp, "\n");
1141 if (ratio > 50.0) 2107
1142 color = PERF_COLOR_RED; 2108 /* each int_node is a syscall */
1143 else if (ratio > 25.0) 2109 while (inode) {
1144 color = PERF_COLOR_GREEN; 2110 stats = inode->priv;
1145 else if (ratio > 5.0) 2111 if (stats) {
1146 color = PERF_COLOR_YELLOW; 2112 double min = (double)(stats->min) / NSEC_PER_MSEC;
2113 double max = (double)(stats->max) / NSEC_PER_MSEC;
2114 double avg = avg_stats(stats);
2115 double pct;
2116 u64 n = (u64) stats->n;
2117
2118 pct = avg ? 100.0 * stddev_stats(stats)/avg : 0.0;
2119 avg /= NSEC_PER_MSEC;
2120
2121 sc = &trace->syscalls.table[inode->i];
2122 printed += fprintf(fp, "%24s %14s : ", "", sc->name);
2123 printed += fprintf(fp, "%5" PRIu64 " %8.3f %8.3f",
2124 n, min, max);
2125 printed += fprintf(fp, " %8.3f %6.2f\n", avg, pct);
2126 }
1147 2127
1148 printed += color_fprintf(fp, color, "%20s", thread->comm); 2128 inode = intlist__next(inode);
1149 printed += fprintf(fp, " - %-5d :%11lu [", thread->tid, ttrace->nr_events);
1150 printed += color_fprintf(fp, color, "%5.1f%%", ratio);
1151 printed += fprintf(fp, " ] %10.3f ms\n", ttrace->runtime_ms);
1152 } 2129 }
1153 2130
2131 printed += fprintf(fp, "\n\n");
2132
1154 return printed; 2133 return printed;
1155} 2134}
1156 2135
2136/* struct used to pass data to per-thread function */
2137struct summary_data {
2138 FILE *fp;
2139 struct trace *trace;
2140 size_t printed;
2141};
2142
2143static int trace__fprintf_one_thread(struct thread *thread, void *priv)
2144{
2145 struct summary_data *data = priv;
2146 FILE *fp = data->fp;
2147 size_t printed = data->printed;
2148 struct trace *trace = data->trace;
2149 struct thread_trace *ttrace = thread->priv;
2150 const char *color;
2151 double ratio;
2152
2153 if (ttrace == NULL)
2154 return 0;
2155
2156 ratio = (double)ttrace->nr_events / trace->nr_events * 100.0;
2157
2158 color = PERF_COLOR_NORMAL;
2159 if (ratio > 50.0)
2160 color = PERF_COLOR_RED;
2161 else if (ratio > 25.0)
2162 color = PERF_COLOR_GREEN;
2163 else if (ratio > 5.0)
2164 color = PERF_COLOR_YELLOW;
2165
2166 printed += color_fprintf(fp, color, "%20s", thread__comm_str(thread));
2167 printed += fprintf(fp, " - %-5d :%11lu [", thread->tid, ttrace->nr_events);
2168 printed += color_fprintf(fp, color, "%5.1f%%", ratio);
2169 printed += fprintf(fp, " ] %10.3f ms\n", ttrace->runtime_ms);
2170 printed += thread__dump_stats(ttrace, trace, fp);
2171
2172 data->printed += printed;
2173
2174 return 0;
2175}
2176
2177static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp)
2178{
2179 struct summary_data data = {
2180 .fp = fp,
2181 .trace = trace
2182 };
2183 data.printed = trace__fprintf_threads_header(fp);
2184
2185 machine__for_each_thread(trace->host, trace__fprintf_one_thread, &data);
2186
2187 return data.printed;
2188}
2189
1157static int trace__set_duration(const struct option *opt, const char *str, 2190static int trace__set_duration(const struct option *opt, const char *str,
1158 int unset __maybe_unused) 2191 int unset __maybe_unused)
1159{ 2192{
@@ -1185,10 +2218,15 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
1185 const char * const trace_usage[] = { 2218 const char * const trace_usage[] = {
1186 "perf trace [<options>] [<command>]", 2219 "perf trace [<options>] [<command>]",
1187 "perf trace [<options>] -- <command> [<options>]", 2220 "perf trace [<options>] -- <command> [<options>]",
2221 "perf trace record [<options>] [<command>]",
2222 "perf trace record [<options>] -- <command> [<options>]",
1188 NULL 2223 NULL
1189 }; 2224 };
1190 struct trace trace = { 2225 struct trace trace = {
1191 .audit_machine = audit_detect_machine(), 2226 .audit = {
2227 .machine = audit_detect_machine(),
2228 .open_id = audit_name_to_syscall("open", trace.audit.machine),
2229 },
1192 .syscalls = { 2230 .syscalls = {
1193 . max = -1, 2231 . max = -1,
1194 }, 2232 },
@@ -1203,10 +2241,14 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
1203 .mmap_pages = 1024, 2241 .mmap_pages = 1024,
1204 }, 2242 },
1205 .output = stdout, 2243 .output = stdout,
2244 .show_comm = true,
1206 }; 2245 };
1207 const char *output_name = NULL; 2246 const char *output_name = NULL;
1208 const char *ev_qualifier_str = NULL; 2247 const char *ev_qualifier_str = NULL;
1209 const struct option trace_options[] = { 2248 const struct option trace_options[] = {
2249 OPT_BOOLEAN(0, "comm", &trace.show_comm,
2250 "show the thread COMM next to its id"),
2251 OPT_BOOLEAN(0, "tool_stats", &trace.show_tool_stats, "show tool stats"),
1210 OPT_STRING('e', "expr", &ev_qualifier_str, "expr", 2252 OPT_STRING('e', "expr", &ev_qualifier_str, "expr",
1211 "list of events to trace"), 2253 "list of events to trace"),
1212 OPT_STRING('o', "output", &output_name, "file", "output file name"), 2254 OPT_STRING('o', "output", &output_name, "file", "output file name"),
@@ -1221,8 +2263,9 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
1221 "list of cpus to monitor"), 2263 "list of cpus to monitor"),
1222 OPT_BOOLEAN(0, "no-inherit", &trace.opts.no_inherit, 2264 OPT_BOOLEAN(0, "no-inherit", &trace.opts.no_inherit,
1223 "child tasks do not inherit counters"), 2265 "child tasks do not inherit counters"),
1224 OPT_UINTEGER('m', "mmap-pages", &trace.opts.mmap_pages, 2266 OPT_CALLBACK('m', "mmap-pages", &trace.opts.mmap_pages, "pages",
1225 "number of mmap data pages"), 2267 "number of mmap data pages",
2268 perf_evlist__parse_mmap_pages),
1226 OPT_STRING('u', "uid", &trace.opts.target.uid_str, "user", 2269 OPT_STRING('u', "uid", &trace.opts.target.uid_str, "user",
1227 "user to profile"), 2270 "user to profile"),
1228 OPT_CALLBACK(0, "duration", &trace, "float", 2271 OPT_CALLBACK(0, "duration", &trace, "float",
@@ -1230,11 +2273,18 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
1230 trace__set_duration), 2273 trace__set_duration),
1231 OPT_BOOLEAN(0, "sched", &trace.sched, "show blocking scheduler events"), 2274 OPT_BOOLEAN(0, "sched", &trace.sched, "show blocking scheduler events"),
1232 OPT_INCR('v', "verbose", &verbose, "be more verbose"), 2275 OPT_INCR('v', "verbose", &verbose, "be more verbose"),
2276 OPT_BOOLEAN('T', "time", &trace.full_time,
2277 "Show full timestamp, not time relative to first start"),
2278 OPT_BOOLEAN(0, "summary", &trace.summary,
2279 "Show syscall summary with statistics"),
1233 OPT_END() 2280 OPT_END()
1234 }; 2281 };
1235 int err; 2282 int err;
1236 char bf[BUFSIZ]; 2283 char bf[BUFSIZ];
1237 2284
2285 if ((argc > 1) && (strcmp(argv[1], "record") == 0))
2286 return trace__record(argc-2, &argv[2]);
2287
1238 argc = parse_options(argc, argv, trace_options, trace_usage, 0); 2288 argc = parse_options(argc, argv, trace_options, trace_usage, 0);
1239 2289
1240 if (output_name != NULL) { 2290 if (output_name != NULL) {
@@ -1282,9 +2332,6 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
1282 else 2332 else
1283 err = trace__run(&trace, argc, argv); 2333 err = trace__run(&trace, argc, argv);
1284 2334
1285 if (trace.sched && !err)
1286 trace__fprintf_thread_summary(&trace, trace.output);
1287
1288out_close: 2335out_close:
1289 if (output_name != NULL) 2336 if (output_name != NULL)
1290 fclose(trace.output); 2337 fclose(trace.output);
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index 5f6f9b3271bb..58b2d37ae23a 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -23,15 +23,17 @@ ifeq ($(ARCH),x86_64)
23 endif 23 endif
24 ifeq (${IS_X86_64}, 1) 24 ifeq (${IS_X86_64}, 1)
25 RAW_ARCH := x86_64 25 RAW_ARCH := x86_64
26 CFLAGS += -DARCH_X86_64 26 CFLAGS += -DHAVE_ARCH_X86_64_SUPPORT
27 ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S 27 ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S
28 LIBUNWIND_LIBS = -lunwind -lunwind-x86_64
29 else
30 LIBUNWIND_LIBS = -lunwind -lunwind-x86
28 endif 31 endif
29 NO_PERF_REGS := 0 32 NO_PERF_REGS := 0
30 LIBUNWIND_LIBS = -lunwind -lunwind-x86_64
31endif 33endif
32 34
33ifeq ($(NO_PERF_REGS),0) 35ifeq ($(NO_PERF_REGS),0)
34 CFLAGS += -DHAVE_PERF_REGS 36 CFLAGS += -DHAVE_PERF_REGS_SUPPORT
35endif 37endif
36 38
37ifeq ($(src-perf),) 39ifeq ($(src-perf),)
@@ -51,7 +53,6 @@ LIB_INCLUDE := $(srctree)/tools/lib/
51# include ARCH specific config 53# include ARCH specific config
52-include $(src-perf)/arch/$(ARCH)/Makefile 54-include $(src-perf)/arch/$(ARCH)/Makefile
53 55
54include $(src-perf)/config/feature-tests.mak
55include $(src-perf)/config/utilities.mak 56include $(src-perf)/config/utilities.mak
56 57
57ifeq ($(call get-executable,$(FLEX)),) 58ifeq ($(call get-executable,$(FLEX)),)
@@ -67,10 +68,11 @@ ifneq ($(WERROR),0)
67 CFLAGS += -Werror 68 CFLAGS += -Werror
68endif 69endif
69 70
70ifeq ("$(origin DEBUG)", "command line") 71ifndef DEBUG
71 PERF_DEBUG = $(DEBUG) 72 DEBUG := 0
72endif 73endif
73ifndef PERF_DEBUG 74
75ifeq ($(DEBUG),0)
74 CFLAGS += -O6 76 CFLAGS += -O6
75endif 77endif
76 78
@@ -89,20 +91,125 @@ CFLAGS += -std=gnu99
89 91
90EXTLIBS = -lelf -lpthread -lrt -lm -ldl 92EXTLIBS = -lelf -lpthread -lrt -lm -ldl
91 93
92ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -fstack-protector-all,-fstack-protector-all),y) 94ifneq ($(OUTPUT),)
93 CFLAGS += -fstack-protector-all 95 OUTPUT_FEATURES = $(OUTPUT)config/feature-checks/
96 $(shell mkdir -p $(OUTPUT_FEATURES))
94endif 97endif
95 98
96ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -Wstack-protector,-Wstack-protector),y) 99feature_check = $(eval $(feature_check_code))
97 CFLAGS += -Wstack-protector 100define feature_check_code
101 feature-$(1) := $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS)" LDFLAGS="$(LDFLAGS)" LIBUNWIND_LIBS="$(LIBUNWIND_LIBS)" -C config/feature-checks test-$1 >/dev/null 2>/dev/null && echo 1 || echo 0)
102endef
103
104feature_set = $(eval $(feature_set_code))
105define feature_set_code
106 feature-$(1) := 1
107endef
108
109#
110# Build the feature check binaries in parallel, ignore errors, ignore return value and suppress output:
111#
112
113#
114# Note that this is not a complete list of all feature tests, just
115# those that are typically built on a fully configured system.
116#
117# [ Feature tests not mentioned here have to be built explicitly in
118# the rule that uses them - an example for that is the 'bionic'
119# feature check. ]
120#
121CORE_FEATURE_TESTS = \
122 backtrace \
123 dwarf \
124 fortify-source \
125 glibc \
126 gtk2 \
127 gtk2-infobar \
128 libaudit \
129 libbfd \
130 libelf \
131 libelf-getphdrnum \
132 libelf-mmap \
133 libnuma \
134 libperl \
135 libpython \
136 libpython-version \
137 libslang \
138 libunwind \
139 on-exit \
140 stackprotector \
141 stackprotector-all
142
143#
144# So here we detect whether test-all was rebuilt, to be able
145# to skip the print-out of the long features list if the file
146# existed before and after it was built:
147#
148ifeq ($(wildcard $(OUTPUT)config/feature-checks/test-all),)
149 test-all-failed := 1
150else
151 test-all-failed := 0
152endif
153
154#
155# Special fast-path for the 'all features are available' case:
156#
157$(call feature_check,all,$(MSG))
158
159#
160# Just in case the build freshly failed, make sure we print the
161# feature matrix:
162#
163ifeq ($(feature-all), 0)
164 test-all-failed := 1
98endif 165endif
99 166
100ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -Wvolatile-register-var,-Wvolatile-register-var),y) 167ifeq ($(test-all-failed),1)
101 CFLAGS += -Wvolatile-register-var 168 $(info )
169 $(info Auto-detecting system features:)
102endif 170endif
103 171
104ifndef PERF_DEBUG 172ifeq ($(feature-all), 1)
105 ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -D_FORTIFY_SOURCE=2,-D_FORTIFY_SOURCE=2),y) 173 #
174 # test-all.c passed - just set all the core feature flags to 1:
175 #
176 $(foreach feat,$(CORE_FEATURE_TESTS),$(call feature_set,$(feat)))
177else
178 $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS)" LDFLAGS=$(LDFLAGS) -i -j -C config/feature-checks $(CORE_FEATURE_TESTS) >/dev/null 2>&1)
179 $(foreach feat,$(CORE_FEATURE_TESTS),$(call feature_check,$(feat)))
180endif
181
182#
183# Print the result of the feature test:
184#
185feature_print = $(eval $(feature_print_code)) $(info $(MSG))
186
187define feature_print_code
188 ifeq ($(feature-$(1)), 1)
189 MSG = $(shell printf '...%30s: [ \033[32mon\033[m ]' $(1))
190 else
191 MSG = $(shell printf '...%30s: [ \033[31mOFF\033[m ]' $(1))
192 endif
193endef
194
195#
196# Only print out our features if we rebuilt the testcases or if a test failed:
197#
198ifeq ($(test-all-failed), 1)
199 $(foreach feat,$(CORE_FEATURE_TESTS),$(call feature_print,$(feat)))
200 $(info )
201endif
202
203ifeq ($(feature-stackprotector-all), 1)
204 CFLAGS += -fstack-protector-all
205endif
206
207ifeq ($(feature-stackprotector), 1)
208 CFLAGS += -Wstack-protector
209endif
210
211ifeq ($(DEBUG),0)
212 ifeq ($(feature-fortify-source), 1)
106 CFLAGS += -D_FORTIFY_SOURCE=2 213 CFLAGS += -D_FORTIFY_SOURCE=2
107 endif 214 endif
108endif 215endif
@@ -128,84 +235,74 @@ CFLAGS += -I$(LIB_INCLUDE)
128CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE 235CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
129 236
130ifndef NO_BIONIC 237ifndef NO_BIONIC
131ifeq ($(call try-cc,$(SOURCE_BIONIC),$(CFLAGS),bionic),y) 238 $(call feature_check,bionic)
132 BIONIC := 1 239 ifeq ($(feature-bionic), 1)
133 EXTLIBS := $(filter-out -lrt,$(EXTLIBS)) 240 BIONIC := 1
134 EXTLIBS := $(filter-out -lpthread,$(EXTLIBS)) 241 EXTLIBS := $(filter-out -lrt,$(EXTLIBS))
242 EXTLIBS := $(filter-out -lpthread,$(EXTLIBS))
243 endif
135endif 244endif
136endif # NO_BIONIC
137 245
138ifdef NO_LIBELF 246ifdef NO_LIBELF
139 NO_DWARF := 1 247 NO_DWARF := 1
140 NO_DEMANGLE := 1 248 NO_DEMANGLE := 1
141 NO_LIBUNWIND := 1 249 NO_LIBUNWIND := 1
142else 250else
143FLAGS_LIBELF=$(CFLAGS) $(LDFLAGS) $(EXTLIBS) 251 ifeq ($(feature-libelf), 0)
144ifneq ($(call try-cc,$(SOURCE_LIBELF),$(FLAGS_LIBELF),libelf),y) 252 ifeq ($(feature-glibc), 1)
145 FLAGS_GLIBC=$(CFLAGS) $(LDFLAGS) 253 LIBC_SUPPORT := 1
146 ifeq ($(call try-cc,$(SOURCE_GLIBC),$(FLAGS_GLIBC),glibc),y) 254 endif
147 LIBC_SUPPORT := 1 255 ifeq ($(BIONIC),1)
148 endif 256 LIBC_SUPPORT := 1
149 ifeq ($(BIONIC),1) 257 endif
150 LIBC_SUPPORT := 1 258 ifeq ($(LIBC_SUPPORT),1)
151 endif 259 msg := $(warning No libelf found, disables 'probe' tool, please install elfutils-libelf-devel/libelf-dev);
152 ifeq ($(LIBC_SUPPORT),1)
153 msg := $(warning No libelf found, disables 'probe' tool, please install elfutils-libelf-devel/libelf-dev);
154 260
155 NO_LIBELF := 1 261 NO_LIBELF := 1
156 NO_DWARF := 1 262 NO_DWARF := 1
157 NO_DEMANGLE := 1 263 NO_DEMANGLE := 1
264 else
265 msg := $(error No gnu/libc-version.h found, please install glibc-dev[el]/glibc-static);
266 endif
158 else 267 else
159 msg := $(error No gnu/libc-version.h found, please install glibc-dev[el]/glibc-static); 268 # for linking with debug library, run like:
160 endif 269 # make DEBUG=1 LIBDW_DIR=/opt/libdw/
161else 270 ifdef LIBDW_DIR
162 # for linking with debug library, run like: 271 LIBDW_CFLAGS := -I$(LIBDW_DIR)/include
163 # make DEBUG=1 LIBDW_DIR=/opt/libdw/ 272 LIBDW_LDFLAGS := -L$(LIBDW_DIR)/lib
164 ifdef LIBDW_DIR 273 endif
165 LIBDW_CFLAGS := -I$(LIBDW_DIR)/include
166 LIBDW_LDFLAGS := -L$(LIBDW_DIR)/lib
167 endif
168 274
169 FLAGS_DWARF=$(CFLAGS) $(LIBDW_CFLAGS) -ldw -lz -lelf $(LIBDW_LDFLAGS) $(LDFLAGS) $(EXTLIBS) 275 ifneq ($(feature-dwarf), 1)
170 ifneq ($(call try-cc,$(SOURCE_DWARF),$(FLAGS_DWARF),libdw),y) 276 msg := $(warning No libdw.h found or old libdw.h found or elfutils is older than 0.138, disables dwarf support. Please install new elfutils-devel/libdw-dev);
171 msg := $(warning No libdw.h found or old libdw.h found or elfutils is older than 0.138, disables dwarf support. Please install new elfutils-devel/libdw-dev); 277 NO_DWARF := 1
172 NO_DWARF := 1 278 endif # Dwarf support
173 endif # Dwarf support 279 endif # libelf support
174endif # SOURCE_LIBELF
175endif # NO_LIBELF 280endif # NO_LIBELF
176 281
177ifndef NO_LIBELF 282ifndef NO_LIBELF
178CFLAGS += -DLIBELF_SUPPORT 283 CFLAGS += -DHAVE_LIBELF_SUPPORT
179FLAGS_LIBELF=$(CFLAGS) $(LDFLAGS) $(EXTLIBS)
180ifeq ($(call try-cc,$(SOURCE_ELF_MMAP),$(FLAGS_LIBELF),-DLIBELF_MMAP),y)
181 CFLAGS += -DLIBELF_MMAP
182endif
183ifeq ($(call try-cc,$(SOURCE_ELF_GETPHDRNUM),$(FLAGS_LIBELF),-DHAVE_ELF_GETPHDRNUM),y)
184 CFLAGS += -DHAVE_ELF_GETPHDRNUM
185endif
186 284
187# include ARCH specific config 285 ifeq ($(feature-libelf-mmap), 1)
188-include $(src-perf)/arch/$(ARCH)/Makefile 286 CFLAGS += -DHAVE_LIBELF_MMAP_SUPPORT
287 endif
189 288
190ifndef NO_DWARF 289 ifeq ($(feature-libelf-getphdrnum), 1)
191ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined) 290 CFLAGS += -DHAVE_ELF_GETPHDRNUM_SUPPORT
192 msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled); 291 endif
193 NO_DWARF := 1
194else
195 CFLAGS += -DDWARF_SUPPORT $(LIBDW_CFLAGS)
196 LDFLAGS += $(LIBDW_LDFLAGS)
197 EXTLIBS += -lelf -ldw
198endif # PERF_HAVE_DWARF_REGS
199endif # NO_DWARF
200 292
201endif # NO_LIBELF 293 # include ARCH specific config
294 -include $(src-perf)/arch/$(ARCH)/Makefile
202 295
203ifndef NO_LIBELF 296 ifndef NO_DWARF
204CFLAGS += -DLIBELF_SUPPORT 297 ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined)
205FLAGS_LIBELF=$(CFLAGS) $(LDFLAGS) $(EXTLIBS) 298 msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled);
206ifeq ($(call try-cc,$(SOURCE_ELF_MMAP),$(FLAGS_LIBELF),-DLIBELF_MMAP),y) 299 NO_DWARF := 1
207 CFLAGS += -DLIBELF_MMAP 300 else
208endif # try-cc 301 CFLAGS += -DHAVE_DWARF_SUPPORT $(LIBDW_CFLAGS)
302 LDFLAGS += $(LIBDW_LDFLAGS)
303 EXTLIBS += -lelf -ldw
304 endif # PERF_HAVE_DWARF_REGS
305 endif # NO_DWARF
209endif # NO_LIBELF 306endif # NO_LIBELF
210 307
211# There's only x86 (both 32 and 64) support for CFI unwind so far 308# There's only x86 (both 32 and 64) support for CFI unwind so far
@@ -214,34 +311,35 @@ ifneq ($(ARCH),x86)
214endif 311endif
215 312
216ifndef NO_LIBUNWIND 313ifndef NO_LIBUNWIND
217# for linking with debug library, run like: 314 #
218# make DEBUG=1 LIBUNWIND_DIR=/opt/libunwind/ 315 # For linking with debug library, run like:
219ifdef LIBUNWIND_DIR 316 #
220 LIBUNWIND_CFLAGS := -I$(LIBUNWIND_DIR)/include 317 # make DEBUG=1 LIBUNWIND_DIR=/opt/libunwind/
221 LIBUNWIND_LDFLAGS := -L$(LIBUNWIND_DIR)/lib 318 #
222endif 319 ifdef LIBUNWIND_DIR
320 LIBUNWIND_CFLAGS := -I$(LIBUNWIND_DIR)/include
321 LIBUNWIND_LDFLAGS := -L$(LIBUNWIND_DIR)/lib
322 endif
223 323
224FLAGS_UNWIND=$(LIBUNWIND_CFLAGS) $(CFLAGS) $(LIBUNWIND_LDFLAGS) $(LDFLAGS) $(EXTLIBS) $(LIBUNWIND_LIBS) 324 ifneq ($(feature-libunwind), 1)
225ifneq ($(call try-cc,$(SOURCE_LIBUNWIND),$(FLAGS_UNWIND),libunwind),y) 325 msg := $(warning No libunwind found, disabling post unwind support. Please install libunwind-dev[el] >= 0.99);
226 msg := $(warning No libunwind found, disabling post unwind support. Please install libunwind-dev[el] >= 0.99); 326 NO_LIBUNWIND := 1
227 NO_LIBUNWIND := 1 327 endif
228endif # Libunwind support 328endif
229endif # NO_LIBUNWIND
230 329
231ifndef NO_LIBUNWIND 330ifndef NO_LIBUNWIND
232 CFLAGS += -DLIBUNWIND_SUPPORT 331 CFLAGS += -DHAVE_LIBUNWIND_SUPPORT
233 EXTLIBS += $(LIBUNWIND_LIBS) 332 EXTLIBS += $(LIBUNWIND_LIBS)
234 CFLAGS += $(LIBUNWIND_CFLAGS) 333 CFLAGS += $(LIBUNWIND_CFLAGS)
235 LDFLAGS += $(LIBUNWIND_LDFLAGS) 334 LDFLAGS += $(LIBUNWIND_LDFLAGS)
236endif # NO_LIBUNWIND 335endif
237 336
238ifndef NO_LIBAUDIT 337ifndef NO_LIBAUDIT
239 FLAGS_LIBAUDIT = $(CFLAGS) $(LDFLAGS) -laudit 338 ifneq ($(feature-libaudit), 1)
240 ifneq ($(call try-cc,$(SOURCE_LIBAUDIT),$(FLAGS_LIBAUDIT),libaudit),y)
241 msg := $(warning No libaudit.h found, disables 'trace' tool, please install audit-libs-devel or libaudit-dev); 339 msg := $(warning No libaudit.h found, disables 'trace' tool, please install audit-libs-devel or libaudit-dev);
242 NO_LIBAUDIT := 1 340 NO_LIBAUDIT := 1
243 else 341 else
244 CFLAGS += -DLIBAUDIT_SUPPORT 342 CFLAGS += -DHAVE_LIBAUDIT_SUPPORT
245 EXTLIBS += -laudit 343 EXTLIBS += -laudit
246 endif 344 endif
247endif 345endif
@@ -251,30 +349,30 @@ ifdef NO_NEWT
251endif 349endif
252 350
253ifndef NO_SLANG 351ifndef NO_SLANG
254 FLAGS_SLANG=$(CFLAGS) $(LDFLAGS) $(EXTLIBS) -I/usr/include/slang -lslang 352 ifneq ($(feature-libslang), 1)
255 ifneq ($(call try-cc,$(SOURCE_SLANG),$(FLAGS_SLANG),libslang),y)
256 msg := $(warning slang not found, disables TUI support. Please install slang-devel or libslang-dev); 353 msg := $(warning slang not found, disables TUI support. Please install slang-devel or libslang-dev);
257 NO_SLANG := 1 354 NO_SLANG := 1
258 else 355 else
259 # Fedora has /usr/include/slang/slang.h, but ubuntu /usr/include/slang.h 356 # Fedora has /usr/include/slang/slang.h, but ubuntu /usr/include/slang.h
260 CFLAGS += -I/usr/include/slang 357 CFLAGS += -I/usr/include/slang
261 CFLAGS += -DSLANG_SUPPORT 358 CFLAGS += -DHAVE_SLANG_SUPPORT
262 EXTLIBS += -lslang 359 EXTLIBS += -lslang
263 endif 360 endif
264endif 361endif
265 362
266ifndef NO_GTK2 363ifndef NO_GTK2
267 FLAGS_GTK2=$(CFLAGS) $(LDFLAGS) $(EXTLIBS) $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null) 364 FLAGS_GTK2=$(CFLAGS) $(LDFLAGS) $(EXTLIBS) $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null)
268 ifneq ($(call try-cc,$(SOURCE_GTK2),$(FLAGS_GTK2),gtk2),y) 365 ifneq ($(feature-gtk2), 1)
269 msg := $(warning GTK2 not found, disables GTK2 support. Please install gtk2-devel or libgtk2.0-dev); 366 msg := $(warning GTK2 not found, disables GTK2 support. Please install gtk2-devel or libgtk2.0-dev);
270 NO_GTK2 := 1 367 NO_GTK2 := 1
271 else 368 else
272 ifeq ($(call try-cc,$(SOURCE_GTK2_INFOBAR),$(FLAGS_GTK2),-DHAVE_GTK_INFO_BAR),y) 369 ifeq ($(feature-gtk2-infobar), 1)
273 CFLAGS += -DHAVE_GTK_INFO_BAR 370 GTK_CFLAGS := -DHAVE_GTK_INFO_BAR_SUPPORT
274 endif 371 endif
275 CFLAGS += -DGTK2_SUPPORT 372 CFLAGS += -DHAVE_GTK2_SUPPORT
276 CFLAGS += $(shell pkg-config --cflags gtk+-2.0 2>/dev/null) 373 GTK_CFLAGS += $(shell pkg-config --cflags gtk+-2.0 2>/dev/null)
277 EXTLIBS += $(shell pkg-config --libs gtk+-2.0 2>/dev/null) 374 GTK_LIBS := $(shell pkg-config --libs gtk+-2.0 2>/dev/null)
375 EXTLIBS += -ldl
278 endif 376 endif
279endif 377endif
280 378
@@ -290,7 +388,7 @@ else
290 PERL_EMBED_CCOPTS = `perl -MExtUtils::Embed -e ccopts 2>/dev/null` 388 PERL_EMBED_CCOPTS = `perl -MExtUtils::Embed -e ccopts 2>/dev/null`
291 FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS) 389 FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS)
292 390
293 ifneq ($(call try-cc,$(SOURCE_PERL_EMBED),$(FLAGS_PERL_EMBED),perl),y) 391 ifneq ($(feature-libperl), 1)
294 CFLAGS += -DNO_LIBPERL 392 CFLAGS += -DNO_LIBPERL
295 NO_LIBPERL := 1 393 NO_LIBPERL := 1
296 else 394 else
@@ -299,6 +397,13 @@ else
299 endif 397 endif
300endif 398endif
301 399
400$(call feature_check,timerfd)
401ifeq ($(feature-timerfd), 1)
402 CFLAGS += -DHAVE_TIMERFD_SUPPORT
403else
404 msg := $(warning No timerfd support. Disables 'perf kvm stat live');
405endif
406
302disable-python = $(eval $(disable-python_code)) 407disable-python = $(eval $(disable-python_code))
303define disable-python_code 408define disable-python_code
304 CFLAGS += -DNO_LIBPYTHON 409 CFLAGS += -DNO_LIBPYTHON
@@ -335,11 +440,11 @@ else
335 PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null) 440 PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null)
336 FLAGS_PYTHON_EMBED := $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS) 441 FLAGS_PYTHON_EMBED := $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS)
337 442
338 ifneq ($(call try-cc,$(SOURCE_PYTHON_EMBED),$(FLAGS_PYTHON_EMBED),python),y) 443 ifneq ($(feature-libpython), 1)
339 $(call disable-python,Python.h (for Python 2.x)) 444 $(call disable-python,Python.h (for Python 2.x))
340 else 445 else
341 446
342 ifneq ($(call try-cc,$(SOURCE_PYTHON_VERSION),$(FLAGS_PYTHON_EMBED),python version),y) 447 ifneq ($(feature-libpython-version), 1)
343 $(warning Python 3 is not yet supported; please set) 448 $(warning Python 3 is not yet supported; please set)
344 $(warning PYTHON and/or PYTHON_CONFIG appropriately.) 449 $(warning PYTHON and/or PYTHON_CONFIG appropriately.)
345 $(warning If you also have Python 2 installed, then) 450 $(warning If you also have Python 2 installed, then)
@@ -362,33 +467,30 @@ else
362 endif 467 endif
363endif 468endif
364 469
470ifeq ($(feature-libbfd), 1)
471 EXTLIBS += -lbfd
472endif
473
365ifdef NO_DEMANGLE 474ifdef NO_DEMANGLE
366 CFLAGS += -DNO_DEMANGLE 475 CFLAGS += -DNO_DEMANGLE
367else 476else
368 ifdef HAVE_CPLUS_DEMANGLE 477 ifdef HAVE_CPLUS_DEMANGLE_SUPPORT
369 EXTLIBS += -liberty 478 EXTLIBS += -liberty
370 CFLAGS += -DHAVE_CPLUS_DEMANGLE 479 CFLAGS += -DHAVE_CPLUS_DEMANGLE_SUPPORT
371 else 480 else
372 FLAGS_BFD=$(CFLAGS) $(LDFLAGS) $(EXTLIBS) -DPACKAGE='perf' -lbfd 481 ifneq ($(feature-libbfd), 1)
373 has_bfd := $(call try-cc,$(SOURCE_BFD),$(FLAGS_BFD),libbfd) 482 $(call feature_check,liberty)
374 ifeq ($(has_bfd),y) 483 ifeq ($(feature-liberty), 1)
375 EXTLIBS += -lbfd
376 else
377 FLAGS_BFD_IBERTY=$(FLAGS_BFD) -liberty
378 has_bfd_iberty := $(call try-cc,$(SOURCE_BFD),$(FLAGS_BFD_IBERTY),liberty)
379 ifeq ($(has_bfd_iberty),y)
380 EXTLIBS += -lbfd -liberty 484 EXTLIBS += -lbfd -liberty
381 else 485 else
382 FLAGS_BFD_IBERTY_Z=$(FLAGS_BFD_IBERTY) -lz 486 $(call feature_check,liberty-z)
383 has_bfd_iberty_z := $(call try-cc,$(SOURCE_BFD),$(FLAGS_BFD_IBERTY_Z),libz) 487 ifeq ($(feature-liberty-z), 1)
384 ifeq ($(has_bfd_iberty_z),y)
385 EXTLIBS += -lbfd -liberty -lz 488 EXTLIBS += -lbfd -liberty -lz
386 else 489 else
387 FLAGS_CPLUS_DEMANGLE=$(CFLAGS) $(LDFLAGS) $(EXTLIBS) -liberty 490 $(call feature_check,cplus-demangle)
388 has_cplus_demangle := $(call try-cc,$(SOURCE_CPLUS_DEMANGLE),$(FLAGS_CPLUS_DEMANGLE),demangle) 491 ifeq ($(feature-cplus-demangle), 1)
389 ifeq ($(has_cplus_demangle),y)
390 EXTLIBS += -liberty 492 EXTLIBS += -liberty
391 CFLAGS += -DHAVE_CPLUS_DEMANGLE 493 CFLAGS += -DHAVE_CPLUS_DEMANGLE_SUPPORT
392 else 494 else
393 msg := $(warning No bfd.h/libbfd found, install binutils-dev[el]/zlib-static to gain symbol demangling) 495 msg := $(warning No bfd.h/libbfd found, install binutils-dev[el]/zlib-static to gain symbol demangling)
394 CFLAGS += -DNO_DEMANGLE 496 CFLAGS += -DNO_DEMANGLE
@@ -399,31 +501,28 @@ else
399 endif 501 endif
400endif 502endif
401 503
402ifndef NO_STRLCPY 504ifneq ($(filter -lbfd,$(EXTLIBS)),)
403 ifeq ($(call try-cc,$(SOURCE_STRLCPY),,-DHAVE_STRLCPY),y) 505 CFLAGS += -DHAVE_LIBBFD_SUPPORT
404 CFLAGS += -DHAVE_STRLCPY
405 endif
406endif 506endif
407 507
408ifndef NO_ON_EXIT 508ifndef NO_ON_EXIT
409 ifeq ($(call try-cc,$(SOURCE_ON_EXIT),,-DHAVE_ON_EXIT),y) 509 ifeq ($(feature-on-exit), 1)
410 CFLAGS += -DHAVE_ON_EXIT 510 CFLAGS += -DHAVE_ON_EXIT_SUPPORT
411 endif 511 endif
412endif 512endif
413 513
414ifndef NO_BACKTRACE 514ifndef NO_BACKTRACE
415 ifeq ($(call try-cc,$(SOURCE_BACKTRACE),,-DBACKTRACE_SUPPORT),y) 515 ifeq ($(feature-backtrace), 1)
416 CFLAGS += -DBACKTRACE_SUPPORT 516 CFLAGS += -DHAVE_BACKTRACE_SUPPORT
417 endif 517 endif
418endif 518endif
419 519
420ifndef NO_LIBNUMA 520ifndef NO_LIBNUMA
421 FLAGS_LIBNUMA = $(CFLAGS) $(LDFLAGS) -lnuma 521 ifeq ($(feature-libnuma), 0)
422 ifneq ($(call try-cc,$(SOURCE_LIBNUMA),$(FLAGS_LIBNUMA),libnuma),y)
423 msg := $(warning No numa.h found, disables 'perf bench numa mem' benchmark, please install numa-libs-devel or libnuma-dev); 522 msg := $(warning No numa.h found, disables 'perf bench numa mem' benchmark, please install numa-libs-devel or libnuma-dev);
424 NO_LIBNUMA := 1 523 NO_LIBNUMA := 1
425 else 524 else
426 CFLAGS += -DLIBNUMA_SUPPORT 525 CFLAGS += -DHAVE_LIBNUMA_SUPPORT
427 EXTLIBS += -lnuma 526 EXTLIBS += -lnuma
428 endif 527 endif
429endif 528endif
@@ -459,7 +558,12 @@ else
459sysconfdir = $(prefix)/etc 558sysconfdir = $(prefix)/etc
460ETC_PERFCONFIG = etc/perfconfig 559ETC_PERFCONFIG = etc/perfconfig
461endif 560endif
561ifeq ($(IS_X86_64),1)
562lib = lib64
563else
462lib = lib 564lib = lib
565endif
566libdir = $(prefix)/$(lib)
463 567
464# Shell quote (do not use $(call) to accommodate ancient setups); 568# Shell quote (do not use $(call) to accommodate ancient setups);
465ETC_PERFCONFIG_SQ = $(subst ','\'',$(ETC_PERFCONFIG)) 569ETC_PERFCONFIG_SQ = $(subst ','\'',$(ETC_PERFCONFIG))
@@ -472,6 +576,7 @@ template_dir_SQ = $(subst ','\'',$(template_dir))
472htmldir_SQ = $(subst ','\'',$(htmldir)) 576htmldir_SQ = $(subst ','\'',$(htmldir))
473prefix_SQ = $(subst ','\'',$(prefix)) 577prefix_SQ = $(subst ','\'',$(prefix))
474sysconfdir_SQ = $(subst ','\'',$(sysconfdir)) 578sysconfdir_SQ = $(subst ','\'',$(sysconfdir))
579libdir_SQ = $(subst ','\'',$(libdir))
475 580
476ifneq ($(filter /%,$(firstword $(perfexecdir))),) 581ifneq ($(filter /%,$(firstword $(perfexecdir))),)
477perfexec_instdir = $(perfexecdir) 582perfexec_instdir = $(perfexecdir)
diff --git a/tools/perf/config/feature-checks/Makefile b/tools/perf/config/feature-checks/Makefile
new file mode 100644
index 000000000000..c803f17fb986
--- /dev/null
+++ b/tools/perf/config/feature-checks/Makefile
@@ -0,0 +1,148 @@
1
2FILES= \
3 test-all \
4 test-backtrace \
5 test-bionic \
6 test-dwarf \
7 test-fortify-source \
8 test-glibc \
9 test-gtk2 \
10 test-gtk2-infobar \
11 test-hello \
12 test-libaudit \
13 test-libbfd \
14 test-liberty \
15 test-liberty-z \
16 test-cplus-demangle \
17 test-libelf \
18 test-libelf-getphdrnum \
19 test-libelf-mmap \
20 test-libnuma \
21 test-libperl \
22 test-libpython \
23 test-libpython-version \
24 test-libslang \
25 test-libunwind \
26 test-on-exit \
27 test-stackprotector-all \
28 test-stackprotector \
29 test-timerfd
30
31CC := $(CC) -MD
32
33all: $(FILES)
34
35BUILD = $(CC) $(CFLAGS) $(LDFLAGS) -o $(OUTPUT)$@ $@.c
36
37###############################
38
39test-all:
40 $(BUILD) -Werror -fstack-protector -fstack-protector-all -O2 -Werror -D_FORTIFY_SOURCE=2 -ldw -lelf -lnuma $(LIBUNWIND_LIBS) -lelf -laudit -I/usr/include/slang -lslang $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null) $(FLAGS_PERL_EMBED) $(FLAGS_PYTHON_EMBED) -DPACKAGE='"perf"' -lbfd -ldl
41
42test-hello:
43 $(BUILD)
44
45test-stackprotector-all:
46 $(BUILD) -Werror -fstack-protector-all
47
48test-stackprotector:
49 $(BUILD) -Werror -fstack-protector -Wstack-protector
50
51test-fortify-source:
52 $(BUILD) -O2 -Werror -D_FORTIFY_SOURCE=2
53
54test-bionic:
55 $(BUILD)
56
57test-libelf:
58 $(BUILD) -lelf
59
60test-glibc:
61 $(BUILD)
62
63test-dwarf:
64 $(BUILD) -ldw
65
66test-libelf-mmap:
67 $(BUILD) -lelf
68
69test-libelf-getphdrnum:
70 $(BUILD) -lelf
71
72test-libnuma:
73 $(BUILD) -lnuma
74
75test-libunwind:
76 $(BUILD) $(LIBUNWIND_LIBS) -lelf
77
78test-libaudit:
79 $(BUILD) -laudit
80
81test-libslang:
82 $(BUILD) -I/usr/include/slang -lslang
83
84test-gtk2:
85 $(BUILD) $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null)
86
87test-gtk2-infobar:
88 $(BUILD) $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null)
89
90grep-libs = $(filter -l%,$(1))
91strip-libs = $(filter-out -l%,$(1))
92
93PERL_EMBED_LDOPTS = $(shell perl -MExtUtils::Embed -e ldopts 2>/dev/null)
94PERL_EMBED_LDFLAGS = $(call strip-libs,$(PERL_EMBED_LDOPTS))
95PERL_EMBED_LIBADD = $(call grep-libs,$(PERL_EMBED_LDOPTS))
96PERL_EMBED_CCOPTS = `perl -MExtUtils::Embed -e ccopts 2>/dev/null`
97FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS)
98
99test-libperl:
100 $(BUILD) $(FLAGS_PERL_EMBED)
101
102override PYTHON := python
103override PYTHON_CONFIG := python-config
104
105escape-for-shell-sq = $(subst ','\'',$(1))
106shell-sq = '$(escape-for-shell-sq)'
107
108PYTHON_CONFIG_SQ = $(call shell-sq,$(PYTHON_CONFIG))
109
110PYTHON_EMBED_LDOPTS = $(shell $(PYTHON_CONFIG_SQ) --ldflags 2>/dev/null)
111PYTHON_EMBED_LDFLAGS = $(call strip-libs,$(PYTHON_EMBED_LDOPTS))
112PYTHON_EMBED_LIBADD = $(call grep-libs,$(PYTHON_EMBED_LDOPTS))
113PYTHON_EMBED_CCOPTS = $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null)
114FLAGS_PYTHON_EMBED = $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS)
115
116test-libpython:
117 $(BUILD) $(FLAGS_PYTHON_EMBED)
118
119test-libpython-version:
120 $(BUILD) $(FLAGS_PYTHON_EMBED)
121
122test-libbfd:
123 $(BUILD) -DPACKAGE='"perf"' -lbfd -ldl
124
125test-liberty:
126 $(CC) -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty
127
128test-liberty-z:
129 $(CC) -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty -lz
130
131test-cplus-demangle:
132 $(BUILD) -liberty
133
134test-on-exit:
135 $(BUILD)
136
137test-backtrace:
138 $(BUILD)
139
140test-timerfd:
141 $(BUILD)
142
143-include *.d
144
145###############################
146
147clean:
148 rm -f $(FILES) *.d
diff --git a/tools/perf/config/feature-checks/test-all.c b/tools/perf/config/feature-checks/test-all.c
new file mode 100644
index 000000000000..59e7a705e146
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-all.c
@@ -0,0 +1,111 @@
1/*
2 * test-all.c: Try to build all the main testcases at once.
3 *
4 * A well-configured system will have all the prereqs installed, so we can speed
5 * up auto-detection on such systems.
6 */
7
8/*
9 * Quirk: Python and Perl headers cannot be in arbitrary places, so keep
10 * these 3 testcases at the top:
11 */
12#define main main_test_libpython
13# include "test-libpython.c"
14#undef main
15
16#define main main_test_libpython_version
17# include "test-libpython-version.c"
18#undef main
19
20#define main main_test_libperl
21# include "test-libperl.c"
22#undef main
23
24#define main main_test_hello
25# include "test-hello.c"
26#undef main
27
28#define main main_test_libelf
29# include "test-libelf.c"
30#undef main
31
32#define main main_test_libelf_mmap
33# include "test-libelf-mmap.c"
34#undef main
35
36#define main main_test_glibc
37# include "test-glibc.c"
38#undef main
39
40#define main main_test_dwarf
41# include "test-dwarf.c"
42#undef main
43
44#define main main_test_libelf_getphdrnum
45# include "test-libelf-getphdrnum.c"
46#undef main
47
48#define main main_test_libunwind
49# include "test-libunwind.c"
50#undef main
51
52#define main main_test_libaudit
53# include "test-libaudit.c"
54#undef main
55
56#define main main_test_libslang
57# include "test-libslang.c"
58#undef main
59
60#define main main_test_gtk2
61# include "test-gtk2.c"
62#undef main
63
64#define main main_test_gtk2_infobar
65# include "test-gtk2-infobar.c"
66#undef main
67
68#define main main_test_libbfd
69# include "test-libbfd.c"
70#undef main
71
72#define main main_test_on_exit
73# include "test-on-exit.c"
74#undef main
75
76#define main main_test_backtrace
77# include "test-backtrace.c"
78#undef main
79
80#define main main_test_libnuma
81# include "test-libnuma.c"
82#undef main
83
84#define main main_test_timerfd
85# include "test-timerfd.c"
86#undef main
87
88int main(int argc, char *argv[])
89{
90 main_test_libpython();
91 main_test_libpython_version();
92 main_test_libperl();
93 main_test_hello();
94 main_test_libelf();
95 main_test_libelf_mmap();
96 main_test_glibc();
97 main_test_dwarf();
98 main_test_libelf_getphdrnum();
99 main_test_libunwind();
100 main_test_libaudit();
101 main_test_libslang();
102 main_test_gtk2(argc, argv);
103 main_test_gtk2_infobar(argc, argv);
104 main_test_libbfd();
105 main_test_on_exit();
106 main_test_backtrace();
107 main_test_libnuma();
108 main_test_timerfd();
109
110 return 0;
111}
diff --git a/tools/perf/config/feature-checks/test-backtrace.c b/tools/perf/config/feature-checks/test-backtrace.c
new file mode 100644
index 000000000000..7124aa1dc8fb
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-backtrace.c
@@ -0,0 +1,13 @@
1#include <execinfo.h>
2#include <stdio.h>
3
4int main(void)
5{
6 void *backtrace_fns[10];
7 size_t entries;
8
9 entries = backtrace(backtrace_fns, 10);
10 backtrace_symbols_fd(backtrace_fns, entries, 1);
11
12 return 0;
13}
diff --git a/tools/perf/config/feature-checks/test-bionic.c b/tools/perf/config/feature-checks/test-bionic.c
new file mode 100644
index 000000000000..eac24e9513eb
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-bionic.c
@@ -0,0 +1,6 @@
1#include <android/api-level.h>
2
3int main(void)
4{
5 return __ANDROID_API__;
6}
diff --git a/tools/perf/config/feature-checks/test-cplus-demangle.c b/tools/perf/config/feature-checks/test-cplus-demangle.c
new file mode 100644
index 000000000000..610c686e0009
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-cplus-demangle.c
@@ -0,0 +1,14 @@
1extern int printf(const char *format, ...);
2extern char *cplus_demangle(const char *, int);
3
4int main(void)
5{
6 char symbol[4096] = "FieldName__9ClassNameFd";
7 char *tmp;
8
9 tmp = cplus_demangle(symbol, 0);
10
11 printf("demangled symbol: {%s}\n", tmp);
12
13 return 0;
14}
diff --git a/tools/perf/config/feature-checks/test-dwarf.c b/tools/perf/config/feature-checks/test-dwarf.c
new file mode 100644
index 000000000000..3fc1801ce4a9
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-dwarf.c
@@ -0,0 +1,10 @@
1#include <dwarf.h>
2#include <elfutils/libdw.h>
3#include <elfutils/version.h>
4
5int main(void)
6{
7 Dwarf *dbg = dwarf_begin(0, DWARF_C_READ);
8
9 return (long)dbg;
10}
diff --git a/tools/perf/config/feature-checks/test-fortify-source.c b/tools/perf/config/feature-checks/test-fortify-source.c
new file mode 100644
index 000000000000..c9f398d87868
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-fortify-source.c
@@ -0,0 +1,6 @@
1#include <stdio.h>
2
3int main(void)
4{
5 return puts("hi");
6}
diff --git a/tools/perf/config/feature-checks/test-glibc.c b/tools/perf/config/feature-checks/test-glibc.c
new file mode 100644
index 000000000000..b0820345cd98
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-glibc.c
@@ -0,0 +1,8 @@
1#include <gnu/libc-version.h>
2
3int main(void)
4{
5 const char *version = gnu_get_libc_version();
6
7 return (long)version;
8}
diff --git a/tools/perf/config/feature-checks/test-gtk2-infobar.c b/tools/perf/config/feature-checks/test-gtk2-infobar.c
new file mode 100644
index 000000000000..397b4646d066
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-gtk2-infobar.c
@@ -0,0 +1,11 @@
1#pragma GCC diagnostic ignored "-Wstrict-prototypes"
2#include <gtk/gtk.h>
3#pragma GCC diagnostic error "-Wstrict-prototypes"
4
5int main(int argc, char *argv[])
6{
7 gtk_init(&argc, &argv);
8 gtk_info_bar_new();
9
10 return 0;
11}
diff --git a/tools/perf/config/feature-checks/test-gtk2.c b/tools/perf/config/feature-checks/test-gtk2.c
new file mode 100644
index 000000000000..6bd80e509439
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-gtk2.c
@@ -0,0 +1,10 @@
1#pragma GCC diagnostic ignored "-Wstrict-prototypes"
2#include <gtk/gtk.h>
3#pragma GCC diagnostic error "-Wstrict-prototypes"
4
5int main(int argc, char *argv[])
6{
7 gtk_init(&argc, &argv);
8
9 return 0;
10}
diff --git a/tools/perf/config/feature-checks/test-hello.c b/tools/perf/config/feature-checks/test-hello.c
new file mode 100644
index 000000000000..c9f398d87868
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-hello.c
@@ -0,0 +1,6 @@
1#include <stdio.h>
2
3int main(void)
4{
5 return puts("hi");
6}
diff --git a/tools/perf/config/feature-checks/test-libaudit.c b/tools/perf/config/feature-checks/test-libaudit.c
new file mode 100644
index 000000000000..afc019f08641
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-libaudit.c
@@ -0,0 +1,10 @@
1#include <libaudit.h>
2
3extern int printf(const char *format, ...);
4
5int main(void)
6{
7 printf("error message: %s\n", audit_errno_to_name(0));
8
9 return audit_open();
10}
diff --git a/tools/perf/config/feature-checks/test-libbfd.c b/tools/perf/config/feature-checks/test-libbfd.c
new file mode 100644
index 000000000000..24059907e990
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-libbfd.c
@@ -0,0 +1,15 @@
1#include <bfd.h>
2
3extern int printf(const char *format, ...);
4
5int main(void)
6{
7 char symbol[4096] = "FieldName__9ClassNameFd";
8 char *tmp;
9
10 tmp = bfd_demangle(0, symbol, 0);
11
12 printf("demangled symbol: {%s}\n", tmp);
13
14 return 0;
15}
diff --git a/tools/perf/config/feature-checks/test-libelf-getphdrnum.c b/tools/perf/config/feature-checks/test-libelf-getphdrnum.c
new file mode 100644
index 000000000000..d710459306c3
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-libelf-getphdrnum.c
@@ -0,0 +1,8 @@
1#include <libelf.h>
2
3int main(void)
4{
5 size_t dst;
6
7 return elf_getphdrnum(0, &dst);
8}
diff --git a/tools/perf/config/feature-checks/test-libelf-mmap.c b/tools/perf/config/feature-checks/test-libelf-mmap.c
new file mode 100644
index 000000000000..564427d7ef18
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-libelf-mmap.c
@@ -0,0 +1,8 @@
1#include <libelf.h>
2
3int main(void)
4{
5 Elf *elf = elf_begin(0, ELF_C_READ_MMAP, 0);
6
7 return (long)elf;
8}
diff --git a/tools/perf/config/feature-checks/test-libelf.c b/tools/perf/config/feature-checks/test-libelf.c
new file mode 100644
index 000000000000..08db322d8957
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-libelf.c
@@ -0,0 +1,8 @@
1#include <libelf.h>
2
3int main(void)
4{
5 Elf *elf = elf_begin(0, ELF_C_READ, 0);
6
7 return (long)elf;
8}
diff --git a/tools/perf/config/feature-checks/test-libnuma.c b/tools/perf/config/feature-checks/test-libnuma.c
new file mode 100644
index 000000000000..4763d9cd587d
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-libnuma.c
@@ -0,0 +1,9 @@
1#include <numa.h>
2#include <numaif.h>
3
4int main(void)
5{
6 numa_available();
7
8 return 0;
9}
diff --git a/tools/perf/config/feature-checks/test-libperl.c b/tools/perf/config/feature-checks/test-libperl.c
new file mode 100644
index 000000000000..8871f6a0fdb4
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-libperl.c
@@ -0,0 +1,9 @@
1#include <EXTERN.h>
2#include <perl.h>
3
4int main(void)
5{
6 perl_alloc();
7
8 return 0;
9}
diff --git a/tools/perf/config/feature-checks/test-libpython-version.c b/tools/perf/config/feature-checks/test-libpython-version.c
new file mode 100644
index 000000000000..facea122d812
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-libpython-version.c
@@ -0,0 +1,10 @@
1#include <Python.h>
2
3#if PY_VERSION_HEX >= 0x03000000
4 #error
5#endif
6
7int main(void)
8{
9 return 0;
10}
diff --git a/tools/perf/config/feature-checks/test-libpython.c b/tools/perf/config/feature-checks/test-libpython.c
new file mode 100644
index 000000000000..b24b28ad6324
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-libpython.c
@@ -0,0 +1,8 @@
1#include <Python.h>
2
3int main(void)
4{
5 Py_Initialize();
6
7 return 0;
8}
diff --git a/tools/perf/config/feature-checks/test-libslang.c b/tools/perf/config/feature-checks/test-libslang.c
new file mode 100644
index 000000000000..22ff22ed94d1
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-libslang.c
@@ -0,0 +1,6 @@
1#include <slang.h>
2
3int main(void)
4{
5 return SLsmg_init_smg();
6}
diff --git a/tools/perf/config/feature-checks/test-libunwind.c b/tools/perf/config/feature-checks/test-libunwind.c
new file mode 100644
index 000000000000..43b9369bcab7
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-libunwind.c
@@ -0,0 +1,27 @@
1#include <libunwind.h>
2#include <stdlib.h>
3
4extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
5 unw_word_t ip,
6 unw_dyn_info_t *di,
7 unw_proc_info_t *pi,
8 int need_unwind_info, void *arg);
9
10
11#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table)
12
13static unw_accessors_t accessors;
14
15int main(void)
16{
17 unw_addr_space_t addr_space;
18
19 addr_space = unw_create_addr_space(&accessors, 0);
20 if (addr_space)
21 return 0;
22
23 unw_init_remote(NULL, addr_space, NULL);
24 dwarf_search_unwind_table(addr_space, 0, NULL, NULL, 0, NULL);
25
26 return 0;
27}
diff --git a/tools/perf/config/feature-checks/test-on-exit.c b/tools/perf/config/feature-checks/test-on-exit.c
new file mode 100644
index 000000000000..8e88b16e6ded
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-on-exit.c
@@ -0,0 +1,16 @@
1#include <stdio.h>
2#include <stdlib.h>
3
4static void exit_fn(int status, void *__data)
5{
6 printf("exit status: %d, data: %d\n", status, *(int *)__data);
7}
8
9static int data = 123;
10
11int main(void)
12{
13 on_exit(exit_fn, &data);
14
15 return 321;
16}
diff --git a/tools/perf/config/feature-checks/test-stackprotector-all.c b/tools/perf/config/feature-checks/test-stackprotector-all.c
new file mode 100644
index 000000000000..c9f398d87868
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-stackprotector-all.c
@@ -0,0 +1,6 @@
1#include <stdio.h>
2
3int main(void)
4{
5 return puts("hi");
6}
diff --git a/tools/perf/config/feature-checks/test-stackprotector.c b/tools/perf/config/feature-checks/test-stackprotector.c
new file mode 100644
index 000000000000..c9f398d87868
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-stackprotector.c
@@ -0,0 +1,6 @@
1#include <stdio.h>
2
3int main(void)
4{
5 return puts("hi");
6}
diff --git a/tools/perf/config/feature-checks/test-timerfd.c b/tools/perf/config/feature-checks/test-timerfd.c
new file mode 100644
index 000000000000..8c5c083b4d3c
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-timerfd.c
@@ -0,0 +1,18 @@
1/*
2 * test for timerfd functions used by perf-kvm-stat-live
3 */
4#include <sys/timerfd.h>
5
6int main(void)
7{
8 struct itimerspec new_value;
9
10 int fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
11 if (fd < 0)
12 return 1;
13
14 if (timerfd_settime(fd, 0, &new_value, NULL) != 0)
15 return 1;
16
17 return 0;
18}
diff --git a/tools/perf/config/feature-checks/test-volatile-register-var.c b/tools/perf/config/feature-checks/test-volatile-register-var.c
new file mode 100644
index 000000000000..c9f398d87868
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-volatile-register-var.c
@@ -0,0 +1,6 @@
1#include <stdio.h>
2
3int main(void)
4{
5 return puts("hi");
6}
diff --git a/tools/perf/config/feature-tests.mak b/tools/perf/config/feature-tests.mak
deleted file mode 100644
index f79305739ecc..000000000000
--- a/tools/perf/config/feature-tests.mak
+++ /dev/null
@@ -1,246 +0,0 @@
1define SOURCE_HELLO
2#include <stdio.h>
3int main(void)
4{
5 return puts(\"hi\");
6}
7endef
8
9ifndef NO_DWARF
10define SOURCE_DWARF
11#include <dwarf.h>
12#include <elfutils/libdw.h>
13#include <elfutils/version.h>
14#ifndef _ELFUTILS_PREREQ
15#error
16#endif
17
18int main(void)
19{
20 Dwarf *dbg = dwarf_begin(0, DWARF_C_READ);
21 return (long)dbg;
22}
23endef
24endif
25
26define SOURCE_LIBELF
27#include <libelf.h>
28
29int main(void)
30{
31 Elf *elf = elf_begin(0, ELF_C_READ, 0);
32 return (long)elf;
33}
34endef
35
36define SOURCE_GLIBC
37#include <gnu/libc-version.h>
38
39int main(void)
40{
41 const char *version = gnu_get_libc_version();
42 return (long)version;
43}
44endef
45
46define SOURCE_BIONIC
47#include <android/api-level.h>
48
49int main(void)
50{
51 return __ANDROID_API__;
52}
53endef
54
55define SOURCE_ELF_MMAP
56#include <libelf.h>
57int main(void)
58{
59 Elf *elf = elf_begin(0, ELF_C_READ_MMAP, 0);
60 return (long)elf;
61}
62endef
63
64define SOURCE_ELF_GETPHDRNUM
65#include <libelf.h>
66int main(void)
67{
68 size_t dst;
69 return elf_getphdrnum(0, &dst);
70}
71endef
72
73ifndef NO_SLANG
74define SOURCE_SLANG
75#include <slang.h>
76
77int main(void)
78{
79 return SLsmg_init_smg();
80}
81endef
82endif
83
84ifndef NO_GTK2
85define SOURCE_GTK2
86#pragma GCC diagnostic ignored \"-Wstrict-prototypes\"
87#include <gtk/gtk.h>
88#pragma GCC diagnostic error \"-Wstrict-prototypes\"
89
90int main(int argc, char *argv[])
91{
92 gtk_init(&argc, &argv);
93
94 return 0;
95}
96endef
97
98define SOURCE_GTK2_INFOBAR
99#pragma GCC diagnostic ignored \"-Wstrict-prototypes\"
100#include <gtk/gtk.h>
101#pragma GCC diagnostic error \"-Wstrict-prototypes\"
102
103int main(void)
104{
105 gtk_info_bar_new();
106
107 return 0;
108}
109endef
110endif
111
112ifndef NO_LIBPERL
113define SOURCE_PERL_EMBED
114#include <EXTERN.h>
115#include <perl.h>
116
117int main(void)
118{
119perl_alloc();
120return 0;
121}
122endef
123endif
124
125ifndef NO_LIBPYTHON
126define SOURCE_PYTHON_VERSION
127#include <Python.h>
128#if PY_VERSION_HEX >= 0x03000000
129 #error
130#endif
131int main(void)
132{
133 return 0;
134}
135endef
136define SOURCE_PYTHON_EMBED
137#include <Python.h>
138int main(void)
139{
140 Py_Initialize();
141 return 0;
142}
143endef
144endif
145
146define SOURCE_BFD
147#include <bfd.h>
148
149int main(void)
150{
151 bfd_demangle(0, 0, 0);
152 return 0;
153}
154endef
155
156define SOURCE_CPLUS_DEMANGLE
157extern char *cplus_demangle(const char *, int);
158
159int main(void)
160{
161 cplus_demangle(0, 0);
162 return 0;
163}
164endef
165
166define SOURCE_STRLCPY
167#include <stdlib.h>
168extern size_t strlcpy(char *dest, const char *src, size_t size);
169
170int main(void)
171{
172 strlcpy(NULL, NULL, 0);
173 return 0;
174}
175endef
176
177ifndef NO_LIBUNWIND
178define SOURCE_LIBUNWIND
179#include <libunwind.h>
180#include <stdlib.h>
181
182extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
183 unw_word_t ip,
184 unw_dyn_info_t *di,
185 unw_proc_info_t *pi,
186 int need_unwind_info, void *arg);
187
188
189#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table)
190
191int main(void)
192{
193 unw_addr_space_t addr_space;
194 addr_space = unw_create_addr_space(NULL, 0);
195 unw_init_remote(NULL, addr_space, NULL);
196 dwarf_search_unwind_table(addr_space, 0, NULL, NULL, 0, NULL);
197 return 0;
198}
199endef
200endif
201
202ifndef NO_BACKTRACE
203define SOURCE_BACKTRACE
204#include <execinfo.h>
205#include <stdio.h>
206
207int main(void)
208{
209 backtrace(NULL, 0);
210 backtrace_symbols(NULL, 0);
211 return 0;
212}
213endef
214endif
215
216ifndef NO_LIBAUDIT
217define SOURCE_LIBAUDIT
218#include <libaudit.h>
219
220int main(void)
221{
222 printf(\"error message: %s\", audit_errno_to_name(0));
223 return audit_open();
224}
225endef
226endif
227
228define SOURCE_ON_EXIT
229#include <stdio.h>
230
231int main(void)
232{
233 return on_exit(NULL, NULL);
234}
235endef
236
237define SOURCE_LIBNUMA
238#include <numa.h>
239#include <numaif.h>
240
241int main(void)
242{
243 numa_available();
244 return 0;
245}
246endef
diff --git a/tools/perf/config/utilities.mak b/tools/perf/config/utilities.mak
index 94d2d4f9c35d..f168debc5be2 100644
--- a/tools/perf/config/utilities.mak
+++ b/tools/perf/config/utilities.mak
@@ -179,16 +179,9 @@ _ge_attempt = $(if $(get-executable),$(get-executable),$(_gea_warn)$(call _gea_e
179_gea_warn = $(warning The path '$(1)' is not executable.) 179_gea_warn = $(warning The path '$(1)' is not executable.)
180_gea_err = $(if $(1),$(error Please set '$(1)' appropriately)) 180_gea_err = $(if $(1),$(error Please set '$(1)' appropriately))
181 181
182# try-cc 182ifneq ($(findstring $(MAKEFLAGS),s),s)
183# Usage: option = $(call try-cc, source-to-build, cc-options, msg) 183 ifneq ($(V),1)
184ifneq ($(V),1) 184 QUIET_CLEAN = @printf ' CLEAN %s\n' $1;
185TRY_CC_OUTPUT= > /dev/null 2>&1 185 QUIET_INSTALL = @printf ' INSTALL %s\n' $1;
186 endif
186endif 187endif
187TRY_CC_MSG=echo " CHK $(3)" 1>&2;
188
189try-cc = $(shell sh -c \
190 'TMP="$(OUTPUT)$(TMPOUT).$$$$"; \
191 $(TRY_CC_MSG) \
192 echo "$(1)" | \
193 $(CC) -x c - $(2) -o "$$TMP" $(TRY_CC_OUTPUT) && echo y; \
194 rm -f "$$TMP"')
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 85e1aed95204..8b38b4e80ec2 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -49,14 +49,14 @@ static struct cmd_struct commands[] = {
49 { "version", cmd_version, 0 }, 49 { "version", cmd_version, 0 },
50 { "script", cmd_script, 0 }, 50 { "script", cmd_script, 0 },
51 { "sched", cmd_sched, 0 }, 51 { "sched", cmd_sched, 0 },
52#ifdef LIBELF_SUPPORT 52#ifdef HAVE_LIBELF_SUPPORT
53 { "probe", cmd_probe, 0 }, 53 { "probe", cmd_probe, 0 },
54#endif 54#endif
55 { "kmem", cmd_kmem, 0 }, 55 { "kmem", cmd_kmem, 0 },
56 { "lock", cmd_lock, 0 }, 56 { "lock", cmd_lock, 0 },
57 { "kvm", cmd_kvm, 0 }, 57 { "kvm", cmd_kvm, 0 },
58 { "test", cmd_test, 0 }, 58 { "test", cmd_test, 0 },
59#ifdef LIBAUDIT_SUPPORT 59#ifdef HAVE_LIBAUDIT_SUPPORT
60 { "trace", cmd_trace, 0 }, 60 { "trace", cmd_trace, 0 },
61#endif 61#endif
62 { "inject", cmd_inject, 0 }, 62 { "inject", cmd_inject, 0 },
@@ -456,6 +456,7 @@ int main(int argc, const char **argv)
456{ 456{
457 const char *cmd; 457 const char *cmd;
458 458
459 /* The page_size is placed in util object. */
459 page_size = sysconf(_SC_PAGE_SIZE); 460 page_size = sysconf(_SC_PAGE_SIZE);
460 461
461 cmd = perf_extract_argv0_path(argv[0]); 462 cmd = perf_extract_argv0_path(argv[0]);
@@ -480,7 +481,14 @@ int main(int argc, const char **argv)
480 fprintf(stderr, "cannot handle %s internally", cmd); 481 fprintf(stderr, "cannot handle %s internally", cmd);
481 goto out; 482 goto out;
482 } 483 }
483 484#ifdef HAVE_LIBAUDIT_SUPPORT
485 if (!prefixcmp(cmd, "trace")) {
486 set_buildid_dir();
487 setup_path();
488 argv[0] = "trace";
489 return cmd_trace(argc, argv, NULL);
490 }
491#endif
484 /* Look for flags.. */ 492 /* Look for flags.. */
485 argv++; 493 argv++;
486 argc--; 494 argc--;
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index cf20187eee0a..6a587e84fdfe 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -4,6 +4,8 @@
4#include <asm/unistd.h> 4#include <asm/unistd.h>
5 5
6#if defined(__i386__) 6#if defined(__i386__)
7#define mb() asm volatile("lock; addl $0,0(%%esp)" ::: "memory")
8#define wmb() asm volatile("lock; addl $0,0(%%esp)" ::: "memory")
7#define rmb() asm volatile("lock; addl $0,0(%%esp)" ::: "memory") 9#define rmb() asm volatile("lock; addl $0,0(%%esp)" ::: "memory")
8#define cpu_relax() asm volatile("rep; nop" ::: "memory"); 10#define cpu_relax() asm volatile("rep; nop" ::: "memory");
9#define CPUINFO_PROC "model name" 11#define CPUINFO_PROC "model name"
@@ -13,6 +15,8 @@
13#endif 15#endif
14 16
15#if defined(__x86_64__) 17#if defined(__x86_64__)
18#define mb() asm volatile("mfence" ::: "memory")
19#define wmb() asm volatile("sfence" ::: "memory")
16#define rmb() asm volatile("lfence" ::: "memory") 20#define rmb() asm volatile("lfence" ::: "memory")
17#define cpu_relax() asm volatile("rep; nop" ::: "memory"); 21#define cpu_relax() asm volatile("rep; nop" ::: "memory");
18#define CPUINFO_PROC "model name" 22#define CPUINFO_PROC "model name"
@@ -23,45 +27,61 @@
23 27
24#ifdef __powerpc__ 28#ifdef __powerpc__
25#include "../../arch/powerpc/include/uapi/asm/unistd.h" 29#include "../../arch/powerpc/include/uapi/asm/unistd.h"
30#define mb() asm volatile ("sync" ::: "memory")
31#define wmb() asm volatile ("sync" ::: "memory")
26#define rmb() asm volatile ("sync" ::: "memory") 32#define rmb() asm volatile ("sync" ::: "memory")
27#define cpu_relax() asm volatile ("" ::: "memory");
28#define CPUINFO_PROC "cpu" 33#define CPUINFO_PROC "cpu"
29#endif 34#endif
30 35
31#ifdef __s390__ 36#ifdef __s390__
37#define mb() asm volatile("bcr 15,0" ::: "memory")
38#define wmb() asm volatile("bcr 15,0" ::: "memory")
32#define rmb() asm volatile("bcr 15,0" ::: "memory") 39#define rmb() asm volatile("bcr 15,0" ::: "memory")
33#define cpu_relax() asm volatile("" ::: "memory");
34#endif 40#endif
35 41
36#ifdef __sh__ 42#ifdef __sh__
37#if defined(__SH4A__) || defined(__SH5__) 43#if defined(__SH4A__) || defined(__SH5__)
44# define mb() asm volatile("synco" ::: "memory")
45# define wmb() asm volatile("synco" ::: "memory")
38# define rmb() asm volatile("synco" ::: "memory") 46# define rmb() asm volatile("synco" ::: "memory")
39#else 47#else
48# define mb() asm volatile("" ::: "memory")
49# define wmb() asm volatile("" ::: "memory")
40# define rmb() asm volatile("" ::: "memory") 50# define rmb() asm volatile("" ::: "memory")
41#endif 51#endif
42#define cpu_relax() asm volatile("" ::: "memory")
43#define CPUINFO_PROC "cpu type" 52#define CPUINFO_PROC "cpu type"
44#endif 53#endif
45 54
46#ifdef __hppa__ 55#ifdef __hppa__
56#define mb() asm volatile("" ::: "memory")
57#define wmb() asm volatile("" ::: "memory")
47#define rmb() asm volatile("" ::: "memory") 58#define rmb() asm volatile("" ::: "memory")
48#define cpu_relax() asm volatile("" ::: "memory");
49#define CPUINFO_PROC "cpu" 59#define CPUINFO_PROC "cpu"
50#endif 60#endif
51 61
52#ifdef __sparc__ 62#ifdef __sparc__
63#ifdef __LP64__
64#define mb() asm volatile("ba,pt %%xcc, 1f\n" \
65 "membar #StoreLoad\n" \
66 "1:\n":::"memory")
67#else
68#define mb() asm volatile("":::"memory")
69#endif
70#define wmb() asm volatile("":::"memory")
53#define rmb() asm volatile("":::"memory") 71#define rmb() asm volatile("":::"memory")
54#define cpu_relax() asm volatile("":::"memory")
55#define CPUINFO_PROC "cpu" 72#define CPUINFO_PROC "cpu"
56#endif 73#endif
57 74
58#ifdef __alpha__ 75#ifdef __alpha__
76#define mb() asm volatile("mb" ::: "memory")
77#define wmb() asm volatile("wmb" ::: "memory")
59#define rmb() asm volatile("mb" ::: "memory") 78#define rmb() asm volatile("mb" ::: "memory")
60#define cpu_relax() asm volatile("" ::: "memory")
61#define CPUINFO_PROC "cpu model" 79#define CPUINFO_PROC "cpu model"
62#endif 80#endif
63 81
64#ifdef __ia64__ 82#ifdef __ia64__
83#define mb() asm volatile ("mf" ::: "memory")
84#define wmb() asm volatile ("mf" ::: "memory")
65#define rmb() asm volatile ("mf" ::: "memory") 85#define rmb() asm volatile ("mf" ::: "memory")
66#define cpu_relax() asm volatile ("hint @pause" ::: "memory") 86#define cpu_relax() asm volatile ("hint @pause" ::: "memory")
67#define CPUINFO_PROC "model name" 87#define CPUINFO_PROC "model name"
@@ -72,40 +92,55 @@
72 * Use the __kuser_memory_barrier helper in the CPU helper page. See 92 * Use the __kuser_memory_barrier helper in the CPU helper page. See
73 * arch/arm/kernel/entry-armv.S in the kernel source for details. 93 * arch/arm/kernel/entry-armv.S in the kernel source for details.
74 */ 94 */
95#define mb() ((void(*)(void))0xffff0fa0)()
96#define wmb() ((void(*)(void))0xffff0fa0)()
75#define rmb() ((void(*)(void))0xffff0fa0)() 97#define rmb() ((void(*)(void))0xffff0fa0)()
76#define cpu_relax() asm volatile("":::"memory")
77#define CPUINFO_PROC "Processor" 98#define CPUINFO_PROC "Processor"
78#endif 99#endif
79 100
80#ifdef __aarch64__ 101#ifdef __aarch64__
81#define rmb() asm volatile("dmb ld" ::: "memory") 102#define mb() asm volatile("dmb ish" ::: "memory")
103#define wmb() asm volatile("dmb ishld" ::: "memory")
104#define rmb() asm volatile("dmb ishst" ::: "memory")
82#define cpu_relax() asm volatile("yield" ::: "memory") 105#define cpu_relax() asm volatile("yield" ::: "memory")
83#endif 106#endif
84 107
85#ifdef __mips__ 108#ifdef __mips__
86#define rmb() asm volatile( \ 109#define mb() asm volatile( \
87 ".set mips2\n\t" \ 110 ".set mips2\n\t" \
88 "sync\n\t" \ 111 "sync\n\t" \
89 ".set mips0" \ 112 ".set mips0" \
90 : /* no output */ \ 113 : /* no output */ \
91 : /* no input */ \ 114 : /* no input */ \
92 : "memory") 115 : "memory")
93#define cpu_relax() asm volatile("" ::: "memory") 116#define wmb() mb()
117#define rmb() mb()
94#define CPUINFO_PROC "cpu model" 118#define CPUINFO_PROC "cpu model"
95#endif 119#endif
96 120
97#ifdef __arc__ 121#ifdef __arc__
122#define mb() asm volatile("" ::: "memory")
123#define wmb() asm volatile("" ::: "memory")
98#define rmb() asm volatile("" ::: "memory") 124#define rmb() asm volatile("" ::: "memory")
99#define cpu_relax() rmb()
100#define CPUINFO_PROC "Processor" 125#define CPUINFO_PROC "Processor"
101#endif 126#endif
102 127
103#ifdef __metag__ 128#ifdef __metag__
129#define mb() asm volatile("" ::: "memory")
130#define wmb() asm volatile("" ::: "memory")
104#define rmb() asm volatile("" ::: "memory") 131#define rmb() asm volatile("" ::: "memory")
105#define cpu_relax() asm volatile("" ::: "memory")
106#define CPUINFO_PROC "CPU" 132#define CPUINFO_PROC "CPU"
107#endif 133#endif
108 134
135#define barrier() asm volatile ("" ::: "memory")
136
137#ifndef cpu_relax
138#define cpu_relax() barrier()
139#endif
140
141#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x))
142
143
109#include <time.h> 144#include <time.h>
110#include <unistd.h> 145#include <unistd.h>
111#include <sys/types.h> 146#include <sys/types.h>
@@ -182,7 +217,9 @@ struct ip_callchain {
182struct branch_flags { 217struct branch_flags {
183 u64 mispred:1; 218 u64 mispred:1;
184 u64 predicted:1; 219 u64 predicted:1;
185 u64 reserved:62; 220 u64 in_tx:1;
221 u64 abort:1;
222 u64 reserved:60;
186}; 223};
187 224
188struct branch_entry { 225struct branch_entry {
@@ -218,7 +255,6 @@ struct perf_record_opts {
218 bool no_delay; 255 bool no_delay;
219 bool no_inherit; 256 bool no_inherit;
220 bool no_samples; 257 bool no_samples;
221 bool pipe_output;
222 bool raw_samples; 258 bool raw_samples;
223 bool sample_address; 259 bool sample_address;
224 bool sample_weight; 260 bool sample_weight;
@@ -231,6 +267,7 @@ struct perf_record_opts {
231 u64 default_interval; 267 u64 default_interval;
232 u64 user_interval; 268 u64 user_interval;
233 u16 stack_dump_size; 269 u16 stack_dump_size;
270 bool sample_transaction;
234}; 271};
235 272
236#endif 273#endif
diff --git a/tools/perf/scripts/python/Perf-Trace-Util/Context.c b/tools/perf/scripts/python/Perf-Trace-Util/Context.c
index 315067b8f552..fcd1dd667906 100644
--- a/tools/perf/scripts/python/Perf-Trace-Util/Context.c
+++ b/tools/perf/scripts/python/Perf-Trace-Util/Context.c
@@ -25,7 +25,7 @@
25 25
26PyMODINIT_FUNC initperf_trace_context(void); 26PyMODINIT_FUNC initperf_trace_context(void);
27 27
28static PyObject *perf_trace_context_common_pc(PyObject *self, PyObject *args) 28static PyObject *perf_trace_context_common_pc(PyObject *obj, PyObject *args)
29{ 29{
30 static struct scripting_context *scripting_context; 30 static struct scripting_context *scripting_context;
31 PyObject *context; 31 PyObject *context;
@@ -40,7 +40,7 @@ static PyObject *perf_trace_context_common_pc(PyObject *self, PyObject *args)
40 return Py_BuildValue("i", retval); 40 return Py_BuildValue("i", retval);
41} 41}
42 42
43static PyObject *perf_trace_context_common_flags(PyObject *self, 43static PyObject *perf_trace_context_common_flags(PyObject *obj,
44 PyObject *args) 44 PyObject *args)
45{ 45{
46 static struct scripting_context *scripting_context; 46 static struct scripting_context *scripting_context;
@@ -56,7 +56,7 @@ static PyObject *perf_trace_context_common_flags(PyObject *self,
56 return Py_BuildValue("i", retval); 56 return Py_BuildValue("i", retval);
57} 57}
58 58
59static PyObject *perf_trace_context_common_lock_depth(PyObject *self, 59static PyObject *perf_trace_context_common_lock_depth(PyObject *obj,
60 PyObject *args) 60 PyObject *args)
61{ 61{
62 static struct scripting_context *scripting_context; 62 static struct scripting_context *scripting_context;
diff --git a/tools/perf/tests/attr/README b/tools/perf/tests/attr/README
index d102957cd59a..430024f618f1 100644
--- a/tools/perf/tests/attr/README
+++ b/tools/perf/tests/attr/README
@@ -44,9 +44,9 @@ Following tests are defined (with perf commands):
44 perf record -c 123 kill (test-record-count) 44 perf record -c 123 kill (test-record-count)
45 perf record -d kill (test-record-data) 45 perf record -d kill (test-record-data)
46 perf record -F 100 kill (test-record-freq) 46 perf record -F 100 kill (test-record-freq)
47 perf record -g -- kill (test-record-graph-default) 47 perf record -g kill (test-record-graph-default)
48 perf record -g dwarf -- kill (test-record-graph-dwarf) 48 perf record --call-graph dwarf kill (test-record-graph-dwarf)
49 perf record -g fp kill (test-record-graph-fp) 49 perf record --call-graph fp kill (test-record-graph-fp)
50 perf record --group -e cycles,instructions kill (test-record-group) 50 perf record --group -e cycles,instructions kill (test-record-group)
51 perf record -e '{cycles,instructions}' kill (test-record-group1) 51 perf record -e '{cycles,instructions}' kill (test-record-group1)
52 perf record -D kill (test-record-no-delay) 52 perf record -D kill (test-record-no-delay)
diff --git a/tools/perf/tests/attr/test-record-graph-default b/tools/perf/tests/attr/test-record-graph-default
index 833d1849d767..853597a9a8f6 100644
--- a/tools/perf/tests/attr/test-record-graph-default
+++ b/tools/perf/tests/attr/test-record-graph-default
@@ -1,6 +1,6 @@
1[config] 1[config]
2command = record 2command = record
3args = -g -- kill >/dev/null 2>&1 3args = -g kill >/dev/null 2>&1
4 4
5[event:base-record] 5[event:base-record]
6sample_type=295 6sample_type=295
diff --git a/tools/perf/tests/attr/test-record-graph-dwarf b/tools/perf/tests/attr/test-record-graph-dwarf
index e93e082f5208..d6f324ea578c 100644
--- a/tools/perf/tests/attr/test-record-graph-dwarf
+++ b/tools/perf/tests/attr/test-record-graph-dwarf
@@ -1,6 +1,6 @@
1[config] 1[config]
2command = record 2command = record
3args = -g dwarf -- kill >/dev/null 2>&1 3args = --call-graph dwarf -- kill >/dev/null 2>&1
4 4
5[event:base-record] 5[event:base-record]
6sample_type=12583 6sample_type=12583
diff --git a/tools/perf/tests/attr/test-record-graph-fp b/tools/perf/tests/attr/test-record-graph-fp
index 7cef3743f03f..055e3bee7993 100644
--- a/tools/perf/tests/attr/test-record-graph-fp
+++ b/tools/perf/tests/attr/test-record-graph-fp
@@ -1,6 +1,6 @@
1[config] 1[config]
2command = record 2command = record
3args = -g fp kill >/dev/null 2>&1 3args = --call-graph fp kill >/dev/null 2>&1
4 4
5[event:base-record] 5[event:base-record]
6sample_type=295 6sample_type=295
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c
index e3fedfa2906e..49ccc3b2995e 100644
--- a/tools/perf/tests/code-reading.c
+++ b/tools/perf/tests/code-reading.c
@@ -276,7 +276,7 @@ static int process_event(struct machine *machine, struct perf_evlist *evlist,
276 return process_sample_event(machine, evlist, event, state); 276 return process_sample_event(machine, evlist, event, state);
277 277
278 if (event->header.type < PERF_RECORD_MAX) 278 if (event->header.type < PERF_RECORD_MAX)
279 return machine__process_event(machine, event); 279 return machine__process_event(machine, event, NULL);
280 280
281 return 0; 281 return 0;
282} 282}
diff --git a/tools/perf/tests/dso-data.c b/tools/perf/tests/dso-data.c
index dffe0551acaa..9cc81a3eb9b4 100644
--- a/tools/perf/tests/dso-data.c
+++ b/tools/perf/tests/dso-data.c
@@ -35,6 +35,7 @@ static char *test_file(int size)
35 if (size != write(fd, buf, size)) 35 if (size != write(fd, buf, size))
36 templ = NULL; 36 templ = NULL;
37 37
38 free(buf);
38 close(fd); 39 close(fd);
39 return templ; 40 return templ;
40} 41}
diff --git a/tools/perf/tests/hists_link.c b/tools/perf/tests/hists_link.c
index 4228ffc0d968..173bf42cc03e 100644
--- a/tools/perf/tests/hists_link.c
+++ b/tools/perf/tests/hists_link.c
@@ -93,7 +93,7 @@ static struct machine *setup_fake_machine(struct machines *machines)
93 if (thread == NULL) 93 if (thread == NULL)
94 goto out; 94 goto out;
95 95
96 thread__set_comm(thread, fake_threads[i].comm); 96 thread__set_comm(thread, fake_threads[i].comm, 0);
97 } 97 }
98 98
99 for (i = 0; i < ARRAY_SIZE(fake_mmap_info); i++) { 99 for (i = 0; i < ARRAY_SIZE(fake_mmap_info); i++) {
@@ -110,7 +110,7 @@ static struct machine *setup_fake_machine(struct machines *machines)
110 strcpy(fake_mmap_event.mmap.filename, 110 strcpy(fake_mmap_event.mmap.filename,
111 fake_mmap_info[i].filename); 111 fake_mmap_info[i].filename);
112 112
113 machine__process_mmap_event(machine, &fake_mmap_event); 113 machine__process_mmap_event(machine, &fake_mmap_event, NULL);
114 } 114 }
115 115
116 for (i = 0; i < ARRAY_SIZE(fake_symbols); i++) { 116 for (i = 0; i < ARRAY_SIZE(fake_symbols); i++) {
@@ -222,7 +222,8 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine)
222 &sample) < 0) 222 &sample) < 0)
223 goto out; 223 goto out;
224 224
225 he = __hists__add_entry(&evsel->hists, &al, NULL, 1, 1); 225 he = __hists__add_entry(&evsel->hists, &al, NULL,
226 NULL, NULL, 1, 1, 0);
226 if (he == NULL) 227 if (he == NULL)
227 goto out; 228 goto out;
228 229
@@ -244,7 +245,8 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine)
244 &sample) < 0) 245 &sample) < 0)
245 goto out; 246 goto out;
246 247
247 he = __hists__add_entry(&evsel->hists, &al, NULL, 1, 1); 248 he = __hists__add_entry(&evsel->hists, &al, NULL,
249 NULL, NULL, 1, 1, 0);
248 if (he == NULL) 250 if (he == NULL)
249 goto out; 251 goto out;
250 252
@@ -419,7 +421,7 @@ static void print_hists(struct hists *hists)
419 he = rb_entry(node, struct hist_entry, rb_node_in); 421 he = rb_entry(node, struct hist_entry, rb_node_in);
420 422
421 pr_info("%2d: entry: %-8s [%-8s] %20s: period = %"PRIu64"\n", 423 pr_info("%2d: entry: %-8s [%-8s] %20s: period = %"PRIu64"\n",
422 i, he->thread->comm, he->ms.map->dso->short_name, 424 i, thread__comm_str(he->thread), he->ms.map->dso->short_name,
423 he->ms.sym->name, he->stat.period); 425 he->ms.sym->name, he->stat.period);
424 426
425 i++; 427 i++;
@@ -465,7 +467,7 @@ int test__hists_link(void)
465 goto out; 467 goto out;
466 468
467 list_for_each_entry(evsel, &evlist->entries, node) { 469 list_for_each_entry(evsel, &evlist->entries, node) {
468 hists__collapse_resort(&evsel->hists); 470 hists__collapse_resort(&evsel->hists, NULL);
469 471
470 if (verbose > 2) 472 if (verbose > 2)
471 print_hists(&evsel->hists); 473 print_hists(&evsel->hists);
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c
index 48114d164e9f..ef671cd41bb3 100644
--- a/tools/perf/tests/parse-events.c
+++ b/tools/perf/tests/parse-events.c
@@ -2,7 +2,7 @@
2#include "parse-events.h" 2#include "parse-events.h"
3#include "evsel.h" 3#include "evsel.h"
4#include "evlist.h" 4#include "evlist.h"
5#include "sysfs.h" 5#include "fs.h"
6#include <lk/debugfs.h> 6#include <lk/debugfs.h>
7#include "tests.h" 7#include "tests.h"
8#include <linux/hw_breakpoint.h> 8#include <linux/hw_breakpoint.h>
@@ -1456,7 +1456,7 @@ static int test_pmu(void)
1456 int ret; 1456 int ret;
1457 1457
1458 snprintf(path, PATH_MAX, "%s/bus/event_source/devices/cpu/format/", 1458 snprintf(path, PATH_MAX, "%s/bus/event_source/devices/cpu/format/",
1459 sysfs_find_mountpoint()); 1459 sysfs__mountpoint());
1460 1460
1461 ret = stat(path, &st); 1461 ret = stat(path, &st);
1462 if (ret) 1462 if (ret)
@@ -1473,7 +1473,7 @@ static int test_pmu_events(void)
1473 int ret; 1473 int ret;
1474 1474
1475 snprintf(path, PATH_MAX, "%s/bus/event_source/devices/cpu/events/", 1475 snprintf(path, PATH_MAX, "%s/bus/event_source/devices/cpu/events/",
1476 sysfs_find_mountpoint()); 1476 sysfs__mountpoint());
1477 1477
1478 ret = stat(path, &st); 1478 ret = stat(path, &st);
1479 if (ret) { 1479 if (ret) {
diff --git a/tools/perf/tests/perf-record.c b/tools/perf/tests/perf-record.c
index 7923b06ffc91..93a62b06c3af 100644
--- a/tools/perf/tests/perf-record.c
+++ b/tools/perf/tests/perf-record.c
@@ -45,7 +45,7 @@ int test__PERF_RECORD(void)
45 }; 45 };
46 cpu_set_t cpu_mask; 46 cpu_set_t cpu_mask;
47 size_t cpu_mask_size = sizeof(cpu_mask); 47 size_t cpu_mask_size = sizeof(cpu_mask);
48 struct perf_evlist *evlist = perf_evlist__new(); 48 struct perf_evlist *evlist = perf_evlist__new_default();
49 struct perf_evsel *evsel; 49 struct perf_evsel *evsel;
50 struct perf_sample sample; 50 struct perf_sample sample;
51 const char *cmd = "sleep"; 51 const char *cmd = "sleep";
@@ -66,16 +66,6 @@ int test__PERF_RECORD(void)
66 } 66 }
67 67
68 /* 68 /*
69 * We need at least one evsel in the evlist, use the default
70 * one: "cycles".
71 */
72 err = perf_evlist__add_default(evlist);
73 if (err < 0) {
74 pr_debug("Not enough memory to create evsel\n");
75 goto out_delete_evlist;
76 }
77
78 /*
79 * Create maps of threads and cpus to monitor. In this case 69 * Create maps of threads and cpus to monitor. In this case
80 * we start with all threads and cpus (-1, -1) but then in 70 * we start with all threads and cpus (-1, -1) but then in
81 * perf_evlist__prepare_workload we'll fill in the only thread 71 * perf_evlist__prepare_workload we'll fill in the only thread
diff --git a/tools/perf/tests/rdpmc.c b/tools/perf/tests/rdpmc.c
index ff94886aad99..46649c25fa5e 100644
--- a/tools/perf/tests/rdpmc.c
+++ b/tools/perf/tests/rdpmc.c
@@ -9,8 +9,6 @@
9 9
10#if defined(__x86_64__) || defined(__i386__) 10#if defined(__x86_64__) || defined(__i386__)
11 11
12#define barrier() asm volatile("" ::: "memory")
13
14static u64 rdpmc(unsigned int counter) 12static u64 rdpmc(unsigned int counter)
15{ 13{
16 unsigned int low, high; 14 unsigned int low, high;
diff --git a/tools/perf/tests/sample-parsing.c b/tools/perf/tests/sample-parsing.c
index 77f598dbd97a..1b677202638d 100644
--- a/tools/perf/tests/sample-parsing.c
+++ b/tools/perf/tests/sample-parsing.c
@@ -121,6 +121,9 @@ static bool samples_same(const struct perf_sample *s1,
121 if (type & PERF_SAMPLE_DATA_SRC) 121 if (type & PERF_SAMPLE_DATA_SRC)
122 COMP(data_src); 122 COMP(data_src);
123 123
124 if (type & PERF_SAMPLE_TRANSACTION)
125 COMP(transaction);
126
124 return true; 127 return true;
125} 128}
126 129
@@ -165,6 +168,7 @@ static int do_test(u64 sample_type, u64 sample_regs_user, u64 read_format)
165 .cpu = 110, 168 .cpu = 110,
166 .raw_size = sizeof(raw_data), 169 .raw_size = sizeof(raw_data),
167 .data_src = 111, 170 .data_src = 111,
171 .transaction = 112,
168 .raw_data = (void *)raw_data, 172 .raw_data = (void *)raw_data,
169 .callchain = &callchain.callchain, 173 .callchain = &callchain.callchain,
170 .branch_stack = &branch_stack.branch_stack, 174 .branch_stack = &branch_stack.branch_stack,
@@ -273,10 +277,11 @@ int test__sample_parsing(void)
273 277
274 /* 278 /*
275 * Fail the test if it has not been updated when new sample format bits 279 * Fail the test if it has not been updated when new sample format bits
276 * were added. 280 * were added. Please actually update the test rather than just change
281 * the condition below.
277 */ 282 */
278 if (PERF_SAMPLE_MAX > PERF_SAMPLE_IDENTIFIER << 1) { 283 if (PERF_SAMPLE_MAX > PERF_SAMPLE_TRANSACTION << 1) {
279 pr_debug("sample format has changed - test needs updating\n"); 284 pr_debug("sample format has changed, some new PERF_SAMPLE_ bit was introduced - test needs updating\n");
280 return -1; 285 return -1;
281 } 286 }
282 287
diff --git a/tools/perf/tests/task-exit.c b/tools/perf/tests/task-exit.c
index a3e64876e940..c33d95f9559a 100644
--- a/tools/perf/tests/task-exit.c
+++ b/tools/perf/tests/task-exit.c
@@ -37,20 +37,11 @@ int test__task_exit(void)
37 signal(SIGCHLD, sig_handler); 37 signal(SIGCHLD, sig_handler);
38 signal(SIGUSR1, sig_handler); 38 signal(SIGUSR1, sig_handler);
39 39
40 evlist = perf_evlist__new(); 40 evlist = perf_evlist__new_default();
41 if (evlist == NULL) { 41 if (evlist == NULL) {
42 pr_debug("perf_evlist__new\n"); 42 pr_debug("perf_evlist__new_default\n");
43 return -1; 43 return -1;
44 } 44 }
45 /*
46 * We need at least one evsel in the evlist, use the default
47 * one: "cycles".
48 */
49 err = perf_evlist__add_default(evlist);
50 if (err < 0) {
51 pr_debug("Not enough memory to create evsel\n");
52 goto out_free_evlist;
53 }
54 45
55 /* 46 /*
56 * Create maps of threads and cpus to monitor. In this case 47 * Create maps of threads and cpus to monitor. In this case
@@ -117,7 +108,6 @@ out_close_evlist:
117 perf_evlist__close(evlist); 108 perf_evlist__close(evlist);
118out_delete_maps: 109out_delete_maps:
119 perf_evlist__delete_maps(evlist); 110 perf_evlist__delete_maps(evlist);
120out_free_evlist:
121 perf_evlist__delete(evlist); 111 perf_evlist__delete(evlist);
122 return err; 112 return err;
123} 113}
diff --git a/tools/perf/ui/browser.h b/tools/perf/ui/browser.h
index 404ff66a3e36..7d45d2f53601 100644
--- a/tools/perf/ui/browser.h
+++ b/tools/perf/ui/browser.h
@@ -21,32 +21,32 @@ struct ui_browser {
21 void *priv; 21 void *priv;
22 const char *title; 22 const char *title;
23 char *helpline; 23 char *helpline;
24 unsigned int (*refresh)(struct ui_browser *self); 24 unsigned int (*refresh)(struct ui_browser *browser);
25 void (*write)(struct ui_browser *self, void *entry, int row); 25 void (*write)(struct ui_browser *browser, void *entry, int row);
26 void (*seek)(struct ui_browser *self, off_t offset, int whence); 26 void (*seek)(struct ui_browser *browser, off_t offset, int whence);
27 bool (*filter)(struct ui_browser *self, void *entry); 27 bool (*filter)(struct ui_browser *browser, void *entry);
28 u32 nr_entries; 28 u32 nr_entries;
29 bool navkeypressed; 29 bool navkeypressed;
30 bool use_navkeypressed; 30 bool use_navkeypressed;
31}; 31};
32 32
33int ui_browser__set_color(struct ui_browser *browser, int color); 33int ui_browser__set_color(struct ui_browser *browser, int color);
34void ui_browser__set_percent_color(struct ui_browser *self, 34void ui_browser__set_percent_color(struct ui_browser *browser,
35 double percent, bool current); 35 double percent, bool current);
36bool ui_browser__is_current_entry(struct ui_browser *self, unsigned row); 36bool ui_browser__is_current_entry(struct ui_browser *browser, unsigned row);
37void ui_browser__refresh_dimensions(struct ui_browser *self); 37void ui_browser__refresh_dimensions(struct ui_browser *browser);
38void ui_browser__reset_index(struct ui_browser *self); 38void ui_browser__reset_index(struct ui_browser *browser);
39 39
40void ui_browser__gotorc(struct ui_browser *self, int y, int x); 40void ui_browser__gotorc(struct ui_browser *browser, int y, int x);
41void ui_browser__write_graph(struct ui_browser *browser, int graph); 41void ui_browser__write_graph(struct ui_browser *browser, int graph);
42void __ui_browser__line_arrow(struct ui_browser *browser, unsigned int column, 42void __ui_browser__line_arrow(struct ui_browser *browser, unsigned int column,
43 u64 start, u64 end); 43 u64 start, u64 end);
44void __ui_browser__show_title(struct ui_browser *browser, const char *title); 44void __ui_browser__show_title(struct ui_browser *browser, const char *title);
45void ui_browser__show_title(struct ui_browser *browser, const char *title); 45void ui_browser__show_title(struct ui_browser *browser, const char *title);
46int ui_browser__show(struct ui_browser *self, const char *title, 46int ui_browser__show(struct ui_browser *browser, const char *title,
47 const char *helpline, ...); 47 const char *helpline, ...);
48void ui_browser__hide(struct ui_browser *self); 48void ui_browser__hide(struct ui_browser *browser);
49int ui_browser__refresh(struct ui_browser *self); 49int ui_browser__refresh(struct ui_browser *browser);
50int ui_browser__run(struct ui_browser *browser, int delay_secs); 50int ui_browser__run(struct ui_browser *browser, int delay_secs);
51void ui_browser__update_nr_entries(struct ui_browser *browser, u32 nr_entries); 51void ui_browser__update_nr_entries(struct ui_browser *browser, u32 nr_entries);
52void ui_browser__handle_resize(struct ui_browser *browser); 52void ui_browser__handle_resize(struct ui_browser *browser);
@@ -63,11 +63,11 @@ int ui_browser__input_window(const char *title, const char *text, char *input,
63void ui_browser__argv_seek(struct ui_browser *browser, off_t offset, int whence); 63void ui_browser__argv_seek(struct ui_browser *browser, off_t offset, int whence);
64unsigned int ui_browser__argv_refresh(struct ui_browser *browser); 64unsigned int ui_browser__argv_refresh(struct ui_browser *browser);
65 65
66void ui_browser__rb_tree_seek(struct ui_browser *self, off_t offset, int whence); 66void ui_browser__rb_tree_seek(struct ui_browser *browser, off_t offset, int whence);
67unsigned int ui_browser__rb_tree_refresh(struct ui_browser *self); 67unsigned int ui_browser__rb_tree_refresh(struct ui_browser *browser);
68 68
69void ui_browser__list_head_seek(struct ui_browser *self, off_t offset, int whence); 69void ui_browser__list_head_seek(struct ui_browser *browser, off_t offset, int whence);
70unsigned int ui_browser__list_head_refresh(struct ui_browser *self); 70unsigned int ui_browser__list_head_refresh(struct ui_browser *browser);
71 71
72void ui_browser__init(void); 72void ui_browser__init(void);
73void annotate_browser__init(void); 73void annotate_browser__init(void);
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index 08545ae46992..f0697a3aede0 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -442,35 +442,37 @@ static bool annotate_browser__callq(struct annotate_browser *browser,
442{ 442{
443 struct map_symbol *ms = browser->b.priv; 443 struct map_symbol *ms = browser->b.priv;
444 struct disasm_line *dl = browser->selection; 444 struct disasm_line *dl = browser->selection;
445 struct symbol *sym = ms->sym;
446 struct annotation *notes; 445 struct annotation *notes;
447 struct symbol *target; 446 struct addr_map_symbol target = {
448 u64 ip; 447 .map = ms->map,
448 .addr = map__objdump_2mem(ms->map, dl->ops.target.addr),
449 };
449 char title[SYM_TITLE_MAX_SIZE]; 450 char title[SYM_TITLE_MAX_SIZE];
450 451
451 if (!ins__is_call(dl->ins)) 452 if (!ins__is_call(dl->ins))
452 return false; 453 return false;
453 454
454 ip = ms->map->map_ip(ms->map, dl->ops.target.addr); 455 if (map_groups__find_ams(&target, NULL) ||
455 target = map__find_symbol(ms->map, ip, NULL); 456 map__rip_2objdump(target.map, target.map->map_ip(target.map,
456 if (target == NULL) { 457 target.addr)) !=
458 dl->ops.target.addr) {
457 ui_helpline__puts("The called function was not found."); 459 ui_helpline__puts("The called function was not found.");
458 return true; 460 return true;
459 } 461 }
460 462
461 notes = symbol__annotation(target); 463 notes = symbol__annotation(target.sym);
462 pthread_mutex_lock(&notes->lock); 464 pthread_mutex_lock(&notes->lock);
463 465
464 if (notes->src == NULL && symbol__alloc_hist(target) < 0) { 466 if (notes->src == NULL && symbol__alloc_hist(target.sym) < 0) {
465 pthread_mutex_unlock(&notes->lock); 467 pthread_mutex_unlock(&notes->lock);
466 ui__warning("Not enough memory for annotating '%s' symbol!\n", 468 ui__warning("Not enough memory for annotating '%s' symbol!\n",
467 target->name); 469 target.sym->name);
468 return true; 470 return true;
469 } 471 }
470 472
471 pthread_mutex_unlock(&notes->lock); 473 pthread_mutex_unlock(&notes->lock);
472 symbol__tui_annotate(target, ms->map, evsel, hbt); 474 symbol__tui_annotate(target.sym, target.map, evsel, hbt);
473 sym_title(sym, ms->map, title, sizeof(title)); 475 sym_title(ms->sym, ms->map, title, sizeof(title));
474 ui_browser__show_title(&browser->b, title); 476 ui_browser__show_title(&browser->b, title);
475 return true; 477 return true;
476} 478}
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 7ef36c360471..16848bb4c418 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -1255,7 +1255,7 @@ static int hists__browser_title(struct hists *hists, char *bf, size_t size,
1255 if (thread) 1255 if (thread)
1256 printed += scnprintf(bf + printed, size - printed, 1256 printed += scnprintf(bf + printed, size - printed,
1257 ", Thread: %s(%d)", 1257 ", Thread: %s(%d)",
1258 (thread->comm_set ? thread->comm : ""), 1258 (thread->comm_set ? thread__comm_str(thread) : ""),
1259 thread->tid); 1259 thread->tid);
1260 if (dso) 1260 if (dso)
1261 printed += scnprintf(bf + printed, size - printed, 1261 printed += scnprintf(bf + printed, size - printed,
@@ -1578,7 +1578,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1578 if (thread != NULL && 1578 if (thread != NULL &&
1579 asprintf(&options[nr_options], "Zoom %s %s(%d) thread", 1579 asprintf(&options[nr_options], "Zoom %s %s(%d) thread",
1580 (browser->hists->thread_filter ? "out of" : "into"), 1580 (browser->hists->thread_filter ? "out of" : "into"),
1581 (thread->comm_set ? thread->comm : ""), 1581 (thread->comm_set ? thread__comm_str(thread) : ""),
1582 thread->tid) > 0) 1582 thread->tid) > 0)
1583 zoom_thread = nr_options++; 1583 zoom_thread = nr_options++;
1584 1584
@@ -1598,7 +1598,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1598 struct symbol *sym; 1598 struct symbol *sym;
1599 1599
1600 if (asprintf(&options[nr_options], "Run scripts for samples of thread [%s]", 1600 if (asprintf(&options[nr_options], "Run scripts for samples of thread [%s]",
1601 browser->he_selection->thread->comm) > 0) 1601 thread__comm_str(browser->he_selection->thread)) > 0)
1602 scripts_comm = nr_options++; 1602 scripts_comm = nr_options++;
1603 1603
1604 sym = browser->he_selection->ms.sym; 1604 sym = browser->he_selection->ms.sym;
@@ -1701,7 +1701,7 @@ zoom_out_thread:
1701 sort_thread.elide = false; 1701 sort_thread.elide = false;
1702 } else { 1702 } else {
1703 ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s(%d) thread\"", 1703 ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s(%d) thread\"",
1704 thread->comm_set ? thread->comm : "", 1704 thread->comm_set ? thread__comm_str(thread) : "",
1705 thread->tid); 1705 thread->tid);
1706 browser->hists->thread_filter = thread; 1706 browser->hists->thread_filter = thread;
1707 sort_thread.elide = true; 1707 sort_thread.elide = true;
@@ -1717,7 +1717,7 @@ do_scripts:
1717 memset(script_opt, 0, 64); 1717 memset(script_opt, 0, 64);
1718 1718
1719 if (choice == scripts_comm) 1719 if (choice == scripts_comm)
1720 sprintf(script_opt, " -c %s ", browser->he_selection->thread->comm); 1720 sprintf(script_opt, " -c %s ", thread__comm_str(browser->he_selection->thread));
1721 1721
1722 if (choice == scripts_symbol) 1722 if (choice == scripts_symbol)
1723 sprintf(script_opt, " -S %s ", browser->he_selection->ms.sym->name); 1723 sprintf(script_opt, " -S %s ", browser->he_selection->ms.sym->name);
@@ -1889,7 +1889,7 @@ out:
1889 return key; 1889 return key;
1890} 1890}
1891 1891
1892static bool filter_group_entries(struct ui_browser *self __maybe_unused, 1892static bool filter_group_entries(struct ui_browser *browser __maybe_unused,
1893 void *entry) 1893 void *entry)
1894{ 1894{
1895 struct perf_evsel *evsel = list_entry(entry, struct perf_evsel, node); 1895 struct perf_evsel *evsel = list_entry(entry, struct perf_evsel, node);
diff --git a/tools/perf/ui/browsers/map.c b/tools/perf/ui/browsers/map.c
index 95c7cfb8f2c6..b11639f33682 100644
--- a/tools/perf/ui/browsers/map.c
+++ b/tools/perf/ui/browsers/map.c
@@ -18,30 +18,30 @@ struct map_browser {
18 u8 addrlen; 18 u8 addrlen;
19}; 19};
20 20
21static void map_browser__write(struct ui_browser *self, void *nd, int row) 21static void map_browser__write(struct ui_browser *browser, void *nd, int row)
22{ 22{
23 struct symbol *sym = rb_entry(nd, struct symbol, rb_node); 23 struct symbol *sym = rb_entry(nd, struct symbol, rb_node);
24 struct map_browser *mb = container_of(self, struct map_browser, b); 24 struct map_browser *mb = container_of(browser, struct map_browser, b);
25 bool current_entry = ui_browser__is_current_entry(self, row); 25 bool current_entry = ui_browser__is_current_entry(browser, row);
26 int width; 26 int width;
27 27
28 ui_browser__set_percent_color(self, 0, current_entry); 28 ui_browser__set_percent_color(browser, 0, current_entry);
29 slsmg_printf("%*" PRIx64 " %*" PRIx64 " %c ", 29 slsmg_printf("%*" PRIx64 " %*" PRIx64 " %c ",
30 mb->addrlen, sym->start, mb->addrlen, sym->end, 30 mb->addrlen, sym->start, mb->addrlen, sym->end,
31 sym->binding == STB_GLOBAL ? 'g' : 31 sym->binding == STB_GLOBAL ? 'g' :
32 sym->binding == STB_LOCAL ? 'l' : 'w'); 32 sym->binding == STB_LOCAL ? 'l' : 'w');
33 width = self->width - ((mb->addrlen * 2) + 4); 33 width = browser->width - ((mb->addrlen * 2) + 4);
34 if (width > 0) 34 if (width > 0)
35 slsmg_write_nstring(sym->name, width); 35 slsmg_write_nstring(sym->name, width);
36} 36}
37 37
38/* FIXME uber-kludgy, see comment on cmd_report... */ 38/* FIXME uber-kludgy, see comment on cmd_report... */
39static u32 *symbol__browser_index(struct symbol *self) 39static u32 *symbol__browser_index(struct symbol *browser)
40{ 40{
41 return ((void *)self) - sizeof(struct rb_node) - sizeof(u32); 41 return ((void *)browser) - sizeof(struct rb_node) - sizeof(u32);
42} 42}
43 43
44static int map_browser__search(struct map_browser *self) 44static int map_browser__search(struct map_browser *browser)
45{ 45{
46 char target[512]; 46 char target[512];
47 struct symbol *sym; 47 struct symbol *sym;
@@ -53,37 +53,37 @@ static int map_browser__search(struct map_browser *self)
53 53
54 if (target[0] == '0' && tolower(target[1]) == 'x') { 54 if (target[0] == '0' && tolower(target[1]) == 'x') {
55 u64 addr = strtoull(target, NULL, 16); 55 u64 addr = strtoull(target, NULL, 16);
56 sym = map__find_symbol(self->map, addr, NULL); 56 sym = map__find_symbol(browser->map, addr, NULL);
57 } else 57 } else
58 sym = map__find_symbol_by_name(self->map, target, NULL); 58 sym = map__find_symbol_by_name(browser->map, target, NULL);
59 59
60 if (sym != NULL) { 60 if (sym != NULL) {
61 u32 *idx = symbol__browser_index(sym); 61 u32 *idx = symbol__browser_index(sym);
62 62
63 self->b.top = &sym->rb_node; 63 browser->b.top = &sym->rb_node;
64 self->b.index = self->b.top_idx = *idx; 64 browser->b.index = browser->b.top_idx = *idx;
65 } else 65 } else
66 ui_helpline__fpush("%s not found!", target); 66 ui_helpline__fpush("%s not found!", target);
67 67
68 return 0; 68 return 0;
69} 69}
70 70
71static int map_browser__run(struct map_browser *self) 71static int map_browser__run(struct map_browser *browser)
72{ 72{
73 int key; 73 int key;
74 74
75 if (ui_browser__show(&self->b, self->map->dso->long_name, 75 if (ui_browser__show(&browser->b, browser->map->dso->long_name,
76 "Press <- or ESC to exit, %s / to search", 76 "Press <- or ESC to exit, %s / to search",
77 verbose ? "" : "restart with -v to use") < 0) 77 verbose ? "" : "restart with -v to use") < 0)
78 return -1; 78 return -1;
79 79
80 while (1) { 80 while (1) {
81 key = ui_browser__run(&self->b, 0); 81 key = ui_browser__run(&browser->b, 0);
82 82
83 switch (key) { 83 switch (key) {
84 case '/': 84 case '/':
85 if (verbose) 85 if (verbose)
86 map_browser__search(self); 86 map_browser__search(browser);
87 default: 87 default:
88 break; 88 break;
89 case K_LEFT: 89 case K_LEFT:
@@ -94,20 +94,20 @@ static int map_browser__run(struct map_browser *self)
94 } 94 }
95 } 95 }
96out: 96out:
97 ui_browser__hide(&self->b); 97 ui_browser__hide(&browser->b);
98 return key; 98 return key;
99} 99}
100 100
101int map__browse(struct map *self) 101int map__browse(struct map *map)
102{ 102{
103 struct map_browser mb = { 103 struct map_browser mb = {
104 .b = { 104 .b = {
105 .entries = &self->dso->symbols[self->type], 105 .entries = &map->dso->symbols[map->type],
106 .refresh = ui_browser__rb_tree_refresh, 106 .refresh = ui_browser__rb_tree_refresh,
107 .seek = ui_browser__rb_tree_seek, 107 .seek = ui_browser__rb_tree_seek,
108 .write = map_browser__write, 108 .write = map_browser__write,
109 }, 109 },
110 .map = self, 110 .map = map,
111 }; 111 };
112 struct rb_node *nd; 112 struct rb_node *nd;
113 char tmp[BITS_PER_LONG / 4]; 113 char tmp[BITS_PER_LONG / 4];
diff --git a/tools/perf/ui/browsers/map.h b/tools/perf/ui/browsers/map.h
index df8581a43e17..2d58e4b3eb6f 100644
--- a/tools/perf/ui/browsers/map.h
+++ b/tools/perf/ui/browsers/map.h
@@ -2,5 +2,5 @@
2#define _PERF_UI_MAP_BROWSER_H_ 1 2#define _PERF_UI_MAP_BROWSER_H_ 1
3struct map; 3struct map;
4 4
5int map__browse(struct map *self); 5int map__browse(struct map *map);
6#endif /* _PERF_UI_MAP_BROWSER_H_ */ 6#endif /* _PERF_UI_MAP_BROWSER_H_ */
diff --git a/tools/perf/ui/browsers/scripts.c b/tools/perf/ui/browsers/scripts.c
index 12f009e61e94..d63c68ea02a8 100644
--- a/tools/perf/ui/browsers/scripts.c
+++ b/tools/perf/ui/browsers/scripts.c
@@ -84,22 +84,22 @@ static void script_browser__write(struct ui_browser *browser,
84 slsmg_write_nstring(sline->line, browser->width); 84 slsmg_write_nstring(sline->line, browser->width);
85} 85}
86 86
87static int script_browser__run(struct perf_script_browser *self) 87static int script_browser__run(struct perf_script_browser *browser)
88{ 88{
89 int key; 89 int key;
90 90
91 if (ui_browser__show(&self->b, self->script_name, 91 if (ui_browser__show(&browser->b, browser->script_name,
92 "Press <- or ESC to exit") < 0) 92 "Press <- or ESC to exit") < 0)
93 return -1; 93 return -1;
94 94
95 while (1) { 95 while (1) {
96 key = ui_browser__run(&self->b, 0); 96 key = ui_browser__run(&browser->b, 0);
97 97
98 /* We can add some special key handling here if needed */ 98 /* We can add some special key handling here if needed */
99 break; 99 break;
100 } 100 }
101 101
102 ui_browser__hide(&self->b); 102 ui_browser__hide(&browser->b);
103 return key; 103 return key;
104} 104}
105 105
diff --git a/tools/perf/ui/gtk/annotate.c b/tools/perf/ui/gtk/annotate.c
index f538794615db..9c7ff8d31b27 100644
--- a/tools/perf/ui/gtk/annotate.c
+++ b/tools/perf/ui/gtk/annotate.c
@@ -154,9 +154,9 @@ static int perf_gtk__annotate_symbol(GtkWidget *window, struct symbol *sym,
154 return 0; 154 return 0;
155} 155}
156 156
157int symbol__gtk_annotate(struct symbol *sym, struct map *map, 157static int symbol__gtk_annotate(struct symbol *sym, struct map *map,
158 struct perf_evsel *evsel, 158 struct perf_evsel *evsel,
159 struct hist_browser_timer *hbt) 159 struct hist_browser_timer *hbt)
160{ 160{
161 GtkWidget *window; 161 GtkWidget *window;
162 GtkWidget *notebook; 162 GtkWidget *notebook;
@@ -226,6 +226,13 @@ int symbol__gtk_annotate(struct symbol *sym, struct map *map,
226 return 0; 226 return 0;
227} 227}
228 228
229int hist_entry__gtk_annotate(struct hist_entry *he,
230 struct perf_evsel *evsel,
231 struct hist_browser_timer *hbt)
232{
233 return symbol__gtk_annotate(he->ms.sym, he->ms.map, evsel, hbt);
234}
235
229void perf_gtk__show_annotations(void) 236void perf_gtk__show_annotations(void)
230{ 237{
231 GtkWidget *window; 238 GtkWidget *window;
diff --git a/tools/perf/ui/gtk/browser.c b/tools/perf/ui/gtk/browser.c
index c95012cdb438..c24d91221290 100644
--- a/tools/perf/ui/gtk/browser.c
+++ b/tools/perf/ui/gtk/browser.c
@@ -43,7 +43,7 @@ const char *perf_gtk__get_percent_color(double percent)
43 return NULL; 43 return NULL;
44} 44}
45 45
46#ifdef HAVE_GTK_INFO_BAR 46#ifdef HAVE_GTK_INFO_BAR_SUPPORT
47GtkWidget *perf_gtk__setup_info_bar(void) 47GtkWidget *perf_gtk__setup_info_bar(void)
48{ 48{
49 GtkWidget *info_bar; 49 GtkWidget *info_bar;
diff --git a/tools/perf/ui/gtk/gtk.h b/tools/perf/ui/gtk/gtk.h
index 3d96785ef155..0a9173ff9a61 100644
--- a/tools/perf/ui/gtk/gtk.h
+++ b/tools/perf/ui/gtk/gtk.h
@@ -12,7 +12,7 @@ struct perf_gtk_context {
12 GtkWidget *main_window; 12 GtkWidget *main_window;
13 GtkWidget *notebook; 13 GtkWidget *notebook;
14 14
15#ifdef HAVE_GTK_INFO_BAR 15#ifdef HAVE_GTK_INFO_BAR_SUPPORT
16 GtkWidget *info_bar; 16 GtkWidget *info_bar;
17 GtkWidget *message_label; 17 GtkWidget *message_label;
18#endif 18#endif
@@ -20,6 +20,9 @@ struct perf_gtk_context {
20 guint statbar_ctx_id; 20 guint statbar_ctx_id;
21}; 21};
22 22
23int perf_gtk__init(void);
24void perf_gtk__exit(bool wait_for_ok);
25
23extern struct perf_gtk_context *pgctx; 26extern struct perf_gtk_context *pgctx;
24 27
25static inline bool perf_gtk__is_active_context(struct perf_gtk_context *ctx) 28static inline bool perf_gtk__is_active_context(struct perf_gtk_context *ctx)
@@ -31,7 +34,7 @@ struct perf_gtk_context *perf_gtk__activate_context(GtkWidget *window);
31int perf_gtk__deactivate_context(struct perf_gtk_context **ctx); 34int perf_gtk__deactivate_context(struct perf_gtk_context **ctx);
32 35
33void perf_gtk__init_helpline(void); 36void perf_gtk__init_helpline(void);
34void perf_gtk__init_progress(void); 37void gtk_ui_progress__init(void);
35void perf_gtk__init_hpp(void); 38void perf_gtk__init_hpp(void);
36 39
37void perf_gtk__signal(int sig); 40void perf_gtk__signal(int sig);
@@ -39,7 +42,7 @@ void perf_gtk__resize_window(GtkWidget *window);
39const char *perf_gtk__get_percent_color(double percent); 42const char *perf_gtk__get_percent_color(double percent);
40GtkWidget *perf_gtk__setup_statusbar(void); 43GtkWidget *perf_gtk__setup_statusbar(void);
41 44
42#ifdef HAVE_GTK_INFO_BAR 45#ifdef HAVE_GTK_INFO_BAR_SUPPORT
43GtkWidget *perf_gtk__setup_info_bar(void); 46GtkWidget *perf_gtk__setup_info_bar(void);
44#else 47#else
45static inline GtkWidget *perf_gtk__setup_info_bar(void) 48static inline GtkWidget *perf_gtk__setup_info_bar(void)
@@ -48,4 +51,17 @@ static inline GtkWidget *perf_gtk__setup_info_bar(void)
48} 51}
49#endif 52#endif
50 53
54struct perf_evsel;
55struct perf_evlist;
56struct hist_entry;
57struct hist_browser_timer;
58
59int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, const char *help,
60 struct hist_browser_timer *hbt,
61 float min_pcnt);
62int hist_entry__gtk_annotate(struct hist_entry *he,
63 struct perf_evsel *evsel,
64 struct hist_browser_timer *hbt);
65void perf_gtk__show_annotations(void);
66
51#endif /* _PERF_GTK_H_ */ 67#endif /* _PERF_GTK_H_ */
diff --git a/tools/perf/ui/gtk/progress.c b/tools/perf/ui/gtk/progress.c
index 482bcf3df9b7..b656655fbc39 100644
--- a/tools/perf/ui/gtk/progress.c
+++ b/tools/perf/ui/gtk/progress.c
@@ -7,14 +7,14 @@
7static GtkWidget *dialog; 7static GtkWidget *dialog;
8static GtkWidget *progress; 8static GtkWidget *progress;
9 9
10static void gtk_progress_update(u64 curr, u64 total, const char *title) 10static void gtk_ui_progress__update(struct ui_progress *p)
11{ 11{
12 double fraction = total ? 1.0 * curr / total : 0.0; 12 double fraction = p->total ? 1.0 * p->curr / p->total : 0.0;
13 char buf[1024]; 13 char buf[1024];
14 14
15 if (dialog == NULL) { 15 if (dialog == NULL) {
16 GtkWidget *vbox = gtk_vbox_new(TRUE, 5); 16 GtkWidget *vbox = gtk_vbox_new(TRUE, 5);
17 GtkWidget *label = gtk_label_new(title); 17 GtkWidget *label = gtk_label_new(p->title);
18 18
19 dialog = gtk_window_new(GTK_WINDOW_TOPLEVEL); 19 dialog = gtk_window_new(GTK_WINDOW_TOPLEVEL);
20 progress = gtk_progress_bar_new(); 20 progress = gtk_progress_bar_new();
@@ -32,7 +32,7 @@ static void gtk_progress_update(u64 curr, u64 total, const char *title)
32 } 32 }
33 33
34 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress), fraction); 34 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress), fraction);
35 snprintf(buf, sizeof(buf), "%"PRIu64" / %"PRIu64, curr, total); 35 snprintf(buf, sizeof(buf), "%"PRIu64" / %"PRIu64, p->curr, p->total);
36 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(progress), buf); 36 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(progress), buf);
37 37
38 /* we didn't call gtk_main yet, so do it manually */ 38 /* we didn't call gtk_main yet, so do it manually */
@@ -40,7 +40,7 @@ static void gtk_progress_update(u64 curr, u64 total, const char *title)
40 gtk_main_iteration(); 40 gtk_main_iteration();
41} 41}
42 42
43static void gtk_progress_finish(void) 43static void gtk_ui_progress__finish(void)
44{ 44{
45 /* this will also destroy all of its children */ 45 /* this will also destroy all of its children */
46 gtk_widget_destroy(dialog); 46 gtk_widget_destroy(dialog);
@@ -48,12 +48,12 @@ static void gtk_progress_finish(void)
48 dialog = NULL; 48 dialog = NULL;
49} 49}
50 50
51static struct ui_progress gtk_progress_fns = { 51static struct ui_progress_ops gtk_ui_progress__ops = {
52 .update = gtk_progress_update, 52 .update = gtk_ui_progress__update,
53 .finish = gtk_progress_finish, 53 .finish = gtk_ui_progress__finish,
54}; 54};
55 55
56void perf_gtk__init_progress(void) 56void gtk_ui_progress__init(void)
57{ 57{
58 progress_fns = &gtk_progress_fns; 58 ui_progress__ops = &gtk_ui_progress__ops;
59} 59}
diff --git a/tools/perf/ui/gtk/setup.c b/tools/perf/ui/gtk/setup.c
index 6c2dd2e423f3..1d57676f8212 100644
--- a/tools/perf/ui/gtk/setup.c
+++ b/tools/perf/ui/gtk/setup.c
@@ -8,7 +8,7 @@ int perf_gtk__init(void)
8{ 8{
9 perf_error__register(&perf_gtk_eops); 9 perf_error__register(&perf_gtk_eops);
10 perf_gtk__init_helpline(); 10 perf_gtk__init_helpline();
11 perf_gtk__init_progress(); 11 gtk_ui_progress__init();
12 perf_gtk__init_hpp(); 12 perf_gtk__init_hpp();
13 13
14 return gtk_init_check(NULL, NULL) ? 0 : -1; 14 return gtk_init_check(NULL, NULL) ? 0 : -1;
diff --git a/tools/perf/ui/gtk/util.c b/tools/perf/ui/gtk/util.c
index c06942a41c78..696c1fbe4248 100644
--- a/tools/perf/ui/gtk/util.c
+++ b/tools/perf/ui/gtk/util.c
@@ -53,7 +53,7 @@ static int perf_gtk__error(const char *format, va_list args)
53 return 0; 53 return 0;
54} 54}
55 55
56#ifdef HAVE_GTK_INFO_BAR 56#ifdef HAVE_GTK_INFO_BAR_SUPPORT
57static int perf_gtk__warning_info_bar(const char *format, va_list args) 57static int perf_gtk__warning_info_bar(const char *format, va_list args)
58{ 58{
59 char *msg; 59 char *msg;
@@ -105,7 +105,7 @@ static int perf_gtk__warning_statusbar(const char *format, va_list args)
105 105
106struct perf_error_ops perf_gtk_eops = { 106struct perf_error_ops perf_gtk_eops = {
107 .error = perf_gtk__error, 107 .error = perf_gtk__error,
108#ifdef HAVE_GTK_INFO_BAR 108#ifdef HAVE_GTK_INFO_BAR_SUPPORT
109 .warning = perf_gtk__warning_info_bar, 109 .warning = perf_gtk__warning_info_bar,
110#else 110#else
111 .warning = perf_gtk__warning_statusbar, 111 .warning = perf_gtk__warning_statusbar,
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 0a193281eba8..78f4c92e9b73 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -117,7 +117,7 @@ static int hpp__color_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \
117 struct perf_hpp *hpp, struct hist_entry *he) \ 117 struct perf_hpp *hpp, struct hist_entry *he) \
118{ \ 118{ \
119 return __hpp__fmt(hpp, he, he_get_##_field, " %6.2f%%", \ 119 return __hpp__fmt(hpp, he, he_get_##_field, " %6.2f%%", \
120 (hpp_snprint_fn)percent_color_snprintf, true); \ 120 percent_color_snprintf, true); \
121} 121}
122 122
123#define __HPP_ENTRY_PERCENT_FN(_type, _field) \ 123#define __HPP_ENTRY_PERCENT_FN(_type, _field) \
diff --git a/tools/perf/ui/progress.c b/tools/perf/ui/progress.c
index 3ec695607a4d..a0f24c7115c5 100644
--- a/tools/perf/ui/progress.c
+++ b/tools/perf/ui/progress.c
@@ -1,26 +1,38 @@
1#include "../cache.h" 1#include "../cache.h"
2#include "progress.h" 2#include "progress.h"
3 3
4static void nop_progress_update(u64 curr __maybe_unused, 4static void null_progress__update(struct ui_progress *p __maybe_unused)
5 u64 total __maybe_unused,
6 const char *title __maybe_unused)
7{ 5{
8} 6}
9 7
10static struct ui_progress default_progress_fns = 8static struct ui_progress_ops null_progress__ops =
11{ 9{
12 .update = nop_progress_update, 10 .update = null_progress__update,
13}; 11};
14 12
15struct ui_progress *progress_fns = &default_progress_fns; 13struct ui_progress_ops *ui_progress__ops = &null_progress__ops;
16 14
17void ui_progress__update(u64 curr, u64 total, const char *title) 15void ui_progress__update(struct ui_progress *p, u64 adv)
18{ 16{
19 return progress_fns->update(curr, total, title); 17 p->curr += adv;
18
19 if (p->curr >= p->next) {
20 p->next += p->step;
21 ui_progress__ops->update(p);
22 }
23}
24
25void ui_progress__init(struct ui_progress *p, u64 total, const char *title)
26{
27 p->curr = 0;
28 p->next = p->step = total / 16;
29 p->total = total;
30 p->title = title;
31
20} 32}
21 33
22void ui_progress__finish(void) 34void ui_progress__finish(void)
23{ 35{
24 if (progress_fns->finish) 36 if (ui_progress__ops->finish)
25 progress_fns->finish(); 37 ui_progress__ops->finish();
26} 38}
diff --git a/tools/perf/ui/progress.h b/tools/perf/ui/progress.h
index 257cc224f9cf..29ec8efffefb 100644
--- a/tools/perf/ui/progress.h
+++ b/tools/perf/ui/progress.h
@@ -3,16 +3,21 @@
3 3
4#include <../types.h> 4#include <../types.h>
5 5
6void ui_progress__finish(void);
7
6struct ui_progress { 8struct ui_progress {
7 void (*update)(u64, u64, const char *); 9 const char *title;
8 void (*finish)(void); 10 u64 curr, next, step, total;
9}; 11};
12
13void ui_progress__init(struct ui_progress *p, u64 total, const char *title);
14void ui_progress__update(struct ui_progress *p, u64 adv);
10 15
11extern struct ui_progress *progress_fns; 16struct ui_progress_ops {
12 17 void (*update)(struct ui_progress *p);
13void ui_progress__init(void); 18 void (*finish)(void);
19};
14 20
15void ui_progress__update(u64 curr, u64 total, const char *title); 21extern struct ui_progress_ops *ui_progress__ops;
16void ui_progress__finish(void);
17 22
18#endif 23#endif
diff --git a/tools/perf/ui/setup.c b/tools/perf/ui/setup.c
index 47d9a571f261..5df5140a9f29 100644
--- a/tools/perf/ui/setup.c
+++ b/tools/perf/ui/setup.c
@@ -1,10 +1,64 @@
1#include <pthread.h> 1#include <pthread.h>
2#include <dlfcn.h>
2 3
3#include "../util/cache.h" 4#include "../util/cache.h"
4#include "../util/debug.h" 5#include "../util/debug.h"
5#include "../util/hist.h" 6#include "../util/hist.h"
6 7
7pthread_mutex_t ui__lock = PTHREAD_MUTEX_INITIALIZER; 8pthread_mutex_t ui__lock = PTHREAD_MUTEX_INITIALIZER;
9void *perf_gtk_handle;
10
11#ifdef HAVE_GTK2_SUPPORT
12static int setup_gtk_browser(void)
13{
14 int (*perf_ui_init)(void);
15
16 if (perf_gtk_handle)
17 return 0;
18
19 perf_gtk_handle = dlopen(PERF_GTK_DSO, RTLD_LAZY);
20 if (perf_gtk_handle == NULL) {
21 char buf[PATH_MAX];
22 scnprintf(buf, sizeof(buf), "%s/%s", LIBDIR, PERF_GTK_DSO);
23 perf_gtk_handle = dlopen(buf, RTLD_LAZY);
24 }
25 if (perf_gtk_handle == NULL)
26 return -1;
27
28 perf_ui_init = dlsym(perf_gtk_handle, "perf_gtk__init");
29 if (perf_ui_init == NULL)
30 goto out_close;
31
32 if (perf_ui_init() == 0)
33 return 0;
34
35out_close:
36 dlclose(perf_gtk_handle);
37 return -1;
38}
39
40static void exit_gtk_browser(bool wait_for_ok)
41{
42 void (*perf_ui_exit)(bool);
43
44 if (perf_gtk_handle == NULL)
45 return;
46
47 perf_ui_exit = dlsym(perf_gtk_handle, "perf_gtk__exit");
48 if (perf_ui_exit == NULL)
49 goto out_close;
50
51 perf_ui_exit(wait_for_ok);
52
53out_close:
54 dlclose(perf_gtk_handle);
55
56 perf_gtk_handle = NULL;
57}
58#else
59static inline int setup_gtk_browser(void) { return -1; }
60static inline void exit_gtk_browser(bool wait_for_ok __maybe_unused) {}
61#endif
8 62
9void setup_browser(bool fallback_to_pager) 63void setup_browser(bool fallback_to_pager)
10{ 64{
@@ -17,8 +71,11 @@ void setup_browser(bool fallback_to_pager)
17 71
18 switch (use_browser) { 72 switch (use_browser) {
19 case 2: 73 case 2:
20 if (perf_gtk__init() == 0) 74 if (setup_gtk_browser() == 0)
21 break; 75 break;
76 printf("GTK browser requested but could not find %s\n",
77 PERF_GTK_DSO);
78 sleep(1);
22 /* fall through */ 79 /* fall through */
23 case 1: 80 case 1:
24 use_browser = 1; 81 use_browser = 1;
@@ -39,7 +96,7 @@ void exit_browser(bool wait_for_ok)
39{ 96{
40 switch (use_browser) { 97 switch (use_browser) {
41 case 2: 98 case 2:
42 perf_gtk__exit(wait_for_ok); 99 exit_gtk_browser(wait_for_ok);
43 break; 100 break;
44 101
45 case 1: 102 case 1:
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index 6c152686e837..c244cb524ef2 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -213,20 +213,19 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root,
213 return ret; 213 return ret;
214} 214}
215 215
216static size_t __callchain__fprintf_flat(FILE *fp, 216static size_t __callchain__fprintf_flat(FILE *fp, struct callchain_node *node,
217 struct callchain_node *self,
218 u64 total_samples) 217 u64 total_samples)
219{ 218{
220 struct callchain_list *chain; 219 struct callchain_list *chain;
221 size_t ret = 0; 220 size_t ret = 0;
222 221
223 if (!self) 222 if (!node)
224 return 0; 223 return 0;
225 224
226 ret += __callchain__fprintf_flat(fp, self->parent, total_samples); 225 ret += __callchain__fprintf_flat(fp, node->parent, total_samples);
227 226
228 227
229 list_for_each_entry(chain, &self->val, list) { 228 list_for_each_entry(chain, &node->val, list) {
230 if (chain->ip >= PERF_CONTEXT_MAX) 229 if (chain->ip >= PERF_CONTEXT_MAX)
231 continue; 230 continue;
232 if (chain->ms.sym) 231 if (chain->ms.sym)
@@ -239,15 +238,14 @@ static size_t __callchain__fprintf_flat(FILE *fp,
239 return ret; 238 return ret;
240} 239}
241 240
242static size_t callchain__fprintf_flat(FILE *fp, struct rb_root *self, 241static size_t callchain__fprintf_flat(FILE *fp, struct rb_root *tree,
243 u64 total_samples) 242 u64 total_samples)
244{ 243{
245 size_t ret = 0; 244 size_t ret = 0;
246 u32 entries_printed = 0; 245 u32 entries_printed = 0;
247 struct rb_node *rb_node;
248 struct callchain_node *chain; 246 struct callchain_node *chain;
247 struct rb_node *rb_node = rb_first(tree);
249 248
250 rb_node = rb_first(self);
251 while (rb_node) { 249 while (rb_node) {
252 double percent; 250 double percent;
253 251
diff --git a/tools/perf/ui/tui/progress.c b/tools/perf/ui/tui/progress.c
index 6c2184d53cbf..3e2d936d7443 100644
--- a/tools/perf/ui/tui/progress.c
+++ b/tools/perf/ui/tui/progress.c
@@ -2,9 +2,10 @@
2#include "../progress.h" 2#include "../progress.h"
3#include "../libslang.h" 3#include "../libslang.h"
4#include "../ui.h" 4#include "../ui.h"
5#include "tui.h"
5#include "../browser.h" 6#include "../browser.h"
6 7
7static void tui_progress__update(u64 curr, u64 total, const char *title) 8static void tui_progress__update(struct ui_progress *p)
8{ 9{
9 int bar, y; 10 int bar, y;
10 /* 11 /*
@@ -14,7 +15,7 @@ static void tui_progress__update(u64 curr, u64 total, const char *title)
14 if (use_browser <= 0) 15 if (use_browser <= 0)
15 return; 16 return;
16 17
17 if (total == 0) 18 if (p->total == 0)
18 return; 19 return;
19 20
20 ui__refresh_dimensions(true); 21 ui__refresh_dimensions(true);
@@ -23,20 +24,20 @@ static void tui_progress__update(u64 curr, u64 total, const char *title)
23 SLsmg_set_color(0); 24 SLsmg_set_color(0);
24 SLsmg_draw_box(y, 0, 3, SLtt_Screen_Cols); 25 SLsmg_draw_box(y, 0, 3, SLtt_Screen_Cols);
25 SLsmg_gotorc(y++, 1); 26 SLsmg_gotorc(y++, 1);
26 SLsmg_write_string((char *)title); 27 SLsmg_write_string((char *)p->title);
27 SLsmg_set_color(HE_COLORSET_SELECTED); 28 SLsmg_set_color(HE_COLORSET_SELECTED);
28 bar = ((SLtt_Screen_Cols - 2) * curr) / total; 29 bar = ((SLtt_Screen_Cols - 2) * p->curr) / p->total;
29 SLsmg_fill_region(y, 1, 1, bar, ' '); 30 SLsmg_fill_region(y, 1, 1, bar, ' ');
30 SLsmg_refresh(); 31 SLsmg_refresh();
31 pthread_mutex_unlock(&ui__lock); 32 pthread_mutex_unlock(&ui__lock);
32} 33}
33 34
34static struct ui_progress tui_progress_fns = 35static struct ui_progress_ops tui_progress__ops =
35{ 36{
36 .update = tui_progress__update, 37 .update = tui_progress__update,
37}; 38};
38 39
39void ui_progress__init(void) 40void tui_progress__init(void)
40{ 41{
41 progress_fns = &tui_progress_fns; 42 ui_progress__ops = &tui_progress__ops;
42} 43}
diff --git a/tools/perf/ui/tui/setup.c b/tools/perf/ui/tui/setup.c
index b9401482d110..2f612562978c 100644
--- a/tools/perf/ui/tui/setup.c
+++ b/tools/perf/ui/tui/setup.c
@@ -9,6 +9,7 @@
9#include "../util.h" 9#include "../util.h"
10#include "../libslang.h" 10#include "../libslang.h"
11#include "../keysyms.h" 11#include "../keysyms.h"
12#include "tui.h"
12 13
13static volatile int ui__need_resize; 14static volatile int ui__need_resize;
14 15
@@ -119,7 +120,7 @@ int ui__init(void)
119 120
120 ui_helpline__init(); 121 ui_helpline__init();
121 ui_browser__init(); 122 ui_browser__init();
122 ui_progress__init(); 123 tui_progress__init();
123 124
124 signal(SIGSEGV, ui__signal); 125 signal(SIGSEGV, ui__signal);
125 signal(SIGFPE, ui__signal); 126 signal(SIGFPE, ui__signal);
diff --git a/tools/perf/ui/tui/tui.h b/tools/perf/ui/tui/tui.h
new file mode 100644
index 000000000000..18961c7b6ec5
--- /dev/null
+++ b/tools/perf/ui/tui/tui.h
@@ -0,0 +1,6 @@
1#ifndef _PERF_TUI_H_
2#define _PERF_TUI_H_ 1
3
4void tui_progress__init(void);
5
6#endif /* _PERF_TUI_H_ */
diff --git a/tools/perf/ui/ui.h b/tools/perf/ui/ui.h
index 70cb0d4eb8aa..ab88383f8be8 100644
--- a/tools/perf/ui/ui.h
+++ b/tools/perf/ui/ui.h
@@ -6,13 +6,14 @@
6#include <linux/compiler.h> 6#include <linux/compiler.h>
7 7
8extern pthread_mutex_t ui__lock; 8extern pthread_mutex_t ui__lock;
9extern void *perf_gtk_handle;
9 10
10extern int use_browser; 11extern int use_browser;
11 12
12void setup_browser(bool fallback_to_pager); 13void setup_browser(bool fallback_to_pager);
13void exit_browser(bool wait_for_ok); 14void exit_browser(bool wait_for_ok);
14 15
15#ifdef SLANG_SUPPORT 16#ifdef HAVE_SLANG_SUPPORT
16int ui__init(void); 17int ui__init(void);
17void ui__exit(bool wait_for_ok); 18void ui__exit(bool wait_for_ok);
18#else 19#else
@@ -23,17 +24,6 @@ static inline int ui__init(void)
23static inline void ui__exit(bool wait_for_ok __maybe_unused) {} 24static inline void ui__exit(bool wait_for_ok __maybe_unused) {}
24#endif 25#endif
25 26
26#ifdef GTK2_SUPPORT
27int perf_gtk__init(void);
28void perf_gtk__exit(bool wait_for_ok);
29#else
30static inline int perf_gtk__init(void)
31{
32 return -1;
33}
34static inline void perf_gtk__exit(bool wait_for_ok __maybe_unused) {}
35#endif
36
37void ui__refresh_dimensions(bool force); 27void ui__refresh_dimensions(bool force);
38 28
39#endif /* _PERF_UI_H_ */ 29#endif /* _PERF_UI_H_ */
diff --git a/tools/perf/util/PERF-VERSION-GEN b/tools/perf/util/PERF-VERSION-GEN
index 15a77b7c0e36..39f17507578d 100755
--- a/tools/perf/util/PERF-VERSION-GEN
+++ b/tools/perf/util/PERF-VERSION-GEN
@@ -19,6 +19,9 @@ if test -d ../../.git -o -f ../../.git
19then 19then
20 TAG=$(git describe --abbrev=0 --match "v[0-9].[0-9]*" 2>/dev/null ) 20 TAG=$(git describe --abbrev=0 --match "v[0-9].[0-9]*" 2>/dev/null )
21 CID=$(git log -1 --abbrev=4 --pretty=format:"%h" 2>/dev/null) && CID="-g$CID" 21 CID=$(git log -1 --abbrev=4 --pretty=format:"%h" 2>/dev/null) && CID="-g$CID"
22elif test -f ../../PERF-VERSION-FILE
23then
24 TAG=$(cut -d' ' -f3 ../../PERF-VERSION-FILE | sed -e 's/\"//g')
22fi 25fi
23if test -z "$TAG" 26if test -z "$TAG"
24then 27then
@@ -40,7 +43,7 @@ else
40 VC=unset 43 VC=unset
41fi 44fi
42test "$VN" = "$VC" || { 45test "$VN" = "$VC" || {
43 echo >&2 "PERF_VERSION = $VN" 46 echo >&2 " PERF_VERSION = $VN"
44 echo "#define PERF_VERSION \"$VN\"" >$GVF 47 echo "#define PERF_VERSION \"$VN\"" >$GVF
45} 48}
46 49
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 7eae5488ecea..cf6242c92ee2 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -825,20 +825,16 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
825 dl->ops.target.offset = dl->ops.target.addr - 825 dl->ops.target.offset = dl->ops.target.addr -
826 map__rip_2objdump(map, sym->start); 826 map__rip_2objdump(map, sym->start);
827 827
828 /* 828 /* kcore has no symbols, so add the call target name */
829 * kcore has no symbols, so add the call target name if it is on the
830 * same map.
831 */
832 if (dl->ins && ins__is_call(dl->ins) && !dl->ops.target.name) { 829 if (dl->ins && ins__is_call(dl->ins) && !dl->ops.target.name) {
833 struct symbol *s; 830 struct addr_map_symbol target = {
834 u64 ip = dl->ops.target.addr; 831 .map = map,
835 832 .addr = dl->ops.target.addr,
836 if (ip >= map->start && ip <= map->end) { 833 };
837 ip = map->map_ip(map, ip); 834
838 s = map__find_symbol(map, ip, NULL); 835 if (!map_groups__find_ams(&target, NULL) &&
839 if (s && s->start == ip) 836 target.sym->start == target.al_addr)
840 dl->ops.target.name = strdup(s->name); 837 dl->ops.target.name = strdup(target.sym->name);
841 }
842 } 838 }
843 839
844 disasm__add(&notes->src->source, dl); 840 disasm__add(&notes->src->source, dl);
@@ -879,6 +875,8 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize)
879 FILE *file; 875 FILE *file;
880 int err = 0; 876 int err = 0;
881 char symfs_filename[PATH_MAX]; 877 char symfs_filename[PATH_MAX];
878 struct kcore_extract kce;
879 bool delete_extract = false;
882 880
883 if (filename) { 881 if (filename) {
884 snprintf(symfs_filename, sizeof(symfs_filename), "%s%s", 882 snprintf(symfs_filename, sizeof(symfs_filename), "%s%s",
@@ -940,6 +938,23 @@ fallback:
940 pr_debug("annotating [%p] %30s : [%p] %30s\n", 938 pr_debug("annotating [%p] %30s : [%p] %30s\n",
941 dso, dso->long_name, sym, sym->name); 939 dso, dso->long_name, sym, sym->name);
942 940
941 if (dso__is_kcore(dso)) {
942 kce.kcore_filename = symfs_filename;
943 kce.addr = map__rip_2objdump(map, sym->start);
944 kce.offs = sym->start;
945 kce.len = sym->end + 1 - sym->start;
946 if (!kcore_extract__create(&kce)) {
947 delete_extract = true;
948 strlcpy(symfs_filename, kce.extract_filename,
949 sizeof(symfs_filename));
950 if (free_filename) {
951 free(filename);
952 free_filename = false;
953 }
954 filename = symfs_filename;
955 }
956 }
957
943 snprintf(command, sizeof(command), 958 snprintf(command, sizeof(command),
944 "%s %s%s --start-address=0x%016" PRIx64 959 "%s %s%s --start-address=0x%016" PRIx64
945 " --stop-address=0x%016" PRIx64 960 " --stop-address=0x%016" PRIx64
@@ -972,6 +987,8 @@ fallback:
972 987
973 pclose(file); 988 pclose(file);
974out_free_filename: 989out_free_filename:
990 if (delete_extract)
991 kcore_extract__delete(&kce);
975 if (free_filename) 992 if (free_filename)
976 free(filename); 993 free(filename);
977 return err; 994 return err;
@@ -1070,7 +1087,7 @@ static void symbol__free_source_line(struct symbol *sym, int len)
1070 (sizeof(src_line->p) * (src_line->nr_pcnt - 1)); 1087 (sizeof(src_line->p) * (src_line->nr_pcnt - 1));
1071 1088
1072 for (i = 0; i < len; i++) { 1089 for (i = 0; i < len; i++) {
1073 free(src_line->path); 1090 free_srcline(src_line->path);
1074 src_line = (void *)src_line + sizeof_src_line; 1091 src_line = (void *)src_line + sizeof_src_line;
1075 } 1092 }
1076 1093
@@ -1081,13 +1098,11 @@ static void symbol__free_source_line(struct symbol *sym, int len)
1081/* Get the filename:line for the colored entries */ 1098/* Get the filename:line for the colored entries */
1082static int symbol__get_source_line(struct symbol *sym, struct map *map, 1099static int symbol__get_source_line(struct symbol *sym, struct map *map,
1083 struct perf_evsel *evsel, 1100 struct perf_evsel *evsel,
1084 struct rb_root *root, int len, 1101 struct rb_root *root, int len)
1085 const char *filename)
1086{ 1102{
1087 u64 start; 1103 u64 start;
1088 int i, k; 1104 int i, k;
1089 int evidx = evsel->idx; 1105 int evidx = evsel->idx;
1090 char cmd[PATH_MAX * 2];
1091 struct source_line *src_line; 1106 struct source_line *src_line;
1092 struct annotation *notes = symbol__annotation(sym); 1107 struct annotation *notes = symbol__annotation(sym);
1093 struct sym_hist *h = annotation__histogram(notes, evidx); 1108 struct sym_hist *h = annotation__histogram(notes, evidx);
@@ -1115,10 +1130,7 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
1115 start = map__rip_2objdump(map, sym->start); 1130 start = map__rip_2objdump(map, sym->start);
1116 1131
1117 for (i = 0; i < len; i++) { 1132 for (i = 0; i < len; i++) {
1118 char *path = NULL;
1119 size_t line_len;
1120 u64 offset; 1133 u64 offset;
1121 FILE *fp;
1122 double percent_max = 0.0; 1134 double percent_max = 0.0;
1123 1135
1124 src_line->nr_pcnt = nr_pcnt; 1136 src_line->nr_pcnt = nr_pcnt;
@@ -1135,23 +1147,9 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
1135 goto next; 1147 goto next;
1136 1148
1137 offset = start + i; 1149 offset = start + i;
1138 sprintf(cmd, "addr2line -e %s %016" PRIx64, filename, offset); 1150 src_line->path = get_srcline(map->dso, offset);
1139 fp = popen(cmd, "r");
1140 if (!fp)
1141 goto next;
1142
1143 if (getline(&path, &line_len, fp) < 0 || !line_len)
1144 goto next_close;
1145
1146 src_line->path = malloc(sizeof(char) * line_len + 1);
1147 if (!src_line->path)
1148 goto next_close;
1149
1150 strcpy(src_line->path, path);
1151 insert_source_line(&tmp_root, src_line); 1151 insert_source_line(&tmp_root, src_line);
1152 1152
1153 next_close:
1154 pclose(fp);
1155 next: 1153 next:
1156 src_line = (void *)src_line + sizeof_src_line; 1154 src_line = (void *)src_line + sizeof_src_line;
1157 } 1155 }
@@ -1192,7 +1190,7 @@ static void print_summary(struct rb_root *root, const char *filename)
1192 1190
1193 path = src_line->path; 1191 path = src_line->path;
1194 color = get_percent_color(percent_max); 1192 color = get_percent_color(percent_max);
1195 color_fprintf(stdout, color, " %s", path); 1193 color_fprintf(stdout, color, " %s\n", path);
1196 1194
1197 node = rb_next(node); 1195 node = rb_next(node);
1198 } 1196 }
@@ -1356,7 +1354,6 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map,
1356 bool full_paths, int min_pcnt, int max_lines) 1354 bool full_paths, int min_pcnt, int max_lines)
1357{ 1355{
1358 struct dso *dso = map->dso; 1356 struct dso *dso = map->dso;
1359 const char *filename = dso->long_name;
1360 struct rb_root source_line = RB_ROOT; 1357 struct rb_root source_line = RB_ROOT;
1361 u64 len; 1358 u64 len;
1362 1359
@@ -1366,9 +1363,8 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map,
1366 len = symbol__size(sym); 1363 len = symbol__size(sym);
1367 1364
1368 if (print_lines) { 1365 if (print_lines) {
1369 symbol__get_source_line(sym, map, evsel, &source_line, 1366 symbol__get_source_line(sym, map, evsel, &source_line, len);
1370 len, filename); 1367 print_summary(&source_line, dso->long_name);
1371 print_summary(&source_line, filename);
1372 } 1368 }
1373 1369
1374 symbol__annotate_printf(sym, map, evsel, full_paths, 1370 symbol__annotate_printf(sym, map, evsel, full_paths,
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index af755156d278..834b7b57b788 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -150,7 +150,7 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map,
150 struct perf_evsel *evsel, bool print_lines, 150 struct perf_evsel *evsel, bool print_lines,
151 bool full_paths, int min_pcnt, int max_lines); 151 bool full_paths, int min_pcnt, int max_lines);
152 152
153#ifdef SLANG_SUPPORT 153#ifdef HAVE_SLANG_SUPPORT
154int symbol__tui_annotate(struct symbol *sym, struct map *map, 154int symbol__tui_annotate(struct symbol *sym, struct map *map,
155 struct perf_evsel *evsel, 155 struct perf_evsel *evsel,
156 struct hist_browser_timer *hbt); 156 struct hist_browser_timer *hbt);
@@ -165,30 +165,6 @@ static inline int symbol__tui_annotate(struct symbol *sym __maybe_unused,
165} 165}
166#endif 166#endif
167 167
168#ifdef GTK2_SUPPORT
169int symbol__gtk_annotate(struct symbol *sym, struct map *map,
170 struct perf_evsel *evsel,
171 struct hist_browser_timer *hbt);
172
173static inline int hist_entry__gtk_annotate(struct hist_entry *he,
174 struct perf_evsel *evsel,
175 struct hist_browser_timer *hbt)
176{
177 return symbol__gtk_annotate(he->ms.sym, he->ms.map, evsel, hbt);
178}
179
180void perf_gtk__show_annotations(void);
181#else
182static inline int hist_entry__gtk_annotate(struct hist_entry *he __maybe_unused,
183 struct perf_evsel *evsel __maybe_unused,
184 struct hist_browser_timer *hbt __maybe_unused)
185{
186 return 0;
187}
188
189static inline void perf_gtk__show_annotations(void) {}
190#endif
191
192extern const char *disassembler_style; 168extern const char *disassembler_style;
193 169
194#endif /* __PERF_ANNOTATE_H */ 170#endif /* __PERF_ANNOTATE_H */
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 7ded71d19d75..a92770c98cc7 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -89,14 +89,14 @@ int build_id__sprintf(const u8 *build_id, int len, char *bf)
89 return raw - build_id; 89 return raw - build_id;
90} 90}
91 91
92char *dso__build_id_filename(struct dso *self, char *bf, size_t size) 92char *dso__build_id_filename(struct dso *dso, char *bf, size_t size)
93{ 93{
94 char build_id_hex[BUILD_ID_SIZE * 2 + 1]; 94 char build_id_hex[BUILD_ID_SIZE * 2 + 1];
95 95
96 if (!self->has_build_id) 96 if (!dso->has_build_id)
97 return NULL; 97 return NULL;
98 98
99 build_id__sprintf(self->build_id, sizeof(self->build_id), build_id_hex); 99 build_id__sprintf(dso->build_id, sizeof(dso->build_id), build_id_hex);
100 if (bf == NULL) { 100 if (bf == NULL) {
101 if (asprintf(&bf, "%s/.build-id/%.2s/%s", buildid_dir, 101 if (asprintf(&bf, "%s/.build-id/%.2s/%s", buildid_dir,
102 build_id_hex, build_id_hex + 2) < 0) 102 build_id_hex, build_id_hex + 2) < 0)
diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h
index a811f5c62e18..929f28a7c14d 100644
--- a/tools/perf/util/build-id.h
+++ b/tools/perf/util/build-id.h
@@ -10,10 +10,9 @@ extern struct perf_tool build_id__mark_dso_hit_ops;
10struct dso; 10struct dso;
11 11
12int build_id__sprintf(const u8 *build_id, int len, char *bf); 12int build_id__sprintf(const u8 *build_id, int len, char *bf);
13char *dso__build_id_filename(struct dso *self, char *bf, size_t size); 13char *dso__build_id_filename(struct dso *dso, char *bf, size_t size);
14 14
15int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event, 15int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event,
16 struct perf_sample *sample, struct perf_evsel *evsel, 16 struct perf_sample *sample, struct perf_evsel *evsel,
17 struct machine *machine); 17 struct machine *machine);
18
19#endif 18#endif
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index 26e367239873..7b176dd02e1a 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -70,8 +70,7 @@ extern char *perf_path(const char *fmt, ...) __attribute__((format (printf, 1, 2
70extern char *perf_pathdup(const char *fmt, ...) 70extern char *perf_pathdup(const char *fmt, ...)
71 __attribute__((format (printf, 1, 2))); 71 __attribute__((format (printf, 1, 2)));
72 72
73#ifndef HAVE_STRLCPY 73/* Matches the libc/libbsd function attribute so we declare this unconditionally: */
74extern size_t strlcpy(char *dest, const char *src, size_t size); 74extern size_t strlcpy(char *dest, const char *src, size_t size);
75#endif
76 75
77#endif /* __PERF_CACHE_H */ 76#endif /* __PERF_CACHE_H */
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 482f68081cd8..e3970e3eaacf 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -21,12 +21,6 @@
21 21
22__thread struct callchain_cursor callchain_cursor; 22__thread struct callchain_cursor callchain_cursor;
23 23
24#define chain_for_each_child(child, parent) \
25 list_for_each_entry(child, &parent->children, siblings)
26
27#define chain_for_each_child_safe(child, next, parent) \
28 list_for_each_entry_safe(child, next, &parent->children, siblings)
29
30static void 24static void
31rb_insert_callchain(struct rb_root *root, struct callchain_node *chain, 25rb_insert_callchain(struct rb_root *root, struct callchain_node *chain,
32 enum chain_mode mode) 26 enum chain_mode mode)
@@ -71,10 +65,16 @@ static void
71__sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node, 65__sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node,
72 u64 min_hit) 66 u64 min_hit)
73{ 67{
68 struct rb_node *n;
74 struct callchain_node *child; 69 struct callchain_node *child;
75 70
76 chain_for_each_child(child, node) 71 n = rb_first(&node->rb_root_in);
72 while (n) {
73 child = rb_entry(n, struct callchain_node, rb_node_in);
74 n = rb_next(n);
75
77 __sort_chain_flat(rb_root, child, min_hit); 76 __sort_chain_flat(rb_root, child, min_hit);
77 }
78 78
79 if (node->hit && node->hit >= min_hit) 79 if (node->hit && node->hit >= min_hit)
80 rb_insert_callchain(rb_root, node, CHAIN_FLAT); 80 rb_insert_callchain(rb_root, node, CHAIN_FLAT);
@@ -94,11 +94,16 @@ sort_chain_flat(struct rb_root *rb_root, struct callchain_root *root,
94static void __sort_chain_graph_abs(struct callchain_node *node, 94static void __sort_chain_graph_abs(struct callchain_node *node,
95 u64 min_hit) 95 u64 min_hit)
96{ 96{
97 struct rb_node *n;
97 struct callchain_node *child; 98 struct callchain_node *child;
98 99
99 node->rb_root = RB_ROOT; 100 node->rb_root = RB_ROOT;
101 n = rb_first(&node->rb_root_in);
102
103 while (n) {
104 child = rb_entry(n, struct callchain_node, rb_node_in);
105 n = rb_next(n);
100 106
101 chain_for_each_child(child, node) {
102 __sort_chain_graph_abs(child, min_hit); 107 __sort_chain_graph_abs(child, min_hit);
103 if (callchain_cumul_hits(child) >= min_hit) 108 if (callchain_cumul_hits(child) >= min_hit)
104 rb_insert_callchain(&node->rb_root, child, 109 rb_insert_callchain(&node->rb_root, child,
@@ -117,13 +122,18 @@ sort_chain_graph_abs(struct rb_root *rb_root, struct callchain_root *chain_root,
117static void __sort_chain_graph_rel(struct callchain_node *node, 122static void __sort_chain_graph_rel(struct callchain_node *node,
118 double min_percent) 123 double min_percent)
119{ 124{
125 struct rb_node *n;
120 struct callchain_node *child; 126 struct callchain_node *child;
121 u64 min_hit; 127 u64 min_hit;
122 128
123 node->rb_root = RB_ROOT; 129 node->rb_root = RB_ROOT;
124 min_hit = ceil(node->children_hit * min_percent); 130 min_hit = ceil(node->children_hit * min_percent);
125 131
126 chain_for_each_child(child, node) { 132 n = rb_first(&node->rb_root_in);
133 while (n) {
134 child = rb_entry(n, struct callchain_node, rb_node_in);
135 n = rb_next(n);
136
127 __sort_chain_graph_rel(child, min_percent); 137 __sort_chain_graph_rel(child, min_percent);
128 if (callchain_cumul_hits(child) >= min_hit) 138 if (callchain_cumul_hits(child) >= min_hit)
129 rb_insert_callchain(&node->rb_root, child, 139 rb_insert_callchain(&node->rb_root, child,
@@ -173,19 +183,26 @@ create_child(struct callchain_node *parent, bool inherit_children)
173 return NULL; 183 return NULL;
174 } 184 }
175 new->parent = parent; 185 new->parent = parent;
176 INIT_LIST_HEAD(&new->children);
177 INIT_LIST_HEAD(&new->val); 186 INIT_LIST_HEAD(&new->val);
178 187
179 if (inherit_children) { 188 if (inherit_children) {
180 struct callchain_node *next; 189 struct rb_node *n;
190 struct callchain_node *child;
191
192 new->rb_root_in = parent->rb_root_in;
193 parent->rb_root_in = RB_ROOT;
181 194
182 list_splice(&parent->children, &new->children); 195 n = rb_first(&new->rb_root_in);
183 INIT_LIST_HEAD(&parent->children); 196 while (n) {
197 child = rb_entry(n, struct callchain_node, rb_node_in);
198 child->parent = new;
199 n = rb_next(n);
200 }
184 201
185 chain_for_each_child(next, new) 202 /* make it the first child */
186 next->parent = new; 203 rb_link_node(&new->rb_node_in, NULL, &parent->rb_root_in.rb_node);
204 rb_insert_color(&new->rb_node_in, &parent->rb_root_in);
187 } 205 }
188 list_add_tail(&new->siblings, &parent->children);
189 206
190 return new; 207 return new;
191} 208}
@@ -223,7 +240,7 @@ fill_node(struct callchain_node *node, struct callchain_cursor *cursor)
223 } 240 }
224} 241}
225 242
226static void 243static struct callchain_node *
227add_child(struct callchain_node *parent, 244add_child(struct callchain_node *parent,
228 struct callchain_cursor *cursor, 245 struct callchain_cursor *cursor,
229 u64 period) 246 u64 period)
@@ -235,6 +252,19 @@ add_child(struct callchain_node *parent,
235 252
236 new->children_hit = 0; 253 new->children_hit = 0;
237 new->hit = period; 254 new->hit = period;
255 return new;
256}
257
258static s64 match_chain(struct callchain_cursor_node *node,
259 struct callchain_list *cnode)
260{
261 struct symbol *sym = node->sym;
262
263 if (cnode->ms.sym && sym &&
264 callchain_param.key == CCKEY_FUNCTION)
265 return cnode->ms.sym->start - sym->start;
266 else
267 return cnode->ip - node->ip;
238} 268}
239 269
240/* 270/*
@@ -272,9 +302,33 @@ split_add_child(struct callchain_node *parent,
272 302
273 /* create a new child for the new branch if any */ 303 /* create a new child for the new branch if any */
274 if (idx_total < cursor->nr) { 304 if (idx_total < cursor->nr) {
305 struct callchain_node *first;
306 struct callchain_list *cnode;
307 struct callchain_cursor_node *node;
308 struct rb_node *p, **pp;
309
275 parent->hit = 0; 310 parent->hit = 0;
276 add_child(parent, cursor, period);
277 parent->children_hit += period; 311 parent->children_hit += period;
312
313 node = callchain_cursor_current(cursor);
314 new = add_child(parent, cursor, period);
315
316 /*
317 * This is second child since we moved parent's children
318 * to new (first) child above.
319 */
320 p = parent->rb_root_in.rb_node;
321 first = rb_entry(p, struct callchain_node, rb_node_in);
322 cnode = list_first_entry(&first->val, struct callchain_list,
323 list);
324
325 if (match_chain(node, cnode) < 0)
326 pp = &p->rb_left;
327 else
328 pp = &p->rb_right;
329
330 rb_link_node(&new->rb_node_in, p, pp);
331 rb_insert_color(&new->rb_node_in, &parent->rb_root_in);
278 } else { 332 } else {
279 parent->hit = period; 333 parent->hit = period;
280 } 334 }
@@ -291,16 +345,40 @@ append_chain_children(struct callchain_node *root,
291 u64 period) 345 u64 period)
292{ 346{
293 struct callchain_node *rnode; 347 struct callchain_node *rnode;
348 struct callchain_cursor_node *node;
349 struct rb_node **p = &root->rb_root_in.rb_node;
350 struct rb_node *parent = NULL;
351
352 node = callchain_cursor_current(cursor);
353 if (!node)
354 return;
294 355
295 /* lookup in childrens */ 356 /* lookup in childrens */
296 chain_for_each_child(rnode, root) { 357 while (*p) {
297 unsigned int ret = append_chain(rnode, cursor, period); 358 s64 ret;
359 struct callchain_list *cnode;
298 360
299 if (!ret) 361 parent = *p;
362 rnode = rb_entry(parent, struct callchain_node, rb_node_in);
363 cnode = list_first_entry(&rnode->val, struct callchain_list,
364 list);
365
366 /* just check first entry */
367 ret = match_chain(node, cnode);
368 if (ret == 0) {
369 append_chain(rnode, cursor, period);
300 goto inc_children_hit; 370 goto inc_children_hit;
371 }
372
373 if (ret < 0)
374 p = &parent->rb_left;
375 else
376 p = &parent->rb_right;
301 } 377 }
302 /* nothing in children, add to the current node */ 378 /* nothing in children, add to the current node */
303 add_child(root, cursor, period); 379 rnode = add_child(root, cursor, period);
380 rb_link_node(&rnode->rb_node_in, parent, p);
381 rb_insert_color(&rnode->rb_node_in, &root->rb_root_in);
304 382
305inc_children_hit: 383inc_children_hit:
306 root->children_hit += period; 384 root->children_hit += period;
@@ -325,28 +403,20 @@ append_chain(struct callchain_node *root,
325 */ 403 */
326 list_for_each_entry(cnode, &root->val, list) { 404 list_for_each_entry(cnode, &root->val, list) {
327 struct callchain_cursor_node *node; 405 struct callchain_cursor_node *node;
328 struct symbol *sym;
329 406
330 node = callchain_cursor_current(cursor); 407 node = callchain_cursor_current(cursor);
331 if (!node) 408 if (!node)
332 break; 409 break;
333 410
334 sym = node->sym; 411 if (match_chain(node, cnode) != 0)
335
336 if (cnode->ms.sym && sym &&
337 callchain_param.key == CCKEY_FUNCTION) {
338 if (cnode->ms.sym->start != sym->start)
339 break;
340 } else if (cnode->ip != node->ip)
341 break; 412 break;
342 413
343 if (!found) 414 found = true;
344 found = true;
345 415
346 callchain_cursor_advance(cursor); 416 callchain_cursor_advance(cursor);
347 } 417 }
348 418
349 /* matches not, relay on the parent */ 419 /* matches not, relay no the parent */
350 if (!found) { 420 if (!found) {
351 cursor->curr = curr_snap; 421 cursor->curr = curr_snap;
352 cursor->pos = start; 422 cursor->pos = start;
@@ -395,8 +465,9 @@ merge_chain_branch(struct callchain_cursor *cursor,
395 struct callchain_node *dst, struct callchain_node *src) 465 struct callchain_node *dst, struct callchain_node *src)
396{ 466{
397 struct callchain_cursor_node **old_last = cursor->last; 467 struct callchain_cursor_node **old_last = cursor->last;
398 struct callchain_node *child, *next_child; 468 struct callchain_node *child;
399 struct callchain_list *list, *next_list; 469 struct callchain_list *list, *next_list;
470 struct rb_node *n;
400 int old_pos = cursor->nr; 471 int old_pos = cursor->nr;
401 int err = 0; 472 int err = 0;
402 473
@@ -412,12 +483,16 @@ merge_chain_branch(struct callchain_cursor *cursor,
412 append_chain_children(dst, cursor, src->hit); 483 append_chain_children(dst, cursor, src->hit);
413 } 484 }
414 485
415 chain_for_each_child_safe(child, next_child, src) { 486 n = rb_first(&src->rb_root_in);
487 while (n) {
488 child = container_of(n, struct callchain_node, rb_node_in);
489 n = rb_next(n);
490 rb_erase(&child->rb_node_in, &src->rb_root_in);
491
416 err = merge_chain_branch(cursor, dst, child); 492 err = merge_chain_branch(cursor, dst, child);
417 if (err) 493 if (err)
418 break; 494 break;
419 495
420 list_del(&child->siblings);
421 free(child); 496 free(child);
422 } 497 }
423 498
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index 9e99060408ae..4f7f989876ec 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -21,11 +21,11 @@ enum chain_order {
21 21
22struct callchain_node { 22struct callchain_node {
23 struct callchain_node *parent; 23 struct callchain_node *parent;
24 struct list_head siblings;
25 struct list_head children;
26 struct list_head val; 24 struct list_head val;
27 struct rb_node rb_node; /* to sort nodes in an rbtree */ 25 struct rb_node rb_node_in; /* to insert nodes in an rbtree */
28 struct rb_root rb_root; /* sorted tree of children */ 26 struct rb_node rb_node; /* to sort nodes in an output tree */
27 struct rb_root rb_root_in; /* input tree of children */
28 struct rb_root rb_root; /* sorted output tree of children */
29 unsigned int val_nr; 29 unsigned int val_nr;
30 u64 hit; 30 u64 hit;
31 u64 children_hit; 31 u64 children_hit;
@@ -86,13 +86,12 @@ extern __thread struct callchain_cursor callchain_cursor;
86 86
87static inline void callchain_init(struct callchain_root *root) 87static inline void callchain_init(struct callchain_root *root)
88{ 88{
89 INIT_LIST_HEAD(&root->node.siblings);
90 INIT_LIST_HEAD(&root->node.children);
91 INIT_LIST_HEAD(&root->node.val); 89 INIT_LIST_HEAD(&root->node.val);
92 90
93 root->node.parent = NULL; 91 root->node.parent = NULL;
94 root->node.hit = 0; 92 root->node.hit = 0;
95 root->node.children_hit = 0; 93 root->node.children_hit = 0;
94 root->node.rb_root_in = RB_ROOT;
96 root->max_depth = 0; 95 root->max_depth = 0;
97} 96}
98 97
diff --git a/tools/perf/util/color.c b/tools/perf/util/color.c
index 11e46da17bbb..66e44a5019d5 100644
--- a/tools/perf/util/color.c
+++ b/tools/perf/util/color.c
@@ -318,8 +318,15 @@ int percent_color_fprintf(FILE *fp, const char *fmt, double percent)
318 return r; 318 return r;
319} 319}
320 320
321int percent_color_snprintf(char *bf, size_t size, const char *fmt, double percent) 321int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...)
322{ 322{
323 const char *color = get_percent_color(percent); 323 va_list args;
324 double percent;
325 const char *color;
326
327 va_start(args, fmt);
328 percent = va_arg(args, double);
329 va_end(args);
330 color = get_percent_color(percent);
324 return color_snprintf(bf, size, color, fmt, percent); 331 return color_snprintf(bf, size, color, fmt, percent);
325} 332}
diff --git a/tools/perf/util/color.h b/tools/perf/util/color.h
index dea082b79602..fced3840e99c 100644
--- a/tools/perf/util/color.h
+++ b/tools/perf/util/color.h
@@ -39,7 +39,7 @@ int color_fprintf(FILE *fp, const char *color, const char *fmt, ...);
39int color_snprintf(char *bf, size_t size, const char *color, const char *fmt, ...); 39int color_snprintf(char *bf, size_t size, const char *color, const char *fmt, ...);
40int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...); 40int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...);
41int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf); 41int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf);
42int percent_color_snprintf(char *bf, size_t size, const char *fmt, double percent); 42int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...);
43int percent_color_fprintf(FILE *fp, const char *fmt, double percent); 43int percent_color_fprintf(FILE *fp, const char *fmt, double percent);
44const char *get_percent_color(double percent); 44const char *get_percent_color(double percent);
45 45
diff --git a/tools/perf/util/comm.c b/tools/perf/util/comm.c
new file mode 100644
index 000000000000..ee0df0e24cdb
--- /dev/null
+++ b/tools/perf/util/comm.c
@@ -0,0 +1,121 @@
1#include "comm.h"
2#include "util.h"
3#include <stdlib.h>
4#include <stdio.h>
5
6struct comm_str {
7 char *str;
8 struct rb_node rb_node;
9 int ref;
10};
11
12/* Should perhaps be moved to struct machine */
13static struct rb_root comm_str_root;
14
15static void comm_str__get(struct comm_str *cs)
16{
17 cs->ref++;
18}
19
20static void comm_str__put(struct comm_str *cs)
21{
22 if (!--cs->ref) {
23 rb_erase(&cs->rb_node, &comm_str_root);
24 free(cs->str);
25 free(cs);
26 }
27}
28
29static struct comm_str *comm_str__alloc(const char *str)
30{
31 struct comm_str *cs;
32
33 cs = zalloc(sizeof(*cs));
34 if (!cs)
35 return NULL;
36
37 cs->str = strdup(str);
38 if (!cs->str) {
39 free(cs);
40 return NULL;
41 }
42
43 return cs;
44}
45
46static struct comm_str *comm_str__findnew(const char *str, struct rb_root *root)
47{
48 struct rb_node **p = &root->rb_node;
49 struct rb_node *parent = NULL;
50 struct comm_str *iter, *new;
51 int cmp;
52
53 while (*p != NULL) {
54 parent = *p;
55 iter = rb_entry(parent, struct comm_str, rb_node);
56
57 cmp = strcmp(str, iter->str);
58 if (!cmp)
59 return iter;
60
61 if (cmp < 0)
62 p = &(*p)->rb_left;
63 else
64 p = &(*p)->rb_right;
65 }
66
67 new = comm_str__alloc(str);
68 if (!new)
69 return NULL;
70
71 rb_link_node(&new->rb_node, parent, p);
72 rb_insert_color(&new->rb_node, root);
73
74 return new;
75}
76
77struct comm *comm__new(const char *str, u64 timestamp)
78{
79 struct comm *comm = zalloc(sizeof(*comm));
80
81 if (!comm)
82 return NULL;
83
84 comm->start = timestamp;
85
86 comm->comm_str = comm_str__findnew(str, &comm_str_root);
87 if (!comm->comm_str) {
88 free(comm);
89 return NULL;
90 }
91
92 comm_str__get(comm->comm_str);
93
94 return comm;
95}
96
97void comm__override(struct comm *comm, const char *str, u64 timestamp)
98{
99 struct comm_str *old = comm->comm_str;
100
101 comm->comm_str = comm_str__findnew(str, &comm_str_root);
102 if (!comm->comm_str) {
103 comm->comm_str = old;
104 return;
105 }
106
107 comm->start = timestamp;
108 comm_str__get(comm->comm_str);
109 comm_str__put(old);
110}
111
112void comm__free(struct comm *comm)
113{
114 comm_str__put(comm->comm_str);
115 free(comm);
116}
117
118const char *comm__str(const struct comm *comm)
119{
120 return comm->comm_str->str;
121}
diff --git a/tools/perf/util/comm.h b/tools/perf/util/comm.h
new file mode 100644
index 000000000000..7a86e5656710
--- /dev/null
+++ b/tools/perf/util/comm.h
@@ -0,0 +1,21 @@
1#ifndef __PERF_COMM_H
2#define __PERF_COMM_H
3
4#include "../perf.h"
5#include <linux/rbtree.h>
6#include <linux/list.h>
7
8struct comm_str;
9
10struct comm {
11 struct comm_str *comm_str;
12 u64 start;
13 struct list_head list;
14};
15
16void comm__free(struct comm *comm);
17struct comm *comm__new(const char *str, u64 timestamp);
18const char *comm__str(const struct comm *comm);
19void comm__override(struct comm *comm, const char *str, u64 timestamp);
20
21#endif /* __PERF_COMM_H */
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index beb8cf9f9976..a9b48c42e81e 100644
--- a/tools/perf/util/cpumap.c
+++ b/tools/perf/util/cpumap.c
@@ -1,5 +1,5 @@
1#include "util.h" 1#include "util.h"
2#include "sysfs.h" 2#include "fs.h"
3#include "../perf.h" 3#include "../perf.h"
4#include "cpumap.h" 4#include "cpumap.h"
5#include <assert.h> 5#include <assert.h>
@@ -216,7 +216,7 @@ int cpu_map__get_socket(struct cpu_map *map, int idx)
216 216
217 cpu = map->map[idx]; 217 cpu = map->map[idx];
218 218
219 mnt = sysfs_find_mountpoint(); 219 mnt = sysfs__mountpoint();
220 if (!mnt) 220 if (!mnt)
221 return -1; 221 return -1;
222 222
@@ -279,7 +279,7 @@ int cpu_map__get_core(struct cpu_map *map, int idx)
279 279
280 cpu = map->map[idx]; 280 cpu = map->map[idx];
281 281
282 mnt = sysfs_find_mountpoint(); 282 mnt = sysfs__mountpoint();
283 if (!mnt) 283 if (!mnt)
284 return -1; 284 return -1;
285 285
diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c
new file mode 100644
index 000000000000..7d09faf85cf1
--- /dev/null
+++ b/tools/perf/util/data.c
@@ -0,0 +1,120 @@
1#include <linux/compiler.h>
2#include <linux/kernel.h>
3#include <sys/types.h>
4#include <sys/stat.h>
5#include <unistd.h>
6#include <string.h>
7
8#include "data.h"
9#include "util.h"
10
11static bool check_pipe(struct perf_data_file *file)
12{
13 struct stat st;
14 bool is_pipe = false;
15 int fd = perf_data_file__is_read(file) ?
16 STDIN_FILENO : STDOUT_FILENO;
17
18 if (!file->path) {
19 if (!fstat(fd, &st) && S_ISFIFO(st.st_mode))
20 is_pipe = true;
21 } else {
22 if (!strcmp(file->path, "-"))
23 is_pipe = true;
24 }
25
26 if (is_pipe)
27 file->fd = fd;
28
29 return file->is_pipe = is_pipe;
30}
31
32static int check_backup(struct perf_data_file *file)
33{
34 struct stat st;
35
36 if (!stat(file->path, &st) && st.st_size) {
37 /* TODO check errors properly */
38 char oldname[PATH_MAX];
39 snprintf(oldname, sizeof(oldname), "%s.old",
40 file->path);
41 unlink(oldname);
42 rename(file->path, oldname);
43 }
44
45 return 0;
46}
47
48static int open_file_read(struct perf_data_file *file)
49{
50 struct stat st;
51 int fd;
52
53 fd = open(file->path, O_RDONLY);
54 if (fd < 0) {
55 int err = errno;
56
57 pr_err("failed to open %s: %s", file->path, strerror(err));
58 if (err == ENOENT && !strcmp(file->path, "perf.data"))
59 pr_err(" (try 'perf record' first)");
60 pr_err("\n");
61 return -err;
62 }
63
64 if (fstat(fd, &st) < 0)
65 goto out_close;
66
67 if (!file->force && st.st_uid && (st.st_uid != geteuid())) {
68 pr_err("file %s not owned by current user or root\n",
69 file->path);
70 goto out_close;
71 }
72
73 if (!st.st_size) {
74 pr_info("zero-sized file (%s), nothing to do!\n",
75 file->path);
76 goto out_close;
77 }
78
79 file->size = st.st_size;
80 return fd;
81
82 out_close:
83 close(fd);
84 return -1;
85}
86
87static int open_file_write(struct perf_data_file *file)
88{
89 if (check_backup(file))
90 return -1;
91
92 return open(file->path, O_CREAT|O_RDWR|O_TRUNC, S_IRUSR|S_IWUSR);
93}
94
95static int open_file(struct perf_data_file *file)
96{
97 int fd;
98
99 fd = perf_data_file__is_read(file) ?
100 open_file_read(file) : open_file_write(file);
101
102 file->fd = fd;
103 return fd < 0 ? -1 : 0;
104}
105
106int perf_data_file__open(struct perf_data_file *file)
107{
108 if (check_pipe(file))
109 return 0;
110
111 if (!file->path)
112 file->path = "perf.data";
113
114 return open_file(file);
115}
116
117void perf_data_file__close(struct perf_data_file *file)
118{
119 close(file->fd);
120}
diff --git a/tools/perf/util/data.h b/tools/perf/util/data.h
new file mode 100644
index 000000000000..8c2df80152a5
--- /dev/null
+++ b/tools/perf/util/data.h
@@ -0,0 +1,48 @@
1#ifndef __PERF_DATA_H
2#define __PERF_DATA_H
3
4#include <stdbool.h>
5
6enum perf_data_mode {
7 PERF_DATA_MODE_WRITE,
8 PERF_DATA_MODE_READ,
9};
10
11struct perf_data_file {
12 const char *path;
13 int fd;
14 bool is_pipe;
15 bool force;
16 unsigned long size;
17 enum perf_data_mode mode;
18};
19
20static inline bool perf_data_file__is_read(struct perf_data_file *file)
21{
22 return file->mode == PERF_DATA_MODE_READ;
23}
24
25static inline bool perf_data_file__is_write(struct perf_data_file *file)
26{
27 return file->mode == PERF_DATA_MODE_WRITE;
28}
29
30static inline int perf_data_file__is_pipe(struct perf_data_file *file)
31{
32 return file->is_pipe;
33}
34
35static inline int perf_data_file__fd(struct perf_data_file *file)
36{
37 return file->fd;
38}
39
40static inline unsigned long perf_data_file__size(struct perf_data_file *file)
41{
42 return file->size;
43}
44
45int perf_data_file__open(struct perf_data_file *file);
46void perf_data_file__close(struct perf_data_file *file);
47
48#endif /* __PERF_DATA_H */
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index e3c1ff8512c8..af4c687cc49b 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -7,19 +7,20 @@
7char dso__symtab_origin(const struct dso *dso) 7char dso__symtab_origin(const struct dso *dso)
8{ 8{
9 static const char origin[] = { 9 static const char origin[] = {
10 [DSO_BINARY_TYPE__KALLSYMS] = 'k', 10 [DSO_BINARY_TYPE__KALLSYMS] = 'k',
11 [DSO_BINARY_TYPE__VMLINUX] = 'v', 11 [DSO_BINARY_TYPE__VMLINUX] = 'v',
12 [DSO_BINARY_TYPE__JAVA_JIT] = 'j', 12 [DSO_BINARY_TYPE__JAVA_JIT] = 'j',
13 [DSO_BINARY_TYPE__DEBUGLINK] = 'l', 13 [DSO_BINARY_TYPE__DEBUGLINK] = 'l',
14 [DSO_BINARY_TYPE__BUILD_ID_CACHE] = 'B', 14 [DSO_BINARY_TYPE__BUILD_ID_CACHE] = 'B',
15 [DSO_BINARY_TYPE__FEDORA_DEBUGINFO] = 'f', 15 [DSO_BINARY_TYPE__FEDORA_DEBUGINFO] = 'f',
16 [DSO_BINARY_TYPE__UBUNTU_DEBUGINFO] = 'u', 16 [DSO_BINARY_TYPE__UBUNTU_DEBUGINFO] = 'u',
17 [DSO_BINARY_TYPE__BUILDID_DEBUGINFO] = 'b', 17 [DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO] = 'o',
18 [DSO_BINARY_TYPE__SYSTEM_PATH_DSO] = 'd', 18 [DSO_BINARY_TYPE__BUILDID_DEBUGINFO] = 'b',
19 [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE] = 'K', 19 [DSO_BINARY_TYPE__SYSTEM_PATH_DSO] = 'd',
20 [DSO_BINARY_TYPE__GUEST_KALLSYMS] = 'g', 20 [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE] = 'K',
21 [DSO_BINARY_TYPE__GUEST_KMODULE] = 'G', 21 [DSO_BINARY_TYPE__GUEST_KALLSYMS] = 'g',
22 [DSO_BINARY_TYPE__GUEST_VMLINUX] = 'V', 22 [DSO_BINARY_TYPE__GUEST_KMODULE] = 'G',
23 [DSO_BINARY_TYPE__GUEST_VMLINUX] = 'V',
23 }; 24 };
24 25
25 if (dso == NULL || dso->symtab_type == DSO_BINARY_TYPE__NOT_FOUND) 26 if (dso == NULL || dso->symtab_type == DSO_BINARY_TYPE__NOT_FOUND)
@@ -64,6 +65,28 @@ int dso__binary_type_file(struct dso *dso, enum dso_binary_type type,
64 symbol_conf.symfs, dso->long_name); 65 symbol_conf.symfs, dso->long_name);
65 break; 66 break;
66 67
68 case DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO:
69 {
70 char *last_slash;
71 size_t len;
72 size_t dir_size;
73
74 last_slash = dso->long_name + dso->long_name_len;
75 while (last_slash != dso->long_name && *last_slash != '/')
76 last_slash--;
77
78 len = scnprintf(file, size, "%s", symbol_conf.symfs);
79 dir_size = last_slash - dso->long_name + 2;
80 if (dir_size > (size - len)) {
81 ret = -1;
82 break;
83 }
84 len += scnprintf(file + len, dir_size, "%s", dso->long_name);
85 len += scnprintf(file + len , size - len, ".debug%s",
86 last_slash);
87 break;
88 }
89
67 case DSO_BINARY_TYPE__BUILDID_DEBUGINFO: 90 case DSO_BINARY_TYPE__BUILDID_DEBUGINFO:
68 if (!dso->has_build_id) { 91 if (!dso->has_build_id) {
69 ret = -1; 92 ret = -1;
@@ -427,6 +450,7 @@ struct dso *dso__new(const char *name)
427 dso->rel = 0; 450 dso->rel = 0;
428 dso->sorted_by_name = 0; 451 dso->sorted_by_name = 0;
429 dso->has_build_id = 0; 452 dso->has_build_id = 0;
453 dso->has_srcline = 1;
430 dso->kernel = DSO_TYPE_USER; 454 dso->kernel = DSO_TYPE_USER;
431 dso->needs_swap = DSO_SWAP__UNSET; 455 dso->needs_swap = DSO_SWAP__UNSET;
432 INIT_LIST_HEAD(&dso->node); 456 INIT_LIST_HEAD(&dso->node);
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index b793053335d6..9ac666abbe7e 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -6,6 +6,7 @@
6#include <stdbool.h> 6#include <stdbool.h>
7#include "types.h" 7#include "types.h"
8#include "map.h" 8#include "map.h"
9#include "build-id.h"
9 10
10enum dso_binary_type { 11enum dso_binary_type {
11 DSO_BINARY_TYPE__KALLSYMS = 0, 12 DSO_BINARY_TYPE__KALLSYMS = 0,
@@ -23,6 +24,7 @@ enum dso_binary_type {
23 DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE, 24 DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE,
24 DSO_BINARY_TYPE__KCORE, 25 DSO_BINARY_TYPE__KCORE,
25 DSO_BINARY_TYPE__GUEST_KCORE, 26 DSO_BINARY_TYPE__GUEST_KCORE,
27 DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,
26 DSO_BINARY_TYPE__NOT_FOUND, 28 DSO_BINARY_TYPE__NOT_FOUND,
27}; 29};
28 30
@@ -81,6 +83,7 @@ struct dso {
81 enum dso_binary_type data_type; 83 enum dso_binary_type data_type;
82 u8 adjust_symbols:1; 84 u8 adjust_symbols:1;
83 u8 has_build_id:1; 85 u8 has_build_id:1;
86 u8 has_srcline:1;
84 u8 hit:1; 87 u8 hit:1;
85 u8 annotate_warned:1; 88 u8 annotate_warned:1;
86 u8 sname_alloc:1; 89 u8 sname_alloc:1;
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 49096ea58a15..ec9ae1114ed4 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -512,18 +512,18 @@ size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp)
512 512
513int perf_event__process_comm(struct perf_tool *tool __maybe_unused, 513int perf_event__process_comm(struct perf_tool *tool __maybe_unused,
514 union perf_event *event, 514 union perf_event *event,
515 struct perf_sample *sample __maybe_unused, 515 struct perf_sample *sample,
516 struct machine *machine) 516 struct machine *machine)
517{ 517{
518 return machine__process_comm_event(machine, event); 518 return machine__process_comm_event(machine, event, sample);
519} 519}
520 520
521int perf_event__process_lost(struct perf_tool *tool __maybe_unused, 521int perf_event__process_lost(struct perf_tool *tool __maybe_unused,
522 union perf_event *event, 522 union perf_event *event,
523 struct perf_sample *sample __maybe_unused, 523 struct perf_sample *sample,
524 struct machine *machine) 524 struct machine *machine)
525{ 525{
526 return machine__process_lost_event(machine, event); 526 return machine__process_lost_event(machine, event, sample);
527} 527}
528 528
529size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp) 529size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp)
@@ -546,18 +546,18 @@ size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp)
546 546
547int perf_event__process_mmap(struct perf_tool *tool __maybe_unused, 547int perf_event__process_mmap(struct perf_tool *tool __maybe_unused,
548 union perf_event *event, 548 union perf_event *event,
549 struct perf_sample *sample __maybe_unused, 549 struct perf_sample *sample,
550 struct machine *machine) 550 struct machine *machine)
551{ 551{
552 return machine__process_mmap_event(machine, event); 552 return machine__process_mmap_event(machine, event, sample);
553} 553}
554 554
555int perf_event__process_mmap2(struct perf_tool *tool __maybe_unused, 555int perf_event__process_mmap2(struct perf_tool *tool __maybe_unused,
556 union perf_event *event, 556 union perf_event *event,
557 struct perf_sample *sample __maybe_unused, 557 struct perf_sample *sample,
558 struct machine *machine) 558 struct machine *machine)
559{ 559{
560 return machine__process_mmap2_event(machine, event); 560 return machine__process_mmap2_event(machine, event, sample);
561} 561}
562 562
563size_t perf_event__fprintf_task(union perf_event *event, FILE *fp) 563size_t perf_event__fprintf_task(union perf_event *event, FILE *fp)
@@ -569,18 +569,18 @@ size_t perf_event__fprintf_task(union perf_event *event, FILE *fp)
569 569
570int perf_event__process_fork(struct perf_tool *tool __maybe_unused, 570int perf_event__process_fork(struct perf_tool *tool __maybe_unused,
571 union perf_event *event, 571 union perf_event *event,
572 struct perf_sample *sample __maybe_unused, 572 struct perf_sample *sample,
573 struct machine *machine) 573 struct machine *machine)
574{ 574{
575 return machine__process_fork_event(machine, event); 575 return machine__process_fork_event(machine, event, sample);
576} 576}
577 577
578int perf_event__process_exit(struct perf_tool *tool __maybe_unused, 578int perf_event__process_exit(struct perf_tool *tool __maybe_unused,
579 union perf_event *event, 579 union perf_event *event,
580 struct perf_sample *sample __maybe_unused, 580 struct perf_sample *sample,
581 struct machine *machine) 581 struct machine *machine)
582{ 582{
583 return machine__process_exit_event(machine, event); 583 return machine__process_exit_event(machine, event, sample);
584} 584}
585 585
586size_t perf_event__fprintf(union perf_event *event, FILE *fp) 586size_t perf_event__fprintf(union perf_event *event, FILE *fp)
@@ -611,21 +611,21 @@ size_t perf_event__fprintf(union perf_event *event, FILE *fp)
611 611
612int perf_event__process(struct perf_tool *tool __maybe_unused, 612int perf_event__process(struct perf_tool *tool __maybe_unused,
613 union perf_event *event, 613 union perf_event *event,
614 struct perf_sample *sample __maybe_unused, 614 struct perf_sample *sample,
615 struct machine *machine) 615 struct machine *machine)
616{ 616{
617 return machine__process_event(machine, event); 617 return machine__process_event(machine, event, sample);
618} 618}
619 619
620void thread__find_addr_map(struct thread *self, 620void thread__find_addr_map(struct thread *thread,
621 struct machine *machine, u8 cpumode, 621 struct machine *machine, u8 cpumode,
622 enum map_type type, u64 addr, 622 enum map_type type, u64 addr,
623 struct addr_location *al) 623 struct addr_location *al)
624{ 624{
625 struct map_groups *mg = &self->mg; 625 struct map_groups *mg = &thread->mg;
626 bool load_map = false; 626 bool load_map = false;
627 627
628 al->thread = self; 628 al->thread = thread;
629 al->addr = addr; 629 al->addr = addr;
630 al->cpumode = cpumode; 630 al->cpumode = cpumode;
631 al->filtered = false; 631 al->filtered = false;
@@ -721,10 +721,10 @@ int perf_event__preprocess_sample(const union perf_event *event,
721 return -1; 721 return -1;
722 722
723 if (symbol_conf.comm_list && 723 if (symbol_conf.comm_list &&
724 !strlist__has_entry(symbol_conf.comm_list, thread->comm)) 724 !strlist__has_entry(symbol_conf.comm_list, thread__comm_str(thread)))
725 goto out_filtered; 725 goto out_filtered;
726 726
727 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->tid); 727 dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread), thread->tid);
728 /* 728 /*
729 * Have we already created the kernel maps for this machine? 729 * Have we already created the kernel maps for this machine?
730 * 730 *
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index c67ecc457d29..f8d70f3003ab 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -61,6 +61,12 @@ struct read_event {
61 u64 id; 61 u64 id;
62}; 62};
63 63
64struct throttle_event {
65 struct perf_event_header header;
66 u64 time;
67 u64 id;
68 u64 stream_id;
69};
64 70
65#define PERF_SAMPLE_MASK \ 71#define PERF_SAMPLE_MASK \
66 (PERF_SAMPLE_IP | PERF_SAMPLE_TID | \ 72 (PERF_SAMPLE_IP | PERF_SAMPLE_TID | \
@@ -69,6 +75,9 @@ struct read_event {
69 PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD | \ 75 PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD | \
70 PERF_SAMPLE_IDENTIFIER) 76 PERF_SAMPLE_IDENTIFIER)
71 77
78/* perf sample has 16 bits size limit */
79#define PERF_SAMPLE_MAX_SIZE (1 << 16)
80
72struct sample_event { 81struct sample_event {
73 struct perf_event_header header; 82 struct perf_event_header header;
74 u64 array[]; 83 u64 array[];
@@ -111,6 +120,7 @@ struct perf_sample {
111 u64 stream_id; 120 u64 stream_id;
112 u64 period; 121 u64 period;
113 u64 weight; 122 u64 weight;
123 u64 transaction;
114 u32 cpu; 124 u32 cpu;
115 u32 raw_size; 125 u32 raw_size;
116 u64 data_src; 126 u64 data_src;
@@ -177,6 +187,7 @@ union perf_event {
177 struct fork_event fork; 187 struct fork_event fork;
178 struct lost_event lost; 188 struct lost_event lost;
179 struct read_event read; 189 struct read_event read;
190 struct throttle_event throttle;
180 struct sample_event sample; 191 struct sample_event sample;
181 struct attr_event attr; 192 struct attr_event attr;
182 struct event_type_event event_type; 193 struct event_type_event event_type;
@@ -240,7 +251,8 @@ int perf_event__process(struct perf_tool *tool,
240 struct machine *machine); 251 struct machine *machine);
241 252
242struct addr_location; 253struct addr_location;
243int perf_event__preprocess_sample(const union perf_event *self, 254
255int perf_event__preprocess_sample(const union perf_event *event,
244 struct machine *machine, 256 struct machine *machine,
245 struct addr_location *al, 257 struct addr_location *al,
246 struct perf_sample *sample); 258 struct perf_sample *sample);
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index e584cd30b0f2..b939221efd8d 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -18,6 +18,7 @@
18#include <unistd.h> 18#include <unistd.h>
19 19
20#include "parse-events.h" 20#include "parse-events.h"
21#include "parse-options.h"
21 22
22#include <sys/mman.h> 23#include <sys/mman.h>
23 24
@@ -49,6 +50,18 @@ struct perf_evlist *perf_evlist__new(void)
49 return evlist; 50 return evlist;
50} 51}
51 52
53struct perf_evlist *perf_evlist__new_default(void)
54{
55 struct perf_evlist *evlist = perf_evlist__new();
56
57 if (evlist && perf_evlist__add_default(evlist)) {
58 perf_evlist__delete(evlist);
59 evlist = NULL;
60 }
61
62 return evlist;
63}
64
52/** 65/**
53 * perf_evlist__set_id_pos - set the positions of event ids. 66 * perf_evlist__set_id_pos - set the positions of event ids.
54 * @evlist: selected event list 67 * @evlist: selected event list
@@ -242,7 +255,7 @@ int perf_evlist__add_newtp(struct perf_evlist *evlist,
242 if (evsel == NULL) 255 if (evsel == NULL)
243 return -1; 256 return -1;
244 257
245 evsel->handler.func = handler; 258 evsel->handler = handler;
246 perf_evlist__add(evlist, evsel); 259 perf_evlist__add(evlist, evsel);
247 return 0; 260 return 0;
248} 261}
@@ -527,7 +540,7 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
527 if ((old & md->mask) + size != ((old + size) & md->mask)) { 540 if ((old & md->mask) + size != ((old + size) & md->mask)) {
528 unsigned int offset = old; 541 unsigned int offset = old;
529 unsigned int len = min(sizeof(*event), size), cpy; 542 unsigned int len = min(sizeof(*event), size), cpy;
530 void *dst = &md->event_copy; 543 void *dst = md->event_copy;
531 544
532 do { 545 do {
533 cpy = min(md->mask + 1 - (offset & md->mask), len); 546 cpy = min(md->mask + 1 - (offset & md->mask), len);
@@ -537,7 +550,7 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
537 len -= cpy; 550 len -= cpy;
538 } while (len); 551 } while (len);
539 552
540 event = &md->event_copy; 553 event = (union perf_event *) md->event_copy;
541 } 554 }
542 555
543 old += size; 556 old += size;
@@ -594,6 +607,8 @@ static int __perf_evlist__mmap(struct perf_evlist *evlist,
594 evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, prot, 607 evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, prot,
595 MAP_SHARED, fd, 0); 608 MAP_SHARED, fd, 0);
596 if (evlist->mmap[idx].base == MAP_FAILED) { 609 if (evlist->mmap[idx].base == MAP_FAILED) {
610 pr_debug2("failed to mmap perf event ring buffer, error %d\n",
611 errno);
597 evlist->mmap[idx].base = NULL; 612 evlist->mmap[idx].base = NULL;
598 return -1; 613 return -1;
599 } 614 }
@@ -602,9 +617,36 @@ static int __perf_evlist__mmap(struct perf_evlist *evlist,
602 return 0; 617 return 0;
603} 618}
604 619
605static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, int prot, int mask) 620static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
621 int prot, int mask, int cpu, int thread,
622 int *output)
606{ 623{
607 struct perf_evsel *evsel; 624 struct perf_evsel *evsel;
625
626 list_for_each_entry(evsel, &evlist->entries, node) {
627 int fd = FD(evsel, cpu, thread);
628
629 if (*output == -1) {
630 *output = fd;
631 if (__perf_evlist__mmap(evlist, idx, prot, mask,
632 *output) < 0)
633 return -1;
634 } else {
635 if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0)
636 return -1;
637 }
638
639 if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
640 perf_evlist__id_add_fd(evlist, evsel, cpu, thread, fd) < 0)
641 return -1;
642 }
643
644 return 0;
645}
646
647static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, int prot,
648 int mask)
649{
608 int cpu, thread; 650 int cpu, thread;
609 int nr_cpus = cpu_map__nr(evlist->cpus); 651 int nr_cpus = cpu_map__nr(evlist->cpus);
610 int nr_threads = thread_map__nr(evlist->threads); 652 int nr_threads = thread_map__nr(evlist->threads);
@@ -614,23 +656,9 @@ static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, int prot, int m
614 int output = -1; 656 int output = -1;
615 657
616 for (thread = 0; thread < nr_threads; thread++) { 658 for (thread = 0; thread < nr_threads; thread++) {
617 list_for_each_entry(evsel, &evlist->entries, node) { 659 if (perf_evlist__mmap_per_evsel(evlist, cpu, prot, mask,
618 int fd = FD(evsel, cpu, thread); 660 cpu, thread, &output))
619 661 goto out_unmap;
620 if (output == -1) {
621 output = fd;
622 if (__perf_evlist__mmap(evlist, cpu,
623 prot, mask, output) < 0)
624 goto out_unmap;
625 } else {
626 if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, output) != 0)
627 goto out_unmap;
628 }
629
630 if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
631 perf_evlist__id_add_fd(evlist, evsel, cpu, thread, fd) < 0)
632 goto out_unmap;
633 }
634 } 662 }
635 } 663 }
636 664
@@ -642,9 +670,9 @@ out_unmap:
642 return -1; 670 return -1;
643} 671}
644 672
645static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, int prot, int mask) 673static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, int prot,
674 int mask)
646{ 675{
647 struct perf_evsel *evsel;
648 int thread; 676 int thread;
649 int nr_threads = thread_map__nr(evlist->threads); 677 int nr_threads = thread_map__nr(evlist->threads);
650 678
@@ -652,23 +680,9 @@ static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, int prot, in
652 for (thread = 0; thread < nr_threads; thread++) { 680 for (thread = 0; thread < nr_threads; thread++) {
653 int output = -1; 681 int output = -1;
654 682
655 list_for_each_entry(evsel, &evlist->entries, node) { 683 if (perf_evlist__mmap_per_evsel(evlist, thread, prot, mask, 0,
656 int fd = FD(evsel, 0, thread); 684 thread, &output))
657 685 goto out_unmap;
658 if (output == -1) {
659 output = fd;
660 if (__perf_evlist__mmap(evlist, thread,
661 prot, mask, output) < 0)
662 goto out_unmap;
663 } else {
664 if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, output) != 0)
665 goto out_unmap;
666 }
667
668 if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
669 perf_evlist__id_add_fd(evlist, evsel, 0, thread, fd) < 0)
670 goto out_unmap;
671 }
672 } 686 }
673 687
674 return 0; 688 return 0;
@@ -679,20 +693,76 @@ out_unmap:
679 return -1; 693 return -1;
680} 694}
681 695
682/** perf_evlist__mmap - Create per cpu maps to receive events 696static size_t perf_evlist__mmap_size(unsigned long pages)
683 * 697{
684 * @evlist - list of events 698 /* 512 kiB: default amount of unprivileged mlocked memory */
685 * @pages - map length in pages 699 if (pages == UINT_MAX)
686 * @overwrite - overwrite older events? 700 pages = (512 * 1024) / page_size;
687 * 701 else if (!is_power_of_2(pages))
688 * If overwrite is false the user needs to signal event consuption using: 702 return 0;
689 * 703
690 * struct perf_mmap *m = &evlist->mmap[cpu]; 704 return (pages + 1) * page_size;
691 * unsigned int head = perf_mmap__read_head(m); 705}
706
707int perf_evlist__parse_mmap_pages(const struct option *opt, const char *str,
708 int unset __maybe_unused)
709{
710 unsigned int *mmap_pages = opt->value;
711 unsigned long pages, val;
712 size_t size;
713 static struct parse_tag tags[] = {
714 { .tag = 'B', .mult = 1 },
715 { .tag = 'K', .mult = 1 << 10 },
716 { .tag = 'M', .mult = 1 << 20 },
717 { .tag = 'G', .mult = 1 << 30 },
718 { .tag = 0 },
719 };
720
721 val = parse_tag_value(str, tags);
722 if (val != (unsigned long) -1) {
723 /* we got file size value */
724 pages = PERF_ALIGN(val, page_size) / page_size;
725 if (pages < (1UL << 31) && !is_power_of_2(pages)) {
726 pages = next_pow2(pages);
727 pr_info("rounding mmap pages size to %lu (%lu pages)\n",
728 pages * page_size, pages);
729 }
730 } else {
731 /* we got pages count value */
732 char *eptr;
733 pages = strtoul(str, &eptr, 10);
734 if (*eptr != '\0') {
735 pr_err("failed to parse --mmap_pages/-m value\n");
736 return -1;
737 }
738 }
739
740 if (pages > UINT_MAX || pages > SIZE_MAX / page_size) {
741 pr_err("--mmap_pages/-m value too big\n");
742 return -1;
743 }
744
745 size = perf_evlist__mmap_size(pages);
746 if (!size) {
747 pr_err("--mmap_pages/-m value must be a power of two.");
748 return -1;
749 }
750
751 *mmap_pages = pages;
752 return 0;
753}
754
755/**
756 * perf_evlist__mmap - Create mmaps to receive events.
757 * @evlist: list of events
758 * @pages: map length in pages
759 * @overwrite: overwrite older events?
692 * 760 *
693 * perf_mmap__write_tail(m, head) 761 * If @overwrite is %false the user needs to signal event consumption using
762 * perf_mmap__write_tail(). Using perf_evlist__mmap_read() does this
763 * automatically.
694 * 764 *
695 * Using perf_evlist__read_on_cpu does this automatically. 765 * Return: %0 on success, negative error code otherwise.
696 */ 766 */
697int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages, 767int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
698 bool overwrite) 768 bool overwrite)
@@ -702,14 +772,6 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
702 const struct thread_map *threads = evlist->threads; 772 const struct thread_map *threads = evlist->threads;
703 int prot = PROT_READ | (overwrite ? 0 : PROT_WRITE), mask; 773 int prot = PROT_READ | (overwrite ? 0 : PROT_WRITE), mask;
704 774
705 /* 512 kiB: default amount of unprivileged mlocked memory */
706 if (pages == UINT_MAX)
707 pages = (512 * 1024) / page_size;
708 else if (!is_power_of_2(pages))
709 return -EINVAL;
710
711 mask = pages * page_size - 1;
712
713 if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0) 775 if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0)
714 return -ENOMEM; 776 return -ENOMEM;
715 777
@@ -717,7 +779,9 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
717 return -ENOMEM; 779 return -ENOMEM;
718 780
719 evlist->overwrite = overwrite; 781 evlist->overwrite = overwrite;
720 evlist->mmap_len = (pages + 1) * page_size; 782 evlist->mmap_len = perf_evlist__mmap_size(pages);
783 pr_debug("mmap size %zuB\n", evlist->mmap_len);
784 mask = evlist->mmap_len - page_size - 1;
721 785
722 list_for_each_entry(evsel, &evlist->entries, node) { 786 list_for_each_entry(evsel, &evlist->entries, node) {
723 if ((evsel->attr.read_format & PERF_FORMAT_ID) && 787 if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
@@ -1073,3 +1137,66 @@ size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp)
1073 1137
1074 return printed + fprintf(fp, "\n");; 1138 return printed + fprintf(fp, "\n");;
1075} 1139}
1140
1141int perf_evlist__strerror_tp(struct perf_evlist *evlist __maybe_unused,
1142 int err, char *buf, size_t size)
1143{
1144 char sbuf[128];
1145
1146 switch (err) {
1147 case ENOENT:
1148 scnprintf(buf, size, "%s",
1149 "Error:\tUnable to find debugfs\n"
1150 "Hint:\tWas your kernel was compiled with debugfs support?\n"
1151 "Hint:\tIs the debugfs filesystem mounted?\n"
1152 "Hint:\tTry 'sudo mount -t debugfs nodev /sys/kernel/debug'");
1153 break;
1154 case EACCES:
1155 scnprintf(buf, size,
1156 "Error:\tNo permissions to read %s/tracing/events/raw_syscalls\n"
1157 "Hint:\tTry 'sudo mount -o remount,mode=755 %s'\n",
1158 debugfs_mountpoint, debugfs_mountpoint);
1159 break;
1160 default:
1161 scnprintf(buf, size, "%s", strerror_r(err, sbuf, sizeof(sbuf)));
1162 break;
1163 }
1164
1165 return 0;
1166}
1167
1168int perf_evlist__strerror_open(struct perf_evlist *evlist __maybe_unused,
1169 int err, char *buf, size_t size)
1170{
1171 int printed, value;
1172 char sbuf[128], *emsg = strerror_r(err, sbuf, sizeof(sbuf));
1173
1174 switch (err) {
1175 case EACCES:
1176 case EPERM:
1177 printed = scnprintf(buf, size,
1178 "Error:\t%s.\n"
1179 "Hint:\tCheck /proc/sys/kernel/perf_event_paranoid setting.", emsg);
1180
1181 if (filename__read_int("/proc/sys/kernel/perf_event_paranoid", &value))
1182 break;
1183
1184 printed += scnprintf(buf + printed, size - printed, "\nHint:\t");
1185
1186 if (value >= 2) {
1187 printed += scnprintf(buf + printed, size - printed,
1188 "For your workloads it needs to be <= 1\nHint:\t");
1189 }
1190 printed += scnprintf(buf + printed, size - printed,
1191 "For system wide tracing it needs to be set to -1");
1192
1193 printed += scnprintf(buf + printed, size - printed,
1194 ".\nHint:\tThe current value is %d.", value);
1195 break;
1196 default:
1197 scnprintf(buf, size, "%s", emsg);
1198 break;
1199 }
1200
1201 return 0;
1202}
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 206d09339306..ecaa582f40e2 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -21,7 +21,7 @@ struct perf_mmap {
21 void *base; 21 void *base;
22 int mask; 22 int mask;
23 unsigned int prev; 23 unsigned int prev;
24 union perf_event event_copy; 24 char event_copy[PERF_SAMPLE_MAX_SIZE];
25}; 25};
26 26
27struct perf_evlist { 27struct perf_evlist {
@@ -31,7 +31,7 @@ struct perf_evlist {
31 int nr_groups; 31 int nr_groups;
32 int nr_fds; 32 int nr_fds;
33 int nr_mmaps; 33 int nr_mmaps;
34 int mmap_len; 34 size_t mmap_len;
35 int id_pos; 35 int id_pos;
36 int is_pos; 36 int is_pos;
37 u64 combined_sample_type; 37 u64 combined_sample_type;
@@ -53,6 +53,7 @@ struct perf_evsel_str_handler {
53}; 53};
54 54
55struct perf_evlist *perf_evlist__new(void); 55struct perf_evlist *perf_evlist__new(void);
56struct perf_evlist *perf_evlist__new_default(void);
56void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus, 57void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus,
57 struct thread_map *threads); 58 struct thread_map *threads);
58void perf_evlist__exit(struct perf_evlist *evlist); 59void perf_evlist__exit(struct perf_evlist *evlist);
@@ -87,7 +88,7 @@ struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id);
87 88
88struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id); 89struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id);
89 90
90union perf_event *perf_evlist__mmap_read(struct perf_evlist *self, int idx); 91union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx);
91 92
92void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx); 93void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx);
93 94
@@ -98,6 +99,7 @@ void perf_evlist__set_id_pos(struct perf_evlist *evlist);
98bool perf_can_sample_identifier(void); 99bool perf_can_sample_identifier(void);
99void perf_evlist__config(struct perf_evlist *evlist, 100void perf_evlist__config(struct perf_evlist *evlist,
100 struct perf_record_opts *opts); 101 struct perf_record_opts *opts);
102int perf_record_opts__config(struct perf_record_opts *opts);
101 103
102int perf_evlist__prepare_workload(struct perf_evlist *evlist, 104int perf_evlist__prepare_workload(struct perf_evlist *evlist,
103 struct perf_target *target, 105 struct perf_target *target,
@@ -105,6 +107,10 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist,
105 bool want_signal); 107 bool want_signal);
106int perf_evlist__start_workload(struct perf_evlist *evlist); 108int perf_evlist__start_workload(struct perf_evlist *evlist);
107 109
110int perf_evlist__parse_mmap_pages(const struct option *opt,
111 const char *str,
112 int unset);
113
108int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages, 114int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
109 bool overwrite); 115 bool overwrite);
110void perf_evlist__munmap(struct perf_evlist *evlist); 116void perf_evlist__munmap(struct perf_evlist *evlist);
@@ -165,10 +171,13 @@ static inline struct perf_evsel *perf_evlist__last(struct perf_evlist *evlist)
165 171
166size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp); 172size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp);
167 173
174int perf_evlist__strerror_tp(struct perf_evlist *evlist, int err, char *buf, size_t size);
175int perf_evlist__strerror_open(struct perf_evlist *evlist, int err, char *buf, size_t size);
176
168static inline unsigned int perf_mmap__read_head(struct perf_mmap *mm) 177static inline unsigned int perf_mmap__read_head(struct perf_mmap *mm)
169{ 178{
170 struct perf_event_mmap_page *pc = mm->base; 179 struct perf_event_mmap_page *pc = mm->base;
171 int head = pc->data_head; 180 int head = ACCESS_ONCE(pc->data_head);
172 rmb(); 181 rmb();
173 return head; 182 return head;
174} 183}
@@ -181,7 +190,7 @@ static inline void perf_mmap__write_tail(struct perf_mmap *md,
181 /* 190 /*
182 * ensure all reads are done before we write the tail out. 191 * ensure all reads are done before we write the tail out.
183 */ 192 */
184 /* mb(); */ 193 mb();
185 pc->data_tail = tail; 194 pc->data_tail = tail;
186} 195}
187 196
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 9f1ef9bee2d0..5280820ed389 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -663,7 +663,7 @@ void perf_evsel__config(struct perf_evsel *evsel,
663 } 663 }
664 664
665 if (opts->sample_address) 665 if (opts->sample_address)
666 attr->sample_type |= PERF_SAMPLE_DATA_SRC; 666 perf_evsel__set_sample_bit(evsel, DATA_SRC);
667 667
668 if (opts->no_delay) { 668 if (opts->no_delay) {
669 attr->watermark = 0; 669 attr->watermark = 0;
@@ -675,11 +675,14 @@ void perf_evsel__config(struct perf_evsel *evsel,
675 } 675 }
676 676
677 if (opts->sample_weight) 677 if (opts->sample_weight)
678 attr->sample_type |= PERF_SAMPLE_WEIGHT; 678 perf_evsel__set_sample_bit(evsel, WEIGHT);
679 679
680 attr->mmap = track; 680 attr->mmap = track;
681 attr->comm = track; 681 attr->comm = track;
682 682
683 if (opts->sample_transaction)
684 perf_evsel__set_sample_bit(evsel, TRANSACTION);
685
683 /* 686 /*
684 * XXX see the function comment above 687 * XXX see the function comment above
685 * 688 *
@@ -982,6 +985,7 @@ static size_t perf_event_attr__fprintf(struct perf_event_attr *attr, FILE *fp)
982 ret += PRINT_ATTR2(exclude_host, exclude_guest); 985 ret += PRINT_ATTR2(exclude_host, exclude_guest);
983 ret += PRINT_ATTR2N("excl.callchain_kern", exclude_callchain_kernel, 986 ret += PRINT_ATTR2N("excl.callchain_kern", exclude_callchain_kernel,
984 "excl.callchain_user", exclude_callchain_user); 987 "excl.callchain_user", exclude_callchain_user);
988 ret += PRINT_ATTR_U32(mmap2);
985 989
986 ret += PRINT_ATTR_U32(wakeup_events); 990 ret += PRINT_ATTR_U32(wakeup_events);
987 ret += PRINT_ATTR_U32(wakeup_watermark); 991 ret += PRINT_ATTR_U32(wakeup_watermark);
@@ -1047,6 +1051,8 @@ retry_open:
1047 group_fd, flags); 1051 group_fd, flags);
1048 if (FD(evsel, cpu, thread) < 0) { 1052 if (FD(evsel, cpu, thread) < 0) {
1049 err = -errno; 1053 err = -errno;
1054 pr_debug2("perf_event_open failed, error %d\n",
1055 err);
1050 goto try_fallback; 1056 goto try_fallback;
1051 } 1057 }
1052 set_rlimit = NO_CHANGE; 1058 set_rlimit = NO_CHANGE;
@@ -1213,6 +1219,7 @@ static int perf_evsel__parse_id_sample(const struct perf_evsel *evsel,
1213 1219
1214 sample->pid = u.val32[0]; 1220 sample->pid = u.val32[0];
1215 sample->tid = u.val32[1]; 1221 sample->tid = u.val32[1];
1222 array--;
1216 } 1223 }
1217 1224
1218 return 0; 1225 return 0;
@@ -1452,6 +1459,9 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
1452 array = (void *)array + sz; 1459 array = (void *)array + sz;
1453 OVERFLOW_CHECK_u64(array); 1460 OVERFLOW_CHECK_u64(array);
1454 data->user_stack.size = *array++; 1461 data->user_stack.size = *array++;
1462 if (WARN_ONCE(data->user_stack.size > sz,
1463 "user stack dump failure\n"))
1464 return -EFAULT;
1455 } 1465 }
1456 } 1466 }
1457 1467
@@ -1469,6 +1479,13 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
1469 array++; 1479 array++;
1470 } 1480 }
1471 1481
1482 data->transaction = 0;
1483 if (type & PERF_SAMPLE_TRANSACTION) {
1484 OVERFLOW_CHECK_u64(array);
1485 data->transaction = *array;
1486 array++;
1487 }
1488
1472 return 0; 1489 return 0;
1473} 1490}
1474 1491
@@ -1561,6 +1578,9 @@ size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type,
1561 if (type & PERF_SAMPLE_DATA_SRC) 1578 if (type & PERF_SAMPLE_DATA_SRC)
1562 result += sizeof(u64); 1579 result += sizeof(u64);
1563 1580
1581 if (type & PERF_SAMPLE_TRANSACTION)
1582 result += sizeof(u64);
1583
1564 return result; 1584 return result;
1565} 1585}
1566 1586
@@ -1734,6 +1754,11 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type,
1734 array++; 1754 array++;
1735 } 1755 }
1736 1756
1757 if (type & PERF_SAMPLE_TRANSACTION) {
1758 *array = sample->transaction;
1759 array++;
1760 }
1761
1737 return 0; 1762 return 0;
1738} 1763}
1739 1764
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 4a7bdc713bab..64ec8e1a7a28 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -74,10 +74,7 @@ struct perf_evsel {
74 off_t id_offset; 74 off_t id_offset;
75 }; 75 };
76 struct cgroup_sel *cgrp; 76 struct cgroup_sel *cgrp;
77 struct { 77 void *handler;
78 void *func;
79 void *data;
80 } handler;
81 struct cpu_map *cpus; 78 struct cpu_map *cpus;
82 unsigned int sample_size; 79 unsigned int sample_size;
83 int id_pos; 80 int id_pos;
@@ -197,6 +194,12 @@ static inline bool perf_evsel__match2(struct perf_evsel *e1,
197 (e1->attr.config == e2->attr.config); 194 (e1->attr.config == e2->attr.config);
198} 195}
199 196
197#define perf_evsel__cmp(a, b) \
198 ((a) && \
199 (b) && \
200 (a)->attr.type == (b)->attr.type && \
201 (a)->attr.config == (b)->attr.config)
202
200int __perf_evsel__read_on_cpu(struct perf_evsel *evsel, 203int __perf_evsel__read_on_cpu(struct perf_evsel *evsel,
201 int cpu, int thread, bool scale); 204 int cpu, int thread, bool scale);
202 205
diff --git a/tools/perf/util/fs.c b/tools/perf/util/fs.c
new file mode 100644
index 000000000000..f5be1f26e724
--- /dev/null
+++ b/tools/perf/util/fs.c
@@ -0,0 +1,119 @@
1
2/* TODO merge/factor into tools/lib/lk/debugfs.c */
3
4#include "util.h"
5#include "util/fs.h"
6
7static const char * const sysfs__fs_known_mountpoints[] = {
8 "/sys",
9 0,
10};
11
12static const char * const procfs__known_mountpoints[] = {
13 "/proc",
14 0,
15};
16
17struct fs {
18 const char *name;
19 const char * const *mounts;
20 char path[PATH_MAX + 1];
21 bool found;
22 long magic;
23};
24
25enum {
26 FS__SYSFS = 0,
27 FS__PROCFS = 1,
28};
29
30static struct fs fs__entries[] = {
31 [FS__SYSFS] = {
32 .name = "sysfs",
33 .mounts = sysfs__fs_known_mountpoints,
34 .magic = SYSFS_MAGIC,
35 },
36 [FS__PROCFS] = {
37 .name = "proc",
38 .mounts = procfs__known_mountpoints,
39 .magic = PROC_SUPER_MAGIC,
40 },
41};
42
43static bool fs__read_mounts(struct fs *fs)
44{
45 bool found = false;
46 char type[100];
47 FILE *fp;
48
49 fp = fopen("/proc/mounts", "r");
50 if (fp == NULL)
51 return NULL;
52
53 while (!found &&
54 fscanf(fp, "%*s %" STR(PATH_MAX) "s %99s %*s %*d %*d\n",
55 fs->path, type) == 2) {
56
57 if (strcmp(type, fs->name) == 0)
58 found = true;
59 }
60
61 fclose(fp);
62 return fs->found = found;
63}
64
65static int fs__valid_mount(const char *fs, long magic)
66{
67 struct statfs st_fs;
68
69 if (statfs(fs, &st_fs) < 0)
70 return -ENOENT;
71 else if (st_fs.f_type != magic)
72 return -ENOENT;
73
74 return 0;
75}
76
77static bool fs__check_mounts(struct fs *fs)
78{
79 const char * const *ptr;
80
81 ptr = fs->mounts;
82 while (*ptr) {
83 if (fs__valid_mount(*ptr, fs->magic) == 0) {
84 fs->found = true;
85 strcpy(fs->path, *ptr);
86 return true;
87 }
88 ptr++;
89 }
90
91 return false;
92}
93
94static const char *fs__get_mountpoint(struct fs *fs)
95{
96 if (fs__check_mounts(fs))
97 return fs->path;
98
99 return fs__read_mounts(fs) ? fs->path : NULL;
100}
101
102static const char *fs__mountpoint(int idx)
103{
104 struct fs *fs = &fs__entries[idx];
105
106 if (fs->found)
107 return (const char *)fs->path;
108
109 return fs__get_mountpoint(fs);
110}
111
112#define FS__MOUNTPOINT(name, idx) \
113const char *name##__mountpoint(void) \
114{ \
115 return fs__mountpoint(idx); \
116}
117
118FS__MOUNTPOINT(sysfs, FS__SYSFS);
119FS__MOUNTPOINT(procfs, FS__PROCFS);
diff --git a/tools/perf/util/fs.h b/tools/perf/util/fs.h
new file mode 100644
index 000000000000..5e09ce1bab0e
--- /dev/null
+++ b/tools/perf/util/fs.h
@@ -0,0 +1,7 @@
1#ifndef __PERF_FS
2#define __PERF_FS
3
4const char *sysfs__mountpoint(void);
5const char *procfs__mountpoint(void);
6
7#endif /* __PERF_FS */
diff --git a/tools/perf/util/generate-cmdlist.sh b/tools/perf/util/generate-cmdlist.sh
index 3ac38031d534..36a885d2cd22 100755
--- a/tools/perf/util/generate-cmdlist.sh
+++ b/tools/perf/util/generate-cmdlist.sh
@@ -22,7 +22,7 @@ do
22 }' "Documentation/perf-$cmd.txt" 22 }' "Documentation/perf-$cmd.txt"
23done 23done
24 24
25echo "#ifdef LIBELF_SUPPORT" 25echo "#ifdef HAVE_LIBELF_SUPPORT"
26sed -n -e 's/^perf-\([^ ]*\)[ ].* full.*/\1/p' command-list.txt | 26sed -n -e 's/^perf-\([^ ]*\)[ ].* full.*/\1/p' command-list.txt |
27sort | 27sort |
28while read cmd 28while read cmd
@@ -35,5 +35,5 @@ do
35 p 35 p
36 }' "Documentation/perf-$cmd.txt" 36 }' "Documentation/perf-$cmd.txt"
37done 37done
38echo "#endif /* LIBELF_SUPPORT */" 38echo "#endif /* HAVE_LIBELF_SUPPORT */"
39echo "};" 39echo "};"
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index c3e5a3b817ab..26d9520a0c1b 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -22,6 +22,7 @@
22#include "vdso.h" 22#include "vdso.h"
23#include "strbuf.h" 23#include "strbuf.h"
24#include "build-id.h" 24#include "build-id.h"
25#include "data.h"
25 26
26static bool no_buildid_cache = false; 27static bool no_buildid_cache = false;
27 28
@@ -2189,7 +2190,7 @@ int perf_header__fprintf_info(struct perf_session *session, FILE *fp, bool full)
2189{ 2190{
2190 struct header_print_data hd; 2191 struct header_print_data hd;
2191 struct perf_header *header = &session->header; 2192 struct perf_header *header = &session->header;
2192 int fd = session->fd; 2193 int fd = perf_data_file__fd(session->file);
2193 hd.fp = fp; 2194 hd.fp = fp;
2194 hd.full = full; 2195 hd.full = full;
2195 2196
@@ -2650,7 +2651,8 @@ static int perf_header__read_pipe(struct perf_session *session)
2650 struct perf_header *header = &session->header; 2651 struct perf_header *header = &session->header;
2651 struct perf_pipe_file_header f_header; 2652 struct perf_pipe_file_header f_header;
2652 2653
2653 if (perf_file_header__read_pipe(&f_header, header, session->fd, 2654 if (perf_file_header__read_pipe(&f_header, header,
2655 perf_data_file__fd(session->file),
2654 session->repipe) < 0) { 2656 session->repipe) < 0) {
2655 pr_debug("incompatible file format\n"); 2657 pr_debug("incompatible file format\n");
2656 return -EINVAL; 2658 return -EINVAL;
@@ -2751,18 +2753,19 @@ static int perf_evlist__prepare_tracepoint_events(struct perf_evlist *evlist,
2751 2753
2752int perf_session__read_header(struct perf_session *session) 2754int perf_session__read_header(struct perf_session *session)
2753{ 2755{
2756 struct perf_data_file *file = session->file;
2754 struct perf_header *header = &session->header; 2757 struct perf_header *header = &session->header;
2755 struct perf_file_header f_header; 2758 struct perf_file_header f_header;
2756 struct perf_file_attr f_attr; 2759 struct perf_file_attr f_attr;
2757 u64 f_id; 2760 u64 f_id;
2758 int nr_attrs, nr_ids, i, j; 2761 int nr_attrs, nr_ids, i, j;
2759 int fd = session->fd; 2762 int fd = perf_data_file__fd(file);
2760 2763
2761 session->evlist = perf_evlist__new(); 2764 session->evlist = perf_evlist__new();
2762 if (session->evlist == NULL) 2765 if (session->evlist == NULL)
2763 return -ENOMEM; 2766 return -ENOMEM;
2764 2767
2765 if (session->fd_pipe) 2768 if (perf_data_file__is_pipe(file))
2766 return perf_header__read_pipe(session); 2769 return perf_header__read_pipe(session);
2767 2770
2768 if (perf_file_header__read(&f_header, header, fd) < 0) 2771 if (perf_file_header__read(&f_header, header, fd) < 0)
@@ -2777,7 +2780,7 @@ int perf_session__read_header(struct perf_session *session)
2777 if (f_header.data.size == 0) { 2780 if (f_header.data.size == 0) {
2778 pr_warning("WARNING: The %s file's data size field is 0 which is unexpected.\n" 2781 pr_warning("WARNING: The %s file's data size field is 0 which is unexpected.\n"
2779 "Was the 'perf record' command properly terminated?\n", 2782 "Was the 'perf record' command properly terminated?\n",
2780 session->filename); 2783 file->path);
2781 } 2784 }
2782 2785
2783 nr_attrs = f_header.attrs.size / f_header.attr_size; 2786 nr_attrs = f_header.attrs.size / f_header.attr_size;
@@ -2990,18 +2993,19 @@ int perf_event__process_tracing_data(struct perf_tool *tool __maybe_unused,
2990 struct perf_session *session) 2993 struct perf_session *session)
2991{ 2994{
2992 ssize_t size_read, padding, size = event->tracing_data.size; 2995 ssize_t size_read, padding, size = event->tracing_data.size;
2993 off_t offset = lseek(session->fd, 0, SEEK_CUR); 2996 int fd = perf_data_file__fd(session->file);
2997 off_t offset = lseek(fd, 0, SEEK_CUR);
2994 char buf[BUFSIZ]; 2998 char buf[BUFSIZ];
2995 2999
2996 /* setup for reading amidst mmap */ 3000 /* setup for reading amidst mmap */
2997 lseek(session->fd, offset + sizeof(struct tracing_data_event), 3001 lseek(fd, offset + sizeof(struct tracing_data_event),
2998 SEEK_SET); 3002 SEEK_SET);
2999 3003
3000 size_read = trace_report(session->fd, &session->pevent, 3004 size_read = trace_report(fd, &session->pevent,
3001 session->repipe); 3005 session->repipe);
3002 padding = PERF_ALIGN(size_read, sizeof(u64)) - size_read; 3006 padding = PERF_ALIGN(size_read, sizeof(u64)) - size_read;
3003 3007
3004 if (readn(session->fd, buf, padding) < 0) { 3008 if (readn(fd, buf, padding) < 0) {
3005 pr_err("%s: reading input file", __func__); 3009 pr_err("%s: reading input file", __func__);
3006 return -1; 3010 return -1;
3007 } 3011 }
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 9ff6cf3e9a99..822903eaa201 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -160,6 +160,10 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
160 hists__new_col_len(hists, HISTC_MEM_LVL, 21 + 3); 160 hists__new_col_len(hists, HISTC_MEM_LVL, 21 + 3);
161 hists__new_col_len(hists, HISTC_LOCAL_WEIGHT, 12); 161 hists__new_col_len(hists, HISTC_LOCAL_WEIGHT, 12);
162 hists__new_col_len(hists, HISTC_GLOBAL_WEIGHT, 12); 162 hists__new_col_len(hists, HISTC_GLOBAL_WEIGHT, 12);
163
164 if (h->transaction)
165 hists__new_col_len(hists, HISTC_TRANSACTION,
166 hist_entry__transaction_len());
163} 167}
164 168
165void hists__output_recalc_col_len(struct hists *hists, int max_rows) 169void hists__output_recalc_col_len(struct hists *hists, int max_rows)
@@ -346,7 +350,7 @@ static struct hist_entry *add_hist_entry(struct hists *hists,
346 struct rb_node **p; 350 struct rb_node **p;
347 struct rb_node *parent = NULL; 351 struct rb_node *parent = NULL;
348 struct hist_entry *he; 352 struct hist_entry *he;
349 int cmp; 353 int64_t cmp;
350 354
351 p = &hists->entries_in->rb_node; 355 p = &hists->entries_in->rb_node;
352 356
@@ -395,6 +399,7 @@ static struct hist_entry *add_hist_entry(struct hists *hists,
395 if (!he) 399 if (!he)
396 return NULL; 400 return NULL;
397 401
402 hists->nr_entries++;
398 rb_link_node(&he->rb_node_in, parent, p); 403 rb_link_node(&he->rb_node_in, parent, p);
399 rb_insert_color(&he->rb_node_in, hists->entries_in); 404 rb_insert_color(&he->rb_node_in, hists->entries_in);
400out: 405out:
@@ -402,74 +407,16 @@ out:
402 return he; 407 return he;
403} 408}
404 409
405struct hist_entry *__hists__add_mem_entry(struct hists *self, 410struct hist_entry *__hists__add_entry(struct hists *hists,
406 struct addr_location *al,
407 struct symbol *sym_parent,
408 struct mem_info *mi,
409 u64 period,
410 u64 weight)
411{
412 struct hist_entry entry = {
413 .thread = al->thread,
414 .ms = {
415 .map = al->map,
416 .sym = al->sym,
417 },
418 .stat = {
419 .period = period,
420 .weight = weight,
421 .nr_events = 1,
422 },
423 .cpu = al->cpu,
424 .ip = al->addr,
425 .level = al->level,
426 .parent = sym_parent,
427 .filtered = symbol__parent_filter(sym_parent),
428 .hists = self,
429 .mem_info = mi,
430 .branch_info = NULL,
431 };
432 return add_hist_entry(self, &entry, al, period, weight);
433}
434
435struct hist_entry *__hists__add_branch_entry(struct hists *self,
436 struct addr_location *al,
437 struct symbol *sym_parent,
438 struct branch_info *bi,
439 u64 period,
440 u64 weight)
441{
442 struct hist_entry entry = {
443 .thread = al->thread,
444 .ms = {
445 .map = bi->to.map,
446 .sym = bi->to.sym,
447 },
448 .cpu = al->cpu,
449 .ip = bi->to.addr,
450 .level = al->level,
451 .stat = {
452 .period = period,
453 .nr_events = 1,
454 .weight = weight,
455 },
456 .parent = sym_parent,
457 .filtered = symbol__parent_filter(sym_parent),
458 .branch_info = bi,
459 .hists = self,
460 .mem_info = NULL,
461 };
462
463 return add_hist_entry(self, &entry, al, period, weight);
464}
465
466struct hist_entry *__hists__add_entry(struct hists *self,
467 struct addr_location *al, 411 struct addr_location *al,
468 struct symbol *sym_parent, u64 period, 412 struct symbol *sym_parent,
469 u64 weight) 413 struct branch_info *bi,
414 struct mem_info *mi,
415 u64 period, u64 weight, u64 transaction)
470{ 416{
471 struct hist_entry entry = { 417 struct hist_entry entry = {
472 .thread = al->thread, 418 .thread = al->thread,
419 .comm = thread__comm(al->thread),
473 .ms = { 420 .ms = {
474 .map = al->map, 421 .map = al->map,
475 .sym = al->sym, 422 .sym = al->sym,
@@ -478,18 +425,19 @@ struct hist_entry *__hists__add_entry(struct hists *self,
478 .ip = al->addr, 425 .ip = al->addr,
479 .level = al->level, 426 .level = al->level,
480 .stat = { 427 .stat = {
481 .period = period,
482 .nr_events = 1, 428 .nr_events = 1,
429 .period = period,
483 .weight = weight, 430 .weight = weight,
484 }, 431 },
485 .parent = sym_parent, 432 .parent = sym_parent,
486 .filtered = symbol__parent_filter(sym_parent), 433 .filtered = symbol__parent_filter(sym_parent),
487 .hists = self, 434 .hists = hists,
488 .branch_info = NULL, 435 .branch_info = bi,
489 .mem_info = NULL, 436 .mem_info = mi,
437 .transaction = transaction,
490 }; 438 };
491 439
492 return add_hist_entry(self, &entry, al, period, weight); 440 return add_hist_entry(hists, &entry, al, period, weight);
493} 441}
494 442
495int64_t 443int64_t
@@ -530,6 +478,7 @@ void hist_entry__free(struct hist_entry *he)
530{ 478{
531 free(he->branch_info); 479 free(he->branch_info);
532 free(he->mem_info); 480 free(he->mem_info);
481 free_srcline(he->srcline);
533 free(he); 482 free(he);
534} 483}
535 484
@@ -598,7 +547,7 @@ static void hists__apply_filters(struct hists *hists, struct hist_entry *he)
598 hists__filter_entry_by_symbol(hists, he); 547 hists__filter_entry_by_symbol(hists, he);
599} 548}
600 549
601void hists__collapse_resort(struct hists *hists) 550void hists__collapse_resort(struct hists *hists, struct ui_progress *prog)
602{ 551{
603 struct rb_root *root; 552 struct rb_root *root;
604 struct rb_node *next; 553 struct rb_node *next;
@@ -625,6 +574,8 @@ void hists__collapse_resort(struct hists *hists)
625 */ 574 */
626 hists__apply_filters(hists, n); 575 hists__apply_filters(hists, n);
627 } 576 }
577 if (prog)
578 ui_progress__update(prog, 1);
628 } 579 }
629} 580}
630 581
@@ -884,7 +835,7 @@ static struct hist_entry *hists__add_dummy_entry(struct hists *hists,
884 struct rb_node **p; 835 struct rb_node **p;
885 struct rb_node *parent = NULL; 836 struct rb_node *parent = NULL;
886 struct hist_entry *he; 837 struct hist_entry *he;
887 int cmp; 838 int64_t cmp;
888 839
889 if (sort__need_collapse) 840 if (sort__need_collapse)
890 root = &hists->entries_collapsed; 841 root = &hists->entries_collapsed;
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index ce8dc61ce2c3..b621347a1585 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -6,6 +6,7 @@
6#include "callchain.h" 6#include "callchain.h"
7#include "header.h" 7#include "header.h"
8#include "color.h" 8#include "color.h"
9#include "ui/progress.h"
9 10
10extern struct callchain_param callchain_param; 11extern struct callchain_param callchain_param;
11 12
@@ -46,6 +47,8 @@ enum hist_column {
46 HISTC_CPU, 47 HISTC_CPU,
47 HISTC_SRCLINE, 48 HISTC_SRCLINE,
48 HISTC_MISPREDICT, 49 HISTC_MISPREDICT,
50 HISTC_IN_TX,
51 HISTC_ABORT,
49 HISTC_SYMBOL_FROM, 52 HISTC_SYMBOL_FROM,
50 HISTC_SYMBOL_TO, 53 HISTC_SYMBOL_TO,
51 HISTC_DSO_FROM, 54 HISTC_DSO_FROM,
@@ -58,6 +61,7 @@ enum hist_column {
58 HISTC_MEM_TLB, 61 HISTC_MEM_TLB,
59 HISTC_MEM_LVL, 62 HISTC_MEM_LVL,
60 HISTC_MEM_SNOOP, 63 HISTC_MEM_SNOOP,
64 HISTC_TRANSACTION,
61 HISTC_NR_COLS, /* Last entry */ 65 HISTC_NR_COLS, /* Last entry */
62}; 66};
63 67
@@ -80,54 +84,43 @@ struct hists {
80 u16 col_len[HISTC_NR_COLS]; 84 u16 col_len[HISTC_NR_COLS];
81}; 85};
82 86
83struct hist_entry *__hists__add_entry(struct hists *self, 87struct hist_entry *__hists__add_entry(struct hists *hists,
84 struct addr_location *al, 88 struct addr_location *al,
85 struct symbol *parent, u64 period, 89 struct symbol *parent,
86 u64 weight); 90 struct branch_info *bi,
91 struct mem_info *mi, u64 period,
92 u64 weight, u64 transaction);
87int64_t hist_entry__cmp(struct hist_entry *left, struct hist_entry *right); 93int64_t hist_entry__cmp(struct hist_entry *left, struct hist_entry *right);
88int64_t hist_entry__collapse(struct hist_entry *left, struct hist_entry *right); 94int64_t hist_entry__collapse(struct hist_entry *left, struct hist_entry *right);
89int hist_entry__sort_snprintf(struct hist_entry *self, char *bf, size_t size, 95int hist_entry__transaction_len(void);
96int hist_entry__sort_snprintf(struct hist_entry *he, char *bf, size_t size,
90 struct hists *hists); 97 struct hists *hists);
91void hist_entry__free(struct hist_entry *); 98void hist_entry__free(struct hist_entry *);
92 99
93struct hist_entry *__hists__add_branch_entry(struct hists *self, 100void hists__output_resort(struct hists *hists);
94 struct addr_location *al, 101void hists__collapse_resort(struct hists *hists, struct ui_progress *prog);
95 struct symbol *sym_parent,
96 struct branch_info *bi,
97 u64 period,
98 u64 weight);
99
100struct hist_entry *__hists__add_mem_entry(struct hists *self,
101 struct addr_location *al,
102 struct symbol *sym_parent,
103 struct mem_info *mi,
104 u64 period,
105 u64 weight);
106
107void hists__output_resort(struct hists *self);
108void hists__collapse_resort(struct hists *self);
109 102
110void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel); 103void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel);
111void hists__output_recalc_col_len(struct hists *hists, int max_rows); 104void hists__output_recalc_col_len(struct hists *hists, int max_rows);
112 105
113void hists__inc_nr_entries(struct hists *hists, struct hist_entry *h); 106void hists__inc_nr_entries(struct hists *hists, struct hist_entry *h);
114void hists__inc_nr_events(struct hists *self, u32 type); 107void hists__inc_nr_events(struct hists *hists, u32 type);
115void events_stats__inc(struct events_stats *stats, u32 type); 108void events_stats__inc(struct events_stats *stats, u32 type);
116size_t events_stats__fprintf(struct events_stats *stats, FILE *fp); 109size_t events_stats__fprintf(struct events_stats *stats, FILE *fp);
117 110
118size_t hists__fprintf(struct hists *self, bool show_header, int max_rows, 111size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
119 int max_cols, float min_pcnt, FILE *fp); 112 int max_cols, float min_pcnt, FILE *fp);
120 113
121int hist_entry__inc_addr_samples(struct hist_entry *self, int evidx, u64 addr); 114int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 addr);
122int hist_entry__annotate(struct hist_entry *self, size_t privsize); 115int hist_entry__annotate(struct hist_entry *he, size_t privsize);
123 116
124void hists__filter_by_dso(struct hists *hists); 117void hists__filter_by_dso(struct hists *hists);
125void hists__filter_by_thread(struct hists *hists); 118void hists__filter_by_thread(struct hists *hists);
126void hists__filter_by_symbol(struct hists *hists); 119void hists__filter_by_symbol(struct hists *hists);
127 120
128u16 hists__col_len(struct hists *self, enum hist_column col); 121u16 hists__col_len(struct hists *hists, enum hist_column col);
129void hists__set_col_len(struct hists *self, enum hist_column col, u16 len); 122void hists__set_col_len(struct hists *hists, enum hist_column col, u16 len);
130bool hists__new_col_len(struct hists *self, enum hist_column col, u16 len); 123bool hists__new_col_len(struct hists *hists, enum hist_column col, u16 len);
131void hists__reset_col_len(struct hists *hists); 124void hists__reset_col_len(struct hists *hists);
132void hists__calc_col_len(struct hists *hists, struct hist_entry *he); 125void hists__calc_col_len(struct hists *hists, struct hist_entry *he);
133 126
@@ -196,7 +189,7 @@ struct hist_browser_timer {
196 int refresh; 189 int refresh;
197}; 190};
198 191
199#ifdef SLANG_SUPPORT 192#ifdef HAVE_SLANG_SUPPORT
200#include "../ui/keysyms.h" 193#include "../ui/keysyms.h"
201int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel, 194int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel,
202 struct hist_browser_timer *hbt); 195 struct hist_browser_timer *hbt);
@@ -217,12 +210,9 @@ int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused,
217 return 0; 210 return 0;
218} 211}
219 212
220static inline int hist_entry__tui_annotate(struct hist_entry *self 213static inline int hist_entry__tui_annotate(struct hist_entry *he __maybe_unused,
221 __maybe_unused, 214 struct perf_evsel *evsel __maybe_unused,
222 struct perf_evsel *evsel 215 struct hist_browser_timer *hbt __maybe_unused)
223 __maybe_unused,
224 struct hist_browser_timer *hbt
225 __maybe_unused)
226{ 216{
227 return 0; 217 return 0;
228} 218}
@@ -237,20 +227,5 @@ static inline int script_browse(const char *script_opt __maybe_unused)
237#define K_SWITCH_INPUT_DATA -3000 227#define K_SWITCH_INPUT_DATA -3000
238#endif 228#endif
239 229
240#ifdef GTK2_SUPPORT 230unsigned int hists__sort_list_width(struct hists *hists);
241int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, const char *help,
242 struct hist_browser_timer *hbt __maybe_unused,
243 float min_pcnt);
244#else
245static inline
246int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist __maybe_unused,
247 const char *help __maybe_unused,
248 struct hist_browser_timer *hbt __maybe_unused,
249 float min_pcnt __maybe_unused)
250{
251 return 0;
252}
253#endif
254
255unsigned int hists__sort_list_width(struct hists *self);
256#endif /* __PERF_HIST_H */ 231#endif /* __PERF_HIST_H */
diff --git a/tools/perf/util/include/dwarf-regs.h b/tools/perf/util/include/dwarf-regs.h
index cf6727e99c44..8f149655f497 100644
--- a/tools/perf/util/include/dwarf-regs.h
+++ b/tools/perf/util/include/dwarf-regs.h
@@ -1,7 +1,7 @@
1#ifndef _PERF_DWARF_REGS_H_ 1#ifndef _PERF_DWARF_REGS_H_
2#define _PERF_DWARF_REGS_H_ 2#define _PERF_DWARF_REGS_H_
3 3
4#ifdef DWARF_SUPPORT 4#ifdef HAVE_DWARF_SUPPORT
5const char *get_arch_regstr(unsigned int n); 5const char *get_arch_regstr(unsigned int n);
6#endif 6#endif
7 7
diff --git a/tools/perf/util/include/linux/compiler.h b/tools/perf/util/include/linux/compiler.h
index 96b919dae11c..b003ad7200b2 100644
--- a/tools/perf/util/include/linux/compiler.h
+++ b/tools/perf/util/include/linux/compiler.h
@@ -2,20 +2,29 @@
2#define _PERF_LINUX_COMPILER_H_ 2#define _PERF_LINUX_COMPILER_H_
3 3
4#ifndef __always_inline 4#ifndef __always_inline
5#define __always_inline inline 5# define __always_inline inline __attribute__((always_inline))
6#endif 6#endif
7
7#define __user 8#define __user
9
8#ifndef __attribute_const__ 10#ifndef __attribute_const__
9#define __attribute_const__ 11# define __attribute_const__
10#endif 12#endif
11 13
12#ifndef __maybe_unused 14#ifndef __maybe_unused
13#define __maybe_unused __attribute__((unused)) 15# define __maybe_unused __attribute__((unused))
16#endif
17
18#ifndef __packed
19# define __packed __attribute__((__packed__))
14#endif 20#endif
15#define __packed __attribute__((__packed__))
16 21
17#ifndef __force 22#ifndef __force
18#define __force 23# define __force
24#endif
25
26#ifndef __weak
27# define __weak __attribute__((weak))
19#endif 28#endif
20 29
21#endif 30#endif
diff --git a/tools/perf/util/include/linux/magic.h b/tools/perf/util/include/linux/magic.h
index 58b64ed4da12..07d63cf3e0f6 100644
--- a/tools/perf/util/include/linux/magic.h
+++ b/tools/perf/util/include/linux/magic.h
@@ -9,4 +9,8 @@
9#define SYSFS_MAGIC 0x62656572 9#define SYSFS_MAGIC 0x62656572
10#endif 10#endif
11 11
12#ifndef PROC_SUPER_MAGIC
13#define PROC_SUPER_MAGIC 0x9fa0
14#endif
15
12#endif 16#endif
diff --git a/tools/perf/util/intlist.c b/tools/perf/util/intlist.c
index 11a8d86f7fea..89715b64a315 100644
--- a/tools/perf/util/intlist.c
+++ b/tools/perf/util/intlist.c
@@ -20,6 +20,7 @@ static struct rb_node *intlist__node_new(struct rblist *rblist __maybe_unused,
20 20
21 if (node != NULL) { 21 if (node != NULL) {
22 node->i = i; 22 node->i = i;
23 node->priv = NULL;
23 rc = &node->rb_node; 24 rc = &node->rb_node;
24 } 25 }
25 26
@@ -57,22 +58,36 @@ void intlist__remove(struct intlist *ilist, struct int_node *node)
57 rblist__remove_node(&ilist->rblist, &node->rb_node); 58 rblist__remove_node(&ilist->rblist, &node->rb_node);
58} 59}
59 60
60struct int_node *intlist__find(struct intlist *ilist, int i) 61static struct int_node *__intlist__findnew(struct intlist *ilist,
62 int i, bool create)
61{ 63{
62 struct int_node *node; 64 struct int_node *node = NULL;
63 struct rb_node *rb_node; 65 struct rb_node *rb_node;
64 66
65 if (ilist == NULL) 67 if (ilist == NULL)
66 return NULL; 68 return NULL;
67 69
68 node = NULL; 70 if (create)
69 rb_node = rblist__find(&ilist->rblist, (void *)((long)i)); 71 rb_node = rblist__findnew(&ilist->rblist, (void *)((long)i));
72 else
73 rb_node = rblist__find(&ilist->rblist, (void *)((long)i));
74
70 if (rb_node) 75 if (rb_node)
71 node = container_of(rb_node, struct int_node, rb_node); 76 node = container_of(rb_node, struct int_node, rb_node);
72 77
73 return node; 78 return node;
74} 79}
75 80
81struct int_node *intlist__find(struct intlist *ilist, int i)
82{
83 return __intlist__findnew(ilist, i, false);
84}
85
86struct int_node *intlist__findnew(struct intlist *ilist, int i)
87{
88 return __intlist__findnew(ilist, i, true);
89}
90
76static int intlist__parse_list(struct intlist *ilist, const char *s) 91static int intlist__parse_list(struct intlist *ilist, const char *s)
77{ 92{
78 char *sep; 93 char *sep;
diff --git a/tools/perf/util/intlist.h b/tools/perf/util/intlist.h
index 62351dad848f..aa6877d36858 100644
--- a/tools/perf/util/intlist.h
+++ b/tools/perf/util/intlist.h
@@ -9,6 +9,7 @@
9struct int_node { 9struct int_node {
10 struct rb_node rb_node; 10 struct rb_node rb_node;
11 int i; 11 int i;
12 void *priv;
12}; 13};
13 14
14struct intlist { 15struct intlist {
@@ -23,6 +24,7 @@ int intlist__add(struct intlist *ilist, int i);
23 24
24struct int_node *intlist__entry(const struct intlist *ilist, unsigned int idx); 25struct int_node *intlist__entry(const struct intlist *ilist, unsigned int idx);
25struct int_node *intlist__find(struct intlist *ilist, int i); 26struct int_node *intlist__find(struct intlist *ilist, int i);
27struct int_node *intlist__findnew(struct intlist *ilist, int i);
26 28
27static inline bool intlist__has_entry(struct intlist *ilist, int i) 29static inline bool intlist__has_entry(struct intlist *ilist, int i)
28{ 30{
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 6188d2876a71..ce034c183a7e 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -40,12 +40,29 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
40 return -ENOMEM; 40 return -ENOMEM;
41 41
42 snprintf(comm, sizeof(comm), "[guest/%d]", pid); 42 snprintf(comm, sizeof(comm), "[guest/%d]", pid);
43 thread__set_comm(thread, comm); 43 thread__set_comm(thread, comm, 0);
44 } 44 }
45 45
46 return 0; 46 return 0;
47} 47}
48 48
49struct machine *machine__new_host(void)
50{
51 struct machine *machine = malloc(sizeof(*machine));
52
53 if (machine != NULL) {
54 machine__init(machine, "", HOST_KERNEL_ID);
55
56 if (machine__create_kernel_maps(machine) < 0)
57 goto out_delete;
58 }
59
60 return machine;
61out_delete:
62 free(machine);
63 return NULL;
64}
65
49static void dsos__delete(struct list_head *dsos) 66static void dsos__delete(struct list_head *dsos)
50{ 67{
51 struct dso *pos, *n; 68 struct dso *pos, *n;
@@ -314,7 +331,8 @@ struct thread *machine__find_thread(struct machine *machine, pid_t tid)
314 return __machine__findnew_thread(machine, 0, tid, false); 331 return __machine__findnew_thread(machine, 0, tid, false);
315} 332}
316 333
317int machine__process_comm_event(struct machine *machine, union perf_event *event) 334int machine__process_comm_event(struct machine *machine, union perf_event *event,
335 struct perf_sample *sample)
318{ 336{
319 struct thread *thread = machine__findnew_thread(machine, 337 struct thread *thread = machine__findnew_thread(machine,
320 event->comm.pid, 338 event->comm.pid,
@@ -323,7 +341,7 @@ int machine__process_comm_event(struct machine *machine, union perf_event *event
323 if (dump_trace) 341 if (dump_trace)
324 perf_event__fprintf_comm(event, stdout); 342 perf_event__fprintf_comm(event, stdout);
325 343
326 if (thread == NULL || thread__set_comm(thread, event->comm.comm)) { 344 if (thread == NULL || thread__set_comm(thread, event->comm.comm, sample->time)) {
327 dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n"); 345 dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
328 return -1; 346 return -1;
329 } 347 }
@@ -332,7 +350,7 @@ int machine__process_comm_event(struct machine *machine, union perf_event *event
332} 350}
333 351
334int machine__process_lost_event(struct machine *machine __maybe_unused, 352int machine__process_lost_event(struct machine *machine __maybe_unused,
335 union perf_event *event) 353 union perf_event *event, struct perf_sample *sample __maybe_unused)
336{ 354{
337 dump_printf(": id:%" PRIu64 ": lost:%" PRIu64 "\n", 355 dump_printf(": id:%" PRIu64 ": lost:%" PRIu64 "\n",
338 event->lost.id, event->lost.lost); 356 event->lost.id, event->lost.lost);
@@ -776,75 +794,44 @@ static int machine__set_modules_path(struct machine *machine)
776 return map_groups__set_modules_path_dir(&machine->kmaps, modules_path); 794 return map_groups__set_modules_path_dir(&machine->kmaps, modules_path);
777} 795}
778 796
779static int machine__create_modules(struct machine *machine) 797static int machine__create_module(void *arg, const char *name, u64 start)
780{ 798{
781 char *line = NULL; 799 struct machine *machine = arg;
782 size_t n;
783 FILE *file;
784 struct map *map; 800 struct map *map;
801
802 map = machine__new_module(machine, start, name);
803 if (map == NULL)
804 return -1;
805
806 dso__kernel_module_get_build_id(map->dso, machine->root_dir);
807
808 return 0;
809}
810
811static int machine__create_modules(struct machine *machine)
812{
785 const char *modules; 813 const char *modules;
786 char path[PATH_MAX]; 814 char path[PATH_MAX];
787 815
788 if (machine__is_default_guest(machine)) 816 if (machine__is_default_guest(machine)) {
789 modules = symbol_conf.default_guest_modules; 817 modules = symbol_conf.default_guest_modules;
790 else { 818 } else {
791 sprintf(path, "%s/proc/modules", machine->root_dir); 819 snprintf(path, PATH_MAX, "%s/proc/modules", machine->root_dir);
792 modules = path; 820 modules = path;
793 } 821 }
794 822
795 if (symbol__restricted_filename(modules, "/proc/modules")) 823 if (symbol__restricted_filename(modules, "/proc/modules"))
796 return -1; 824 return -1;
797 825
798 file = fopen(modules, "r"); 826 if (modules__parse(modules, machine, machine__create_module))
799 if (file == NULL)
800 return -1; 827 return -1;
801 828
802 while (!feof(file)) { 829 if (!machine__set_modules_path(machine))
803 char name[PATH_MAX]; 830 return 0;
804 u64 start;
805 char *sep;
806 int line_len;
807
808 line_len = getline(&line, &n, file);
809 if (line_len < 0)
810 break;
811
812 if (!line)
813 goto out_failure;
814
815 line[--line_len] = '\0'; /* \n */
816
817 sep = strrchr(line, 'x');
818 if (sep == NULL)
819 continue;
820
821 hex2u64(sep + 1, &start);
822
823 sep = strchr(line, ' ');
824 if (sep == NULL)
825 continue;
826
827 *sep = '\0';
828
829 snprintf(name, sizeof(name), "[%s]", line);
830 map = machine__new_module(machine, start, name);
831 if (map == NULL)
832 goto out_delete_line;
833 dso__kernel_module_get_build_id(map->dso, machine->root_dir);
834 }
835 831
836 free(line); 832 pr_debug("Problems setting modules path maps, continuing anyway...\n");
837 fclose(file);
838 833
839 if (machine__set_modules_path(machine) < 0) {
840 pr_debug("Problems setting modules path maps, continuing anyway...\n");
841 }
842 return 0; 834 return 0;
843
844out_delete_line:
845 free(line);
846out_failure:
847 return -1;
848} 835}
849 836
850int machine__create_kernel_maps(struct machine *machine) 837int machine__create_kernel_maps(struct machine *machine)
@@ -998,7 +985,8 @@ out_problem:
998} 985}
999 986
1000int machine__process_mmap2_event(struct machine *machine, 987int machine__process_mmap2_event(struct machine *machine,
1001 union perf_event *event) 988 union perf_event *event,
989 struct perf_sample *sample __maybe_unused)
1002{ 990{
1003 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 991 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
1004 struct thread *thread; 992 struct thread *thread;
@@ -1045,7 +1033,8 @@ out_problem:
1045 return 0; 1033 return 0;
1046} 1034}
1047 1035
1048int machine__process_mmap_event(struct machine *machine, union perf_event *event) 1036int machine__process_mmap_event(struct machine *machine, union perf_event *event,
1037 struct perf_sample *sample __maybe_unused)
1049{ 1038{
1050 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 1039 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
1051 struct thread *thread; 1040 struct thread *thread;
@@ -1102,7 +1091,8 @@ static void machine__remove_thread(struct machine *machine, struct thread *th)
1102 list_add_tail(&th->node, &machine->dead_threads); 1091 list_add_tail(&th->node, &machine->dead_threads);
1103} 1092}
1104 1093
1105int machine__process_fork_event(struct machine *machine, union perf_event *event) 1094int machine__process_fork_event(struct machine *machine, union perf_event *event,
1095 struct perf_sample *sample)
1106{ 1096{
1107 struct thread *thread = machine__find_thread(machine, event->fork.tid); 1097 struct thread *thread = machine__find_thread(machine, event->fork.tid);
1108 struct thread *parent = machine__findnew_thread(machine, 1098 struct thread *parent = machine__findnew_thread(machine,
@@ -1119,7 +1109,7 @@ int machine__process_fork_event(struct machine *machine, union perf_event *event
1119 perf_event__fprintf_task(event, stdout); 1109 perf_event__fprintf_task(event, stdout);
1120 1110
1121 if (thread == NULL || parent == NULL || 1111 if (thread == NULL || parent == NULL ||
1122 thread__fork(thread, parent) < 0) { 1112 thread__fork(thread, parent, sample->time) < 0) {
1123 dump_printf("problem processing PERF_RECORD_FORK, skipping event.\n"); 1113 dump_printf("problem processing PERF_RECORD_FORK, skipping event.\n");
1124 return -1; 1114 return -1;
1125 } 1115 }
@@ -1127,8 +1117,8 @@ int machine__process_fork_event(struct machine *machine, union perf_event *event
1127 return 0; 1117 return 0;
1128} 1118}
1129 1119
1130int machine__process_exit_event(struct machine *machine __maybe_unused, 1120int machine__process_exit_event(struct machine *machine, union perf_event *event,
1131 union perf_event *event) 1121 struct perf_sample *sample __maybe_unused)
1132{ 1122{
1133 struct thread *thread = machine__find_thread(machine, event->fork.tid); 1123 struct thread *thread = machine__find_thread(machine, event->fork.tid);
1134 1124
@@ -1141,23 +1131,24 @@ int machine__process_exit_event(struct machine *machine __maybe_unused,
1141 return 0; 1131 return 0;
1142} 1132}
1143 1133
1144int machine__process_event(struct machine *machine, union perf_event *event) 1134int machine__process_event(struct machine *machine, union perf_event *event,
1135 struct perf_sample *sample)
1145{ 1136{
1146 int ret; 1137 int ret;
1147 1138
1148 switch (event->header.type) { 1139 switch (event->header.type) {
1149 case PERF_RECORD_COMM: 1140 case PERF_RECORD_COMM:
1150 ret = machine__process_comm_event(machine, event); break; 1141 ret = machine__process_comm_event(machine, event, sample); break;
1151 case PERF_RECORD_MMAP: 1142 case PERF_RECORD_MMAP:
1152 ret = machine__process_mmap_event(machine, event); break; 1143 ret = machine__process_mmap_event(machine, event, sample); break;
1153 case PERF_RECORD_MMAP2: 1144 case PERF_RECORD_MMAP2:
1154 ret = machine__process_mmap2_event(machine, event); break; 1145 ret = machine__process_mmap2_event(machine, event, sample); break;
1155 case PERF_RECORD_FORK: 1146 case PERF_RECORD_FORK:
1156 ret = machine__process_fork_event(machine, event); break; 1147 ret = machine__process_fork_event(machine, event, sample); break;
1157 case PERF_RECORD_EXIT: 1148 case PERF_RECORD_EXIT:
1158 ret = machine__process_exit_event(machine, event); break; 1149 ret = machine__process_exit_event(machine, event, sample); break;
1159 case PERF_RECORD_LOST: 1150 case PERF_RECORD_LOST:
1160 ret = machine__process_lost_event(machine, event); break; 1151 ret = machine__process_lost_event(machine, event, sample); break;
1161 default: 1152 default:
1162 ret = -1; 1153 ret = -1;
1163 break; 1154 break;
@@ -1267,10 +1258,12 @@ static int machine__resolve_callchain_sample(struct machine *machine,
1267 struct thread *thread, 1258 struct thread *thread,
1268 struct ip_callchain *chain, 1259 struct ip_callchain *chain,
1269 struct symbol **parent, 1260 struct symbol **parent,
1270 struct addr_location *root_al) 1261 struct addr_location *root_al,
1262 int max_stack)
1271{ 1263{
1272 u8 cpumode = PERF_RECORD_MISC_USER; 1264 u8 cpumode = PERF_RECORD_MISC_USER;
1273 unsigned int i; 1265 int chain_nr = min(max_stack, (int)chain->nr);
1266 int i;
1274 int err; 1267 int err;
1275 1268
1276 callchain_cursor_reset(&callchain_cursor); 1269 callchain_cursor_reset(&callchain_cursor);
@@ -1280,7 +1273,7 @@ static int machine__resolve_callchain_sample(struct machine *machine,
1280 return 0; 1273 return 0;
1281 } 1274 }
1282 1275
1283 for (i = 0; i < chain->nr; i++) { 1276 for (i = 0; i < chain_nr; i++) {
1284 u64 ip; 1277 u64 ip;
1285 struct addr_location al; 1278 struct addr_location al;
1286 1279
@@ -1352,12 +1345,14 @@ int machine__resolve_callchain(struct machine *machine,
1352 struct thread *thread, 1345 struct thread *thread,
1353 struct perf_sample *sample, 1346 struct perf_sample *sample,
1354 struct symbol **parent, 1347 struct symbol **parent,
1355 struct addr_location *root_al) 1348 struct addr_location *root_al,
1349 int max_stack)
1356{ 1350{
1357 int ret; 1351 int ret;
1358 1352
1359 ret = machine__resolve_callchain_sample(machine, thread, 1353 ret = machine__resolve_callchain_sample(machine, thread,
1360 sample->callchain, parent, root_al); 1354 sample->callchain, parent,
1355 root_al, max_stack);
1361 if (ret) 1356 if (ret)
1362 return ret; 1357 return ret;
1363 1358
@@ -1376,3 +1371,26 @@ int machine__resolve_callchain(struct machine *machine,
1376 sample); 1371 sample);
1377 1372
1378} 1373}
1374
1375int machine__for_each_thread(struct machine *machine,
1376 int (*fn)(struct thread *thread, void *p),
1377 void *priv)
1378{
1379 struct rb_node *nd;
1380 struct thread *thread;
1381 int rc = 0;
1382
1383 for (nd = rb_first(&machine->threads); nd; nd = rb_next(nd)) {
1384 thread = rb_entry(nd, struct thread, rb_node);
1385 rc = fn(thread, priv);
1386 if (rc != 0)
1387 return rc;
1388 }
1389
1390 list_for_each_entry(thread, &machine->dead_threads, node) {
1391 rc = fn(thread, priv);
1392 if (rc != 0)
1393 return rc;
1394 }
1395 return rc;
1396}
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index 58a6be1fc739..2389ba81fafe 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -40,13 +40,20 @@ struct map *machine__kernel_map(struct machine *machine, enum map_type type)
40 40
41struct thread *machine__find_thread(struct machine *machine, pid_t tid); 41struct thread *machine__find_thread(struct machine *machine, pid_t tid);
42 42
43int machine__process_comm_event(struct machine *machine, union perf_event *event); 43int machine__process_comm_event(struct machine *machine, union perf_event *event,
44int machine__process_exit_event(struct machine *machine, union perf_event *event); 44 struct perf_sample *sample);
45int machine__process_fork_event(struct machine *machine, union perf_event *event); 45int machine__process_exit_event(struct machine *machine, union perf_event *event,
46int machine__process_lost_event(struct machine *machine, union perf_event *event); 46 struct perf_sample *sample);
47int machine__process_mmap_event(struct machine *machine, union perf_event *event); 47int machine__process_fork_event(struct machine *machine, union perf_event *event,
48int machine__process_mmap2_event(struct machine *machine, union perf_event *event); 48 struct perf_sample *sample);
49int machine__process_event(struct machine *machine, union perf_event *event); 49int machine__process_lost_event(struct machine *machine, union perf_event *event,
50 struct perf_sample *sample);
51int machine__process_mmap_event(struct machine *machine, union perf_event *event,
52 struct perf_sample *sample);
53int machine__process_mmap2_event(struct machine *machine, union perf_event *event,
54 struct perf_sample *sample);
55int machine__process_event(struct machine *machine, union perf_event *event,
56 struct perf_sample *sample);
50 57
51typedef void (*machine__process_t)(struct machine *machine, void *data); 58typedef void (*machine__process_t)(struct machine *machine, void *data);
52 59
@@ -74,6 +81,7 @@ char *machine__mmap_name(struct machine *machine, char *bf, size_t size);
74void machines__set_symbol_filter(struct machines *machines, 81void machines__set_symbol_filter(struct machines *machines,
75 symbol_filter_t symbol_filter); 82 symbol_filter_t symbol_filter);
76 83
84struct machine *machine__new_host(void);
77int machine__init(struct machine *machine, const char *root_dir, pid_t pid); 85int machine__init(struct machine *machine, const char *root_dir, pid_t pid);
78void machine__exit(struct machine *machine); 86void machine__exit(struct machine *machine);
79void machine__delete_dead_threads(struct machine *machine); 87void machine__delete_dead_threads(struct machine *machine);
@@ -91,7 +99,8 @@ int machine__resolve_callchain(struct machine *machine,
91 struct thread *thread, 99 struct thread *thread,
92 struct perf_sample *sample, 100 struct perf_sample *sample,
93 struct symbol **parent, 101 struct symbol **parent,
94 struct addr_location *root_al); 102 struct addr_location *root_al,
103 int max_stack);
95 104
96/* 105/*
97 * Default guest kernel is defined by parameter --guestkallsyms 106 * Default guest kernel is defined by parameter --guestkallsyms
@@ -165,4 +174,8 @@ void machines__destroy_kernel_maps(struct machines *machines);
165 174
166size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp); 175size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp);
167 176
177int machine__for_each_thread(struct machine *machine,
178 int (*fn)(struct thread *thread, void *p),
179 void *priv);
180
168#endif /* __PERF_MACHINE_H */ 181#endif /* __PERF_MACHINE_H */
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 4f6680d2043b..ef5bc913ca7a 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -172,7 +172,7 @@ int map__load(struct map *map, symbol_filter_t filter)
172 pr_warning(", continuing without symbols\n"); 172 pr_warning(", continuing without symbols\n");
173 return -1; 173 return -1;
174 } else if (nr == 0) { 174 } else if (nr == 0) {
175#ifdef LIBELF_SUPPORT 175#ifdef HAVE_LIBELF_SUPPORT
176 const size_t len = strlen(name); 176 const size_t len = strlen(name);
177 const size_t real_len = len - sizeof(DSO__DELETED); 177 const size_t real_len = len - sizeof(DSO__DELETED);
178 178
@@ -252,10 +252,16 @@ size_t map__fprintf_dsoname(struct map *map, FILE *fp)
252 return fprintf(fp, "%s", dsoname); 252 return fprintf(fp, "%s", dsoname);
253} 253}
254 254
255/* 255/**
256 * map__rip_2objdump - convert symbol start address to objdump address.
257 * @map: memory map
258 * @rip: symbol start address
259 *
256 * objdump wants/reports absolute IPs for ET_EXEC, and RIPs for ET_DYN. 260 * objdump wants/reports absolute IPs for ET_EXEC, and RIPs for ET_DYN.
257 * map->dso->adjust_symbols==1 for ET_EXEC-like cases except ET_REL which is 261 * map->dso->adjust_symbols==1 for ET_EXEC-like cases except ET_REL which is
258 * relative to section start. 262 * relative to section start.
263 *
264 * Return: Address suitable for passing to "objdump --start-address="
259 */ 265 */
260u64 map__rip_2objdump(struct map *map, u64 rip) 266u64 map__rip_2objdump(struct map *map, u64 rip)
261{ 267{
@@ -268,6 +274,29 @@ u64 map__rip_2objdump(struct map *map, u64 rip)
268 return map->unmap_ip(map, rip); 274 return map->unmap_ip(map, rip);
269} 275}
270 276
277/**
278 * map__objdump_2mem - convert objdump address to a memory address.
279 * @map: memory map
280 * @ip: objdump address
281 *
282 * Closely related to map__rip_2objdump(), this function takes an address from
283 * objdump and converts it to a memory address. Note this assumes that @map
284 * contains the address. To be sure the result is valid, check it forwards
285 * e.g. map__rip_2objdump(map->map_ip(map, map__objdump_2mem(map, ip))) == ip
286 *
287 * Return: Memory address.
288 */
289u64 map__objdump_2mem(struct map *map, u64 ip)
290{
291 if (!map->dso->adjust_symbols)
292 return map->unmap_ip(map, ip);
293
294 if (map->dso->rel)
295 return map->unmap_ip(map, ip + map->pgoff);
296
297 return ip;
298}
299
271void map_groups__init(struct map_groups *mg) 300void map_groups__init(struct map_groups *mg)
272{ 301{
273 int i; 302 int i;
@@ -371,6 +400,23 @@ struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg,
371 return NULL; 400 return NULL;
372} 401}
373 402
403int map_groups__find_ams(struct addr_map_symbol *ams, symbol_filter_t filter)
404{
405 if (ams->addr < ams->map->start || ams->addr > ams->map->end) {
406 if (ams->map->groups == NULL)
407 return -1;
408 ams->map = map_groups__find(ams->map->groups, ams->map->type,
409 ams->addr);
410 if (ams->map == NULL)
411 return -1;
412 }
413
414 ams->al_addr = ams->map->map_ip(ams->map, ams->addr);
415 ams->sym = map__find_symbol(ams->map, ams->al_addr, filter);
416
417 return ams->sym ? 0 : -1;
418}
419
374size_t __map_groups__fprintf_maps(struct map_groups *mg, 420size_t __map_groups__fprintf_maps(struct map_groups *mg,
375 enum map_type type, int verbose, FILE *fp) 421 enum map_type type, int verbose, FILE *fp)
376{ 422{
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index 4886ca280536..e4e259c3ba16 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -84,6 +84,9 @@ static inline u64 identity__map_ip(struct map *map __maybe_unused, u64 ip)
84/* rip/ip <-> addr suitable for passing to `objdump --start-address=` */ 84/* rip/ip <-> addr suitable for passing to `objdump --start-address=` */
85u64 map__rip_2objdump(struct map *map, u64 rip); 85u64 map__rip_2objdump(struct map *map, u64 rip);
86 86
87/* objdump address -> memory address */
88u64 map__objdump_2mem(struct map *map, u64 ip);
89
87struct symbol; 90struct symbol;
88 91
89typedef int (*symbol_filter_t)(struct map *map, struct symbol *sym); 92typedef int (*symbol_filter_t)(struct map *map, struct symbol *sym);
@@ -167,6 +170,10 @@ struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg,
167 struct map **mapp, 170 struct map **mapp,
168 symbol_filter_t filter); 171 symbol_filter_t filter);
169 172
173struct addr_map_symbol;
174
175int map_groups__find_ams(struct addr_map_symbol *ams, symbol_filter_t filter);
176
170static inline 177static inline
171struct symbol *map_groups__find_function_by_name(struct map_groups *mg, 178struct symbol *map_groups__find_function_by_name(struct map_groups *mg,
172 const char *name, struct map **mapp, 179 const char *name, struct map **mapp,
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 98125319b158..c90e55cf7e82 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -998,8 +998,10 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
998 char evt_path[MAXPATHLEN]; 998 char evt_path[MAXPATHLEN];
999 char dir_path[MAXPATHLEN]; 999 char dir_path[MAXPATHLEN];
1000 1000
1001 if (debugfs_valid_mountpoint(tracing_events_path)) 1001 if (debugfs_valid_mountpoint(tracing_events_path)) {
1002 printf(" [ Tracepoints not available: %s ]\n", strerror(errno));
1002 return; 1003 return;
1004 }
1003 1005
1004 sys_dir = opendir(tracing_events_path); 1006 sys_dir = opendir(tracing_events_path);
1005 if (!sys_dir) 1007 if (!sys_dir)
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 91346b753960..343299575b30 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -126,6 +126,37 @@ modifier_bp [rwx]{1,3}
126 126
127} 127}
128 128
129<config>{
130config { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG); }
131config1 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG1); }
132config2 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG2); }
133name { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NAME); }
134period { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); }
135branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); }
136, { return ','; }
137"/" { BEGIN(INITIAL); return '/'; }
138{name_minus} { return str(yyscanner, PE_NAME); }
139}
140
141<mem>{
142{modifier_bp} { return str(yyscanner, PE_MODIFIER_BP); }
143: { return ':'; }
144{num_dec} { return value(yyscanner, 10); }
145{num_hex} { return value(yyscanner, 16); }
146 /*
147 * We need to separate 'mem:' scanner part, in order to get specific
148 * modifier bits parsed out. Otherwise we would need to handle PE_NAME
149 * and we'd need to parse it manually. During the escape from <mem>
150 * state we need to put the escaping char back, so we dont miss it.
151 */
152. { unput(*yytext); BEGIN(INITIAL); }
153 /*
154 * We destroy the scanner after reaching EOF,
155 * but anyway just to be sure get back to INIT state.
156 */
157<<EOF>> { BEGIN(INITIAL); }
158}
159
129cpu-cycles|cycles { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES); } 160cpu-cycles|cycles { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES); }
130stalled-cycles-frontend|idle-cycles-frontend { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); } 161stalled-cycles-frontend|idle-cycles-frontend { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); }
131stalled-cycles-backend|idle-cycles-backend { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); } 162stalled-cycles-backend|idle-cycles-backend { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); }
@@ -162,18 +193,6 @@ speculative-read|speculative-load |
162refs|Reference|ops|access | 193refs|Reference|ops|access |
163misses|miss { return str(yyscanner, PE_NAME_CACHE_OP_RESULT); } 194misses|miss { return str(yyscanner, PE_NAME_CACHE_OP_RESULT); }
164 195
165<config>{
166config { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG); }
167config1 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG1); }
168config2 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG2); }
169name { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NAME); }
170period { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); }
171branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); }
172, { return ','; }
173"/" { BEGIN(INITIAL); return '/'; }
174{name_minus} { return str(yyscanner, PE_NAME); }
175}
176
177mem: { BEGIN(mem); return PE_PREFIX_MEM; } 196mem: { BEGIN(mem); return PE_PREFIX_MEM; }
178r{num_raw_hex} { return raw(yyscanner); } 197r{num_raw_hex} { return raw(yyscanner); }
179{num_dec} { return value(yyscanner, 10); } 198{num_dec} { return value(yyscanner, 10); }
@@ -189,25 +208,7 @@ r{num_raw_hex} { return raw(yyscanner); }
189"}" { return '}'; } 208"}" { return '}'; }
190= { return '='; } 209= { return '='; }
191\n { } 210\n { }
192 211. { }
193<mem>{
194{modifier_bp} { return str(yyscanner, PE_MODIFIER_BP); }
195: { return ':'; }
196{num_dec} { return value(yyscanner, 10); }
197{num_hex} { return value(yyscanner, 16); }
198 /*
199 * We need to separate 'mem:' scanner part, in order to get specific
200 * modifier bits parsed out. Otherwise we would need to handle PE_NAME
201 * and we'd need to parse it manually. During the escape from <mem>
202 * state we need to put the escaping char back, so we dont miss it.
203 */
204. { unput(*yytext); BEGIN(INITIAL); }
205 /*
206 * We destroy the scanner after reaching EOF,
207 * but anyway just to be sure get back to INIT state.
208 */
209<<EOF>> { BEGIN(INITIAL); }
210}
211 212
212%% 213%%
213 214
diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c
index 2bc9e70df7e2..31f404a032a9 100644
--- a/tools/perf/util/parse-options.c
+++ b/tools/perf/util/parse-options.c
@@ -339,10 +339,10 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
339 if (arg[1] != '-') { 339 if (arg[1] != '-') {
340 ctx->opt = arg + 1; 340 ctx->opt = arg + 1;
341 if (internal_help && *ctx->opt == 'h') 341 if (internal_help && *ctx->opt == 'h')
342 return parse_options_usage(usagestr, options); 342 return usage_with_options_internal(usagestr, options, 0);
343 switch (parse_short_opt(ctx, options)) { 343 switch (parse_short_opt(ctx, options)) {
344 case -1: 344 case -1:
345 return parse_options_usage(usagestr, options); 345 return parse_options_usage(usagestr, options, arg + 1, 1);
346 case -2: 346 case -2:
347 goto unknown; 347 goto unknown;
348 default: 348 default:
@@ -352,10 +352,11 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
352 check_typos(arg + 1, options); 352 check_typos(arg + 1, options);
353 while (ctx->opt) { 353 while (ctx->opt) {
354 if (internal_help && *ctx->opt == 'h') 354 if (internal_help && *ctx->opt == 'h')
355 return parse_options_usage(usagestr, options); 355 return usage_with_options_internal(usagestr, options, 0);
356 arg = ctx->opt;
356 switch (parse_short_opt(ctx, options)) { 357 switch (parse_short_opt(ctx, options)) {
357 case -1: 358 case -1:
358 return parse_options_usage(usagestr, options); 359 return parse_options_usage(usagestr, options, arg, 1);
359 case -2: 360 case -2:
360 /* fake a short option thing to hide the fact that we may have 361 /* fake a short option thing to hide the fact that we may have
361 * started to parse aggregated stuff 362 * started to parse aggregated stuff
@@ -383,12 +384,12 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
383 if (internal_help && !strcmp(arg + 2, "help-all")) 384 if (internal_help && !strcmp(arg + 2, "help-all"))
384 return usage_with_options_internal(usagestr, options, 1); 385 return usage_with_options_internal(usagestr, options, 1);
385 if (internal_help && !strcmp(arg + 2, "help")) 386 if (internal_help && !strcmp(arg + 2, "help"))
386 return parse_options_usage(usagestr, options); 387 return usage_with_options_internal(usagestr, options, 0);
387 if (!strcmp(arg + 2, "list-opts")) 388 if (!strcmp(arg + 2, "list-opts"))
388 return PARSE_OPT_LIST; 389 return PARSE_OPT_LIST;
389 switch (parse_long_opt(ctx, arg + 2, options)) { 390 switch (parse_long_opt(ctx, arg + 2, options)) {
390 case -1: 391 case -1:
391 return parse_options_usage(usagestr, options); 392 return parse_options_usage(usagestr, options, arg + 2, 0);
392 case -2: 393 case -2:
393 goto unknown; 394 goto unknown;
394 default: 395 default:
@@ -445,6 +446,89 @@ int parse_options(int argc, const char **argv, const struct option *options,
445#define USAGE_OPTS_WIDTH 24 446#define USAGE_OPTS_WIDTH 24
446#define USAGE_GAP 2 447#define USAGE_GAP 2
447 448
449static void print_option_help(const struct option *opts, int full)
450{
451 size_t pos;
452 int pad;
453
454 if (opts->type == OPTION_GROUP) {
455 fputc('\n', stderr);
456 if (*opts->help)
457 fprintf(stderr, "%s\n", opts->help);
458 return;
459 }
460 if (!full && (opts->flags & PARSE_OPT_HIDDEN))
461 return;
462
463 pos = fprintf(stderr, " ");
464 if (opts->short_name)
465 pos += fprintf(stderr, "-%c", opts->short_name);
466 else
467 pos += fprintf(stderr, " ");
468
469 if (opts->long_name && opts->short_name)
470 pos += fprintf(stderr, ", ");
471 if (opts->long_name)
472 pos += fprintf(stderr, "--%s", opts->long_name);
473
474 switch (opts->type) {
475 case OPTION_ARGUMENT:
476 break;
477 case OPTION_LONG:
478 case OPTION_U64:
479 case OPTION_INTEGER:
480 case OPTION_UINTEGER:
481 if (opts->flags & PARSE_OPT_OPTARG)
482 if (opts->long_name)
483 pos += fprintf(stderr, "[=<n>]");
484 else
485 pos += fprintf(stderr, "[<n>]");
486 else
487 pos += fprintf(stderr, " <n>");
488 break;
489 case OPTION_CALLBACK:
490 if (opts->flags & PARSE_OPT_NOARG)
491 break;
492 /* FALLTHROUGH */
493 case OPTION_STRING:
494 if (opts->argh) {
495 if (opts->flags & PARSE_OPT_OPTARG)
496 if (opts->long_name)
497 pos += fprintf(stderr, "[=<%s>]", opts->argh);
498 else
499 pos += fprintf(stderr, "[<%s>]", opts->argh);
500 else
501 pos += fprintf(stderr, " <%s>", opts->argh);
502 } else {
503 if (opts->flags & PARSE_OPT_OPTARG)
504 if (opts->long_name)
505 pos += fprintf(stderr, "[=...]");
506 else
507 pos += fprintf(stderr, "[...]");
508 else
509 pos += fprintf(stderr, " ...");
510 }
511 break;
512 default: /* OPTION_{BIT,BOOLEAN,SET_UINT,SET_PTR} */
513 case OPTION_END:
514 case OPTION_GROUP:
515 case OPTION_BIT:
516 case OPTION_BOOLEAN:
517 case OPTION_INCR:
518 case OPTION_SET_UINT:
519 case OPTION_SET_PTR:
520 break;
521 }
522
523 if (pos <= USAGE_OPTS_WIDTH)
524 pad = USAGE_OPTS_WIDTH - pos;
525 else {
526 fputc('\n', stderr);
527 pad = USAGE_OPTS_WIDTH;
528 }
529 fprintf(stderr, "%*s%s\n", pad + USAGE_GAP, "", opts->help);
530}
531
448int usage_with_options_internal(const char * const *usagestr, 532int usage_with_options_internal(const char * const *usagestr,
449 const struct option *opts, int full) 533 const struct option *opts, int full)
450{ 534{
@@ -464,87 +548,9 @@ int usage_with_options_internal(const char * const *usagestr,
464 if (opts->type != OPTION_GROUP) 548 if (opts->type != OPTION_GROUP)
465 fputc('\n', stderr); 549 fputc('\n', stderr);
466 550
467 for (; opts->type != OPTION_END; opts++) { 551 for ( ; opts->type != OPTION_END; opts++)
468 size_t pos; 552 print_option_help(opts, full);
469 int pad;
470
471 if (opts->type == OPTION_GROUP) {
472 fputc('\n', stderr);
473 if (*opts->help)
474 fprintf(stderr, "%s\n", opts->help);
475 continue;
476 }
477 if (!full && (opts->flags & PARSE_OPT_HIDDEN))
478 continue;
479
480 pos = fprintf(stderr, " ");
481 if (opts->short_name)
482 pos += fprintf(stderr, "-%c", opts->short_name);
483 else
484 pos += fprintf(stderr, " ");
485
486 if (opts->long_name && opts->short_name)
487 pos += fprintf(stderr, ", ");
488 if (opts->long_name)
489 pos += fprintf(stderr, "--%s", opts->long_name);
490
491 switch (opts->type) {
492 case OPTION_ARGUMENT:
493 break;
494 case OPTION_LONG:
495 case OPTION_U64:
496 case OPTION_INTEGER:
497 case OPTION_UINTEGER:
498 if (opts->flags & PARSE_OPT_OPTARG)
499 if (opts->long_name)
500 pos += fprintf(stderr, "[=<n>]");
501 else
502 pos += fprintf(stderr, "[<n>]");
503 else
504 pos += fprintf(stderr, " <n>");
505 break;
506 case OPTION_CALLBACK:
507 if (opts->flags & PARSE_OPT_NOARG)
508 break;
509 /* FALLTHROUGH */
510 case OPTION_STRING:
511 if (opts->argh) {
512 if (opts->flags & PARSE_OPT_OPTARG)
513 if (opts->long_name)
514 pos += fprintf(stderr, "[=<%s>]", opts->argh);
515 else
516 pos += fprintf(stderr, "[<%s>]", opts->argh);
517 else
518 pos += fprintf(stderr, " <%s>", opts->argh);
519 } else {
520 if (opts->flags & PARSE_OPT_OPTARG)
521 if (opts->long_name)
522 pos += fprintf(stderr, "[=...]");
523 else
524 pos += fprintf(stderr, "[...]");
525 else
526 pos += fprintf(stderr, " ...");
527 }
528 break;
529 default: /* OPTION_{BIT,BOOLEAN,SET_UINT,SET_PTR} */
530 case OPTION_END:
531 case OPTION_GROUP:
532 case OPTION_BIT:
533 case OPTION_BOOLEAN:
534 case OPTION_INCR:
535 case OPTION_SET_UINT:
536 case OPTION_SET_PTR:
537 break;
538 }
539 553
540 if (pos <= USAGE_OPTS_WIDTH)
541 pad = USAGE_OPTS_WIDTH - pos;
542 else {
543 fputc('\n', stderr);
544 pad = USAGE_OPTS_WIDTH;
545 }
546 fprintf(stderr, "%*s%s\n", pad + USAGE_GAP, "", opts->help);
547 }
548 fputc('\n', stderr); 554 fputc('\n', stderr);
549 555
550 return PARSE_OPT_HELP; 556 return PARSE_OPT_HELP;
@@ -559,9 +565,45 @@ void usage_with_options(const char * const *usagestr,
559} 565}
560 566
561int parse_options_usage(const char * const *usagestr, 567int parse_options_usage(const char * const *usagestr,
562 const struct option *opts) 568 const struct option *opts,
569 const char *optstr, bool short_opt)
563{ 570{
564 return usage_with_options_internal(usagestr, opts, 0); 571 if (!usagestr)
572 goto opt;
573
574 fprintf(stderr, "\n usage: %s\n", *usagestr++);
575 while (*usagestr && **usagestr)
576 fprintf(stderr, " or: %s\n", *usagestr++);
577 while (*usagestr) {
578 fprintf(stderr, "%s%s\n",
579 **usagestr ? " " : "",
580 *usagestr);
581 usagestr++;
582 }
583 fputc('\n', stderr);
584
585opt:
586 for ( ; opts->type != OPTION_END; opts++) {
587 if (short_opt) {
588 if (opts->short_name == *optstr)
589 break;
590 continue;
591 }
592
593 if (opts->long_name == NULL)
594 continue;
595
596 if (!prefixcmp(optstr, opts->long_name))
597 break;
598 if (!prefixcmp(optstr, "no-") &&
599 !prefixcmp(optstr + 3, opts->long_name))
600 break;
601 }
602
603 if (opts->type != OPTION_END)
604 print_option_help(opts, 0);
605
606 return PARSE_OPT_HELP;
565} 607}
566 608
567 609
diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h
index 7bb5999940ca..b0241e28eaf7 100644
--- a/tools/perf/util/parse-options.h
+++ b/tools/perf/util/parse-options.h
@@ -158,7 +158,9 @@ struct parse_opt_ctx_t {
158}; 158};
159 159
160extern int parse_options_usage(const char * const *usagestr, 160extern int parse_options_usage(const char * const *usagestr,
161 const struct option *opts); 161 const struct option *opts,
162 const char *optstr,
163 bool short_opt);
162 164
163extern void parse_options_start(struct parse_opt_ctx_t *ctx, 165extern void parse_options_start(struct parse_opt_ctx_t *ctx,
164 int argc, const char **argv, int flags); 166 int argc, const char **argv, int flags);
diff --git a/tools/perf/util/path.c b/tools/perf/util/path.c
index a8c49548ca48..5d13cb45b317 100644
--- a/tools/perf/util/path.c
+++ b/tools/perf/util/path.c
@@ -22,19 +22,23 @@ static const char *get_perf_dir(void)
22 return "."; 22 return ".";
23} 23}
24 24
25#ifndef HAVE_STRLCPY 25/*
26size_t strlcpy(char *dest, const char *src, size_t size) 26 * If libc has strlcpy() then that version will override this
27 * implementation:
28 */
29size_t __weak strlcpy(char *dest, const char *src, size_t size)
27{ 30{
28 size_t ret = strlen(src); 31 size_t ret = strlen(src);
29 32
30 if (size) { 33 if (size) {
31 size_t len = (ret >= size) ? size - 1 : ret; 34 size_t len = (ret >= size) ? size - 1 : ret;
35
32 memcpy(dest, src, len); 36 memcpy(dest, src, len);
33 dest[len] = '\0'; 37 dest[len] = '\0';
34 } 38 }
39
35 return ret; 40 return ret;
36} 41}
37#endif
38 42
39static char *get_pathname(void) 43static char *get_pathname(void)
40{ 44{
diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h
index 5a4f2b6f3738..a3d42cd74919 100644
--- a/tools/perf/util/perf_regs.h
+++ b/tools/perf/util/perf_regs.h
@@ -1,7 +1,7 @@
1#ifndef __PERF_REGS_H 1#ifndef __PERF_REGS_H
2#define __PERF_REGS_H 2#define __PERF_REGS_H
3 3
4#ifdef HAVE_PERF_REGS 4#ifdef HAVE_PERF_REGS_SUPPORT
5#include <perf_regs.h> 5#include <perf_regs.h>
6#else 6#else
7#define PERF_REGS_MASK 0 7#define PERF_REGS_MASK 0
@@ -10,5 +10,5 @@ static inline const char *perf_reg_name(int id __maybe_unused)
10{ 10{
11 return NULL; 11 return NULL;
12} 12}
13#endif /* HAVE_PERF_REGS */ 13#endif /* HAVE_PERF_REGS_SUPPORT */
14#endif /* __PERF_REGS_H */ 14#endif /* __PERF_REGS_H */
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index bc9d8069d376..c232d8dd410b 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -4,7 +4,7 @@
4#include <unistd.h> 4#include <unistd.h>
5#include <stdio.h> 5#include <stdio.h>
6#include <dirent.h> 6#include <dirent.h>
7#include "sysfs.h" 7#include "fs.h"
8#include "util.h" 8#include "util.h"
9#include "pmu.h" 9#include "pmu.h"
10#include "parse-events.h" 10#include "parse-events.h"
@@ -77,9 +77,8 @@ static int pmu_format(const char *name, struct list_head *format)
77{ 77{
78 struct stat st; 78 struct stat st;
79 char path[PATH_MAX]; 79 char path[PATH_MAX];
80 const char *sysfs; 80 const char *sysfs = sysfs__mountpoint();
81 81
82 sysfs = sysfs_find_mountpoint();
83 if (!sysfs) 82 if (!sysfs)
84 return -1; 83 return -1;
85 84
@@ -166,9 +165,8 @@ static int pmu_aliases(const char *name, struct list_head *head)
166{ 165{
167 struct stat st; 166 struct stat st;
168 char path[PATH_MAX]; 167 char path[PATH_MAX];
169 const char *sysfs; 168 const char *sysfs = sysfs__mountpoint();
170 169
171 sysfs = sysfs_find_mountpoint();
172 if (!sysfs) 170 if (!sysfs)
173 return -1; 171 return -1;
174 172
@@ -212,11 +210,10 @@ static int pmu_type(const char *name, __u32 *type)
212{ 210{
213 struct stat st; 211 struct stat st;
214 char path[PATH_MAX]; 212 char path[PATH_MAX];
215 const char *sysfs;
216 FILE *file; 213 FILE *file;
217 int ret = 0; 214 int ret = 0;
215 const char *sysfs = sysfs__mountpoint();
218 216
219 sysfs = sysfs_find_mountpoint();
220 if (!sysfs) 217 if (!sysfs)
221 return -1; 218 return -1;
222 219
@@ -241,11 +238,10 @@ static int pmu_type(const char *name, __u32 *type)
241static void pmu_read_sysfs(void) 238static void pmu_read_sysfs(void)
242{ 239{
243 char path[PATH_MAX]; 240 char path[PATH_MAX];
244 const char *sysfs;
245 DIR *dir; 241 DIR *dir;
246 struct dirent *dent; 242 struct dirent *dent;
243 const char *sysfs = sysfs__mountpoint();
247 244
248 sysfs = sysfs_find_mountpoint();
249 if (!sysfs) 245 if (!sysfs)
250 return; 246 return;
251 247
@@ -270,11 +266,10 @@ static struct cpu_map *pmu_cpumask(const char *name)
270{ 266{
271 struct stat st; 267 struct stat st;
272 char path[PATH_MAX]; 268 char path[PATH_MAX];
273 const char *sysfs;
274 FILE *file; 269 FILE *file;
275 struct cpu_map *cpus; 270 struct cpu_map *cpus;
271 const char *sysfs = sysfs__mountpoint();
276 272
277 sysfs = sysfs_find_mountpoint();
278 if (!sysfs) 273 if (!sysfs)
279 return NULL; 274 return NULL;
280 275
@@ -637,3 +632,19 @@ void print_pmu_events(const char *event_glob, bool name_only)
637 printf("\n"); 632 printf("\n");
638 free(aliases); 633 free(aliases);
639} 634}
635
636bool pmu_have_event(const char *pname, const char *name)
637{
638 struct perf_pmu *pmu;
639 struct perf_pmu_alias *alias;
640
641 pmu = NULL;
642 while ((pmu = perf_pmu__scan(pmu)) != NULL) {
643 if (strcmp(pname, pmu->name))
644 continue;
645 list_for_each_entry(alias, &pmu->aliases, list)
646 if (!strcmp(alias->name, name))
647 return true;
648 }
649 return false;
650}
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index 6b2cbe2d4cc3..1179b26f244a 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -42,6 +42,7 @@ int perf_pmu__format_parse(char *dir, struct list_head *head);
42struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu); 42struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu);
43 43
44void print_pmu_events(const char *event_glob, bool name_only); 44void print_pmu_events(const char *event_glob, bool name_only);
45bool pmu_have_event(const char *pname, const char *name);
45 46
46int perf_pmu__test(void); 47int perf_pmu__test(void);
47#endif /* __PMU_H */ 48#endif /* __PMU_H */
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index aa04bf9c9ad7..9c6989ca2bea 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -47,7 +47,6 @@
47#include "session.h" 47#include "session.h"
48 48
49#define MAX_CMDLEN 256 49#define MAX_CMDLEN 256
50#define MAX_PROBE_ARGS 128
51#define PERFPROBE_GROUP "probe" 50#define PERFPROBE_GROUP "probe"
52 51
53bool probe_event_dry_run; /* Dry run flag */ 52bool probe_event_dry_run; /* Dry run flag */
@@ -201,7 +200,7 @@ static int convert_to_perf_probe_point(struct probe_trace_point *tp,
201 return 0; 200 return 0;
202} 201}
203 202
204#ifdef DWARF_SUPPORT 203#ifdef HAVE_DWARF_SUPPORT
205/* Open new debuginfo of given module */ 204/* Open new debuginfo of given module */
206static struct debuginfo *open_debuginfo(const char *module) 205static struct debuginfo *open_debuginfo(const char *module)
207{ 206{
@@ -630,7 +629,7 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
630 return ret; 629 return ret;
631} 630}
632 631
633#else /* !DWARF_SUPPORT */ 632#else /* !HAVE_DWARF_SUPPORT */
634 633
635static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp, 634static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
636 struct perf_probe_point *pp) 635 struct perf_probe_point *pp)
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index f0692737ebf1..ffb657ffd327 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -115,7 +115,7 @@ static const Dwfl_Callbacks offline_callbacks = {
115}; 115};
116 116
117/* Get a Dwarf from offline image */ 117/* Get a Dwarf from offline image */
118static int debuginfo__init_offline_dwarf(struct debuginfo *self, 118static int debuginfo__init_offline_dwarf(struct debuginfo *dbg,
119 const char *path) 119 const char *path)
120{ 120{
121 int fd; 121 int fd;
@@ -124,25 +124,25 @@ static int debuginfo__init_offline_dwarf(struct debuginfo *self,
124 if (fd < 0) 124 if (fd < 0)
125 return fd; 125 return fd;
126 126
127 self->dwfl = dwfl_begin(&offline_callbacks); 127 dbg->dwfl = dwfl_begin(&offline_callbacks);
128 if (!self->dwfl) 128 if (!dbg->dwfl)
129 goto error; 129 goto error;
130 130
131 self->mod = dwfl_report_offline(self->dwfl, "", "", fd); 131 dbg->mod = dwfl_report_offline(dbg->dwfl, "", "", fd);
132 if (!self->mod) 132 if (!dbg->mod)
133 goto error; 133 goto error;
134 134
135 self->dbg = dwfl_module_getdwarf(self->mod, &self->bias); 135 dbg->dbg = dwfl_module_getdwarf(dbg->mod, &dbg->bias);
136 if (!self->dbg) 136 if (!dbg->dbg)
137 goto error; 137 goto error;
138 138
139 return 0; 139 return 0;
140error: 140error:
141 if (self->dwfl) 141 if (dbg->dwfl)
142 dwfl_end(self->dwfl); 142 dwfl_end(dbg->dwfl);
143 else 143 else
144 close(fd); 144 close(fd);
145 memset(self, 0, sizeof(*self)); 145 memset(dbg, 0, sizeof(*dbg));
146 146
147 return -ENOENT; 147 return -ENOENT;
148} 148}
@@ -180,24 +180,24 @@ static const Dwfl_Callbacks kernel_callbacks = {
180}; 180};
181 181
182/* Get a Dwarf from live kernel image */ 182/* Get a Dwarf from live kernel image */
183static int debuginfo__init_online_kernel_dwarf(struct debuginfo *self, 183static int debuginfo__init_online_kernel_dwarf(struct debuginfo *dbg,
184 Dwarf_Addr addr) 184 Dwarf_Addr addr)
185{ 185{
186 self->dwfl = dwfl_begin(&kernel_callbacks); 186 dbg->dwfl = dwfl_begin(&kernel_callbacks);
187 if (!self->dwfl) 187 if (!dbg->dwfl)
188 return -EINVAL; 188 return -EINVAL;
189 189
190 /* Load the kernel dwarves: Don't care the result here */ 190 /* Load the kernel dwarves: Don't care the result here */
191 dwfl_linux_kernel_report_kernel(self->dwfl); 191 dwfl_linux_kernel_report_kernel(dbg->dwfl);
192 dwfl_linux_kernel_report_modules(self->dwfl); 192 dwfl_linux_kernel_report_modules(dbg->dwfl);
193 193
194 self->dbg = dwfl_addrdwarf(self->dwfl, addr, &self->bias); 194 dbg->dbg = dwfl_addrdwarf(dbg->dwfl, addr, &dbg->bias);
195 /* Here, check whether we could get a real dwarf */ 195 /* Here, check whether we could get a real dwarf */
196 if (!self->dbg) { 196 if (!dbg->dbg) {
197 pr_debug("Failed to find kernel dwarf at %lx\n", 197 pr_debug("Failed to find kernel dwarf at %lx\n",
198 (unsigned long)addr); 198 (unsigned long)addr);
199 dwfl_end(self->dwfl); 199 dwfl_end(dbg->dwfl);
200 memset(self, 0, sizeof(*self)); 200 memset(dbg, 0, sizeof(*dbg));
201 return -ENOENT; 201 return -ENOENT;
202 } 202 }
203 203
@@ -205,7 +205,7 @@ static int debuginfo__init_online_kernel_dwarf(struct debuginfo *self,
205} 205}
206#else 206#else
207/* With older elfutils, this just support kernel module... */ 207/* With older elfutils, this just support kernel module... */
208static int debuginfo__init_online_kernel_dwarf(struct debuginfo *self, 208static int debuginfo__init_online_kernel_dwarf(struct debuginfo *dbg,
209 Dwarf_Addr addr __maybe_unused) 209 Dwarf_Addr addr __maybe_unused)
210{ 210{
211 const char *path = kernel_get_module_path("kernel"); 211 const char *path = kernel_get_module_path("kernel");
@@ -216,44 +216,45 @@ static int debuginfo__init_online_kernel_dwarf(struct debuginfo *self,
216 } 216 }
217 217
218 pr_debug2("Use file %s for debuginfo\n", path); 218 pr_debug2("Use file %s for debuginfo\n", path);
219 return debuginfo__init_offline_dwarf(self, path); 219 return debuginfo__init_offline_dwarf(dbg, path);
220} 220}
221#endif 221#endif
222 222
223struct debuginfo *debuginfo__new(const char *path) 223struct debuginfo *debuginfo__new(const char *path)
224{ 224{
225 struct debuginfo *self = zalloc(sizeof(struct debuginfo)); 225 struct debuginfo *dbg = zalloc(sizeof(*dbg));
226 if (!self) 226 if (!dbg)
227 return NULL; 227 return NULL;
228 228
229 if (debuginfo__init_offline_dwarf(self, path) < 0) { 229 if (debuginfo__init_offline_dwarf(dbg, path) < 0) {
230 free(self); 230 free(dbg);
231 self = NULL; 231 dbg = NULL;
232 } 232 }
233 233
234 return self; 234 return dbg;
235} 235}
236 236
237struct debuginfo *debuginfo__new_online_kernel(unsigned long addr) 237struct debuginfo *debuginfo__new_online_kernel(unsigned long addr)
238{ 238{
239 struct debuginfo *self = zalloc(sizeof(struct debuginfo)); 239 struct debuginfo *dbg = zalloc(sizeof(*dbg));
240 if (!self) 240
241 if (!dbg)
241 return NULL; 242 return NULL;
242 243
243 if (debuginfo__init_online_kernel_dwarf(self, (Dwarf_Addr)addr) < 0) { 244 if (debuginfo__init_online_kernel_dwarf(dbg, (Dwarf_Addr)addr) < 0) {
244 free(self); 245 free(dbg);
245 self = NULL; 246 dbg = NULL;
246 } 247 }
247 248
248 return self; 249 return dbg;
249} 250}
250 251
251void debuginfo__delete(struct debuginfo *self) 252void debuginfo__delete(struct debuginfo *dbg)
252{ 253{
253 if (self) { 254 if (dbg) {
254 if (self->dwfl) 255 if (dbg->dwfl)
255 dwfl_end(self->dwfl); 256 dwfl_end(dbg->dwfl);
256 free(self); 257 free(dbg);
257 } 258 }
258} 259}
259 260
@@ -273,12 +274,15 @@ static struct probe_trace_arg_ref *alloc_trace_arg_ref(long offs)
273/* 274/*
274 * Convert a location into trace_arg. 275 * Convert a location into trace_arg.
275 * If tvar == NULL, this just checks variable can be converted. 276 * If tvar == NULL, this just checks variable can be converted.
277 * If fentry == true and vr_die is a parameter, do huristic search
278 * for the location fuzzed by function entry mcount.
276 */ 279 */
277static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr, 280static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr,
278 Dwarf_Op *fb_ops, 281 Dwarf_Op *fb_ops, Dwarf_Die *sp_die,
279 struct probe_trace_arg *tvar) 282 struct probe_trace_arg *tvar)
280{ 283{
281 Dwarf_Attribute attr; 284 Dwarf_Attribute attr;
285 Dwarf_Addr tmp = 0;
282 Dwarf_Op *op; 286 Dwarf_Op *op;
283 size_t nops; 287 size_t nops;
284 unsigned int regn; 288 unsigned int regn;
@@ -291,12 +295,29 @@ static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr,
291 goto static_var; 295 goto static_var;
292 296
293 /* TODO: handle more than 1 exprs */ 297 /* TODO: handle more than 1 exprs */
294 if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL || 298 if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL)
295 dwarf_getlocation_addr(&attr, addr, &op, &nops, 1) <= 0 || 299 return -EINVAL; /* Broken DIE ? */
296 nops == 0) { 300 if (dwarf_getlocation_addr(&attr, addr, &op, &nops, 1) <= 0) {
297 /* TODO: Support const_value */ 301 ret = dwarf_entrypc(sp_die, &tmp);
302 if (ret || addr != tmp ||
303 dwarf_tag(vr_die) != DW_TAG_formal_parameter ||
304 dwarf_highpc(sp_die, &tmp))
305 return -ENOENT;
306 /*
307 * This is fuzzed by fentry mcount. We try to find the
308 * parameter location at the earliest address.
309 */
310 for (addr += 1; addr <= tmp; addr++) {
311 if (dwarf_getlocation_addr(&attr, addr, &op,
312 &nops, 1) > 0)
313 goto found;
314 }
298 return -ENOENT; 315 return -ENOENT;
299 } 316 }
317found:
318 if (nops == 0)
319 /* TODO: Support const_value */
320 return -ENOENT;
300 321
301 if (op->atom == DW_OP_addr) { 322 if (op->atom == DW_OP_addr) {
302static_var: 323static_var:
@@ -563,7 +584,7 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
563 } 584 }
564 585
565 if (die_find_member(&type, field->name, die_mem) == NULL) { 586 if (die_find_member(&type, field->name, die_mem) == NULL) {
566 pr_warning("%s(tyep:%s) has no member %s.\n", varname, 587 pr_warning("%s(type:%s) has no member %s.\n", varname,
567 dwarf_diename(&type), field->name); 588 dwarf_diename(&type), field->name);
568 return -EINVAL; 589 return -EINVAL;
569 } 590 }
@@ -600,7 +621,7 @@ static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
600 dwarf_diename(vr_die)); 621 dwarf_diename(vr_die));
601 622
602 ret = convert_variable_location(vr_die, pf->addr, pf->fb_ops, 623 ret = convert_variable_location(vr_die, pf->addr, pf->fb_ops,
603 pf->tvar); 624 &pf->sp_die, pf->tvar);
604 if (ret == -ENOENT) 625 if (ret == -ENOENT)
605 pr_err("Failed to find the location of %s at this address.\n" 626 pr_err("Failed to find the location of %s at this address.\n"
606 " Perhaps, it has been optimized out.\n", pf->pvar->var); 627 " Perhaps, it has been optimized out.\n", pf->pvar->var);
@@ -1063,7 +1084,7 @@ static int pubname_search_cb(Dwarf *dbg, Dwarf_Global *gl, void *data)
1063} 1084}
1064 1085
1065/* Find probe points from debuginfo */ 1086/* Find probe points from debuginfo */
1066static int debuginfo__find_probes(struct debuginfo *self, 1087static int debuginfo__find_probes(struct debuginfo *dbg,
1067 struct probe_finder *pf) 1088 struct probe_finder *pf)
1068{ 1089{
1069 struct perf_probe_point *pp = &pf->pev->point; 1090 struct perf_probe_point *pp = &pf->pev->point;
@@ -1074,7 +1095,7 @@ static int debuginfo__find_probes(struct debuginfo *self,
1074 1095
1075#if _ELFUTILS_PREREQ(0, 142) 1096#if _ELFUTILS_PREREQ(0, 142)
1076 /* Get the call frame information from this dwarf */ 1097 /* Get the call frame information from this dwarf */
1077 pf->cfi = dwarf_getcfi(self->dbg); 1098 pf->cfi = dwarf_getcfi(dbg->dbg);
1078#endif 1099#endif
1079 1100
1080 off = 0; 1101 off = 0;
@@ -1093,7 +1114,7 @@ static int debuginfo__find_probes(struct debuginfo *self,
1093 .data = pf, 1114 .data = pf,
1094 }; 1115 };
1095 1116
1096 dwarf_getpubnames(self->dbg, pubname_search_cb, 1117 dwarf_getpubnames(dbg->dbg, pubname_search_cb,
1097 &pubname_param, 0); 1118 &pubname_param, 0);
1098 if (pubname_param.found) { 1119 if (pubname_param.found) {
1099 ret = probe_point_search_cb(&pf->sp_die, &probe_param); 1120 ret = probe_point_search_cb(&pf->sp_die, &probe_param);
@@ -1103,9 +1124,9 @@ static int debuginfo__find_probes(struct debuginfo *self,
1103 } 1124 }
1104 1125
1105 /* Loop on CUs (Compilation Unit) */ 1126 /* Loop on CUs (Compilation Unit) */
1106 while (!dwarf_nextcu(self->dbg, off, &noff, &cuhl, NULL, NULL, NULL)) { 1127 while (!dwarf_nextcu(dbg->dbg, off, &noff, &cuhl, NULL, NULL, NULL)) {
1107 /* Get the DIE(Debugging Information Entry) of this CU */ 1128 /* Get the DIE(Debugging Information Entry) of this CU */
1108 diep = dwarf_offdie(self->dbg, off + cuhl, &pf->cu_die); 1129 diep = dwarf_offdie(dbg->dbg, off + cuhl, &pf->cu_die);
1109 if (!diep) 1130 if (!diep)
1110 continue; 1131 continue;
1111 1132
@@ -1136,12 +1157,80 @@ found:
1136 return ret; 1157 return ret;
1137} 1158}
1138 1159
1160struct local_vars_finder {
1161 struct probe_finder *pf;
1162 struct perf_probe_arg *args;
1163 int max_args;
1164 int nargs;
1165 int ret;
1166};
1167
1168/* Collect available variables in this scope */
1169static int copy_variables_cb(Dwarf_Die *die_mem, void *data)
1170{
1171 struct local_vars_finder *vf = data;
1172 struct probe_finder *pf = vf->pf;
1173 int tag;
1174
1175 tag = dwarf_tag(die_mem);
1176 if (tag == DW_TAG_formal_parameter ||
1177 tag == DW_TAG_variable) {
1178 if (convert_variable_location(die_mem, vf->pf->addr,
1179 vf->pf->fb_ops, &pf->sp_die,
1180 NULL) == 0) {
1181 vf->args[vf->nargs].var = (char *)dwarf_diename(die_mem);
1182 if (vf->args[vf->nargs].var == NULL) {
1183 vf->ret = -ENOMEM;
1184 return DIE_FIND_CB_END;
1185 }
1186 pr_debug(" %s", vf->args[vf->nargs].var);
1187 vf->nargs++;
1188 }
1189 }
1190
1191 if (dwarf_haspc(die_mem, vf->pf->addr))
1192 return DIE_FIND_CB_CONTINUE;
1193 else
1194 return DIE_FIND_CB_SIBLING;
1195}
1196
1197static int expand_probe_args(Dwarf_Die *sc_die, struct probe_finder *pf,
1198 struct perf_probe_arg *args)
1199{
1200 Dwarf_Die die_mem;
1201 int i;
1202 int n = 0;
1203 struct local_vars_finder vf = {.pf = pf, .args = args,
1204 .max_args = MAX_PROBE_ARGS, .ret = 0};
1205
1206 for (i = 0; i < pf->pev->nargs; i++) {
1207 /* var never be NULL */
1208 if (strcmp(pf->pev->args[i].var, "$vars") == 0) {
1209 pr_debug("Expanding $vars into:");
1210 vf.nargs = n;
1211 /* Special local variables */
1212 die_find_child(sc_die, copy_variables_cb, (void *)&vf,
1213 &die_mem);
1214 pr_debug(" (%d)\n", vf.nargs - n);
1215 if (vf.ret < 0)
1216 return vf.ret;
1217 n = vf.nargs;
1218 } else {
1219 /* Copy normal argument */
1220 args[n] = pf->pev->args[i];
1221 n++;
1222 }
1223 }
1224 return n;
1225}
1226
1139/* Add a found probe point into trace event list */ 1227/* Add a found probe point into trace event list */
1140static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf) 1228static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf)
1141{ 1229{
1142 struct trace_event_finder *tf = 1230 struct trace_event_finder *tf =
1143 container_of(pf, struct trace_event_finder, pf); 1231 container_of(pf, struct trace_event_finder, pf);
1144 struct probe_trace_event *tev; 1232 struct probe_trace_event *tev;
1233 struct perf_probe_arg *args;
1145 int ret, i; 1234 int ret, i;
1146 1235
1147 /* Check number of tevs */ 1236 /* Check number of tevs */
@@ -1161,31 +1250,45 @@ static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf)
1161 pr_debug("Probe point found: %s+%lu\n", tev->point.symbol, 1250 pr_debug("Probe point found: %s+%lu\n", tev->point.symbol,
1162 tev->point.offset); 1251 tev->point.offset);
1163 1252
1164 /* Find each argument */ 1253 /* Expand special probe argument if exist */
1165 tev->nargs = pf->pev->nargs; 1254 args = zalloc(sizeof(struct perf_probe_arg) * MAX_PROBE_ARGS);
1166 tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs); 1255 if (args == NULL)
1167 if (tev->args == NULL)
1168 return -ENOMEM; 1256 return -ENOMEM;
1169 for (i = 0; i < pf->pev->nargs; i++) { 1257
1170 pf->pvar = &pf->pev->args[i]; 1258 ret = expand_probe_args(sc_die, pf, args);
1259 if (ret < 0)
1260 goto end;
1261
1262 tev->nargs = ret;
1263 tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs);
1264 if (tev->args == NULL) {
1265 ret = -ENOMEM;
1266 goto end;
1267 }
1268
1269 /* Find each argument */
1270 for (i = 0; i < tev->nargs; i++) {
1271 pf->pvar = &args[i];
1171 pf->tvar = &tev->args[i]; 1272 pf->tvar = &tev->args[i];
1172 /* Variable should be found from scope DIE */ 1273 /* Variable should be found from scope DIE */
1173 ret = find_variable(sc_die, pf); 1274 ret = find_variable(sc_die, pf);
1174 if (ret != 0) 1275 if (ret != 0)
1175 return ret; 1276 break;
1176 } 1277 }
1177 1278
1178 return 0; 1279end:
1280 free(args);
1281 return ret;
1179} 1282}
1180 1283
1181/* Find probe_trace_events specified by perf_probe_event from debuginfo */ 1284/* Find probe_trace_events specified by perf_probe_event from debuginfo */
1182int debuginfo__find_trace_events(struct debuginfo *self, 1285int debuginfo__find_trace_events(struct debuginfo *dbg,
1183 struct perf_probe_event *pev, 1286 struct perf_probe_event *pev,
1184 struct probe_trace_event **tevs, int max_tevs) 1287 struct probe_trace_event **tevs, int max_tevs)
1185{ 1288{
1186 struct trace_event_finder tf = { 1289 struct trace_event_finder tf = {
1187 .pf = {.pev = pev, .callback = add_probe_trace_event}, 1290 .pf = {.pev = pev, .callback = add_probe_trace_event},
1188 .mod = self->mod, .max_tevs = max_tevs}; 1291 .mod = dbg->mod, .max_tevs = max_tevs};
1189 int ret; 1292 int ret;
1190 1293
1191 /* Allocate result tevs array */ 1294 /* Allocate result tevs array */
@@ -1196,7 +1299,7 @@ int debuginfo__find_trace_events(struct debuginfo *self,
1196 tf.tevs = *tevs; 1299 tf.tevs = *tevs;
1197 tf.ntevs = 0; 1300 tf.ntevs = 0;
1198 1301
1199 ret = debuginfo__find_probes(self, &tf.pf); 1302 ret = debuginfo__find_probes(dbg, &tf.pf);
1200 if (ret < 0) { 1303 if (ret < 0) {
1201 free(*tevs); 1304 free(*tevs);
1202 *tevs = NULL; 1305 *tevs = NULL;
@@ -1222,7 +1325,8 @@ static int collect_variables_cb(Dwarf_Die *die_mem, void *data)
1222 if (tag == DW_TAG_formal_parameter || 1325 if (tag == DW_TAG_formal_parameter ||
1223 tag == DW_TAG_variable) { 1326 tag == DW_TAG_variable) {
1224 ret = convert_variable_location(die_mem, af->pf.addr, 1327 ret = convert_variable_location(die_mem, af->pf.addr,
1225 af->pf.fb_ops, NULL); 1328 af->pf.fb_ops, &af->pf.sp_die,
1329 NULL);
1226 if (ret == 0) { 1330 if (ret == 0) {
1227 ret = die_get_varname(die_mem, buf, MAX_VAR_LEN); 1331 ret = die_get_varname(die_mem, buf, MAX_VAR_LEN);
1228 pr_debug2("Add new var: %s\n", buf); 1332 pr_debug2("Add new var: %s\n", buf);
@@ -1286,14 +1390,14 @@ out:
1286} 1390}
1287 1391
1288/* Find available variables at given probe point */ 1392/* Find available variables at given probe point */
1289int debuginfo__find_available_vars_at(struct debuginfo *self, 1393int debuginfo__find_available_vars_at(struct debuginfo *dbg,
1290 struct perf_probe_event *pev, 1394 struct perf_probe_event *pev,
1291 struct variable_list **vls, 1395 struct variable_list **vls,
1292 int max_vls, bool externs) 1396 int max_vls, bool externs)
1293{ 1397{
1294 struct available_var_finder af = { 1398 struct available_var_finder af = {
1295 .pf = {.pev = pev, .callback = add_available_vars}, 1399 .pf = {.pev = pev, .callback = add_available_vars},
1296 .mod = self->mod, 1400 .mod = dbg->mod,
1297 .max_vls = max_vls, .externs = externs}; 1401 .max_vls = max_vls, .externs = externs};
1298 int ret; 1402 int ret;
1299 1403
@@ -1305,7 +1409,7 @@ int debuginfo__find_available_vars_at(struct debuginfo *self,
1305 af.vls = *vls; 1409 af.vls = *vls;
1306 af.nvls = 0; 1410 af.nvls = 0;
1307 1411
1308 ret = debuginfo__find_probes(self, &af.pf); 1412 ret = debuginfo__find_probes(dbg, &af.pf);
1309 if (ret < 0) { 1413 if (ret < 0) {
1310 /* Free vlist for error */ 1414 /* Free vlist for error */
1311 while (af.nvls--) { 1415 while (af.nvls--) {
@@ -1323,7 +1427,7 @@ int debuginfo__find_available_vars_at(struct debuginfo *self,
1323} 1427}
1324 1428
1325/* Reverse search */ 1429/* Reverse search */
1326int debuginfo__find_probe_point(struct debuginfo *self, unsigned long addr, 1430int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr,
1327 struct perf_probe_point *ppt) 1431 struct perf_probe_point *ppt)
1328{ 1432{
1329 Dwarf_Die cudie, spdie, indie; 1433 Dwarf_Die cudie, spdie, indie;
@@ -1332,10 +1436,10 @@ int debuginfo__find_probe_point(struct debuginfo *self, unsigned long addr,
1332 int baseline = 0, lineno = 0, ret = 0; 1436 int baseline = 0, lineno = 0, ret = 0;
1333 1437
1334 /* Adjust address with bias */ 1438 /* Adjust address with bias */
1335 addr += self->bias; 1439 addr += dbg->bias;
1336 1440
1337 /* Find cu die */ 1441 /* Find cu die */
1338 if (!dwarf_addrdie(self->dbg, (Dwarf_Addr)addr - self->bias, &cudie)) { 1442 if (!dwarf_addrdie(dbg->dbg, (Dwarf_Addr)addr - dbg->bias, &cudie)) {
1339 pr_warning("Failed to find debug information for address %lx\n", 1443 pr_warning("Failed to find debug information for address %lx\n",
1340 addr); 1444 addr);
1341 ret = -EINVAL; 1445 ret = -EINVAL;
@@ -1536,7 +1640,7 @@ static int find_line_range_by_func(struct line_finder *lf)
1536 return param.retval; 1640 return param.retval;
1537} 1641}
1538 1642
1539int debuginfo__find_line_range(struct debuginfo *self, struct line_range *lr) 1643int debuginfo__find_line_range(struct debuginfo *dbg, struct line_range *lr)
1540{ 1644{
1541 struct line_finder lf = {.lr = lr, .found = 0}; 1645 struct line_finder lf = {.lr = lr, .found = 0};
1542 int ret = 0; 1646 int ret = 0;
@@ -1553,7 +1657,7 @@ int debuginfo__find_line_range(struct debuginfo *self, struct line_range *lr)
1553 struct dwarf_callback_param line_range_param = { 1657 struct dwarf_callback_param line_range_param = {
1554 .data = (void *)&lf, .retval = 0}; 1658 .data = (void *)&lf, .retval = 0};
1555 1659
1556 dwarf_getpubnames(self->dbg, pubname_search_cb, 1660 dwarf_getpubnames(dbg->dbg, pubname_search_cb,
1557 &pubname_param, 0); 1661 &pubname_param, 0);
1558 if (pubname_param.found) { 1662 if (pubname_param.found) {
1559 line_range_search_cb(&lf.sp_die, &line_range_param); 1663 line_range_search_cb(&lf.sp_die, &line_range_param);
@@ -1564,12 +1668,12 @@ int debuginfo__find_line_range(struct debuginfo *self, struct line_range *lr)
1564 1668
1565 /* Loop on CUs (Compilation Unit) */ 1669 /* Loop on CUs (Compilation Unit) */
1566 while (!lf.found && ret >= 0) { 1670 while (!lf.found && ret >= 0) {
1567 if (dwarf_nextcu(self->dbg, off, &noff, &cuhl, 1671 if (dwarf_nextcu(dbg->dbg, off, &noff, &cuhl,
1568 NULL, NULL, NULL) != 0) 1672 NULL, NULL, NULL) != 0)
1569 break; 1673 break;
1570 1674
1571 /* Get the DIE(Debugging Information Entry) of this CU */ 1675 /* Get the DIE(Debugging Information Entry) of this CU */
1572 diep = dwarf_offdie(self->dbg, off + cuhl, &lf.cu_die); 1676 diep = dwarf_offdie(dbg->dbg, off + cuhl, &lf.cu_die);
1573 if (!diep) 1677 if (!diep)
1574 continue; 1678 continue;
1575 1679
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
index 3b7d63018960..ffc33cdd25cc 100644
--- a/tools/perf/util/probe-finder.h
+++ b/tools/perf/util/probe-finder.h
@@ -7,6 +7,7 @@
7 7
8#define MAX_PROBE_BUFFER 1024 8#define MAX_PROBE_BUFFER 1024
9#define MAX_PROBES 128 9#define MAX_PROBES 128
10#define MAX_PROBE_ARGS 128
10 11
11static inline int is_c_varname(const char *name) 12static inline int is_c_varname(const char *name)
12{ 13{
@@ -14,7 +15,7 @@ static inline int is_c_varname(const char *name)
14 return isalpha(name[0]) || name[0] == '_'; 15 return isalpha(name[0]) || name[0] == '_';
15} 16}
16 17
17#ifdef DWARF_SUPPORT 18#ifdef HAVE_DWARF_SUPPORT
18 19
19#include "dwarf-aux.h" 20#include "dwarf-aux.h"
20 21
@@ -30,25 +31,25 @@ struct debuginfo {
30 31
31extern struct debuginfo *debuginfo__new(const char *path); 32extern struct debuginfo *debuginfo__new(const char *path);
32extern struct debuginfo *debuginfo__new_online_kernel(unsigned long addr); 33extern struct debuginfo *debuginfo__new_online_kernel(unsigned long addr);
33extern void debuginfo__delete(struct debuginfo *self); 34extern void debuginfo__delete(struct debuginfo *dbg);
34 35
35/* Find probe_trace_events specified by perf_probe_event from debuginfo */ 36/* Find probe_trace_events specified by perf_probe_event from debuginfo */
36extern int debuginfo__find_trace_events(struct debuginfo *self, 37extern int debuginfo__find_trace_events(struct debuginfo *dbg,
37 struct perf_probe_event *pev, 38 struct perf_probe_event *pev,
38 struct probe_trace_event **tevs, 39 struct probe_trace_event **tevs,
39 int max_tevs); 40 int max_tevs);
40 41
41/* Find a perf_probe_point from debuginfo */ 42/* Find a perf_probe_point from debuginfo */
42extern int debuginfo__find_probe_point(struct debuginfo *self, 43extern int debuginfo__find_probe_point(struct debuginfo *dbg,
43 unsigned long addr, 44 unsigned long addr,
44 struct perf_probe_point *ppt); 45 struct perf_probe_point *ppt);
45 46
46/* Find a line range */ 47/* Find a line range */
47extern int debuginfo__find_line_range(struct debuginfo *self, 48extern int debuginfo__find_line_range(struct debuginfo *dbg,
48 struct line_range *lr); 49 struct line_range *lr);
49 50
50/* Find available variables */ 51/* Find available variables */
51extern int debuginfo__find_available_vars_at(struct debuginfo *self, 52extern int debuginfo__find_available_vars_at(struct debuginfo *dbg,
52 struct perf_probe_event *pev, 53 struct perf_probe_event *pev,
53 struct variable_list **vls, 54 struct variable_list **vls,
54 int max_points, bool externs); 55 int max_points, bool externs);
@@ -105,6 +106,6 @@ struct line_finder {
105 int found; 106 int found;
106}; 107};
107 108
108#endif /* DWARF_SUPPORT */ 109#endif /* HAVE_DWARF_SUPPORT */
109 110
110#endif /*_PROBE_FINDER_H */ 111#endif /*_PROBE_FINDER_H */
diff --git a/tools/perf/util/pstack.h b/tools/perf/util/pstack.h
index 4cedea59f518..c3cb6584d527 100644
--- a/tools/perf/util/pstack.h
+++ b/tools/perf/util/pstack.h
@@ -5,10 +5,10 @@
5 5
6struct pstack; 6struct pstack;
7struct pstack *pstack__new(unsigned short max_nr_entries); 7struct pstack *pstack__new(unsigned short max_nr_entries);
8void pstack__delete(struct pstack *self); 8void pstack__delete(struct pstack *pstack);
9bool pstack__empty(const struct pstack *self); 9bool pstack__empty(const struct pstack *pstack);
10void pstack__remove(struct pstack *self, void *key); 10void pstack__remove(struct pstack *pstack, void *key);
11void pstack__push(struct pstack *self, void *key); 11void pstack__push(struct pstack *pstack, void *key);
12void *pstack__pop(struct pstack *self); 12void *pstack__pop(struct pstack *pstack);
13 13
14#endif /* _PERF_PSTACK_ */ 14#endif /* _PERF_PSTACK_ */
diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources
index f75ae1b9900c..239036fb2b2c 100644
--- a/tools/perf/util/python-ext-sources
+++ b/tools/perf/util/python-ext-sources
@@ -17,5 +17,5 @@ util/xyarray.c
17util/cgroup.c 17util/cgroup.c
18util/rblist.c 18util/rblist.c
19util/strlist.c 19util/strlist.c
20util/sysfs.c 20util/fs.c
21../../lib/rbtree.c 21../../lib/rbtree.c
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 2ac4bc92bb1f..4bf8ace7f511 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -33,13 +33,6 @@ int eprintf(int level, const char *fmt, ...)
33# define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size, 33# define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size,
34#endif 34#endif
35 35
36struct throttle_event {
37 struct perf_event_header header;
38 u64 time;
39 u64 id;
40 u64 stream_id;
41};
42
43PyMODINIT_FUNC initperf(void); 36PyMODINIT_FUNC initperf(void);
44 37
45#define member_def(type, member, ptype, help) \ 38#define member_def(type, member, ptype, help) \
@@ -1038,6 +1031,7 @@ PyMODINIT_FUNC initperf(void)
1038 pyrf_cpu_map__setup_types() < 0) 1031 pyrf_cpu_map__setup_types() < 0)
1039 return; 1032 return;
1040 1033
1034 /* The page_size is placed in util object. */
1041 page_size = sysconf(_SC_PAGE_SIZE); 1035 page_size = sysconf(_SC_PAGE_SIZE);
1042 1036
1043 Py_INCREF(&pyrf_evlist__type); 1037 Py_INCREF(&pyrf_evlist__type);
diff --git a/tools/perf/util/rblist.c b/tools/perf/util/rblist.c
index a16cdd2625ad..0dfe27d99458 100644
--- a/tools/perf/util/rblist.c
+++ b/tools/perf/util/rblist.c
@@ -48,10 +48,12 @@ void rblist__remove_node(struct rblist *rblist, struct rb_node *rb_node)
48 rblist->node_delete(rblist, rb_node); 48 rblist->node_delete(rblist, rb_node);
49} 49}
50 50
51struct rb_node *rblist__find(struct rblist *rblist, const void *entry) 51static struct rb_node *__rblist__findnew(struct rblist *rblist,
52 const void *entry,
53 bool create)
52{ 54{
53 struct rb_node **p = &rblist->entries.rb_node; 55 struct rb_node **p = &rblist->entries.rb_node;
54 struct rb_node *parent = NULL; 56 struct rb_node *parent = NULL, *new_node = NULL;
55 57
56 while (*p != NULL) { 58 while (*p != NULL) {
57 int rc; 59 int rc;
@@ -67,7 +69,26 @@ struct rb_node *rblist__find(struct rblist *rblist, const void *entry)
67 return parent; 69 return parent;
68 } 70 }
69 71
70 return NULL; 72 if (create) {
73 new_node = rblist->node_new(rblist, entry);
74 if (new_node) {
75 rb_link_node(new_node, parent, p);
76 rb_insert_color(new_node, &rblist->entries);
77 ++rblist->nr_entries;
78 }
79 }
80
81 return new_node;
82}
83
84struct rb_node *rblist__find(struct rblist *rblist, const void *entry)
85{
86 return __rblist__findnew(rblist, entry, false);
87}
88
89struct rb_node *rblist__findnew(struct rblist *rblist, const void *entry)
90{
91 return __rblist__findnew(rblist, entry, true);
71} 92}
72 93
73void rblist__init(struct rblist *rblist) 94void rblist__init(struct rblist *rblist)
diff --git a/tools/perf/util/rblist.h b/tools/perf/util/rblist.h
index 6d0cae5ae83d..ff9913b994c2 100644
--- a/tools/perf/util/rblist.h
+++ b/tools/perf/util/rblist.h
@@ -32,6 +32,7 @@ void rblist__delete(struct rblist *rblist);
32int rblist__add_node(struct rblist *rblist, const void *new_entry); 32int rblist__add_node(struct rblist *rblist, const void *new_entry);
33void rblist__remove_node(struct rblist *rblist, struct rb_node *rb_node); 33void rblist__remove_node(struct rblist *rblist, struct rb_node *rb_node);
34struct rb_node *rblist__find(struct rblist *rblist, const void *entry); 34struct rb_node *rblist__find(struct rblist *rblist, const void *entry);
35struct rb_node *rblist__findnew(struct rblist *rblist, const void *entry);
35struct rb_node *rblist__entry(const struct rblist *rblist, unsigned int idx); 36struct rb_node *rblist__entry(const struct rblist *rblist, unsigned int idx);
36 37
37static inline bool rblist__empty(const struct rblist *rblist) 38static inline bool rblist__empty(const struct rblist *rblist)
diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c
index 18d73aa2f0f8..c8845b107f60 100644
--- a/tools/perf/util/record.c
+++ b/tools/perf/util/record.c
@@ -2,6 +2,8 @@
2#include "evsel.h" 2#include "evsel.h"
3#include "cpumap.h" 3#include "cpumap.h"
4#include "parse-events.h" 4#include "parse-events.h"
5#include "fs.h"
6#include "util.h"
5 7
6typedef void (*setup_probe_fn_t)(struct perf_evsel *evsel); 8typedef void (*setup_probe_fn_t)(struct perf_evsel *evsel);
7 9
@@ -106,3 +108,72 @@ void perf_evlist__config(struct perf_evlist *evlist,
106 108
107 perf_evlist__set_id_pos(evlist); 109 perf_evlist__set_id_pos(evlist);
108} 110}
111
112static int get_max_rate(unsigned int *rate)
113{
114 char path[PATH_MAX];
115 const char *procfs = procfs__mountpoint();
116
117 if (!procfs)
118 return -1;
119
120 snprintf(path, PATH_MAX,
121 "%s/sys/kernel/perf_event_max_sample_rate", procfs);
122
123 return filename__read_int(path, (int *) rate);
124}
125
126static int perf_record_opts__config_freq(struct perf_record_opts *opts)
127{
128 bool user_freq = opts->user_freq != UINT_MAX;
129 unsigned int max_rate;
130
131 if (opts->user_interval != ULLONG_MAX)
132 opts->default_interval = opts->user_interval;
133 if (user_freq)
134 opts->freq = opts->user_freq;
135
136 /*
137 * User specified count overrides default frequency.
138 */
139 if (opts->default_interval)
140 opts->freq = 0;
141 else if (opts->freq) {
142 opts->default_interval = opts->freq;
143 } else {
144 pr_err("frequency and count are zero, aborting\n");
145 return -1;
146 }
147
148 if (get_max_rate(&max_rate))
149 return 0;
150
151 /*
152 * User specified frequency is over current maximum.
153 */
154 if (user_freq && (max_rate < opts->freq)) {
155 pr_err("Maximum frequency rate (%u) reached.\n"
156 "Please use -F freq option with lower value or consider\n"
157 "tweaking /proc/sys/kernel/perf_event_max_sample_rate.\n",
158 max_rate);
159 return -1;
160 }
161
162 /*
163 * Default frequency is over current maximum.
164 */
165 if (max_rate < opts->freq) {
166 pr_warning("Lowering default frequency rate to %u.\n"
167 "Please consider tweaking "
168 "/proc/sys/kernel/perf_event_max_sample_rate.\n",
169 max_rate);
170 opts->freq = max_rate;
171 }
172
173 return 0;
174}
175
176int perf_record_opts__config(struct perf_record_opts *opts)
177{
178 return perf_record_opts__config_freq(opts);
179}
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index c0c9795c4f02..d5e5969f6fea 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -273,7 +273,7 @@ static void perl_process_tracepoint(union perf_event *perf_event __maybe_unused,
273 int cpu = sample->cpu; 273 int cpu = sample->cpu;
274 void *data = sample->raw_data; 274 void *data = sample->raw_data;
275 unsigned long long nsecs = sample->time; 275 unsigned long long nsecs = sample->time;
276 char *comm = thread->comm; 276 const char *comm = thread__comm_str(thread);
277 277
278 dSP; 278 dSP;
279 279
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 95d91a0b23af..53c20e7fd900 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -250,7 +250,7 @@ static void python_process_tracepoint(union perf_event *perf_event
250 int cpu = sample->cpu; 250 int cpu = sample->cpu;
251 void *data = sample->raw_data; 251 void *data = sample->raw_data;
252 unsigned long long nsecs = sample->time; 252 unsigned long long nsecs = sample->time;
253 char *comm = thread->comm; 253 const char *comm = thread__comm_str(thread);
254 254
255 t = PyTuple_New(MAX_FIELDS); 255 t = PyTuple_New(MAX_FIELDS);
256 if (!t) 256 if (!t)
@@ -389,7 +389,7 @@ static void python_process_general_event(union perf_event *perf_event
389 pydict_set_item_string_decref(dict, "raw_buf", PyString_FromStringAndSize( 389 pydict_set_item_string_decref(dict, "raw_buf", PyString_FromStringAndSize(
390 (const char *)sample->raw_data, sample->raw_size)); 390 (const char *)sample->raw_data, sample->raw_size));
391 pydict_set_item_string_decref(dict, "comm", 391 pydict_set_item_string_decref(dict, "comm",
392 PyString_FromString(thread->comm)); 392 PyString_FromString(thread__comm_str(thread)));
393 if (al->map) { 393 if (al->map) {
394 pydict_set_item_string_decref(dict, "dso", 394 pydict_set_item_string_decref(dict, "dso",
395 PyString_FromString(al->map->dso->name)); 395 PyString_FromString(al->map->dso->name));
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 568b750c01f6..f36d24a02445 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -16,73 +16,34 @@
16#include "perf_regs.h" 16#include "perf_regs.h"
17#include "vdso.h" 17#include "vdso.h"
18 18
19static int perf_session__open(struct perf_session *self, bool force) 19static int perf_session__open(struct perf_session *session)
20{ 20{
21 struct stat input_stat; 21 struct perf_data_file *file = session->file;
22 22
23 if (!strcmp(self->filename, "-")) { 23 if (perf_session__read_header(session) < 0) {
24 self->fd_pipe = true;
25 self->fd = STDIN_FILENO;
26
27 if (perf_session__read_header(self) < 0)
28 pr_err("incompatible file format (rerun with -v to learn more)");
29
30 return 0;
31 }
32
33 self->fd = open(self->filename, O_RDONLY);
34 if (self->fd < 0) {
35 int err = errno;
36
37 pr_err("failed to open %s: %s", self->filename, strerror(err));
38 if (err == ENOENT && !strcmp(self->filename, "perf.data"))
39 pr_err(" (try 'perf record' first)");
40 pr_err("\n");
41 return -errno;
42 }
43
44 if (fstat(self->fd, &input_stat) < 0)
45 goto out_close;
46
47 if (!force && input_stat.st_uid && (input_stat.st_uid != geteuid())) {
48 pr_err("file %s not owned by current user or root\n",
49 self->filename);
50 goto out_close;
51 }
52
53 if (!input_stat.st_size) {
54 pr_info("zero-sized file (%s), nothing to do!\n",
55 self->filename);
56 goto out_close;
57 }
58
59 if (perf_session__read_header(self) < 0) {
60 pr_err("incompatible file format (rerun with -v to learn more)"); 24 pr_err("incompatible file format (rerun with -v to learn more)");
61 goto out_close; 25 return -1;
62 } 26 }
63 27
64 if (!perf_evlist__valid_sample_type(self->evlist)) { 28 if (perf_data_file__is_pipe(file))
29 return 0;
30
31 if (!perf_evlist__valid_sample_type(session->evlist)) {
65 pr_err("non matching sample_type"); 32 pr_err("non matching sample_type");
66 goto out_close; 33 return -1;
67 } 34 }
68 35
69 if (!perf_evlist__valid_sample_id_all(self->evlist)) { 36 if (!perf_evlist__valid_sample_id_all(session->evlist)) {
70 pr_err("non matching sample_id_all"); 37 pr_err("non matching sample_id_all");
71 goto out_close; 38 return -1;
72 } 39 }
73 40
74 if (!perf_evlist__valid_read_format(self->evlist)) { 41 if (!perf_evlist__valid_read_format(session->evlist)) {
75 pr_err("non matching read_format"); 42 pr_err("non matching read_format");
76 goto out_close; 43 return -1;
77 } 44 }
78 45
79 self->size = input_stat.st_size;
80 return 0; 46 return 0;
81
82out_close:
83 close(self->fd);
84 self->fd = -1;
85 return -1;
86} 47}
87 48
88void perf_session__set_id_hdr_size(struct perf_session *session) 49void perf_session__set_id_hdr_size(struct perf_session *session)
@@ -92,71 +53,70 @@ void perf_session__set_id_hdr_size(struct perf_session *session)
92 machines__set_id_hdr_size(&session->machines, id_hdr_size); 53 machines__set_id_hdr_size(&session->machines, id_hdr_size);
93} 54}
94 55
95int perf_session__create_kernel_maps(struct perf_session *self) 56int perf_session__create_kernel_maps(struct perf_session *session)
96{ 57{
97 int ret = machine__create_kernel_maps(&self->machines.host); 58 int ret = machine__create_kernel_maps(&session->machines.host);
98 59
99 if (ret >= 0) 60 if (ret >= 0)
100 ret = machines__create_guest_kernel_maps(&self->machines); 61 ret = machines__create_guest_kernel_maps(&session->machines);
101 return ret; 62 return ret;
102} 63}
103 64
104static void perf_session__destroy_kernel_maps(struct perf_session *self) 65static void perf_session__destroy_kernel_maps(struct perf_session *session)
105{ 66{
106 machines__destroy_kernel_maps(&self->machines); 67 machines__destroy_kernel_maps(&session->machines);
107} 68}
108 69
109struct perf_session *perf_session__new(const char *filename, int mode, 70struct perf_session *perf_session__new(struct perf_data_file *file,
110 bool force, bool repipe, 71 bool repipe, struct perf_tool *tool)
111 struct perf_tool *tool)
112{ 72{
113 struct perf_session *self; 73 struct perf_session *session = zalloc(sizeof(*session));
114 struct stat st;
115 size_t len;
116
117 if (!filename || !strlen(filename)) {
118 if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode))
119 filename = "-";
120 else
121 filename = "perf.data";
122 }
123 74
124 len = strlen(filename); 75 if (!session)
125 self = zalloc(sizeof(*self) + len);
126
127 if (self == NULL)
128 goto out; 76 goto out;
129 77
130 memcpy(self->filename, filename, len); 78 session->repipe = repipe;
131 self->repipe = repipe; 79 INIT_LIST_HEAD(&session->ordered_samples.samples);
132 INIT_LIST_HEAD(&self->ordered_samples.samples); 80 INIT_LIST_HEAD(&session->ordered_samples.sample_cache);
133 INIT_LIST_HEAD(&self->ordered_samples.sample_cache); 81 INIT_LIST_HEAD(&session->ordered_samples.to_free);
134 INIT_LIST_HEAD(&self->ordered_samples.to_free); 82 machines__init(&session->machines);
135 machines__init(&self->machines);
136 83
137 if (mode == O_RDONLY) { 84 if (file) {
138 if (perf_session__open(self, force) < 0) 85 if (perf_data_file__open(file))
139 goto out_delete; 86 goto out_delete;
140 perf_session__set_id_hdr_size(self); 87
141 } else if (mode == O_WRONLY) { 88 session->file = file;
89
90 if (perf_data_file__is_read(file)) {
91 if (perf_session__open(session) < 0)
92 goto out_close;
93
94 perf_session__set_id_hdr_size(session);
95 }
96 }
97
98 if (!file || perf_data_file__is_write(file)) {
142 /* 99 /*
143 * In O_RDONLY mode this will be performed when reading the 100 * In O_RDONLY mode this will be performed when reading the
144 * kernel MMAP event, in perf_event__process_mmap(). 101 * kernel MMAP event, in perf_event__process_mmap().
145 */ 102 */
146 if (perf_session__create_kernel_maps(self) < 0) 103 if (perf_session__create_kernel_maps(session) < 0)
147 goto out_delete; 104 goto out_delete;
148 } 105 }
149 106
150 if (tool && tool->ordering_requires_timestamps && 107 if (tool && tool->ordering_requires_timestamps &&
151 tool->ordered_samples && !perf_evlist__sample_id_all(self->evlist)) { 108 tool->ordered_samples && !perf_evlist__sample_id_all(session->evlist)) {
152 dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n"); 109 dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n");
153 tool->ordered_samples = false; 110 tool->ordered_samples = false;
154 } 111 }
155 112
156out: 113 return session;
157 return self; 114
158out_delete: 115 out_close:
159 perf_session__delete(self); 116 perf_data_file__close(file);
117 out_delete:
118 perf_session__delete(session);
119 out:
160 return NULL; 120 return NULL;
161} 121}
162 122
@@ -186,15 +146,16 @@ static void perf_session_env__delete(struct perf_session_env *env)
186 free(env->pmu_mappings); 146 free(env->pmu_mappings);
187} 147}
188 148
189void perf_session__delete(struct perf_session *self) 149void perf_session__delete(struct perf_session *session)
190{ 150{
191 perf_session__destroy_kernel_maps(self); 151 perf_session__destroy_kernel_maps(session);
192 perf_session__delete_dead_threads(self); 152 perf_session__delete_dead_threads(session);
193 perf_session__delete_threads(self); 153 perf_session__delete_threads(session);
194 perf_session_env__delete(&self->header.env); 154 perf_session_env__delete(&session->header.env);
195 machines__exit(&self->machines); 155 machines__exit(&session->machines);
196 close(self->fd); 156 if (session->file)
197 free(self); 157 perf_data_file__close(session->file);
158 free(session);
198 vdso__exit(); 159 vdso__exit();
199} 160}
200 161
@@ -397,6 +358,17 @@ static void perf_event__read_swap(union perf_event *event, bool sample_id_all)
397 swap_sample_id_all(event, &event->read + 1); 358 swap_sample_id_all(event, &event->read + 1);
398} 359}
399 360
361static void perf_event__throttle_swap(union perf_event *event,
362 bool sample_id_all)
363{
364 event->throttle.time = bswap_64(event->throttle.time);
365 event->throttle.id = bswap_64(event->throttle.id);
366 event->throttle.stream_id = bswap_64(event->throttle.stream_id);
367
368 if (sample_id_all)
369 swap_sample_id_all(event, &event->throttle + 1);
370}
371
400static u8 revbyte(u8 b) 372static u8 revbyte(u8 b)
401{ 373{
402 int rev = (b >> 4) | ((b & 0xf) << 4); 374 int rev = (b >> 4) | ((b & 0xf) << 4);
@@ -442,6 +414,9 @@ void perf_event__attr_swap(struct perf_event_attr *attr)
442 attr->bp_type = bswap_32(attr->bp_type); 414 attr->bp_type = bswap_32(attr->bp_type);
443 attr->bp_addr = bswap_64(attr->bp_addr); 415 attr->bp_addr = bswap_64(attr->bp_addr);
444 attr->bp_len = bswap_64(attr->bp_len); 416 attr->bp_len = bswap_64(attr->bp_len);
417 attr->branch_sample_type = bswap_64(attr->branch_sample_type);
418 attr->sample_regs_user = bswap_64(attr->sample_regs_user);
419 attr->sample_stack_user = bswap_32(attr->sample_stack_user);
445 420
446 swap_bitfield((u8 *) (&attr->read_format + 1), sizeof(u64)); 421 swap_bitfield((u8 *) (&attr->read_format + 1), sizeof(u64));
447} 422}
@@ -482,6 +457,8 @@ static perf_event__swap_op perf_event__swap_ops[] = {
482 [PERF_RECORD_EXIT] = perf_event__task_swap, 457 [PERF_RECORD_EXIT] = perf_event__task_swap,
483 [PERF_RECORD_LOST] = perf_event__all64_swap, 458 [PERF_RECORD_LOST] = perf_event__all64_swap,
484 [PERF_RECORD_READ] = perf_event__read_swap, 459 [PERF_RECORD_READ] = perf_event__read_swap,
460 [PERF_RECORD_THROTTLE] = perf_event__throttle_swap,
461 [PERF_RECORD_UNTHROTTLE] = perf_event__throttle_swap,
485 [PERF_RECORD_SAMPLE] = perf_event__all64_swap, 462 [PERF_RECORD_SAMPLE] = perf_event__all64_swap,
486 [PERF_RECORD_HEADER_ATTR] = perf_event__hdr_attr_swap, 463 [PERF_RECORD_HEADER_ATTR] = perf_event__hdr_attr_swap,
487 [PERF_RECORD_HEADER_EVENT_TYPE] = perf_event__event_type_swap, 464 [PERF_RECORD_HEADER_EVENT_TYPE] = perf_event__event_type_swap,
@@ -525,13 +502,16 @@ static int flush_sample_queue(struct perf_session *s,
525 struct perf_sample sample; 502 struct perf_sample sample;
526 u64 limit = os->next_flush; 503 u64 limit = os->next_flush;
527 u64 last_ts = os->last_sample ? os->last_sample->timestamp : 0ULL; 504 u64 last_ts = os->last_sample ? os->last_sample->timestamp : 0ULL;
528 unsigned idx = 0, progress_next = os->nr_samples / 16;
529 bool show_progress = limit == ULLONG_MAX; 505 bool show_progress = limit == ULLONG_MAX;
506 struct ui_progress prog;
530 int ret; 507 int ret;
531 508
532 if (!tool->ordered_samples || !limit) 509 if (!tool->ordered_samples || !limit)
533 return 0; 510 return 0;
534 511
512 if (show_progress)
513 ui_progress__init(&prog, os->nr_samples, "Processing time ordered events...");
514
535 list_for_each_entry_safe(iter, tmp, head, list) { 515 list_for_each_entry_safe(iter, tmp, head, list) {
536 if (session_done()) 516 if (session_done())
537 return 0; 517 return 0;
@@ -552,11 +532,9 @@ static int flush_sample_queue(struct perf_session *s,
552 os->last_flush = iter->timestamp; 532 os->last_flush = iter->timestamp;
553 list_del(&iter->list); 533 list_del(&iter->list);
554 list_add(&iter->list, &os->sample_cache); 534 list_add(&iter->list, &os->sample_cache);
555 if (show_progress && (++idx >= progress_next)) { 535
556 progress_next += os->nr_samples / 16; 536 if (show_progress)
557 ui_progress__update(idx, os->nr_samples, 537 ui_progress__update(&prog, 1);
558 "Processing time ordered events...");
559 }
560 } 538 }
561 539
562 if (list_empty(head)) { 540 if (list_empty(head)) {
@@ -860,6 +838,9 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event,
860 if (sample_type & PERF_SAMPLE_DATA_SRC) 838 if (sample_type & PERF_SAMPLE_DATA_SRC)
861 printf(" . data_src: 0x%"PRIx64"\n", sample->data_src); 839 printf(" . data_src: 0x%"PRIx64"\n", sample->data_src);
862 840
841 if (sample_type & PERF_SAMPLE_TRANSACTION)
842 printf("... transaction: %" PRIx64 "\n", sample->transaction);
843
863 if (sample_type & PERF_SAMPLE_READ) 844 if (sample_type & PERF_SAMPLE_READ)
864 sample_read__printf(sample, evsel->attr.read_format); 845 sample_read__printf(sample, evsel->attr.read_format);
865} 846}
@@ -1031,6 +1012,7 @@ static int perf_session_deliver_event(struct perf_session *session,
1031static int perf_session__process_user_event(struct perf_session *session, union perf_event *event, 1012static int perf_session__process_user_event(struct perf_session *session, union perf_event *event,
1032 struct perf_tool *tool, u64 file_offset) 1013 struct perf_tool *tool, u64 file_offset)
1033{ 1014{
1015 int fd = perf_data_file__fd(session->file);
1034 int err; 1016 int err;
1035 1017
1036 dump_event(session, event, file_offset, NULL); 1018 dump_event(session, event, file_offset, NULL);
@@ -1044,7 +1026,7 @@ static int perf_session__process_user_event(struct perf_session *session, union
1044 return err; 1026 return err;
1045 case PERF_RECORD_HEADER_TRACING_DATA: 1027 case PERF_RECORD_HEADER_TRACING_DATA:
1046 /* setup for reading amidst mmap */ 1028 /* setup for reading amidst mmap */
1047 lseek(session->fd, file_offset, SEEK_SET); 1029 lseek(fd, file_offset, SEEK_SET);
1048 return tool->tracing_data(tool, event, session); 1030 return tool->tracing_data(tool, event, session);
1049 case PERF_RECORD_HEADER_BUILD_ID: 1031 case PERF_RECORD_HEADER_BUILD_ID:
1050 return tool->build_id(tool, event, session); 1032 return tool->build_id(tool, event, session);
@@ -1101,11 +1083,11 @@ static int perf_session__process_event(struct perf_session *session,
1101 file_offset); 1083 file_offset);
1102} 1084}
1103 1085
1104void perf_event_header__bswap(struct perf_event_header *self) 1086void perf_event_header__bswap(struct perf_event_header *hdr)
1105{ 1087{
1106 self->type = bswap_32(self->type); 1088 hdr->type = bswap_32(hdr->type);
1107 self->misc = bswap_16(self->misc); 1089 hdr->misc = bswap_16(hdr->misc);
1108 self->size = bswap_16(self->size); 1090 hdr->size = bswap_16(hdr->size);
1109} 1091}
1110 1092
1111struct thread *perf_session__findnew(struct perf_session *session, pid_t pid) 1093struct thread *perf_session__findnew(struct perf_session *session, pid_t pid)
@@ -1113,11 +1095,11 @@ struct thread *perf_session__findnew(struct perf_session *session, pid_t pid)
1113 return machine__findnew_thread(&session->machines.host, 0, pid); 1095 return machine__findnew_thread(&session->machines.host, 0, pid);
1114} 1096}
1115 1097
1116static struct thread *perf_session__register_idle_thread(struct perf_session *self) 1098static struct thread *perf_session__register_idle_thread(struct perf_session *session)
1117{ 1099{
1118 struct thread *thread = perf_session__findnew(self, 0); 1100 struct thread *thread = perf_session__findnew(session, 0);
1119 1101
1120 if (thread == NULL || thread__set_comm(thread, "swapper")) { 1102 if (thread == NULL || thread__set_comm(thread, "swapper", 0)) {
1121 pr_err("problem inserting idle task.\n"); 1103 pr_err("problem inserting idle task.\n");
1122 thread = NULL; 1104 thread = NULL;
1123 } 1105 }
@@ -1167,9 +1149,10 @@ static void perf_session__warn_about_errors(const struct perf_session *session,
1167 1149
1168volatile int session_done; 1150volatile int session_done;
1169 1151
1170static int __perf_session__process_pipe_events(struct perf_session *self, 1152static int __perf_session__process_pipe_events(struct perf_session *session,
1171 struct perf_tool *tool) 1153 struct perf_tool *tool)
1172{ 1154{
1155 int fd = perf_data_file__fd(session->file);
1173 union perf_event *event; 1156 union perf_event *event;
1174 uint32_t size, cur_size = 0; 1157 uint32_t size, cur_size = 0;
1175 void *buf = NULL; 1158 void *buf = NULL;
@@ -1188,7 +1171,7 @@ static int __perf_session__process_pipe_events(struct perf_session *self,
1188 return -errno; 1171 return -errno;
1189more: 1172more:
1190 event = buf; 1173 event = buf;
1191 err = readn(self->fd, event, sizeof(struct perf_event_header)); 1174 err = readn(fd, event, sizeof(struct perf_event_header));
1192 if (err <= 0) { 1175 if (err <= 0) {
1193 if (err == 0) 1176 if (err == 0)
1194 goto done; 1177 goto done;
@@ -1197,7 +1180,7 @@ more:
1197 goto out_err; 1180 goto out_err;
1198 } 1181 }
1199 1182
1200 if (self->header.needs_swap) 1183 if (session->header.needs_swap)
1201 perf_event_header__bswap(&event->header); 1184 perf_event_header__bswap(&event->header);
1202 1185
1203 size = event->header.size; 1186 size = event->header.size;
@@ -1220,7 +1203,7 @@ more:
1220 p += sizeof(struct perf_event_header); 1203 p += sizeof(struct perf_event_header);
1221 1204
1222 if (size - sizeof(struct perf_event_header)) { 1205 if (size - sizeof(struct perf_event_header)) {
1223 err = readn(self->fd, p, size - sizeof(struct perf_event_header)); 1206 err = readn(fd, p, size - sizeof(struct perf_event_header));
1224 if (err <= 0) { 1207 if (err <= 0) {
1225 if (err == 0) { 1208 if (err == 0) {
1226 pr_err("unexpected end of event stream\n"); 1209 pr_err("unexpected end of event stream\n");
@@ -1232,7 +1215,7 @@ more:
1232 } 1215 }
1233 } 1216 }
1234 1217
1235 if ((skip = perf_session__process_event(self, event, tool, head)) < 0) { 1218 if ((skip = perf_session__process_event(session, event, tool, head)) < 0) {
1236 pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n", 1219 pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n",
1237 head, event->header.size, event->header.type); 1220 head, event->header.size, event->header.type);
1238 err = -EINVAL; 1221 err = -EINVAL;
@@ -1247,11 +1230,13 @@ more:
1247 if (!session_done()) 1230 if (!session_done())
1248 goto more; 1231 goto more;
1249done: 1232done:
1250 err = 0; 1233 /* do the final flush for ordered samples */
1234 session->ordered_samples.next_flush = ULLONG_MAX;
1235 err = flush_sample_queue(session, tool);
1251out_err: 1236out_err:
1252 free(buf); 1237 free(buf);
1253 perf_session__warn_about_errors(self, tool); 1238 perf_session__warn_about_errors(session, tool);
1254 perf_session_free_sample_buffers(self); 1239 perf_session_free_sample_buffers(session);
1255 return err; 1240 return err;
1256} 1241}
1257 1242
@@ -1299,12 +1284,14 @@ int __perf_session__process_events(struct perf_session *session,
1299 u64 data_offset, u64 data_size, 1284 u64 data_offset, u64 data_size,
1300 u64 file_size, struct perf_tool *tool) 1285 u64 file_size, struct perf_tool *tool)
1301{ 1286{
1302 u64 head, page_offset, file_offset, file_pos, progress_next; 1287 int fd = perf_data_file__fd(session->file);
1288 u64 head, page_offset, file_offset, file_pos;
1303 int err, mmap_prot, mmap_flags, map_idx = 0; 1289 int err, mmap_prot, mmap_flags, map_idx = 0;
1304 size_t mmap_size; 1290 size_t mmap_size;
1305 char *buf, *mmaps[NUM_MMAPS]; 1291 char *buf, *mmaps[NUM_MMAPS];
1306 union perf_event *event; 1292 union perf_event *event;
1307 uint32_t size; 1293 uint32_t size;
1294 struct ui_progress prog;
1308 1295
1309 perf_tool__fill_defaults(tool); 1296 perf_tool__fill_defaults(tool);
1310 1297
@@ -1315,7 +1302,7 @@ int __perf_session__process_events(struct perf_session *session,
1315 if (data_size && (data_offset + data_size < file_size)) 1302 if (data_size && (data_offset + data_size < file_size))
1316 file_size = data_offset + data_size; 1303 file_size = data_offset + data_size;
1317 1304
1318 progress_next = file_size / 16; 1305 ui_progress__init(&prog, file_size, "Processing events...");
1319 1306
1320 mmap_size = MMAP_SIZE; 1307 mmap_size = MMAP_SIZE;
1321 if (mmap_size > file_size) 1308 if (mmap_size > file_size)
@@ -1331,7 +1318,7 @@ int __perf_session__process_events(struct perf_session *session,
1331 mmap_flags = MAP_PRIVATE; 1318 mmap_flags = MAP_PRIVATE;
1332 } 1319 }
1333remap: 1320remap:
1334 buf = mmap(NULL, mmap_size, mmap_prot, mmap_flags, session->fd, 1321 buf = mmap(NULL, mmap_size, mmap_prot, mmap_flags, fd,
1335 file_offset); 1322 file_offset);
1336 if (buf == MAP_FAILED) { 1323 if (buf == MAP_FAILED) {
1337 pr_err("failed to mmap file\n"); 1324 pr_err("failed to mmap file\n");
@@ -1370,19 +1357,15 @@ more:
1370 head += size; 1357 head += size;
1371 file_pos += size; 1358 file_pos += size;
1372 1359
1373 if (file_pos >= progress_next) { 1360 ui_progress__update(&prog, size);
1374 progress_next += file_size / 16;
1375 ui_progress__update(file_pos, file_size,
1376 "Processing events...");
1377 }
1378 1361
1379 err = 0;
1380 if (session_done()) 1362 if (session_done())
1381 goto out_err; 1363 goto out;
1382 1364
1383 if (file_pos < file_size) 1365 if (file_pos < file_size)
1384 goto more; 1366 goto more;
1385 1367
1368out:
1386 /* do the final flush for ordered samples */ 1369 /* do the final flush for ordered samples */
1387 session->ordered_samples.next_flush = ULLONG_MAX; 1370 session->ordered_samples.next_flush = ULLONG_MAX;
1388 err = flush_sample_queue(session, tool); 1371 err = flush_sample_queue(session, tool);
@@ -1393,21 +1376,22 @@ out_err:
1393 return err; 1376 return err;
1394} 1377}
1395 1378
1396int perf_session__process_events(struct perf_session *self, 1379int perf_session__process_events(struct perf_session *session,
1397 struct perf_tool *tool) 1380 struct perf_tool *tool)
1398{ 1381{
1382 u64 size = perf_data_file__size(session->file);
1399 int err; 1383 int err;
1400 1384
1401 if (perf_session__register_idle_thread(self) == NULL) 1385 if (perf_session__register_idle_thread(session) == NULL)
1402 return -ENOMEM; 1386 return -ENOMEM;
1403 1387
1404 if (!self->fd_pipe) 1388 if (!perf_data_file__is_pipe(session->file))
1405 err = __perf_session__process_events(self, 1389 err = __perf_session__process_events(session,
1406 self->header.data_offset, 1390 session->header.data_offset,
1407 self->header.data_size, 1391 session->header.data_size,
1408 self->size, tool); 1392 size, tool);
1409 else 1393 else
1410 err = __perf_session__process_pipe_events(self, tool); 1394 err = __perf_session__process_pipe_events(session, tool);
1411 1395
1412 return err; 1396 return err;
1413} 1397}
@@ -1456,15 +1440,15 @@ int maps__set_kallsyms_ref_reloc_sym(struct map **maps,
1456 return 0; 1440 return 0;
1457} 1441}
1458 1442
1459size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp) 1443size_t perf_session__fprintf_dsos(struct perf_session *session, FILE *fp)
1460{ 1444{
1461 return machines__fprintf_dsos(&self->machines, fp); 1445 return machines__fprintf_dsos(&session->machines, fp);
1462} 1446}
1463 1447
1464size_t perf_session__fprintf_dsos_buildid(struct perf_session *self, FILE *fp, 1448size_t perf_session__fprintf_dsos_buildid(struct perf_session *session, FILE *fp,
1465 bool (skip)(struct dso *dso, int parm), int parm) 1449 bool (skip)(struct dso *dso, int parm), int parm)
1466{ 1450{
1467 return machines__fprintf_dsos_buildid(&self->machines, fp, skip, parm); 1451 return machines__fprintf_dsos_buildid(&session->machines, fp, skip, parm);
1468} 1452}
1469 1453
1470size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp) 1454size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp)
@@ -1525,7 +1509,8 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event,
1525 if (symbol_conf.use_callchain && sample->callchain) { 1509 if (symbol_conf.use_callchain && sample->callchain) {
1526 1510
1527 if (machine__resolve_callchain(machine, evsel, al.thread, 1511 if (machine__resolve_callchain(machine, evsel, al.thread,
1528 sample, NULL, NULL) != 0) { 1512 sample, NULL, NULL,
1513 PERF_MAX_STACK_DEPTH) != 0) {
1529 if (verbose) 1514 if (verbose)
1530 error("Failed to resolve callchain. Skipping\n"); 1515 error("Failed to resolve callchain. Skipping\n");
1531 return; 1516 return;
@@ -1629,13 +1614,14 @@ int perf_session__cpu_bitmap(struct perf_session *session,
1629void perf_session__fprintf_info(struct perf_session *session, FILE *fp, 1614void perf_session__fprintf_info(struct perf_session *session, FILE *fp,
1630 bool full) 1615 bool full)
1631{ 1616{
1617 int fd = perf_data_file__fd(session->file);
1632 struct stat st; 1618 struct stat st;
1633 int ret; 1619 int ret;
1634 1620
1635 if (session == NULL || fp == NULL) 1621 if (session == NULL || fp == NULL)
1636 return; 1622 return;
1637 1623
1638 ret = fstat(session->fd, &st); 1624 ret = fstat(fd, &st);
1639 if (ret == -1) 1625 if (ret == -1)
1640 return; 1626 return;
1641 1627
@@ -1664,9 +1650,9 @@ int __perf_session__set_tracepoints_handlers(struct perf_session *session,
1664 continue; 1650 continue;
1665 1651
1666 err = -EEXIST; 1652 err = -EEXIST;
1667 if (evsel->handler.func != NULL) 1653 if (evsel->handler != NULL)
1668 goto out; 1654 goto out;
1669 evsel->handler.func = assocs[i].handler; 1655 evsel->handler = assocs[i].handler;
1670 } 1656 }
1671 1657
1672 err = 0; 1658 err = 0;
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 04bf7373a7e5..50f640958f0f 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -7,6 +7,7 @@
7#include "machine.h" 7#include "machine.h"
8#include "symbol.h" 8#include "symbol.h"
9#include "thread.h" 9#include "thread.h"
10#include "data.h"
10#include <linux/rbtree.h> 11#include <linux/rbtree.h>
11#include <linux/perf_event.h> 12#include <linux/perf_event.h>
12 13
@@ -29,16 +30,13 @@ struct ordered_samples {
29 30
30struct perf_session { 31struct perf_session {
31 struct perf_header header; 32 struct perf_header header;
32 unsigned long size;
33 struct machines machines; 33 struct machines machines;
34 struct perf_evlist *evlist; 34 struct perf_evlist *evlist;
35 struct pevent *pevent; 35 struct pevent *pevent;
36 struct events_stats stats; 36 struct events_stats stats;
37 int fd;
38 bool fd_pipe;
39 bool repipe; 37 bool repipe;
40 struct ordered_samples ordered_samples; 38 struct ordered_samples ordered_samples;
41 char filename[1]; 39 struct perf_data_file *file;
42}; 40};
43 41
44#define PRINT_IP_OPT_IP (1<<0) 42#define PRINT_IP_OPT_IP (1<<0)
@@ -49,17 +47,16 @@ struct perf_session {
49 47
50struct perf_tool; 48struct perf_tool;
51 49
52struct perf_session *perf_session__new(const char *filename, int mode, 50struct perf_session *perf_session__new(struct perf_data_file *file,
53 bool force, bool repipe, 51 bool repipe, struct perf_tool *tool);
54 struct perf_tool *tool);
55void perf_session__delete(struct perf_session *session); 52void perf_session__delete(struct perf_session *session);
56 53
57void perf_event_header__bswap(struct perf_event_header *self); 54void perf_event_header__bswap(struct perf_event_header *hdr);
58 55
59int __perf_session__process_events(struct perf_session *self, 56int __perf_session__process_events(struct perf_session *session,
60 u64 data_offset, u64 data_size, u64 size, 57 u64 data_offset, u64 data_size, u64 size,
61 struct perf_tool *tool); 58 struct perf_tool *tool);
62int perf_session__process_events(struct perf_session *self, 59int perf_session__process_events(struct perf_session *session,
63 struct perf_tool *tool); 60 struct perf_tool *tool);
64 61
65int perf_session_queue_event(struct perf_session *s, union perf_event *event, 62int perf_session_queue_event(struct perf_session *s, union perf_event *event,
@@ -67,37 +64,38 @@ int perf_session_queue_event(struct perf_session *s, union perf_event *event,
67 64
68void perf_tool__fill_defaults(struct perf_tool *tool); 65void perf_tool__fill_defaults(struct perf_tool *tool);
69 66
70int perf_session__resolve_callchain(struct perf_session *self, struct perf_evsel *evsel, 67int perf_session__resolve_callchain(struct perf_session *session,
68 struct perf_evsel *evsel,
71 struct thread *thread, 69 struct thread *thread,
72 struct ip_callchain *chain, 70 struct ip_callchain *chain,
73 struct symbol **parent); 71 struct symbol **parent);
74 72
75bool perf_session__has_traces(struct perf_session *self, const char *msg); 73bool perf_session__has_traces(struct perf_session *session, const char *msg);
76 74
77void mem_bswap_64(void *src, int byte_size); 75void mem_bswap_64(void *src, int byte_size);
78void mem_bswap_32(void *src, int byte_size); 76void mem_bswap_32(void *src, int byte_size);
79void perf_event__attr_swap(struct perf_event_attr *attr); 77void perf_event__attr_swap(struct perf_event_attr *attr);
80 78
81int perf_session__create_kernel_maps(struct perf_session *self); 79int perf_session__create_kernel_maps(struct perf_session *session);
82 80
83void perf_session__set_id_hdr_size(struct perf_session *session); 81void perf_session__set_id_hdr_size(struct perf_session *session);
84 82
85static inline 83static inline
86struct machine *perf_session__find_machine(struct perf_session *self, pid_t pid) 84struct machine *perf_session__find_machine(struct perf_session *session, pid_t pid)
87{ 85{
88 return machines__find(&self->machines, pid); 86 return machines__find(&session->machines, pid);
89} 87}
90 88
91static inline 89static inline
92struct machine *perf_session__findnew_machine(struct perf_session *self, pid_t pid) 90struct machine *perf_session__findnew_machine(struct perf_session *session, pid_t pid)
93{ 91{
94 return machines__findnew(&self->machines, pid); 92 return machines__findnew(&session->machines, pid);
95} 93}
96 94
97struct thread *perf_session__findnew(struct perf_session *self, pid_t pid); 95struct thread *perf_session__findnew(struct perf_session *session, pid_t pid);
98size_t perf_session__fprintf(struct perf_session *self, FILE *fp); 96size_t perf_session__fprintf(struct perf_session *session, FILE *fp);
99 97
100size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp); 98size_t perf_session__fprintf_dsos(struct perf_session *session, FILE *fp);
101 99
102size_t perf_session__fprintf_dsos_buildid(struct perf_session *session, FILE *fp, 100size_t perf_session__fprintf_dsos_buildid(struct perf_session *session, FILE *fp,
103 bool (fn)(struct dso *dso, int parm), int parm); 101 bool (fn)(struct dso *dso, int parm), int parm);
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 5f118a089519..3c1b75c8b9a6 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -1,5 +1,6 @@
1#include "sort.h" 1#include "sort.h"
2#include "hist.h" 2#include "hist.h"
3#include "comm.h"
3#include "symbol.h" 4#include "symbol.h"
4 5
5regex_t parent_regex; 6regex_t parent_regex;
@@ -42,7 +43,7 @@ static int repsep_snprintf(char *bf, size_t size, const char *fmt, ...)
42 return n; 43 return n;
43} 44}
44 45
45static int64_t cmp_null(void *l, void *r) 46static int64_t cmp_null(const void *l, const void *r)
46{ 47{
47 if (!l && !r) 48 if (!l && !r)
48 return 0; 49 return 0;
@@ -60,11 +61,12 @@ sort__thread_cmp(struct hist_entry *left, struct hist_entry *right)
60 return right->thread->tid - left->thread->tid; 61 return right->thread->tid - left->thread->tid;
61} 62}
62 63
63static int hist_entry__thread_snprintf(struct hist_entry *self, char *bf, 64static int hist_entry__thread_snprintf(struct hist_entry *he, char *bf,
64 size_t size, unsigned int width) 65 size_t size, unsigned int width)
65{ 66{
67 const char *comm = thread__comm_str(he->thread);
66 return repsep_snprintf(bf, size, "%*s:%5d", width - 6, 68 return repsep_snprintf(bf, size, "%*s:%5d", width - 6,
67 self->thread->comm ?: "", self->thread->tid); 69 comm ?: "", he->thread->tid);
68} 70}
69 71
70struct sort_entry sort_thread = { 72struct sort_entry sort_thread = {
@@ -79,25 +81,21 @@ struct sort_entry sort_thread = {
79static int64_t 81static int64_t
80sort__comm_cmp(struct hist_entry *left, struct hist_entry *right) 82sort__comm_cmp(struct hist_entry *left, struct hist_entry *right)
81{ 83{
82 return right->thread->tid - left->thread->tid; 84 /* Compare the addr that should be unique among comm */
85 return comm__str(right->comm) - comm__str(left->comm);
83} 86}
84 87
85static int64_t 88static int64_t
86sort__comm_collapse(struct hist_entry *left, struct hist_entry *right) 89sort__comm_collapse(struct hist_entry *left, struct hist_entry *right)
87{ 90{
88 char *comm_l = left->thread->comm; 91 /* Compare the addr that should be unique among comm */
89 char *comm_r = right->thread->comm; 92 return comm__str(right->comm) - comm__str(left->comm);
90
91 if (!comm_l || !comm_r)
92 return cmp_null(comm_l, comm_r);
93
94 return strcmp(comm_l, comm_r);
95} 93}
96 94
97static int hist_entry__comm_snprintf(struct hist_entry *self, char *bf, 95static int hist_entry__comm_snprintf(struct hist_entry *he, char *bf,
98 size_t size, unsigned int width) 96 size_t size, unsigned int width)
99{ 97{
100 return repsep_snprintf(bf, size, "%*s", width, self->thread->comm); 98 return repsep_snprintf(bf, size, "%*s", width, comm__str(he->comm));
101} 99}
102 100
103struct sort_entry sort_comm = { 101struct sort_entry sort_comm = {
@@ -148,10 +146,10 @@ static int _hist_entry__dso_snprintf(struct map *map, char *bf,
148 return repsep_snprintf(bf, size, "%-*s", width, "[unknown]"); 146 return repsep_snprintf(bf, size, "%-*s", width, "[unknown]");
149} 147}
150 148
151static int hist_entry__dso_snprintf(struct hist_entry *self, char *bf, 149static int hist_entry__dso_snprintf(struct hist_entry *he, char *bf,
152 size_t size, unsigned int width) 150 size_t size, unsigned int width)
153{ 151{
154 return _hist_entry__dso_snprintf(self->ms.map, bf, size, width); 152 return _hist_entry__dso_snprintf(he->ms.map, bf, size, width);
155} 153}
156 154
157struct sort_entry sort_dso = { 155struct sort_entry sort_dso = {
@@ -182,9 +180,19 @@ static int64_t _sort__sym_cmp(struct symbol *sym_l, struct symbol *sym_r)
182static int64_t 180static int64_t
183sort__sym_cmp(struct hist_entry *left, struct hist_entry *right) 181sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
184{ 182{
183 int64_t ret;
184
185 if (!left->ms.sym && !right->ms.sym) 185 if (!left->ms.sym && !right->ms.sym)
186 return right->level - left->level; 186 return right->level - left->level;
187 187
188 /*
189 * comparing symbol address alone is not enough since it's a
190 * relative address within a dso.
191 */
192 ret = sort__dso_cmp(left, right);
193 if (ret != 0)
194 return ret;
195
188 return _sort__sym_cmp(left->ms.sym, right->ms.sym); 196 return _sort__sym_cmp(left->ms.sym, right->ms.sym);
189} 197}
190 198
@@ -224,11 +232,11 @@ static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym,
224 return ret; 232 return ret;
225} 233}
226 234
227static int hist_entry__sym_snprintf(struct hist_entry *self, char *bf, 235static int hist_entry__sym_snprintf(struct hist_entry *he, char *bf,
228 size_t size, unsigned int width) 236 size_t size, unsigned int width)
229{ 237{
230 return _hist_entry__sym_snprintf(self->ms.map, self->ms.sym, self->ip, 238 return _hist_entry__sym_snprintf(he->ms.map, he->ms.sym, he->ip,
231 self->level, bf, size, width); 239 he->level, bf, size, width);
232} 240}
233 241
234struct sort_entry sort_sym = { 242struct sort_entry sort_sym = {
@@ -243,50 +251,32 @@ struct sort_entry sort_sym = {
243static int64_t 251static int64_t
244sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right) 252sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right)
245{ 253{
246 return (int64_t)(right->ip - left->ip); 254 if (!left->srcline) {
255 if (!left->ms.map)
256 left->srcline = SRCLINE_UNKNOWN;
257 else {
258 struct map *map = left->ms.map;
259 left->srcline = get_srcline(map->dso,
260 map__rip_2objdump(map, left->ip));
261 }
262 }
263 if (!right->srcline) {
264 if (!right->ms.map)
265 right->srcline = SRCLINE_UNKNOWN;
266 else {
267 struct map *map = right->ms.map;
268 right->srcline = get_srcline(map->dso,
269 map__rip_2objdump(map, right->ip));
270 }
271 }
272 return strcmp(left->srcline, right->srcline);
247} 273}
248 274
249static int hist_entry__srcline_snprintf(struct hist_entry *self, char *bf, 275static int hist_entry__srcline_snprintf(struct hist_entry *he, char *bf,
250 size_t size, 276 size_t size,
251 unsigned int width __maybe_unused) 277 unsigned int width __maybe_unused)
252{ 278{
253 FILE *fp = NULL; 279 return repsep_snprintf(bf, size, "%s", he->srcline);
254 char cmd[PATH_MAX + 2], *path = self->srcline, *nl;
255 size_t line_len;
256
257 if (path != NULL)
258 goto out_path;
259
260 if (!self->ms.map)
261 goto out_ip;
262
263 if (!strncmp(self->ms.map->dso->long_name, "/tmp/perf-", 10))
264 goto out_ip;
265
266 snprintf(cmd, sizeof(cmd), "addr2line -e %s %016" PRIx64,
267 self->ms.map->dso->long_name, self->ip);
268 fp = popen(cmd, "r");
269 if (!fp)
270 goto out_ip;
271
272 if (getline(&path, &line_len, fp) < 0 || !line_len)
273 goto out_ip;
274 self->srcline = strdup(path);
275 if (self->srcline == NULL)
276 goto out_ip;
277
278 nl = strchr(self->srcline, '\n');
279 if (nl != NULL)
280 *nl = '\0';
281 path = self->srcline;
282out_path:
283 if (fp)
284 pclose(fp);
285 return repsep_snprintf(bf, size, "%s", path);
286out_ip:
287 if (fp)
288 pclose(fp);
289 return repsep_snprintf(bf, size, "%-#*llx", BITS_PER_LONG / 4, self->ip);
290} 280}
291 281
292struct sort_entry sort_srcline = { 282struct sort_entry sort_srcline = {
@@ -310,11 +300,11 @@ sort__parent_cmp(struct hist_entry *left, struct hist_entry *right)
310 return strcmp(sym_l->name, sym_r->name); 300 return strcmp(sym_l->name, sym_r->name);
311} 301}
312 302
313static int hist_entry__parent_snprintf(struct hist_entry *self, char *bf, 303static int hist_entry__parent_snprintf(struct hist_entry *he, char *bf,
314 size_t size, unsigned int width) 304 size_t size, unsigned int width)
315{ 305{
316 return repsep_snprintf(bf, size, "%-*s", width, 306 return repsep_snprintf(bf, size, "%-*s", width,
317 self->parent ? self->parent->name : "[other]"); 307 he->parent ? he->parent->name : "[other]");
318} 308}
319 309
320struct sort_entry sort_parent = { 310struct sort_entry sort_parent = {
@@ -332,10 +322,10 @@ sort__cpu_cmp(struct hist_entry *left, struct hist_entry *right)
332 return right->cpu - left->cpu; 322 return right->cpu - left->cpu;
333} 323}
334 324
335static int hist_entry__cpu_snprintf(struct hist_entry *self, char *bf, 325static int hist_entry__cpu_snprintf(struct hist_entry *he, char *bf,
336 size_t size, unsigned int width) 326 size_t size, unsigned int width)
337{ 327{
338 return repsep_snprintf(bf, size, "%*d", width, self->cpu); 328 return repsep_snprintf(bf, size, "%*d", width, he->cpu);
339} 329}
340 330
341struct sort_entry sort_cpu = { 331struct sort_entry sort_cpu = {
@@ -354,10 +344,10 @@ sort__dso_from_cmp(struct hist_entry *left, struct hist_entry *right)
354 right->branch_info->from.map); 344 right->branch_info->from.map);
355} 345}
356 346
357static int hist_entry__dso_from_snprintf(struct hist_entry *self, char *bf, 347static int hist_entry__dso_from_snprintf(struct hist_entry *he, char *bf,
358 size_t size, unsigned int width) 348 size_t size, unsigned int width)
359{ 349{
360 return _hist_entry__dso_snprintf(self->branch_info->from.map, 350 return _hist_entry__dso_snprintf(he->branch_info->from.map,
361 bf, size, width); 351 bf, size, width);
362} 352}
363 353
@@ -368,10 +358,10 @@ sort__dso_to_cmp(struct hist_entry *left, struct hist_entry *right)
368 right->branch_info->to.map); 358 right->branch_info->to.map);
369} 359}
370 360
371static int hist_entry__dso_to_snprintf(struct hist_entry *self, char *bf, 361static int hist_entry__dso_to_snprintf(struct hist_entry *he, char *bf,
372 size_t size, unsigned int width) 362 size_t size, unsigned int width)
373{ 363{
374 return _hist_entry__dso_snprintf(self->branch_info->to.map, 364 return _hist_entry__dso_snprintf(he->branch_info->to.map,
375 bf, size, width); 365 bf, size, width);
376} 366}
377 367
@@ -399,21 +389,21 @@ sort__sym_to_cmp(struct hist_entry *left, struct hist_entry *right)
399 return _sort__sym_cmp(to_l->sym, to_r->sym); 389 return _sort__sym_cmp(to_l->sym, to_r->sym);
400} 390}
401 391
402static int hist_entry__sym_from_snprintf(struct hist_entry *self, char *bf, 392static int hist_entry__sym_from_snprintf(struct hist_entry *he, char *bf,
403 size_t size, unsigned int width) 393 size_t size, unsigned int width)
404{ 394{
405 struct addr_map_symbol *from = &self->branch_info->from; 395 struct addr_map_symbol *from = &he->branch_info->from;
406 return _hist_entry__sym_snprintf(from->map, from->sym, from->addr, 396 return _hist_entry__sym_snprintf(from->map, from->sym, from->addr,
407 self->level, bf, size, width); 397 he->level, bf, size, width);
408 398
409} 399}
410 400
411static int hist_entry__sym_to_snprintf(struct hist_entry *self, char *bf, 401static int hist_entry__sym_to_snprintf(struct hist_entry *he, char *bf,
412 size_t size, unsigned int width) 402 size_t size, unsigned int width)
413{ 403{
414 struct addr_map_symbol *to = &self->branch_info->to; 404 struct addr_map_symbol *to = &he->branch_info->to;
415 return _hist_entry__sym_snprintf(to->map, to->sym, to->addr, 405 return _hist_entry__sym_snprintf(to->map, to->sym, to->addr,
416 self->level, bf, size, width); 406 he->level, bf, size, width);
417 407
418} 408}
419 409
@@ -456,13 +446,13 @@ sort__mispredict_cmp(struct hist_entry *left, struct hist_entry *right)
456 return mp || p; 446 return mp || p;
457} 447}
458 448
459static int hist_entry__mispredict_snprintf(struct hist_entry *self, char *bf, 449static int hist_entry__mispredict_snprintf(struct hist_entry *he, char *bf,
460 size_t size, unsigned int width){ 450 size_t size, unsigned int width){
461 static const char *out = "N/A"; 451 static const char *out = "N/A";
462 452
463 if (self->branch_info->flags.predicted) 453 if (he->branch_info->flags.predicted)
464 out = "N"; 454 out = "N";
465 else if (self->branch_info->flags.mispred) 455 else if (he->branch_info->flags.mispred)
466 out = "Y"; 456 out = "Y";
467 457
468 return repsep_snprintf(bf, size, "%-*s", width, out); 458 return repsep_snprintf(bf, size, "%-*s", width, out);
@@ -482,19 +472,19 @@ sort__daddr_cmp(struct hist_entry *left, struct hist_entry *right)
482 return (int64_t)(r - l); 472 return (int64_t)(r - l);
483} 473}
484 474
485static int hist_entry__daddr_snprintf(struct hist_entry *self, char *bf, 475static int hist_entry__daddr_snprintf(struct hist_entry *he, char *bf,
486 size_t size, unsigned int width) 476 size_t size, unsigned int width)
487{ 477{
488 uint64_t addr = 0; 478 uint64_t addr = 0;
489 struct map *map = NULL; 479 struct map *map = NULL;
490 struct symbol *sym = NULL; 480 struct symbol *sym = NULL;
491 481
492 if (self->mem_info) { 482 if (he->mem_info) {
493 addr = self->mem_info->daddr.addr; 483 addr = he->mem_info->daddr.addr;
494 map = self->mem_info->daddr.map; 484 map = he->mem_info->daddr.map;
495 sym = self->mem_info->daddr.sym; 485 sym = he->mem_info->daddr.sym;
496 } 486 }
497 return _hist_entry__sym_snprintf(map, sym, addr, self->level, bf, size, 487 return _hist_entry__sym_snprintf(map, sym, addr, he->level, bf, size,
498 width); 488 width);
499} 489}
500 490
@@ -512,13 +502,13 @@ sort__dso_daddr_cmp(struct hist_entry *left, struct hist_entry *right)
512 return _sort__dso_cmp(map_l, map_r); 502 return _sort__dso_cmp(map_l, map_r);
513} 503}
514 504
515static int hist_entry__dso_daddr_snprintf(struct hist_entry *self, char *bf, 505static int hist_entry__dso_daddr_snprintf(struct hist_entry *he, char *bf,
516 size_t size, unsigned int width) 506 size_t size, unsigned int width)
517{ 507{
518 struct map *map = NULL; 508 struct map *map = NULL;
519 509
520 if (self->mem_info) 510 if (he->mem_info)
521 map = self->mem_info->daddr.map; 511 map = he->mem_info->daddr.map;
522 512
523 return _hist_entry__dso_snprintf(map, bf, size, width); 513 return _hist_entry__dso_snprintf(map, bf, size, width);
524} 514}
@@ -542,14 +532,14 @@ sort__locked_cmp(struct hist_entry *left, struct hist_entry *right)
542 return (int64_t)(data_src_r.mem_lock - data_src_l.mem_lock); 532 return (int64_t)(data_src_r.mem_lock - data_src_l.mem_lock);
543} 533}
544 534
545static int hist_entry__locked_snprintf(struct hist_entry *self, char *bf, 535static int hist_entry__locked_snprintf(struct hist_entry *he, char *bf,
546 size_t size, unsigned int width) 536 size_t size, unsigned int width)
547{ 537{
548 const char *out; 538 const char *out;
549 u64 mask = PERF_MEM_LOCK_NA; 539 u64 mask = PERF_MEM_LOCK_NA;
550 540
551 if (self->mem_info) 541 if (he->mem_info)
552 mask = self->mem_info->data_src.mem_lock; 542 mask = he->mem_info->data_src.mem_lock;
553 543
554 if (mask & PERF_MEM_LOCK_NA) 544 if (mask & PERF_MEM_LOCK_NA)
555 out = "N/A"; 545 out = "N/A";
@@ -591,7 +581,7 @@ static const char * const tlb_access[] = {
591}; 581};
592#define NUM_TLB_ACCESS (sizeof(tlb_access)/sizeof(const char *)) 582#define NUM_TLB_ACCESS (sizeof(tlb_access)/sizeof(const char *))
593 583
594static int hist_entry__tlb_snprintf(struct hist_entry *self, char *bf, 584static int hist_entry__tlb_snprintf(struct hist_entry *he, char *bf,
595 size_t size, unsigned int width) 585 size_t size, unsigned int width)
596{ 586{
597 char out[64]; 587 char out[64];
@@ -602,8 +592,8 @@ static int hist_entry__tlb_snprintf(struct hist_entry *self, char *bf,
602 592
603 out[0] = '\0'; 593 out[0] = '\0';
604 594
605 if (self->mem_info) 595 if (he->mem_info)
606 m = self->mem_info->data_src.mem_dtlb; 596 m = he->mem_info->data_src.mem_dtlb;
607 597
608 hit = m & PERF_MEM_TLB_HIT; 598 hit = m & PERF_MEM_TLB_HIT;
609 miss = m & PERF_MEM_TLB_MISS; 599 miss = m & PERF_MEM_TLB_MISS;
@@ -668,7 +658,7 @@ static const char * const mem_lvl[] = {
668}; 658};
669#define NUM_MEM_LVL (sizeof(mem_lvl)/sizeof(const char *)) 659#define NUM_MEM_LVL (sizeof(mem_lvl)/sizeof(const char *))
670 660
671static int hist_entry__lvl_snprintf(struct hist_entry *self, char *bf, 661static int hist_entry__lvl_snprintf(struct hist_entry *he, char *bf,
672 size_t size, unsigned int width) 662 size_t size, unsigned int width)
673{ 663{
674 char out[64]; 664 char out[64];
@@ -677,8 +667,8 @@ static int hist_entry__lvl_snprintf(struct hist_entry *self, char *bf,
677 u64 m = PERF_MEM_LVL_NA; 667 u64 m = PERF_MEM_LVL_NA;
678 u64 hit, miss; 668 u64 hit, miss;
679 669
680 if (self->mem_info) 670 if (he->mem_info)
681 m = self->mem_info->data_src.mem_lvl; 671 m = he->mem_info->data_src.mem_lvl;
682 672
683 out[0] = '\0'; 673 out[0] = '\0';
684 674
@@ -736,7 +726,7 @@ static const char * const snoop_access[] = {
736}; 726};
737#define NUM_SNOOP_ACCESS (sizeof(snoop_access)/sizeof(const char *)) 727#define NUM_SNOOP_ACCESS (sizeof(snoop_access)/sizeof(const char *))
738 728
739static int hist_entry__snoop_snprintf(struct hist_entry *self, char *bf, 729static int hist_entry__snoop_snprintf(struct hist_entry *he, char *bf,
740 size_t size, unsigned int width) 730 size_t size, unsigned int width)
741{ 731{
742 char out[64]; 732 char out[64];
@@ -746,8 +736,8 @@ static int hist_entry__snoop_snprintf(struct hist_entry *self, char *bf,
746 736
747 out[0] = '\0'; 737 out[0] = '\0';
748 738
749 if (self->mem_info) 739 if (he->mem_info)
750 m = self->mem_info->data_src.mem_snoop; 740 m = he->mem_info->data_src.mem_snoop;
751 741
752 for (i = 0; m && i < NUM_SNOOP_ACCESS; i++, m >>= 1) { 742 for (i = 0; m && i < NUM_SNOOP_ACCESS; i++, m >>= 1) {
753 if (!(m & 0x1)) 743 if (!(m & 0x1))
@@ -784,10 +774,10 @@ sort__local_weight_cmp(struct hist_entry *left, struct hist_entry *right)
784 return he_weight(left) - he_weight(right); 774 return he_weight(left) - he_weight(right);
785} 775}
786 776
787static int hist_entry__local_weight_snprintf(struct hist_entry *self, char *bf, 777static int hist_entry__local_weight_snprintf(struct hist_entry *he, char *bf,
788 size_t size, unsigned int width) 778 size_t size, unsigned int width)
789{ 779{
790 return repsep_snprintf(bf, size, "%-*llu", width, he_weight(self)); 780 return repsep_snprintf(bf, size, "%-*llu", width, he_weight(he));
791} 781}
792 782
793struct sort_entry sort_local_weight = { 783struct sort_entry sort_local_weight = {
@@ -803,10 +793,10 @@ sort__global_weight_cmp(struct hist_entry *left, struct hist_entry *right)
803 return left->stat.weight - right->stat.weight; 793 return left->stat.weight - right->stat.weight;
804} 794}
805 795
806static int hist_entry__global_weight_snprintf(struct hist_entry *self, char *bf, 796static int hist_entry__global_weight_snprintf(struct hist_entry *he, char *bf,
807 size_t size, unsigned int width) 797 size_t size, unsigned int width)
808{ 798{
809 return repsep_snprintf(bf, size, "%-*llu", width, self->stat.weight); 799 return repsep_snprintf(bf, size, "%-*llu", width, he->stat.weight);
810} 800}
811 801
812struct sort_entry sort_global_weight = { 802struct sort_entry sort_global_weight = {
@@ -858,6 +848,127 @@ struct sort_entry sort_mem_snoop = {
858 .se_width_idx = HISTC_MEM_SNOOP, 848 .se_width_idx = HISTC_MEM_SNOOP,
859}; 849};
860 850
851static int64_t
852sort__abort_cmp(struct hist_entry *left, struct hist_entry *right)
853{
854 return left->branch_info->flags.abort !=
855 right->branch_info->flags.abort;
856}
857
858static int hist_entry__abort_snprintf(struct hist_entry *he, char *bf,
859 size_t size, unsigned int width)
860{
861 static const char *out = ".";
862
863 if (he->branch_info->flags.abort)
864 out = "A";
865 return repsep_snprintf(bf, size, "%-*s", width, out);
866}
867
868struct sort_entry sort_abort = {
869 .se_header = "Transaction abort",
870 .se_cmp = sort__abort_cmp,
871 .se_snprintf = hist_entry__abort_snprintf,
872 .se_width_idx = HISTC_ABORT,
873};
874
875static int64_t
876sort__in_tx_cmp(struct hist_entry *left, struct hist_entry *right)
877{
878 return left->branch_info->flags.in_tx !=
879 right->branch_info->flags.in_tx;
880}
881
882static int hist_entry__in_tx_snprintf(struct hist_entry *he, char *bf,
883 size_t size, unsigned int width)
884{
885 static const char *out = ".";
886
887 if (he->branch_info->flags.in_tx)
888 out = "T";
889
890 return repsep_snprintf(bf, size, "%-*s", width, out);
891}
892
893struct sort_entry sort_in_tx = {
894 .se_header = "Branch in transaction",
895 .se_cmp = sort__in_tx_cmp,
896 .se_snprintf = hist_entry__in_tx_snprintf,
897 .se_width_idx = HISTC_IN_TX,
898};
899
900static int64_t
901sort__transaction_cmp(struct hist_entry *left, struct hist_entry *right)
902{
903 return left->transaction - right->transaction;
904}
905
906static inline char *add_str(char *p, const char *str)
907{
908 strcpy(p, str);
909 return p + strlen(str);
910}
911
912static struct txbit {
913 unsigned flag;
914 const char *name;
915 int skip_for_len;
916} txbits[] = {
917 { PERF_TXN_ELISION, "EL ", 0 },
918 { PERF_TXN_TRANSACTION, "TX ", 1 },
919 { PERF_TXN_SYNC, "SYNC ", 1 },
920 { PERF_TXN_ASYNC, "ASYNC ", 0 },
921 { PERF_TXN_RETRY, "RETRY ", 0 },
922 { PERF_TXN_CONFLICT, "CON ", 0 },
923 { PERF_TXN_CAPACITY_WRITE, "CAP-WRITE ", 1 },
924 { PERF_TXN_CAPACITY_READ, "CAP-READ ", 0 },
925 { 0, NULL, 0 }
926};
927
928int hist_entry__transaction_len(void)
929{
930 int i;
931 int len = 0;
932
933 for (i = 0; txbits[i].name; i++) {
934 if (!txbits[i].skip_for_len)
935 len += strlen(txbits[i].name);
936 }
937 len += 4; /* :XX<space> */
938 return len;
939}
940
941static int hist_entry__transaction_snprintf(struct hist_entry *he, char *bf,
942 size_t size, unsigned int width)
943{
944 u64 t = he->transaction;
945 char buf[128];
946 char *p = buf;
947 int i;
948
949 buf[0] = 0;
950 for (i = 0; txbits[i].name; i++)
951 if (txbits[i].flag & t)
952 p = add_str(p, txbits[i].name);
953 if (t && !(t & (PERF_TXN_SYNC|PERF_TXN_ASYNC)))
954 p = add_str(p, "NEITHER ");
955 if (t & PERF_TXN_ABORT_MASK) {
956 sprintf(p, ":%" PRIx64,
957 (t & PERF_TXN_ABORT_MASK) >>
958 PERF_TXN_ABORT_SHIFT);
959 p += strlen(p);
960 }
961
962 return repsep_snprintf(bf, size, "%-*s", width, buf);
963}
964
965struct sort_entry sort_transaction = {
966 .se_header = "Transaction ",
967 .se_cmp = sort__transaction_cmp,
968 .se_snprintf = hist_entry__transaction_snprintf,
969 .se_width_idx = HISTC_TRANSACTION,
970};
971
861struct sort_dimension { 972struct sort_dimension {
862 const char *name; 973 const char *name;
863 struct sort_entry *entry; 974 struct sort_entry *entry;
@@ -876,6 +987,7 @@ static struct sort_dimension common_sort_dimensions[] = {
876 DIM(SORT_SRCLINE, "srcline", sort_srcline), 987 DIM(SORT_SRCLINE, "srcline", sort_srcline),
877 DIM(SORT_LOCAL_WEIGHT, "local_weight", sort_local_weight), 988 DIM(SORT_LOCAL_WEIGHT, "local_weight", sort_local_weight),
878 DIM(SORT_GLOBAL_WEIGHT, "weight", sort_global_weight), 989 DIM(SORT_GLOBAL_WEIGHT, "weight", sort_global_weight),
990 DIM(SORT_TRANSACTION, "transaction", sort_transaction),
879}; 991};
880 992
881#undef DIM 993#undef DIM
@@ -888,6 +1000,8 @@ static struct sort_dimension bstack_sort_dimensions[] = {
888 DIM(SORT_SYM_FROM, "symbol_from", sort_sym_from), 1000 DIM(SORT_SYM_FROM, "symbol_from", sort_sym_from),
889 DIM(SORT_SYM_TO, "symbol_to", sort_sym_to), 1001 DIM(SORT_SYM_TO, "symbol_to", sort_sym_to),
890 DIM(SORT_MISPREDICT, "mispredict", sort_mispredict), 1002 DIM(SORT_MISPREDICT, "mispredict", sort_mispredict),
1003 DIM(SORT_IN_TX, "in_tx", sort_in_tx),
1004 DIM(SORT_ABORT, "abort", sort_abort),
891}; 1005};
892 1006
893#undef DIM 1007#undef DIM
@@ -1009,7 +1123,7 @@ int setup_sorting(void)
1009 return ret; 1123 return ret;
1010} 1124}
1011 1125
1012static void sort_entry__setup_elide(struct sort_entry *self, 1126static void sort_entry__setup_elide(struct sort_entry *se,
1013 struct strlist *list, 1127 struct strlist *list,
1014 const char *list_name, FILE *fp) 1128 const char *list_name, FILE *fp)
1015{ 1129{
@@ -1017,7 +1131,7 @@ static void sort_entry__setup_elide(struct sort_entry *self,
1017 if (fp != NULL) 1131 if (fp != NULL)
1018 fprintf(fp, "# %s: %s\n", list_name, 1132 fprintf(fp, "# %s: %s\n", list_name,
1019 strlist__entry(list, 0)->s); 1133 strlist__entry(list, 0)->s);
1020 self->elide = true; 1134 se->elide = true;
1021 } 1135 }
1022} 1136}
1023 1137
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 4e80dbd271e7..43e5ff42a609 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -22,7 +22,6 @@
22#include "parse-events.h" 22#include "parse-events.h"
23 23
24#include "thread.h" 24#include "thread.h"
25#include "sort.h"
26 25
27extern regex_t parent_regex; 26extern regex_t parent_regex;
28extern const char *sort_order; 27extern const char *sort_order;
@@ -84,7 +83,9 @@ struct hist_entry {
84 struct he_stat stat; 83 struct he_stat stat;
85 struct map_symbol ms; 84 struct map_symbol ms;
86 struct thread *thread; 85 struct thread *thread;
86 struct comm *comm;
87 u64 ip; 87 u64 ip;
88 u64 transaction;
88 s32 cpu; 89 s32 cpu;
89 90
90 struct hist_entry_diff diff; 91 struct hist_entry_diff diff;
@@ -145,6 +146,7 @@ enum sort_type {
145 SORT_SRCLINE, 146 SORT_SRCLINE,
146 SORT_LOCAL_WEIGHT, 147 SORT_LOCAL_WEIGHT,
147 SORT_GLOBAL_WEIGHT, 148 SORT_GLOBAL_WEIGHT,
149 SORT_TRANSACTION,
148 150
149 /* branch stack specific sort keys */ 151 /* branch stack specific sort keys */
150 __SORT_BRANCH_STACK, 152 __SORT_BRANCH_STACK,
@@ -153,6 +155,8 @@ enum sort_type {
153 SORT_SYM_FROM, 155 SORT_SYM_FROM,
154 SORT_SYM_TO, 156 SORT_SYM_TO,
155 SORT_MISPREDICT, 157 SORT_MISPREDICT,
158 SORT_ABORT,
159 SORT_IN_TX,
156 160
157 /* memory mode specific sort keys */ 161 /* memory mode specific sort keys */
158 __SORT_MEMORY_MODE, 162 __SORT_MEMORY_MODE,
@@ -175,7 +179,7 @@ struct sort_entry {
175 179
176 int64_t (*se_cmp)(struct hist_entry *, struct hist_entry *); 180 int64_t (*se_cmp)(struct hist_entry *, struct hist_entry *);
177 int64_t (*se_collapse)(struct hist_entry *, struct hist_entry *); 181 int64_t (*se_collapse)(struct hist_entry *, struct hist_entry *);
178 int (*se_snprintf)(struct hist_entry *self, char *bf, size_t size, 182 int (*se_snprintf)(struct hist_entry *he, char *bf, size_t size,
179 unsigned int width); 183 unsigned int width);
180 u8 se_width_idx; 184 u8 se_width_idx;
181 bool elide; 185 bool elide;
diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c
new file mode 100644
index 000000000000..d11aefbc4b8d
--- /dev/null
+++ b/tools/perf/util/srcline.c
@@ -0,0 +1,265 @@
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4
5#include <linux/kernel.h>
6
7#include "util/dso.h"
8#include "util/util.h"
9#include "util/debug.h"
10
11#ifdef HAVE_LIBBFD_SUPPORT
12
13/*
14 * Implement addr2line using libbfd.
15 */
16#define PACKAGE "perf"
17#include <bfd.h>
18
19struct a2l_data {
20 const char *input;
21 unsigned long addr;
22
23 bool found;
24 const char *filename;
25 const char *funcname;
26 unsigned line;
27
28 bfd *abfd;
29 asymbol **syms;
30};
31
32static int bfd_error(const char *string)
33{
34 const char *errmsg;
35
36 errmsg = bfd_errmsg(bfd_get_error());
37 fflush(stdout);
38
39 if (string)
40 pr_debug("%s: %s\n", string, errmsg);
41 else
42 pr_debug("%s\n", errmsg);
43
44 return -1;
45}
46
47static int slurp_symtab(bfd *abfd, struct a2l_data *a2l)
48{
49 long storage;
50 long symcount;
51 asymbol **syms;
52 bfd_boolean dynamic = FALSE;
53
54 if ((bfd_get_file_flags(abfd) & HAS_SYMS) == 0)
55 return bfd_error(bfd_get_filename(abfd));
56
57 storage = bfd_get_symtab_upper_bound(abfd);
58 if (storage == 0L) {
59 storage = bfd_get_dynamic_symtab_upper_bound(abfd);
60 dynamic = TRUE;
61 }
62 if (storage < 0L)
63 return bfd_error(bfd_get_filename(abfd));
64
65 syms = malloc(storage);
66 if (dynamic)
67 symcount = bfd_canonicalize_dynamic_symtab(abfd, syms);
68 else
69 symcount = bfd_canonicalize_symtab(abfd, syms);
70
71 if (symcount < 0) {
72 free(syms);
73 return bfd_error(bfd_get_filename(abfd));
74 }
75
76 a2l->syms = syms;
77 return 0;
78}
79
80static void find_address_in_section(bfd *abfd, asection *section, void *data)
81{
82 bfd_vma pc, vma;
83 bfd_size_type size;
84 struct a2l_data *a2l = data;
85
86 if (a2l->found)
87 return;
88
89 if ((bfd_get_section_flags(abfd, section) & SEC_ALLOC) == 0)
90 return;
91
92 pc = a2l->addr;
93 vma = bfd_get_section_vma(abfd, section);
94 size = bfd_get_section_size(section);
95
96 if (pc < vma || pc >= vma + size)
97 return;
98
99 a2l->found = bfd_find_nearest_line(abfd, section, a2l->syms, pc - vma,
100 &a2l->filename, &a2l->funcname,
101 &a2l->line);
102}
103
104static struct a2l_data *addr2line_init(const char *path)
105{
106 bfd *abfd;
107 struct a2l_data *a2l = NULL;
108
109 abfd = bfd_openr(path, NULL);
110 if (abfd == NULL)
111 return NULL;
112
113 if (!bfd_check_format(abfd, bfd_object))
114 goto out;
115
116 a2l = zalloc(sizeof(*a2l));
117 if (a2l == NULL)
118 goto out;
119
120 a2l->abfd = abfd;
121 a2l->input = strdup(path);
122 if (a2l->input == NULL)
123 goto out;
124
125 if (slurp_symtab(abfd, a2l))
126 goto out;
127
128 return a2l;
129
130out:
131 if (a2l) {
132 free((void *)a2l->input);
133 free(a2l);
134 }
135 bfd_close(abfd);
136 return NULL;
137}
138
139static void addr2line_cleanup(struct a2l_data *a2l)
140{
141 if (a2l->abfd)
142 bfd_close(a2l->abfd);
143 free((void *)a2l->input);
144 free(a2l->syms);
145 free(a2l);
146}
147
148static int addr2line(const char *dso_name, unsigned long addr,
149 char **file, unsigned int *line)
150{
151 int ret = 0;
152 struct a2l_data *a2l;
153
154 a2l = addr2line_init(dso_name);
155 if (a2l == NULL) {
156 pr_warning("addr2line_init failed for %s\n", dso_name);
157 return 0;
158 }
159
160 a2l->addr = addr;
161 bfd_map_over_sections(a2l->abfd, find_address_in_section, a2l);
162
163 if (a2l->found && a2l->filename) {
164 *file = strdup(a2l->filename);
165 *line = a2l->line;
166
167 if (*file)
168 ret = 1;
169 }
170
171 addr2line_cleanup(a2l);
172 return ret;
173}
174
175#else /* HAVE_LIBBFD_SUPPORT */
176
177static int addr2line(const char *dso_name, unsigned long addr,
178 char **file, unsigned int *line_nr)
179{
180 FILE *fp;
181 char cmd[PATH_MAX];
182 char *filename = NULL;
183 size_t len;
184 char *sep;
185 int ret = 0;
186
187 scnprintf(cmd, sizeof(cmd), "addr2line -e %s %016"PRIx64,
188 dso_name, addr);
189
190 fp = popen(cmd, "r");
191 if (fp == NULL) {
192 pr_warning("popen failed for %s\n", dso_name);
193 return 0;
194 }
195
196 if (getline(&filename, &len, fp) < 0 || !len) {
197 pr_warning("addr2line has no output for %s\n", dso_name);
198 goto out;
199 }
200
201 sep = strchr(filename, '\n');
202 if (sep)
203 *sep = '\0';
204
205 if (!strcmp(filename, "??:0")) {
206 pr_debug("no debugging info in %s\n", dso_name);
207 free(filename);
208 goto out;
209 }
210
211 sep = strchr(filename, ':');
212 if (sep) {
213 *sep++ = '\0';
214 *file = filename;
215 *line_nr = strtoul(sep, NULL, 0);
216 ret = 1;
217 }
218out:
219 pclose(fp);
220 return ret;
221}
222#endif /* HAVE_LIBBFD_SUPPORT */
223
224char *get_srcline(struct dso *dso, unsigned long addr)
225{
226 char *file = NULL;
227 unsigned line = 0;
228 char *srcline;
229 char *dso_name = dso->long_name;
230 size_t size;
231
232 if (!dso->has_srcline)
233 return SRCLINE_UNKNOWN;
234
235 if (dso_name[0] == '[')
236 goto out;
237
238 if (!strncmp(dso_name, "/tmp/perf-", 10))
239 goto out;
240
241 if (!addr2line(dso_name, addr, &file, &line))
242 goto out;
243
244 /* just calculate actual length */
245 size = snprintf(NULL, 0, "%s:%u", file, line) + 1;
246
247 srcline = malloc(size);
248 if (srcline)
249 snprintf(srcline, size, "%s:%u", file, line);
250 else
251 srcline = SRCLINE_UNKNOWN;
252
253 free(file);
254 return srcline;
255
256out:
257 dso->has_srcline = 0;
258 return SRCLINE_UNKNOWN;
259}
260
261void free_srcline(char *srcline)
262{
263 if (srcline && strcmp(srcline, SRCLINE_UNKNOWN) != 0)
264 free(srcline);
265}
diff --git a/tools/perf/util/strfilter.c b/tools/perf/util/strfilter.c
index 834c8ebfe38e..3edd0538161f 100644
--- a/tools/perf/util/strfilter.c
+++ b/tools/perf/util/strfilter.c
@@ -10,22 +10,22 @@ static const char *OP_not = "!"; /* Logical NOT */
10#define is_operator(c) ((c) == '|' || (c) == '&' || (c) == '!') 10#define is_operator(c) ((c) == '|' || (c) == '&' || (c) == '!')
11#define is_separator(c) (is_operator(c) || (c) == '(' || (c) == ')') 11#define is_separator(c) (is_operator(c) || (c) == '(' || (c) == ')')
12 12
13static void strfilter_node__delete(struct strfilter_node *self) 13static void strfilter_node__delete(struct strfilter_node *node)
14{ 14{
15 if (self) { 15 if (node) {
16 if (self->p && !is_operator(*self->p)) 16 if (node->p && !is_operator(*node->p))
17 free((char *)self->p); 17 free((char *)node->p);
18 strfilter_node__delete(self->l); 18 strfilter_node__delete(node->l);
19 strfilter_node__delete(self->r); 19 strfilter_node__delete(node->r);
20 free(self); 20 free(node);
21 } 21 }
22} 22}
23 23
24void strfilter__delete(struct strfilter *self) 24void strfilter__delete(struct strfilter *filter)
25{ 25{
26 if (self) { 26 if (filter) {
27 strfilter_node__delete(self->root); 27 strfilter_node__delete(filter->root);
28 free(self); 28 free(filter);
29 } 29 }
30} 30}
31 31
@@ -62,15 +62,15 @@ static struct strfilter_node *strfilter_node__alloc(const char *op,
62 struct strfilter_node *l, 62 struct strfilter_node *l,
63 struct strfilter_node *r) 63 struct strfilter_node *r)
64{ 64{
65 struct strfilter_node *ret = zalloc(sizeof(struct strfilter_node)); 65 struct strfilter_node *node = zalloc(sizeof(*node));
66 66
67 if (ret) { 67 if (node) {
68 ret->p = op; 68 node->p = op;
69 ret->l = l; 69 node->l = l;
70 ret->r = r; 70 node->r = r;
71 } 71 }
72 72
73 return ret; 73 return node;
74} 74}
75 75
76static struct strfilter_node *strfilter_node__new(const char *s, 76static struct strfilter_node *strfilter_node__new(const char *s,
@@ -154,46 +154,46 @@ error:
154 */ 154 */
155struct strfilter *strfilter__new(const char *rules, const char **err) 155struct strfilter *strfilter__new(const char *rules, const char **err)
156{ 156{
157 struct strfilter *ret = zalloc(sizeof(struct strfilter)); 157 struct strfilter *filter = zalloc(sizeof(*filter));
158 const char *ep = NULL; 158 const char *ep = NULL;
159 159
160 if (ret) 160 if (filter)
161 ret->root = strfilter_node__new(rules, &ep); 161 filter->root = strfilter_node__new(rules, &ep);
162 162
163 if (!ret || !ret->root || *ep != '\0') { 163 if (!filter || !filter->root || *ep != '\0') {
164 if (err) 164 if (err)
165 *err = ep; 165 *err = ep;
166 strfilter__delete(ret); 166 strfilter__delete(filter);
167 ret = NULL; 167 filter = NULL;
168 } 168 }
169 169
170 return ret; 170 return filter;
171} 171}
172 172
173static bool strfilter_node__compare(struct strfilter_node *self, 173static bool strfilter_node__compare(struct strfilter_node *node,
174 const char *str) 174 const char *str)
175{ 175{
176 if (!self || !self->p) 176 if (!node || !node->p)
177 return false; 177 return false;
178 178
179 switch (*self->p) { 179 switch (*node->p) {
180 case '|': /* OR */ 180 case '|': /* OR */
181 return strfilter_node__compare(self->l, str) || 181 return strfilter_node__compare(node->l, str) ||
182 strfilter_node__compare(self->r, str); 182 strfilter_node__compare(node->r, str);
183 case '&': /* AND */ 183 case '&': /* AND */
184 return strfilter_node__compare(self->l, str) && 184 return strfilter_node__compare(node->l, str) &&
185 strfilter_node__compare(self->r, str); 185 strfilter_node__compare(node->r, str);
186 case '!': /* NOT */ 186 case '!': /* NOT */
187 return !strfilter_node__compare(self->r, str); 187 return !strfilter_node__compare(node->r, str);
188 default: 188 default:
189 return strglobmatch(str, self->p); 189 return strglobmatch(str, node->p);
190 } 190 }
191} 191}
192 192
193/* Return true if STR matches the filter rules */ 193/* Return true if STR matches the filter rules */
194bool strfilter__compare(struct strfilter *self, const char *str) 194bool strfilter__compare(struct strfilter *filter, const char *str)
195{ 195{
196 if (!self) 196 if (!filter)
197 return false; 197 return false;
198 return strfilter_node__compare(self->root, str); 198 return strfilter_node__compare(filter->root, str);
199} 199}
diff --git a/tools/perf/util/strfilter.h b/tools/perf/util/strfilter.h
index 00f58a7506de..fe611f3c9e39 100644
--- a/tools/perf/util/strfilter.h
+++ b/tools/perf/util/strfilter.h
@@ -30,19 +30,19 @@ struct strfilter *strfilter__new(const char *rules, const char **err);
30 30
31/** 31/**
32 * strfilter__compare - compare given string and a string filter 32 * strfilter__compare - compare given string and a string filter
33 * @self: String filter 33 * @filter: String filter
34 * @str: target string 34 * @str: target string
35 * 35 *
36 * Compare @str and @self. Return true if the str match the rule 36 * Compare @str and @filter. Return true if the str match the rule
37 */ 37 */
38bool strfilter__compare(struct strfilter *self, const char *str); 38bool strfilter__compare(struct strfilter *filter, const char *str);
39 39
40/** 40/**
41 * strfilter__delete - delete a string filter 41 * strfilter__delete - delete a string filter
42 * @self: String filter to delete 42 * @filter: String filter to delete
43 * 43 *
44 * Delete @self. 44 * Delete @filter.
45 */ 45 */
46void strfilter__delete(struct strfilter *self); 46void strfilter__delete(struct strfilter *filter);
47 47
48#endif 48#endif
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index a9c829be5216..eed0b96302af 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -8,7 +8,7 @@
8#include "symbol.h" 8#include "symbol.h"
9#include "debug.h" 9#include "debug.h"
10 10
11#ifndef HAVE_ELF_GETPHDRNUM 11#ifndef HAVE_ELF_GETPHDRNUM_SUPPORT
12static int elf_getphdrnum(Elf *elf, size_t *dst) 12static int elf_getphdrnum(Elf *elf, size_t *dst)
13{ 13{
14 GElf_Ehdr gehdr; 14 GElf_Ehdr gehdr;
@@ -487,27 +487,27 @@ int filename__read_debuglink(const char *filename, char *debuglink,
487 487
488 ek = elf_kind(elf); 488 ek = elf_kind(elf);
489 if (ek != ELF_K_ELF) 489 if (ek != ELF_K_ELF)
490 goto out_close; 490 goto out_elf_end;
491 491
492 if (gelf_getehdr(elf, &ehdr) == NULL) { 492 if (gelf_getehdr(elf, &ehdr) == NULL) {
493 pr_err("%s: cannot get elf header.\n", __func__); 493 pr_err("%s: cannot get elf header.\n", __func__);
494 goto out_close; 494 goto out_elf_end;
495 } 495 }
496 496
497 sec = elf_section_by_name(elf, &ehdr, &shdr, 497 sec = elf_section_by_name(elf, &ehdr, &shdr,
498 ".gnu_debuglink", NULL); 498 ".gnu_debuglink", NULL);
499 if (sec == NULL) 499 if (sec == NULL)
500 goto out_close; 500 goto out_elf_end;
501 501
502 data = elf_getdata(sec, NULL); 502 data = elf_getdata(sec, NULL);
503 if (data == NULL) 503 if (data == NULL)
504 goto out_close; 504 goto out_elf_end;
505 505
506 /* the start of this section is a zero-terminated string */ 506 /* the start of this section is a zero-terminated string */
507 strncpy(debuglink, data->d_buf, size); 507 strncpy(debuglink, data->d_buf, size);
508 508
509out_elf_end:
509 elf_end(elf); 510 elf_end(elf);
510
511out_close: 511out_close:
512 close(fd); 512 close(fd);
513out: 513out:
@@ -1018,6 +1018,601 @@ int file__read_maps(int fd, bool exe, mapfn_t mapfn, void *data,
1018 return err; 1018 return err;
1019} 1019}
1020 1020
1021static int copy_bytes(int from, off_t from_offs, int to, off_t to_offs, u64 len)
1022{
1023 ssize_t r;
1024 size_t n;
1025 int err = -1;
1026 char *buf = malloc(page_size);
1027
1028 if (buf == NULL)
1029 return -1;
1030
1031 if (lseek(to, to_offs, SEEK_SET) != to_offs)
1032 goto out;
1033
1034 if (lseek(from, from_offs, SEEK_SET) != from_offs)
1035 goto out;
1036
1037 while (len) {
1038 n = page_size;
1039 if (len < n)
1040 n = len;
1041 /* Use read because mmap won't work on proc files */
1042 r = read(from, buf, n);
1043 if (r < 0)
1044 goto out;
1045 if (!r)
1046 break;
1047 n = r;
1048 r = write(to, buf, n);
1049 if (r < 0)
1050 goto out;
1051 if ((size_t)r != n)
1052 goto out;
1053 len -= n;
1054 }
1055
1056 err = 0;
1057out:
1058 free(buf);
1059 return err;
1060}
1061
1062struct kcore {
1063 int fd;
1064 int elfclass;
1065 Elf *elf;
1066 GElf_Ehdr ehdr;
1067};
1068
1069static int kcore__open(struct kcore *kcore, const char *filename)
1070{
1071 GElf_Ehdr *ehdr;
1072
1073 kcore->fd = open(filename, O_RDONLY);
1074 if (kcore->fd == -1)
1075 return -1;
1076
1077 kcore->elf = elf_begin(kcore->fd, ELF_C_READ, NULL);
1078 if (!kcore->elf)
1079 goto out_close;
1080
1081 kcore->elfclass = gelf_getclass(kcore->elf);
1082 if (kcore->elfclass == ELFCLASSNONE)
1083 goto out_end;
1084
1085 ehdr = gelf_getehdr(kcore->elf, &kcore->ehdr);
1086 if (!ehdr)
1087 goto out_end;
1088
1089 return 0;
1090
1091out_end:
1092 elf_end(kcore->elf);
1093out_close:
1094 close(kcore->fd);
1095 return -1;
1096}
1097
1098static int kcore__init(struct kcore *kcore, char *filename, int elfclass,
1099 bool temp)
1100{
1101 GElf_Ehdr *ehdr;
1102
1103 kcore->elfclass = elfclass;
1104
1105 if (temp)
1106 kcore->fd = mkstemp(filename);
1107 else
1108 kcore->fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0400);
1109 if (kcore->fd == -1)
1110 return -1;
1111
1112 kcore->elf = elf_begin(kcore->fd, ELF_C_WRITE, NULL);
1113 if (!kcore->elf)
1114 goto out_close;
1115
1116 if (!gelf_newehdr(kcore->elf, elfclass))
1117 goto out_end;
1118
1119 ehdr = gelf_getehdr(kcore->elf, &kcore->ehdr);
1120 if (!ehdr)
1121 goto out_end;
1122
1123 return 0;
1124
1125out_end:
1126 elf_end(kcore->elf);
1127out_close:
1128 close(kcore->fd);
1129 unlink(filename);
1130 return -1;
1131}
1132
1133static void kcore__close(struct kcore *kcore)
1134{
1135 elf_end(kcore->elf);
1136 close(kcore->fd);
1137}
1138
1139static int kcore__copy_hdr(struct kcore *from, struct kcore *to, size_t count)
1140{
1141 GElf_Ehdr *ehdr = &to->ehdr;
1142 GElf_Ehdr *kehdr = &from->ehdr;
1143
1144 memcpy(ehdr->e_ident, kehdr->e_ident, EI_NIDENT);
1145 ehdr->e_type = kehdr->e_type;
1146 ehdr->e_machine = kehdr->e_machine;
1147 ehdr->e_version = kehdr->e_version;
1148 ehdr->e_entry = 0;
1149 ehdr->e_shoff = 0;
1150 ehdr->e_flags = kehdr->e_flags;
1151 ehdr->e_phnum = count;
1152 ehdr->e_shentsize = 0;
1153 ehdr->e_shnum = 0;
1154 ehdr->e_shstrndx = 0;
1155
1156 if (from->elfclass == ELFCLASS32) {
1157 ehdr->e_phoff = sizeof(Elf32_Ehdr);
1158 ehdr->e_ehsize = sizeof(Elf32_Ehdr);
1159 ehdr->e_phentsize = sizeof(Elf32_Phdr);
1160 } else {
1161 ehdr->e_phoff = sizeof(Elf64_Ehdr);
1162 ehdr->e_ehsize = sizeof(Elf64_Ehdr);
1163 ehdr->e_phentsize = sizeof(Elf64_Phdr);
1164 }
1165
1166 if (!gelf_update_ehdr(to->elf, ehdr))
1167 return -1;
1168
1169 if (!gelf_newphdr(to->elf, count))
1170 return -1;
1171
1172 return 0;
1173}
1174
1175static int kcore__add_phdr(struct kcore *kcore, int idx, off_t offset,
1176 u64 addr, u64 len)
1177{
1178 GElf_Phdr gphdr;
1179 GElf_Phdr *phdr;
1180
1181 phdr = gelf_getphdr(kcore->elf, idx, &gphdr);
1182 if (!phdr)
1183 return -1;
1184
1185 phdr->p_type = PT_LOAD;
1186 phdr->p_flags = PF_R | PF_W | PF_X;
1187 phdr->p_offset = offset;
1188 phdr->p_vaddr = addr;
1189 phdr->p_paddr = 0;
1190 phdr->p_filesz = len;
1191 phdr->p_memsz = len;
1192 phdr->p_align = page_size;
1193
1194 if (!gelf_update_phdr(kcore->elf, idx, phdr))
1195 return -1;
1196
1197 return 0;
1198}
1199
1200static off_t kcore__write(struct kcore *kcore)
1201{
1202 return elf_update(kcore->elf, ELF_C_WRITE);
1203}
1204
1205struct phdr_data {
1206 off_t offset;
1207 u64 addr;
1208 u64 len;
1209};
1210
1211struct kcore_copy_info {
1212 u64 stext;
1213 u64 etext;
1214 u64 first_symbol;
1215 u64 last_symbol;
1216 u64 first_module;
1217 u64 last_module_symbol;
1218 struct phdr_data kernel_map;
1219 struct phdr_data modules_map;
1220};
1221
1222static int kcore_copy__process_kallsyms(void *arg, const char *name, char type,
1223 u64 start)
1224{
1225 struct kcore_copy_info *kci = arg;
1226
1227 if (!symbol_type__is_a(type, MAP__FUNCTION))
1228 return 0;
1229
1230 if (strchr(name, '[')) {
1231 if (start > kci->last_module_symbol)
1232 kci->last_module_symbol = start;
1233 return 0;
1234 }
1235
1236 if (!kci->first_symbol || start < kci->first_symbol)
1237 kci->first_symbol = start;
1238
1239 if (!kci->last_symbol || start > kci->last_symbol)
1240 kci->last_symbol = start;
1241
1242 if (!strcmp(name, "_stext")) {
1243 kci->stext = start;
1244 return 0;
1245 }
1246
1247 if (!strcmp(name, "_etext")) {
1248 kci->etext = start;
1249 return 0;
1250 }
1251
1252 return 0;
1253}
1254
1255static int kcore_copy__parse_kallsyms(struct kcore_copy_info *kci,
1256 const char *dir)
1257{
1258 char kallsyms_filename[PATH_MAX];
1259
1260 scnprintf(kallsyms_filename, PATH_MAX, "%s/kallsyms", dir);
1261
1262 if (symbol__restricted_filename(kallsyms_filename, "/proc/kallsyms"))
1263 return -1;
1264
1265 if (kallsyms__parse(kallsyms_filename, kci,
1266 kcore_copy__process_kallsyms) < 0)
1267 return -1;
1268
1269 return 0;
1270}
1271
1272static int kcore_copy__process_modules(void *arg,
1273 const char *name __maybe_unused,
1274 u64 start)
1275{
1276 struct kcore_copy_info *kci = arg;
1277
1278 if (!kci->first_module || start < kci->first_module)
1279 kci->first_module = start;
1280
1281 return 0;
1282}
1283
1284static int kcore_copy__parse_modules(struct kcore_copy_info *kci,
1285 const char *dir)
1286{
1287 char modules_filename[PATH_MAX];
1288
1289 scnprintf(modules_filename, PATH_MAX, "%s/modules", dir);
1290
1291 if (symbol__restricted_filename(modules_filename, "/proc/modules"))
1292 return -1;
1293
1294 if (modules__parse(modules_filename, kci,
1295 kcore_copy__process_modules) < 0)
1296 return -1;
1297
1298 return 0;
1299}
1300
1301static void kcore_copy__map(struct phdr_data *p, u64 start, u64 end, u64 pgoff,
1302 u64 s, u64 e)
1303{
1304 if (p->addr || s < start || s >= end)
1305 return;
1306
1307 p->addr = s;
1308 p->offset = (s - start) + pgoff;
1309 p->len = e < end ? e - s : end - s;
1310}
1311
1312static int kcore_copy__read_map(u64 start, u64 len, u64 pgoff, void *data)
1313{
1314 struct kcore_copy_info *kci = data;
1315 u64 end = start + len;
1316
1317 kcore_copy__map(&kci->kernel_map, start, end, pgoff, kci->stext,
1318 kci->etext);
1319
1320 kcore_copy__map(&kci->modules_map, start, end, pgoff, kci->first_module,
1321 kci->last_module_symbol);
1322
1323 return 0;
1324}
1325
1326static int kcore_copy__read_maps(struct kcore_copy_info *kci, Elf *elf)
1327{
1328 if (elf_read_maps(elf, true, kcore_copy__read_map, kci) < 0)
1329 return -1;
1330
1331 return 0;
1332}
1333
1334static int kcore_copy__calc_maps(struct kcore_copy_info *kci, const char *dir,
1335 Elf *elf)
1336{
1337 if (kcore_copy__parse_kallsyms(kci, dir))
1338 return -1;
1339
1340 if (kcore_copy__parse_modules(kci, dir))
1341 return -1;
1342
1343 if (kci->stext)
1344 kci->stext = round_down(kci->stext, page_size);
1345 else
1346 kci->stext = round_down(kci->first_symbol, page_size);
1347
1348 if (kci->etext) {
1349 kci->etext = round_up(kci->etext, page_size);
1350 } else if (kci->last_symbol) {
1351 kci->etext = round_up(kci->last_symbol, page_size);
1352 kci->etext += page_size;
1353 }
1354
1355 kci->first_module = round_down(kci->first_module, page_size);
1356
1357 if (kci->last_module_symbol) {
1358 kci->last_module_symbol = round_up(kci->last_module_symbol,
1359 page_size);
1360 kci->last_module_symbol += page_size;
1361 }
1362
1363 if (!kci->stext || !kci->etext)
1364 return -1;
1365
1366 if (kci->first_module && !kci->last_module_symbol)
1367 return -1;
1368
1369 return kcore_copy__read_maps(kci, elf);
1370}
1371
1372static int kcore_copy__copy_file(const char *from_dir, const char *to_dir,
1373 const char *name)
1374{
1375 char from_filename[PATH_MAX];
1376 char to_filename[PATH_MAX];
1377
1378 scnprintf(from_filename, PATH_MAX, "%s/%s", from_dir, name);
1379 scnprintf(to_filename, PATH_MAX, "%s/%s", to_dir, name);
1380
1381 return copyfile_mode(from_filename, to_filename, 0400);
1382}
1383
1384static int kcore_copy__unlink(const char *dir, const char *name)
1385{
1386 char filename[PATH_MAX];
1387
1388 scnprintf(filename, PATH_MAX, "%s/%s", dir, name);
1389
1390 return unlink(filename);
1391}
1392
1393static int kcore_copy__compare_fds(int from, int to)
1394{
1395 char *buf_from;
1396 char *buf_to;
1397 ssize_t ret;
1398 size_t len;
1399 int err = -1;
1400
1401 buf_from = malloc(page_size);
1402 buf_to = malloc(page_size);
1403 if (!buf_from || !buf_to)
1404 goto out;
1405
1406 while (1) {
1407 /* Use read because mmap won't work on proc files */
1408 ret = read(from, buf_from, page_size);
1409 if (ret < 0)
1410 goto out;
1411
1412 if (!ret)
1413 break;
1414
1415 len = ret;
1416
1417 if (readn(to, buf_to, len) != (int)len)
1418 goto out;
1419
1420 if (memcmp(buf_from, buf_to, len))
1421 goto out;
1422 }
1423
1424 err = 0;
1425out:
1426 free(buf_to);
1427 free(buf_from);
1428 return err;
1429}
1430
1431static int kcore_copy__compare_files(const char *from_filename,
1432 const char *to_filename)
1433{
1434 int from, to, err = -1;
1435
1436 from = open(from_filename, O_RDONLY);
1437 if (from < 0)
1438 return -1;
1439
1440 to = open(to_filename, O_RDONLY);
1441 if (to < 0)
1442 goto out_close_from;
1443
1444 err = kcore_copy__compare_fds(from, to);
1445
1446 close(to);
1447out_close_from:
1448 close(from);
1449 return err;
1450}
1451
1452static int kcore_copy__compare_file(const char *from_dir, const char *to_dir,
1453 const char *name)
1454{
1455 char from_filename[PATH_MAX];
1456 char to_filename[PATH_MAX];
1457
1458 scnprintf(from_filename, PATH_MAX, "%s/%s", from_dir, name);
1459 scnprintf(to_filename, PATH_MAX, "%s/%s", to_dir, name);
1460
1461 return kcore_copy__compare_files(from_filename, to_filename);
1462}
1463
1464/**
1465 * kcore_copy - copy kallsyms, modules and kcore from one directory to another.
1466 * @from_dir: from directory
1467 * @to_dir: to directory
1468 *
1469 * This function copies kallsyms, modules and kcore files from one directory to
1470 * another. kallsyms and modules are copied entirely. Only code segments are
1471 * copied from kcore. It is assumed that two segments suffice: one for the
1472 * kernel proper and one for all the modules. The code segments are determined
1473 * from kallsyms and modules files. The kernel map starts at _stext or the
1474 * lowest function symbol, and ends at _etext or the highest function symbol.
1475 * The module map starts at the lowest module address and ends at the highest
1476 * module symbol. Start addresses are rounded down to the nearest page. End
1477 * addresses are rounded up to the nearest page. An extra page is added to the
1478 * highest kernel symbol and highest module symbol to, hopefully, encompass that
1479 * symbol too. Because it contains only code sections, the resulting kcore is
1480 * unusual. One significant peculiarity is that the mapping (start -> pgoff)
1481 * is not the same for the kernel map and the modules map. That happens because
1482 * the data is copied adjacently whereas the original kcore has gaps. Finally,
1483 * kallsyms and modules files are compared with their copies to check that
1484 * modules have not been loaded or unloaded while the copies were taking place.
1485 *
1486 * Return: %0 on success, %-1 on failure.
1487 */
1488int kcore_copy(const char *from_dir, const char *to_dir)
1489{
1490 struct kcore kcore;
1491 struct kcore extract;
1492 size_t count = 2;
1493 int idx = 0, err = -1;
1494 off_t offset = page_size, sz, modules_offset = 0;
1495 struct kcore_copy_info kci = { .stext = 0, };
1496 char kcore_filename[PATH_MAX];
1497 char extract_filename[PATH_MAX];
1498
1499 if (kcore_copy__copy_file(from_dir, to_dir, "kallsyms"))
1500 return -1;
1501
1502 if (kcore_copy__copy_file(from_dir, to_dir, "modules"))
1503 goto out_unlink_kallsyms;
1504
1505 scnprintf(kcore_filename, PATH_MAX, "%s/kcore", from_dir);
1506 scnprintf(extract_filename, PATH_MAX, "%s/kcore", to_dir);
1507
1508 if (kcore__open(&kcore, kcore_filename))
1509 goto out_unlink_modules;
1510
1511 if (kcore_copy__calc_maps(&kci, from_dir, kcore.elf))
1512 goto out_kcore_close;
1513
1514 if (kcore__init(&extract, extract_filename, kcore.elfclass, false))
1515 goto out_kcore_close;
1516
1517 if (!kci.modules_map.addr)
1518 count -= 1;
1519
1520 if (kcore__copy_hdr(&kcore, &extract, count))
1521 goto out_extract_close;
1522
1523 if (kcore__add_phdr(&extract, idx++, offset, kci.kernel_map.addr,
1524 kci.kernel_map.len))
1525 goto out_extract_close;
1526
1527 if (kci.modules_map.addr) {
1528 modules_offset = offset + kci.kernel_map.len;
1529 if (kcore__add_phdr(&extract, idx, modules_offset,
1530 kci.modules_map.addr, kci.modules_map.len))
1531 goto out_extract_close;
1532 }
1533
1534 sz = kcore__write(&extract);
1535 if (sz < 0 || sz > offset)
1536 goto out_extract_close;
1537
1538 if (copy_bytes(kcore.fd, kci.kernel_map.offset, extract.fd, offset,
1539 kci.kernel_map.len))
1540 goto out_extract_close;
1541
1542 if (modules_offset && copy_bytes(kcore.fd, kci.modules_map.offset,
1543 extract.fd, modules_offset,
1544 kci.modules_map.len))
1545 goto out_extract_close;
1546
1547 if (kcore_copy__compare_file(from_dir, to_dir, "modules"))
1548 goto out_extract_close;
1549
1550 if (kcore_copy__compare_file(from_dir, to_dir, "kallsyms"))
1551 goto out_extract_close;
1552
1553 err = 0;
1554
1555out_extract_close:
1556 kcore__close(&extract);
1557 if (err)
1558 unlink(extract_filename);
1559out_kcore_close:
1560 kcore__close(&kcore);
1561out_unlink_modules:
1562 if (err)
1563 kcore_copy__unlink(to_dir, "modules");
1564out_unlink_kallsyms:
1565 if (err)
1566 kcore_copy__unlink(to_dir, "kallsyms");
1567
1568 return err;
1569}
1570
1571int kcore_extract__create(struct kcore_extract *kce)
1572{
1573 struct kcore kcore;
1574 struct kcore extract;
1575 size_t count = 1;
1576 int idx = 0, err = -1;
1577 off_t offset = page_size, sz;
1578
1579 if (kcore__open(&kcore, kce->kcore_filename))
1580 return -1;
1581
1582 strcpy(kce->extract_filename, PERF_KCORE_EXTRACT);
1583 if (kcore__init(&extract, kce->extract_filename, kcore.elfclass, true))
1584 goto out_kcore_close;
1585
1586 if (kcore__copy_hdr(&kcore, &extract, count))
1587 goto out_extract_close;
1588
1589 if (kcore__add_phdr(&extract, idx, offset, kce->addr, kce->len))
1590 goto out_extract_close;
1591
1592 sz = kcore__write(&extract);
1593 if (sz < 0 || sz > offset)
1594 goto out_extract_close;
1595
1596 if (copy_bytes(kcore.fd, kce->offs, extract.fd, offset, kce->len))
1597 goto out_extract_close;
1598
1599 err = 0;
1600
1601out_extract_close:
1602 kcore__close(&extract);
1603 if (err)
1604 unlink(kce->extract_filename);
1605out_kcore_close:
1606 kcore__close(&kcore);
1607
1608 return err;
1609}
1610
1611void kcore_extract__delete(struct kcore_extract *kce)
1612{
1613 unlink(kce->extract_filename);
1614}
1615
1021void symbol__elf_init(void) 1616void symbol__elf_init(void)
1022{ 1617{
1023 elf_version(EV_CURRENT); 1618 elf_version(EV_CURRENT);
diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c
index 3a802c300fc5..2d2dd0532b5a 100644
--- a/tools/perf/util/symbol-minimal.c
+++ b/tools/perf/util/symbol-minimal.c
@@ -308,6 +308,21 @@ int file__read_maps(int fd __maybe_unused, bool exe __maybe_unused,
308 return -1; 308 return -1;
309} 309}
310 310
311int kcore_extract__create(struct kcore_extract *kce __maybe_unused)
312{
313 return -1;
314}
315
316void kcore_extract__delete(struct kcore_extract *kce __maybe_unused)
317{
318}
319
320int kcore_copy(const char *from_dir __maybe_unused,
321 const char *to_dir __maybe_unused)
322{
323 return -1;
324}
325
311void symbol__elf_init(void) 326void symbol__elf_init(void)
312{ 327{
313} 328}
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 7eb0362f4ffd..c0c36965fff0 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -51,6 +51,7 @@ static enum dso_binary_type binary_type_symtab[] = {
51 DSO_BINARY_TYPE__SYSTEM_PATH_DSO, 51 DSO_BINARY_TYPE__SYSTEM_PATH_DSO,
52 DSO_BINARY_TYPE__GUEST_KMODULE, 52 DSO_BINARY_TYPE__GUEST_KMODULE,
53 DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE, 53 DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE,
54 DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,
54 DSO_BINARY_TYPE__NOT_FOUND, 55 DSO_BINARY_TYPE__NOT_FOUND,
55}; 56};
56 57
@@ -159,10 +160,12 @@ again:
159 160
160 if (choose_best_symbol(curr, next) == SYMBOL_A) { 161 if (choose_best_symbol(curr, next) == SYMBOL_A) {
161 rb_erase(&next->rb_node, symbols); 162 rb_erase(&next->rb_node, symbols);
163 symbol__delete(next);
162 goto again; 164 goto again;
163 } else { 165 } else {
164 nd = rb_next(&curr->rb_node); 166 nd = rb_next(&curr->rb_node);
165 rb_erase(&curr->rb_node, symbols); 167 rb_erase(&curr->rb_node, symbols);
168 symbol__delete(curr);
166 } 169 }
167 } 170 }
168} 171}
@@ -499,6 +502,64 @@ out_failure:
499 return -1; 502 return -1;
500} 503}
501 504
505int modules__parse(const char *filename, void *arg,
506 int (*process_module)(void *arg, const char *name,
507 u64 start))
508{
509 char *line = NULL;
510 size_t n;
511 FILE *file;
512 int err = 0;
513
514 file = fopen(filename, "r");
515 if (file == NULL)
516 return -1;
517
518 while (1) {
519 char name[PATH_MAX];
520 u64 start;
521 char *sep;
522 ssize_t line_len;
523
524 line_len = getline(&line, &n, file);
525 if (line_len < 0) {
526 if (feof(file))
527 break;
528 err = -1;
529 goto out;
530 }
531
532 if (!line) {
533 err = -1;
534 goto out;
535 }
536
537 line[--line_len] = '\0'; /* \n */
538
539 sep = strrchr(line, 'x');
540 if (sep == NULL)
541 continue;
542
543 hex2u64(sep + 1, &start);
544
545 sep = strchr(line, ' ');
546 if (sep == NULL)
547 continue;
548
549 *sep = '\0';
550
551 scnprintf(name, sizeof(name), "[%s]", line);
552
553 err = process_module(arg, name, start);
554 if (err)
555 break;
556 }
557out:
558 free(line);
559 fclose(file);
560 return err;
561}
562
502struct process_kallsyms_args { 563struct process_kallsyms_args {
503 struct map *map; 564 struct map *map;
504 struct dso *dso; 565 struct dso *dso;
@@ -739,51 +800,242 @@ bool symbol__restricted_filename(const char *filename,
739 return restricted; 800 return restricted;
740} 801}
741 802
742struct kcore_mapfn_data { 803struct module_info {
743 struct dso *dso; 804 struct rb_node rb_node;
744 enum map_type type; 805 char *name;
745 struct list_head maps; 806 u64 start;
746}; 807};
747 808
748static int kcore_mapfn(u64 start, u64 len, u64 pgoff, void *data) 809static void add_module(struct module_info *mi, struct rb_root *modules)
749{ 810{
750 struct kcore_mapfn_data *md = data; 811 struct rb_node **p = &modules->rb_node;
751 struct map *map; 812 struct rb_node *parent = NULL;
813 struct module_info *m;
752 814
753 map = map__new2(start, md->dso, md->type); 815 while (*p != NULL) {
754 if (map == NULL) 816 parent = *p;
817 m = rb_entry(parent, struct module_info, rb_node);
818 if (strcmp(mi->name, m->name) < 0)
819 p = &(*p)->rb_left;
820 else
821 p = &(*p)->rb_right;
822 }
823 rb_link_node(&mi->rb_node, parent, p);
824 rb_insert_color(&mi->rb_node, modules);
825}
826
827static void delete_modules(struct rb_root *modules)
828{
829 struct module_info *mi;
830 struct rb_node *next = rb_first(modules);
831
832 while (next) {
833 mi = rb_entry(next, struct module_info, rb_node);
834 next = rb_next(&mi->rb_node);
835 rb_erase(&mi->rb_node, modules);
836 free(mi->name);
837 free(mi);
838 }
839}
840
841static struct module_info *find_module(const char *name,
842 struct rb_root *modules)
843{
844 struct rb_node *n = modules->rb_node;
845
846 while (n) {
847 struct module_info *m;
848 int cmp;
849
850 m = rb_entry(n, struct module_info, rb_node);
851 cmp = strcmp(name, m->name);
852 if (cmp < 0)
853 n = n->rb_left;
854 else if (cmp > 0)
855 n = n->rb_right;
856 else
857 return m;
858 }
859
860 return NULL;
861}
862
863static int __read_proc_modules(void *arg, const char *name, u64 start)
864{
865 struct rb_root *modules = arg;
866 struct module_info *mi;
867
868 mi = zalloc(sizeof(struct module_info));
869 if (!mi)
755 return -ENOMEM; 870 return -ENOMEM;
756 871
757 map->end = map->start + len; 872 mi->name = strdup(name);
758 map->pgoff = pgoff; 873 mi->start = start;
759 874
760 list_add(&map->node, &md->maps); 875 if (!mi->name) {
876 free(mi);
877 return -ENOMEM;
878 }
879
880 add_module(mi, modules);
881
882 return 0;
883}
884
885static int read_proc_modules(const char *filename, struct rb_root *modules)
886{
887 if (symbol__restricted_filename(filename, "/proc/modules"))
888 return -1;
889
890 if (modules__parse(filename, modules, __read_proc_modules)) {
891 delete_modules(modules);
892 return -1;
893 }
761 894
762 return 0; 895 return 0;
763} 896}
764 897
898int compare_proc_modules(const char *from, const char *to)
899{
900 struct rb_root from_modules = RB_ROOT;
901 struct rb_root to_modules = RB_ROOT;
902 struct rb_node *from_node, *to_node;
903 struct module_info *from_m, *to_m;
904 int ret = -1;
905
906 if (read_proc_modules(from, &from_modules))
907 return -1;
908
909 if (read_proc_modules(to, &to_modules))
910 goto out_delete_from;
911
912 from_node = rb_first(&from_modules);
913 to_node = rb_first(&to_modules);
914 while (from_node) {
915 if (!to_node)
916 break;
917
918 from_m = rb_entry(from_node, struct module_info, rb_node);
919 to_m = rb_entry(to_node, struct module_info, rb_node);
920
921 if (from_m->start != to_m->start ||
922 strcmp(from_m->name, to_m->name))
923 break;
924
925 from_node = rb_next(from_node);
926 to_node = rb_next(to_node);
927 }
928
929 if (!from_node && !to_node)
930 ret = 0;
931
932 delete_modules(&to_modules);
933out_delete_from:
934 delete_modules(&from_modules);
935
936 return ret;
937}
938
939static int do_validate_kcore_modules(const char *filename, struct map *map,
940 struct map_groups *kmaps)
941{
942 struct rb_root modules = RB_ROOT;
943 struct map *old_map;
944 int err;
945
946 err = read_proc_modules(filename, &modules);
947 if (err)
948 return err;
949
950 old_map = map_groups__first(kmaps, map->type);
951 while (old_map) {
952 struct map *next = map_groups__next(old_map);
953 struct module_info *mi;
954
955 if (old_map == map || old_map->start == map->start) {
956 /* The kernel map */
957 old_map = next;
958 continue;
959 }
960
961 /* Module must be in memory at the same address */
962 mi = find_module(old_map->dso->short_name, &modules);
963 if (!mi || mi->start != old_map->start) {
964 err = -EINVAL;
965 goto out;
966 }
967
968 old_map = next;
969 }
970out:
971 delete_modules(&modules);
972 return err;
973}
974
765/* 975/*
766 * If kallsyms is referenced by name then we look for kcore in the same 976 * If kallsyms is referenced by name then we look for filename in the same
767 * directory. 977 * directory.
768 */ 978 */
769static bool kcore_filename_from_kallsyms_filename(char *kcore_filename, 979static bool filename_from_kallsyms_filename(char *filename,
770 const char *kallsyms_filename) 980 const char *base_name,
981 const char *kallsyms_filename)
771{ 982{
772 char *name; 983 char *name;
773 984
774 strcpy(kcore_filename, kallsyms_filename); 985 strcpy(filename, kallsyms_filename);
775 name = strrchr(kcore_filename, '/'); 986 name = strrchr(filename, '/');
776 if (!name) 987 if (!name)
777 return false; 988 return false;
778 989
779 if (!strcmp(name, "/kallsyms")) { 990 name += 1;
780 strcpy(name, "/kcore"); 991
992 if (!strcmp(name, "kallsyms")) {
993 strcpy(name, base_name);
781 return true; 994 return true;
782 } 995 }
783 996
784 return false; 997 return false;
785} 998}
786 999
1000static int validate_kcore_modules(const char *kallsyms_filename,
1001 struct map *map)
1002{
1003 struct map_groups *kmaps = map__kmap(map)->kmaps;
1004 char modules_filename[PATH_MAX];
1005
1006 if (!filename_from_kallsyms_filename(modules_filename, "modules",
1007 kallsyms_filename))
1008 return -EINVAL;
1009
1010 if (do_validate_kcore_modules(modules_filename, map, kmaps))
1011 return -EINVAL;
1012
1013 return 0;
1014}
1015
1016struct kcore_mapfn_data {
1017 struct dso *dso;
1018 enum map_type type;
1019 struct list_head maps;
1020};
1021
1022static int kcore_mapfn(u64 start, u64 len, u64 pgoff, void *data)
1023{
1024 struct kcore_mapfn_data *md = data;
1025 struct map *map;
1026
1027 map = map__new2(start, md->dso, md->type);
1028 if (map == NULL)
1029 return -ENOMEM;
1030
1031 map->end = map->start + len;
1032 map->pgoff = pgoff;
1033
1034 list_add(&map->node, &md->maps);
1035
1036 return 0;
1037}
1038
787static int dso__load_kcore(struct dso *dso, struct map *map, 1039static int dso__load_kcore(struct dso *dso, struct map *map,
788 const char *kallsyms_filename) 1040 const char *kallsyms_filename)
789{ 1041{
@@ -800,8 +1052,12 @@ static int dso__load_kcore(struct dso *dso, struct map *map,
800 if (map != machine->vmlinux_maps[map->type]) 1052 if (map != machine->vmlinux_maps[map->type])
801 return -EINVAL; 1053 return -EINVAL;
802 1054
803 if (!kcore_filename_from_kallsyms_filename(kcore_filename, 1055 if (!filename_from_kallsyms_filename(kcore_filename, "kcore",
804 kallsyms_filename)) 1056 kallsyms_filename))
1057 return -EINVAL;
1058
1059 /* All modules must be present at their original addresses */
1060 if (validate_kcore_modules(kallsyms_filename, map))
805 return -EINVAL; 1061 return -EINVAL;
806 1062
807 md.dso = dso; 1063 md.dso = dso;
@@ -1188,6 +1444,105 @@ out:
1188 return err; 1444 return err;
1189} 1445}
1190 1446
1447static int find_matching_kcore(struct map *map, char *dir, size_t dir_sz)
1448{
1449 char kallsyms_filename[PATH_MAX];
1450 struct dirent *dent;
1451 int ret = -1;
1452 DIR *d;
1453
1454 d = opendir(dir);
1455 if (!d)
1456 return -1;
1457
1458 while (1) {
1459 dent = readdir(d);
1460 if (!dent)
1461 break;
1462 if (dent->d_type != DT_DIR)
1463 continue;
1464 scnprintf(kallsyms_filename, sizeof(kallsyms_filename),
1465 "%s/%s/kallsyms", dir, dent->d_name);
1466 if (!validate_kcore_modules(kallsyms_filename, map)) {
1467 strlcpy(dir, kallsyms_filename, dir_sz);
1468 ret = 0;
1469 break;
1470 }
1471 }
1472
1473 closedir(d);
1474
1475 return ret;
1476}
1477
1478static char *dso__find_kallsyms(struct dso *dso, struct map *map)
1479{
1480 u8 host_build_id[BUILD_ID_SIZE];
1481 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
1482 bool is_host = false;
1483 char path[PATH_MAX];
1484
1485 if (!dso->has_build_id) {
1486 /*
1487 * Last resort, if we don't have a build-id and couldn't find
1488 * any vmlinux file, try the running kernel kallsyms table.
1489 */
1490 goto proc_kallsyms;
1491 }
1492
1493 if (sysfs__read_build_id("/sys/kernel/notes", host_build_id,
1494 sizeof(host_build_id)) == 0)
1495 is_host = dso__build_id_equal(dso, host_build_id);
1496
1497 build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
1498
1499 /* Use /proc/kallsyms if possible */
1500 if (is_host) {
1501 DIR *d;
1502 int fd;
1503
1504 /* If no cached kcore go with /proc/kallsyms */
1505 scnprintf(path, sizeof(path), "%s/[kernel.kcore]/%s",
1506 buildid_dir, sbuild_id);
1507 d = opendir(path);
1508 if (!d)
1509 goto proc_kallsyms;
1510 closedir(d);
1511
1512 /*
1513 * Do not check the build-id cache, until we know we cannot use
1514 * /proc/kcore.
1515 */
1516 fd = open("/proc/kcore", O_RDONLY);
1517 if (fd != -1) {
1518 close(fd);
1519 /* If module maps match go with /proc/kallsyms */
1520 if (!validate_kcore_modules("/proc/kallsyms", map))
1521 goto proc_kallsyms;
1522 }
1523
1524 /* Find kallsyms in build-id cache with kcore */
1525 if (!find_matching_kcore(map, path, sizeof(path)))
1526 return strdup(path);
1527
1528 goto proc_kallsyms;
1529 }
1530
1531 scnprintf(path, sizeof(path), "%s/[kernel.kallsyms]/%s",
1532 buildid_dir, sbuild_id);
1533
1534 if (access(path, F_OK)) {
1535 pr_err("No kallsyms or vmlinux with build-id %s was found\n",
1536 sbuild_id);
1537 return NULL;
1538 }
1539
1540 return strdup(path);
1541
1542proc_kallsyms:
1543 return strdup("/proc/kallsyms");
1544}
1545
1191static int dso__load_kernel_sym(struct dso *dso, struct map *map, 1546static int dso__load_kernel_sym(struct dso *dso, struct map *map,
1192 symbol_filter_t filter) 1547 symbol_filter_t filter)
1193{ 1548{
@@ -1214,7 +1569,7 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map,
1214 goto do_kallsyms; 1569 goto do_kallsyms;
1215 } 1570 }
1216 1571
1217 if (symbol_conf.vmlinux_name != NULL) { 1572 if (!symbol_conf.ignore_vmlinux && symbol_conf.vmlinux_name != NULL) {
1218 err = dso__load_vmlinux(dso, map, 1573 err = dso__load_vmlinux(dso, map,
1219 symbol_conf.vmlinux_name, filter); 1574 symbol_conf.vmlinux_name, filter);
1220 if (err > 0) { 1575 if (err > 0) {
@@ -1226,7 +1581,7 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map,
1226 return err; 1581 return err;
1227 } 1582 }
1228 1583
1229 if (vmlinux_path != NULL) { 1584 if (!symbol_conf.ignore_vmlinux && vmlinux_path != NULL) {
1230 err = dso__load_vmlinux_path(dso, map, filter); 1585 err = dso__load_vmlinux_path(dso, map, filter);
1231 if (err > 0) 1586 if (err > 0)
1232 return err; 1587 return err;
@@ -1236,51 +1591,11 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map,
1236 if (symbol_conf.symfs[0] != 0) 1591 if (symbol_conf.symfs[0] != 0)
1237 return -1; 1592 return -1;
1238 1593
1239 /* 1594 kallsyms_allocated_filename = dso__find_kallsyms(dso, map);
1240 * Say the kernel DSO was created when processing the build-id header table, 1595 if (!kallsyms_allocated_filename)
1241 * we have a build-id, so check if it is the same as the running kernel, 1596 return -1;
1242 * using it if it is.
1243 */
1244 if (dso->has_build_id) {
1245 u8 kallsyms_build_id[BUILD_ID_SIZE];
1246 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
1247
1248 if (sysfs__read_build_id("/sys/kernel/notes", kallsyms_build_id,
1249 sizeof(kallsyms_build_id)) == 0) {
1250 if (dso__build_id_equal(dso, kallsyms_build_id)) {
1251 kallsyms_filename = "/proc/kallsyms";
1252 goto do_kallsyms;
1253 }
1254 }
1255 /*
1256 * Now look if we have it on the build-id cache in
1257 * $HOME/.debug/[kernel.kallsyms].
1258 */
1259 build_id__sprintf(dso->build_id, sizeof(dso->build_id),
1260 sbuild_id);
1261
1262 if (asprintf(&kallsyms_allocated_filename,
1263 "%s/.debug/[kernel.kallsyms]/%s",
1264 getenv("HOME"), sbuild_id) == -1) {
1265 pr_err("Not enough memory for kallsyms file lookup\n");
1266 return -1;
1267 }
1268
1269 kallsyms_filename = kallsyms_allocated_filename;
1270 1597
1271 if (access(kallsyms_filename, F_OK)) { 1598 kallsyms_filename = kallsyms_allocated_filename;
1272 pr_err("No kallsyms or vmlinux with build-id %s "
1273 "was found\n", sbuild_id);
1274 free(kallsyms_allocated_filename);
1275 return -1;
1276 }
1277 } else {
1278 /*
1279 * Last resort, if we don't have a build-id and couldn't find
1280 * any vmlinux file, try the running kernel kallsyms table.
1281 */
1282 kallsyms_filename = "/proc/kallsyms";
1283 }
1284 1599
1285do_kallsyms: 1600do_kallsyms:
1286 err = dso__load_kallsyms(dso, kallsyms_filename, map, filter); 1601 err = dso__load_kallsyms(dso, kallsyms_filename, map, filter);
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index fd5b70ea2981..07de8fea2f48 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -13,7 +13,7 @@
13#include <libgen.h> 13#include <libgen.h>
14#include "build-id.h" 14#include "build-id.h"
15 15
16#ifdef LIBELF_SUPPORT 16#ifdef HAVE_LIBELF_SUPPORT
17#include <libelf.h> 17#include <libelf.h>
18#include <gelf.h> 18#include <gelf.h>
19#endif 19#endif
@@ -21,7 +21,7 @@
21 21
22#include "dso.h" 22#include "dso.h"
23 23
24#ifdef HAVE_CPLUS_DEMANGLE 24#ifdef HAVE_CPLUS_DEMANGLE_SUPPORT
25extern char *cplus_demangle(const char *, int); 25extern char *cplus_demangle(const char *, int);
26 26
27static inline char *bfd_demangle(void __maybe_unused *v, const char *c, int i) 27static inline char *bfd_demangle(void __maybe_unused *v, const char *c, int i)
@@ -46,7 +46,7 @@ static inline char *bfd_demangle(void __maybe_unused *v,
46 * libelf 0.8.x and earlier do not support ELF_C_READ_MMAP; 46 * libelf 0.8.x and earlier do not support ELF_C_READ_MMAP;
47 * for newer versions we can use mmap to reduce memory usage: 47 * for newer versions we can use mmap to reduce memory usage:
48 */ 48 */
49#ifdef LIBELF_MMAP 49#ifdef HAVE_LIBELF_MMAP_SUPPORT
50# define PERF_ELF_C_READ_MMAP ELF_C_READ_MMAP 50# define PERF_ELF_C_READ_MMAP ELF_C_READ_MMAP
51#else 51#else
52# define PERF_ELF_C_READ_MMAP ELF_C_READ 52# define PERF_ELF_C_READ_MMAP ELF_C_READ
@@ -85,6 +85,7 @@ struct symbol_conf {
85 unsigned short priv_size; 85 unsigned short priv_size;
86 unsigned short nr_events; 86 unsigned short nr_events;
87 bool try_vmlinux_path, 87 bool try_vmlinux_path,
88 ignore_vmlinux,
88 show_kernel_path, 89 show_kernel_path,
89 use_modules, 90 use_modules,
90 sort_by_name, 91 sort_by_name,
@@ -178,7 +179,7 @@ struct symsrc {
178 int fd; 179 int fd;
179 enum dso_binary_type type; 180 enum dso_binary_type type;
180 181
181#ifdef LIBELF_SUPPORT 182#ifdef HAVE_LIBELF_SUPPORT
182 Elf *elf; 183 Elf *elf;
183 GElf_Ehdr ehdr; 184 GElf_Ehdr ehdr;
184 185
@@ -222,6 +223,9 @@ int sysfs__read_build_id(const char *filename, void *bf, size_t size);
222int kallsyms__parse(const char *filename, void *arg, 223int kallsyms__parse(const char *filename, void *arg,
223 int (*process_symbol)(void *arg, const char *name, 224 int (*process_symbol)(void *arg, const char *name,
224 char type, u64 start)); 225 char type, u64 start));
226int modules__parse(const char *filename, void *arg,
227 int (*process_module)(void *arg, const char *name,
228 u64 start));
225int filename__read_debuglink(const char *filename, char *debuglink, 229int filename__read_debuglink(const char *filename, char *debuglink,
226 size_t size); 230 size_t size);
227 231
@@ -252,4 +256,21 @@ typedef int (*mapfn_t)(u64 start, u64 len, u64 pgoff, void *data);
252int file__read_maps(int fd, bool exe, mapfn_t mapfn, void *data, 256int file__read_maps(int fd, bool exe, mapfn_t mapfn, void *data,
253 bool *is_64_bit); 257 bool *is_64_bit);
254 258
259#define PERF_KCORE_EXTRACT "/tmp/perf-kcore-XXXXXX"
260
261struct kcore_extract {
262 char *kcore_filename;
263 u64 addr;
264 u64 offs;
265 u64 len;
266 char extract_filename[sizeof(PERF_KCORE_EXTRACT)];
267 int fd;
268};
269
270int kcore_extract__create(struct kcore_extract *kce);
271void kcore_extract__delete(struct kcore_extract *kce);
272
273int kcore_copy(const char *from_dir, const char *to_dir);
274int compare_proc_modules(const char *from, const char *to);
275
255#endif /* __PERF_SYMBOL */ 276#endif /* __PERF_SYMBOL */
diff --git a/tools/perf/util/sysfs.c b/tools/perf/util/sysfs.c
deleted file mode 100644
index f71e9eafe15a..000000000000
--- a/tools/perf/util/sysfs.c
+++ /dev/null
@@ -1,60 +0,0 @@
1
2#include "util.h"
3#include "sysfs.h"
4
5static const char * const sysfs_known_mountpoints[] = {
6 "/sys",
7 0,
8};
9
10static int sysfs_found;
11char sysfs_mountpoint[PATH_MAX + 1];
12
13static int sysfs_valid_mountpoint(const char *sysfs)
14{
15 struct statfs st_fs;
16
17 if (statfs(sysfs, &st_fs) < 0)
18 return -ENOENT;
19 else if (st_fs.f_type != (long) SYSFS_MAGIC)
20 return -ENOENT;
21
22 return 0;
23}
24
25const char *sysfs_find_mountpoint(void)
26{
27 const char * const *ptr;
28 char type[100];
29 FILE *fp;
30
31 if (sysfs_found)
32 return (const char *) sysfs_mountpoint;
33
34 ptr = sysfs_known_mountpoints;
35 while (*ptr) {
36 if (sysfs_valid_mountpoint(*ptr) == 0) {
37 sysfs_found = 1;
38 strcpy(sysfs_mountpoint, *ptr);
39 return sysfs_mountpoint;
40 }
41 ptr++;
42 }
43
44 /* give up and parse /proc/mounts */
45 fp = fopen("/proc/mounts", "r");
46 if (fp == NULL)
47 return NULL;
48
49 while (!sysfs_found &&
50 fscanf(fp, "%*s %" STR(PATH_MAX) "s %99s %*s %*d %*d\n",
51 sysfs_mountpoint, type) == 2) {
52
53 if (strcmp(type, "sysfs") == 0)
54 sysfs_found = 1;
55 }
56
57 fclose(fp);
58
59 return sysfs_found ? sysfs_mountpoint : NULL;
60}
diff --git a/tools/perf/util/sysfs.h b/tools/perf/util/sysfs.h
deleted file mode 100644
index a813b7203938..000000000000
--- a/tools/perf/util/sysfs.h
+++ /dev/null
@@ -1,6 +0,0 @@
1#ifndef __SYSFS_H__
2#define __SYSFS_H__
3
4const char *sysfs_find_mountpoint(void);
5
6#endif /* __DEBUGFS_H__ */
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index e3d4a550a703..cd8e2f592719 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -6,86 +6,137 @@
6#include "thread.h" 6#include "thread.h"
7#include "util.h" 7#include "util.h"
8#include "debug.h" 8#include "debug.h"
9#include "comm.h"
9 10
10struct thread *thread__new(pid_t pid, pid_t tid) 11struct thread *thread__new(pid_t pid, pid_t tid)
11{ 12{
12 struct thread *self = zalloc(sizeof(*self)); 13 char *comm_str;
13 14 struct comm *comm;
14 if (self != NULL) { 15 struct thread *thread = zalloc(sizeof(*thread));
15 map_groups__init(&self->mg); 16
16 self->pid_ = pid; 17 if (thread != NULL) {
17 self->tid = tid; 18 map_groups__init(&thread->mg);
18 self->ppid = -1; 19 thread->pid_ = pid;
19 self->comm = malloc(32); 20 thread->tid = tid;
20 if (self->comm) 21 thread->ppid = -1;
21 snprintf(self->comm, 32, ":%d", self->tid); 22 INIT_LIST_HEAD(&thread->comm_list);
23
24 comm_str = malloc(32);
25 if (!comm_str)
26 goto err_thread;
27
28 snprintf(comm_str, 32, ":%d", tid);
29 comm = comm__new(comm_str, 0);
30 free(comm_str);
31 if (!comm)
32 goto err_thread;
33
34 list_add(&comm->list, &thread->comm_list);
35 }
36
37 return thread;
38
39err_thread:
40 free(thread);
41 return NULL;
42}
43
44void thread__delete(struct thread *thread)
45{
46 struct comm *comm, *tmp;
47
48 map_groups__exit(&thread->mg);
49 list_for_each_entry_safe(comm, tmp, &thread->comm_list, list) {
50 list_del(&comm->list);
51 comm__free(comm);
22 } 52 }
23 53
24 return self; 54 free(thread);
25} 55}
26 56
27void thread__delete(struct thread *self) 57struct comm *thread__comm(const struct thread *thread)
28{ 58{
29 map_groups__exit(&self->mg); 59 if (list_empty(&thread->comm_list))
30 free(self->comm); 60 return NULL;
31 free(self); 61
62 return list_first_entry(&thread->comm_list, struct comm, list);
32} 63}
33 64
34int thread__set_comm(struct thread *self, const char *comm) 65/* CHECKME: time should always be 0 if event aren't ordered */
66int thread__set_comm(struct thread *thread, const char *str, u64 timestamp)
35{ 67{
36 int err; 68 struct comm *new, *curr = thread__comm(thread);
37 69
38 if (self->comm) 70 /* Override latest entry if it had no specific time coverage */
39 free(self->comm); 71 if (!curr->start) {
40 self->comm = strdup(comm); 72 comm__override(curr, str, timestamp);
41 err = self->comm == NULL ? -ENOMEM : 0; 73 return 0;
42 if (!err) {
43 self->comm_set = true;
44 } 74 }
45 return err; 75
76 new = comm__new(str, timestamp);
77 if (!new)
78 return -ENOMEM;
79
80 list_add(&new->list, &thread->comm_list);
81 thread->comm_set = true;
82
83 return 0;
84}
85
86const char *thread__comm_str(const struct thread *thread)
87{
88 const struct comm *comm = thread__comm(thread);
89
90 if (!comm)
91 return NULL;
92
93 return comm__str(comm);
46} 94}
47 95
48int thread__comm_len(struct thread *self) 96/* CHECKME: it should probably better return the max comm len from its comm list */
97int thread__comm_len(struct thread *thread)
49{ 98{
50 if (!self->comm_len) { 99 if (!thread->comm_len) {
51 if (!self->comm) 100 const char *comm = thread__comm_str(thread);
101 if (!comm)
52 return 0; 102 return 0;
53 self->comm_len = strlen(self->comm); 103 thread->comm_len = strlen(comm);
54 } 104 }
55 105
56 return self->comm_len; 106 return thread->comm_len;
57} 107}
58 108
59size_t thread__fprintf(struct thread *thread, FILE *fp) 109size_t thread__fprintf(struct thread *thread, FILE *fp)
60{ 110{
61 return fprintf(fp, "Thread %d %s\n", thread->tid, thread->comm) + 111 return fprintf(fp, "Thread %d %s\n", thread->tid, thread__comm_str(thread)) +
62 map_groups__fprintf(&thread->mg, verbose, fp); 112 map_groups__fprintf(&thread->mg, verbose, fp);
63} 113}
64 114
65void thread__insert_map(struct thread *self, struct map *map) 115void thread__insert_map(struct thread *thread, struct map *map)
66{ 116{
67 map_groups__fixup_overlappings(&self->mg, map, verbose, stderr); 117 map_groups__fixup_overlappings(&thread->mg, map, verbose, stderr);
68 map_groups__insert(&self->mg, map); 118 map_groups__insert(&thread->mg, map);
69} 119}
70 120
71int thread__fork(struct thread *self, struct thread *parent) 121int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp)
72{ 122{
73 int i; 123 int i, err;
74 124
75 if (parent->comm_set) { 125 if (parent->comm_set) {
76 if (self->comm) 126 const char *comm = thread__comm_str(parent);
77 free(self->comm); 127 if (!comm)
78 self->comm = strdup(parent->comm);
79 if (!self->comm)
80 return -ENOMEM; 128 return -ENOMEM;
81 self->comm_set = true; 129 err = thread__set_comm(thread, comm, timestamp);
130 if (!err)
131 return err;
132 thread->comm_set = true;
82 } 133 }
83 134
84 for (i = 0; i < MAP__NR_TYPES; ++i) 135 for (i = 0; i < MAP__NR_TYPES; ++i)
85 if (map_groups__clone(&self->mg, &parent->mg, i) < 0) 136 if (map_groups__clone(&thread->mg, &parent->mg, i) < 0)
86 return -ENOMEM; 137 return -ENOMEM;
87 138
88 self->ppid = parent->tid; 139 thread->ppid = parent->tid;
89 140
90 return 0; 141 return 0;
91} 142}
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 4ebbb40d46d4..897c1b2a750a 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -2,6 +2,7 @@
2#define __PERF_THREAD_H 2#define __PERF_THREAD_H
3 3
4#include <linux/rbtree.h> 4#include <linux/rbtree.h>
5#include <linux/list.h>
5#include <unistd.h> 6#include <unistd.h>
6#include <sys/types.h> 7#include <sys/types.h>
7#include "symbol.h" 8#include "symbol.h"
@@ -18,31 +19,34 @@ struct thread {
18 char shortname[3]; 19 char shortname[3];
19 bool comm_set; 20 bool comm_set;
20 bool dead; /* if set thread has exited */ 21 bool dead; /* if set thread has exited */
21 char *comm; 22 struct list_head comm_list;
22 int comm_len; 23 int comm_len;
23 24
24 void *priv; 25 void *priv;
25}; 26};
26 27
27struct machine; 28struct machine;
29struct comm;
28 30
29struct thread *thread__new(pid_t pid, pid_t tid); 31struct thread *thread__new(pid_t pid, pid_t tid);
30void thread__delete(struct thread *self); 32void thread__delete(struct thread *thread);
31static inline void thread__exited(struct thread *thread) 33static inline void thread__exited(struct thread *thread)
32{ 34{
33 thread->dead = true; 35 thread->dead = true;
34} 36}
35 37
36int thread__set_comm(struct thread *self, const char *comm); 38int thread__set_comm(struct thread *thread, const char *comm, u64 timestamp);
37int thread__comm_len(struct thread *self); 39int thread__comm_len(struct thread *thread);
38void thread__insert_map(struct thread *self, struct map *map); 40struct comm *thread__comm(const struct thread *thread);
39int thread__fork(struct thread *self, struct thread *parent); 41const char *thread__comm_str(const struct thread *thread);
42void thread__insert_map(struct thread *thread, struct map *map);
43int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp);
40size_t thread__fprintf(struct thread *thread, FILE *fp); 44size_t thread__fprintf(struct thread *thread, FILE *fp);
41 45
42static inline struct map *thread__find_map(struct thread *self, 46static inline struct map *thread__find_map(struct thread *thread,
43 enum map_type type, u64 addr) 47 enum map_type type, u64 addr)
44{ 48{
45 return self ? map_groups__find(&self->mg, type, addr) : NULL; 49 return thread ? map_groups__find(&thread->mg, type, addr) : NULL;
46} 50}
47 51
48void thread__find_addr_map(struct thread *thread, struct machine *machine, 52void thread__find_addr_map(struct thread *thread, struct machine *machine,
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h
index b554ffc462b6..88cfeaff600b 100644
--- a/tools/perf/util/top.h
+++ b/tools/perf/util/top.h
@@ -24,6 +24,7 @@ struct perf_top {
24 u64 exact_samples; 24 u64 exact_samples;
25 u64 guest_us_samples, guest_kernel_samples; 25 u64 guest_us_samples, guest_kernel_samples;
26 int print_entries, count_filter, delay_secs; 26 int print_entries, count_filter, delay_secs;
27 int max_stack;
27 bool hide_kernel_symbols, hide_user_symbols, zero; 28 bool hide_kernel_symbols, hide_user_symbols, zero;
28 bool use_tui, use_stdio; 29 bool use_tui, use_stdio;
29 bool kptr_restrict_warned; 30 bool kptr_restrict_warned;
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index e9e1c03f927d..6681f71f2f95 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -120,42 +120,6 @@ raw_field_value(struct event_format *event, const char *name, void *data)
120 return val; 120 return val;
121} 121}
122 122
123void *raw_field_ptr(struct event_format *event, const char *name, void *data)
124{
125 struct format_field *field;
126
127 field = pevent_find_any_field(event, name);
128 if (!field)
129 return NULL;
130
131 if (field->flags & FIELD_IS_DYNAMIC) {
132 int offset;
133
134 offset = *(int *)(data + field->offset);
135 offset &= 0xffff;
136
137 return data + offset;
138 }
139
140 return data + field->offset;
141}
142
143int trace_parse_common_type(struct pevent *pevent, void *data)
144{
145 struct pevent_record record;
146
147 record.data = data;
148 return pevent_data_type(pevent, &record);
149}
150
151int trace_parse_common_pid(struct pevent *pevent, void *data)
152{
153 struct pevent_record record;
154
155 record.data = data;
156 return pevent_data_pid(pevent, &record);
157}
158
159unsigned long long read_size(struct event_format *event, void *ptr, int size) 123unsigned long long read_size(struct event_format *event, void *ptr, int size)
160{ 124{
161 return pevent_read_number(event->pevent, ptr, size); 125 return pevent_read_number(event->pevent, ptr, size);
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index fafe1a40444a..04df63114109 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -11,8 +11,6 @@ union perf_event;
11struct perf_tool; 11struct perf_tool;
12struct thread; 12struct thread;
13 13
14extern struct pevent *perf_pevent;
15
16int bigendian(void); 14int bigendian(void);
17 15
18struct pevent *read_trace_init(int file_bigendian, int host_bigendian); 16struct pevent *read_trace_init(int file_bigendian, int host_bigendian);
@@ -23,26 +21,19 @@ int parse_ftrace_file(struct pevent *pevent, char *buf, unsigned long size);
23int parse_event_file(struct pevent *pevent, 21int parse_event_file(struct pevent *pevent,
24 char *buf, unsigned long size, char *sys); 22 char *buf, unsigned long size, char *sys);
25 23
26struct pevent_record *trace_peek_data(struct pevent *pevent, int cpu);
27
28unsigned long long 24unsigned long long
29raw_field_value(struct event_format *event, const char *name, void *data); 25raw_field_value(struct event_format *event, const char *name, void *data);
30void *raw_field_ptr(struct event_format *event, const char *name, void *data);
31 26
32void parse_proc_kallsyms(struct pevent *pevent, char *file, unsigned int size); 27void parse_proc_kallsyms(struct pevent *pevent, char *file, unsigned int size);
33void parse_ftrace_printk(struct pevent *pevent, char *file, unsigned int size); 28void parse_ftrace_printk(struct pevent *pevent, char *file, unsigned int size);
34 29
35ssize_t trace_report(int fd, struct pevent **pevent, bool repipe); 30ssize_t trace_report(int fd, struct pevent **pevent, bool repipe);
36 31
37int trace_parse_common_type(struct pevent *pevent, void *data);
38int trace_parse_common_pid(struct pevent *pevent, void *data);
39
40struct event_format *trace_find_next_event(struct pevent *pevent, 32struct event_format *trace_find_next_event(struct pevent *pevent,
41 struct event_format *event); 33 struct event_format *event);
42unsigned long long read_size(struct event_format *event, void *ptr, int size); 34unsigned long long read_size(struct event_format *event, void *ptr, int size);
43unsigned long long eval_flag(const char *flag); 35unsigned long long eval_flag(const char *flag);
44 36
45struct pevent_record *trace_read_data(struct pevent *pevent, int cpu);
46int read_tracing_data(int fd, struct list_head *pattrs); 37int read_tracing_data(int fd, struct list_head *pattrs);
47 38
48struct tracing_data { 39struct tracing_data {
diff --git a/tools/perf/util/unwind.h b/tools/perf/util/unwind.h
index cb6bc503a792..ec0c71a2ca2e 100644
--- a/tools/perf/util/unwind.h
+++ b/tools/perf/util/unwind.h
@@ -13,7 +13,7 @@ struct unwind_entry {
13 13
14typedef int (*unwind_entry_cb_t)(struct unwind_entry *entry, void *arg); 14typedef int (*unwind_entry_cb_t)(struct unwind_entry *entry, void *arg);
15 15
16#ifdef LIBUNWIND_SUPPORT 16#ifdef HAVE_LIBUNWIND_SUPPORT
17int unwind__get_entries(unwind_entry_cb_t cb, void *arg, 17int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
18 struct machine *machine, 18 struct machine *machine,
19 struct thread *thread, 19 struct thread *thread,
@@ -31,5 +31,5 @@ unwind__get_entries(unwind_entry_cb_t cb __maybe_unused,
31{ 31{
32 return 0; 32 return 0;
33} 33}
34#endif /* LIBUNWIND_SUPPORT */ 34#endif /* HAVE_LIBUNWIND_SUPPORT */
35#endif /* __UNWIND_H */ 35#endif /* __UNWIND_H */
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 6d17b18e915d..28a0a89c1f73 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -1,7 +1,7 @@
1#include "../perf.h" 1#include "../perf.h"
2#include "util.h" 2#include "util.h"
3#include <sys/mman.h> 3#include <sys/mman.h>
4#ifdef BACKTRACE_SUPPORT 4#ifdef HAVE_BACKTRACE_SUPPORT
5#include <execinfo.h> 5#include <execinfo.h>
6#endif 6#endif
7#include <stdio.h> 7#include <stdio.h>
@@ -55,17 +55,20 @@ int mkdir_p(char *path, mode_t mode)
55 return (stat(path, &st) && mkdir(path, mode)) ? -1 : 0; 55 return (stat(path, &st) && mkdir(path, mode)) ? -1 : 0;
56} 56}
57 57
58static int slow_copyfile(const char *from, const char *to) 58static int slow_copyfile(const char *from, const char *to, mode_t mode)
59{ 59{
60 int err = 0; 60 int err = -1;
61 char *line = NULL; 61 char *line = NULL;
62 size_t n; 62 size_t n;
63 FILE *from_fp = fopen(from, "r"), *to_fp; 63 FILE *from_fp = fopen(from, "r"), *to_fp;
64 mode_t old_umask;
64 65
65 if (from_fp == NULL) 66 if (from_fp == NULL)
66 goto out; 67 goto out;
67 68
69 old_umask = umask(mode ^ 0777);
68 to_fp = fopen(to, "w"); 70 to_fp = fopen(to, "w");
71 umask(old_umask);
69 if (to_fp == NULL) 72 if (to_fp == NULL)
70 goto out_fclose_from; 73 goto out_fclose_from;
71 74
@@ -82,7 +85,7 @@ out:
82 return err; 85 return err;
83} 86}
84 87
85int copyfile(const char *from, const char *to) 88int copyfile_mode(const char *from, const char *to, mode_t mode)
86{ 89{
87 int fromfd, tofd; 90 int fromfd, tofd;
88 struct stat st; 91 struct stat st;
@@ -93,13 +96,13 @@ int copyfile(const char *from, const char *to)
93 goto out; 96 goto out;
94 97
95 if (st.st_size == 0) /* /proc? do it slowly... */ 98 if (st.st_size == 0) /* /proc? do it slowly... */
96 return slow_copyfile(from, to); 99 return slow_copyfile(from, to, mode);
97 100
98 fromfd = open(from, O_RDONLY); 101 fromfd = open(from, O_RDONLY);
99 if (fromfd < 0) 102 if (fromfd < 0)
100 goto out; 103 goto out;
101 104
102 tofd = creat(to, 0755); 105 tofd = creat(to, mode);
103 if (tofd < 0) 106 if (tofd < 0)
104 goto out_close_from; 107 goto out_close_from;
105 108
@@ -121,6 +124,11 @@ out:
121 return err; 124 return err;
122} 125}
123 126
127int copyfile(const char *from, const char *to)
128{
129 return copyfile_mode(from, to, 0755);
130}
131
124unsigned long convert_unit(unsigned long value, char *unit) 132unsigned long convert_unit(unsigned long value, char *unit)
125{ 133{
126 *unit = ' '; 134 *unit = ' ';
@@ -204,7 +212,7 @@ int hex2u64(const char *ptr, u64 *long_val)
204} 212}
205 213
206/* Obtain a backtrace and print it to stdout. */ 214/* Obtain a backtrace and print it to stdout. */
207#ifdef BACKTRACE_SUPPORT 215#ifdef HAVE_BACKTRACE_SUPPORT
208void dump_stack(void) 216void dump_stack(void)
209{ 217{
210 void *array[16]; 218 void *array[16];
@@ -361,3 +369,47 @@ int parse_nsec_time(const char *str, u64 *ptime)
361 *ptime = time_sec * NSEC_PER_SEC + time_nsec; 369 *ptime = time_sec * NSEC_PER_SEC + time_nsec;
362 return 0; 370 return 0;
363} 371}
372
373unsigned long parse_tag_value(const char *str, struct parse_tag *tags)
374{
375 struct parse_tag *i = tags;
376
377 while (i->tag) {
378 char *s;
379
380 s = strchr(str, i->tag);
381 if (s) {
382 unsigned long int value;
383 char *endptr;
384
385 value = strtoul(str, &endptr, 10);
386 if (s != endptr)
387 break;
388
389 if (value > ULONG_MAX / i->mult)
390 break;
391 value *= i->mult;
392 return value;
393 }
394 i++;
395 }
396
397 return (unsigned long) -1;
398}
399
400int filename__read_int(const char *filename, int *value)
401{
402 char line[64];
403 int fd = open(filename, O_RDONLY), err = -1;
404
405 if (fd < 0)
406 return -1;
407
408 if (read(fd, line, sizeof(line)) > 0) {
409 *value = atoi(line);
410 err = 0;
411 }
412
413 close(fd);
414 return err;
415}
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index a53535949043..c8f362daba87 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -128,6 +128,8 @@ void put_tracing_file(char *file);
128#endif 128#endif
129#endif 129#endif
130 130
131#define PERF_GTK_DSO "libperf-gtk.so"
132
131/* General helper functions */ 133/* General helper functions */
132extern void usage(const char *err) NORETURN; 134extern void usage(const char *err) NORETURN;
133extern void die(const char *err, ...) NORETURN __attribute__((format (printf, 1, 2))); 135extern void die(const char *err, ...) NORETURN __attribute__((format (printf, 1, 2)));
@@ -241,6 +243,7 @@ static inline int sane_case(int x, int high)
241 243
242int mkdir_p(char *path, mode_t mode); 244int mkdir_p(char *path, mode_t mode);
243int copyfile(const char *from, const char *to); 245int copyfile(const char *from, const char *to);
246int copyfile_mode(const char *from, const char *to, mode_t mode);
244 247
245s64 perf_atoll(const char *str); 248s64 perf_atoll(const char *str);
246char **argv_split(const char *str, int *argcp); 249char **argv_split(const char *str, int *argcp);
@@ -270,6 +273,13 @@ bool is_power_of_2(unsigned long n)
270 return (n != 0 && ((n & (n - 1)) == 0)); 273 return (n != 0 && ((n & (n - 1)) == 0));
271} 274}
272 275
276static inline unsigned next_pow2(unsigned x)
277{
278 if (!x)
279 return 1;
280 return 1ULL << (32 - __builtin_clz(x - 1));
281}
282
273size_t hex_width(u64 v); 283size_t hex_width(u64 v);
274int hex2u64(const char *ptr, u64 *val); 284int hex2u64(const char *ptr, u64 *val);
275 285
@@ -281,4 +291,20 @@ void dump_stack(void);
281extern unsigned int page_size; 291extern unsigned int page_size;
282 292
283void get_term_dimensions(struct winsize *ws); 293void get_term_dimensions(struct winsize *ws);
294
295struct parse_tag {
296 char tag;
297 int mult;
298};
299
300unsigned long parse_tag_value(const char *str, struct parse_tag *tags);
301
302#define SRCLINE_UNKNOWN ((char *) "??:0")
303
304struct dso;
305
306char *get_srcline(struct dso *dso, unsigned long addr);
307void free_srcline(char *srcline);
308
309int filename__read_int(const char *filename, int *value);
284#endif /* GIT_COMPAT_UTIL_H */ 310#endif /* GIT_COMPAT_UTIL_H */
diff --git a/tools/scripts/Makefile.include b/tools/scripts/Makefile.include
index 0d0506d55c71..ee76544deecb 100644
--- a/tools/scripts/Makefile.include
+++ b/tools/scripts/Makefile.include
@@ -59,21 +59,22 @@ QUIET_SUBDIR0 = +$(MAKE) $(COMMAND_O) -C # space to separate -C and subdir
59QUIET_SUBDIR1 = 59QUIET_SUBDIR1 =
60 60
61ifneq ($(findstring $(MAKEFLAGS),s),s) 61ifneq ($(findstring $(MAKEFLAGS),s),s)
62ifneq ($(V),1) 62 ifneq ($(V),1)
63 QUIET_CC = @echo ' ' CC $@; 63 QUIET_CC = @echo ' CC '$@;
64 QUIET_AR = @echo ' ' AR $@; 64 QUIET_AR = @echo ' AR '$@;
65 QUIET_LINK = @echo ' ' LINK $@; 65 QUIET_LINK = @echo ' LINK '$@;
66 QUIET_MKDIR = @echo ' ' MKDIR $@; 66 QUIET_MKDIR = @echo ' MKDIR '$@;
67 QUIET_GEN = @echo ' ' GEN $@; 67 QUIET_GEN = @echo ' GEN '$@;
68 QUIET_SUBDIR0 = +@subdir= 68 QUIET_SUBDIR0 = +@subdir=
69 QUIET_SUBDIR1 = ;$(NO_SUBDIR) echo ' ' SUBDIR $$subdir; \ 69 QUIET_SUBDIR1 = ;$(NO_SUBDIR) \
70 echo ' SUBDIR '$$subdir; \
70 $(MAKE) $(PRINT_DIR) -C $$subdir 71 $(MAKE) $(PRINT_DIR) -C $$subdir
71 QUIET_FLEX = @echo ' ' FLEX $@; 72 QUIET_FLEX = @echo ' FLEX '$@;
72 QUIET_BISON = @echo ' ' BISON $@; 73 QUIET_BISON = @echo ' BISON '$@;
73 74
74 descend = \ 75 descend = \
75 +@echo ' ' DESCEND $(1); \ 76 +@echo ' DESCEND '$(1); \
76 mkdir -p $(OUTPUT)$(1) && \ 77 mkdir -p $(OUTPUT)$(1) && \
77 $(MAKE) $(COMMAND_O) subdir=$(if $(subdir),$(subdir)/$(1),$(1)) $(PRINT_DIR) -C $(1) $(2) 78 $(MAKE) $(COMMAND_O) subdir=$(if $(subdir),$(subdir)/$(1),$(1)) $(PRINT_DIR) -C $(1) $(2)
78endif 79 endif
79endif 80endif