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.c98
1 files changed, 90 insertions, 8 deletions
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 90289f31dd87..dc8a6c4986ce 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -89,6 +89,8 @@ struct trace {
89 u64 base_time; 89 u64 base_time;
90 FILE *output; 90 FILE *output;
91 unsigned long nr_events; 91 unsigned long nr_events;
92 unsigned long nr_events_printed;
93 unsigned long max_events;
92 struct strlist *ev_qualifier; 94 struct strlist *ev_qualifier;
93 struct { 95 struct {
94 size_t nr; 96 size_t nr;
@@ -612,6 +614,7 @@ static size_t syscall_arg__scnprintf_getrandom_flags(char *bf, size_t size,
612 614
613struct syscall_arg_fmt { 615struct syscall_arg_fmt {
614 size_t (*scnprintf)(char *bf, size_t size, struct syscall_arg *arg); 616 size_t (*scnprintf)(char *bf, size_t size, struct syscall_arg *arg);
617 unsigned long (*mask_val)(struct syscall_arg *arg, unsigned long val);
615 void *parm; 618 void *parm;
616 const char *name; 619 const char *name;
617 bool show_zero; 620 bool show_zero;
@@ -723,6 +726,10 @@ static struct syscall_fmt {
723 .arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ }, 726 .arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ },
724 [2] = { .scnprintf = SCA_MMAP_PROT, /* prot */ }, 727 [2] = { .scnprintf = SCA_MMAP_PROT, /* prot */ },
725 [3] = { .scnprintf = SCA_MMAP_FLAGS, /* flags */ }, }, }, 728 [3] = { .scnprintf = SCA_MMAP_FLAGS, /* flags */ }, }, },
729 { .name = "mount",
730 .arg = { [0] = { .scnprintf = SCA_FILENAME, /* dev_name */ },
731 [3] = { .scnprintf = SCA_MOUNT_FLAGS, /* flags */
732 .mask_val = SCAMV_MOUNT_FLAGS, /* flags */ }, }, },
726 { .name = "mprotect", 733 { .name = "mprotect",
727 .arg = { [0] = { .scnprintf = SCA_HEX, /* start */ }, 734 .arg = { [0] = { .scnprintf = SCA_HEX, /* start */ },
728 [2] = { .scnprintf = SCA_MMAP_PROT, /* prot */ }, }, }, 735 [2] = { .scnprintf = SCA_MMAP_PROT, /* prot */ }, }, },
@@ -832,7 +839,8 @@ static struct syscall_fmt {
832 .arg = { [2] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, }, 839 .arg = { [2] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
833 { .name = "tkill", 840 { .name = "tkill",
834 .arg = { [1] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, }, 841 .arg = { [1] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
835 { .name = "umount2", .alias = "umount", }, 842 { .name = "umount2", .alias = "umount",
843 .arg = { [0] = { .scnprintf = SCA_FILENAME, /* name */ }, }, },
836 { .name = "uname", .alias = "newuname", }, 844 { .name = "uname", .alias = "newuname", },
837 { .name = "unlinkat", 845 { .name = "unlinkat",
838 .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, }, 846 .arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, },
@@ -856,6 +864,18 @@ static struct syscall_fmt *syscall_fmt__find(const char *name)
856 return bsearch(name, syscall_fmts, nmemb, sizeof(struct syscall_fmt), syscall_fmt__cmp); 864 return bsearch(name, syscall_fmts, nmemb, sizeof(struct syscall_fmt), syscall_fmt__cmp);
857} 865}
858 866
867static struct syscall_fmt *syscall_fmt__find_by_alias(const char *alias)
868{
869 int i, nmemb = ARRAY_SIZE(syscall_fmts);
870
871 for (i = 0; i < nmemb; ++i) {
872 if (syscall_fmts[i].alias && strcmp(syscall_fmts[i].alias, alias) == 0)
873 return &syscall_fmts[i];
874 }
875
876 return NULL;
877}
878
859/* 879/*
860 * is_exit: is this "exit" or "exit_group"? 880 * is_exit: is this "exit" or "exit_group"?
861 * is_open: is this "open" or "openat"? To associate the fd returned in sys_exit with the pathname in sys_enter. 881 * is_open: is this "open" or "openat"? To associate the fd returned in sys_exit with the pathname in sys_enter.
@@ -1485,6 +1505,19 @@ static size_t syscall__scnprintf_name(struct syscall *sc, char *bf, size_t size,
1485 return scnprintf(bf, size, "arg%d: ", arg->idx); 1505 return scnprintf(bf, size, "arg%d: ", arg->idx);
1486} 1506}
1487 1507
1508/*
1509 * Check if the value is in fact zero, i.e. mask whatever needs masking, such
1510 * as mount 'flags' argument that needs ignoring some magic flag, see comment
1511 * in tools/perf/trace/beauty/mount_flags.c
1512 */
1513static unsigned long syscall__mask_val(struct syscall *sc, struct syscall_arg *arg, unsigned long val)
1514{
1515 if (sc->arg_fmt && sc->arg_fmt[arg->idx].mask_val)
1516 return sc->arg_fmt[arg->idx].mask_val(arg, val);
1517
1518 return val;
1519}
1520
1488static size_t syscall__scnprintf_val(struct syscall *sc, char *bf, size_t size, 1521static size_t syscall__scnprintf_val(struct syscall *sc, char *bf, size_t size,
1489 struct syscall_arg *arg, unsigned long val) 1522 struct syscall_arg *arg, unsigned long val)
1490{ 1523{
@@ -1533,6 +1566,11 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
1533 continue; 1566 continue;
1534 1567
1535 val = syscall_arg__val(&arg, arg.idx); 1568 val = syscall_arg__val(&arg, arg.idx);
1569 /*
1570 * Some syscall args need some mask, most don't and
1571 * return val untouched.
1572 */
1573 val = syscall__mask_val(sc, &arg, val);
1536 1574
1537 /* 1575 /*
1538 * Suppress this argument if its value is zero and 1576 * Suppress this argument if its value is zero and
@@ -1664,6 +1702,8 @@ static int trace__printf_interrupted_entry(struct trace *trace)
1664 printed += fprintf(trace->output, "%-70s) ...\n", ttrace->entry_str); 1702 printed += fprintf(trace->output, "%-70s) ...\n", ttrace->entry_str);
1665 ttrace->entry_pending = false; 1703 ttrace->entry_pending = false;
1666 1704
1705 ++trace->nr_events_printed;
1706
1667 return printed; 1707 return printed;
1668} 1708}
1669 1709
@@ -1810,12 +1850,14 @@ static int trace__resolve_callchain(struct trace *trace, struct perf_evsel *evse
1810 int max_stack = evsel->attr.sample_max_stack ? 1850 int max_stack = evsel->attr.sample_max_stack ?
1811 evsel->attr.sample_max_stack : 1851 evsel->attr.sample_max_stack :
1812 trace->max_stack; 1852 trace->max_stack;
1853 int err;
1813 1854
1814 if (machine__resolve(trace->host, &al, sample) < 0 || 1855 if (machine__resolve(trace->host, &al, sample) < 0)
1815 thread__resolve_callchain(al.thread, cursor, evsel, sample, NULL, NULL, max_stack))
1816 return -1; 1856 return -1;
1817 1857
1818 return 0; 1858 err = thread__resolve_callchain(al.thread, cursor, evsel, sample, NULL, NULL, max_stack);
1859 addr_location__put(&al);
1860 return err;
1819} 1861}
1820 1862
1821static int trace__fprintf_callchain(struct trace *trace, struct perf_sample *sample) 1863static int trace__fprintf_callchain(struct trace *trace, struct perf_sample *sample)
@@ -1940,6 +1982,13 @@ errno_print: {
1940 1982
1941 fputc('\n', trace->output); 1983 fputc('\n', trace->output);
1942 1984
1985 /*
1986 * We only consider an 'event' for the sake of --max-events a non-filtered
1987 * sys_enter + sys_exit and other tracepoint events.
1988 */
1989 if (++trace->nr_events_printed == trace->max_events && trace->max_events != ULONG_MAX)
1990 interrupted = true;
1991
1943 if (callchain_ret > 0) 1992 if (callchain_ret > 0)
1944 trace__fprintf_callchain(trace, sample); 1993 trace__fprintf_callchain(trace, sample);
1945 else if (callchain_ret < 0) 1994 else if (callchain_ret < 0)
@@ -2072,14 +2121,25 @@ static void bpf_output__fprintf(struct trace *trace,
2072{ 2121{
2073 binary__fprintf(sample->raw_data, sample->raw_size, 8, 2122 binary__fprintf(sample->raw_data, sample->raw_size, 8,
2074 bpf_output__printer, NULL, trace->output); 2123 bpf_output__printer, NULL, trace->output);
2124 ++trace->nr_events_printed;
2075} 2125}
2076 2126
2077static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel, 2127static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
2078 union perf_event *event __maybe_unused, 2128 union perf_event *event __maybe_unused,
2079 struct perf_sample *sample) 2129 struct perf_sample *sample)
2080{ 2130{
2081 struct thread *thread = machine__findnew_thread(trace->host, sample->pid, sample->tid); 2131 struct thread *thread;
2082 int callchain_ret = 0; 2132 int callchain_ret = 0;
2133 /*
2134 * Check if we called perf_evsel__disable(evsel) due to, for instance,
2135 * this event's max_events having been hit and this is an entry coming
2136 * from the ring buffer that we should discard, since the max events
2137 * have already been considered/printed.
2138 */
2139 if (evsel->disabled)
2140 return 0;
2141
2142 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
2083 2143
2084 if (sample->callchain) { 2144 if (sample->callchain) {
2085 callchain_ret = trace__resolve_callchain(trace, evsel, sample, &callchain_cursor); 2145 callchain_ret = trace__resolve_callchain(trace, evsel, sample, &callchain_cursor);
@@ -2127,6 +2187,12 @@ static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
2127 event_format__fprintf(evsel->tp_format, sample->cpu, 2187 event_format__fprintf(evsel->tp_format, sample->cpu,
2128 sample->raw_data, sample->raw_size, 2188 sample->raw_data, sample->raw_size,
2129 trace->output); 2189 trace->output);
2190 ++trace->nr_events_printed;
2191
2192 if (evsel->max_events != ULONG_MAX && ++evsel->nr_events_printed == evsel->max_events) {
2193 perf_evsel__disable(evsel);
2194 perf_evsel__close(evsel);
2195 }
2130 } 2196 }
2131 } 2197 }
2132 2198
@@ -2137,8 +2203,8 @@ newline:
2137 trace__fprintf_callchain(trace, sample); 2203 trace__fprintf_callchain(trace, sample);
2138 else if (callchain_ret < 0) 2204 else if (callchain_ret < 0)
2139 pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel)); 2205 pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel));
2140 thread__put(thread);
2141out: 2206out:
2207 thread__put(thread);
2142 return 0; 2208 return 0;
2143} 2209}
2144 2210
@@ -2225,6 +2291,8 @@ static int trace__pgfault(struct trace *trace,
2225 trace__fprintf_callchain(trace, sample); 2291 trace__fprintf_callchain(trace, sample);
2226 else if (callchain_ret < 0) 2292 else if (callchain_ret < 0)
2227 pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel)); 2293 pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel));
2294
2295 ++trace->nr_events_printed;
2228out: 2296out:
2229 err = 0; 2297 err = 0;
2230out_put: 2298out_put:
@@ -2402,6 +2470,9 @@ static void trace__handle_event(struct trace *trace, union perf_event *event, st
2402 tracepoint_handler handler = evsel->handler; 2470 tracepoint_handler handler = evsel->handler;
2403 handler(trace, evsel, event, sample); 2471 handler(trace, evsel, event, sample);
2404 } 2472 }
2473
2474 if (trace->nr_events_printed >= trace->max_events && trace->max_events != ULONG_MAX)
2475 interrupted = true;
2405} 2476}
2406 2477
2407static int trace__add_syscall_newtp(struct trace *trace) 2478static int trace__add_syscall_newtp(struct trace *trace)
@@ -2706,7 +2777,7 @@ next_event:
2706 int timeout = done ? 100 : -1; 2777 int timeout = done ? 100 : -1;
2707 2778
2708 if (!draining && perf_evlist__poll(evlist, timeout) > 0) { 2779 if (!draining && perf_evlist__poll(evlist, timeout) > 0) {
2709 if (perf_evlist__filter_pollfd(evlist, POLLERR | POLLHUP) == 0) 2780 if (perf_evlist__filter_pollfd(evlist, POLLERR | POLLHUP | POLLNVAL) == 0)
2710 draining = true; 2781 draining = true;
2711 2782
2712 goto again; 2783 goto again;
@@ -3138,6 +3209,7 @@ static int trace__parse_events_option(const struct option *opt, const char *str,
3138 int len = strlen(str) + 1, err = -1, list, idx; 3209 int len = strlen(str) + 1, err = -1, list, idx;
3139 char *strace_groups_dir = system_path(STRACE_GROUPS_DIR); 3210 char *strace_groups_dir = system_path(STRACE_GROUPS_DIR);
3140 char group_name[PATH_MAX]; 3211 char group_name[PATH_MAX];
3212 struct syscall_fmt *fmt;
3141 3213
3142 if (strace_groups_dir == NULL) 3214 if (strace_groups_dir == NULL)
3143 return -1; 3215 return -1;
@@ -3155,12 +3227,19 @@ static int trace__parse_events_option(const struct option *opt, const char *str,
3155 if (syscalltbl__id(trace->sctbl, s) >= 0 || 3227 if (syscalltbl__id(trace->sctbl, s) >= 0 ||
3156 syscalltbl__strglobmatch_first(trace->sctbl, s, &idx) >= 0) { 3228 syscalltbl__strglobmatch_first(trace->sctbl, s, &idx) >= 0) {
3157 list = 1; 3229 list = 1;
3230 goto do_concat;
3231 }
3232
3233 fmt = syscall_fmt__find_by_alias(s);
3234 if (fmt != NULL) {
3235 list = 1;
3236 s = fmt->name;
3158 } else { 3237 } else {
3159 path__join(group_name, sizeof(group_name), strace_groups_dir, s); 3238 path__join(group_name, sizeof(group_name), strace_groups_dir, s);
3160 if (access(group_name, R_OK) == 0) 3239 if (access(group_name, R_OK) == 0)
3161 list = 1; 3240 list = 1;
3162 } 3241 }
3163 3242do_concat:
3164 if (lists[list]) { 3243 if (lists[list]) {
3165 sprintf(lists[list] + strlen(lists[list]), ",%s", s); 3244 sprintf(lists[list] + strlen(lists[list]), ",%s", s);
3166 } else { 3245 } else {
@@ -3249,6 +3328,7 @@ int cmd_trace(int argc, const char **argv)
3249 .trace_syscalls = false, 3328 .trace_syscalls = false,
3250 .kernel_syscallchains = false, 3329 .kernel_syscallchains = false,
3251 .max_stack = UINT_MAX, 3330 .max_stack = UINT_MAX,
3331 .max_events = ULONG_MAX,
3252 }; 3332 };
3253 const char *output_name = NULL; 3333 const char *output_name = NULL;
3254 const struct option trace_options[] = { 3334 const struct option trace_options[] = {
@@ -3301,6 +3381,8 @@ int cmd_trace(int argc, const char **argv)
3301 &record_parse_callchain_opt), 3381 &record_parse_callchain_opt),
3302 OPT_BOOLEAN(0, "kernel-syscall-graph", &trace.kernel_syscallchains, 3382 OPT_BOOLEAN(0, "kernel-syscall-graph", &trace.kernel_syscallchains,
3303 "Show the kernel callchains on the syscall exit path"), 3383 "Show the kernel callchains on the syscall exit path"),
3384 OPT_ULONG(0, "max-events", &trace.max_events,
3385 "Set the maximum number of events to print, exit after that is reached. "),
3304 OPT_UINTEGER(0, "min-stack", &trace.min_stack, 3386 OPT_UINTEGER(0, "min-stack", &trace.min_stack,
3305 "Set the minimum stack depth when parsing the callchain, " 3387 "Set the minimum stack depth when parsing the callchain, "
3306 "anything below the specified depth will be ignored."), 3388 "anything below the specified depth will be ignored."),