aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2016-04-27 11:02:24 -0400
committerIngo Molnar <mingo@kernel.org>2016-04-27 11:02:24 -0400
commita8944c5bf86dc6c153a71f2a386738c0d3f5ff9c (patch)
treea251b1d510831dc071eadbbbe3e38a85fe643365 /tools/perf
parent67d61296ffcc850bffdd4466430cb91e5328f39a (diff)
parent4cb93446c587d56e2a54f4f83113daba2c0b6dee (diff)
Merge tag 'perf-core-for-mingo-20160427' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo: User visible changes: - perf trace --pf maj/min/all works with --call-graph: (Arnaldo Carvalho de Melo) Tracing write syscalls and major page faults with callchains while starting firefox, limiting the stack to 5 frames: # perf trace -e write --pf maj --max-stack 5 firefox 589.549 ( 0.014 ms): firefox/15377 write(fd: 4, buf: 0x7fff80acc898, count: 151) = 151 [0xfaed] (/usr/lib64/libpthread-2.22.so) fire_glxtest_process+0x5c (/usr/lib64/firefox/libxul.so) InstallGdkErrorHandler+0x41 (/usr/lib64/firefox/libxul.so) XREMain::XRE_mainInit+0x12c (/usr/lib64/firefox/libxul.so) XREMain::XRE_main+0x1e4 (/usr/lib64/firefox/libxul.so) 760.704 ( 0.000 ms): firefox/15332 majfault [gtk_tree_view_accessible_get_type+0x0] => /usr/lib64/libgtk-3.so.0.1800.9@0xa0850 (x.) gtk_tree_view_accessible_get_type+0x0 (/usr/lib64/libgtk-3.so.0.1800.9) gtk_tree_view_class_intern_init+0x1a54 (/usr/lib64/libgtk-3.so.0.1800.9) g_type_class_ref+0x6dd (/usr/lib64/libgobject-2.0.so.0.4600.2) [0x115378] (/usr/lib64/libgnutls.so.30.6.3) This automagically selects "--call-graph dwarf", use "--call-graph fp" on systems where -fno-omit-frame-pointer was used to built the components of interest, to incur in less overhead, or tune "--call-graph dwarf" appropriately, see 'perf record --help'. - Allow /proc/sys/kernel/perf_event_max_stack, that defaults to the old hard coded value of PERF_MAX_STACK_DEPTH (127), useful for huge callstacks for things like Groovy, Ruby, etc, and also to reduce overhead by limiting it to a smaller value, upcoming work will allow this to be done per-event (Arnaldo Carvalho de Melo) - Make 'perf trace --min-stack' be honoured by --pf and --event (Arnaldo Carvalho de Melo) - Make 'perf evlist -v' decode perf_event_attr->branch_sample_type (Arnaldo Carvalho de Melo) # perf record --call lbr usleep 1 # perf evlist -v cycles:ppp: ... sample_type: IP|TID|TIME|CALLCHAIN|PERIOD|BRANCH_STACK, ... branch_sample_type: USER|CALL_STACK|NO_FLAGS|NO_CYCLES # - Clear dummy entry accumulated period, fixing such 'perf top/report' output as: (Kan Liang) 4769.98% 0.01% 0.00% 0.01% tchain_edit [kernel] [k] update_fast_timekeeper - System calls with pid_t arguments gets them augmented with the COMM event more thoroughly: # trace -e perf_event_open perf stat -e cycles -p 15608 6.876 ( 0.014 ms): perf_event_open(attr_uptr: 0x2ae20d8, pid: 15608 (hexchat), cpu: -1, group_fd: -1, flags: FD_CLOEXEC) = 3 6.882 ( 0.005 ms): perf_event_open(attr_uptr: 0x2ae20d8, pid: 15639 (gmain), cpu: -1, group_fd: -1, flags: FD_CLOEXEC) = 4 6.889 ( 0.005 ms): perf_event_open(attr_uptr: 0x2ae20d8, pid: 15640 (gdbus), cpu: -1, group_fd: -1, flags: FD_CLOEXEC) = 5 ^^^^^^^^^^^^^^^^^^ ^C - Fix offline module name mismatch issue in 'perf probe' (Ravi Bangoria) - Fix module probe issue if no dwarf support in (Ravi Bangoria) Assorted fixes: - Fix off-by-one in write_buildid() (Andrey Ryabinin) - Fix segfault when printing callchains in 'perf script' (Chris Phlipot) - Replace assignment with comparison on assert check in 'perf test' entry (Colin Ian King) - Fix off-by-one comparison in intel-pt code (Colin Ian King) - Close target file on error path in 'perf probe' (Masami Hiramatsu) - Set default kprobe group name if not given in 'perf probe' (Masami Hiramatsu) - Avoid partial perf_event_header reads (Wang Nan) Infrastructure changes: - Update x86's syscall_64.tbl copy, adding preadv2 & pwritev2 (Arnaldo Carvalho de Melo) - Make the x86 clean quiet wrt syscall table removal (Jiri Olsa) Cleanups: - Simplify wrapper for LOCK_PI in 'perf bench futex' (Davidlohr Bueso) - Remove duplicate const qualifier (Eric Engestrom) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/Documentation/perf-report.txt2
-rw-r--r--tools/perf/Documentation/perf-script.txt2
-rw-r--r--tools/perf/Documentation/perf-top.txt2
-rw-r--r--tools/perf/Documentation/perf-trace.txt2
-rw-r--r--tools/perf/arch/x86/Makefile2
-rw-r--r--tools/perf/arch/x86/entry/syscalls/syscall_64.tbl2
-rw-r--r--tools/perf/bench/futex-lock-pi.c2
-rw-r--r--tools/perf/bench/futex.h6
-rw-r--r--tools/perf/bench/mem-functions.c22
-rw-r--r--tools/perf/builtin-report.c4
-rw-r--r--tools/perf/builtin-script.c16
-rw-r--r--tools/perf/builtin-top.c4
-rw-r--r--tools/perf/builtin-trace.c174
-rw-r--r--tools/perf/perf.c5
-rw-r--r--tools/perf/tests/event_update.c2
-rw-r--r--tools/perf/tests/hists_cumulate.c2
-rw-r--r--tools/perf/tests/hists_filter.c2
-rw-r--r--tools/perf/tests/hists_output.c2
-rw-r--r--tools/perf/trace/beauty/perf_event_open.c43
-rw-r--r--tools/perf/trace/beauty/pid.c5
-rw-r--r--tools/perf/util/build-id.c6
-rw-r--r--tools/perf/util/evlist.c12
-rw-r--r--tools/perf/util/evsel.c18
-rw-r--r--tools/perf/util/hist.c2
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-decoder.c2
-rw-r--r--tools/perf/util/machine.c6
-rw-r--r--tools/perf/util/probe-event.c114
-rw-r--r--tools/perf/util/probe-file.c3
-rw-r--r--tools/perf/util/scripting-engines/trace-event-perl.c2
-rw-r--r--tools/perf/util/thread.c21
-rw-r--r--tools/perf/util/thread.h2
-rw-r--r--tools/perf/util/util.c36
-rw-r--r--tools/perf/util/util.h4
33 files changed, 374 insertions, 155 deletions
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 496d42cdf02b..ebaf849e30ef 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -248,7 +248,7 @@ OPTIONS
248 Note that when using the --itrace option the synthesized callchain size 248 Note that when using the --itrace option the synthesized callchain size
249 will override this value if the synthesized callchain size is bigger. 249 will override this value if the synthesized callchain size is bigger.
250 250
251 Default: 127 251 Default: /proc/sys/kernel/perf_event_max_stack when present, 127 otherwise.
252 252
253-G:: 253-G::
254--inverted:: 254--inverted::
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index 4fc44c75263f..a856a1095893 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -267,7 +267,7 @@ include::itrace.txt[]
267 Note that when using the --itrace option the synthesized callchain size 267 Note that when using the --itrace option the synthesized callchain size
268 will override this value if the synthesized callchain size is bigger. 268 will override this value if the synthesized callchain size is bigger.
269 269
270 Default: 127 270 Default: /proc/sys/kernel/perf_event_max_stack when present, 127 otherwise.
271 271
272--ns:: 272--ns::
273 Use 9 decimal places when displaying time (i.e. show the nanoseconds) 273 Use 9 decimal places when displaying time (i.e. show the nanoseconds)
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt
index 19f046f027cd..91d638df3a6b 100644
--- a/tools/perf/Documentation/perf-top.txt
+++ b/tools/perf/Documentation/perf-top.txt
@@ -177,7 +177,7 @@ Default is to monitor all CPUS.
177 between information loss and faster processing especially for 177 between information loss and faster processing especially for
178 workloads that can have a very long callchain stack. 178 workloads that can have a very long callchain stack.
179 179
180 Default: 127 180 Default: /proc/sys/kernel/perf_event_max_stack when present, 127 otherwise.
181 181
182--ignore-callees=<regex>:: 182--ignore-callees=<regex>::
183 Ignore callees of the function(s) matching the given regex. 183 Ignore callees of the function(s) matching the given regex.
diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt
index c075c002eaa4..6afe20121bc0 100644
--- a/tools/perf/Documentation/perf-trace.txt
+++ b/tools/perf/Documentation/perf-trace.txt
@@ -143,7 +143,7 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs.
143 Implies '--call-graph dwarf' when --call-graph not present on the 143 Implies '--call-graph dwarf' when --call-graph not present on the
144 command line, on systems where DWARF unwinding was built in. 144 command line, on systems where DWARF unwinding was built in.
145 145
146 Default: 127 146 Default: /proc/sys/kernel/perf_event_max_stack when present, 127 otherwise.
147 147
148--min-stack:: 148--min-stack::
149 Set the stack depth limit when parsing the callchain, anything 149 Set the stack depth limit when parsing the callchain, anything
diff --git a/tools/perf/arch/x86/Makefile b/tools/perf/arch/x86/Makefile
index a33729173b13..6c9211b18ec0 100644
--- a/tools/perf/arch/x86/Makefile
+++ b/tools/perf/arch/x86/Makefile
@@ -24,6 +24,6 @@ $(header): $(sys)/syscall_64.tbl $(systbl)
24 $(Q)$(SHELL) '$(systbl)' $(sys)/syscall_64.tbl 'x86_64' > $@ 24 $(Q)$(SHELL) '$(systbl)' $(sys)/syscall_64.tbl 'x86_64' > $@
25 25
26clean:: 26clean::
27 rm -f $(header) 27 $(call QUIET_CLEAN, x86) $(RM) $(header)
28 28
29archheaders: $(header) 29archheaders: $(header)
diff --git a/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl b/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
index 2e5b565adacc..cac6d17ce5db 100644
--- a/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
+++ b/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
@@ -333,6 +333,8 @@
333324 common membarrier sys_membarrier 333324 common membarrier sys_membarrier
334325 common mlock2 sys_mlock2 334325 common mlock2 sys_mlock2
335326 common copy_file_range sys_copy_file_range 335326 common copy_file_range sys_copy_file_range
336327 64 preadv2 sys_preadv2
337328 64 pwritev2 sys_pwritev2
336 338
337# 339#
338# x32-specific system call numbers start at 512 to avoid cache impact 340# x32-specific system call numbers start at 512 to avoid cache impact
diff --git a/tools/perf/bench/futex-lock-pi.c b/tools/perf/bench/futex-lock-pi.c
index 6a18ce21f865..6952db65508a 100644
--- a/tools/perf/bench/futex-lock-pi.c
+++ b/tools/perf/bench/futex-lock-pi.c
@@ -83,7 +83,7 @@ static void *workerfn(void *arg)
83 do { 83 do {
84 int ret; 84 int ret;
85 again: 85 again:
86 ret = futex_lock_pi(w->futex, NULL, 0, futex_flag); 86 ret = futex_lock_pi(w->futex, NULL, futex_flag);
87 87
88 if (ret) { /* handle lock acquisition */ 88 if (ret) { /* handle lock acquisition */
89 if (!silent) 89 if (!silent)
diff --git a/tools/perf/bench/futex.h b/tools/perf/bench/futex.h
index d44de9f44281..b2e06d1190d0 100644
--- a/tools/perf/bench/futex.h
+++ b/tools/perf/bench/futex.h
@@ -57,13 +57,11 @@ futex_wake(u_int32_t *uaddr, int nr_wake, int opflags)
57 57
58/** 58/**
59 * futex_lock_pi() - block on uaddr as a PI mutex 59 * futex_lock_pi() - block on uaddr as a PI mutex
60 * @detect: whether (1) or not (0) to perform deadlock detection
61 */ 60 */
62static inline int 61static inline int
63futex_lock_pi(u_int32_t *uaddr, struct timespec *timeout, int detect, 62futex_lock_pi(u_int32_t *uaddr, struct timespec *timeout, int opflags)
64 int opflags)
65{ 63{
66 return futex(uaddr, FUTEX_LOCK_PI, detect, timeout, NULL, 0, opflags); 64 return futex(uaddr, FUTEX_LOCK_PI, 0, timeout, NULL, 0, opflags);
67} 65}
68 66
69/** 67/**
diff --git a/tools/perf/bench/mem-functions.c b/tools/perf/bench/mem-functions.c
index a91aa85d80ff..2b54d0f2672a 100644
--- a/tools/perf/bench/mem-functions.c
+++ b/tools/perf/bench/mem-functions.c
@@ -6,6 +6,7 @@
6 * Written by Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp> 6 * Written by Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
7 */ 7 */
8 8
9#include "debug.h"
9#include "../perf.h" 10#include "../perf.h"
10#include "../util/util.h" 11#include "../util/util.h"
11#include <subcmd/parse-options.h> 12#include <subcmd/parse-options.h>
@@ -63,14 +64,16 @@ static struct perf_event_attr cycle_attr = {
63 .config = PERF_COUNT_HW_CPU_CYCLES 64 .config = PERF_COUNT_HW_CPU_CYCLES
64}; 65};
65 66
66static void init_cycles(void) 67static int init_cycles(void)
67{ 68{
68 cycles_fd = sys_perf_event_open(&cycle_attr, getpid(), -1, -1, perf_event_open_cloexec_flag()); 69 cycles_fd = sys_perf_event_open(&cycle_attr, getpid(), -1, -1, perf_event_open_cloexec_flag());
69 70
70 if (cycles_fd < 0 && errno == ENOSYS) 71 if (cycles_fd < 0 && errno == ENOSYS) {
71 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); 72 pr_debug("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
72 else 73 return -1;
73 BUG_ON(cycles_fd < 0); 74 }
75
76 return cycles_fd;
74} 77}
75 78
76static u64 get_cycles(void) 79static u64 get_cycles(void)
@@ -155,8 +158,13 @@ static int bench_mem_common(int argc, const char **argv, struct bench_mem_info *
155 158
156 argc = parse_options(argc, argv, options, info->usage, 0); 159 argc = parse_options(argc, argv, options, info->usage, 0);
157 160
158 if (use_cycles) 161 if (use_cycles) {
159 init_cycles(); 162 i = init_cycles();
163 if (i < 0) {
164 fprintf(stderr, "Failed to open cycles counter\n");
165 return i;
166 }
167 }
160 168
161 size = (size_t)perf_atoll((char *)size_str); 169 size = (size_t)perf_atoll((char *)size_str);
162 size_total = (double)size * nr_loops; 170 size_total = (double)size * nr_loops;
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 1d5be0bd426f..8d9b88af901d 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -691,7 +691,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
691 .ordered_events = true, 691 .ordered_events = true,
692 .ordering_requires_timestamps = true, 692 .ordering_requires_timestamps = true,
693 }, 693 },
694 .max_stack = PERF_MAX_STACK_DEPTH, 694 .max_stack = sysctl_perf_event_max_stack,
695 .pretty_printing_style = "normal", 695 .pretty_printing_style = "normal",
696 .socket_filter = -1, 696 .socket_filter = -1,
697 }; 697 };
@@ -744,7 +744,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
744 OPT_INTEGER(0, "max-stack", &report.max_stack, 744 OPT_INTEGER(0, "max-stack", &report.max_stack,
745 "Set the maximum stack depth when parsing the callchain, " 745 "Set the maximum stack depth when parsing the callchain, "
746 "anything beyond the specified depth will be ignored. " 746 "anything beyond the specified depth will be ignored. "
747 "Default: " __stringify(PERF_MAX_STACK_DEPTH)), 747 "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)),
748 OPT_BOOLEAN('G', "inverted", &report.inverted_callchain, 748 OPT_BOOLEAN('G', "inverted", &report.inverted_callchain,
749 "alias for inverted call graph"), 749 "alias for inverted call graph"),
750 OPT_CALLBACK(0, "ignore-callees", NULL, "regex", 750 OPT_CALLBACK(0, "ignore-callees", NULL, "regex",
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 5099740aa50b..efca81679bb3 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -570,12 +570,12 @@ static void print_sample_bts(struct perf_sample *sample,
570 /* print branch_from information */ 570 /* print branch_from information */
571 if (PRINT_FIELD(IP)) { 571 if (PRINT_FIELD(IP)) {
572 unsigned int print_opts = output[attr->type].print_ip_opts; 572 unsigned int print_opts = output[attr->type].print_ip_opts;
573 struct callchain_cursor *cursor = NULL, cursor_callchain; 573 struct callchain_cursor *cursor = NULL;
574 574
575 if (symbol_conf.use_callchain && sample->callchain && 575 if (symbol_conf.use_callchain && sample->callchain &&
576 thread__resolve_callchain(al->thread, &cursor_callchain, evsel, 576 thread__resolve_callchain(al->thread, &callchain_cursor, evsel,
577 sample, NULL, NULL, scripting_max_stack) == 0) 577 sample, NULL, NULL, scripting_max_stack) == 0)
578 cursor = &cursor_callchain; 578 cursor = &callchain_cursor;
579 579
580 if (cursor == NULL) { 580 if (cursor == NULL) {
581 putchar(' '); 581 putchar(' ');
@@ -789,12 +789,12 @@ static void process_event(struct perf_script *script,
789 printf("%16" PRIu64, sample->weight); 789 printf("%16" PRIu64, sample->weight);
790 790
791 if (PRINT_FIELD(IP)) { 791 if (PRINT_FIELD(IP)) {
792 struct callchain_cursor *cursor = NULL, cursor_callchain; 792 struct callchain_cursor *cursor = NULL;
793 793
794 if (symbol_conf.use_callchain && sample->callchain && 794 if (symbol_conf.use_callchain && sample->callchain &&
795 thread__resolve_callchain(al->thread, &cursor_callchain, evsel, 795 thread__resolve_callchain(al->thread, &callchain_cursor, evsel,
796 sample, NULL, NULL, scripting_max_stack) == 0) 796 sample, NULL, NULL, scripting_max_stack) == 0)
797 cursor = &cursor_callchain; 797 cursor = &callchain_cursor;
798 798
799 putchar(cursor ? '\n' : ' '); 799 putchar(cursor ? '\n' : ' ');
800 sample__fprintf_sym(sample, al, 0, output[attr->type].print_ip_opts, cursor, stdout); 800 sample__fprintf_sym(sample, al, 0, output[attr->type].print_ip_opts, cursor, stdout);
@@ -2031,7 +2031,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
2031 OPT_UINTEGER(0, "max-stack", &scripting_max_stack, 2031 OPT_UINTEGER(0, "max-stack", &scripting_max_stack,
2032 "Set the maximum stack depth when parsing the callchain, " 2032 "Set the maximum stack depth when parsing the callchain, "
2033 "anything beyond the specified depth will be ignored. " 2033 "anything beyond the specified depth will be ignored. "
2034 "Default: " __stringify(PERF_MAX_STACK_DEPTH)), 2034 "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)),
2035 OPT_BOOLEAN('I', "show-info", &show_full_info, 2035 OPT_BOOLEAN('I', "show-info", &show_full_info,
2036 "display extended information from perf.data file"), 2036 "display extended information from perf.data file"),
2037 OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path, 2037 OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path,
@@ -2067,6 +2067,8 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
2067 NULL 2067 NULL
2068 }; 2068 };
2069 2069
2070 scripting_max_stack = sysctl_perf_event_max_stack;
2071
2070 setup_scripting(); 2072 setup_scripting();
2071 2073
2072 argc = parse_options_subcommand(argc, argv, options, script_subcommands, script_usage, 2074 argc = parse_options_subcommand(argc, argv, options, script_subcommands, script_usage,
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index c130a11d3a0d..da18517b1d40 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -1103,7 +1103,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1103 }, 1103 },
1104 .proc_map_timeout = 500, 1104 .proc_map_timeout = 500,
1105 }, 1105 },
1106 .max_stack = PERF_MAX_STACK_DEPTH, 1106 .max_stack = sysctl_perf_event_max_stack,
1107 .sym_pcnt_filter = 5, 1107 .sym_pcnt_filter = 5,
1108 }; 1108 };
1109 struct record_opts *opts = &top.record_opts; 1109 struct record_opts *opts = &top.record_opts;
@@ -1171,7 +1171,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1171 "Accumulate callchains of children and show total overhead as well"), 1171 "Accumulate callchains of children and show total overhead as well"),
1172 OPT_INTEGER(0, "max-stack", &top.max_stack, 1172 OPT_INTEGER(0, "max-stack", &top.max_stack,
1173 "Set the maximum stack depth when parsing the callchain. " 1173 "Set the maximum stack depth when parsing the callchain. "
1174 "Default: " __stringify(PERF_MAX_STACK_DEPTH)), 1174 "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)),
1175 OPT_CALLBACK(0, "ignore-callees", NULL, "regex", 1175 OPT_CALLBACK(0, "ignore-callees", NULL, "regex",
1176 "ignore callees of these functions in call graphs", 1176 "ignore callees of these functions in call graphs",
1177 report_parse_ignore_callees_opt), 1177 report_parse_ignore_callees_opt),
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 5e2614bbb48d..f4f3389c92c7 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -56,22 +56,6 @@
56# define MSG_CMSG_CLOEXEC 0x40000000 56# define MSG_CMSG_CLOEXEC 0x40000000
57#endif 57#endif
58 58
59#ifndef PERF_FLAG_FD_NO_GROUP
60# define PERF_FLAG_FD_NO_GROUP (1UL << 0)
61#endif
62
63#ifndef PERF_FLAG_FD_OUTPUT
64# define PERF_FLAG_FD_OUTPUT (1UL << 1)
65#endif
66
67#ifndef PERF_FLAG_PID_CGROUP
68# define PERF_FLAG_PID_CGROUP (1UL << 2) /* pid=cgroup id, per-cpu mode only */
69#endif
70
71#ifndef PERF_FLAG_FD_CLOEXEC
72# define PERF_FLAG_FD_CLOEXEC (1UL << 3) /* O_CLOEXEC */
73#endif
74
75struct trace { 59struct trace {
76 struct perf_tool tool; 60 struct perf_tool tool;
77 struct syscalltbl *sctbl; 61 struct syscalltbl *sctbl;
@@ -674,34 +658,6 @@ static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
674 658
675#define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags 659#define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags
676 660
677static size_t syscall_arg__scnprintf_perf_flags(char *bf, size_t size,
678 struct syscall_arg *arg)
679{
680 int printed = 0, flags = arg->val;
681
682 if (flags == 0)
683 return 0;
684
685#define P_FLAG(n) \
686 if (flags & PERF_FLAG_##n) { \
687 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
688 flags &= ~PERF_FLAG_##n; \
689 }
690
691 P_FLAG(FD_NO_GROUP);
692 P_FLAG(FD_OUTPUT);
693 P_FLAG(PID_CGROUP);
694 P_FLAG(FD_CLOEXEC);
695#undef P_FLAG
696
697 if (flags)
698 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
699
700 return printed;
701}
702
703#define SCA_PERF_FLAGS syscall_arg__scnprintf_perf_flags
704
705static size_t syscall_arg__scnprintf_pipe_flags(char *bf, size_t size, 661static size_t syscall_arg__scnprintf_pipe_flags(char *bf, size_t size,
706 struct syscall_arg *arg) 662 struct syscall_arg *arg)
707{ 663{
@@ -894,6 +850,7 @@ static size_t syscall_arg__scnprintf_getrandom_flags(char *bf, size_t size,
894#include "trace/beauty/pid.c" 850#include "trace/beauty/pid.c"
895#include "trace/beauty/mmap.c" 851#include "trace/beauty/mmap.c"
896#include "trace/beauty/mode_t.c" 852#include "trace/beauty/mode_t.c"
853#include "trace/beauty/perf_event_open.c"
897#include "trace/beauty/sched_policy.c" 854#include "trace/beauty/sched_policy.c"
898#include "trace/beauty/socket_type.c" 855#include "trace/beauty/socket_type.c"
899#include "trace/beauty/waitid_options.c" 856#include "trace/beauty/waitid_options.c"
@@ -1086,8 +1043,7 @@ static struct syscall_fmt {
1086 [1] = SCA_FILENAME, /* filename */ 1043 [1] = SCA_FILENAME, /* filename */
1087 [2] = SCA_OPEN_FLAGS, /* flags */ }, }, 1044 [2] = SCA_OPEN_FLAGS, /* flags */ }, },
1088 { .name = "perf_event_open", .errmsg = true, 1045 { .name = "perf_event_open", .errmsg = true,
1089 .arg_scnprintf = { [1] = SCA_INT, /* pid */ 1046 .arg_scnprintf = { [2] = SCA_INT, /* cpu */
1090 [2] = SCA_INT, /* cpu */
1091 [3] = SCA_FD, /* group_fd */ 1047 [3] = SCA_FD, /* group_fd */
1092 [4] = SCA_PERF_FLAGS, /* flags */ }, }, 1048 [4] = SCA_PERF_FLAGS, /* flags */ }, },
1093 { .name = "pipe2", .errmsg = true, 1049 { .name = "pipe2", .errmsg = true,
@@ -2126,6 +2082,17 @@ static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
2126 union perf_event *event __maybe_unused, 2082 union perf_event *event __maybe_unused,
2127 struct perf_sample *sample) 2083 struct perf_sample *sample)
2128{ 2084{
2085 int callchain_ret = 0;
2086
2087 if (sample->callchain) {
2088 callchain_ret = trace__resolve_callchain(trace, evsel, sample, &callchain_cursor);
2089 if (callchain_ret == 0) {
2090 if (callchain_cursor.nr < trace->min_stack)
2091 goto out;
2092 callchain_ret = 1;
2093 }
2094 }
2095
2129 trace__printf_interrupted_entry(trace, sample); 2096 trace__printf_interrupted_entry(trace, sample);
2130 trace__fprintf_tstamp(trace, sample->time, trace->output); 2097 trace__fprintf_tstamp(trace, sample->time, trace->output);
2131 2098
@@ -2144,11 +2111,11 @@ static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
2144 2111
2145 fprintf(trace->output, ")\n"); 2112 fprintf(trace->output, ")\n");
2146 2113
2147 if (sample->callchain) { 2114 if (callchain_ret > 0)
2148 if (trace__resolve_callchain(trace, evsel, sample, &callchain_cursor) == 0) 2115 trace__fprintf_callchain(trace, sample);
2149 trace__fprintf_callchain(trace, sample); 2116 else if (callchain_ret < 0)
2150 } 2117 pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel));
2151 2118out:
2152 return 0; 2119 return 0;
2153} 2120}
2154 2121
@@ -2179,8 +2146,19 @@ static int trace__pgfault(struct trace *trace,
2179 char map_type = 'd'; 2146 char map_type = 'd';
2180 struct thread_trace *ttrace; 2147 struct thread_trace *ttrace;
2181 int err = -1; 2148 int err = -1;
2149 int callchain_ret = 0;
2182 2150
2183 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid); 2151 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
2152
2153 if (sample->callchain) {
2154 callchain_ret = trace__resolve_callchain(trace, evsel, sample, &callchain_cursor);
2155 if (callchain_ret == 0) {
2156 if (callchain_cursor.nr < trace->min_stack)
2157 goto out_put;
2158 callchain_ret = 1;
2159 }
2160 }
2161
2184 ttrace = thread__trace(thread, trace->output); 2162 ttrace = thread__trace(thread, trace->output);
2185 if (ttrace == NULL) 2163 if (ttrace == NULL)
2186 goto out_put; 2164 goto out_put;
@@ -2222,6 +2200,11 @@ static int trace__pgfault(struct trace *trace,
2222 print_location(trace->output, sample, &al, true, false); 2200 print_location(trace->output, sample, &al, true, false);
2223 2201
2224 fprintf(trace->output, " (%c%c)\n", map_type, al.level); 2202 fprintf(trace->output, " (%c%c)\n", map_type, al.level);
2203
2204 if (callchain_ret > 0)
2205 trace__fprintf_callchain(trace, sample);
2206 else if (callchain_ret < 0)
2207 pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel));
2225out: 2208out:
2226 err = 0; 2209 err = 0;
2227out_put: 2210out_put:
@@ -2381,8 +2364,7 @@ static bool perf_evlist__add_vfs_getname(struct perf_evlist *evlist)
2381 return true; 2364 return true;
2382} 2365}
2383 2366
2384static int perf_evlist__add_pgfault(struct perf_evlist *evlist, 2367static struct perf_evsel *perf_evsel__new_pgfault(u64 config)
2385 u64 config)
2386{ 2368{
2387 struct perf_evsel *evsel; 2369 struct perf_evsel *evsel;
2388 struct perf_event_attr attr = { 2370 struct perf_event_attr attr = {
@@ -2396,13 +2378,10 @@ static int perf_evlist__add_pgfault(struct perf_evlist *evlist,
2396 event_attr_init(&attr); 2378 event_attr_init(&attr);
2397 2379
2398 evsel = perf_evsel__new(&attr); 2380 evsel = perf_evsel__new(&attr);
2399 if (!evsel) 2381 if (evsel)
2400 return -ENOMEM; 2382 evsel->handler = trace__pgfault;
2401 2383
2402 evsel->handler = trace__pgfault; 2384 return evsel;
2403 perf_evlist__add(evlist, evsel);
2404
2405 return 0;
2406} 2385}
2407 2386
2408static void trace__handle_event(struct trace *trace, union perf_event *event, struct perf_sample *sample) 2387static void trace__handle_event(struct trace *trace, union perf_event *event, struct perf_sample *sample)
@@ -2504,7 +2483,7 @@ out_enomem:
2504static int trace__run(struct trace *trace, int argc, const char **argv) 2483static int trace__run(struct trace *trace, int argc, const char **argv)
2505{ 2484{
2506 struct perf_evlist *evlist = trace->evlist; 2485 struct perf_evlist *evlist = trace->evlist;
2507 struct perf_evsel *evsel; 2486 struct perf_evsel *evsel, *pgfault_maj = NULL, *pgfault_min = NULL;
2508 int err = -1, i; 2487 int err = -1, i;
2509 unsigned long before; 2488 unsigned long before;
2510 const bool forks = argc > 0; 2489 const bool forks = argc > 0;
@@ -2518,14 +2497,19 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
2518 if (trace->trace_syscalls) 2497 if (trace->trace_syscalls)
2519 trace->vfs_getname = perf_evlist__add_vfs_getname(evlist); 2498 trace->vfs_getname = perf_evlist__add_vfs_getname(evlist);
2520 2499
2521 if ((trace->trace_pgfaults & TRACE_PFMAJ) && 2500 if ((trace->trace_pgfaults & TRACE_PFMAJ)) {
2522 perf_evlist__add_pgfault(evlist, PERF_COUNT_SW_PAGE_FAULTS_MAJ)) { 2501 pgfault_maj = perf_evsel__new_pgfault(PERF_COUNT_SW_PAGE_FAULTS_MAJ);
2523 goto out_error_mem; 2502 if (pgfault_maj == NULL)
2503 goto out_error_mem;
2504 perf_evlist__add(evlist, pgfault_maj);
2524 } 2505 }
2525 2506
2526 if ((trace->trace_pgfaults & TRACE_PFMIN) && 2507 if ((trace->trace_pgfaults & TRACE_PFMIN)) {
2527 perf_evlist__add_pgfault(evlist, PERF_COUNT_SW_PAGE_FAULTS_MIN)) 2508 pgfault_min = perf_evsel__new_pgfault(PERF_COUNT_SW_PAGE_FAULTS_MIN);
2528 goto out_error_mem; 2509 if (pgfault_min == NULL)
2510 goto out_error_mem;
2511 perf_evlist__add(evlist, pgfault_min);
2512 }
2529 2513
2530 if (trace->sched && 2514 if (trace->sched &&
2531 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime", 2515 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime",
@@ -2546,24 +2530,42 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
2546 2530
2547 perf_evlist__config(evlist, &trace->opts, NULL); 2531 perf_evlist__config(evlist, &trace->opts, NULL);
2548 2532
2549 if (callchain_param.enabled && trace->syscalls.events.sys_exit) { 2533 if (callchain_param.enabled) {
2550 perf_evsel__config_callchain(trace->syscalls.events.sys_exit, 2534 bool use_identifier = false;
2551 &trace->opts, &callchain_param); 2535
2552 /* 2536 if (trace->syscalls.events.sys_exit) {
2553 * Now we have evsels with different sample_ids, use 2537 perf_evsel__config_callchain(trace->syscalls.events.sys_exit,
2554 * PERF_SAMPLE_IDENTIFIER to map from sample to evsel 2538 &trace->opts, &callchain_param);
2555 * from a fixed position in each ring buffer record. 2539 use_identifier = true;
2556 * 2540 }
2557 * As of this the changeset introducing this comment, this 2541
2558 * isn't strictly needed, as the fields that can come before 2542 if (pgfault_maj) {
2559 * PERF_SAMPLE_ID are all used, but we'll probably disable 2543 perf_evsel__config_callchain(pgfault_maj, &trace->opts, &callchain_param);
2560 * some of those for things like copying the payload of 2544 use_identifier = true;
2561 * pointer syscall arguments, and for vfs_getname we don't 2545 }
2562 * need PERF_SAMPLE_ADDR and PERF_SAMPLE_IP, so do this 2546
2563 * here as a warning we need to use PERF_SAMPLE_IDENTIFIER. 2547 if (pgfault_min) {
2564 */ 2548 perf_evsel__config_callchain(pgfault_min, &trace->opts, &callchain_param);
2565 perf_evlist__set_sample_bit(evlist, IDENTIFIER); 2549 use_identifier = true;
2566 perf_evlist__reset_sample_bit(evlist, ID); 2550 }
2551
2552 if (use_identifier) {
2553 /*
2554 * Now we have evsels with different sample_ids, use
2555 * PERF_SAMPLE_IDENTIFIER to map from sample to evsel
2556 * from a fixed position in each ring buffer record.
2557 *
2558 * As of this the changeset introducing this comment, this
2559 * isn't strictly needed, as the fields that can come before
2560 * PERF_SAMPLE_ID are all used, but we'll probably disable
2561 * some of those for things like copying the payload of
2562 * pointer syscall arguments, and for vfs_getname we don't
2563 * need PERF_SAMPLE_ADDR and PERF_SAMPLE_IP, so do this
2564 * here as a warning we need to use PERF_SAMPLE_IDENTIFIER.
2565 */
2566 perf_evlist__set_sample_bit(evlist, IDENTIFIER);
2567 perf_evlist__reset_sample_bit(evlist, ID);
2568 }
2567 } 2569 }
2568 2570
2569 signal(SIGCHLD, sig_handler); 2571 signal(SIGCHLD, sig_handler);
@@ -3104,7 +3106,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
3104 OPT_UINTEGER(0, "max-stack", &trace.max_stack, 3106 OPT_UINTEGER(0, "max-stack", &trace.max_stack,
3105 "Set the maximum stack depth when parsing the callchain, " 3107 "Set the maximum stack depth when parsing the callchain, "
3106 "anything beyond the specified depth will be ignored. " 3108 "anything beyond the specified depth will be ignored. "
3107 "Default: " __stringify(PERF_MAX_STACK_DEPTH)), 3109 "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)),
3108 OPT_UINTEGER(0, "proc-map-timeout", &trace.opts.proc_map_timeout, 3110 OPT_UINTEGER(0, "proc-map-timeout", &trace.opts.proc_map_timeout,
3109 "per thread proc mmap processing timeout in ms"), 3111 "per thread proc mmap processing timeout in ms"),
3110 OPT_END() 3112 OPT_END()
@@ -3148,7 +3150,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
3148 mmap_pages_user_set = false; 3150 mmap_pages_user_set = false;
3149 3151
3150 if (trace.max_stack == UINT_MAX) { 3152 if (trace.max_stack == UINT_MAX) {
3151 trace.max_stack = PERF_MAX_STACK_DEPTH; 3153 trace.max_stack = sysctl_perf_event_max_stack;
3152 max_stack_user_set = false; 3154 max_stack_user_set = false;
3153 } 3155 }
3154 3156
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 7b2df2b46525..83ffe7cd7330 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -17,6 +17,7 @@
17#include <subcmd/parse-options.h> 17#include <subcmd/parse-options.h>
18#include "util/bpf-loader.h" 18#include "util/bpf-loader.h"
19#include "util/debug.h" 19#include "util/debug.h"
20#include <api/fs/fs.h>
20#include <api/fs/tracing_path.h> 21#include <api/fs/tracing_path.h>
21#include <pthread.h> 22#include <pthread.h>
22#include <stdlib.h> 23#include <stdlib.h>
@@ -533,6 +534,7 @@ int main(int argc, const char **argv)
533{ 534{
534 const char *cmd; 535 const char *cmd;
535 char sbuf[STRERR_BUFSIZE]; 536 char sbuf[STRERR_BUFSIZE];
537 int value;
536 538
537 /* libsubcmd init */ 539 /* libsubcmd init */
538 exec_cmd_init("perf", PREFIX, PERF_EXEC_PATH, EXEC_PATH_ENVIRONMENT); 540 exec_cmd_init("perf", PREFIX, PERF_EXEC_PATH, EXEC_PATH_ENVIRONMENT);
@@ -542,6 +544,9 @@ int main(int argc, const char **argv)
542 page_size = sysconf(_SC_PAGE_SIZE); 544 page_size = sysconf(_SC_PAGE_SIZE);
543 cacheline_size = sysconf(_SC_LEVEL1_DCACHE_LINESIZE); 545 cacheline_size = sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
544 546
547 if (sysctl__read_int("kernel/perf_event_max_stack", &value) == 0)
548 sysctl_perf_event_max_stack = value;
549
545 cmd = extract_argv0_path(argv[0]); 550 cmd = extract_argv0_path(argv[0]);
546 if (!cmd) 551 if (!cmd)
547 cmd = "perf-help"; 552 cmd = "perf-help";
diff --git a/tools/perf/tests/event_update.c b/tools/perf/tests/event_update.c
index 012eab5d1df1..63ecf21750eb 100644
--- a/tools/perf/tests/event_update.c
+++ b/tools/perf/tests/event_update.c
@@ -30,7 +30,7 @@ static int process_event_scale(struct perf_tool *tool __maybe_unused,
30 30
31 TEST_ASSERT_VAL("wrong id", ev->id == 123); 31 TEST_ASSERT_VAL("wrong id", ev->id == 123);
32 TEST_ASSERT_VAL("wrong id", ev->type == PERF_EVENT_UPDATE__SCALE); 32 TEST_ASSERT_VAL("wrong id", ev->type == PERF_EVENT_UPDATE__SCALE);
33 TEST_ASSERT_VAL("wrong scale", ev_data->scale = 0.123); 33 TEST_ASSERT_VAL("wrong scale", ev_data->scale == 0.123);
34 return 0; 34 return 0;
35} 35}
36 36
diff --git a/tools/perf/tests/hists_cumulate.c b/tools/perf/tests/hists_cumulate.c
index ed5aa9eaeb6c..4a2bbff9b1ee 100644
--- a/tools/perf/tests/hists_cumulate.c
+++ b/tools/perf/tests/hists_cumulate.c
@@ -101,7 +101,7 @@ static int add_hist_entries(struct hists *hists, struct machine *machine)
101 if (machine__resolve(machine, &al, &sample) < 0) 101 if (machine__resolve(machine, &al, &sample) < 0)
102 goto out; 102 goto out;
103 103
104 if (hist_entry_iter__add(&iter, &al, PERF_MAX_STACK_DEPTH, 104 if (hist_entry_iter__add(&iter, &al, sysctl_perf_event_max_stack,
105 NULL) < 0) { 105 NULL) < 0) {
106 addr_location__put(&al); 106 addr_location__put(&al);
107 goto out; 107 goto out;
diff --git a/tools/perf/tests/hists_filter.c b/tools/perf/tests/hists_filter.c
index b825d24f8186..e846f8c42013 100644
--- a/tools/perf/tests/hists_filter.c
+++ b/tools/perf/tests/hists_filter.c
@@ -81,7 +81,7 @@ static int add_hist_entries(struct perf_evlist *evlist,
81 81
82 al.socket = fake_samples[i].socket; 82 al.socket = fake_samples[i].socket;
83 if (hist_entry_iter__add(&iter, &al, 83 if (hist_entry_iter__add(&iter, &al,
84 PERF_MAX_STACK_DEPTH, NULL) < 0) { 84 sysctl_perf_event_max_stack, NULL) < 0) {
85 addr_location__put(&al); 85 addr_location__put(&al);
86 goto out; 86 goto out;
87 } 87 }
diff --git a/tools/perf/tests/hists_output.c b/tools/perf/tests/hists_output.c
index d3556fbe8c5c..7cd8738e842f 100644
--- a/tools/perf/tests/hists_output.c
+++ b/tools/perf/tests/hists_output.c
@@ -67,7 +67,7 @@ static int add_hist_entries(struct hists *hists, struct machine *machine)
67 if (machine__resolve(machine, &al, &sample) < 0) 67 if (machine__resolve(machine, &al, &sample) < 0)
68 goto out; 68 goto out;
69 69
70 if (hist_entry_iter__add(&iter, &al, PERF_MAX_STACK_DEPTH, 70 if (hist_entry_iter__add(&iter, &al, sysctl_perf_event_max_stack,
71 NULL) < 0) { 71 NULL) < 0) {
72 addr_location__put(&al); 72 addr_location__put(&al);
73 goto out; 73 goto out;
diff --git a/tools/perf/trace/beauty/perf_event_open.c b/tools/perf/trace/beauty/perf_event_open.c
new file mode 100644
index 000000000000..311f09dd718d
--- /dev/null
+++ b/tools/perf/trace/beauty/perf_event_open.c
@@ -0,0 +1,43 @@
1#ifndef PERF_FLAG_FD_NO_GROUP
2# define PERF_FLAG_FD_NO_GROUP (1UL << 0)
3#endif
4
5#ifndef PERF_FLAG_FD_OUTPUT
6# define PERF_FLAG_FD_OUTPUT (1UL << 1)
7#endif
8
9#ifndef PERF_FLAG_PID_CGROUP
10# define PERF_FLAG_PID_CGROUP (1UL << 2) /* pid=cgroup id, per-cpu mode only */
11#endif
12
13#ifndef PERF_FLAG_FD_CLOEXEC
14# define PERF_FLAG_FD_CLOEXEC (1UL << 3) /* O_CLOEXEC */
15#endif
16
17static size_t syscall_arg__scnprintf_perf_flags(char *bf, size_t size,
18 struct syscall_arg *arg)
19{
20 int printed = 0, flags = arg->val;
21
22 if (flags == 0)
23 return 0;
24
25#define P_FLAG(n) \
26 if (flags & PERF_FLAG_##n) { \
27 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
28 flags &= ~PERF_FLAG_##n; \
29 }
30
31 P_FLAG(FD_NO_GROUP);
32 P_FLAG(FD_OUTPUT);
33 P_FLAG(PID_CGROUP);
34 P_FLAG(FD_CLOEXEC);
35#undef P_FLAG
36
37 if (flags)
38 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
39
40 return printed;
41}
42
43#define SCA_PERF_FLAGS syscall_arg__scnprintf_perf_flags
diff --git a/tools/perf/trace/beauty/pid.c b/tools/perf/trace/beauty/pid.c
index 111ae08d38f1..07486ea65ae3 100644
--- a/tools/perf/trace/beauty/pid.c
+++ b/tools/perf/trace/beauty/pid.c
@@ -3,9 +3,12 @@ static size_t syscall_arg__scnprintf_pid(char *bf, size_t size, struct syscall_a
3 int pid = arg->val; 3 int pid = arg->val;
4 struct trace *trace = arg->trace; 4 struct trace *trace = arg->trace;
5 size_t printed = scnprintf(bf, size, "%d", pid); 5 size_t printed = scnprintf(bf, size, "%d", pid);
6 struct thread *thread = machine__find_thread(trace->host, pid, pid); 6 struct thread *thread = machine__findnew_thread(trace->host, pid, pid);
7 7
8 if (thread != NULL) { 8 if (thread != NULL) {
9 if (!thread->comm_set)
10 thread__set_comm_from_proc(thread);
11
9 if (thread->comm_set) 12 if (thread->comm_set)
10 printed += scnprintf(bf + printed, size - printed, 13 printed += scnprintf(bf + printed, size - printed,
11 " (%s)", thread__comm_str(thread)); 14 " (%s)", thread__comm_str(thread));
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 0573c2ec861d..b6ecf87bc3e3 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -261,14 +261,14 @@ static int machine__write_buildid_table(struct machine *machine, int fd)
261 261
262 if (dso__is_vdso(pos)) { 262 if (dso__is_vdso(pos)) {
263 name = pos->short_name; 263 name = pos->short_name;
264 name_len = pos->short_name_len + 1; 264 name_len = pos->short_name_len;
265 } else if (dso__is_kcore(pos)) { 265 } else if (dso__is_kcore(pos)) {
266 machine__mmap_name(machine, nm, sizeof(nm)); 266 machine__mmap_name(machine, nm, sizeof(nm));
267 name = nm; 267 name = nm;
268 name_len = strlen(nm) + 1; 268 name_len = strlen(nm);
269 } else { 269 } else {
270 name = pos->long_name; 270 name = pos->long_name;
271 name_len = pos->long_name_len + 1; 271 name_len = pos->long_name_len;
272 } 272 }
273 273
274 in_kernel = pos->kernel || 274 in_kernel = pos->kernel ||
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 6fb5725821de..85271e54a63b 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -684,6 +684,7 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
684 struct perf_mmap *md = &evlist->mmap[idx]; 684 struct perf_mmap *md = &evlist->mmap[idx];
685 u64 head; 685 u64 head;
686 u64 old = md->prev; 686 u64 old = md->prev;
687 int diff;
687 unsigned char *data = md->base + page_size; 688 unsigned char *data = md->base + page_size;
688 union perf_event *event = NULL; 689 union perf_event *event = NULL;
689 690
@@ -694,6 +695,7 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
694 return NULL; 695 return NULL;
695 696
696 head = perf_mmap__read_head(md); 697 head = perf_mmap__read_head(md);
698 diff = head - old;
697 if (evlist->overwrite) { 699 if (evlist->overwrite) {
698 /* 700 /*
699 * If we're further behind than half the buffer, there's a chance 701 * If we're further behind than half the buffer, there's a chance
@@ -703,7 +705,6 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
703 * 705 *
704 * In either case, truncate and restart at head. 706 * In either case, truncate and restart at head.
705 */ 707 */
706 int diff = head - old;
707 if (diff > md->mask / 2 || diff < 0) { 708 if (diff > md->mask / 2 || diff < 0) {
708 fprintf(stderr, "WARNING: failed to keep up with mmap data.\n"); 709 fprintf(stderr, "WARNING: failed to keep up with mmap data.\n");
709 710
@@ -711,15 +712,21 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
711 * head points to a known good entry, start there. 712 * head points to a known good entry, start there.
712 */ 713 */
713 old = head; 714 old = head;
715 diff = 0;
714 } 716 }
715 } 717 }
716 718
717 if (old != head) { 719 if (diff >= (int)sizeof(event->header)) {
718 size_t size; 720 size_t size;
719 721
720 event = (union perf_event *)&data[old & md->mask]; 722 event = (union perf_event *)&data[old & md->mask];
721 size = event->header.size; 723 size = event->header.size;
722 724
725 if (size < sizeof(event->header) || diff < (int)size) {
726 event = NULL;
727 goto broken_event;
728 }
729
723 /* 730 /*
724 * Event straddles the mmap boundary -- header should always 731 * Event straddles the mmap boundary -- header should always
725 * be inside due to u64 alignment of output. 732 * be inside due to u64 alignment of output.
@@ -743,6 +750,7 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
743 old += size; 750 old += size;
744 } 751 }
745 752
753broken_event:
746 md->prev = old; 754 md->prev = old;
747 755
748 return event; 756 return event;
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 545bb3f0b2b0..334364e25bbe 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -1231,6 +1231,21 @@ static void __p_sample_type(char *buf, size_t size, u64 value)
1231 __p_bits(buf, size, value, bits); 1231 __p_bits(buf, size, value, bits);
1232} 1232}
1233 1233
1234static void __p_branch_sample_type(char *buf, size_t size, u64 value)
1235{
1236#define bit_name(n) { PERF_SAMPLE_BRANCH_##n, #n }
1237 struct bit_names bits[] = {
1238 bit_name(USER), bit_name(KERNEL), bit_name(HV), bit_name(ANY),
1239 bit_name(ANY_CALL), bit_name(ANY_RETURN), bit_name(IND_CALL),
1240 bit_name(ABORT_TX), bit_name(IN_TX), bit_name(NO_TX),
1241 bit_name(COND), bit_name(CALL_STACK), bit_name(IND_JUMP),
1242 bit_name(CALL), bit_name(NO_FLAGS), bit_name(NO_CYCLES),
1243 { .name = NULL, }
1244 };
1245#undef bit_name
1246 __p_bits(buf, size, value, bits);
1247}
1248
1234static void __p_read_format(char *buf, size_t size, u64 value) 1249static void __p_read_format(char *buf, size_t size, u64 value)
1235{ 1250{
1236#define bit_name(n) { PERF_FORMAT_##n, #n } 1251#define bit_name(n) { PERF_FORMAT_##n, #n }
@@ -1249,6 +1264,7 @@ static void __p_read_format(char *buf, size_t size, u64 value)
1249#define p_unsigned(val) snprintf(buf, BUF_SIZE, "%"PRIu64, (uint64_t)(val)) 1264#define p_unsigned(val) snprintf(buf, BUF_SIZE, "%"PRIu64, (uint64_t)(val))
1250#define p_signed(val) snprintf(buf, BUF_SIZE, "%"PRId64, (int64_t)(val)) 1265#define p_signed(val) snprintf(buf, BUF_SIZE, "%"PRId64, (int64_t)(val))
1251#define p_sample_type(val) __p_sample_type(buf, BUF_SIZE, val) 1266#define p_sample_type(val) __p_sample_type(buf, BUF_SIZE, val)
1267#define p_branch_sample_type(val) __p_branch_sample_type(buf, BUF_SIZE, val)
1252#define p_read_format(val) __p_read_format(buf, BUF_SIZE, val) 1268#define p_read_format(val) __p_read_format(buf, BUF_SIZE, val)
1253 1269
1254#define PRINT_ATTRn(_n, _f, _p) \ 1270#define PRINT_ATTRn(_n, _f, _p) \
@@ -1305,7 +1321,7 @@ int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr,
1305 PRINT_ATTRf(bp_type, p_unsigned); 1321 PRINT_ATTRf(bp_type, p_unsigned);
1306 PRINT_ATTRn("{ bp_addr, config1 }", bp_addr, p_hex); 1322 PRINT_ATTRn("{ bp_addr, config1 }", bp_addr, p_hex);
1307 PRINT_ATTRn("{ bp_len, config2 }", bp_len, p_hex); 1323 PRINT_ATTRn("{ bp_len, config2 }", bp_len, p_hex);
1308 PRINT_ATTRf(branch_sample_type, p_unsigned); 1324 PRINT_ATTRf(branch_sample_type, p_branch_sample_type);
1309 PRINT_ATTRf(sample_regs_user, p_hex); 1325 PRINT_ATTRf(sample_regs_user, p_hex);
1310 PRINT_ATTRf(sample_stack_user, p_unsigned); 1326 PRINT_ATTRf(sample_stack_user, p_unsigned);
1311 PRINT_ATTRf(clockid, p_signed); 1327 PRINT_ATTRf(clockid, p_signed);
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 991a351a8a41..0f33d7e698c4 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -2062,6 +2062,8 @@ static struct hist_entry *hists__add_dummy_entry(struct hists *hists,
2062 if (he) { 2062 if (he) {
2063 memset(&he->stat, 0, sizeof(he->stat)); 2063 memset(&he->stat, 0, sizeof(he->stat));
2064 he->hists = hists; 2064 he->hists = hists;
2065 if (symbol_conf.cumulate_callchain)
2066 memset(he->stat_acc, 0, sizeof(he->stat));
2065 rb_link_node(&he->rb_node_in, parent, p); 2067 rb_link_node(&he->rb_node_in, parent, p);
2066 rb_insert_color(&he->rb_node_in, root); 2068 rb_insert_color(&he->rb_node_in, root);
2067 hists__inc_stats(hists, he); 2069 hists__inc_stats(hists, he);
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
index 9409d014b46c..9c8f15da86ce 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
@@ -356,7 +356,7 @@ static const char *intel_pt_err_msgs[] = {
356 356
357int intel_pt__strerror(int code, char *buf, size_t buflen) 357int intel_pt__strerror(int code, char *buf, size_t buflen)
358{ 358{
359 if (code < 1 || code > INTEL_PT_ERR_MAX) 359 if (code < 1 || code >= INTEL_PT_ERR_MAX)
360 code = INTEL_PT_ERR_UNK; 360 code = INTEL_PT_ERR_UNK;
361 strlcpy(buf, intel_pt_err_msgs[code], buflen); 361 strlcpy(buf, intel_pt_err_msgs[code], buflen);
362 return 0; 362 return 0;
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 656c1d7ee7d4..2cb95bbf9ea6 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -1764,7 +1764,7 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
1764 */ 1764 */
1765 int mix_chain_nr = i + 1 + lbr_nr + 1; 1765 int mix_chain_nr = i + 1 + lbr_nr + 1;
1766 1766
1767 if (mix_chain_nr > PERF_MAX_STACK_DEPTH + PERF_MAX_BRANCH_DEPTH) { 1767 if (mix_chain_nr > (int)sysctl_perf_event_max_stack + PERF_MAX_BRANCH_DEPTH) {
1768 pr_warning("corrupted callchain. skipping...\n"); 1768 pr_warning("corrupted callchain. skipping...\n");
1769 return 0; 1769 return 0;
1770 } 1770 }
@@ -1825,7 +1825,7 @@ static int thread__resolve_callchain_sample(struct thread *thread,
1825 * Based on DWARF debug information, some architectures skip 1825 * Based on DWARF debug information, some architectures skip
1826 * a callchain entry saved by the kernel. 1826 * a callchain entry saved by the kernel.
1827 */ 1827 */
1828 if (chain->nr < PERF_MAX_STACK_DEPTH) 1828 if (chain->nr < sysctl_perf_event_max_stack)
1829 skip_idx = arch_skip_callchain_idx(thread, chain); 1829 skip_idx = arch_skip_callchain_idx(thread, chain);
1830 1830
1831 /* 1831 /*
@@ -1886,7 +1886,7 @@ static int thread__resolve_callchain_sample(struct thread *thread,
1886 } 1886 }
1887 1887
1888check_calls: 1888check_calls:
1889 if (chain->nr > PERF_MAX_STACK_DEPTH && (int)chain->nr > max_stack) { 1889 if (chain->nr > sysctl_perf_event_max_stack && (int)chain->nr > max_stack) {
1890 pr_warning("corrupted callchain. skipping...\n"); 1890 pr_warning("corrupted callchain. skipping...\n");
1891 return 0; 1891 return 0;
1892 } 1892 }
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 8319fbb08636..a9774628c6f6 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -265,6 +265,65 @@ static bool kprobe_warn_out_range(const char *symbol, unsigned long address)
265 return true; 265 return true;
266} 266}
267 267
268/*
269 * NOTE:
270 * '.gnu.linkonce.this_module' section of kernel module elf directly
271 * maps to 'struct module' from linux/module.h. This section contains
272 * actual module name which will be used by kernel after loading it.
273 * But, we cannot use 'struct module' here since linux/module.h is not
274 * exposed to user-space. Offset of 'name' has remained same from long
275 * time, so hardcoding it here.
276 */
277#ifdef __LP64__
278#define MOD_NAME_OFFSET 24
279#else
280#define MOD_NAME_OFFSET 12
281#endif
282
283/*
284 * @module can be module name of module file path. In case of path,
285 * inspect elf and find out what is actual module name.
286 * Caller has to free mod_name after using it.
287 */
288static char *find_module_name(const char *module)
289{
290 int fd;
291 Elf *elf;
292 GElf_Ehdr ehdr;
293 GElf_Shdr shdr;
294 Elf_Data *data;
295 Elf_Scn *sec;
296 char *mod_name = NULL;
297
298 fd = open(module, O_RDONLY);
299 if (fd < 0)
300 return NULL;
301
302 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
303 if (elf == NULL)
304 goto elf_err;
305
306 if (gelf_getehdr(elf, &ehdr) == NULL)
307 goto ret_err;
308
309 sec = elf_section_by_name(elf, &ehdr, &shdr,
310 ".gnu.linkonce.this_module", NULL);
311 if (!sec)
312 goto ret_err;
313
314 data = elf_getdata(sec, NULL);
315 if (!data || !data->d_buf)
316 goto ret_err;
317
318 mod_name = strdup((char *)data->d_buf + MOD_NAME_OFFSET);
319
320ret_err:
321 elf_end(elf);
322elf_err:
323 close(fd);
324 return mod_name;
325}
326
268#ifdef HAVE_DWARF_SUPPORT 327#ifdef HAVE_DWARF_SUPPORT
269 328
270static int kernel_get_module_dso(const char *module, struct dso **pdso) 329static int kernel_get_module_dso(const char *module, struct dso **pdso)
@@ -486,8 +545,10 @@ static int get_text_start_address(const char *exec, unsigned long *address)
486 return -errno; 545 return -errno;
487 546
488 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); 547 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
489 if (elf == NULL) 548 if (elf == NULL) {
490 return -EINVAL; 549 ret = -EINVAL;
550 goto out_close;
551 }
491 552
492 if (gelf_getehdr(elf, &ehdr) == NULL) 553 if (gelf_getehdr(elf, &ehdr) == NULL)
493 goto out; 554 goto out;
@@ -499,6 +560,9 @@ static int get_text_start_address(const char *exec, unsigned long *address)
499 ret = 0; 560 ret = 0;
500out: 561out:
501 elf_end(elf); 562 elf_end(elf);
563out_close:
564 close(fd);
565
502 return ret; 566 return ret;
503} 567}
504 568
@@ -583,32 +647,23 @@ static int add_module_to_probe_trace_events(struct probe_trace_event *tevs,
583 int ntevs, const char *module) 647 int ntevs, const char *module)
584{ 648{
585 int i, ret = 0; 649 int i, ret = 0;
586 char *tmp; 650 char *mod_name = NULL;
587 651
588 if (!module) 652 if (!module)
589 return 0; 653 return 0;
590 654
591 tmp = strrchr(module, '/'); 655 mod_name = find_module_name(module);
592 if (tmp) {
593 /* This is a module path -- get the module name */
594 module = strdup(tmp + 1);
595 if (!module)
596 return -ENOMEM;
597 tmp = strchr(module, '.');
598 if (tmp)
599 *tmp = '\0';
600 tmp = (char *)module; /* For free() */
601 }
602 656
603 for (i = 0; i < ntevs; i++) { 657 for (i = 0; i < ntevs; i++) {
604 tevs[i].point.module = strdup(module); 658 tevs[i].point.module =
659 strdup(mod_name ? mod_name : module);
605 if (!tevs[i].point.module) { 660 if (!tevs[i].point.module) {
606 ret = -ENOMEM; 661 ret = -ENOMEM;
607 break; 662 break;
608 } 663 }
609 } 664 }
610 665
611 free(tmp); 666 free(mod_name);
612 return ret; 667 return ret;
613} 668}
614 669
@@ -2516,6 +2571,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
2516 struct probe_trace_point *tp; 2571 struct probe_trace_point *tp;
2517 int num_matched_functions; 2572 int num_matched_functions;
2518 int ret, i, j, skipped = 0; 2573 int ret, i, j, skipped = 0;
2574 char *mod_name;
2519 2575
2520 map = get_target_map(pev->target, pev->uprobes); 2576 map = get_target_map(pev->target, pev->uprobes);
2521 if (!map) { 2577 if (!map) {
@@ -2600,9 +2656,19 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
2600 tp->realname = strdup_or_goto(sym->name, nomem_out); 2656 tp->realname = strdup_or_goto(sym->name, nomem_out);
2601 2657
2602 tp->retprobe = pp->retprobe; 2658 tp->retprobe = pp->retprobe;
2603 if (pev->target) 2659 if (pev->target) {
2604 tev->point.module = strdup_or_goto(pev->target, 2660 if (pev->uprobes) {
2605 nomem_out); 2661 tev->point.module = strdup_or_goto(pev->target,
2662 nomem_out);
2663 } else {
2664 mod_name = find_module_name(pev->target);
2665 tev->point.module =
2666 strdup(mod_name ? mod_name : pev->target);
2667 free(mod_name);
2668 if (!tev->point.module)
2669 goto nomem_out;
2670 }
2671 }
2606 tev->uprobes = pev->uprobes; 2672 tev->uprobes = pev->uprobes;
2607 tev->nargs = pev->nargs; 2673 tev->nargs = pev->nargs;
2608 if (tev->nargs) { 2674 if (tev->nargs) {
@@ -2743,9 +2809,13 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
2743{ 2809{
2744 int ret; 2810 int ret;
2745 2811
2746 if (pev->uprobes && !pev->group) { 2812 if (!pev->group) {
2747 /* Replace group name if not given */ 2813 /* Set group name if not given */
2748 ret = convert_exec_to_group(pev->target, &pev->group); 2814 if (!pev->uprobes) {
2815 pev->group = strdup(PERFPROBE_GROUP);
2816 ret = pev->group ? 0 : -ENOMEM;
2817 } else
2818 ret = convert_exec_to_group(pev->target, &pev->group);
2749 if (ret != 0) { 2819 if (ret != 0) {
2750 pr_warning("Failed to make a group name.\n"); 2820 pr_warning("Failed to make a group name.\n");
2751 return ret; 2821 return ret;
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index e3b3b92e4458..3fe6214970e6 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -220,8 +220,7 @@ int probe_file__add_event(int fd, struct probe_trace_event *tev)
220 220
221 pr_debug("Writing event: %s\n", buf); 221 pr_debug("Writing event: %s\n", buf);
222 if (!probe_event_dry_run) { 222 if (!probe_event_dry_run) {
223 ret = write(fd, buf, strlen(buf)); 223 if (write(fd, buf, strlen(buf)) < (int)strlen(buf)) {
224 if (ret <= 0) {
225 ret = -errno; 224 ret = -errno;
226 pr_warning("Failed to write event: %s\n", 225 pr_warning("Failed to write event: %s\n",
227 strerror_r(errno, sbuf, sizeof(sbuf))); 226 strerror_r(errno, sbuf, sizeof(sbuf)));
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index ae1cebc307c5..62c7f6988e0e 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -265,7 +265,7 @@ static SV *perl_process_callchain(struct perf_sample *sample,
265 265
266 if (thread__resolve_callchain(al->thread, &callchain_cursor, evsel, 266 if (thread__resolve_callchain(al->thread, &callchain_cursor, evsel,
267 sample, NULL, NULL, 267 sample, NULL, NULL,
268 PERF_MAX_STACK_DEPTH) != 0) { 268 sysctl_perf_event_max_stack) != 0) {
269 pr_err("Failed to resolve callchain. Skipping\n"); 269 pr_err("Failed to resolve callchain. Skipping\n");
270 goto exit; 270 goto exit;
271 } 271 }
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index dfd00c6dad6e..45fcb715a36b 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -10,6 +10,8 @@
10#include "comm.h" 10#include "comm.h"
11#include "unwind.h" 11#include "unwind.h"
12 12
13#include <api/fs/fs.h>
14
13int thread__init_map_groups(struct thread *thread, struct machine *machine) 15int thread__init_map_groups(struct thread *thread, struct machine *machine)
14{ 16{
15 struct thread *leader; 17 struct thread *leader;
@@ -153,6 +155,23 @@ int __thread__set_comm(struct thread *thread, const char *str, u64 timestamp,
153 return 0; 155 return 0;
154} 156}
155 157
158int thread__set_comm_from_proc(struct thread *thread)
159{
160 char path[64];
161 char *comm = NULL;
162 size_t sz;
163 int err = -1;
164
165 if (!(snprintf(path, sizeof(path), "%d/task/%d/comm",
166 thread->pid_, thread->tid) >= (int)sizeof(path)) &&
167 procfs__read_str(path, &comm, &sz) == 0) {
168 comm[sz - 1] = '\0';
169 err = thread__set_comm(thread, comm, 0);
170 }
171
172 return err;
173}
174
156const char *thread__comm_str(const struct thread *thread) 175const char *thread__comm_str(const struct thread *thread)
157{ 176{
158 const struct comm *comm = thread__comm(thread); 177 const struct comm *comm = thread__comm(thread);
@@ -233,7 +252,7 @@ void thread__find_cpumode_addr_location(struct thread *thread,
233 struct addr_location *al) 252 struct addr_location *al)
234{ 253{
235 size_t i; 254 size_t i;
236 const u8 const cpumodes[] = { 255 const u8 cpumodes[] = {
237 PERF_RECORD_MISC_USER, 256 PERF_RECORD_MISC_USER,
238 PERF_RECORD_MISC_KERNEL, 257 PERF_RECORD_MISC_KERNEL,
239 PERF_RECORD_MISC_GUEST_USER, 258 PERF_RECORD_MISC_GUEST_USER,
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index e214207bb13a..45fba13c800b 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -71,6 +71,8 @@ static inline int thread__set_comm(struct thread *thread, const char *comm,
71 return __thread__set_comm(thread, comm, timestamp, false); 71 return __thread__set_comm(thread, comm, timestamp, false);
72} 72}
73 73
74int thread__set_comm_from_proc(struct thread *thread);
75
74int thread__comm_len(struct thread *thread); 76int thread__comm_len(struct thread *thread);
75struct comm *thread__comm(const struct thread *thread); 77struct comm *thread__comm(const struct thread *thread);
76struct comm *thread__exec_comm(const struct thread *thread); 78struct comm *thread__exec_comm(const struct thread *thread);
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index b7766c577b01..619ba2061b62 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -33,6 +33,8 @@ struct callchain_param callchain_param = {
33unsigned int page_size; 33unsigned int page_size;
34int cacheline_size; 34int cacheline_size;
35 35
36unsigned int sysctl_perf_event_max_stack = PERF_MAX_STACK_DEPTH;
37
36bool test_attr__enabled; 38bool test_attr__enabled;
37 39
38bool perf_host = true; 40bool perf_host = true;
@@ -117,6 +119,40 @@ int rm_rf(char *path)
117 return rmdir(path); 119 return rmdir(path);
118} 120}
119 121
122/* A filter which removes dot files */
123bool lsdir_no_dot_filter(const char *name __maybe_unused, struct dirent *d)
124{
125 return d->d_name[0] != '.';
126}
127
128/* lsdir reads a directory and store it in strlist */
129struct strlist *lsdir(const char *name,
130 bool (*filter)(const char *, struct dirent *))
131{
132 struct strlist *list = NULL;
133 DIR *dir;
134 struct dirent *d;
135
136 dir = opendir(name);
137 if (!dir)
138 return NULL;
139
140 list = strlist__new(NULL, NULL);
141 if (!list) {
142 errno = -ENOMEM;
143 goto out;
144 }
145
146 while ((d = readdir(dir)) != NULL) {
147 if (!filter || filter(name, d))
148 strlist__add(list, d->d_name);
149 }
150
151out:
152 closedir(dir);
153 return list;
154}
155
120static int slow_copyfile(const char *from, const char *to) 156static int slow_copyfile(const char *from, const char *to)
121{ 157{
122 int err = -1; 158 int err = -1;
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 3bf3de86d429..88f607af1f47 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -79,6 +79,7 @@
79#include <termios.h> 79#include <termios.h>
80#include <linux/bitops.h> 80#include <linux/bitops.h>
81#include <termios.h> 81#include <termios.h>
82#include "strlist.h"
82 83
83extern const char *graph_line; 84extern const char *graph_line;
84extern const char *graph_dotted_line; 85extern const char *graph_dotted_line;
@@ -222,6 +223,8 @@ static inline int sane_case(int x, int high)
222 223
223int mkdir_p(char *path, mode_t mode); 224int mkdir_p(char *path, mode_t mode);
224int rm_rf(char *path); 225int rm_rf(char *path);
226struct strlist *lsdir(const char *name, bool (*filter)(const char *, struct dirent *));
227bool lsdir_no_dot_filter(const char *name, struct dirent *d);
225int copyfile(const char *from, const char *to); 228int copyfile(const char *from, const char *to);
226int copyfile_mode(const char *from, const char *to, mode_t mode); 229int copyfile_mode(const char *from, const char *to, mode_t mode);
227int copyfile_offset(int fromfd, loff_t from_ofs, int tofd, loff_t to_ofs, u64 size); 230int copyfile_offset(int fromfd, loff_t from_ofs, int tofd, loff_t to_ofs, u64 size);
@@ -264,6 +267,7 @@ void sighandler_dump_stack(int sig);
264 267
265extern unsigned int page_size; 268extern unsigned int page_size;
266extern int cacheline_size; 269extern int cacheline_size;
270extern unsigned int sysctl_perf_event_max_stack;
267 271
268struct parse_tag { 272struct parse_tag {
269 char tag; 273 char tag;