diff options
author | Ingo Molnar <mingo@kernel.org> | 2016-04-27 11:02:24 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2016-04-27 11:02:24 -0400 |
commit | a8944c5bf86dc6c153a71f2a386738c0d3f5ff9c (patch) | |
tree | a251b1d510831dc071eadbbbe3e38a85fe643365 /tools/perf | |
parent | 67d61296ffcc850bffdd4466430cb91e5328f39a (diff) | |
parent | 4cb93446c587d56e2a54f4f83113daba2c0b6dee (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')
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 | ||
26 | clean:: | 26 | clean:: |
27 | rm -f $(header) | 27 | $(call QUIET_CLEAN, x86) $(RM) $(header) |
28 | 28 | ||
29 | archheaders: $(header) | 29 | archheaders: $(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 @@ | |||
333 | 324 common membarrier sys_membarrier | 333 | 324 common membarrier sys_membarrier |
334 | 325 common mlock2 sys_mlock2 | 334 | 325 common mlock2 sys_mlock2 |
335 | 326 common copy_file_range sys_copy_file_range | 335 | 326 common copy_file_range sys_copy_file_range |
336 | 327 64 preadv2 sys_preadv2 | ||
337 | 328 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 | */ |
62 | static inline int | 61 | static inline int |
63 | futex_lock_pi(u_int32_t *uaddr, struct timespec *timeout, int detect, | 62 | futex_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 | ||
66 | static void init_cycles(void) | 67 | static 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 | ||
76 | static u64 get_cycles(void) | 79 | static 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 | |||
75 | struct trace { | 59 | struct 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 | ||
677 | static 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 | |||
705 | static size_t syscall_arg__scnprintf_pipe_flags(char *bf, size_t size, | 661 | static 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 | 2118 | out: | |
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)); | ||
2225 | out: | 2208 | out: |
2226 | err = 0; | 2209 | err = 0; |
2227 | out_put: | 2210 | out_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 | ||
2384 | static int perf_evlist__add_pgfault(struct perf_evlist *evlist, | 2367 | static 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 | ||
2408 | static void trace__handle_event(struct trace *trace, union perf_event *event, struct perf_sample *sample) | 2387 | static void trace__handle_event(struct trace *trace, union perf_event *event, struct perf_sample *sample) |
@@ -2504,7 +2483,7 @@ out_enomem: | |||
2504 | static int trace__run(struct trace *trace, int argc, const char **argv) | 2483 | static 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 | |||
17 | static 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 | ||
753 | broken_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 | ||
1234 | static 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 | |||
1234 | static void __p_read_format(char *buf, size_t size, u64 value) | 1249 | static 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 | ||
357 | int intel_pt__strerror(int code, char *buf, size_t buflen) | 357 | int 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 | ||
1888 | check_calls: | 1888 | check_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 | */ | ||
288 | static 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 | |||
320 | ret_err: | ||
321 | elf_end(elf); | ||
322 | elf_err: | ||
323 | close(fd); | ||
324 | return mod_name; | ||
325 | } | ||
326 | |||
268 | #ifdef HAVE_DWARF_SUPPORT | 327 | #ifdef HAVE_DWARF_SUPPORT |
269 | 328 | ||
270 | static int kernel_get_module_dso(const char *module, struct dso **pdso) | 329 | static 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; |
500 | out: | 561 | out: |
501 | elf_end(elf); | 562 | elf_end(elf); |
563 | out_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 | |||
13 | int thread__init_map_groups(struct thread *thread, struct machine *machine) | 15 | int 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 | ||
158 | int 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 | |||
156 | const char *thread__comm_str(const struct thread *thread) | 175 | const 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 | ||
74 | int thread__set_comm_from_proc(struct thread *thread); | ||
75 | |||
74 | int thread__comm_len(struct thread *thread); | 76 | int thread__comm_len(struct thread *thread); |
75 | struct comm *thread__comm(const struct thread *thread); | 77 | struct comm *thread__comm(const struct thread *thread); |
76 | struct comm *thread__exec_comm(const struct thread *thread); | 78 | struct 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 = { | |||
33 | unsigned int page_size; | 33 | unsigned int page_size; |
34 | int cacheline_size; | 34 | int cacheline_size; |
35 | 35 | ||
36 | unsigned int sysctl_perf_event_max_stack = PERF_MAX_STACK_DEPTH; | ||
37 | |||
36 | bool test_attr__enabled; | 38 | bool test_attr__enabled; |
37 | 39 | ||
38 | bool perf_host = true; | 40 | bool 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 */ | ||
123 | bool 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 */ | ||
129 | struct 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 | |||
151 | out: | ||
152 | closedir(dir); | ||
153 | return list; | ||
154 | } | ||
155 | |||
120 | static int slow_copyfile(const char *from, const char *to) | 156 | static 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 | ||
83 | extern const char *graph_line; | 84 | extern const char *graph_line; |
84 | extern const char *graph_dotted_line; | 85 | extern const char *graph_dotted_line; |
@@ -222,6 +223,8 @@ static inline int sane_case(int x, int high) | |||
222 | 223 | ||
223 | int mkdir_p(char *path, mode_t mode); | 224 | int mkdir_p(char *path, mode_t mode); |
224 | int rm_rf(char *path); | 225 | int rm_rf(char *path); |
226 | struct strlist *lsdir(const char *name, bool (*filter)(const char *, struct dirent *)); | ||
227 | bool lsdir_no_dot_filter(const char *name, struct dirent *d); | ||
225 | int copyfile(const char *from, const char *to); | 228 | int copyfile(const char *from, const char *to); |
226 | int copyfile_mode(const char *from, const char *to, mode_t mode); | 229 | int copyfile_mode(const char *from, const char *to, mode_t mode); |
227 | int copyfile_offset(int fromfd, loff_t from_ofs, int tofd, loff_t to_ofs, u64 size); | 230 | int 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 | ||
265 | extern unsigned int page_size; | 268 | extern unsigned int page_size; |
266 | extern int cacheline_size; | 269 | extern int cacheline_size; |
270 | extern unsigned int sysctl_perf_event_max_stack; | ||
267 | 271 | ||
268 | struct parse_tag { | 272 | struct parse_tag { |
269 | char tag; | 273 | char tag; |