aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-trace.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-trace.c')
-rw-r--r--tools/perf/builtin-trace.c125
1 files changed, 70 insertions, 55 deletions
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 84debdbad327..e7f1b182fc15 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -21,6 +21,7 @@
21#include "builtin.h" 21#include "builtin.h"
22#include "util/color.h" 22#include "util/color.h"
23#include "util/debug.h" 23#include "util/debug.h"
24#include "util/env.h"
24#include "util/event.h" 25#include "util/event.h"
25#include "util/evlist.h" 26#include "util/evlist.h"
26#include <subcmd/exec-cmd.h> 27#include <subcmd/exec-cmd.h>
@@ -45,18 +46,17 @@
45 46
46#include <errno.h> 47#include <errno.h>
47#include <inttypes.h> 48#include <inttypes.h>
48#include <libaudit.h> /* FIXME: Still needed for audit_errno_to_name */
49#include <poll.h> 49#include <poll.h>
50#include <signal.h> 50#include <signal.h>
51#include <stdlib.h> 51#include <stdlib.h>
52#include <string.h> 52#include <string.h>
53#include <linux/err.h> 53#include <linux/err.h>
54#include <linux/filter.h> 54#include <linux/filter.h>
55#include <linux/audit.h>
56#include <linux/kernel.h> 55#include <linux/kernel.h>
57#include <linux/random.h> 56#include <linux/random.h>
58#include <linux/stringify.h> 57#include <linux/stringify.h>
59#include <linux/time64.h> 58#include <linux/time64.h>
59#include <fcntl.h>
60 60
61#include "sane_ctype.h" 61#include "sane_ctype.h"
62 62
@@ -111,6 +111,7 @@ struct trace {
111 bool summary; 111 bool summary;
112 bool summary_only; 112 bool summary_only;
113 bool show_comm; 113 bool show_comm;
114 bool print_sample;
114 bool show_tool_stats; 115 bool show_tool_stats;
115 bool trace_syscalls; 116 bool trace_syscalls;
116 bool kernel_syscallchains; 117 bool kernel_syscallchains;
@@ -545,9 +546,10 @@ static size_t syscall_arg__scnprintf_getrandom_flags(char *bf, size_t size,
545 { .scnprintf = SCA_STRARRAY, \ 546 { .scnprintf = SCA_STRARRAY, \
546 .parm = &strarray__##array, } 547 .parm = &strarray__##array, }
547 548
549#include "trace/beauty/arch_errno_names.c"
548#include "trace/beauty/eventfd.c" 550#include "trace/beauty/eventfd.c"
549#include "trace/beauty/flock.c"
550#include "trace/beauty/futex_op.c" 551#include "trace/beauty/futex_op.c"
552#include "trace/beauty/futex_val3.c"
551#include "trace/beauty/mmap.c" 553#include "trace/beauty/mmap.c"
552#include "trace/beauty/mode_t.c" 554#include "trace/beauty/mode_t.c"
553#include "trace/beauty/msg_flags.c" 555#include "trace/beauty/msg_flags.c"
@@ -610,7 +612,8 @@ static struct syscall_fmt {
610 { .name = "fstat", .alias = "newfstat", }, 612 { .name = "fstat", .alias = "newfstat", },
611 { .name = "fstatat", .alias = "newfstatat", }, 613 { .name = "fstatat", .alias = "newfstatat", },
612 { .name = "futex", 614 { .name = "futex",
613 .arg = { [1] = { .scnprintf = SCA_FUTEX_OP, /* op */ }, }, }, 615 .arg = { [1] = { .scnprintf = SCA_FUTEX_OP, /* op */ },
616 [5] = { .scnprintf = SCA_FUTEX_VAL3, /* val3 */ }, }, },
614 { .name = "futimesat", 617 { .name = "futimesat",
615 .arg = { [0] = { .scnprintf = SCA_FDAT, /* fd */ }, }, }, 618 .arg = { [0] = { .scnprintf = SCA_FDAT, /* fd */ }, }, },
616 { .name = "getitimer", 619 { .name = "getitimer",
@@ -622,6 +625,7 @@ static struct syscall_fmt {
622 .arg = { [2] = { .scnprintf = SCA_GETRANDOM_FLAGS, /* flags */ }, }, }, 625 .arg = { [2] = { .scnprintf = SCA_GETRANDOM_FLAGS, /* flags */ }, }, },
623 { .name = "getrlimit", 626 { .name = "getrlimit",
624 .arg = { [0] = STRARRAY(resource, rlimit_resources), }, }, 627 .arg = { [0] = STRARRAY(resource, rlimit_resources), }, },
628 { .name = "gettid", .errpid = true, },
625 { .name = "ioctl", 629 { .name = "ioctl",
626 .arg = { 630 .arg = {
627#if defined(__i386__) || defined(__x86_64__) 631#if defined(__i386__) || defined(__x86_64__)
@@ -819,7 +823,7 @@ static size_t fprintf_duration(unsigned long t, bool calculated, FILE *fp)
819 size_t printed = fprintf(fp, "("); 823 size_t printed = fprintf(fp, "(");
820 824
821 if (!calculated) 825 if (!calculated)
822 printed += fprintf(fp, " ? "); 826 printed += fprintf(fp, " ");
823 else if (duration >= 1.0) 827 else if (duration >= 1.0)
824 printed += color_fprintf(fp, PERF_COLOR_RED, "%6.3f ms", duration); 828 printed += color_fprintf(fp, PERF_COLOR_RED, "%6.3f ms", duration);
825 else if (duration >= 0.01) 829 else if (duration >= 0.01)
@@ -1554,10 +1558,9 @@ static void thread__update_stats(struct thread_trace *ttrace,
1554 update_stats(stats, duration); 1558 update_stats(stats, duration);
1555} 1559}
1556 1560
1557static int trace__printf_interrupted_entry(struct trace *trace, struct perf_sample *sample) 1561static int trace__printf_interrupted_entry(struct trace *trace)
1558{ 1562{
1559 struct thread_trace *ttrace; 1563 struct thread_trace *ttrace;
1560 u64 duration;
1561 size_t printed; 1564 size_t printed;
1562 1565
1563 if (trace->current == NULL) 1566 if (trace->current == NULL)
@@ -1568,15 +1571,30 @@ static int trace__printf_interrupted_entry(struct trace *trace, struct perf_samp
1568 if (!ttrace->entry_pending) 1571 if (!ttrace->entry_pending)
1569 return 0; 1572 return 0;
1570 1573
1571 duration = sample->time - ttrace->entry_time; 1574 printed = trace__fprintf_entry_head(trace, trace->current, 0, false, ttrace->entry_time, trace->output);
1572
1573 printed = trace__fprintf_entry_head(trace, trace->current, duration, true, ttrace->entry_time, trace->output);
1574 printed += fprintf(trace->output, "%-70s) ...\n", ttrace->entry_str); 1575 printed += fprintf(trace->output, "%-70s) ...\n", ttrace->entry_str);
1575 ttrace->entry_pending = false; 1576 ttrace->entry_pending = false;
1576 1577
1577 return printed; 1578 return printed;
1578} 1579}
1579 1580
1581static int trace__fprintf_sample(struct trace *trace, struct perf_evsel *evsel,
1582 struct perf_sample *sample, struct thread *thread)
1583{
1584 int printed = 0;
1585
1586 if (trace->print_sample) {
1587 double ts = (double)sample->time / NSEC_PER_MSEC;
1588
1589 printed += fprintf(trace->output, "%22s %10.3f %s %d/%d [%d]\n",
1590 perf_evsel__name(evsel), ts,
1591 thread__comm_str(thread),
1592 sample->pid, sample->tid, sample->cpu);
1593 }
1594
1595 return printed;
1596}
1597
1580static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel, 1598static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
1581 union perf_event *event __maybe_unused, 1599 union perf_event *event __maybe_unused,
1582 struct perf_sample *sample) 1600 struct perf_sample *sample)
@@ -1597,6 +1615,8 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
1597 if (ttrace == NULL) 1615 if (ttrace == NULL)
1598 goto out_put; 1616 goto out_put;
1599 1617
1618 trace__fprintf_sample(trace, evsel, sample, thread);
1619
1600 args = perf_evsel__sc_tp_ptr(evsel, args, sample); 1620 args = perf_evsel__sc_tp_ptr(evsel, args, sample);
1601 1621
1602 if (ttrace->entry_str == NULL) { 1622 if (ttrace->entry_str == NULL) {
@@ -1606,7 +1626,7 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
1606 } 1626 }
1607 1627
1608 if (!(trace->duration_filter || trace->summary_only || trace->min_stack)) 1628 if (!(trace->duration_filter || trace->summary_only || trace->min_stack))
1609 trace__printf_interrupted_entry(trace, sample); 1629 trace__printf_interrupted_entry(trace);
1610 1630
1611 ttrace->entry_time = sample->time; 1631 ttrace->entry_time = sample->time;
1612 msg = ttrace->entry_str; 1632 msg = ttrace->entry_str;
@@ -1641,9 +1661,12 @@ static int trace__resolve_callchain(struct trace *trace, struct perf_evsel *evse
1641 struct callchain_cursor *cursor) 1661 struct callchain_cursor *cursor)
1642{ 1662{
1643 struct addr_location al; 1663 struct addr_location al;
1664 int max_stack = evsel->attr.sample_max_stack ?
1665 evsel->attr.sample_max_stack :
1666 trace->max_stack;
1644 1667
1645 if (machine__resolve(trace->host, &al, sample) < 0 || 1668 if (machine__resolve(trace->host, &al, sample) < 0 ||
1646 thread__resolve_callchain(al.thread, cursor, evsel, sample, NULL, NULL, trace->max_stack)) 1669 thread__resolve_callchain(al.thread, cursor, evsel, sample, NULL, NULL, max_stack))
1647 return -1; 1670 return -1;
1648 1671
1649 return 0; 1672 return 0;
@@ -1659,6 +1682,14 @@ static int trace__fprintf_callchain(struct trace *trace, struct perf_sample *sam
1659 return sample__fprintf_callchain(sample, 38, print_opts, &callchain_cursor, trace->output); 1682 return sample__fprintf_callchain(sample, 38, print_opts, &callchain_cursor, trace->output);
1660} 1683}
1661 1684
1685static const char *errno_to_name(struct perf_evsel *evsel, int err)
1686{
1687 struct perf_env *env = perf_evsel__env(evsel);
1688 const char *arch_name = perf_env__arch(env);
1689
1690 return arch_syscalls__strerrno(arch_name, err);
1691}
1692
1662static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel, 1693static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
1663 union perf_event *event __maybe_unused, 1694 union perf_event *event __maybe_unused,
1664 struct perf_sample *sample) 1695 struct perf_sample *sample)
@@ -1679,6 +1710,8 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
1679 if (ttrace == NULL) 1710 if (ttrace == NULL)
1680 goto out_put; 1711 goto out_put;
1681 1712
1713 trace__fprintf_sample(trace, evsel, sample, thread);
1714
1682 if (trace->summary) 1715 if (trace->summary)
1683 thread__update_stats(ttrace, id, sample); 1716 thread__update_stats(ttrace, id, sample);
1684 1717
@@ -1729,7 +1762,7 @@ signed_print:
1729errno_print: { 1762errno_print: {
1730 char bf[STRERR_BUFSIZE]; 1763 char bf[STRERR_BUFSIZE];
1731 const char *emsg = str_error_r(-ret, bf, sizeof(bf)), 1764 const char *emsg = str_error_r(-ret, bf, sizeof(bf)),
1732 *e = audit_errno_to_name(-ret); 1765 *e = errno_to_name(evsel, -ret);
1733 1766
1734 fprintf(trace->output, ") = -1 %s %s", e, emsg); 1767 fprintf(trace->output, ") = -1 %s %s", e, emsg);
1735 } 1768 }
@@ -1910,7 +1943,7 @@ static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
1910 } 1943 }
1911 } 1944 }
1912 1945
1913 trace__printf_interrupted_entry(trace, sample); 1946 trace__printf_interrupted_entry(trace);
1914 trace__fprintf_tstamp(trace, sample->time, trace->output); 1947 trace__fprintf_tstamp(trace, sample->time, trace->output);
1915 1948
1916 if (trace->trace_syscalls) 1949 if (trace->trace_syscalls)
@@ -2221,6 +2254,9 @@ static int trace__add_syscall_newtp(struct trace *trace)
2221 if (perf_evsel__init_sc_tp_uint_field(sys_exit, ret)) 2254 if (perf_evsel__init_sc_tp_uint_field(sys_exit, ret))
2222 goto out_delete_sys_exit; 2255 goto out_delete_sys_exit;
2223 2256
2257 perf_evsel__config_callchain(sys_enter, &trace->opts, &callchain_param);
2258 perf_evsel__config_callchain(sys_exit, &trace->opts, &callchain_param);
2259
2224 perf_evlist__add(evlist, sys_enter); 2260 perf_evlist__add(evlist, sys_enter);
2225 perf_evlist__add(evlist, sys_exit); 2261 perf_evlist__add(evlist, sys_exit);
2226 2262
@@ -2317,6 +2353,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
2317 pgfault_maj = perf_evsel__new_pgfault(PERF_COUNT_SW_PAGE_FAULTS_MAJ); 2353 pgfault_maj = perf_evsel__new_pgfault(PERF_COUNT_SW_PAGE_FAULTS_MAJ);
2318 if (pgfault_maj == NULL) 2354 if (pgfault_maj == NULL)
2319 goto out_error_mem; 2355 goto out_error_mem;
2356 perf_evsel__config_callchain(pgfault_maj, &trace->opts, &callchain_param);
2320 perf_evlist__add(evlist, pgfault_maj); 2357 perf_evlist__add(evlist, pgfault_maj);
2321 } 2358 }
2322 2359
@@ -2324,6 +2361,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
2324 pgfault_min = perf_evsel__new_pgfault(PERF_COUNT_SW_PAGE_FAULTS_MIN); 2361 pgfault_min = perf_evsel__new_pgfault(PERF_COUNT_SW_PAGE_FAULTS_MIN);
2325 if (pgfault_min == NULL) 2362 if (pgfault_min == NULL)
2326 goto out_error_mem; 2363 goto out_error_mem;
2364 perf_evsel__config_callchain(pgfault_min, &trace->opts, &callchain_param);
2327 perf_evlist__add(evlist, pgfault_min); 2365 perf_evlist__add(evlist, pgfault_min);
2328 } 2366 }
2329 2367
@@ -2344,45 +2382,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
2344 goto out_delete_evlist; 2382 goto out_delete_evlist;
2345 } 2383 }
2346 2384
2347 perf_evlist__config(evlist, &trace->opts, NULL); 2385 perf_evlist__config(evlist, &trace->opts, &callchain_param);
2348
2349 if (callchain_param.enabled) {
2350 bool use_identifier = false;
2351
2352 if (trace->syscalls.events.sys_exit) {
2353 perf_evsel__config_callchain(trace->syscalls.events.sys_exit,
2354 &trace->opts, &callchain_param);
2355 use_identifier = true;
2356 }
2357
2358 if (pgfault_maj) {
2359 perf_evsel__config_callchain(pgfault_maj, &trace->opts, &callchain_param);
2360 use_identifier = true;
2361 }
2362
2363 if (pgfault_min) {
2364 perf_evsel__config_callchain(pgfault_min, &trace->opts, &callchain_param);
2365 use_identifier = true;
2366 }
2367
2368 if (use_identifier) {
2369 /*
2370 * Now we have evsels with different sample_ids, use
2371 * PERF_SAMPLE_IDENTIFIER to map from sample to evsel
2372 * from a fixed position in each ring buffer record.
2373 *
2374 * As of this the changeset introducing this comment, this
2375 * isn't strictly needed, as the fields that can come before
2376 * PERF_SAMPLE_ID are all used, but we'll probably disable
2377 * some of those for things like copying the payload of
2378 * pointer syscall arguments, and for vfs_getname we don't
2379 * need PERF_SAMPLE_ADDR and PERF_SAMPLE_IP, so do this
2380 * here as a warning we need to use PERF_SAMPLE_IDENTIFIER.
2381 */
2382 perf_evlist__set_sample_bit(evlist, IDENTIFIER);
2383 perf_evlist__reset_sample_bit(evlist, ID);
2384 }
2385 }
2386 2386
2387 signal(SIGCHLD, sig_handler); 2387 signal(SIGCHLD, sig_handler);
2388 signal(SIGINT, sig_handler); 2388 signal(SIGINT, sig_handler);
@@ -2437,7 +2437,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
2437 if (err < 0) 2437 if (err < 0)
2438 goto out_error_apply_filters; 2438 goto out_error_apply_filters;
2439 2439
2440 err = perf_evlist__mmap(evlist, trace->opts.mmap_pages, false); 2440 err = perf_evlist__mmap(evlist, trace->opts.mmap_pages);
2441 if (err < 0) 2441 if (err < 0)
2442 goto out_error_mmap; 2442 goto out_error_mmap;
2443 2443
@@ -2455,6 +2455,18 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
2455 trace->multiple_threads = thread_map__pid(evlist->threads, 0) == -1 || 2455 trace->multiple_threads = thread_map__pid(evlist->threads, 0) == -1 ||
2456 evlist->threads->nr > 1 || 2456 evlist->threads->nr > 1 ||
2457 perf_evlist__first(evlist)->attr.inherit; 2457 perf_evlist__first(evlist)->attr.inherit;
2458
2459 /*
2460 * Now that we already used evsel->attr to ask the kernel to setup the
2461 * events, lets reuse evsel->attr.sample_max_stack as the limit in
2462 * trace__resolve_callchain(), allowing per-event max-stack settings
2463 * to override an explicitely set --max-stack global setting.
2464 */
2465 evlist__for_each_entry(evlist, evsel) {
2466 if ((evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN) &&
2467 evsel->attr.sample_max_stack == 0)
2468 evsel->attr.sample_max_stack = trace->max_stack;
2469 }
2458again: 2470again:
2459 before = trace->nr_events; 2471 before = trace->nr_events;
2460 2472
@@ -3046,6 +3058,8 @@ int cmd_trace(int argc, const char **argv)
3046 "Set the maximum stack depth when parsing the callchain, " 3058 "Set the maximum stack depth when parsing the callchain, "
3047 "anything beyond the specified depth will be ignored. " 3059 "anything beyond the specified depth will be ignored. "
3048 "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)), 3060 "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)),
3061 OPT_BOOLEAN(0, "print-sample", &trace.print_sample,
3062 "print the PERF_RECORD_SAMPLE PERF_SAMPLE_ info, for debugging"),
3049 OPT_UINTEGER(0, "proc-map-timeout", &trace.opts.proc_map_timeout, 3063 OPT_UINTEGER(0, "proc-map-timeout", &trace.opts.proc_map_timeout,
3050 "per thread proc mmap processing timeout in ms"), 3064 "per thread proc mmap processing timeout in ms"),
3051 OPT_UINTEGER('D', "delay", &trace.opts.initial_delay, 3065 OPT_UINTEGER('D', "delay", &trace.opts.initial_delay,
@@ -3097,8 +3111,9 @@ int cmd_trace(int argc, const char **argv)
3097 } 3111 }
3098 3112
3099#ifdef HAVE_DWARF_UNWIND_SUPPORT 3113#ifdef HAVE_DWARF_UNWIND_SUPPORT
3100 if ((trace.min_stack || max_stack_user_set) && !callchain_param.enabled && trace.trace_syscalls) 3114 if ((trace.min_stack || max_stack_user_set) && !callchain_param.enabled) {
3101 record_opts__parse_callchain(&trace.opts, &callchain_param, "dwarf", false); 3115 record_opts__parse_callchain(&trace.opts, &callchain_param, "dwarf", false);
3116 }
3102#endif 3117#endif
3103 3118
3104 if (callchain_param.enabled) { 3119 if (callchain_param.enabled) {